libMesh
Loading...
Searching...
No Matches
fe_hierarchic.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 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// Local includes
21#include "libmesh/elem.h"
22#include "libmesh/enum_to_string.h"
23#include "libmesh/fe.h"
24#include "libmesh/fe_interface.h"
25#include "libmesh/fe_macro.h"
26
27namespace libMesh
28{
29
30// ------------------------------------------------------------
31// Hierarchic-specific implementations
32
33// Anonymous namespace for local helper functions
34namespace {
35
36void hierarchic_nodal_soln(const Elem * elem,
37 const Order order,
38 const std::vector<Number> & elem_soln,
39 std::vector<Number> & nodal_soln,
40 const bool add_p_level)
41{
42 const unsigned int n_nodes = elem->n_nodes();
43
44 const ElemType elem_type = elem->type();
45
46 nodal_soln.resize(n_nodes);
47
48 const Order totalorder = order + add_p_level*elem->p_level();
49
50 // FEType object to be passed to various FEInterface functions below.
51 FEType fe_type(order, HIERARCHIC);
52
53 switch (totalorder)
54 {
55 // Constant shape functions
56 case CONSTANT:
57 {
58 libmesh_assert_equal_to (elem_soln.size(), 1);
59
60 std::fill(nodal_soln.begin(), nodal_soln.end(), elem_soln[0]);
61
62 return;
63 }
64
65
66 // For other orders do interpolation at the nodes
67 // explicitly.
68 default:
69 {
70 const unsigned int n_sf =
71 FEInterface::n_shape_functions(fe_type, elem);
72
73 std::vector<Point> refspace_nodes;
74 FEBase::get_refspace_nodes(elem_type,refspace_nodes);
75 libmesh_assert_equal_to (refspace_nodes.size(), n_nodes);
76 libmesh_assert_equal_to (elem_soln.size(), n_sf);
77
78 // Zero before summation
79 std::fill(nodal_soln.begin(), nodal_soln.end(), 0);
80
81 for (unsigned int n=0; n<n_nodes; n++)
82 // u_i = Sum (alpha_i phi_i)
83 for (unsigned int i=0; i<n_sf; i++)
84 nodal_soln[n] += elem_soln[i] *
85 FEInterface::shape(fe_type, elem, i, refspace_nodes[n]);
86
87 return;
88 }
89 }
90} // hierarchic_nodal_soln()
91
92
93
94unsigned int HIERARCHIC_n_dofs(const ElemType t, const Order o)
95{
96 libmesh_assert_greater (o, 0);
97 switch (t)
98 {
99 case NODEELEM:
100 return 1;
101 case EDGE2:
102 case EDGE3:
103 return (o+1);
104 case QUAD4:
105 case QUADSHELL4:
106 libmesh_assert_less (o, 2);
107 libmesh_fallthrough();
108 case QUAD8:
109 case QUADSHELL8:
110 case QUAD9:
111 case QUADSHELL9:
112 return ((o+1)*(o+1));
113 case HEX8:
114 case HEX20:
115 libmesh_assert_less (o, 2);
116 libmesh_fallthrough();
117 case HEX27:
118 return ((o+1)*(o+1)*(o+1));
119 case PRISM6:
120 case PRISM15:
121 libmesh_assert_less (o, 2);
122 libmesh_fallthrough();
123 case PRISM18:
124 libmesh_assert_less (o, 3);
125 libmesh_fallthrough();
126 case PRISM20:
127 case PRISM21:
128 return ((o+1)*(o+1)*(o+2)/2);
129 case TRI3:
130 libmesh_assert_less (o, 2);
131 libmesh_fallthrough();
132 case TRI6:
133 case TRI7:
134 return ((o+1)*(o+2)/2);
135 case TET4:
136 libmesh_assert_less (o, 2);
137 libmesh_fallthrough();
138 case TET10:
139 libmesh_assert_less (o, 3);
140 libmesh_fallthrough();
141 case TET14:
142 return ((o+1)*(o+2)*(o+3)/6);
143 case INVALID_ELEM:
144 return 0;
145 default:
146 libmesh_error_msg("ERROR: Invalid ElemType " << Utility::enum_to_string(t) << " selected for HIERARCHIC FE family!");
147 }
148} // HIERARCHIC_n_dofs()
149
150
151
152unsigned int HIERARCHIC_n_dofs(const Elem * e, const Order o)
153{
155 return HIERARCHIC_n_dofs(e->type(), o);
156}
157
158
159
160unsigned int HIERARCHIC_n_dofs_at_node(const ElemType t,
161 const Order o,
162 const unsigned int n)
163{
164 libmesh_assert_greater (o, 0);
165 switch (t)
166 {
167 case NODEELEM:
168 return 1;
169 case EDGE2:
170 case EDGE3:
171 switch (n)
172 {
173 case 0:
174 case 1:
175 return 1;
176 // Internal DoFs are associated with the elem, not its nodes
177 case 2:
178 libmesh_assert_equal_to(t, EDGE3);
179 return 0;
180 default:
181 libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for EDGE2/3!");
182 }
183 case TRI3:
184 libmesh_assert_less (n, 3);
185 libmesh_assert_less (o, 2);
186 libmesh_fallthrough();
187 case TRI6:
188 // Internal DoFs are associated with the elem on a Tri6, or node 6 on a Tri7
189 libmesh_assert_less (n, 6);
190 libmesh_fallthrough();
191 case TRI7:
192 switch (n)
193 {
194 case 0:
195 case 1:
196 case 2:
197 return 1;
198
199 case 3:
200 case 4:
201 case 5:
202 return (o-1);
203
204 case 6:
205 return ((o-1)*(o-2)/2);
206 default:
207 libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for TRI!");
208 }
209 case QUAD4:
210 case QUADSHELL4:
211 libmesh_assert_less (n, 4);
212 libmesh_assert_less (o, 2);
213 libmesh_fallthrough();
214 case QUAD8:
215 case QUADSHELL8:
216 case QUAD9:
217 case QUADSHELL9:
218 switch (n)
219 {
220 case 0:
221 case 1:
222 case 2:
223 case 3:
224 return 1;
225
226 case 4:
227 case 5:
228 case 6:
229 case 7:
230 return (o-1);
231
232 // Internal DoFs are associated with the elem, not its nodes
233 case 8:
234 return 0;
235
236 default:
237 libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for QUAD4/8/9!");
238 }
239 case HEX8:
240 libmesh_assert_less (n, 8);
241 libmesh_assert_less (o, 2);
242 libmesh_fallthrough();
243 case HEX20:
244 libmesh_assert_less (n, 20);
245 libmesh_assert_less (o, 2);
246 libmesh_fallthrough();
247 case HEX27:
248 switch (n)
249 {
250 case 0:
251 case 1:
252 case 2:
253 case 3:
254 case 4:
255 case 5:
256 case 6:
257 case 7:
258 return 1;
259
260 case 8:
261 case 9:
262 case 10:
263 case 11:
264 case 12:
265 case 13:
266 case 14:
267 case 15:
268 case 16:
269 case 17:
270 case 18:
271 case 19:
272 return (o-1);
273
274 case 20:
275 case 21:
276 case 22:
277 case 23:
278 case 24:
279 case 25:
280 return ((o-1)*(o-1));
281
282 // Internal DoFs are associated with the elem, not its nodes
283 case 26:
284 return 0;
285 default:
286 libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for HEX8/20/27!");
287 }
288
289 case PRISM6:
290 libmesh_assert_less (n, 6);
291 libmesh_fallthrough();
292 case PRISM15:
293 libmesh_assert_less (n, 15);
294 libmesh_assert_less (o, 2);
295 libmesh_fallthrough();
296 case PRISM18:
297 libmesh_assert_less (n, 18);
298 libmesh_assert_less (o, 3);
299 libmesh_fallthrough();
300 case PRISM20:
301 // Internal DoFs are associated with the elem on a Prism20, or
302 // node 20 on a Prism21
303 libmesh_assert_less (n, 20);
304 libmesh_fallthrough();
305 case PRISM21:
306 libmesh_assert_less (n, 21);
307 switch (n)
308 {
309 case 0:
310 case 1:
311 case 2:
312 case 3:
313 case 4:
314 case 5:
315 return 1;
316
317 case 6:
318 case 7:
319 case 8:
320 case 9:
321 case 10:
322 case 11:
323 case 12:
324 case 13:
325 case 14:
326 return (o-1);
327
328 case 15:
329 case 16:
330 case 17:
331 return ((o-1)*(o-1));
332
333 case 18:
334 case 19:
335 return ((o-1)*(o-2)/2);
336 case 20:
337 return ((o-1)*(o-1)*(o-2)/2);
338 default:
339 libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for TRI!");
340 }
341
342 case TET4:
343 libmesh_assert_less (o, 2);
344 libmesh_assert_less (n, 4);
345 libmesh_fallthrough();
346 case TET10:
347 libmesh_assert_less (o, 3);
348 libmesh_assert_less (n, 10);
349 libmesh_fallthrough();
350 case TET14:
351 libmesh_assert_less (n, 14);
352 switch (n)
353 {
354 case 0:
355 case 1:
356 case 2:
357 case 3:
358 return 1;
359
360 case 4:
361 case 5:
362 case 6:
363 case 7:
364 case 8:
365 case 9:
366 return (o-1);
367
368 case 10:
369 case 11:
370 case 12:
371 case 13:
372 return ((o-1)*(o-2)/2);
373
374 default:
375 libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for TET!");
376 }
377
378
379 case INVALID_ELEM:
380 return 0;
381
382 default:
383 libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
384 }
385} // HIERARCHIC_n_dofs_at_node()
386
387
388
389unsigned int HIERARCHIC_n_dofs_at_node(const Elem & e,
390 const Order o,
391 const unsigned int n)
392{
393 return HIERARCHIC_n_dofs_at_node(e.type(), o, n);
394}
395
396
397
398unsigned int HIERARCHIC_n_dofs_per_elem(const ElemType t,
399 const Order o)
400{
401 libmesh_assert_greater (o, 0);
402 switch (t)
403 {
404 case NODEELEM:
405 return 0;
406 case EDGE2:
407 case EDGE3:
408 return (o-1);
409 case TRI3:
410 case TRISHELL3:
411 case QUAD4:
412 case QUADSHELL4:
413 return 0;
414 case TRI6:
415 return ((o-1)*(o-2)/2);
416 case TRI7:
417 return 0;
418 case QUAD8:
419 case QUADSHELL8:
420 case QUAD9:
421 case QUADSHELL9:
422 return ((o-1)*(o-1));
423 case HEX8:
424 case HEX20:
425 libmesh_assert_less (o, 2);
426 return 0;
427 case HEX27:
428 return ((o-1)*(o-1)*(o-1));
429 case PRISM6:
430 case PRISM15:
431 libmesh_assert_less (o, 2);
432 libmesh_fallthrough();
433 case PRISM18:
434 libmesh_assert_less (o, 3);
435 return 0;
436 case PRISM20:
437 return ((o-1)*(o-1)*(o-2)/2);
438 case PRISM21: // Store interior DoFs on interior node
439 return 0;
440 case TET4:
441 libmesh_assert_less (o, 2);
442 libmesh_fallthrough();
443 case TET10:
444 libmesh_assert_less (o, 3);
445 libmesh_fallthrough();
446 case TET14:
447 return ((o-3)*(o-2)*(o-1)/6);
448 case INVALID_ELEM:
449 return 0;
450 default:
451 libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
452 }
453} // HIERARCHIC_n_dofs_per_elem()
454
455
456
457unsigned int HIERARCHIC_n_dofs_per_elem(const Elem & e,
458 const Order o)
459{
460 return HIERARCHIC_n_dofs_per_elem(e.type(), o);
461}
462
463} // anonymous namespace
464
465
466// Instantiate (side_) nodal_soln() function for every dimension
467LIBMESH_FE_NODAL_SOLN(HIERARCHIC, hierarchic_nodal_soln)
469
470
471// Instantiate n_dofs*() functions for every dimension
472LIBMESH_DEFAULT_NDOFS(HIERARCHIC)
473
474
475// Hierarchic FEMs are C^0 continuous
476template <> FEContinuity FE<0,HIERARCHIC>::get_continuity() const { return C_ZERO; }
480
481// Hierarchic FEMs are hierarchic (duh!)
482template <> bool FE<0,HIERARCHIC>::is_hierarchic() const { return true; }
483template <> bool FE<1,HIERARCHIC>::is_hierarchic() const { return true; }
484template <> bool FE<2,HIERARCHIC>::is_hierarchic() const { return true; }
485template <> bool FE<3,HIERARCHIC>::is_hierarchic() const { return true; }
486
487#ifdef LIBMESH_ENABLE_AMR
488// compute_constraints() specializations are only needed for 2 and 3D
489template <>
491 DofMap & dof_map,
492 const unsigned int variable_number,
493 const Elem * elem)
494{ compute_proj_constraints(constraints, dof_map, variable_number, elem); }
495
496template <>
498 DofMap & dof_map,
499 const unsigned int variable_number,
500 const Elem * elem)
501{ compute_proj_constraints(constraints, dof_map, variable_number, elem); }
502#endif // #ifdef LIBMESH_ENABLE_AMR
503
504// Hierarchic FEM shapes need reinit
505template <> bool FE<0,HIERARCHIC>::shapes_need_reinit() const { return true; }
506template <> bool FE<1,HIERARCHIC>::shapes_need_reinit() const { return true; }
507template <> bool FE<2,HIERARCHIC>::shapes_need_reinit() const { return true; }
508template <> bool FE<3,HIERARCHIC>::shapes_need_reinit() const { return true; }
509
510} // namespace libMesh
The constraint matrix storage format.
Definition dof_map.h:112
This class handles the numbering of degrees of freedom on a mesh.
Definition dof_map.h:181
This is the base class from which all geometric element types are derived.
Definition elem.h:96
static void get_refspace_nodes(const ElemType t, std::vector< Point > &nodes)
static Real shape(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int i, const Point &p)
static unsigned int n_shape_functions(const unsigned int dim, const FEType &fe_t, const ElemType t)
virtual bool is_hierarchic() const override
virtual FEContinuity get_continuity() const override
static void compute_constraints(DofConstraints &constraints, DofMap &dof_map, const unsigned int variable_number, const Elem *elem)
Computes the constraint matrix contributions (for non-conforming adapted meshes) corresponding to var...
virtual bool shapes_need_reinit() const override
std::string enum_to_string(const T e)
The libMesh namespace provides an interface to certain functionality in the library.
LIBMESH_FE_NODAL_SOLN(BERNSTEIN, bernstein_nodal_soln)
ElemType
Defines an enum for geometric element types.
libmesh_assert(ctx)
LIBMESH_FE_SIDE_NODAL_SOLN(HIERARCHIC_VEC)
const dof_id_type n_nodes
Definition tecplot_io.C:67