libMesh
Loading...
Searching...
No Matches
Public Member Functions | Protected Attributes | List of all members
PerElemTest< elem_type > Class Template Reference

#include <elem_test.h>

Inheritance diagram for PerElemTest< elem_type >:
[legend]

Public Member Functions

void setUp ()
 

Protected Attributes

std::unique_ptr< Mesh_mesh
 
std::string libmesh_suite_name
 

Detailed Description

template<ElemType elem_type>
class PerElemTest< elem_type >

Definition at line 23 of file elem_test.h.

Member Function Documentation

◆ setUp()

template<ElemType elem_type>
void PerElemTest< elem_type >::setUp ( )
inline

Definition at line 30 of file elem_test.h.

31 {
32 const Real minpos = 1.5, maxpos = 5.5;
33 const unsigned int N = 2;
34
35 _mesh = std::make_unique<Mesh>(*TestCommWorld);
36
37 std::unique_ptr<Elem> test_elem;
38
39 if (elem_type != C0POLYHEDRON)
40 test_elem = Elem::build(elem_type);
41
42#ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
43#if LIBMESH_DIM > 1
44 if (test_elem.get() && test_elem->infinite())
45 {
46 Elem * elem = _mesh->add_elem(std::move(test_elem));
47
48 const auto add_point =
49 [this, elem](const unsigned int i,
50 const Real x,
51 const Real y,
52 const Real
53#if LIBMESH_DIM == 3
54 z
55#endif
56 )
57 {
58#if LIBMESH_DIM == 2
59 auto node = _mesh->add_point(Point(x, y), i);
60#else
61 auto node = _mesh->add_point(Point(x, y, z), i);
62#endif
63 elem->set_node(i, node);
64 };
65
66 const Real halfpos = (minpos + maxpos) / 2.;
67
68 if (elem_type == INFQUAD4 || elem_type == INFQUAD6 ||
69 elem_type == INFHEX8 || elem_type == INFHEX16 || elem_type == INFHEX18)
70 {
71 const bool is_quad = (elem_type == INFQUAD4 || elem_type == INFQUAD6);
72
73 add_point(0, minpos, minpos, minpos);
74 add_point(1, maxpos, minpos, minpos);
75 add_point(2+is_quad, maxpos, maxpos, minpos);
76 add_point(3-is_quad, minpos, maxpos, minpos);
77
78 if (elem_type == INFQUAD6)
79 {
80 add_point(4, halfpos, minpos, minpos);
81 add_point(5, halfpos, maxpos, minpos);
82 }
83 }
84 if (elem_type == INFHEX8 || elem_type == INFHEX16 || elem_type == INFHEX18)
85 {
86 add_point(4, minpos, minpos, maxpos);
87 add_point(5, maxpos, minpos, maxpos);
88 add_point(6, maxpos, maxpos, maxpos);
89 add_point(7, minpos, maxpos, maxpos);
90
91 if (elem_type == INFHEX16 || elem_type == INFHEX18)
92 {
93 add_point(8, halfpos, minpos, minpos);
94 add_point(9, maxpos, halfpos, minpos);
95 add_point(10, halfpos, maxpos, minpos);
96 add_point(11, minpos, halfpos, minpos);
97 add_point(12, halfpos, minpos, maxpos);
98 add_point(13, maxpos, halfpos, maxpos);
99 add_point(14, halfpos, maxpos, maxpos);
100 add_point(15, minpos, halfpos, maxpos);
101 }
102 if (elem_type == INFHEX18)
103 {
104 add_point(16, halfpos, halfpos, minpos);
105 add_point(17, halfpos, halfpos, maxpos);
106 }
107 }
108 if (elem_type == INFPRISM6 || elem_type == INFPRISM12)
109 {
110 add_point(0, minpos, minpos, minpos);
111 add_point(1, maxpos, minpos, minpos);
112 add_point(2, halfpos, maxpos, minpos);
113 add_point(3, minpos, minpos, maxpos);
114 add_point(4, maxpos, minpos, maxpos);
115 add_point(5, halfpos, maxpos, maxpos);
116
117 if (elem_type == INFPRISM12)
118 {
119 add_point(6, halfpos, minpos, minpos);
120 add_point(7, (halfpos + maxpos) / 2., halfpos, minpos);
121 add_point(8, (halfpos + minpos) / 2., halfpos, minpos);
122 add_point(9, halfpos, minpos, maxpos);
123 add_point(10, (halfpos + maxpos) / 2., halfpos, maxpos);
124 add_point(11, (halfpos + minpos) / 2., halfpos, maxpos);
125 }
126 }
127
128 _mesh->prepare_for_use();
129 }
130 else
131#endif // LIBMESH_DIM > 1
132#endif // LIBMESH_ENABLE_INFINITE_ELEMENTS
133 if (elem_type == C0POLYGON)
134 {
135 // We're not going to implement build_square for e.g.
136 // pentagons any time soon.
137 //
138 // We should probably implement build_dual_mesh, though, and
139 // run it on a perturbed or triangle input so we don't just
140 // get quads in the output...
141
142 _mesh->add_point(Point(0, 0), 0);
143 _mesh->add_point(Point(1, 0), 1);
144 _mesh->add_point(Point(1.5, 0.5), 2);
145 _mesh->add_point(Point(1, 1), 3);
146 _mesh->add_point(Point(0, 1), 4);
147
148 std::unique_ptr<Elem> polygon = std::make_unique<C0Polygon>(5);
149 for (auto i : make_range(5))
150 polygon->set_node(i, _mesh->node_ptr(i));
151 polygon->set_id() = 0;
152
153 _mesh->add_elem(std::move(polygon));
154 _mesh->prepare_for_use();
155 }
156 else if (elem_type == C0POLYHEDRON)
157 {
158 // There's even less point in having a build_cube for general
159 // polyhedra, so again we'll hand-make one for testing and
160 // we'll plan on making a build_dual_mesh for the future.
161
162#if 0
163 // Try a truncated cube for relatively simple verification.
164
165 // We have some differing orientations on the top sides, to
166 // test handling of that.
167 // Lower octagon points, counterclockwise
168 _mesh->add_point(Point(1/Real(3), 0, 0), 0);
169 _mesh->add_point(Point(2/Real(3), 0, 0), 1);
170 _mesh->add_point(Point(1, 1/Real(3), 0), 2);
171 _mesh->add_point(Point(1, 2/Real(3), 0), 3);
172 _mesh->add_point(Point(2/Real(3), 1, 0), 4);
173 _mesh->add_point(Point(1/Real(3), 1, 0), 5);
174 _mesh->add_point(Point(0, 2/Real(3), 0), 6);
175 _mesh->add_point(Point(0, 1/Real(3), 0), 7);
176
177 // Lower-middle points, counterclockwise
178 _mesh->add_point(Point(0, 0, 1/Real(3)), 8);
179 _mesh->add_point(Point(1, 0, 1/Real(3)), 9);
180 _mesh->add_point(Point(1, 1, 1/Real(3)), 10);
181 _mesh->add_point(Point(0, 1, 1/Real(3)), 11);
182
183 // Upper-middle points, counterclockwise
184 _mesh->add_point(Point(0, 0, 2/Real(3)), 12);
185 _mesh->add_point(Point(1, 0, 2/Real(3)), 13);
186 _mesh->add_point(Point(1, 1, 2/Real(3)), 14);
187 _mesh->add_point(Point(0, 1, 2/Real(3)), 15);
188
189 // Upper octagon points, counterclockwise
190 _mesh->add_point(Point(1/Real(3), 0, 1), 16);
191 _mesh->add_point(Point(2/Real(3), 0, 1), 17);
192 _mesh->add_point(Point(1, 1/Real(3), 1), 18);
193 _mesh->add_point(Point(1, 2/Real(3), 1), 19);
194 _mesh->add_point(Point(2/Real(3), 1, 1), 20);
195 _mesh->add_point(Point(1/Real(3), 1, 1), 21);
196 _mesh->add_point(Point(0, 2/Real(3), 1), 22);
197 _mesh->add_point(Point(0, 1/Real(3), 1), 23);
198
199 const std::vector<std::vector<unsigned int>> nodes_on_side =
200 { {0, 1, 2, 3, 4, 5, 6, 7}, // min z
201 {0, 1, 9, 13, 17, 16, 12, 8}, // min y
202 {2, 3, 10, 14, 19, 18, 13, 9}, // max x
203 {4, 5, 11, 15, 21, 20, 14, 10}, // max y
204 {6, 7, 8, 12, 23, 22, 15, 11}, // min x
205 {16, 17, 18, 19, 20, 21, 22, 23}, // max z
206 {7, 0, 8}, // max nothing
207 {1, 2, 9}, // max x
208 {3, 4, 10}, // max xy
209 {5, 6, 11}, // max y
210 {23, 16, 12}, // max z
211 {17, 18, 13}, // max xz
212 {19, 20, 14}, // max xyz
213 {21, 22, 15} }; // max yz
214#endif
215
216#if 1
217 // Or try an affine-skewed box. Unlike a unit cube, its
218 // non-unit quality values cannot be confused with the generic
219 // fallback value of 1.
220 _mesh->add_point(Point(0, 0, 0), 0);
221 _mesh->add_point(Point(2, 0, 0), 1);
222 _mesh->add_point(Point(2.25, 1, 0), 2);
223 _mesh->add_point(Point(0.25, 1, 0), 3);
224 _mesh->add_point(Point(0, 0, 1), 4);
225 _mesh->add_point(Point(2, 0, 1), 5);
226 _mesh->add_point(Point(2.25, 1, 1), 6);
227 _mesh->add_point(Point(0.25, 1, 1), 7);
228
229 // With some combinations of face triangulations, even a
230 // simple box has no tetrahedralization that doesn't have
231 // either interior discontinuities or a 0-volume pancake tet!
232 //
233 // The initial "natural" way to orient our sides is commented
234 // out here; permutations that fix diagonals for us are used
235 // instead.
236 // Listing both z sides first also tests nonconsecutive local
237 // side edges in the polyhedron edge lookup.
238 const std::vector<std::vector<unsigned int>> nodes_on_side =
239 { {0, 1, 2, 3}, // min z
240 {5, 6, 7, 4}, // max z
241 {0, 1, 5, 4}, // min y
242 // {1, 2, 6, 5}, // max x - bad
243 {2, 6, 5, 1}, // max x
244 {2, 3, 7, 6}, // max y
245 // {3, 0, 4, 7}, // min x - bad
246 {0, 4, 7, 3} }; // min x
247#endif
248
249 // Build all the sides.
250 std::vector<std::shared_ptr<Polygon>> sides(nodes_on_side.size());
251
252 for (auto s : index_range(nodes_on_side))
253 {
254 const auto & nodes_on_s = nodes_on_side[s];
255 sides[s] = std::make_shared<C0Polygon>(nodes_on_s.size());
256 for (auto i : index_range(nodes_on_s))
257 sides[s]->set_node(i, _mesh->node_ptr(nodes_on_s[i]));
258 }
259
260 std::unique_ptr<libMesh::Node> mid_elem_node;
261 std::unique_ptr<Elem> polyhedron = std::make_unique<C0Polyhedron>(sides, mid_elem_node);
262 _mesh->add_elem(std::move(polyhedron));
263 if (mid_elem_node)
264 _mesh->add_node(std::move(mid_elem_node));
265 _mesh->prepare_for_use();
266 }
267 else
268 {
269 const unsigned int dim = test_elem->dim();
270 const unsigned int use_x = dim > 0;
271 const unsigned int use_y = dim > 1;
272 const unsigned int use_z = dim > 2;
273
275 N*use_x, N*use_y, N*use_z,
276 minpos, maxpos,
277 minpos, use_y*maxpos,
278 minpos, use_z*maxpos,
279 elem_type);
280 }
281
282 // Use non-default subdomain ids so we can properly test their
283 // preservation.
284 //
285 // Use long subdomain names so we can test that we're not
286 // truncating as badly as we used to in ExodusII.
287 for (const auto & elem :
288 this->_mesh->element_ptr_range())
289 {
290 const subdomain_id_type sbdid = 10 + (elem->id() % 10);
291 elem->subdomain_id() = sbdid;
292 std::ostringstream sbdname;
293 sbdname <<
294 "a_very_long_subdomain_name_for_the_subdomain_with_number_" << sbdid;
295 this->_mesh->set_subdomain_name(sbdid, sbdname.str());
296 }
297
298 // Make sure our mesh's cache knows about them all for later
299 // test comparisons
300 this->_mesh->cache_elem_data();
301
302 // We may have updated only a portion of subdomain names if we're
303 // on a distributed mesh, but every processor should know about
304 // every name.
305 this->_mesh->sync_subdomain_name_map();
306 }
unsigned int dim
std::unique_ptr< Mesh > _mesh
Definition elem_test.h:26
dof_id_type id() const
Definition dof_object.h:819
This is the base class from which all geometric element types are derived.
Definition elem.h:96
virtual Node *& set_node(const unsigned int i)
Definition elem.h:2567
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition elem.C:442
subdomain_id_type subdomain_id() const
Definition elem.h:2591
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
void build_cube(UnstructuredMesh &mesh, const unsigned int nx=0, const unsigned int ny=0, const unsigned int nz=0, const Real xmin=0., const Real xmax=1., const Real ymin=0., const Real ymax=1., const Real zmin=0., const Real zmax=1., const ElemType type=INVALID_ELEM, const bool gauss_lobatto_grid=false)
Builds a (elements) cube.
auto index_range(const T &sizable)
Helper function that returns an IntRange<std::size_t> representing all the indices of the passed-in v...
Definition int_range.h:153
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176

References PerElemTest< elem_type >::_mesh, libMesh::Elem::build(), libMesh::MeshTools::Generation::build_cube(), libMesh::C0POLYGON, libMesh::C0POLYHEDRON, dim, libMesh::index_range(), libMesh::INFHEX16, libMesh::INFHEX18, libMesh::INFHEX8, libMesh::INFPRISM12, libMesh::INFPRISM6, libMesh::INFQUAD4, libMesh::INFQUAD6, libMesh::make_range(), libMesh::Real, libMesh::Elem::set_node(), and TestCommWorld.

Member Data Documentation

◆ _mesh

template<ElemType elem_type>
std::unique_ptr<Mesh> PerElemTest< elem_type >::_mesh
protected

◆ libmesh_suite_name

template<ElemType elem_type>
std::string PerElemTest< elem_type >::libmesh_suite_name
protected

Definition at line 27 of file elem_test.h.


The documentation for this class was generated from the following file: