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 : }