LCOV - code coverage report
Current view: top level - src/loops - BoundaryElemIntegrityCheckThread.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: fef103 Lines: 84 86 97.7 %
Date: 2025-09-03 20:01:23 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : // MOOSE includes
      11             : #include "BoundaryElemIntegrityCheckThread.h"
      12             : #include "AuxiliarySystem.h"
      13             : #include "NonlinearSystemBase.h"
      14             : #include "FEProblemBase.h"
      15             : #include "SideUserObject.h"
      16             : #include "MooseMesh.h"
      17             : #include "IntegratedBCBase.h"
      18             : #include "MooseObjectTagWarehouse.h"
      19             : 
      20             : #include "libmesh/threads.h"
      21             : #include "libmesh/elem.h"
      22             : #include "libmesh/mesh_base.h"
      23             : 
      24             : #include <vector>
      25             : 
      26       60267 : BoundaryElemIntegrityCheckThread::BoundaryElemIntegrityCheckThread(
      27       60267 :     FEProblemBase & fe_problem, const TheWarehouse::Query & query)
      28       60267 :   : _fe_problem(fe_problem),
      29       60267 :     _aux_sys(fe_problem.getAuxiliarySystem()),
      30       60267 :     _elem_aux(_aux_sys.elemAuxWarehouse()),
      31       60267 :     _elem_vec_aux(_aux_sys.elemVectorAuxWarehouse()),
      32       60267 :     _elem_array_aux(_aux_sys.elemArrayAuxWarehouse()),
      33       60267 :     _query(query)
      34             : {
      35       60267 : }
      36             : 
      37             : // Splitting Constructor
      38        5149 : BoundaryElemIntegrityCheckThread::BoundaryElemIntegrityCheckThread(
      39        5149 :     BoundaryElemIntegrityCheckThread & x, Threads::split)
      40        5149 :   : _fe_problem(x._fe_problem),
      41        5149 :     _aux_sys(x._aux_sys),
      42        5149 :     _elem_aux(x._elem_aux),
      43        5149 :     _elem_vec_aux(x._elem_vec_aux),
      44        5149 :     _elem_array_aux(x._elem_array_aux),
      45        5149 :     _query(x._query)
      46             : {
      47        5149 : }
      48             : 
      49             : void
      50       65416 : BoundaryElemIntegrityCheckThread::operator()(const ConstBndElemRange & range)
      51             : {
      52       65416 :   ParallelUniqueId puid;
      53       65416 :   const auto tid = puid.id;
      54             : 
      55     2171980 :   for (const auto & belem : range)
      56             :   {
      57     2129600 :     const Elem * elem = belem->_elem;
      58     2129600 :     const auto boundary_id = belem->_bnd_id;
      59     2129600 :     const auto side = belem->_side;
      60             : 
      61             :     // We can distribute work just as the actual execution code will
      62     2129600 :     if (elem->processor_id() != _fe_problem.processor_id())
      63       23019 :       return;
      64             : 
      65     2106581 :     auto & mesh = _fe_problem.mesh();
      66             : 
      67     2106581 :     const auto & bnd_name = mesh.getBoundaryName(boundary_id);
      68             : 
      69             :     // uo check
      70     2106581 :     std::vector<SideUserObject *> objs;
      71     2106581 :     _query.clone()
      72     2106581 :         .condition<AttribThread>(tid)
      73     2106581 :         .condition<AttribInterfaces>(Interfaces::SideUserObject)
      74     4213162 :         .condition<AttribBoundaries>(boundary_id, true)
      75     2106581 :         .queryInto(objs);
      76     2243709 :     for (const auto & uo : objs)
      77      137137 :       if (uo->checkVariableBoundaryIntegrity())
      78             :       {
      79      137137 :         auto leftover_vars = uo->checkAllVariables(*elem);
      80      137137 :         if (!leftover_vars.empty())
      81             :         {
      82         138 :           const auto neighbor = elem->neighbor_ptr(side);
      83         138 :           const bool upwind_elem = !neighbor || elem->id() < neighbor->id();
      84             :           const Elem * lower_d_elem =
      85         138 :               upwind_elem ? mesh.getLowerDElem(elem, side)
      86          14 :                           : mesh.getLowerDElem(neighbor, neighbor->which_neighbor_am_i(elem));
      87         138 :           if (lower_d_elem)
      88         134 :             leftover_vars = uo->checkVariables(*lower_d_elem, leftover_vars);
      89             :         }
      90      137137 :         boundaryIntegrityCheckError(*uo, leftover_vars, bnd_name);
      91      137128 :       }
      92             : 
      93     8382940 :     auto check = [elem, boundary_id, &bnd_name, tid, &mesh, side](const auto & warehouse)
      94             :     {
      95     8382940 :       if (!warehouse.hasBoundaryObjects(boundary_id, tid))
      96     8229036 :         return;
      97             : 
      98      153904 :       const auto & bnd_objects = warehouse.getBoundaryObjects(boundary_id, tid);
      99      331536 :       for (const auto & bnd_object : bnd_objects)
     100             :         // Skip if this object uses geometric search because coupled variables may be defined on
     101             :         // paired boundaries instead of the boundary this elem is on
     102      177640 :         if (!bnd_object->requiresGeometricSearch() && bnd_object->checkVariableBoundaryIntegrity())
     103             :         {
     104             :           // First check the higher-dimensional element
     105      173730 :           auto leftover_vars = bnd_object->checkAllVariables(*elem);
     106      173730 :           if (!leftover_vars.empty())
     107             :           {
     108        3458 :             const auto neighbor = elem->neighbor_ptr(side);
     109        3458 :             const bool upwind_elem = !neighbor || elem->id() < neighbor->id();
     110        3458 :             const Elem * lower_d_elem =
     111        3458 :                 upwind_elem ? mesh.getLowerDElem(elem, side)
     112           0 :                             : mesh.getLowerDElem(neighbor, neighbor->which_neighbor_am_i(elem));
     113        3458 :             if (lower_d_elem)
     114        3450 :               leftover_vars = bnd_object->checkVariables(*lower_d_elem, leftover_vars);
     115             :           }
     116             : 
     117      173730 :           boundaryIntegrityCheckError(*bnd_object, leftover_vars, bnd_name);
     118      173722 :         }
     119     2106572 :     };
     120             : 
     121     2106572 :     check(_elem_aux);
     122     2106568 :     check(_elem_vec_aux);
     123     2106568 :     check(_elem_array_aux);
     124     4169796 :     for (const auto i : make_range(_fe_problem.numNonlinearSystems()))
     125     2063232 :       check(_fe_problem.getNonlinearSystemBase(i).getIntegratedBCWarehouse());
     126     2106564 :   }
     127       65399 : }
     128             : 
     129             : void
     130        5145 : BoundaryElemIntegrityCheckThread::join(const BoundaryElemIntegrityCheckThread & /*y*/)
     131             : {
     132        5145 : }
     133             : 
     134             : void
     135     1322949 : boundaryIntegrityCheckError(const MooseObject & object,
     136             :                             const std::set<MooseVariableFieldBase *> & variables,
     137             :                             const BoundaryName & boundary_name)
     138             : {
     139     1322949 :   if (variables.empty())
     140     1322908 :     return;
     141             : 
     142          41 :   std::vector<std::string> names;
     143          41 :   names.reserve(variables.size());
     144          82 :   for (const auto * const var : variables)
     145          41 :     names.push_back(var->name());
     146             : 
     147          41 :   mooseError("'",
     148          41 :              object.name(),
     149             :              "' of type '",
     150          41 :              object.type(),
     151             :              "' depends on variable(s) '",
     152          41 :              MooseUtils::join(names, ","),
     153             :              "'. However, that variable does not appear to be defined on (all of) boundary '",
     154             :              boundary_name,
     155             :              "'.");
     156           0 : }

Generated by: LCOV version 1.14