LCOV - code coverage report
Current view: top level - src/meshgenerators - RenumberBySubdomainGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 54 71 76.1 %
Date: 2026-05-29 20:35:17 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 "RenumberBySubdomainGenerator.h"
      11             : #include "CastUniquePointer.h"
      12             : #include "MooseMeshUtils.h"
      13             : 
      14             : registerMooseObject("MooseApp", RenumberBySubdomainGenerator);
      15             : 
      16             : InputParameters
      17        3077 : RenumberBySubdomainGenerator::validParams()
      18             : {
      19        3077 :   InputParameters params = MeshGenerator::validParams();
      20             : 
      21       12308 :   params.addRequiredParam<MeshGeneratorName>("input", "The mesh we want to modify");
      22       12308 :   params.addParam<std::vector<SubdomainName>>(
      23             :       "blocks_to_renumber",
      24             :       "Elements and nodes within these blocks will be renumbered. If none are specified, all "
      25             :       "subdomains are affected by the renumbering");
      26             : 
      27        3077 :   params.addClassDescription("Changes the element and node IDs so that elements and nodes are "
      28             :                              "contiguous within a subdomain. Note that DoF ordering may be "
      29             :                              "affected as well, and that the mesh renumbering will be turned off.");
      30             : 
      31        3077 :   return params;
      32           0 : }
      33             : 
      34           8 : RenumberBySubdomainGenerator::RenumberBySubdomainGenerator(const InputParameters & parameters)
      35          16 :   : MeshGenerator(parameters), _input(getMesh("input"))
      36             : {
      37           8 : }
      38             : 
      39             : std::unique_ptr<MeshBase>
      40           8 : RenumberBySubdomainGenerator::generate()
      41             : {
      42           8 :   std::unique_ptr<MeshBase> mesh = std::move(_input);
      43             : 
      44             :   // Not impossible to do.
      45           8 :   if (!mesh->is_serial())
      46           0 :     mooseError("Not implemented for non-serialized distributed meshes");
      47             : 
      48             :   // Orphaned nodes would cause problems on renumbering, we are looping on the nodes attached
      49             :   // to elements
      50           8 :   mesh->remove_orphaned_nodes();
      51           8 :   mesh->renumber_nodes_and_elements();
      52             : 
      53             :   // Get the blocks provided by the user
      54             :   std::optional<std::vector<SubdomainName>> blocks =
      55          16 :       isParamValid("blocks_to_renumber")
      56          40 :           ? getParam<std::vector<SubdomainName>>("blocks_to_renumber")
      57           8 :           : std::vector<SubdomainName>();
      58           8 :   std::vector<SubdomainID> block_ids(blocks->size());
      59           8 :   std::stringstream missing_block;
      60             : 
      61          40 :   for (const auto i : index_range(block_ids))
      62             :   {
      63          32 :     const SubdomainName & name = blocks.value()[i];
      64             : 
      65             :     // Convert the SubdomainName to an id and store
      66          32 :     const auto id = MooseMeshUtils::getSubdomainID(name, *mesh);
      67          32 :     block_ids[i] = id;
      68             : 
      69             :     // Block does not exist - store for a future error
      70          32 :     if (id == Moose::INVALID_BLOCK_ID)
      71           0 :       missing_block << name << " ";
      72             :   }
      73           8 :   if (missing_block.str().size())
      74           0 :     paramError("blocks_to_renumber",
      75             :                "The following blocks were requested to be renumbered, but do not exist: ",
      76           0 :                missing_block.str());
      77             : 
      78             :   // User did not specify blocks, just get them all
      79           8 :   if (blocks->empty())
      80             :   {
      81           0 :     std::set<subdomain_id_type> block_ids_set;
      82           0 :     mesh->subdomain_ids(block_ids_set);
      83           0 :     block_ids.reserve(block_ids_set.size());
      84           0 :     block_ids.assign(block_ids_set.begin(), block_ids_set.end());
      85             : 
      86             :     // Does not have useful data
      87           0 :     blocks.reset();
      88           0 :   }
      89             : 
      90             :   // Renumber all elements with an ID we can recognize (so we can tell an already renumbered elem)
      91           8 :   const auto max_elem_id = mesh->max_elem_id();
      92           8 :   const auto max_node_id = mesh->max_node_id();
      93           8 :   std::unordered_map<dof_id_type, dof_id_type> new_elem_ids;
      94           8 :   new_elem_ids.reserve(max_elem_id);
      95           8 :   std::unordered_set<dof_id_type> renumbered_nodes;
      96           8 :   renumbered_nodes.reserve(max_node_id);
      97             : 
      98             :   // Renumber block IDs one at a time
      99             :   // We have to move them out of range, then back to range
     100           8 :   dof_id_type elem_count = 0;
     101           8 :   dof_id_type node_count = 0;
     102          40 :   for (const auto i : index_range(block_ids))
     103             :   {
     104         272 :     for (auto elem : mesh->active_subdomain_elements_ptr_range(block_ids[i]))
     105             :     {
     106             :       // If we didn't specify all the subdomains, we might have to skip elem ids that are still
     107             :       // taken
     108         480 :       while (mesh->query_elem_ptr(elem_count))
     109             :       {
     110         240 :         elem_count++;
     111             :       }
     112             :       // We can't mess with the range while looping in them
     113         240 :       new_elem_ids[elem->id()] = elem_count++;
     114             : 
     115        1200 :       for (auto & node : elem->node_ref_range())
     116             :         // prevent re-renumbering
     117         960 :         if (!renumbered_nodes.count(node.id()))
     118             :         {
     119             :           // If we didn't specify all the subdomains, we might have to skip node ids that are still
     120             :           // taken
     121        1296 :           while (mesh->query_node_ptr(node_count))
     122             :           {
     123         336 :             node_count++;
     124             :           }
     125         960 :           renumbered_nodes.insert(node.id());
     126         960 :           mesh->renumber_node(node.id(), node_count++);
     127             :         }
     128          32 :     }
     129             :   }
     130             : 
     131             :   // Now change the IDs
     132         248 :   for (const auto [key, value] : new_elem_ids)
     133         240 :     mesh->renumber_elem(key, value);
     134             : 
     135             :   // Update the max ids
     136           8 :   mesh->contract();
     137             : 
     138             :   // Try to disallow renumbering from now on since we just renumbered
     139           8 :   mesh->allow_renumbering(false);
     140             :   // No gain if exodus just renumbers this. Better to tell the user
     141           8 :   if (mesh->n_nodes() != mesh->max_node_id() || mesh->n_elem() != mesh->max_elem_id())
     142           0 :     mooseWarning("Mesh is not contiguously numbered after renumbering. The numbering may be erased "
     143           0 :                  "by outputs that require contiguous numbering such as Exodus.\nNumber of nodes: " +
     144           0 :                  std::to_string(mesh->n_nodes()) +
     145           0 :                  "\nMax node ID: " + std::to_string(mesh->max_node_id() - 1) +
     146           0 :                  "\nNumber of elements: " + std::to_string(mesh->n_elem()) +
     147           0 :                  "\nMax elem ID: " + std::to_string(mesh->max_elem_id() - 1));
     148             : 
     149           8 :   mesh->unset_is_prepared();
     150          16 :   return dynamic_pointer_cast<MeshBase>(mesh);
     151           8 : }

Generated by: LCOV version 1.14