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 14401 : BlockToMeshConverterGenerator::validParams() 19 : { 20 14401 : InputParameters params = MeshGenerator::validParams(); 21 : 22 14401 : 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 14401 : params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify"); 27 14401 : 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 14401 : return params; 33 0 : } 34 : 35 68 : BlockToMeshConverterGenerator::BlockToMeshConverterGenerator(const InputParameters & parameters) 36 : : MeshGenerator(parameters), 37 68 : _input(getMesh("input")), 38 136 : _target_blocks(getParam<std::vector<SubdomainName>>("target_blocks")) 39 : { 40 68 : } 41 : 42 : std::unique_ptr<MeshBase> 43 68 : BlockToMeshConverterGenerator::generate() 44 : { 45 68 : std::unique_ptr<MeshBase> mesh = std::move(_input); 46 : 47 68 : if (!mesh->is_replicated()) 48 0 : mooseError("This generator does not support distributed meshes."); 49 : 50 68 : auto new_mesh = buildMeshBaseObject(); 51 : 52 68 : const auto target_block_ids = MooseMeshUtils::getSubdomainIDs((*mesh), _target_blocks); 53 : 54 : // Check that the block ids/names exist in the mesh 55 68 : std::set<SubdomainID> mesh_blocks; 56 68 : mesh->subdomain_ids(mesh_blocks); 57 : 58 204 : for (const auto i : index_range(target_block_ids)) 59 136 : 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 68 : std::unordered_map<dof_id_type, dof_id_type> old_new_node_map; 69 : 70 184 : for (const auto target_block_id : target_block_ids) 71 : { 72 : 73 1368 : for (auto elem : mesh->active_subdomain_elements_ptr_range(target_block_id)) 74 : { 75 628 : 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 624 : 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 624 : dof_id_type copy_n_index = 0; 85 : 86 : // correctly assign new copies of nodes, loop over nodes 87 4896 : for (dof_id_type i : elem->node_index_range()) 88 : { 89 4272 : auto & n = elem->node_ref(i); 90 : 91 4272 : 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 2392 : 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 1880 : Node * node = new_mesh->add_point(elem->point(i)); 107 : 108 : // Add to element copy (manually) 109 1880 : copy->set_node(copy_n_index++, node); 110 : 111 : // remember the (old) ID 112 1880 : 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 624 : new_mesh->add_elem(copy.release()); 119 740 : } 120 : } 121 : 122 128 : return dynamic_pointer_cast<MeshBase>(new_mesh); 123 64 : }