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 "BlockToMeshConverterGenerator.h" 11 : #include "CastUniquePointer.h" 12 : #include "libmesh/elem.h" 13 : #include "MooseMeshUtils.h" 14 : 15 : registerMooseObject("MooseApp", BlockToMeshConverterGenerator); 16 : 17 : InputParameters 18 14417 : BlockToMeshConverterGenerator::validParams() 19 : { 20 14417 : InputParameters params = MeshGenerator::validParams(); 21 : 22 14417 : params.addClassDescription( 23 : "Converts one or more blocks (subdomains) from a mesh into a stand-alone mesh with a " 24 : "single block in it."); 25 : 26 14417 : params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify"); 27 14417 : params.addRequiredParam<std::vector<SubdomainName>>( 28 : "target_blocks", 29 : "The (list of) blocks (or 'subdomains') we wish to have moved to a new mesh (by name, not " 30 : "ID)"); 31 : 32 14417 : return params; 33 0 : } 34 : 35 76 : BlockToMeshConverterGenerator::BlockToMeshConverterGenerator(const InputParameters & parameters) 36 : : MeshGenerator(parameters), 37 76 : _input(getMesh("input")), 38 152 : _target_blocks(getParam<std::vector<SubdomainName>>("target_blocks")) 39 : { 40 76 : } 41 : 42 : std::unique_ptr<MeshBase> 43 76 : BlockToMeshConverterGenerator::generate() 44 : { 45 76 : std::unique_ptr<MeshBase> mesh = std::move(_input); 46 : 47 76 : if (!mesh->is_replicated()) 48 0 : mooseError("This generator does not support distributed meshes."); 49 : 50 76 : auto new_mesh = buildMeshBaseObject(); 51 : 52 76 : const auto target_block_ids = MooseMeshUtils::getSubdomainIDs((*mesh), _target_blocks); 53 : 54 : // Check that the block ids/names exist in the mesh 55 76 : std::set<SubdomainID> mesh_blocks; 56 76 : mesh->subdomain_ids(mesh_blocks); 57 : 58 226 : for (const auto i : index_range(target_block_ids)) 59 150 : if (target_block_ids[i] == Moose::INVALID_BLOCK_ID || !mesh_blocks.count(target_block_ids[i])) 60 : { 61 0 : paramError("target_blocks", 62 : "The target_block '", 63 0 : _target_blocks[i], 64 : "' was not found within the mesh."); 65 : } 66 : 67 : // know which nodes have already been inserted, by tracking the old mesh's node's ids' 68 76 : std::unordered_map<dof_id_type, dof_id_type> old_new_node_map; 69 : 70 206 : for (const auto target_block_id : target_block_ids) 71 : { 72 : 73 1532 : for (auto elem : mesh->active_subdomain_elements_ptr_range(target_block_id)) 74 : { 75 703 : if (elem->level() != 0) 76 4 : mooseError("Refined blocks are not supported by this generator. " 77 : "Can you re-organize mesh generators to refine after converting the block?"); 78 : 79 : // make a deep copy so that mutiple meshes' destructors don't segfault at program termination 80 699 : auto copy = elem->build(elem->type()); 81 : 82 : // index of node in the copy element must be managed manually as there is no intelligent 83 : // insert method 84 699 : dof_id_type copy_n_index = 0; 85 : 86 : // correctly assign new copies of nodes, loop over nodes 87 5481 : for (dof_id_type i : elem->node_index_range()) 88 : { 89 4782 : auto & n = elem->node_ref(i); 90 : 91 4782 : if (old_new_node_map.count(n.id())) 92 : { 93 : // case where we have already inserted this particular point before 94 : // then we need to find the already-inserted one and hook it up right 95 : // to it's respective element 96 2685 : copy->set_node(copy_n_index++, new_mesh->node_ptr(old_new_node_map[n.id()])); 97 : } 98 : else 99 : { 100 : // case where we've NEVER inserted this particular point before 101 : // add them both to the element and the mesh 102 : 103 : // Nodes' IDs are their indexes in the nodes' respective mesh 104 : // If we set them as invalid they are automatically assigned 105 : // Add to mesh, auto-assigning a new id. 106 2097 : Node * node = new_mesh->add_point(elem->point(i)); 107 : 108 : // Add to element copy (manually) 109 2097 : copy->set_node(copy_n_index++, node); 110 : 111 : // remember the (old) ID 112 2097 : old_new_node_map[n.id()] = node->id(); 113 : } 114 : } 115 : 116 : // it is ok to release the copy element into the mesh because derived meshes class 117 : // (ReplicatedMesh, DistributedMesh) manage their own elements, will delete them 118 699 : new_mesh->add_elem(copy.release()); 119 829 : } 120 : } 121 : 122 144 : return dynamic_pointer_cast<MeshBase>(new_mesh); 123 72 : }