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