LCOV - code coverage report
Current view: top level - src/meshgenerators - RefineBlockGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 76 78 97.4 %
Date: 2026-05-29 20:35:17 Functions: 4 4 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 "RefineBlockGenerator.h"
      11             : #include "MooseMeshUtils.h"
      12             : 
      13             : #include "libmesh/elem.h"
      14             : #include "libmesh/mesh_refinement.h"
      15             : #include "CastUniquePointer.h"
      16             : 
      17             : registerMooseObject("MooseApp", RefineBlockGenerator);
      18             : 
      19             : InputParameters
      20        3726 : RefineBlockGenerator::validParams()
      21             : {
      22        3726 :   InputParameters params = MeshGenerator::validParams();
      23             : 
      24        7452 :   params.addClassDescription("Mesh generator which refines one or more blocks in an existing mesh");
      25       14904 :   params.addRequiredParam<MeshGeneratorName>("input", "Input mesh to refine");
      26       14904 :   params.addRequiredParam<std::vector<SubdomainName>>("block", "The list of blocks to be refined");
      27       14904 :   params.addRequiredParam<std::vector<unsigned int>>(
      28             :       "refinement",
      29             :       "Minimum amount of times to refine each block, corresponding to their index in 'block'. A "
      30             :       "single value can be specified to refine all blocks.");
      31       11178 :   params.addParam<bool>(
      32             :       "enable_neighbor_refinement",
      33        7452 :       true,
      34             :       "Toggles whether neighboring level one elements should be refined or not. Defaults to true. "
      35             :       "False may lead to unsupported mesh non-conformality without great care.");
      36        7452 :   params.addParam<Real>(
      37        7452 :       "max_element_volume", 1e8, "If elements are above that size, they will be refined more");
      38             : 
      39        3726 :   return params;
      40           0 : }
      41             : 
      42         334 : RefineBlockGenerator::RefineBlockGenerator(const InputParameters & parameters)
      43             :   : MeshGenerator(parameters),
      44         334 :     _input(getMesh("input")),
      45         668 :     _block(getParam<std::vector<SubdomainName>>("block")),
      46         668 :     _refinement(getParam<std::vector<unsigned int>>("refinement")),
      47         668 :     _enable_neighbor_refinement(getParam<bool>("enable_neighbor_refinement")),
      48        1002 :     _max_element_volume(getParam<Real>("max_element_volume"))
      49             : {
      50         334 :   if (_refinement.size() == 1)
      51          35 :     _refinement.resize(_block.size(), _refinement[0]);
      52         334 :   if (_block.size() != _refinement.size())
      53           6 :     paramError("refinement", "The blocks and refinement parameter vectors should be the same size");
      54         331 : }
      55             : 
      56             : std::unique_ptr<MeshBase>
      57         322 : RefineBlockGenerator::generate()
      58             : {
      59             :   // Get the list of block ids from the block names
      60             :   const auto block_ids =
      61         644 :       MooseMeshUtils::getSubdomainIDs(*_input, getParam<std::vector<SubdomainName>>("block"));
      62             : 
      63             :   // Check that the block ids/names exist in the mesh
      64         322 :   if (!_input->preparation().has_cached_elem_data)
      65         276 :     _input->cache_elem_data();
      66         322 :   std::set<SubdomainID> mesh_blocks;
      67         322 :   _input->subdomain_ids(mesh_blocks);
      68             : 
      69        1148 :   for (std::size_t i = 0; i < block_ids.size(); ++i)
      70         829 :     if (!MooseMeshUtils::hasSubdomainID(*_input, block_ids[i]))
      71           9 :       paramError("block",
      72             :                  "The block '",
      73           6 :                  getParam<std::vector<SubdomainName>>("block")[i],
      74             :                  "' was not found within the mesh.\nBlock ID: ",
      75           3 :                  block_ids[i],
      76             :                  "\nBlock IDs in the mesh: ",
      77           6 :                  Moose::stringify(mesh_blocks));
      78             : 
      79         319 :   std::unique_ptr<MeshBase> mesh = std::move(_input);
      80         319 :   int max = *std::max_element(_refinement.begin(), _refinement.end());
      81             : 
      82         319 :   if (max > 0 && !mesh->is_replicated() && !mesh->is_prepared())
      83             :     // refinement requires that (or at least it asserts that) the mesh is either replicated or
      84             :     // prepared
      85          28 :     mesh->prepare_for_use();
      86             : 
      87         319 :   auto mesh_ptr = recursive_refine(block_ids, mesh, _refinement, max);
      88             : 
      89         319 :   if (max > 0 && !mesh_ptr->is_replicated() && !mesh_ptr->is_prepared())
      90             :     // refinement requires that (or at least it asserts that) the mesh is either replicated or
      91             :     // prepared
      92           0 :     mesh_ptr->prepare_for_use();
      93             : 
      94             :   // Refine elements that are too big
      95         319 :   bool found_element_to_refine = true;
      96         319 :   bool refined_on_size = false;
      97         967 :   while (found_element_to_refine)
      98             :   {
      99         329 :     found_element_to_refine = false;
     100        1165 :     for (auto bid : block_ids)
     101      264546 :       for (auto & elem : mesh_ptr->active_subdomain_elements_ptr_range(bid))
     102      263710 :         if (elem->volume() >= _max_element_volume)
     103             :         {
     104          27 :           elem->set_refinement_flag(Elem::REFINE);
     105          27 :           found_element_to_refine = true;
     106         836 :         }
     107             :     // Refinement needs to be done on all ranks at the same time
     108         329 :     mesh_ptr->comm().max(found_element_to_refine);
     109             : 
     110         329 :     if (found_element_to_refine)
     111             :     {
     112          10 :       libMesh::MeshRefinement refinedmesh(*mesh_ptr);
     113          10 :       if (!_enable_neighbor_refinement)
     114          10 :         refinedmesh.face_level_mismatch_limit() = 0;
     115          10 :       refinedmesh.refine_elements();
     116          10 :       refined_on_size = true;
     117          10 :     }
     118             :   }
     119             : 
     120         319 :   if (refined_on_size || max > 0)
     121         276 :     mesh_ptr->unset_is_prepared();
     122             : 
     123         638 :   return mesh_ptr;
     124         319 : }
     125             : 
     126             : std::unique_ptr<MeshBase>
     127         678 : RefineBlockGenerator::recursive_refine(std::vector<subdomain_id_type> block_ids,
     128             :                                        std::unique_ptr<MeshBase> & mesh,
     129             :                                        std::vector<unsigned int> refinement,
     130             :                                        unsigned int max,
     131             :                                        unsigned int ref_step)
     132             : {
     133         678 :   if (ref_step == max)
     134         319 :     return dynamic_pointer_cast<MeshBase>(mesh);
     135        1375 :   for (std::size_t i = 0; i < block_ids.size(); i++)
     136             :   {
     137        1016 :     if (refinement[i] > 0 && refinement[i] > ref_step)
     138             :     {
     139       83093 :       for (const auto & elem : mesh->active_subdomain_elements_ptr_range(block_ids[i]))
     140       41908 :         elem->set_refinement_flag(Elem::REFINE);
     141             :     }
     142             :   }
     143         359 :   libMesh::MeshRefinement refinedmesh(*mesh);
     144         359 :   if (!_enable_neighbor_refinement)
     145         240 :     refinedmesh.face_level_mismatch_limit() = 0;
     146         359 :   refinedmesh.refine_elements();
     147             : 
     148         359 :   ref_step++;
     149         359 :   return recursive_refine(block_ids, mesh, refinement, max, ref_step);
     150         359 : }

Generated by: LCOV version 1.14