Line data Source code
1 : // The libMesh Finite Element Library.
2 : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 :
4 : // This library is free software; you can redistribute it and/or
5 : // modify it under the terms of the GNU Lesser General Public
6 : // License as published by the Free Software Foundation; either
7 : // version 2.1 of the License, or (at your option) any later version.
8 :
9 : // This library is distributed in the hope that it will be useful,
10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : // Lesser General Public License for more details.
13 :
14 : // You should have received a copy of the GNU Lesser General Public
15 : // License along with this library; if not, write to the Free Software
16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 :
18 : #include "libmesh/libmesh_config.h"
19 :
20 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
21 :
22 : // Local includes
23 : #include "libmesh/cell_inf_prism12.h"
24 : #include "libmesh/edge_edge3.h"
25 : #include "libmesh/edge_inf_edge2.h"
26 : #include "libmesh/face_tri6.h"
27 : #include "libmesh/face_inf_quad6.h"
28 : #include "libmesh/enum_io_package.h"
29 : #include "libmesh/enum_order.h"
30 :
31 : namespace libMesh
32 : {
33 :
34 :
35 : // ------------------------------------------------------------
36 : // InfPrism12 class static member initializations
37 : const int InfPrism12::num_nodes;
38 : const int InfPrism12::nodes_per_side;
39 : const int InfPrism12::nodes_per_edge;
40 :
41 : const unsigned int InfPrism12::side_nodes_map[InfPrism12::num_sides][InfPrism12::nodes_per_side] =
42 : {
43 : { 0, 1, 2, 6, 7, 8}, // Side 0
44 : { 0, 1, 3, 4, 6, 9}, // Side 1
45 : { 1, 2, 4, 5, 7, 10}, // Side 2
46 : { 2, 0, 5, 3, 8, 11} // Side 3
47 : };
48 :
49 : const unsigned int InfPrism12::edge_nodes_map[InfPrism12::num_edges][InfPrism12::nodes_per_edge] =
50 : {
51 : {0, 1, 6}, // Side 0
52 : {1, 2, 7}, // Side 1
53 : {0, 2, 8}, // Side 2
54 : {0, 3, 99}, // Side 3
55 : {1, 4, 99}, // Side 4
56 : {2, 5, 99} // Side 5
57 : };
58 :
59 : // ------------------------------------------------------------
60 : // InfPrism12 class member functions
61 :
62 402 : bool InfPrism12::is_node_on_side(const unsigned int n,
63 : const unsigned int s) const
64 : {
65 150 : libmesh_assert_less (s, n_sides());
66 150 : return std::find(std::begin(side_nodes_map[s]),
67 402 : std::end(side_nodes_map[s]),
68 402 : n) != std::end(side_nodes_map[s]);
69 : }
70 :
71 : std::vector<unsigned>
72 104 : InfPrism12::nodes_on_side(const unsigned int s) const
73 : {
74 36 : libmesh_assert_less(s, n_sides());
75 140 : return {std::begin(side_nodes_map[s]), std::end(side_nodes_map[s])};
76 : }
77 :
78 : std::vector<unsigned>
79 129 : InfPrism12::nodes_on_edge(const unsigned int e) const
80 : {
81 45 : libmesh_assert_less(e, n_edges());
82 84 : auto trim = (e < 3) ? 0 : 1;
83 129 : return {std::begin(edge_nodes_map[e]), std::end(edge_nodes_map[e]) - trim};
84 : }
85 :
86 405 : bool InfPrism12::is_node_on_edge(const unsigned int n,
87 : const unsigned int e) const
88 : {
89 159 : libmesh_assert_less (e, n_edges());
90 159 : return std::find(std::begin(edge_nodes_map[e]),
91 405 : std::end(edge_nodes_map[e]),
92 405 : n) != std::end(edge_nodes_map[e]);
93 : }
94 :
95 6818 : Order InfPrism12::default_order() const
96 : {
97 6818 : return SECOND;
98 : }
99 :
100 0 : unsigned int InfPrism12::local_side_node(unsigned int side,
101 : unsigned int side_node) const
102 : {
103 0 : libmesh_assert_less (side, this->n_sides());
104 :
105 : // Never more than 6 nodes per side.
106 0 : libmesh_assert_less(side_node, InfPrism12::nodes_per_side);
107 :
108 0 : return InfPrism12::side_nodes_map[side][side_node];
109 : }
110 :
111 :
112 :
113 360 : unsigned int InfPrism12::local_edge_node(unsigned int edge,
114 : unsigned int edge_node) const
115 : {
116 120 : libmesh_assert_less (edge, this->n_edges());
117 :
118 : // Never more than 3 nodes per edge.
119 120 : libmesh_assert_less(edge_node, InfPrism12::nodes_per_edge);
120 :
121 : // Some edges only have 2 nodes.
122 120 : libmesh_assert(edge < 3 || edge_node < 2);
123 :
124 360 : return InfPrism12::edge_nodes_map[edge][edge_node];
125 : }
126 :
127 :
128 :
129 294070 : std::unique_ptr<Elem> InfPrism12::build_side_ptr (const unsigned int i)
130 : {
131 104552 : libmesh_assert_less (i, this->n_sides());
132 :
133 294070 : std::unique_ptr<Elem> face;
134 :
135 294070 : switch (i)
136 : {
137 293663 : case 0: // the triangular face at z=-1, base face
138 : {
139 293663 : face = std::make_unique<Tri6>();
140 293663 : break;
141 : }
142 :
143 407 : case 1: // the quad face at y=0
144 : case 2: // the other quad face
145 : case 3: // the quad face at x=0
146 : {
147 407 : face = std::make_unique<InfQuad6>();
148 407 : break;
149 : }
150 :
151 0 : default:
152 0 : libmesh_error_msg("Invalid side i = " << i);
153 : }
154 :
155 : // Set the nodes
156 2058490 : for (auto n : face->node_index_range())
157 2384214 : face->set_node(n, this->node_ptr(InfPrism12::side_nodes_map[i][n]));
158 :
159 294070 : face->set_interior_parent(this);
160 190771 : face->inherit_data_from(*this);
161 :
162 294070 : return face;
163 0 : }
164 :
165 :
166 56 : void InfPrism12::build_side_ptr (std::unique_ptr<Elem> & side,
167 : const unsigned int i)
168 : {
169 20 : libmesh_assert_less (i, this->n_sides());
170 :
171 56 : switch (i)
172 : {
173 5 : case 0: // the triangular face at z=-1, base face
174 : {
175 14 : if (!side.get() || side->type() != TRI6)
176 : {
177 14 : side = this->build_side_ptr(i);
178 11 : return;
179 : }
180 1 : break;
181 : }
182 :
183 15 : case 1: // the quad face at y=0
184 : case 2: // the other quad face
185 : case 3: // the quad face at x=0
186 : {
187 42 : if (!side.get() || side->type() != INFQUAD6)
188 : {
189 14 : side = this->build_side_ptr(i);
190 11 : return;
191 : }
192 11 : break;
193 : }
194 :
195 0 : default:
196 0 : libmesh_error_msg("Invalid side i = " << i);
197 : }
198 :
199 22 : side->inherit_data_from(*this);
200 :
201 : // Set the nodes
202 238 : for (auto n : side->node_index_range())
203 276 : side->set_node(n, this->node_ptr(InfPrism12::side_nodes_map[i][n]));
204 : }
205 :
206 :
207 :
208 2028 : std::unique_ptr<Elem> InfPrism12::build_edge_ptr (const unsigned int i)
209 : {
210 2028 : if (i < 3) // base edges
211 945 : return this->simple_build_edge_ptr<Edge3,InfPrism12>(i);
212 :
213 : // infinite edges
214 1083 : return this->simple_build_edge_ptr<InfEdge2,InfPrism12>(i);
215 : }
216 :
217 :
218 :
219 0 : void InfPrism12::build_edge_ptr (std::unique_ptr<Elem> & edge,
220 : const unsigned int i)
221 : {
222 0 : libmesh_assert_less (i, this->n_edges());
223 :
224 0 : switch (i)
225 : {
226 : // the base edges
227 0 : case 0:
228 : case 1:
229 : case 2:
230 : {
231 0 : if (!edge.get() || edge->type() != EDGE3)
232 : {
233 0 : edge = this->build_edge_ptr(i);
234 0 : return;
235 : }
236 0 : break;
237 : }
238 :
239 : // the infinite edges
240 0 : case 3:
241 : case 4:
242 : case 5:
243 : {
244 0 : if (!edge.get() || edge->type() != INFEDGE2)
245 : {
246 0 : edge = this->build_edge_ptr(i);
247 0 : return;
248 : }
249 0 : break;
250 : }
251 :
252 0 : default:
253 0 : libmesh_error_msg("Invalid edge i = " << i);
254 : }
255 :
256 0 : edge->inherit_data_from(*this);
257 :
258 : // Set the nodes
259 0 : for (auto n : edge->node_index_range())
260 0 : edge->set_node(n, this->node_ptr(InfPrism12::edge_nodes_map[i][n]));
261 : }
262 :
263 :
264 :
265 0 : void InfPrism12::connectivity(const unsigned int sc,
266 : const IOPackage iop,
267 : std::vector<dof_id_type> & conn) const
268 : {
269 0 : libmesh_assert(_nodes);
270 0 : libmesh_assert_less (sc, this->n_sub_elem());
271 0 : libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
272 :
273 0 : switch (iop)
274 : {
275 0 : case TECPLOT:
276 : {
277 0 : conn.resize(8);
278 0 : switch (sc)
279 : {
280 0 : case 0:
281 :
282 : // guess this is a collapsed hex8
283 0 : conn[0] = this->node_id(0)+1;
284 0 : conn[1] = this->node_id(6)+1;
285 0 : conn[2] = this->node_id(8)+1;
286 0 : conn[3] = this->node_id(8)+1;
287 0 : conn[4] = this->node_id(3)+1;
288 0 : conn[5] = this->node_id(9)+1;
289 0 : conn[6] = this->node_id(11)+1;
290 0 : conn[7] = this->node_id(11)+1;
291 :
292 0 : return;
293 :
294 0 : case 1:
295 :
296 0 : conn[0] = this->node_id(6)+1;
297 0 : conn[1] = this->node_id(7)+1;
298 0 : conn[2] = this->node_id(8)+1;
299 0 : conn[3] = this->node_id(8)+1;
300 0 : conn[4] = this->node_id(9)+1;
301 0 : conn[5] = this->node_id(10)+1;
302 0 : conn[6] = this->node_id(11)+1;
303 0 : conn[7] = this->node_id(11)+1;
304 :
305 0 : return;
306 :
307 0 : case 2:
308 :
309 0 : conn[0] = this->node_id(6)+1;
310 0 : conn[1] = this->node_id(1)+1;
311 0 : conn[2] = this->node_id(7)+1;
312 0 : conn[3] = this->node_id(7)+1;
313 0 : conn[4] = this->node_id(9)+1;
314 0 : conn[5] = this->node_id(4)+1;
315 0 : conn[6] = this->node_id(10)+1;
316 0 : conn[7] = this->node_id(10)+1;
317 :
318 0 : return;
319 :
320 0 : case 3:
321 :
322 0 : conn[0] = this->node_id(8)+1;
323 0 : conn[1] = this->node_id(7)+1;
324 0 : conn[2] = this->node_id(2)+1;
325 0 : conn[3] = this->node_id(2)+1;
326 0 : conn[4] = this->node_id(11)+1;
327 0 : conn[5] = this->node_id(10)+1;
328 0 : conn[6] = this->node_id(5)+1;
329 0 : conn[7] = this->node_id(5)+1;
330 :
331 0 : return;
332 :
333 0 : default:
334 0 : libmesh_error_msg("Invalid sc = " << sc);
335 : }
336 : }
337 :
338 0 : default:
339 0 : libmesh_error_msg("Unsupported IO package " << iop);
340 : }
341 : }
342 :
343 :
344 :
345 :
346 :
347 0 : unsigned short int InfPrism12::second_order_adjacent_vertex (const unsigned int n,
348 : const unsigned int v) const
349 : {
350 0 : libmesh_assert_greater_equal (n, this->n_vertices());
351 0 : libmesh_assert_less (n, this->n_nodes());
352 0 : libmesh_assert_less (v, 2);
353 0 : return _second_order_adjacent_vertices[n-this->n_vertices()][v];
354 : }
355 :
356 :
357 :
358 : const unsigned short int InfPrism12::_second_order_adjacent_vertices[InfPrism12::num_edges][2] =
359 : {
360 : { 0, 1}, // vertices adjacent to node 6
361 : { 1, 2}, // vertices adjacent to node 7
362 : { 0, 2}, // vertices adjacent to node 8
363 :
364 : { 3, 4}, // vertices adjacent to node 9
365 : { 4, 5}, // vertices adjacent to node 10
366 : { 3, 5} // vertices adjacent to node 11
367 : };
368 :
369 :
370 :
371 : std::pair<unsigned short int, unsigned short int>
372 0 : InfPrism12::second_order_child_vertex (const unsigned int n) const
373 : {
374 0 : libmesh_assert_greater_equal (n, this->n_vertices());
375 0 : libmesh_assert_less (n, this->n_nodes());
376 :
377 0 : return std::pair<unsigned short int, unsigned short int>
378 0 : (_second_order_vertex_child_number[n],
379 0 : _second_order_vertex_child_index[n]);
380 : }
381 :
382 :
383 :
384 : const unsigned short int InfPrism12::_second_order_vertex_child_number[InfPrism12::num_nodes] =
385 : {
386 : 99,99,99,99,99,99, // Vertices
387 : 0,1,0, // Edges
388 : 0,1,0 // Faces
389 : };
390 :
391 :
392 :
393 : const unsigned short int InfPrism12::_second_order_vertex_child_index[InfPrism12::num_nodes] =
394 : {
395 : 99,99,99,99,99,99, // Vertices
396 : 1,2,2, // Edges
397 : 4,5,5 // Faces
398 : };
399 :
400 :
401 :
402 : #ifdef LIBMESH_ENABLE_AMR
403 :
404 : const Real InfPrism12::_embedding_matrix[InfPrism12::num_children][InfPrism12::num_nodes][InfPrism12::num_nodes] =
405 : {
406 : // embedding matrix for child 0
407 : {
408 : // 0 1 2 3 4 5 6 7 8 9 10 11 th parent Node
409 : { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 0th child N.
410 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 1
411 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, // 2
412 : { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 3
413 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, // 4
414 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0}, // 5
415 : { 0.375, -0.125, 0.0, 0.0, 0.0, 0.0, 0.75, 0.0, 0.0, 0.0, 0.0, 0.0}, // 6
416 : { 0.0, -0.125, -0.125, 0.0, 0.0, 0.0, 0.5, 0.25, 0.5, 0.0, 0.0, 0.0}, // 7
417 : { 0.375, 0.0, -0.125, 0.0, 0.0, 0.0, 0.0, 0.0, 0.75, 0.0, 0.0, 0.0}, // 8
418 : { 0.0, 0.0, 0.0, 0.375, -0.125, 0.0, 0.0, 0.0, 0.0, 0.75, 0.0, 0.0}, // 9
419 : { 0.0, 0.0, 0.0, 0.0, -0.125, -0.125, 0.0, 0.0, 0.0, 0.5, 0.25, 0.5}, // 10
420 : { 0.0, 0.0, 0.0, 0.375, 0.0, -0.125, 0.0, 0.0, 0.0, 0.0, 0.0, 0.75} // 11
421 : },
422 :
423 : // embedding matrix for child 1
424 : {
425 : // 0 1 2 3 4 5 6 7 8 9 10 11 th parent Node
426 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 0th child N.
427 : { 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 1
428 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, // 2
429 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, // 3
430 : { 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 4
431 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, // 5
432 : { -0.125, 0.375, 0.0, 0.0, 0.0, 0.0, 0.75, 0.0, 0.0, 0.0, 0.0, 0.0}, // 6
433 : { 0.0, 0.375, -0.125, 0.0, 0.0, 0.0, 0.0, 0.75, 0.0, 0.0, 0.0, 0.0}, // 7
434 : { -0.125, 0.0, -0.125, 0.0, 0.0, 0.0, 0.5, 0.5, 0.25, 0.0, 0.0, 0.0}, // 8
435 : { 0.0, 0.0, 0.0, -0.125, 0.375, 0.0, 0.0, 0.0, 0.0, 0.75, 0.0, 0.0}, // 9
436 : { 0.0, 0.0, 0.0, 0.0, 0.375, -0.125, 0.0, 0.0, 0.0, 0.0, 0.75, 0.0}, // 10
437 : { 0.0, 0.0, 0.0, -0.125, 0.0, -0.125, 0.0, 0.0, 0.0, 0.5, 0.5, 0.25} // 11
438 : },
439 :
440 : // embedding matrix for child 2
441 : {
442 : // 0 1 2 3 4 5 6 7 8 9 10 11 th parent Node
443 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, // 0th child N.
444 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, // 1
445 : { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 2
446 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0}, // 3
447 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, // 4
448 : { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 5
449 : { -0.125, -0.125, 0.0, 0.0, 0.0, 0.0, 0.25, 0.5, 0.5, 0.0, 0.0, 0.0}, // 6
450 : { 0.0, -0.125, 0.375, 0.0, 0.0, 0.0, 0.0, 0.75, 0.0, 0.0, 0.0, 0.0}, // 7
451 : { -0.125, 0.0, 0.375, 0.0, 0.0, 0.0, 0.0, 0.0, 0.75, 0.0, 0.0, 0.0}, // 8
452 : { 0.0, 0.0, 0.0, -0.125, -0.125, 0.0, 0.0, 0.0, 0.0, 0.25, 0.5, 0.5}, // 9
453 : { 0.0, 0.0, 0.0, 0.0, -0.125, 0.375, 0.0, 0.0, 0.0, 0.0, 0.75, 0.0}, // 10
454 : { 0.0, 0.0, 0.0, -0.125, 0.0, 0.375, 0.0, 0.0, 0.0, 0.0, 0.0, 0.75} // 11
455 : },
456 :
457 : // embedding matrix for child 3
458 : {
459 : // 0 1 2 3 4 5 6 7 8 9 10 11 th parent Node
460 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 0th child N.
461 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, // 1
462 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, // 2
463 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, // 3
464 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, // 4
465 : { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0}, // 5
466 : { -0.125, 0.0, -0.125, 0.0, 0.0, 0.0, 0.5, 0.5, 0.25, 0.0, 0.0, 0.0}, // 6
467 : { -0.125, -0.125, 0.0, 0.0, 0.0, 0.0, 0.25, 0.5, 0.5, 0.0, 0.0, 0.0}, // 7
468 : { 0.0, -0.125, -0.125, 0.0, 0.0, 0.0, 0.5, 0.25, 0.5, 0.0, 0.0, 0.0}, // 8
469 : { 0.0, 0.0, 0.0, -0.125, 0.0, -0.125, 0.0, 0.0, 0.0, 0.5, 0.5, 0.25}, // 9
470 : { 0.0, 0.0, 0.0, -0.125, -0.125, 0.0, 0.0, 0.0, 0.0, 0.25, 0.5, 0.5}, // 10
471 : { 0.0, 0.0, 0.0, 0.0, -0.125, -0.125, 0.0, 0.0, 0.0, 0.5, 0.25, 0.5} // 11
472 : }
473 :
474 : };
475 :
476 :
477 : #endif
478 :
479 :
480 : void
481 0 : InfPrism12::permute(unsigned int perm_num)
482 : {
483 0 : libmesh_assert_less (perm_num, 3);
484 :
485 0 : for (unsigned int i = 0; i != perm_num; ++i)
486 : {
487 0 : swap3nodes(0,1,2);
488 0 : swap3nodes(3,4,5);
489 0 : swap3nodes(6,7,8);
490 0 : swap3nodes(9,10,11);
491 0 : swap3neighbors(1,2,3);
492 : }
493 0 : }
494 :
495 :
496 : void
497 0 : InfPrism12::flip(BoundaryInfo * boundary_info)
498 : {
499 0 : libmesh_assert(boundary_info);
500 :
501 0 : swap2nodes(0,1);
502 0 : swap2nodes(3,4);
503 0 : swap2nodes(7,8);
504 0 : swap2nodes(10,11);
505 0 : swap2neighbors(2,3);
506 0 : swap2boundarysides(2,3,boundary_info);
507 0 : swap2boundaryedges(3,4,boundary_info);
508 0 : }
509 :
510 :
511 : ElemType
512 36 : InfPrism12::side_type (const unsigned int s) const
513 : {
514 12 : libmesh_assert_less (s, 4);
515 36 : if (s == 0)
516 9 : return TRI6;
517 9 : return INFQUAD6;
518 : }
519 :
520 :
521 : } // namespace libMesh
522 :
523 : #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
|