LCOV - code coverage report
Current view: top level - src/loops - BoundaryElemIntegrityCheckThread.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 84 86 97.7 %
Date: 2025-07-17 01:28:37 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       55047 : BoundaryElemIntegrityCheckThread::BoundaryElemIntegrityCheckThread(
      27       55047 :     FEProblemBase & fe_problem, const TheWarehouse::Query & query)
      28       55047 :   : _fe_problem(fe_problem),
      29       55047 :     _aux_sys(fe_problem.getAuxiliarySystem()),
      30       55047 :     _elem_aux(_aux_sys.elemAuxWarehouse()),
      31       55047 :     _elem_vec_aux(_aux_sys.elemVectorAuxWarehouse()),
      32       55047 :     _elem_array_aux(_aux_sys.elemArrayAuxWarehouse()),
      33       55047 :     _query(query)
      34             : {
      35       55047 : }
      36             : 
      37             : // Splitting Constructor
      38        5066 : BoundaryElemIntegrityCheckThread::BoundaryElemIntegrityCheckThread(
      39        5066 :     BoundaryElemIntegrityCheckThread & x, Threads::split)
      40        5066 :   : _fe_problem(x._fe_problem),
      41        5066 :     _aux_sys(x._aux_sys),
      42        5066 :     _elem_aux(x._elem_aux),
      43        5066 :     _elem_vec_aux(x._elem_vec_aux),
      44        5066 :     _elem_array_aux(x._elem_array_aux),
      45        5066 :     _query(x._query)
      46             : {
      47        5066 : }
      48             : 
      49             : void
      50       60113 : BoundaryElemIntegrityCheckThread::operator()(const ConstBndElemRange & range)
      51             : {
      52       60113 :   ParallelUniqueId puid;
      53       60113 :   const auto tid = puid.id;
      54             : 
      55     1907378 :   for (const auto & belem : range)
      56             :   {
      57     1869565 :     const Elem * elem = belem->_elem;
      58     1869565 :     const auto boundary_id = belem->_bnd_id;
      59     1869565 :     const auto side = belem->_side;
      60             : 
      61             :     // We can distribute work just as the actual execution code will
      62     1869565 :     if (elem->processor_id() != _fe_problem.processor_id())
      63       22285 :       return;
      64             : 
      65     1847280 :     auto & mesh = _fe_problem.mesh();
      66             : 
      67     1847280 :     const auto & bnd_name = mesh.getBoundaryName(boundary_id);
      68             : 
      69             :     // uo check
      70     1847280 :     std::vector<SideUserObject *> objs;
      71     1847280 :     _query.clone()
      72     1847280 :         .condition<AttribThread>(tid)
      73     1847280 :         .condition<AttribInterfaces>(Interfaces::SideUserObject)
      74     3694560 :         .condition<AttribBoundaries>(boundary_id, true)
      75     1847280 :         .queryInto(objs);
      76     1966398 :     for (const auto & uo : objs)
      77      119125 :       if (uo->checkVariableBoundaryIntegrity())
      78             :       {
      79      119125 :         auto leftover_vars = uo->checkAllVariables(*elem);
      80      119125 :         if (!leftover_vars.empty())
      81             :         {
      82         120 :           const auto neighbor = elem->neighbor_ptr(side);
      83         120 :           const bool upwind_elem = !neighbor || elem->id() < neighbor->id();
      84             :           const Elem * lower_d_elem =
      85         120 :               upwind_elem ? mesh.getLowerDElem(elem, side)
      86          12 :                           : mesh.getLowerDElem(neighbor, neighbor->which_neighbor_am_i(elem));
      87         120 :           if (lower_d_elem)
      88         116 :             leftover_vars = uo->checkVariables(*lower_d_elem, leftover_vars);
      89             :         }
      90      119125 :         boundaryIntegrityCheckError(*uo, leftover_vars, bnd_name);
      91      119118 :       }
      92             : 
      93     7807549 :     auto check = [elem, boundary_id, &bnd_name, tid, &mesh, side](const auto & warehouse)
      94             :     {
      95     7349254 :       if (!warehouse.hasBoundaryObjects(boundary_id, tid))
      96     7211513 :         return;
      97             : 
      98      137741 :       const auto & bnd_objects = warehouse.getBoundaryObjects(boundary_id, tid);
      99      298234 :       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      160501 :         if (!bnd_object->requiresGeometricSearch() && bnd_object->checkVariableBoundaryIntegrity())
     103             :         {
     104             :           // First check the higher-dimensional element
     105      157247 :           auto leftover_vars = bnd_object->checkAllVariables(*elem);
     106      157247 :           if (!leftover_vars.empty())
     107             :           {
     108        3030 :             const auto neighbor = elem->neighbor_ptr(side);
     109        3030 :             const bool upwind_elem = !neighbor || elem->id() < neighbor->id();
     110        3030 :             const Elem * lower_d_elem =
     111        3030 :                 upwind_elem ? mesh.getLowerDElem(elem, side)
     112           0 :                             : mesh.getLowerDElem(neighbor, neighbor->which_neighbor_am_i(elem));
     113        3030 :             if (lower_d_elem)
     114        3022 :               leftover_vars = bnd_object->checkVariables(*lower_d_elem, leftover_vars);
     115             :           }
     116             : 
     117      157247 :           boundaryIntegrityCheckError(*bnd_object, leftover_vars, bnd_name);
     118      157239 :         }
     119     1847273 :     };
     120             : 
     121     1847273 :     check(_elem_aux);
     122     1847269 :     check(_elem_vec_aux);
     123     1847269 :     check(_elem_array_aux);
     124     3654708 :     for (const auto i : make_range(_fe_problem.numNonlinearSystems()))
     125     1807443 :       check(_fe_problem.getNonlinearSystemBase(i).getIntegratedBCWarehouse());
     126     1847265 :   }
     127       60098 : }
     128             : 
     129             : void
     130        5063 : BoundaryElemIntegrityCheckThread::join(const BoundaryElemIntegrityCheckThread & /*y*/)
     131             : {
     132        5063 : }
     133             : 
     134             : void
     135     1186593 : boundaryIntegrityCheckError(const MooseObject & object,
     136             :                             const std::set<MooseVariableFieldBase *> & variables,
     137             :                             const BoundaryName & boundary_name)
     138             : {
     139     1186593 :   if (variables.empty())
     140     1186554 :     return;
     141             : 
     142          39 :   std::vector<std::string> names;
     143          39 :   names.reserve(variables.size());
     144          78 :   for (const auto * const var : variables)
     145          39 :     names.push_back(var->name());
     146             : 
     147          78 :   mooseError("'",
     148          39 :              object.name(),
     149             :              "' of type '",
     150          39 :              object.type(),
     151             :              "' depends on variable(s) '",
     152          39 :              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