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 "SubdomainPerElementGenerator.h" 11 : #include "CastUniquePointer.h" 12 : 13 : #include "libmesh/elem.h" 14 : 15 : registerMooseObject("MooseApp", SubdomainPerElementGenerator); 16 : registerMooseObjectRenamed("MooseApp", 17 : ElementSubdomainIDGenerator, 18 : "05/18/2024 24:00", 19 : SubdomainPerElementGenerator); 20 : 21 : InputParameters 22 28790 : SubdomainPerElementGenerator::validParams() 23 : { 24 28790 : InputParameters params = MeshGenerator::validParams(); 25 : 26 28790 : params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify"); 27 28790 : params.addRequiredParam<std::vector<SubdomainID>>("subdomain_ids", 28 : "New subdomain IDs of all elements"); 29 28790 : params.addParam<std::vector<dof_id_type>>("element_ids", "New element IDs of all elements"); 30 28790 : params.addClassDescription( 31 : "Allows the user to assign each element the subdomain ID of their choice"); 32 28790 : return params; 33 0 : } 34 : 35 130 : SubdomainPerElementGenerator::SubdomainPerElementGenerator(const InputParameters & parameters) 36 130 : : MeshGenerator(parameters), _input(getMesh("input")) 37 : { 38 130 : } 39 : 40 : std::unique_ptr<MeshBase> 41 124 : SubdomainPerElementGenerator::generate() 42 : { 43 124 : std::unique_ptr<MeshBase> mesh = std::move(_input); 44 : 45 124 : std::vector<SubdomainID> bids = getParam<std::vector<SubdomainID>>("subdomain_ids"); 46 : 47 : // Generate a list of elements to which new subdomain IDs are to be assigned 48 124 : std::vector<Elem *> elements; 49 124 : if (isParamValid("element_ids")) 50 : { 51 22 : std::vector<dof_id_type> elemids = getParam<std::vector<dof_id_type>>("element_ids"); 52 99 : for (const auto & dof : elemids) 53 : { 54 77 : Elem * elem = mesh->query_elem_ptr(dof); 55 77 : bool has_elem = elem; 56 : 57 : // If no processor sees this element, something must be wrong 58 : // with the specified ID. If another processor sees this 59 : // element but we don't, we'll insert NULL into our elements 60 : // vector anyway so as to keep the indexing matching our bids 61 : // vector. 62 77 : this->comm().max(has_elem); 63 77 : if (!has_elem) 64 0 : mooseError("invalid element ID is in element_ids"); 65 : else 66 77 : elements.push_back(elem); 67 : } 68 22 : } 69 : 70 : else 71 : { 72 102 : bool has_warned_remapping = false; 73 : 74 : // On a distributed mesh, iterating over all elements in 75 : // increasing order is tricky. We have to consider element ids 76 : // which aren't on a particular processor because they're remote, 77 : // *and* elements which aren't on a particular processor because 78 : // there's a hole in the current numbering. 79 : // 80 : // I don't see how to do this without a ton of communication, 81 : // which is hopefully okay because it only happens at mesh setup, 82 : // and because nobody who is here trying to use 83 : // AssignElementSubdomainID to hand write every single element's 84 : // subdomain ID will have a huge number of elements on their 85 : // initial mesh. 86 : 87 : // Using plain max_elem_id() currently gives the same result on 88 : // every processor, but that isn't guaranteed by the libMesh 89 : // documentation, so let's be paranoid. 90 102 : dof_id_type end_id = mesh->max_elem_id(); 91 102 : this->comm().max(end_id); 92 : 93 2743 : for (dof_id_type e = 0; e != end_id; ++e) 94 : { 95 : // This is O(1) on ReplicatedMesh but O(log(N_elem)) on 96 : // DistributedMesh. We can switch to more complicated but 97 : // asymptotically faster code if my "nobody who is here ... will 98 : // have a huge number of elements" claim turns out to be false. 99 2641 : Elem * elem = mesh->query_elem_ptr(e); 100 2641 : bool someone_has_elem = elem; 101 2641 : if (!mesh->is_replicated()) 102 448 : this->comm().max(someone_has_elem); 103 : 104 2641 : if (elem && elem->id() != e && (!has_warned_remapping)) 105 : { 106 0 : mooseWarning("AssignElementSubdomainID will ignore the element remapping"); 107 0 : has_warned_remapping = true; 108 : } 109 : 110 2641 : if (someone_has_elem) 111 2641 : elements.push_back(elem); 112 : } 113 : } 114 : 115 124 : if (bids.size() != elements.size()) 116 0 : mooseError(" Size of subdomain_ids is not consistent with the number of elements"); 117 : 118 : // Assign new subdomain IDs and make sure elements in different types are not assigned with the 119 : // same subdomain ID 120 124 : std::map<ElemType, std::set<SubdomainID>> type2blocks; 121 2842 : for (dof_id_type e = 0; e < elements.size(); ++e) 122 : { 123 : // Get the element we need to assign, or skip it if we just have a 124 : // nullptr placeholder indicating a remote element. 125 2718 : Elem * elem = elements[e]; 126 2718 : if (!elem) 127 42 : continue; 128 : 129 2676 : ElemType type = elem->type(); 130 2676 : SubdomainID newid = bids[e]; 131 : 132 2676 : bool has_type = false; 133 5228 : for (auto & it : type2blocks) 134 : { 135 2552 : if (it.first == type) 136 : { 137 2552 : has_type = true; 138 2552 : it.second.insert(newid); 139 : } 140 0 : else if (it.second.count(newid) > 0) 141 0 : mooseError("trying to assign elements with different types with the same subdomain ID"); 142 : } 143 : 144 2676 : if (!has_type) 145 : { 146 124 : std::set<SubdomainID> blocks; 147 124 : blocks.insert(newid); 148 124 : type2blocks.insert(std::make_pair(type, blocks)); 149 124 : } 150 : 151 2676 : elem->subdomain_id() = newid; 152 : } 153 : 154 124 : mesh->set_isnt_prepared(); 155 248 : return dynamic_pointer_cast<MeshBase>(mesh); 156 124 : }