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 : // Local includes
19 : #include "libmesh/libmesh_config.h"
20 :
21 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
22 :
23 : // Local includes cont'd
24 : #include "libmesh/cell_inf_prism6.h"
25 : #include "libmesh/edge_edge2.h"
26 : #include "libmesh/edge_inf_edge2.h"
27 : #include "libmesh/fe_interface.h"
28 : #include "libmesh/face_inf_quad4.h"
29 : #include "libmesh/face_tri3.h"
30 : #include "libmesh/enum_io_package.h"
31 : #include "libmesh/enum_order.h"
32 :
33 : namespace libMesh
34 : {
35 :
36 :
37 : // ------------------------------------------------------------
38 : // InfPrism6 class static member initializations
39 : const int InfPrism6::num_nodes;
40 : const int InfPrism6::nodes_per_side;
41 : const int InfPrism6::nodes_per_edge;
42 :
43 : const unsigned int InfPrism6::side_nodes_map[InfPrism6::num_sides][InfPrism6::nodes_per_side] =
44 : {
45 : { 0, 1, 2, 99}, // Side 0
46 : { 0, 1, 3, 4}, // Side 1
47 : { 1, 2, 4, 5}, // Side 2
48 : { 2, 0, 5, 3} // Side 3
49 : };
50 :
51 : const unsigned int InfPrism6::edge_nodes_map[InfPrism6::num_edges][InfPrism6::nodes_per_edge] =
52 : {
53 : {0, 1}, // Edge 0
54 : {1, 2}, // Edge 1
55 : {0, 2}, // Edge 2
56 : {0, 3}, // Edge 3
57 : {1, 4}, // Edge 4
58 : {2, 5} // Edge 5
59 : };
60 :
61 : // ------------------------------------------------------------
62 : // InfPrism6 class member functions
63 :
64 237 : bool InfPrism6::is_node_on_side(const unsigned int n,
65 : const unsigned int s) const
66 : {
67 87 : libmesh_assert_less (s, n_sides());
68 87 : return std::find(std::begin(side_nodes_map[s]),
69 237 : std::end(side_nodes_map[s]),
70 237 : n) != std::end(side_nodes_map[s]);
71 : }
72 :
73 : std::vector<unsigned>
74 104 : InfPrism6::nodes_on_side(const unsigned int s) const
75 : {
76 36 : libmesh_assert_less(s, n_sides());
77 104 : auto trim = (s > 0) ? 0 : 1;
78 104 : return {std::begin(side_nodes_map[s]), std::end(side_nodes_map[s]) - trim};
79 : }
80 :
81 : std::vector<unsigned>
82 120 : InfPrism6::nodes_on_edge(const unsigned int e) const
83 : {
84 42 : libmesh_assert_less(e, n_edges());
85 162 : return {std::begin(edge_nodes_map[e]), std::end(edge_nodes_map[e])};
86 : }
87 :
88 216 : bool InfPrism6::is_node_on_edge(const unsigned int n,
89 : const unsigned int e) const
90 : {
91 84 : libmesh_assert_less (e, n_edges());
92 84 : return std::find(std::begin(edge_nodes_map[e]),
93 216 : std::end(edge_nodes_map[e]),
94 216 : n) != std::end(edge_nodes_map[e]);
95 : }
96 :
97 :
98 :
99 578 : Order InfPrism6::default_order() const
100 : {
101 578 : return FIRST;
102 : }
103 :
104 :
105 :
106 628 : std::unique_ptr<Elem> InfPrism6::build_side_ptr (const unsigned int i)
107 : {
108 248 : libmesh_assert_less (i, this->n_sides());
109 :
110 628 : std::unique_ptr<Elem> face;
111 :
112 628 : switch (i)
113 : {
114 232 : case 0: // the triangular face at z=-1, base face
115 : {
116 232 : face = std::make_unique<Tri3>();
117 232 : break;
118 : }
119 :
120 396 : case 1: // the quad face at y=0
121 : case 2: // the other quad face
122 : case 3: // the quad face at x=0
123 : {
124 396 : face = std::make_unique<InfQuad4>();
125 396 : break;
126 : }
127 :
128 0 : default:
129 0 : libmesh_error_msg("Invalid side i = " << i);
130 : }
131 :
132 : // Set the nodes
133 2908 : for (auto n : face->node_index_range())
134 3180 : face->set_node(n, this->node_ptr(InfPrism6::side_nodes_map[i][n]));
135 :
136 628 : face->set_interior_parent(this);
137 380 : face->inherit_data_from(*this);
138 :
139 628 : return face;
140 0 : }
141 :
142 :
143 56 : void InfPrism6::build_side_ptr (std::unique_ptr<Elem> & side,
144 : const unsigned int i)
145 : {
146 56 : this->side_ptr(side, i);
147 56 : side->set_interior_parent(this);
148 36 : side->inherit_data_from(*this);
149 56 : }
150 :
151 :
152 2028 : std::unique_ptr<Elem> InfPrism6::build_edge_ptr (const unsigned int i)
153 : {
154 2028 : if (i < 3)
155 945 : return this->simple_build_edge_ptr<Edge2,InfPrism6>(i);
156 :
157 : // infinite edges
158 1083 : return this->simple_build_edge_ptr<InfEdge2,InfPrism6>(i);
159 : }
160 :
161 :
162 :
163 0 : void InfPrism6::build_edge_ptr (std::unique_ptr<Elem> & edge,
164 : const unsigned int i)
165 : {
166 0 : libmesh_assert_less (i, this->n_edges());
167 :
168 0 : switch (i)
169 : {
170 : // the base edges
171 0 : case 0:
172 : case 1:
173 : case 2:
174 : {
175 0 : if (!edge.get() || edge->type() != EDGE2)
176 : {
177 0 : edge = this->build_edge_ptr(i);
178 0 : return;
179 : }
180 0 : break;
181 : }
182 :
183 : // the infinite edges
184 0 : case 3:
185 : case 4:
186 : case 5:
187 : {
188 0 : if (!edge.get() || edge->type() != INFEDGE2)
189 : {
190 0 : edge = this->build_edge_ptr(i);
191 0 : return;
192 : }
193 0 : break;
194 : }
195 :
196 0 : default:
197 0 : libmesh_error_msg("Invalid edge i = " << i);
198 : }
199 :
200 0 : edge->inherit_data_from(*this);
201 :
202 : // Set the nodes
203 0 : for (auto n : edge->node_index_range())
204 0 : edge->set_node(n, this->node_ptr(InfPrism6::edge_nodes_map[i][n]));
205 : }
206 :
207 :
208 :
209 0 : void InfPrism6::connectivity(const unsigned int libmesh_dbg_var(sc),
210 : const IOPackage iop,
211 : std::vector<dof_id_type> & conn) const
212 : {
213 0 : libmesh_assert(_nodes);
214 0 : libmesh_assert_less (sc, this->n_sub_elem());
215 0 : libmesh_assert_not_equal_to (iop, INVALID_IO_PACKAGE);
216 :
217 0 : switch (iop)
218 : {
219 0 : case TECPLOT:
220 : {
221 0 : conn.resize(8);
222 0 : conn[0] = this->node_id(0)+1;
223 0 : conn[1] = this->node_id(1)+1;
224 0 : conn[2] = this->node_id(2)+1;
225 0 : conn[3] = this->node_id(2)+1;
226 0 : conn[4] = this->node_id(3)+1;
227 0 : conn[5] = this->node_id(4)+1;
228 0 : conn[6] = this->node_id(5)+1;
229 0 : conn[7] = this->node_id(5)+1;
230 0 : return;
231 : }
232 :
233 0 : default:
234 0 : libmesh_error_msg("Unsupported IO package " << iop);
235 : }
236 : }
237 :
238 :
239 :
240 :
241 :
242 : #ifdef LIBMESH_ENABLE_AMR
243 :
244 : const Real InfPrism6::_embedding_matrix[InfPrism6::num_children][InfPrism6::num_nodes][InfPrism6::num_nodes] =
245 : {
246 : // embedding matrix for child 0
247 : {
248 : // 0 1 2 3 4 5 th parent Node
249 : { 1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, // 0th child N.
250 : { 0.5, 0.5, 0.0, 0.0, 0.0, 0.0}, // 1
251 : { 0.5, 0.0, 0.5, 0.0, 0.0, 0.0}, // 2
252 : { 0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, // 3
253 : { 0.0, 0.0, 0.0, 0.5, 0.5, 0.0}, // 4
254 : { 0.0, 0.0, 0.0, 0.5, 0.0, 0.5} // 5
255 : },
256 :
257 : // embedding matrix for child 1
258 : {
259 : // 0 1 2 3 4 5 th parent Node
260 : { 0.5, 0.5, 0.0, 0.0, 0.0, 0.0}, // 0th child N.
261 : { 0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, // 1
262 : { 0.0, 0.5, 0.5, 0.0, 0.0, 0.0}, // 2
263 : { 0.0, 0.0, 0.0, 0.5, 0.5, 0.0}, // 3
264 : { 0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, // 4
265 : { 0.0, 0.0, 0.0, 0.0, 0.5, 0.5} // 5
266 : },
267 :
268 : // embedding matrix for child 2
269 : {
270 : // 0 1 2 3 4 5 th parent Node
271 : { 0.5, 0.0, 0.5, 0.0, 0.0, 0.0}, // 0th child N.
272 : { 0.0, 0.5, 0.5, 0.0, 0.0, 0.0}, // 1
273 : { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, // 2
274 : { 0.0, 0.0, 0.0, 0.5, 0.0, 0.5}, // 3
275 : { 0.0, 0.0, 0.0, 0.0, 0.5, 0.5}, // 4
276 : { 0.0, 0.0, 0.0, 0.0, 0.0, 1.0} // 5
277 : },
278 :
279 : // embedding matrix for child 3
280 : {
281 : // 0 1 2 3 4 5 th parent Node
282 : { 0.5, 0.5, 0.0, 0.0, 0.0, 0.0}, // 0th child N.
283 : { 0.0, 0.5, 0.5, 0.0, 0.0, 0.0}, // 1
284 : { 0.5, 0.0, 0.5, 0.0, 0.0, 0.0}, // 2
285 : { 0.0, 0.0, 0.0, 0.5, 0.5, 0.0}, // 3
286 : { 0.0, 0.0, 0.0, 0.0, 0.5, 0.5}, // 4
287 : { 0.0, 0.0, 0.0, 0.5, 0.0, 0.5} // 5
288 : }
289 : };
290 :
291 :
292 : #endif
293 :
294 :
295 : void
296 0 : InfPrism6::permute(unsigned int perm_num)
297 : {
298 0 : libmesh_assert_less (perm_num, 3);
299 :
300 0 : for (unsigned int i = 0; i != perm_num; ++i)
301 : {
302 0 : swap3nodes(0,1,2);
303 0 : swap3nodes(3,4,5);
304 0 : swap3neighbors(1,2,3);
305 : }
306 0 : }
307 :
308 :
309 : void
310 0 : InfPrism6::flip(BoundaryInfo * boundary_info)
311 : {
312 0 : libmesh_assert(boundary_info);
313 :
314 0 : swap2nodes(0,1);
315 0 : swap2nodes(3,4);
316 0 : swap2nodes(7,8);
317 0 : swap2neighbors(2,3);
318 0 : swap2boundarysides(2,3,boundary_info);
319 0 : swap2boundaryedges(3,4,boundary_info);
320 0 : }
321 :
322 :
323 : ElemType
324 36 : InfPrism6::side_type (const unsigned int s) const
325 : {
326 12 : libmesh_assert_less (s, 4);
327 36 : if (s == 0)
328 9 : return TRI3;
329 9 : return INFQUAD4;
330 : }
331 :
332 : } // namespace libMesh
333 :
334 : #endif // ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
|