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