LCOV - code coverage report
Current view: top level - src/loops - BoundaryElemIntegrityCheckThread.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 84 86 97.7 %
Date: 2025-08-08 20:01:16 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       59557 : BoundaryElemIntegrityCheckThread::BoundaryElemIntegrityCheckThread(
      27       59557 :     FEProblemBase & fe_problem, const TheWarehouse::Query & query)
      28       59557 :   : _fe_problem(fe_problem),
      29       59557 :     _aux_sys(fe_problem.getAuxiliarySystem()),
      30       59557 :     _elem_aux(_aux_sys.elemAuxWarehouse()),
      31       59557 :     _elem_vec_aux(_aux_sys.elemVectorAuxWarehouse()),
      32       59557 :     _elem_array_aux(_aux_sys.elemArrayAuxWarehouse()),
      33       59557 :     _query(query)
      34             : {
      35       59557 : }
      36             : 
      37             : // Splitting Constructor
      38        5090 : BoundaryElemIntegrityCheckThread::BoundaryElemIntegrityCheckThread(
      39        5090 :     BoundaryElemIntegrityCheckThread & x, Threads::split)
      40        5090 :   : _fe_problem(x._fe_problem),
      41        5090 :     _aux_sys(x._aux_sys),
      42        5090 :     _elem_aux(x._elem_aux),
      43        5090 :     _elem_vec_aux(x._elem_vec_aux),
      44        5090 :     _elem_array_aux(x._elem_array_aux),
      45        5090 :     _query(x._query)
      46             : {
      47        5090 : }
      48             : 
      49             : void
      50       64647 : BoundaryElemIntegrityCheckThread::operator()(const ConstBndElemRange & range)
      51             : {
      52       64647 :   ParallelUniqueId puid;
      53       64647 :   const auto tid = puid.id;
      54             : 
      55     2146459 :   for (const auto & belem : range)
      56             :   {
      57     2104583 :     const Elem * elem = belem->_elem;
      58     2104583 :     const auto boundary_id = belem->_bnd_id;
      59     2104583 :     const auto side = belem->_side;
      60             : 
      61             :     // We can distribute work just as the actual execution code will
      62     2104583 :     if (elem->processor_id() != _fe_problem.processor_id())
      63       22756 :       return;
      64             : 
      65     2081827 :     auto & mesh = _fe_problem.mesh();
      66             : 
      67     2081827 :     const auto & bnd_name = mesh.getBoundaryName(boundary_id);
      68             : 
      69             :     // uo check
      70     2081827 :     std::vector<SideUserObject *> objs;
      71     2081827 :     _query.clone()
      72     2081827 :         .condition<AttribThread>(tid)
      73     2081827 :         .condition<AttribInterfaces>(Interfaces::SideUserObject)
      74     4163654 :         .condition<AttribBoundaries>(boundary_id, true)
      75     2081827 :         .queryInto(objs);
      76     2218947 :     for (const auto & uo : objs)
      77      137127 :       if (uo->checkVariableBoundaryIntegrity())
      78             :       {
      79      137127 :         auto leftover_vars = uo->checkAllVariables(*elem);
      80      137127 :         if (!leftover_vars.empty())
      81             :         {
      82         136 :           const auto neighbor = elem->neighbor_ptr(side);
      83         136 :           const bool upwind_elem = !neighbor || elem->id() < neighbor->id();
      84             :           const Elem * lower_d_elem =
      85         136 :               upwind_elem ? mesh.getLowerDElem(elem, side)
      86          14 :                           : mesh.getLowerDElem(neighbor, neighbor->which_neighbor_am_i(elem));
      87         136 :           if (lower_d_elem)
      88         132 :             leftover_vars = uo->checkVariables(*lower_d_elem, leftover_vars);
      89             :         }
      90      137127 :         boundaryIntegrityCheckError(*uo, leftover_vars, bnd_name);
      91      137120 :       }
      92             : 
      93     8789972 :     auto check = [elem, boundary_id, &bnd_name, tid, &mesh, side](const auto & warehouse)
      94             :     {
      95     8283932 :       if (!warehouse.hasBoundaryObjects(boundary_id, tid))
      96     8130546 :         return;
      97             : 
      98      153386 :       const auto & bnd_objects = warehouse.getBoundaryObjects(boundary_id, tid);
      99      330157 :       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      176779 :         if (!bnd_object->requiresGeometricSearch() && bnd_object->checkVariableBoundaryIntegrity())
     103             :         {
     104             :           // First check the higher-dimensional element
     105      172869 :           auto leftover_vars = bnd_object->checkAllVariables(*elem);
     106      172869 :           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      172869 :           boundaryIntegrityCheckError(*bnd_object, leftover_vars, bnd_name);
     118      172861 :         }
     119     2081820 :     };
     120             : 
     121     2081820 :     check(_elem_aux);
     122     2081816 :     check(_elem_vec_aux);
     123     2081816 :     check(_elem_array_aux);
     124     4120292 :     for (const auto i : make_range(_fe_problem.numNonlinearSystems()))
     125     2038480 :       check(_fe_problem.getNonlinearSystemBase(i).getIntegratedBCWarehouse());
     126     2081812 :   }
     127       64632 : }
     128             : 
     129             : void
     130        5087 : BoundaryElemIntegrityCheckThread::join(const BoundaryElemIntegrityCheckThread & /*y*/)
     131             : {
     132        5087 : }
     133             : 
     134             : void
     135     1314380 : boundaryIntegrityCheckError(const MooseObject & object,
     136             :                             const std::set<MooseVariableFieldBase *> & variables,
     137             :                             const BoundaryName & boundary_name)
     138             : {
     139     1314380 :   if (variables.empty())
     140     1314341 :     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