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 14949 : RefineBlockGenerator::validParams() 21 : { 22 14949 : InputParameters params = MeshGenerator::validParams(); 23 : 24 14949 : params.addClassDescription("Mesh generator which refines one or more blocks in an existing mesh"); 25 14949 : params.addRequiredParam<MeshGeneratorName>("input", "Input mesh to refine"); 26 14949 : params.addRequiredParam<std::vector<SubdomainName>>("block", "The list of blocks to be refined"); 27 14949 : params.addRequiredParam<std::vector<unsigned int>>( 28 : "refinement", 29 : "Minimum amount of times to refine each block, corresponding to their index in 'block'"); 30 44847 : params.addParam<bool>( 31 : "enable_neighbor_refinement", 32 29898 : 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 44847 : params.addParam<Real>( 36 29898 : "max_element_volume", 1e8, "If elements are above that size, they will be refined more"); 37 : 38 14949 : return params; 39 0 : } 40 : 41 344 : RefineBlockGenerator::RefineBlockGenerator(const InputParameters & parameters) 42 : : MeshGenerator(parameters), 43 344 : _input(getMesh("input")), 44 344 : _block(getParam<std::vector<SubdomainName>>("block")), 45 344 : _refinement(getParam<std::vector<unsigned int>>("refinement")), 46 344 : _enable_neighbor_refinement(getParam<bool>("enable_neighbor_refinement")), 47 688 : _max_element_volume(getParam<Real>("max_element_volume")) 48 : { 49 344 : if (_block.size() != _refinement.size()) 50 4 : paramError("refinement", "The blocks and refinement parameter vectors should be the same size"); 51 340 : } 52 : 53 : std::unique_ptr<MeshBase> 54 330 : RefineBlockGenerator::generate() 55 : { 56 : // Get the list of block ids from the block names 57 : const auto block_ids = 58 330 : MooseMeshUtils::getSubdomainIDs(*_input, getParam<std::vector<SubdomainName>>("block")); 59 : 60 : // Check that the block ids/names exist in the mesh 61 330 : std::set<SubdomainID> mesh_blocks; 62 330 : _input->subdomain_ids(mesh_blocks); 63 : 64 1166 : for (std::size_t i = 0; i < block_ids.size(); ++i) 65 840 : 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 326 : std::unique_ptr<MeshBase> mesh = std::move(_input); 72 326 : int max = *std::max_element(_refinement.begin(), _refinement.end()); 73 : 74 326 : 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 326 : auto mesh_ptr = recursive_refine(block_ids, mesh, _refinement, max); 80 : 81 326 : 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 326 : bool found_element_to_refine = true; 88 326 : bool refined_on_size = false; 89 988 : while (found_element_to_refine) 90 : { 91 336 : found_element_to_refine = false; 92 1182 : for (auto bid : block_ids) 93 530282 : for (auto & elem : mesh_ptr->active_subdomain_elements_ptr_range(bid)) 94 264718 : if (elem->volume() >= _max_element_volume) 95 : { 96 27 : elem->set_refinement_flag(Elem::REFINE); 97 27 : found_element_to_refine = true; 98 846 : } 99 : // Refinement needs to be done on all ranks at the same time 100 336 : mesh_ptr->comm().max(found_element_to_refine); 101 : 102 336 : if (found_element_to_refine) 103 : { 104 10 : libMesh::MeshRefinement refinedmesh(*mesh_ptr); 105 10 : if (!_enable_neighbor_refinement) 106 10 : refinedmesh.face_level_mismatch_limit() = 0; 107 10 : refinedmesh.refine_elements(); 108 10 : refined_on_size = true; 109 10 : } 110 : } 111 : 112 326 : if (refined_on_size || max > 0) 113 280 : mesh_ptr->set_isnt_prepared(); 114 : 115 652 : return mesh_ptr; 116 326 : } 117 : 118 : std::unique_ptr<MeshBase> 119 689 : 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 689 : if (ref_step == max) 126 326 : return dynamic_pointer_cast<MeshBase>(mesh); 127 1383 : for (std::size_t i = 0; i < block_ids.size(); i++) 128 : { 129 1020 : if (refinement[i] > 0 && refinement[i] > ref_step) 130 : { 131 83301 : for (const auto & elem : mesh->active_subdomain_elements_ptr_range(block_ids[i])) 132 42014 : elem->set_refinement_flag(Elem::REFINE); 133 : } 134 : } 135 363 : libMesh::MeshRefinement refinedmesh(*mesh); 136 363 : if (!_enable_neighbor_refinement) 137 240 : refinedmesh.face_level_mismatch_limit() = 0; 138 363 : refinedmesh.refine_elements(); 139 : 140 363 : ref_step++; 141 363 : return recursive_refine(block_ids, mesh, refinement, max, ref_step); 142 363 : }