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