LCOV - code coverage report
Current view: top level - src/meshgenerators - MeshExtruderGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 76 81 93.8 %
Date: 2025-07-17 01:28:37 Functions: 6 6 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 "MeshExtruderGenerator.h"
      11             : #include "MooseMeshUtils.h"
      12             : #include "CastUniquePointer.h"
      13             : 
      14             : #include "libmesh/replicated_mesh.h"
      15             : #include "libmesh/boundary_info.h"
      16             : #include "libmesh/elem.h"
      17             : 
      18             : registerMooseObjectDeprecated("MooseApp", MeshExtruderGenerator, "12/31/2025 24:00");
      19             : 
      20             : InputParameters
      21       14839 : MeshExtruderGenerator::validParams()
      22             : {
      23       14839 :   InputParameters params = MeshGenerator::validParams();
      24             : 
      25       14839 :   params.addRequiredParam<MeshGeneratorName>("input", "the mesh we want to extrude");
      26       14839 :   params.addClassDescription("Takes a 1D or 2D mesh and extrudes the entire structure along the "
      27             :                              "specified axis increasing the dimensionality of the mesh.");
      28       14839 :   params.addRequiredParam<RealVectorValue>("extrusion_vector",
      29             :                                            "The direction and length of the extrusion");
      30       14839 :   params.addParam<unsigned int>("num_layers", 1, "The number of layers in the extruded mesh");
      31       14839 :   params.addParam<std::vector<BoundaryName>>(
      32             :       "bottom_sideset", "The boundary that will be applied to the bottom of the extruded mesh");
      33       14839 :   params.addParam<std::vector<BoundaryName>>(
      34             :       "top_sideset", "The boundary that will be to the top of the extruded mesh");
      35             : 
      36       44517 :   params.addParam<std::vector<SubdomainID>>(
      37             :       "existing_subdomains",
      38       29678 :       std::vector<SubdomainID>(),
      39             :       "The subdomains that will be remapped for specific layers");
      40       44517 :   params.addParam<std::vector<unsigned int>>(
      41             :       "layers",
      42       29678 :       std::vector<unsigned int>(),
      43             :       "The layers where the \"existing_subdomain\" will be remapped to new ids");
      44       44517 :   params.addParam<std::vector<unsigned int>>(
      45             :       "new_ids",
      46       29678 :       std::vector<unsigned int>(),
      47             :       "The list of new ids, This list should be either length \"existing_subdomains\" or "
      48             :       "\"existing_subdomains\" * layers");
      49             : 
      50       14839 :   return params;
      51           0 : }
      52             : 
      53         287 : MeshExtruderGenerator::MeshExtruderGenerator(const InputParameters & parameters)
      54             :   : MeshGenerator(parameters),
      55         287 :     _input(getMesh("input")),
      56         287 :     _extrusion_vector(getParam<RealVectorValue>("extrusion_vector")),
      57         287 :     _num_layers(getParam<unsigned int>("num_layers")),
      58         287 :     _existing_subdomains(getParam<std::vector<SubdomainID>>("existing_subdomains")),
      59         287 :     _layers(getParam<std::vector<unsigned int>>("layers")),
      60         574 :     _new_ids(getParam<std::vector<unsigned int>>("new_ids"))
      61             : {
      62             :   // Check the length of the vectors
      63         301 :   if (_existing_subdomains.size() != _new_ids.size() &&
      64          14 :       _existing_subdomains.size() * _layers.size() != _new_ids.size())
      65           0 :     mooseError(
      66             :         "The length of the \"existing_subdomains\", \"layers\", and \"new_ids\" are not valid");
      67         287 : }
      68             : 
      69             : std::unique_ptr<MeshBase>
      70         274 : MeshExtruderGenerator::generate()
      71             : {
      72         274 :   std::unique_ptr<MeshBase> source_mesh = std::move(_input);
      73             : 
      74         274 :   auto dest_mesh = buildMeshBaseObject();
      75             : 
      76             :   // check that the existing_subdomains exist in the mesh
      77         342 :   for (const auto & id : _existing_subdomains)
      78          72 :     if (!MooseMeshUtils::hasSubdomainID(*source_mesh, id))
      79           4 :       paramError("existing_subdomains", "The block ID '", id, "' was not found in the mesh");
      80             : 
      81         270 :   if (source_mesh->mesh_dimension() == 3)
      82           0 :     mooseError("You cannot extrude a 3D mesh !");
      83             : 
      84         270 :   std::unique_ptr<QueryElemSubdomainID> elem_subdomain_id;
      85         270 :   if (_existing_subdomains.size() > 0)
      86          20 :     elem_subdomain_id = std::make_unique<QueryElemSubdomainID>(
      87          20 :         _existing_subdomains, _layers, _new_ids, _num_layers);
      88             : 
      89         270 :   MeshTools::Generation::build_extrusion(dynamic_cast<libMesh::UnstructuredMesh &>(*dest_mesh),
      90         270 :                                          *source_mesh,
      91             :                                          _num_layers,
      92             :                                          _extrusion_vector,
      93         270 :                                          elem_subdomain_id.get());
      94             : 
      95             :   // See if the user has requested specific sides for the top and bottom
      96         270 :   std::set<boundary_id_type> side_ids = dest_mesh->get_boundary_info().get_side_boundary_ids();
      97             : 
      98             :   // Handle distributed meshes: processors may not know all side ids
      99         270 :   _communicator.set_union(side_ids);
     100             : 
     101         270 :   std::set<boundary_id_type>::reverse_iterator last_side_it = side_ids.rbegin();
     102             : 
     103         270 :   const boundary_id_type old_top = *last_side_it;
     104             :   mooseAssert(last_side_it != side_ids.rend(), "Error in generating sidesets for extruded mesh");
     105         270 :   const boundary_id_type old_bottom = *++last_side_it;
     106             : 
     107             :   // Update the IDs
     108         270 :   if (isParamValid("bottom_sideset"))
     109         175 :     changeID(*dest_mesh, getParam<std::vector<BoundaryName>>("bottom_sideset"), old_bottom);
     110         270 :   if (isParamValid("top_sideset"))
     111         151 :     changeID(*dest_mesh, getParam<std::vector<BoundaryName>>("top_sideset"), old_top);
     112             : 
     113         270 :   dest_mesh->set_isnt_prepared();
     114         540 :   return dynamic_pointer_cast<MeshBase>(dest_mesh);
     115         270 : }
     116             : 
     117             : void
     118         326 : MeshExtruderGenerator::changeID(MeshBase & mesh,
     119             :                                 const std::vector<BoundaryName> & names,
     120             :                                 BoundaryID old_id)
     121             : {
     122         326 :   std::vector<boundary_id_type> boundary_ids = MooseMeshUtils::getBoundaryIDs(mesh, names, true);
     123             : 
     124         326 :   if (std::find(boundary_ids.begin(), boundary_ids.end(), old_id) == boundary_ids.end())
     125         315 :     MooseMeshUtils::changeBoundaryId(mesh, old_id, boundary_ids[0], true);
     126             : 
     127         652 :   for (unsigned int i = 0; i < boundary_ids.size(); ++i)
     128             :   {
     129         326 :     mesh.get_boundary_info().sideset_name(boundary_ids[i]) = names[i];
     130         326 :     mesh.get_boundary_info().nodeset_name(boundary_ids[i]) = names[i];
     131             :   }
     132         326 : }
     133             : 
     134          20 : MeshExtruderGenerator::QueryElemSubdomainID::QueryElemSubdomainID(
     135             :     const std::vector<SubdomainID> & existing_subdomains,
     136             :     std::vector<unsigned int> layers,
     137             :     const std::vector<unsigned int> & new_ids,
     138          20 :     unsigned int num_layers)
     139          20 :   : QueryElemSubdomainIDBase(), _num_layers(num_layers)
     140             : {
     141             :   // Setup our stride depending on whether the user passed unique sets in new ids or just a single
     142             :   // set of new ids
     143             :   const unsigned int stride =
     144          20 :       existing_subdomains.size() == new_ids.size() ? 0 : existing_subdomains.size();
     145             : 
     146          20 :   if (layers.size() == 0)
     147           0 :     for (unsigned int i = 0; i < _num_layers; i++)
     148           0 :       layers.push_back(i);
     149             : 
     150             :   // Populate the data structure
     151          80 :   for (unsigned int i = 0; i < layers.size(); ++i)
     152         240 :     for (unsigned int j = 0; j < existing_subdomains.size(); ++j)
     153         180 :       _layer_data[layers[i]][existing_subdomains[j]] = new_ids[i * stride + j];
     154          20 : }
     155             : 
     156             : subdomain_id_type
     157        1824 : MeshExtruderGenerator::QueryElemSubdomainID::get_subdomain_for_layer(const Elem * old_elem,
     158             :                                                                      unsigned int layer)
     159             : {
     160             :   mooseAssert(layer < _num_layers, "Access out of bounds: " << layer);
     161             : 
     162             :   // First locate the layer if it exists
     163             :   std::map<unsigned int, std::map<SubdomainID, unsigned int>>::const_iterator layer_it =
     164        1824 :       _layer_data.find(layer);
     165             : 
     166        1824 :   if (layer_it == _layer_data.end())
     167             :     // If the layer wasn't found, there is no mapping so just return the original subdomain id
     168         912 :     return old_elem->subdomain_id();
     169             :   else
     170             :   {
     171             :     std::map<SubdomainID, unsigned int>::const_iterator sub_id_it =
     172         912 :         layer_it->second.find(old_elem->subdomain_id());
     173             : 
     174         912 :     if (sub_id_it == layer_it->second.end())
     175             :       // If the subdomain wasn't found, it won't be remapped, so just return the original subdomain
     176             :       // id
     177         456 :       return old_elem->subdomain_id();
     178             : 
     179             :     // Return the remapped id
     180         456 :     return sub_id_it->second;
     181             :   }
     182             : }

Generated by: LCOV version 1.14