13 #include "libmesh/replicated_mesh.h"
14 #include "libmesh/face_quad4.h"
15 #include "libmesh/face_tri3.h"
27 "nr", 1,
"nr>0",
"Number of elements in the radial direction");
29 "nt",
"nt>0",
"Number of elements in the angular direction");
33 "Inner radius. If rmin=0 then a disc mesh (with no central hole) will be created.");
37 "Minimum angle, measured in radians anticlockwise from x axis",
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",
47 "dmin", 0.0,
"Minimum degree, measured in degrees anticlockwise from x axis");
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");
54 "growth_r", 1.0,
"growth_r>0.0",
"The ratio of radial sizes of successive rings of elements");
56 "quad_subdomain_id", 0,
"The subdomain ID given to the QUAD4 elements");
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 "
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
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"))
94 "You specified the angles using both degrees and radians. Please use degrees.");
97 paramError(
"rmax",
"rmax must be greater than rmin");
99 paramError(
"dmax",
"dmax must be greater than dmin");
101 paramError(
"dmax",
"dmax - dmin must be <= 360");
104 "nt must be greater than (dmax - dmin) / 180 in order to avoid inverted "
107 paramError(
"quad_subdomain_id",
"quad_subdomain_id must not equal tri_subdomain_id");
110 std::unique_ptr<MeshBase>
114 auto mesh =
_mesh->buildMeshBaseObject();
118 mesh->set_mesh_dimension(2);
119 mesh->set_spatial_dimension(2);
120 BoundaryInfo & boundary_info = mesh->get_boundary_info();
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;
130 Real current_r =
_rmax;
131 for (
unsigned angle_num = 0; angle_num < num_angular_nodes; ++angle_num)
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);
141 for (
unsigned layer_num =
_nr; layer_num > min_nonzero_layer_num; --layer_num)
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),
154 for (
unsigned angle_num = 1; angle_num < num_angular_nodes; ++angle_num)
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];
168 if (layer_num ==
_nr)
170 boundary_info.add_side(elem, 2, 1);
173 boundary_info.add_side(elem, 0, 0);
176 boundary_info.add_side(elem, 1, 2);
179 boundary_info.add_side(elem, 3, 3);
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];
191 if (layer_num ==
_nr)
193 boundary_info.add_side(elem, 2, 1);
196 boundary_info.add_side(elem, 0, 0);
203 nodes[node_id] = mesh->add_point(Point(0.0, 0.0, 0.0), node_id);
204 boundary_info.add_node(node_id, 0);
205 for (
unsigned angle_num = 0; angle_num < num_angular_nodes - 1; ++angle_num)
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];
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];
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";
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";
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";
245 mesh->prepare_for_use(
false);
247 return dynamic_pointer_cast<MeshBase>(mesh);