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