https://mooseframework.inl.gov
RefineBlockGenerator.C
Go to the documentation of this file.
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 
18 
21 {
23 
24  params.addClassDescription("Mesh generator which refines one or more blocks in an existing mesh");
25  params.addRequiredParam<MeshGeneratorName>("input", "Input mesh to refine");
26  params.addRequiredParam<std::vector<SubdomainName>>("block", "The list of blocks to be refined");
27  params.addRequiredParam<std::vector<unsigned int>>(
28  "refinement",
29  "Minimum amount of times to refine each block, corresponding to their index in 'block'");
30  params.addParam<bool>(
31  "enable_neighbor_refinement",
32  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  params.addParam<Real>(
36  "max_element_volume", 1e8, "If elements are above that size, they will be refined more");
37 
38  return params;
39 }
40 
42  : MeshGenerator(parameters),
43  _input(getMesh("input")),
44  _block(getParam<std::vector<SubdomainName>>("block")),
45  _refinement(getParam<std::vector<unsigned int>>("refinement")),
46  _enable_neighbor_refinement(getParam<bool>("enable_neighbor_refinement")),
47  _max_element_volume(getParam<Real>("max_element_volume"))
48 {
49  if (_block.size() != _refinement.size())
50  paramError("refinement", "The blocks and refinement parameter vectors should be the same size");
51 }
52 
53 std::unique_ptr<MeshBase>
55 {
56  // Get the list of block ids from the block names
57  const auto block_ids =
58  MooseMeshUtils::getSubdomainIDs(*_input, getParam<std::vector<SubdomainName>>("block"));
59 
60  // Check that the block ids/names exist in the mesh
61  std::set<SubdomainID> mesh_blocks;
62  _input->subdomain_ids(mesh_blocks);
63 
64  for (std::size_t i = 0; i < block_ids.size(); ++i)
65  if (!MooseMeshUtils::hasSubdomainID(*_input, block_ids[i]))
66  paramError("block",
67  "The block '",
68  getParam<std::vector<SubdomainName>>("block")[i],
69  "' was not found within the mesh");
70 
71  std::unique_ptr<MeshBase> mesh = std::move(_input);
72  int max = *std::max_element(_refinement.begin(), _refinement.end());
73 
74  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  mesh->prepare_for_use();
78 
79  auto mesh_ptr = recursive_refine(block_ids, mesh, _refinement, max);
80 
81  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  mesh_ptr->prepare_for_use();
85 
86  // Refine elements that are too big
87  bool found_element_to_refine = true;
88  bool refined_on_size = false;
89  while (found_element_to_refine)
90  {
91  found_element_to_refine = false;
92  for (auto bid : block_ids)
93  for (auto & elem : mesh_ptr->active_subdomain_elements_ptr_range(bid))
94  if (elem->volume() >= _max_element_volume)
95  {
96  elem->set_refinement_flag(Elem::REFINE);
97  found_element_to_refine = true;
98  }
99  // Refinement needs to be done on all ranks at the same time
100  mesh_ptr->comm().max(found_element_to_refine);
101 
102  if (found_element_to_refine)
103  {
104  libMesh::MeshRefinement refinedmesh(*mesh_ptr);
106  refinedmesh.face_level_mismatch_limit() = 0;
107  refinedmesh.refine_elements();
108  refined_on_size = true;
109  }
110  }
111 
112  if (refined_on_size || max > 0)
113  mesh_ptr->set_isnt_prepared();
114 
115  return mesh_ptr;
116 }
117 
118 std::unique_ptr<MeshBase>
119 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  if (ref_step == max)
126  return dynamic_pointer_cast<MeshBase>(mesh);
127  for (std::size_t i = 0; i < block_ids.size(); i++)
128  {
129  if (refinement[i] > 0 && refinement[i] > ref_step)
130  {
131  for (const auto & elem : mesh->active_subdomain_elements_ptr_range(block_ids[i]))
132  elem->set_refinement_flag(Elem::REFINE);
133  }
134  }
135  libMesh::MeshRefinement refinedmesh(*mesh);
137  refinedmesh.face_level_mismatch_limit() = 0;
138  refinedmesh.refine_elements();
139 
140  ref_step++;
141  return recursive_refine(block_ids, mesh, refinement, max, ref_step);
142 }
MeshBase & mesh
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
std::unique_ptr< T_DEST, T_DELETER > dynamic_pointer_cast(std::unique_ptr< T_SRC, T_DELETER > &src)
These are reworked from https://stackoverflow.com/a/11003103.
std::vector< subdomain_id_type > getSubdomainIDs(const libMesh::MeshBase &mesh, const std::vector< SubdomainName > &subdomain_name)
Get the associated subdomainIDs for the subdomain names that are passed in.
virtual std::unique_ptr< MeshBase > recursive_refine(const std::vector< subdomain_id_type > block_ids, std::unique_ptr< MeshBase > &mesh, const std::vector< unsigned int > refinement, const unsigned int max, unsigned int ref_step=0)
The actual function refining the blocks.
virtual std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
auto max(const L &left, const R &right)
RefineBlockGenerator(const InputParameters &parameters)
std::unique_ptr< MeshBase > & _input
Input mesh to refine.
bool hasSubdomainID(const MeshBase &input_mesh, const SubdomainID &id)
Whether a particular subdomain ID exists in the mesh.
const std::vector< unsigned int > _refinement
The amount of times to refine each block, corresponding to their index in &#39;block&#39;.
const Real _max_element_volume
maximum element size over which elements are refined
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
const std::vector< SubdomainName > _block
List of block(s) to refine.
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
static InputParameters validParams()
Definition: MeshGenerator.C:23
unsigned char & face_level_mismatch_limit()
const bool _enable_neighbor_refinement
Toggles whether neighboring level one elements should be refined or not. Defaults to true...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
registerMooseObject("MooseApp", RefineBlockGenerator)
MeshGenerators are objects that can modify or add to an existing mesh.
Definition: MeshGenerator.h:32
void ErrorVector unsigned int
static InputParameters validParams()
MeshGenerator for refining one or more blocks.