LCOV - code coverage report
Current view: top level - src/meshgenerators - RefineBlockGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 70 72 97.2 %
Date: 2025-08-08 20:01:16 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       15009 : RefineBlockGenerator::validParams()
      21             : {
      22       15009 :   InputParameters params = MeshGenerator::validParams();
      23             : 
      24       15009 :   params.addClassDescription("Mesh generator which refines one or more blocks in an existing mesh");
      25       15009 :   params.addRequiredParam<MeshGeneratorName>("input", "Input mesh to refine");
      26       15009 :   params.addRequiredParam<std::vector<SubdomainName>>("block", "The list of blocks to be refined");
      27       15009 :   params.addRequiredParam<std::vector<unsigned int>>(
      28             :       "refinement",
      29             :       "Minimum amount of times to refine each block, corresponding to their index in 'block'");
      30       45027 :   params.addParam<bool>(
      31             :       "enable_neighbor_refinement",
      32       30018 :       true,
      33             :       "Toggles whether neighboring level one elements should be refined or not. Defaults to true. "
      34             :       "False may lead to unsupported mesh non-conformality without great care.");
      35       45027 :   params.addParam<Real>(
      36       30018 :       "max_element_volume", 1e8, "If elements are above that size, they will be refined more");
      37             : 
      38       15009 :   return params;
      39           0 : }
      40             : 
      41         374 : RefineBlockGenerator::RefineBlockGenerator(const InputParameters & parameters)
      42             :   : MeshGenerator(parameters),
      43         374 :     _input(getMesh("input")),
      44         374 :     _block(getParam<std::vector<SubdomainName>>("block")),
      45         374 :     _refinement(getParam<std::vector<unsigned int>>("refinement")),
      46         374 :     _enable_neighbor_refinement(getParam<bool>("enable_neighbor_refinement")),
      47         748 :     _max_element_volume(getParam<Real>("max_element_volume"))
      48             : {
      49         374 :   if (_block.size() != _refinement.size())
      50           4 :     paramError("refinement", "The blocks and refinement parameter vectors should be the same size");
      51         370 : }
      52             : 
      53             : std::unique_ptr<MeshBase>
      54         360 : RefineBlockGenerator::generate()
      55             : {
      56             :   // Get the list of block ids from the block names
      57             :   const auto block_ids =
      58         360 :       MooseMeshUtils::getSubdomainIDs(*_input, getParam<std::vector<SubdomainName>>("block"));
      59             : 
      60             :   // Check that the block ids/names exist in the mesh
      61         360 :   std::set<SubdomainID> mesh_blocks;
      62         360 :   _input->subdomain_ids(mesh_blocks);
      63             : 
      64        1278 :   for (std::size_t i = 0; i < block_ids.size(); ++i)
      65         922 :     if (!MooseMeshUtils::hasSubdomainID(*_input, block_ids[i]))
      66           4 :       paramError("block",
      67             :                  "The block '",
      68           4 :                  getParam<std::vector<SubdomainName>>("block")[i],
      69             :                  "' was not found within the mesh");
      70             : 
      71         356 :   std::unique_ptr<MeshBase> mesh = std::move(_input);
      72         356 :   int max = *std::max_element(_refinement.begin(), _refinement.end());
      73             : 
      74         356 :   if (max > 0 && !mesh->is_replicated() && !mesh->is_prepared())
      75             :     // refinement requires that (or at least it asserts that) the mesh is either replicated or
      76             :     // prepared
      77          28 :     mesh->prepare_for_use();
      78             : 
      79         356 :   auto mesh_ptr = recursive_refine(block_ids, mesh, _refinement, max);
      80             : 
      81         356 :   if (max > 0 && !mesh_ptr->is_replicated() && !mesh_ptr->is_prepared())
      82             :     // refinement requires that (or at least it asserts that) the mesh is either replicated or
      83             :     // prepared
      84           0 :     mesh_ptr->prepare_for_use();
      85             : 
      86             :   // Refine elements that are too big
      87         356 :   bool found_element_to_refine = true;
      88         356 :   bool refined_on_size = false;
      89        1079 :   while (found_element_to_refine)
      90             :   {
      91         367 :     found_element_to_refine = false;
      92        1296 :     for (auto bid : block_ids)
      93      587411 :       for (auto & elem : mesh_ptr->active_subdomain_elements_ptr_range(bid))
      94      293241 :         if (elem->volume() >= _max_element_volume)
      95             :         {
      96          30 :           elem->set_refinement_flag(Elem::REFINE);
      97          30 :           found_element_to_refine = true;
      98         929 :         }
      99             :     // Refinement needs to be done on all ranks at the same time
     100         367 :     mesh_ptr->comm().max(found_element_to_refine);
     101             : 
     102         367 :     if (found_element_to_refine)
     103             :     {
     104          11 :       libMesh::MeshRefinement refinedmesh(*mesh_ptr);
     105          11 :       if (!_enable_neighbor_refinement)
     106          11 :         refinedmesh.face_level_mismatch_limit() = 0;
     107          11 :       refinedmesh.refine_elements();
     108          11 :       refined_on_size = true;
     109          11 :     }
     110             :   }
     111             : 
     112         356 :   if (refined_on_size || max > 0)
     113         308 :     mesh_ptr->set_isnt_prepared();
     114             : 
     115         712 :   return mesh_ptr;
     116         356 : }
     117             : 
     118             : std::unique_ptr<MeshBase>
     119         755 : RefineBlockGenerator::recursive_refine(std::vector<subdomain_id_type> block_ids,
     120             :                                        std::unique_ptr<MeshBase> & mesh,
     121             :                                        std::vector<unsigned int> refinement,
     122             :                                        unsigned int max,
     123             :                                        unsigned int ref_step)
     124             : {
     125         755 :   if (ref_step == max)
     126         356 :     return dynamic_pointer_cast<MeshBase>(mesh);
     127        1524 :   for (std::size_t i = 0; i < block_ids.size(); i++)
     128             :   {
     129        1125 :     if (refinement[i] > 0 && refinement[i] > ref_step)
     130             :     {
     131       92060 :       for (const auto & elem : mesh->active_subdomain_elements_ptr_range(block_ids[i]))
     132       46431 :         elem->set_refinement_flag(Elem::REFINE);
     133             :     }
     134             :   }
     135         399 :   libMesh::MeshRefinement refinedmesh(*mesh);
     136         399 :   if (!_enable_neighbor_refinement)
     137         266 :     refinedmesh.face_level_mismatch_limit() = 0;
     138         399 :   refinedmesh.refine_elements();
     139             : 
     140         399 :   ref_step++;
     141         399 :   return recursive_refine(block_ids, mesh, refinement, max, ref_step);
     142         399 : }

Generated by: LCOV version 1.14