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 61367 : BoundaryElemIntegrityCheckThread::BoundaryElemIntegrityCheckThread( 27 61367 : FEProblemBase & fe_problem, const TheWarehouse::Query & query) 28 61367 : : _fe_problem(fe_problem), 29 61367 : _aux_sys(fe_problem.getAuxiliarySystem()), 30 61367 : _elem_aux(_aux_sys.elemAuxWarehouse()), 31 61367 : _elem_vec_aux(_aux_sys.elemVectorAuxWarehouse()), 32 61367 : _elem_array_aux(_aux_sys.elemArrayAuxWarehouse()), 33 61367 : _query(query) 34 : { 35 61367 : } 36 : 37 : // Splitting Constructor 38 5251 : BoundaryElemIntegrityCheckThread::BoundaryElemIntegrityCheckThread( 39 5251 : BoundaryElemIntegrityCheckThread & x, Threads::split) 40 5251 : : _fe_problem(x._fe_problem), 41 5251 : _aux_sys(x._aux_sys), 42 5251 : _elem_aux(x._elem_aux), 43 5251 : _elem_vec_aux(x._elem_vec_aux), 44 5251 : _elem_array_aux(x._elem_array_aux), 45 5251 : _query(x._query) 46 : { 47 5251 : } 48 : 49 : void 50 66618 : BoundaryElemIntegrityCheckThread::operator()(const ConstBndElemRange & range) 51 : { 52 66618 : ParallelUniqueId puid; 53 66618 : const auto tid = puid.id; 54 : 55 2229099 : for (const auto & belem : range) 56 : { 57 2185856 : const Elem * elem = belem->_elem; 58 2185856 : const auto boundary_id = belem->_bnd_id; 59 2185856 : const auto side = belem->_side; 60 : 61 : // We can distribute work just as the actual execution code will 62 2185856 : if (elem->processor_id() != _fe_problem.processor_id()) 63 23358 : return; 64 : 65 2162498 : auto & mesh = _fe_problem.mesh(); 66 : 67 2162498 : const auto & bnd_name = mesh.getBoundaryName(boundary_id); 68 : 69 : // uo check 70 2162498 : std::vector<SideUserObject *> objs; 71 2162498 : _query.clone() 72 2162498 : .condition<AttribThread>(tid) 73 2162498 : .condition<AttribInterfaces>(Interfaces::SideUserObject) 74 4324996 : .condition<AttribBoundaries>(boundary_id, true) 75 2162498 : .queryInto(objs); 76 2300355 : for (const auto & uo : objs) 77 137866 : if (uo->checkVariableBoundaryIntegrity()) 78 : { 79 137866 : auto leftover_vars = uo->checkAllVariables(*elem); 80 137866 : 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 137866 : boundaryIntegrityCheckError(*uo, leftover_vars, bnd_name); 91 137857 : } 92 : 93 8606608 : auto check = [elem, boundary_id, &bnd_name, tid, &mesh, side](const auto & warehouse) 94 : { 95 8606608 : if (!warehouse.hasBoundaryObjects(boundary_id, tid)) 96 8451914 : return; 97 : 98 154694 : const auto & bnd_objects = warehouse.getBoundaryObjects(boundary_id, tid); 99 333251 : 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 178565 : if (!bnd_object->requiresGeometricSearch() && bnd_object->checkVariableBoundaryIntegrity()) 103 : { 104 : // First check the higher-dimensional element 105 174655 : auto leftover_vars = bnd_object->checkAllVariables(*elem); 106 174655 : 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 174655 : boundaryIntegrityCheckError(*bnd_object, leftover_vars, bnd_name); 118 174647 : } 119 2162489 : }; 120 : 121 2162489 : check(_elem_aux); 122 2162485 : check(_elem_vec_aux); 123 2162485 : check(_elem_array_aux); 124 4281630 : for (const auto i : make_range(_fe_problem.numNonlinearSystems())) 125 2119149 : check(_fe_problem.getNonlinearSystemBase(i).getIntegratedBCWarehouse()); 126 2162481 : } 127 66601 : } 128 : 129 : void 130 5247 : BoundaryElemIntegrityCheckThread::join(const BoundaryElemIntegrityCheckThread & /*y*/) 131 : { 132 5247 : } 133 : 134 : void 135 1327211 : boundaryIntegrityCheckError(const MooseObject & object, 136 : const std::set<MooseVariableFieldBase *> & variables, 137 : const BoundaryName & boundary_name) 138 : { 139 1327211 : if (variables.empty()) 140 1327170 : 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 : }