LCOV - code coverage report
Current view: top level - src/meshgenerators - BlockToMeshConverterGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 37 41 90.2 %
Date: 2025-07-17 01:28:37 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14