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 : #include "CoarseMeshExtraElementIDGenerator.h" 11 : #include "MooseMeshUtils.h" 12 : 13 : #include "libmesh/enum_point_locator_type.h" 14 : #include "libmesh/elem.h" 15 : #include "libmesh/mesh_serializer.h" 16 : 17 : using namespace libMesh; 18 : 19 : registerMooseObject("ReactorApp", CoarseMeshExtraElementIDGenerator); 20 : 21 : InputParameters 22 114 : CoarseMeshExtraElementIDGenerator::validParams() 23 : { 24 114 : InputParameters params = MeshGenerator::validParams(); 25 228 : params.addRequiredParam<MeshGeneratorName>( 26 : "input", "Name of an existing mesh generator to which we assign coarse element IDs"); 27 228 : params.addRequiredParam<MeshGeneratorName>( 28 : "coarse_mesh", "Name of an existing mesh generator as the coarse mesh"); 29 228 : params.addRequiredParam<std::string>( 30 : "extra_element_id_name", "Name for the extra element ID that is added to the input mesh"); 31 228 : params.addParam<std::string>( 32 : "coarse_mesh_extra_element_id", 33 : "Name for the extra element ID that is copied from the coarse mesh (default to element ID)"); 34 114 : params.addParam<std::vector<SubdomainName>>( 35 114 : "subdomains", std::vector<SubdomainName>(), "Subdomains to apply extra element IDs to."); 36 228 : params.addParam<bool>("enforce_mesh_embedding", 37 228 : false, 38 : "True to error out when the input mesh is not embedded in the coarse mesh"); 39 : 40 114 : params.addClassDescription("Assign coarse element IDs for elements on a " 41 : "mesh based on a coarse mesh."); 42 114 : return params; 43 0 : } 44 : 45 57 : CoarseMeshExtraElementIDGenerator::CoarseMeshExtraElementIDGenerator(const InputParameters & params) 46 : : MeshGenerator(params), 47 57 : _input(getMesh("input")), 48 57 : _coarse_mesh(getMesh("coarse_mesh")), 49 114 : _coarse_id_name(getParam<std::string>("extra_element_id_name")), 50 114 : _using_coarse_element_id(isParamValid("coarse_mesh_extra_element_id")), 51 171 : _embedding_necessary(getParam<bool>("enforce_mesh_embedding")) 52 : { 53 57 : } 54 : 55 : std::unique_ptr<MeshBase> 56 57 : CoarseMeshExtraElementIDGenerator::generate() 57 : { 58 57 : std::unique_ptr<MeshBase> mesh = std::move(_input); 59 : 60 : unsigned int coarse_id; 61 57 : const bool already_has_id = mesh->has_elem_integer(_coarse_id_name); 62 57 : if (!already_has_id) 63 92 : coarse_id = mesh->add_elem_integer(_coarse_id_name); 64 : else 65 11 : coarse_id = mesh->get_elem_integer_index(_coarse_id_name); 66 : 67 : // Get the requested subdomain IDs 68 : std::set<SubdomainID> included_subdomains; 69 : std::set<SubdomainName> bad_subdomains; 70 140 : for (const auto & snm : getParam<std::vector<SubdomainName>>("subdomains")) 71 : { 72 26 : auto sid = MooseMeshUtils::getSubdomainID(snm, *mesh); 73 26 : if (!MooseMeshUtils::hasSubdomainID(*mesh, sid)) 74 4 : bad_subdomains.insert(snm); 75 : else 76 22 : included_subdomains.insert(sid); 77 : } 78 57 : if (!bad_subdomains.empty()) 79 2 : paramError("subdomains", 80 : "The requested subdomains do not exist on the fine mesh: ", 81 2 : Moose::stringify(bad_subdomains)); 82 : 83 : // If we are not going through the entire mesh and the ID already exists, we need to offset the 84 : // assigned ID so that we don't copy ones that are already there 85 : dof_id_type id_offset = 0; 86 55 : if (already_has_id && !included_subdomains.empty()) 87 : { 88 1818 : for (auto & elem : mesh->active_element_ptr_range()) 89 : { 90 900 : dof_id_type elem_id = elem->get_extra_integer(coarse_id); 91 900 : if (elem_id != DofObject::invalid_id && elem_id > id_offset) 92 : id_offset = elem_id; 93 9 : } 94 9 : id_offset++; 95 : } 96 : 97 55 : std::unique_ptr<MeshBase> coarse_mesh = std::move(_coarse_mesh); 98 : 99 : bool using_subdomain_id = false; 100 : unsigned int id_for_assignment = 0; 101 55 : if (_using_coarse_element_id) 102 : { 103 20 : const auto & id_name = getParam<std::string>("coarse_mesh_extra_element_id"); 104 20 : if (id_name == "subdomain_id") 105 : using_subdomain_id = true; 106 : else 107 : { 108 : using_subdomain_id = false; 109 11 : if (!coarse_mesh->has_elem_integer(id_name)) 110 2 : paramError("coarse_mesh_extra_element_id", 111 : "The extra element ID does not exist on the coarse mesh"); 112 : else 113 9 : id_for_assignment = coarse_mesh->get_elem_integer_index(id_name); 114 : } 115 : } 116 : 117 : // a relative tolerance on checking if fine mesh is embedded in the coarse mesh 118 53 : Real aeps = 0.01; 119 : 120 : // The coarse mesh is serialized for distributed mesh to avoid boundary issues. 121 : // As it is coarse this should be cheap. This will be a null operation for a replicated mesh. 122 53 : MeshSerializer tm(*coarse_mesh); 123 : 124 : // build a point_locator on coarse mesh 125 : std::unique_ptr<PointLocatorBase> point_locator = 126 53 : PointLocatorBase::build(TREE_ELEMENTS, *coarse_mesh); 127 53 : point_locator->enable_out_of_mesh_mode(); 128 : 129 : // loop through fine mesh elements and get element's centroid 130 : auto elem_range = included_subdomains.empty() 131 53 : ? mesh->active_element_ptr_range() 132 73 : : mesh->active_subdomain_set_elements_ptr_range(included_subdomains); 133 5569 : for (auto & elem : elem_range) 134 : { 135 : // Get the centroid of the fine elem 136 2764 : Point centroid = elem->true_centroid(); 137 : 138 : // Find coarse elem 139 2764 : const Elem * coarse_elem = (*point_locator)(centroid); 140 2764 : if (!coarse_elem) 141 2 : mooseError("Could not find a coarse element containing a fine element with centroid ", 142 : centroid); 143 : 144 : // get id from the coarse element 145 : dof_id_type elem_id; 146 2762 : if (_using_coarse_element_id) 147 : { 148 1152 : if (using_subdomain_id) 149 576 : elem_id = coarse_elem->subdomain_id(); 150 : else 151 576 : elem_id = coarse_elem->get_extra_integer(id_for_assignment); 152 : } 153 : else 154 : elem_id = coarse_elem->id(); 155 2762 : elem_id += id_offset; 156 : 157 : // Check if the fine elem is nested in the coarse element 158 13798 : for (unsigned int n = 0; n < elem->n_nodes(); n++) 159 : { 160 : // Get the node: we need to manually move it towards the centroid to 161 : // ensure that nothing weird happes due to round-off 162 11040 : Point current_node = elem->point(n); 163 11040 : current_node.add_scaled(current_node, -aeps); 164 11040 : current_node.add_scaled(centroid, aeps); 165 : 166 : // Get the element this node is in and check if it is the same 167 : // as the coarse elem; however check if node_elem is valid as it 168 : // might not be in case the sub element it outside the coarse domain 169 11040 : const Elem * node_elem = (*point_locator)(current_node); 170 11040 : if (!node_elem) 171 2 : mooseError("Could not find a coarse element containing a node of fine element at ", 172 : elem->point(n)); 173 : 174 : // get another id from the coarse element with this node 175 : dof_id_type node_elem_id; 176 11038 : if (_using_coarse_element_id) 177 : { 178 4608 : if (using_subdomain_id) 179 2304 : node_elem_id = node_elem->subdomain_id(); 180 : else 181 2304 : node_elem_id = node_elem->get_extra_integer(id_for_assignment); 182 : } 183 : else 184 : node_elem_id = node_elem->id(); 185 : 186 11038 : if (node_elem_id != elem_id) 187 3114 : if (_embedding_necessary) 188 2 : mooseError( 189 : "Input mesh is not nested in the coarse mesh in CoarseMeshExtraElementIDGenerator."); 190 : } 191 : 192 2758 : elem->set_extra_integer(coarse_id, elem_id); 193 : } 194 : 195 47 : return mesh; 196 47 : }