https://mooseframework.inl.gov
Loading...
Searching...
No Matches
AnnularMesh.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 "AnnularMesh.h"
11
12#include "MooseApp.h"
13
14#include "libmesh/face_quad4.h"
15#include "libmesh/face_tri3.h"
16
18
21{
23 params.addRangeCheckedParam<unsigned int>(
24 "nr", 1, "nr>0", "Number of elements in the radial direction");
25 params.addRequiredRangeCheckedParam<unsigned int>(
26 "nt", "nt>0", "Number of elements in the angular direction");
28 "rmin",
29 "rmin>=0.0",
30 "Inner radius. If rmin=0 then a disc mesh (with no central hole) will be created.");
31 params.addRequiredParam<Real>("rmax", "Outer radius");
32 params.addDeprecatedParam<Real>("tmin",
33 0.0,
34 "Minimum angle, measured in radians anticlockwise from x axis",
35 "Use dmin instead");
36 params.addDeprecatedParam<Real>(
37 "tmax",
38 2 * M_PI,
39 "Maximum angle, measured in radians anticlockwise from x axis. If "
40 "tmin=0 and tmax=2Pi an annular mesh is created. "
41 "Otherwise, only a sector of an annulus is created",
42 "Use dmin instead");
43 params.addParam<Real>(
44 "dmin", 0.0, "Minimum degree, measured in degrees anticlockwise from x axis");
45 params.addParam<Real>("dmax",
46 360.0,
47 "Maximum angle, measured in degrees anticlockwise from x axis. If "
48 "dmin=0 and dmax=360 an annular mesh is created. "
49 "Otherwise, only a sector of an annulus is created");
50 params.addRangeCheckedParam<Real>(
51 "growth_r", 1.0, "growth_r>0.0", "The ratio of radial sizes of successive rings of elements");
52 params.addParam<SubdomainID>(
53 "quad_subdomain_id", 0, "The subdomain ID given to the QUAD4 elements");
54 params.addParam<SubdomainID>("tri_subdomain_id",
55 1,
56 "The subdomain ID given to the TRI3 elements "
57 "(these exist only if rmin=0, and they exist "
58 "at the center of the disc");
59 params.addClassDescription("For rmin>0: creates an annular mesh of QUAD4 elements. For rmin=0: "
60 "creates a disc mesh of QUAD4 and TRI3 elements. Boundary sidesets "
61 "are created at rmax and rmin, and given these names. If dmin!=0 and "
62 "dmax!=360, a sector of an annulus or disc is created. In this case "
63 "boundary sidesets are also created a dmin and dmax, and "
64 "given these names");
65 return params;
66}
67
69 : MooseMesh(parameters),
70 _nr(getParam<unsigned int>("nr")),
71 _nt(getParam<unsigned int>("nt")),
72 _rmin(getParam<Real>("rmin")),
73 _rmax(getParam<Real>("rmax")),
74 _dmin(parameters.isParamSetByUser("tmin") ? getParam<Real>("tmin") / M_PI * 180.0
75 : getParam<Real>("dmin")),
76 _dmax(parameters.isParamSetByUser("tmax") ? getParam<Real>("tmax") / M_PI * 180.0
77 : getParam<Real>("dmax")),
78 _radians((parameters.isParamSetByUser("tmin") || parameters.isParamSetByUser("tmax")) ? true
79 : false),
80 _growth_r(getParam<Real>("growth_r")),
81 _len(_growth_r == 1.0 ? (_rmax - _rmin) / _nr
82 : (_rmax - _rmin) * (1.0 - _growth_r) / (1.0 - std::pow(_growth_r, _nr))),
83 _full_annulus(_dmin == 0.0 && _dmax == 360),
84 _quad_subdomain_id(getParam<SubdomainID>("quad_subdomain_id")),
85 _tri_subdomain_id(getParam<SubdomainID>("tri_subdomain_id")),
86 _dims_may_have_changed(false)
87{
88 if ((parameters.isParamSetByUser("tmin") || parameters.isParamSetByUser("tmax")) &&
90 paramError("tmin",
91 "You specified the angles using both degrees and radians. Please use degrees.");
92
93 if (_rmax <= _rmin)
94 paramError("rmax", "rmax must be greater than rmin");
95 if (_dmax <= _dmin)
96 paramError("dmax", "dmax must be greater than dmin");
97 if (_dmax - _dmin > 360)
98 paramError("dmax", "dmax - dmin must be <= 360");
99 if (_nt <= (_dmax - _dmin) / 180.0)
100 paramError("nt",
101 "nt must be greater than (dmax - dmin) / 180 in order to avoid inverted "
102 "elements");
104 paramError("quad_subdomain_id", "quad_subdomain_id must not equal tri_subdomain_id");
105}
106
107void
109{
110 MooseMesh::prepared(state);
111
112 // Fall back on scanning the mesh for coordinates instead of using input parameters for queries
113 if (!state)
115}
116
117Real
118AnnularMesh::getMinInDimension(unsigned int component) const
119{
121 return MooseMesh::getMinInDimension(component);
122
123 switch (component)
124 {
125 case 0:
126 return -_rmax;
127 case 1:
128 return -_rmax;
129 case 2:
130 return 0.0;
131 default:
132 mooseError("Invalid component");
133 }
134}
135
136Real
137AnnularMesh::getMaxInDimension(unsigned int component) const
138{
140 return MooseMesh::getMaxInDimension(component);
141
142 switch (component)
143 {
144 case 0:
145 return _rmax;
146 case 1:
147 return _rmax;
148 case 2:
149 return 0.0;
150 default:
151 mooseError("Invalid component");
152 }
153}
154
155std::unique_ptr<MooseMesh>
157{
158 return _app.getFactory().copyConstruct(*this);
159}
160
161void
163{
164 const Real dt = (_dmax - _dmin) / _nt;
165
166 MeshBase & mesh = getMesh();
167 mesh.clear();
168 mesh.set_mesh_dimension(2);
169 mesh.set_spatial_dimension(2);
170 libMesh::BoundaryInfo & boundary_info = mesh.get_boundary_info();
171
172 const unsigned num_angular_nodes = (_full_annulus ? _nt : _nt + 1);
173 const unsigned num_nodes =
174 (_rmin > 0.0 ? (_nr + 1) * num_angular_nodes : _nr * num_angular_nodes + 1);
175 const unsigned min_nonzero_layer_num = (_rmin > 0.0 ? 0 : 1);
176 std::vector<Node *> nodes(num_nodes);
177 unsigned node_id = 0;
178
179 // add nodes at rmax that aren't yet connected to any elements
180 Real current_r = _rmax;
181 for (unsigned angle_num = 0; angle_num < num_angular_nodes; ++angle_num)
182 {
183 const Real angle = _dmin + angle_num * dt;
184 const Real x = current_r * std::cos(angle * M_PI / 180.0);
185 const Real y = current_r * std::sin(angle * M_PI / 180.0);
186 nodes[node_id] = mesh.add_point(Point(x, y, 0.0), node_id);
187 node_id++;
188 }
189
190 // add nodes at smaller radii, and connect them with elements
191 for (unsigned layer_num = _nr; layer_num > min_nonzero_layer_num; --layer_num)
192 {
193 if (layer_num == 1)
194 current_r = _rmin; // account for precision loss
195 else
196 current_r -= _len * std::pow(_growth_r, layer_num - 1);
197
198 // add node at angle = _dmin
199 nodes[node_id] = mesh.add_point(Point(current_r * std::cos(_dmin * M_PI / 180.0),
200 current_r * std::sin(_dmin * M_PI / 180.0),
201 0.0),
202 node_id);
203 node_id++;
204 for (unsigned angle_num = 1; angle_num < num_angular_nodes; ++angle_num)
205 {
206 const Real angle = _dmin + angle_num * dt;
207 const Real x = current_r * std::cos(angle * M_PI / 180.0);
208 const Real y = current_r * std::sin(angle * M_PI / 180.0);
209 nodes[node_id] = mesh.add_point(Point(x, y, 0.0), node_id);
210 Elem * elem = mesh.add_elem(new libMesh::Quad4);
211 elem->set_node(0, nodes[node_id]);
212 elem->set_node(1, nodes[node_id - 1]);
213 elem->set_node(2, nodes[node_id - num_angular_nodes - 1]);
214 elem->set_node(3, nodes[node_id - num_angular_nodes]);
215 elem->subdomain_id() = _quad_subdomain_id;
216 node_id++;
217
218 if (layer_num == _nr)
219 // add outer boundary (boundary_id = 1)
220 boundary_info.add_side(elem, 2, 1);
221 if (layer_num == 1)
222 // add inner boundary (boundary_id = 0)
223 boundary_info.add_side(elem, 0, 0);
224 if (!_full_annulus && angle_num == 1)
225 // add tmin boundary (boundary_id = 2)
226 boundary_info.add_side(elem, 1, 2);
227 if (!_full_annulus && angle_num == num_angular_nodes - 1)
228 // add tmin boundary (boundary_id = 3)
229 boundary_info.add_side(elem, 3, 3);
230 }
231 if (_full_annulus)
232 {
233 // add element connecting to node at angle=0
234 Elem * elem = mesh.add_elem(new libMesh::Quad4);
235 elem->set_node(0, nodes[node_id - num_angular_nodes]);
236 elem->set_node(1, nodes[node_id - 1]);
237 elem->set_node(2, nodes[node_id - num_angular_nodes - 1]);
238 elem->set_node(3, nodes[node_id - 2 * num_angular_nodes]);
239 elem->subdomain_id() = _quad_subdomain_id;
240
241 if (layer_num == _nr)
242 // add outer boundary (boundary_id = 1)
243 boundary_info.add_side(elem, 2, 1);
244 if (layer_num == 1)
245 // add inner boundary (boundary_id = 0)
246 boundary_info.add_side(elem, 0, 0);
247 }
248 }
249
250 // add single node at origin, if relevant
251 if (_rmin == 0.0)
252 {
253 nodes[node_id] = mesh.add_point(Point(0.0, 0.0, 0.0), node_id);
254 boundary_info.add_node(node_id, 0); // boundary_id=0 is centre
255 for (unsigned angle_num = 0; angle_num < num_angular_nodes - 1; ++angle_num)
256 {
257 Elem * elem = mesh.add_elem(new libMesh::Tri3);
258 elem->set_node(0, nodes[node_id]);
259 elem->set_node(1, nodes[node_id - num_angular_nodes + angle_num]);
260 elem->set_node(2, nodes[node_id - num_angular_nodes + angle_num + 1]);
261 elem->subdomain_id() = _tri_subdomain_id;
262 }
263 if (_full_annulus)
264 {
265 Elem * elem = mesh.add_elem(new libMesh::Tri3);
266 elem->set_node(0, nodes[node_id]);
267 elem->set_node(1, nodes[node_id - 1]);
268 elem->set_node(2, nodes[node_id - num_angular_nodes]);
269 elem->subdomain_id() = _tri_subdomain_id;
270 }
271 }
272
273 boundary_info.sideset_name(0) = "rmin";
274 boundary_info.sideset_name(1) = "rmax";
275 boundary_info.nodeset_name(0) = "rmin";
276 boundary_info.nodeset_name(1) = "rmax";
277 if (!_full_annulus)
278 {
279 if (_radians)
280 {
281 boundary_info.sideset_name(2) = "tmin";
282 boundary_info.sideset_name(3) = "tmax";
283 boundary_info.nodeset_name(2) = "tmin";
284 boundary_info.nodeset_name(3) = "tmax";
285 }
286 else
287 {
288 boundary_info.sideset_name(2) = "dmin";
289 boundary_info.sideset_name(3) = "dmax";
290 boundary_info.nodeset_name(2) = "dmin";
291 boundary_info.nodeset_name(3) = "dmax";
292 }
293 }
294
295 // We just created this mesh from scratch, and we're not in the mesh
296 // generator system that will handle flagged preparation
297 // requirements later, so we need a full prepare_for_use() here.
298 mesh.prepare_for_use();
299}
registerMooseObject("MooseApp", AnnularMesh)
void ErrorVector unsigned int
Mesh generated from parameters.
Definition AnnularMesh.h:18
const bool _full_annulus
Whether a full annulus (as opposed to a sector) will needs to generate.
Definition AnnularMesh.h:64
AnnularMesh(const InputParameters &parameters)
Definition AnnularMesh.C:68
const unsigned _nr
Number of elements in radial direction.
Definition AnnularMesh.h:37
const Real _growth_r
Bias on radial meshing.
Definition AnnularMesh.h:58
const SubdomainID _quad_subdomain_id
Subdomain ID of created quad elements.
Definition AnnularMesh.h:67
virtual void buildMesh() override
Must be overridden by child classes.
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 AnnularMesh.h:61
const Real _rmax
Maximum radius.
Definition AnnularMesh.h:46
static InputParameters validParams()
Definition AnnularMesh.C:20
const unsigned _nt
Number of elements in angular direction.
Definition AnnularMesh.h:40
bool _dims_may_have_changed
Boolean to indicate that dimensions may have changed.
Definition AnnularMesh.h:73
virtual std::unique_ptr< MooseMesh > safeClone() const override
A safer version of the clone() method that hands back an allocated object wrapped in a smart pointer.
const Real _dmin
Minimum angle in degrees.
Definition AnnularMesh.h:49
const Real _rmin
Minimum radius.
Definition AnnularMesh.h:43
virtual Real getMinInDimension(unsigned int component) const override
Returns the min or max of the requested dimension respectively.
const Real _dmax
Maximum angle in degrees.
Definition AnnularMesh.h:52
const bool _radians
Bool to check if radians are given in the input file.
Definition AnnularMesh.h:55
virtual Real getMaxInDimension(unsigned int component) const override
const SubdomainID _tri_subdomain_id
Subdomain ID of created tri elements (that only exist if rmin=0)
Definition AnnularMesh.h:70
std::unique_ptr< T > copyConstruct(const T &object)
Copy constructs the object object.
Definition Factory.h:358
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addRequiredRangeCheckedParam(const std::string &name, const std::string &parsed_function, const std::string &doc_string)
These methods add an range checked parameters.
bool isParamSetByUser(const std::string &name) const
Method returns true if the parameter was set by the user.
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.
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...
void addDeprecatedParam(const std::string &name, const T &value, const std::string &doc_string, const std::string &deprecation_message)
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 addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
Factory & getFactory()
Retrieve a writable reference to the Factory associated with this App.
Definition MooseApp.h:407
const InputParameters & parameters() const
Get the parameters of the object.
Definition MooseBase.h:131
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 MooseBase.h:457
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition MooseBase.h:271
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition MooseMesh.h:95
virtual Elem * elem(const dof_id_type i)
Various accessors (pointers/references) for Elem "i".
Definition MooseMesh.C:3200
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition MooseMesh.C:3549
bool prepared() const
Setter/getter for whether the mesh is prepared.
Definition MooseMesh.C:3238
virtual Real getMaxInDimension(unsigned int component) const
Definition MooseMesh.C:2186
static InputParameters validParams()
Typical "Moose-style" constructor and copy constructor.
Definition MooseMesh.C:83
virtual Real getMinInDimension(unsigned int component) const
Returns the min or max of the requested dimension respectively.
Definition MooseMesh.C:2177
MooseApp & _app
The MOOSE application this is associated with.
Definition MooseBase.h:375
std::string & sideset_name(boundary_id_type id)
std::string & nodeset_name(boundary_id_type id)
void add_node(const Node *node, const boundary_id_type id)
void add_side(const dof_id_type elem, const unsigned short int side, const boundary_id_type id)
MeshBase & mesh
MooseUnits pow(const MooseUnits &, int)
Definition Units.C:537