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