www.mooseframework.org
AnnularMeshGenerator.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 "AnnularMeshGenerator.h"
11 #include "CastUniquePointer.h"
12 
13 #include "libmesh/replicated_mesh.h"
14 #include "libmesh/face_quad4.h"
15 #include "libmesh/face_tri3.h"
16 
18 
20 
23 {
25 
26  params.addRangeCheckedParam<unsigned int>(
27  "nr", 1, "nr>0", "Number of elements in the radial direction");
28  params.addRequiredRangeCheckedParam<unsigned int>(
29  "nt", "nt>0", "Number of elements in the angular direction");
30  params.addRequiredRangeCheckedParam<Real>(
31  "rmin",
32  "rmin>=0.0",
33  "Inner radius. If rmin=0 then a disc mesh (with no central hole) will be created.");
34  params.addRequiredParam<Real>("rmax", "Outer radius");
35  params.addDeprecatedParam<Real>("tmin",
36  0.0,
37  "Minimum angle, measured in radians anticlockwise from x axis",
38  "Use dmin instead");
39  params.addDeprecatedParam<Real>(
40  "tmax",
41  2 * M_PI,
42  "Maximum angle, measured in radians anticlockwise from x axis. If "
43  "tmin=0 and tmax=2Pi an annular mesh is created. "
44  "Otherwise, only a sector of an annulus is created",
45  "Use dmin instead");
46  params.addParam<Real>(
47  "dmin", 0.0, "Minimum degree, measured in degrees anticlockwise from x axis");
48  params.addParam<Real>("dmax",
49  360.0,
50  "Maximum angle, measured in degrees anticlockwise from x axis. If "
51  "dmin=0 and dmax=360 an annular mesh is created. "
52  "Otherwise, only a sector of an annulus is created");
53  params.addRangeCheckedParam<Real>(
54  "growth_r", 1.0, "growth_r>0.0", "The ratio of radial sizes of successive rings of elements");
55  params.addParam<SubdomainID>(
56  "quad_subdomain_id", 0, "The subdomain ID given to the QUAD4 elements");
57  params.addParam<SubdomainID>("tri_subdomain_id",
58  1,
59  "The subdomain ID given to the TRI3 elements "
60  "(these exist only if rmin=0, and they exist "
61  "at the center of the disc");
62  params.addClassDescription("For rmin>0: creates an annular mesh of QUAD4 elements. For rmin=0: "
63  "creates a disc mesh of QUAD4 and TRI3 elements. Boundary sidesets "
64  "are created at rmax and rmin, and given these names. If dmin!=0 and "
65  "dmax!=360, a sector of an annulus or disc is created. In this case "
66  "boundary sidesets are also created a dmin and dmax, and "
67  "given these names");
68 
69  return params;
70 }
71 
73  : MeshGenerator(parameters),
74  _nr(getParam<unsigned int>("nr")),
75  _nt(getParam<unsigned int>("nt")),
76  _rmin(getParam<Real>("rmin")),
77  _rmax(getParam<Real>("rmax")),
78  _dmin(parameters.isParamSetByUser("tmin") ? getParam<Real>("tmin") / M_PI * 180.0
79  : getParam<Real>("dmin")),
80  _dmax(parameters.isParamSetByUser("tmax") ? getParam<Real>("tmax") / M_PI * 180.0
81  : getParam<Real>("dmax")),
82  _radians((parameters.isParamSetByUser("tmin") || parameters.isParamSetByUser("tmax")) ? true
83  : false),
84  _growth_r(getParam<Real>("growth_r")),
85  _len(_growth_r == 1.0 ? (_rmax - _rmin) / _nr
86  : (_rmax - _rmin) * (1.0 - _growth_r) / (1.0 - std::pow(_growth_r, _nr))),
87  _full_annulus(_dmin == 0.0 && _dmax == 360),
88  _quad_subdomain_id(getParam<SubdomainID>("quad_subdomain_id")),
89  _tri_subdomain_id(getParam<SubdomainID>("tri_subdomain_id"))
90 {
91  if ((parameters.isParamSetByUser("tmin") || parameters.isParamSetByUser("tmax")) &&
93  paramError("tmin",
94  "You specified the angles using both degrees and radians. Please use degrees.");
95 
96  if (_rmax <= _rmin)
97  paramError("rmax", "rmax must be greater than rmin");
98  if (_dmax <= _dmin)
99  paramError("dmax", "dmax must be greater than dmin");
100  if (_dmax - _dmin > 360)
101  paramError("dmax", "dmax - dmin must be <= 360");
102  if (_nt <= (_dmax - _dmin) / 180.0)
103  paramError("nt",
104  "nt must be greater than (dmax - dmin) / 180 in order to avoid inverted "
105  "elements");
107  paramError("quad_subdomain_id", "quad_subdomain_id must not equal tri_subdomain_id");
108 }
109 
110 std::unique_ptr<MeshBase>
112 {
113  // Have MOOSE construct the correct libMesh::Mesh object using Mesh block and CLI parameters.
114  auto mesh = _mesh->buildMeshBaseObject();
115 
116  const Real dt = (_dmax - _dmin) / _nt;
117 
118  mesh->set_mesh_dimension(2);
119  mesh->set_spatial_dimension(2);
120  BoundaryInfo & boundary_info = mesh->get_boundary_info();
121 
122  const unsigned num_angular_nodes = (_full_annulus ? _nt : _nt + 1);
123  const unsigned num_nodes =
124  (_rmin > 0.0 ? (_nr + 1) * num_angular_nodes : _nr * num_angular_nodes + 1);
125  const unsigned min_nonzero_layer_num = (_rmin > 0.0 ? 0 : 1);
126  std::vector<Node *> nodes(num_nodes);
127  unsigned node_id = 0;
128 
129  // add nodes at rmax that aren't yet connected to any elements
130  Real current_r = _rmax;
131  for (unsigned angle_num = 0; angle_num < num_angular_nodes; ++angle_num)
132  {
133  const Real angle = _dmin + angle_num * dt;
134  const Real x = current_r * std::cos(angle * M_PI / 180.0);
135  const Real y = current_r * std::sin(angle * M_PI / 180.0);
136  nodes[node_id] = mesh->add_point(Point(x, y, 0.0), node_id);
137  node_id++;
138  }
139 
140  // add nodes at smaller radii, and connect them with elements
141  for (unsigned layer_num = _nr; layer_num > min_nonzero_layer_num; --layer_num)
142  {
143  if (layer_num == 1)
144  current_r = _rmin; // account for precision loss
145  else
146  current_r -= _len * std::pow(_growth_r, layer_num - 1);
147 
148  // add node at angle = _dmin
149  nodes[node_id] = mesh->add_point(Point(current_r * std::cos(_dmin * M_PI / 180.0),
150  current_r * std::sin(_dmin * M_PI / 180.0),
151  0.0),
152  node_id);
153  node_id++;
154  for (unsigned angle_num = 1; angle_num < num_angular_nodes; ++angle_num)
155  {
156  const Real angle = _dmin + angle_num * dt;
157  const Real x = current_r * std::cos(angle * M_PI / 180.0);
158  const Real y = current_r * std::sin(angle * M_PI / 180.0);
159  nodes[node_id] = mesh->add_point(Point(x, y, 0.0), node_id);
160  Elem * elem = mesh->add_elem(new Quad4);
161  elem->set_node(0) = nodes[node_id];
162  elem->set_node(1) = nodes[node_id - 1];
163  elem->set_node(2) = nodes[node_id - num_angular_nodes - 1];
164  elem->set_node(3) = nodes[node_id - num_angular_nodes];
165  elem->subdomain_id() = _quad_subdomain_id;
166  node_id++;
167 
168  if (layer_num == _nr)
169  // add outer boundary (boundary_id = 1)
170  boundary_info.add_side(elem, 2, 1);
171  if (layer_num == 1)
172  // add inner boundary (boundary_id = 0)
173  boundary_info.add_side(elem, 0, 0);
174  if (!_full_annulus && angle_num == 1)
175  // add tmin boundary (boundary_id = 2)
176  boundary_info.add_side(elem, 1, 2);
177  if (!_full_annulus && angle_num == num_angular_nodes - 1)
178  // add tmin boundary (boundary_id = 3)
179  boundary_info.add_side(elem, 3, 3);
180  }
181  if (_full_annulus)
182  {
183  // add element connecting to node at angle=0
184  Elem * elem = mesh->add_elem(new Quad4);
185  elem->set_node(0) = nodes[node_id - num_angular_nodes];
186  elem->set_node(1) = nodes[node_id - 1];
187  elem->set_node(2) = nodes[node_id - num_angular_nodes - 1];
188  elem->set_node(3) = nodes[node_id - 2 * num_angular_nodes];
189  elem->subdomain_id() = _quad_subdomain_id;
190 
191  if (layer_num == _nr)
192  // add outer boundary (boundary_id = 1)
193  boundary_info.add_side(elem, 2, 1);
194  if (layer_num == 1)
195  // add inner boundary (boundary_id = 0)
196  boundary_info.add_side(elem, 0, 0);
197  }
198  }
199 
200  // add single node at origin, if relevant
201  if (_rmin == 0.0)
202  {
203  nodes[node_id] = mesh->add_point(Point(0.0, 0.0, 0.0), node_id);
204  boundary_info.add_node(node_id, 0); // boundary_id=0 is centre
205  for (unsigned angle_num = 0; angle_num < num_angular_nodes - 1; ++angle_num)
206  {
207  Elem * elem = mesh->add_elem(new Tri3);
208  elem->set_node(0) = nodes[node_id];
209  elem->set_node(1) = nodes[node_id - num_angular_nodes + angle_num];
210  elem->set_node(2) = nodes[node_id - num_angular_nodes + angle_num + 1];
211  elem->subdomain_id() = _tri_subdomain_id;
212  }
213  if (_full_annulus)
214  {
215  Elem * elem = mesh->add_elem(new Tri3);
216  elem->set_node(0) = nodes[node_id];
217  elem->set_node(1) = nodes[node_id - 1];
218  elem->set_node(2) = nodes[node_id - num_angular_nodes];
219  elem->subdomain_id() = _tri_subdomain_id;
220  }
221  }
222 
223  boundary_info.sideset_name(0) = "rmin";
224  boundary_info.sideset_name(1) = "rmax";
225  boundary_info.nodeset_name(0) = "rmin";
226  boundary_info.nodeset_name(1) = "rmax";
227  if (!_full_annulus)
228  {
229  if (_radians)
230  {
231  boundary_info.sideset_name(2) = "tmin";
232  boundary_info.sideset_name(3) = "tmax";
233  boundary_info.nodeset_name(2) = "tmin";
234  boundary_info.nodeset_name(3) = "tmax";
235  }
236  else
237  {
238  boundary_info.sideset_name(2) = "dmin";
239  boundary_info.sideset_name(3) = "dmax";
240  boundary_info.nodeset_name(2) = "dmin";
241  boundary_info.nodeset_name(3) = "dmax";
242  }
243  }
244 
245  mesh->prepare_for_use(false);
246 
247  return dynamic_pointer_cast<MeshBase>(mesh);
248 }
InputParameters::isParamSetByUser
bool isParamSetByUser(const std::string &name) const
Method returns true if the parameter was by the user.
Definition: InputParameters.C:837
defineLegacyParams
defineLegacyParams(AnnularMeshGenerator)
AnnularMeshGenerator
Generates an annular mesh given all the parameters.
Definition: AnnularMeshGenerator.h:23
AnnularMeshGenerator::validParams
static InputParameters validParams()
Definition: AnnularMeshGenerator.C:22
MeshGenerator
MeshGenerators are objects that can modify or add to an existing mesh.
Definition: MeshGenerator.h:32
AnnularMeshGenerator::_rmin
const Real _rmin
Minimum radius.
Definition: AnnularMeshGenerator.h:40
InputParameters::addParam
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an option parameter and a documentation string to the InputParameters object.
Definition: InputParameters.h:1198
MooseObject::parameters
const InputParameters & parameters() const
Get the parameters of the object.
Definition: MooseObject.h:76
AnnularMeshGenerator::_quad_subdomain_id
const SubdomainID _quad_subdomain_id
Subdomain ID of created quad elements.
Definition: AnnularMeshGenerator.h:64
AnnularMeshGenerator::_dmin
const Real _dmin
Minimum angle in degrees.
Definition: AnnularMeshGenerator.h:46
MooseObject::paramError
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 ...
Definition: MooseObject.h:215
MeshGenerator::_mesh
std::shared_ptr< MooseMesh > & _mesh
References to the mesh and displaced mesh (currently in the ActionWarehouse)
Definition: MeshGenerator.h:87
InputParameters
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
Definition: InputParameters.h:53
x
static PetscErrorCode Vec x
Definition: PetscDMMoose.C:1263
AnnularMeshGenerator::_nr
const unsigned _nr
Number of elements in radial direction.
Definition: AnnularMeshGenerator.h:34
AnnularMeshGenerator::_rmax
const Real _rmax
Maximum radius.
Definition: AnnularMeshGenerator.h:43
registerMooseObject
registerMooseObject("MooseApp", AnnularMeshGenerator)
AnnularMeshGenerator::generate
std::unique_ptr< MeshBase > generate() override
Generate / modify the mesh.
Definition: AnnularMeshGenerator.C:111
InputParameters::addDeprecatedParam
void addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
Definition: InputParameters.h:1406
AnnularMeshGenerator.h
InputParameters::addClassDescription
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.
Definition: InputParameters.C:70
AnnularMeshGenerator::_radians
const bool _radians
Bool to check if radians are given in the input file.
Definition: AnnularMeshGenerator.h:52
AnnularMeshGenerator::_tri_subdomain_id
const SubdomainID _tri_subdomain_id
Subdomain ID of created tri elements (that only exist if rmin=0)
Definition: AnnularMeshGenerator.h:67
InputParameters::addRequiredRangeCheckedParam
void addRequiredRangeCheckedParam(const std::string &name, const std::string &parsed_function, const std::string &doc_string)
These methods add an range checked parameters.
Definition: InputParameters.h:1235
SubdomainID
subdomain_id_type SubdomainID
Definition: AutomaticMortarGeneration.h:48
InputParameters::addRangeCheckedParam
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
Definition: InputParameters.h:1245
MathUtils::pow
T pow(T x, int e)
Definition: MathUtils.h:44
AnnularMeshGenerator::_dmax
const Real _dmax
Maximum angle in degrees.
Definition: AnnularMeshGenerator.h:49
std
Definition: TheWarehouse.h:80
AnnularMeshGenerator::_growth_r
const Real _growth_r
Bias on radial meshing.
Definition: AnnularMeshGenerator.h:55
AnnularMeshGenerator::_len
const Real _len
rmax = rmin + len + len*g + len*g^2 + len*g^3 + ... + len*g^(nr-1) = rmin + len*(1 - g^nr)/(1 - g)
Definition: AnnularMeshGenerator.h:58
AnnularMeshGenerator::_full_annulus
const bool _full_annulus
Whether a full annulus (as opposed to a sector) will needs to generate.
Definition: AnnularMeshGenerator.h:61
MeshGenerator::validParams
static InputParameters validParams()
Constructor.
Definition: MeshGenerator.C:17
AnnularMeshGenerator::_nt
const unsigned _nt
Number of elements in angular direction.
Definition: AnnularMeshGenerator.h:37
AnnularMeshGenerator::AnnularMeshGenerator
AnnularMeshGenerator(const InputParameters &parameters)
Definition: AnnularMeshGenerator.C:72
CastUniquePointer.h
InputParameters::addRequiredParam
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...
Definition: InputParameters.h:1176