Line data Source code
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/fe_interface.h"
22 : #include "libmesh/fe_lagrange_gll_shape_1D.h"
23 :
24 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
25 : #include "libmesh/fe_interface_macros.h"
26 : #include "libmesh/inf_fe.h"
27 : #endif
28 :
29 : #include "libmesh/elem.h"
30 : #include "libmesh/fe.h"
31 : #include "libmesh/fe_compute_data.h"
32 : #include "libmesh/dof_map.h"
33 : #include "libmesh/enum_fe_family.h"
34 : #include "libmesh/enum_order.h"
35 : #include "libmesh/enum_elem_type.h"
36 : #include "libmesh/enum_to_string.h"
37 :
38 : namespace libMesh
39 : {
40 :
41 : //------------------------------------------------------------
42 : //FEInterface class members
43 0 : FEInterface::FEInterface()
44 : {
45 0 : libmesh_error_msg("ERROR: Do not define an object of this type.");
46 : }
47 :
48 :
49 :
50 : #ifndef LIBMESH_ENABLE_INFINITE_ELEMENTS
51 :
52 : bool
53 0 : FEInterface::is_InfFE_elem(const ElemType)
54 : {
55 0 : return false;
56 : }
57 :
58 : #else
59 :
60 : bool
61 1166008072 : FEInterface::is_InfFE_elem(const ElemType et)
62 : {
63 :
64 1166008072 : switch (et)
65 : {
66 184371 : case INFEDGE2:
67 : case INFQUAD4:
68 : case INFQUAD6:
69 : case INFHEX8:
70 : case INFHEX16:
71 : case INFHEX18:
72 : case INFPRISM6:
73 : case INFPRISM12:
74 184371 : return true;
75 :
76 1165500961 : default:
77 1165500961 : return false;
78 : }
79 : }
80 :
81 : #endif //ifndef LIBMESH_ENABLE_INFINITE_ELEMENTS
82 :
83 : #define fe_family_case_func(family, dim, func_and_args, prefix, suffix) \
84 : case family: \
85 : prefix FE<dim,family>::func_and_args suffix \
86 :
87 : #define fe_family_case(family) \
88 : case family:
89 :
90 : #define fe_family_scalar_case_func(dim, func_and_args, prefix, suffix) \
91 : fe_family_case_func(CLOUGH, dim, func_and_args, prefix, suffix) \
92 : fe_family_case_func(HERMITE, dim, func_and_args, prefix, suffix) \
93 : fe_family_case_func(HIERARCHIC, dim, func_and_args, prefix, suffix) \
94 : fe_family_case_func(L2_HIERARCHIC, dim, func_and_args, prefix, suffix) \
95 : fe_family_case_func(SIDE_HIERARCHIC, dim, func_and_args, prefix, suffix) \
96 : fe_family_case_func(LAGRANGE, dim, func_and_args, prefix, suffix) \
97 : fe_family_case_func(L2_LAGRANGE, dim, func_and_args, prefix, suffix) \
98 : fe_family_case_func(L2_LAGRANGE_GLL, dim, func_and_args, prefix, suffix) \
99 : fe_family_case_func(MONOMIAL, dim, func_and_args, prefix, suffix) \
100 : fe_family_case_func(SCALAR, dim, func_and_args, prefix, suffix) \
101 : fe_family_case_func(XYZ, dim, func_and_args, prefix, suffix) \
102 : fe_family_case_func(SUBDIVISION, 2, func_and_args, \
103 : libmesh_assert_equal_to (dim, 2); prefix, suffix)
104 :
105 : #define fe_family_scalar_case() \
106 : fe_family_case(CLOUGH) \
107 : fe_family_case(HERMITE) \
108 : fe_family_case(HIERARCHIC) \
109 : fe_family_case(L2_HIERARCHIC) \
110 : fe_family_case(SIDE_HIERARCHIC) \
111 : fe_family_case(LAGRANGE) \
112 : fe_family_case(L2_LAGRANGE) \
113 : fe_family_case(L2_LAGRANGE_GLL) \
114 : fe_family_case(MONOMIAL) \
115 : fe_family_case(SCALAR) \
116 : fe_family_case(XYZ) \
117 : fe_family_case(SUBDIVISION) \
118 :
119 : #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
120 :
121 : #define fe_family_horder_case_func(dim, func_and_args, prefix, suffix) \
122 : fe_family_case_func(BERNSTEIN, dim, func_and_args, prefix, suffix) \
123 : fe_family_case_func(SZABAB, dim, func_and_args, prefix, suffix) \
124 : fe_family_case_func(RATIONAL_BERNSTEIN, dim, func_and_args, prefix, suffix) \
125 :
126 : #define fe_family_horder_case() \
127 : fe_family_case(BERNSTEIN) \
128 : fe_family_case(SZABAB) \
129 : fe_family_case(RATIONAL_BERNSTEIN) \
130 :
131 : #else
132 :
133 : #define fe_family_horder_case_func(dim, func_and_args, prefix, suffix)
134 : #define fe_family_horder_case()
135 :
136 : #endif
137 :
138 : #define fe_family_vector_case_func(dim, func_and_args, prefix, suffix) \
139 : fe_family_case_func(HIERARCHIC_VEC, dim, func_and_args, prefix, suffix) \
140 : fe_family_case_func(L2_HIERARCHIC_VEC, dim, func_and_args, prefix, suffix) \
141 : fe_family_case_func(LAGRANGE_VEC, dim, func_and_args, prefix, suffix) \
142 : fe_family_case_func(L2_LAGRANGE_VEC, dim, func_and_args, prefix, suffix) \
143 : fe_family_case_func(MONOMIAL_VEC, dim, func_and_args, prefix, suffix) \
144 : fe_family_case_func(NEDELEC_ONE, dim, func_and_args, prefix, suffix) \
145 : fe_family_case_func(RAVIART_THOMAS, dim, func_and_args, prefix, suffix) \
146 : fe_family_case_func(L2_RAVIART_THOMAS, dim, func_and_args, prefix, suffix) \
147 :
148 : #define fe_family_vector_case() \
149 : fe_family_case(HIERARCHIC_VEC) \
150 : fe_family_case(L2_HIERARCHIC_VEC) \
151 : fe_family_case(LAGRANGE_VEC) \
152 : fe_family_case(L2_LAGRANGE_VEC) \
153 : fe_family_case(MONOMIAL_VEC) \
154 : fe_family_case(NEDELEC_ONE) \
155 : fe_family_case(RAVIART_THOMAS) \
156 : fe_family_case(L2_RAVIART_THOMAS) \
157 :
158 : #define fe_family_switch(dim, func_and_args, prefix, suffix) \
159 : do { \
160 : switch (fe_t.family) \
161 : { \
162 : fe_family_scalar_case_func(dim, func_and_args, prefix, suffix) \
163 : fe_family_horder_case_func(dim, func_and_args, prefix, suffix) \
164 : default: \
165 : libmesh_error_msg("Unsupported family = " << Utility::enum_to_string(fe_t.family)); \
166 : } \
167 : } while (0)
168 :
169 : #define fe_family_with_vec_switch(dim, func_and_args, prefix, suffix) \
170 : do { \
171 : switch (fe_t.family) \
172 : { \
173 : fe_family_scalar_case_func(dim, func_and_args, prefix, suffix) \
174 : fe_family_horder_case_func(dim, func_and_args, prefix, suffix) \
175 : fe_family_vector_case_func(dim, func_and_args, prefix, suffix) \
176 : default: \
177 : libmesh_error_msg("Unsupported family = " << Utility::enum_to_string(fe_t.family)); \
178 : } \
179 : } while (0)
180 :
181 : #define fe_scalar_vec_error_switch(dim, func_and_args, prefix, suffix) \
182 : do { \
183 : switch (fe_t.family) \
184 : { \
185 : fe_family_scalar_case_func(dim, func_and_args, prefix, suffix) \
186 : fe_family_horder_case_func(dim, func_and_args, prefix, suffix) \
187 : fe_family_vector_case() \
188 : libmesh_error_msg("Error: Can only request scalar valued elements for Real FEInterface::func_and_args"); \
189 : default: \
190 : libmesh_error_msg("Unsupported family = " << Utility::enum_to_string(fe_t.family)); \
191 : } \
192 : } while (0)
193 :
194 :
195 : #define fe_vector_scalar_error_switch(dim, func_and_args, prefix, suffix) \
196 : do { \
197 : switch (fe_t.family) \
198 : { \
199 : fe_family_vector_case_func(dim, func_and_args, prefix, suffix) \
200 : fe_family_scalar_case() \
201 : fe_family_horder_case() \
202 : libmesh_error_msg("Error: Can only request vector valued elements for RealGradient FEInterface::func_and_args"); \
203 : default: \
204 : libmesh_error_msg("Unsupported family = " << Utility::enum_to_string(fe_t.family)); \
205 : } \
206 : } while (0)
207 :
208 :
209 : #define fe_switch(func_and_args) \
210 : do { \
211 : switch (dim) \
212 : { \
213 : /* 0D */ \
214 : case 0: \
215 : fe_family_switch (0, func_and_args, return, ;); \
216 : /* 1D */ \
217 : case 1: \
218 : fe_family_switch (1, func_and_args, return, ;); \
219 : /* 2D */ \
220 : case 2: \
221 : fe_family_switch (2, func_and_args, return, ;); \
222 : /* 3D */ \
223 : case 3: \
224 : fe_family_switch (3, func_and_args, return, ;); \
225 : default: \
226 : libmesh_error_msg("Invalid dim = " << dim); \
227 : } \
228 : } while (0)
229 :
230 : #define fe_with_vec_switch(func_and_args) \
231 : do { \
232 : switch (dim) \
233 : { \
234 : /* 0D */ \
235 : case 0: \
236 : fe_family_with_vec_switch (0, func_and_args, return, ;); \
237 : /* 1D */ \
238 : case 1: \
239 : fe_family_with_vec_switch (1, func_and_args, return, ;); \
240 : /* 2D */ \
241 : case 2: \
242 : fe_family_with_vec_switch (2, func_and_args, return, ;); \
243 : /* 3D */ \
244 : case 3: \
245 : fe_family_with_vec_switch (3, func_and_args, return, ;); \
246 : default: \
247 : libmesh_error_msg("Invalid dim = " << dim); \
248 : } \
249 : } while (0)
250 :
251 : #define void_fe_with_vec_switch(func_and_args) \
252 : do { \
253 : switch (dim) \
254 : { \
255 : /* 0D */ \
256 : case 0: \
257 : fe_family_with_vec_switch (0, func_and_args, , ; return;); \
258 : /* 1D */ \
259 : case 1: \
260 : fe_family_with_vec_switch (1, func_and_args, , ; return;); \
261 : /* 2D */ \
262 : case 2: \
263 : fe_family_with_vec_switch (2, func_and_args, , ; return;); \
264 : /* 3D */ \
265 : case 3: \
266 : fe_family_with_vec_switch (3, func_and_args, , ; return;); \
267 : default: \
268 : libmesh_error_msg("Invalid dim = " << dim); \
269 : } \
270 : } while (0)
271 :
272 :
273 :
274 : #ifdef LIBMESH_ENABLE_DEPRECATED
275 0 : unsigned int FEInterface::n_shape_functions(const unsigned int dim,
276 : const FEType & fe_t,
277 : const ElemType t)
278 : {
279 : libmesh_deprecated();
280 :
281 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
282 :
283 : // We no longer support calling this function with an infinite
284 : // ElemType, you must call the FeInterface::n_shape_functions()
285 : // taking an Elem* instead.
286 0 : if (is_InfFE_elem(t))
287 0 : libmesh_not_implemented();
288 :
289 : #endif
290 :
291 0 : const Order o = fe_t.order;
292 :
293 0 : fe_with_vec_switch(n_shape_functions(t, o));
294 : }
295 : #endif // LIBMESH_ENABLE_DEPRECATED
296 :
297 :
298 :
299 : unsigned int
300 8435330 : FEInterface::n_shape_functions(const FEType & fe_t,
301 : const Elem * elem,
302 : const bool add_p_level)
303 : {
304 : // dim is required by the fe_with_vec_switch macro
305 8435330 : auto dim = elem->dim();
306 :
307 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
308 : /*
309 : * Since the FEType, stored in DofMap/(some System child), has to
310 : * be the _same_ for InfFE and FE, we have to catch calls
311 : * to infinite elements through the element type.
312 : */
313 :
314 1861874 : if (is_InfFE_elem(elem->type()))
315 0 : return ifem_n_shape_functions(fe_t, elem);
316 :
317 : #endif
318 :
319 : // Account for Elem::p_level() when computing total_order
320 9198435 : auto total_order = fe_t.order + add_p_level*elem->p_level();
321 :
322 8435330 : fe_with_vec_switch(n_dofs(elem, total_order));
323 : }
324 :
325 :
326 :
327 : unsigned int
328 1663885730 : FEInterface::n_shape_functions(const FEType & fe_t,
329 : const int extra_order,
330 : const Elem * elem)
331 : {
332 : // dim is required by the fe_with_vec_switch macro
333 1663885730 : auto dim = elem->dim();
334 :
335 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
336 : /*
337 : * Since the FEType, stored in DofMap/(some System child), has to
338 : * be the _same_ for InfFE and FE, we have to catch calls
339 : * to infinite elements through the element type.
340 : */
341 :
342 307533488 : if (is_InfFE_elem(elem->type()))
343 0 : return ifem_n_shape_functions(fe_t, elem);
344 :
345 : #endif
346 :
347 : // Ignore Elem::p_level() and instead use extra_order to compute total_order.
348 228182102 : auto total_order = fe_t.order + extra_order;
349 :
350 1663885730 : fe_with_vec_switch(n_dofs(elem, total_order));
351 : }
352 :
353 :
354 :
355 : #ifdef LIBMESH_ENABLE_DEPRECATED
356 0 : unsigned int FEInterface::n_dofs(const unsigned int dim,
357 : const FEType & fe_t,
358 : const ElemType t)
359 : {
360 : libmesh_deprecated();
361 :
362 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
363 :
364 : // We no longer support calling this function with an infinite
365 : // ElemType, you must call the FeInterface::n_dofs() taking an Elem*
366 : // instead.
367 0 : if (is_InfFE_elem(t))
368 0 : libmesh_not_implemented();
369 :
370 : #endif
371 :
372 0 : const Order o = fe_t.order;
373 :
374 0 : fe_with_vec_switch(n_dofs(t, o));
375 : }
376 :
377 :
378 :
379 :
380 : unsigned int
381 0 : FEInterface::n_dofs (const unsigned int dim,
382 : const FEType & fe_t,
383 : const Elem * elem)
384 : {
385 : libmesh_deprecated();
386 :
387 0 : fe_with_vec_switch(n_dofs(elem, fe_t.order + elem->p_level()));
388 : }
389 : #endif // LIBMESH_ENABLE_DEPRECATED
390 :
391 :
392 :
393 : unsigned int
394 9100199 : FEInterface::n_dofs(const FEType & fe_t,
395 : const Elem * elem,
396 : const bool add_p_level)
397 : {
398 : // dim is required by the fe_with_vec_switch macro
399 9100199 : auto dim = elem->dim();
400 :
401 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
402 :
403 : // InfElems currently don't support p_level()
404 1589879 : if (is_InfFE_elem(elem->type()))
405 223092 : return ifem_n_dofs(fe_t, elem);
406 :
407 : #endif
408 :
409 : // Account for Elem::p_level() when computing total_order
410 8877107 : fe_with_vec_switch(n_dofs(elem, fe_t.order + add_p_level*elem->p_level()));
411 : }
412 :
413 :
414 :
415 : unsigned int
416 24751485 : FEInterface::n_dofs(const FEType & fe_t,
417 : int extra_order,
418 : const Elem * elem)
419 : {
420 : // dim is required by the fe_with_vec_switch macro
421 24751485 : auto dim = elem->dim();
422 :
423 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
424 :
425 : // InfElems currently don't support p_level()
426 24750797 : if (is_InfFE_elem(elem->type()))
427 4257 : return ifem_n_dofs(fe_t, elem);
428 :
429 : #endif
430 :
431 : // Elem::p_level() is ignored, extra_order is used instead.
432 24746463 : auto total_order = fe_t.order + extra_order;
433 :
434 24747228 : fe_with_vec_switch(n_dofs(elem, total_order));
435 : }
436 :
437 :
438 :
439 : #ifdef LIBMESH_ENABLE_DEPRECATED
440 0 : unsigned int FEInterface::n_dofs_at_node(const unsigned int dim,
441 : const FEType & fe_t,
442 : const ElemType t,
443 : const unsigned int n)
444 : {
445 : libmesh_deprecated();
446 :
447 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
448 :
449 0 : if (is_InfFE_elem(t))
450 0 : return ifem_n_dofs_at_node(dim, fe_t, t, n);
451 :
452 : #endif
453 :
454 0 : const Order o = fe_t.order;
455 :
456 0 : fe_with_vec_switch(n_dofs_at_node(t, o, n));
457 : }
458 :
459 :
460 :
461 : FEInterface::n_dofs_at_node_ptr
462 0 : FEInterface::n_dofs_at_node_function(const unsigned int dim,
463 : const FEType & fe_t)
464 : {
465 : libmesh_deprecated();
466 :
467 0 : fe_with_vec_switch(n_dofs_at_node);
468 : }
469 : #endif // LIBMESH_ENABLE_DEPRECATED
470 :
471 :
472 :
473 : FEInterface::n_dofs_at_node_ptr
474 309480063 : FEInterface::n_dofs_at_node_function(const FEType & fe_t,
475 : const Elem * elem)
476 : {
477 : // dim is required by the fe_with_vec_switch macro
478 309480063 : auto dim = elem->dim();
479 :
480 309480063 : fe_with_vec_switch(n_dofs_at_node);
481 : }
482 :
483 :
484 :
485 : unsigned int
486 192578215 : FEInterface::n_dofs_at_node(const FEType & fe_t,
487 : const Elem * elem,
488 : const unsigned int n,
489 : const bool add_p_level)
490 : {
491 : // dim is required by the fe_with_vec_switch macro
492 192578215 : auto dim = elem->dim();
493 :
494 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
495 :
496 30778274 : if (is_InfFE_elem(elem->type()))
497 99078 : return ifem_n_dofs_at_node(fe_t, elem, n);
498 :
499 : #endif
500 :
501 : // Account for Elem::p_level() when computing total_order
502 204887426 : auto total_order = fe_t.order + add_p_level*elem->p_level();
503 :
504 192479137 : fe_with_vec_switch(n_dofs_at_node(*elem, total_order, n));
505 : }
506 :
507 :
508 :
509 : unsigned int
510 159660 : FEInterface::n_dofs_at_node(const FEType & fe_t,
511 : const int extra_order,
512 : const Elem * elem,
513 : const unsigned int n)
514 : {
515 : // dim is required by the fe_with_vec_switch macro
516 159660 : auto dim = elem->dim();
517 :
518 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
519 :
520 158364 : if (is_InfFE_elem(elem->type()))
521 157932 : return ifem_n_dofs_at_node(fe_t, elem, n);
522 :
523 : #endif
524 :
525 : // Ignore Elem::p_level() and instead use extra_order to compute total_order.
526 288 : auto total_order = fe_t.order + extra_order;
527 :
528 1728 : fe_with_vec_switch(n_dofs_at_node(*elem, total_order, n));
529 : }
530 :
531 :
532 :
533 : #ifdef LIBMESH_ENABLE_DEPRECATED
534 0 : unsigned int FEInterface::n_dofs_per_elem(const unsigned int dim,
535 : const FEType & fe_t,
536 : const ElemType t)
537 : {
538 : libmesh_deprecated();
539 :
540 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
541 :
542 0 : if (is_InfFE_elem(t))
543 0 : return ifem_n_dofs_per_elem(dim, fe_t, t);
544 :
545 : #endif
546 :
547 0 : const Order o = fe_t.order;
548 :
549 0 : fe_with_vec_switch(n_dofs_per_elem(t, o));
550 : }
551 : #endif // LIBMESH_ENABLE_DEPRECATED
552 :
553 :
554 :
555 : unsigned int
556 24007961 : FEInterface::n_dofs_per_elem(const FEType & fe_t,
557 : const Elem * elem,
558 : const bool add_p_level)
559 : {
560 : // dim is required by the fe_with_vec_switch macro
561 24007961 : auto dim = elem->dim();
562 :
563 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
564 :
565 4626167 : if (is_InfFE_elem(elem->type()))
566 7932 : return ifem_n_dofs_per_elem(fe_t, elem);
567 :
568 : #endif
569 :
570 : // Account for Elem::p_level() when computing total_order
571 25764675 : auto total_order = fe_t.order + add_p_level*elem->p_level();
572 :
573 24000029 : fe_with_vec_switch(n_dofs_per_elem(*elem, total_order));
574 : }
575 :
576 :
577 :
578 : unsigned int
579 309480063 : FEInterface::n_dofs_per_elem(const FEType & fe_t,
580 : const int extra_order,
581 : const Elem * elem)
582 : {
583 : // dim is required by the fe_with_vec_switch macro
584 309480063 : auto dim = elem->dim();
585 :
586 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
587 :
588 58075789 : if (is_InfFE_elem(elem->type()))
589 14820 : return ifem_n_dofs_per_elem(fe_t, elem);
590 :
591 : #endif
592 :
593 : // Ignore Elem::p_level() and instead use extra_order to compute total_order.
594 50125122 : auto total_order = fe_t.order + extra_order;
595 :
596 309465243 : fe_with_vec_switch(n_dofs_per_elem(*elem, total_order));
597 : }
598 :
599 :
600 :
601 930161 : void FEInterface::dofs_on_side(const Elem * const elem,
602 : const unsigned int dim,
603 : const FEType & fe_t,
604 : unsigned int s,
605 : std::vector<unsigned int> & di,
606 : const bool add_p_level)
607 : {
608 157230 : const Order o = fe_t.order;
609 :
610 930161 : void_fe_with_vec_switch(dofs_on_side(elem, o, s, di, add_p_level));
611 : }
612 :
613 :
614 :
615 148298 : void FEInterface::dofs_on_edge(const Elem * const elem,
616 : const unsigned int dim,
617 : const FEType & fe_t,
618 : unsigned int e,
619 : std::vector<unsigned int> & di,
620 : const bool add_p_level)
621 : {
622 21578 : const Order o = fe_t.order;
623 :
624 148298 : void_fe_with_vec_switch(dofs_on_edge(elem, o, e, di, add_p_level));
625 : }
626 :
627 :
628 :
629 15889262 : void FEInterface::nodal_soln(const unsigned int dim,
630 : const FEType & fe_t,
631 : const Elem * elem,
632 : const std::vector<Number> & elem_soln,
633 : std::vector<Number> & nodal_soln,
634 : const bool add_p_level,
635 : const unsigned int vdim)
636 : {
637 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
638 :
639 3469759 : if (is_InfFE_elem(elem->type()))
640 : {
641 0 : ifem_nodal_soln(dim, fe_t, elem, elem_soln, nodal_soln);
642 0 : return;
643 : }
644 :
645 : #endif
646 :
647 2884090 : const Order order = fe_t.order;
648 :
649 15889262 : void_fe_with_vec_switch(nodal_soln(elem, order, elem_soln, nodal_soln, add_p_level, vdim));
650 : }
651 :
652 :
653 :
654 495912 : void FEInterface::side_nodal_soln(const FEType & fe_t,
655 : const Elem * elem,
656 : const unsigned int side,
657 : const std::vector<Number> & elem_soln,
658 : std::vector<Number> & nodal_soln,
659 : const bool add_p_level,
660 : const unsigned int vdim)
661 : {
662 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
663 :
664 123402 : if (is_InfFE_elem(elem->type()))
665 : {
666 0 : libmesh_not_implemented();
667 : return;
668 : }
669 :
670 : #endif
671 :
672 82780 : const Order order = fe_t.order;
673 495912 : const unsigned int dim = elem->dim();
674 :
675 495912 : void_fe_with_vec_switch(side_nodal_soln(elem, order, side, elem_soln, nodal_soln, add_p_level, vdim));
676 : }
677 :
678 :
679 :
680 : #ifdef LIBMESH_ENABLE_DEPRECATED
681 0 : Point FEInterface::map(unsigned int dim,
682 : const FEType & fe_t,
683 : const Elem * elem,
684 : const Point & p)
685 : {
686 : libmesh_deprecated();
687 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
688 0 : if (is_InfFE_elem(elem->type()))
689 0 : return ifem_map(dim, fe_t, elem, p);
690 : #endif
691 0 : fe_with_vec_switch(map(elem, p));
692 : }
693 :
694 :
695 :
696 0 : Point FEInterface::inverse_map (const unsigned int dim,
697 : const FEType & fe_t,
698 : const Elem * elem,
699 : const Point & p,
700 : const Real tolerance,
701 : const bool secure)
702 : {
703 : libmesh_deprecated();
704 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
705 :
706 0 : if (is_InfFE_elem(elem->type()))
707 0 : return ifem_inverse_map(dim, fe_t, elem, p,tolerance, secure);
708 :
709 : #endif
710 :
711 0 : fe_with_vec_switch(inverse_map(elem, p, tolerance, secure));
712 : }
713 :
714 :
715 :
716 0 : void FEInterface::inverse_map (const unsigned int dim,
717 : const FEType & fe_t,
718 : const Elem * elem,
719 : const std::vector<Point> & physical_points,
720 : std::vector<Point> & reference_points,
721 : const Real tolerance,
722 : const bool secure)
723 : {
724 : libmesh_deprecated();
725 :
726 0 : const std::size_t n_pts = physical_points.size();
727 :
728 : // Resize the vector
729 0 : reference_points.resize(n_pts);
730 :
731 0 : if (n_pts == 0)
732 : {
733 0 : libMesh::err << "WARNING: empty vector physical_points!"
734 0 : << std::endl;
735 0 : libmesh_here();
736 0 : return;
737 : }
738 :
739 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
740 :
741 0 : if (is_InfFE_elem(elem->type()))
742 : {
743 0 : ifem_inverse_map(dim, fe_t, elem, physical_points, reference_points, tolerance, secure);
744 0 : return;
745 : // libmesh_not_implemented();
746 : }
747 :
748 : #endif
749 :
750 0 : void_fe_with_vec_switch(inverse_map(elem, physical_points, reference_points, tolerance, secure));
751 : }
752 :
753 :
754 :
755 0 : bool FEInterface::on_reference_element(const Point & p,
756 : const ElemType t,
757 : const Real eps)
758 : {
759 0 : return FEBase::on_reference_element(p,t,eps);
760 : }
761 :
762 :
763 :
764 0 : Real FEInterface::shape(const unsigned int dim,
765 : const FEType & fe_t,
766 : const ElemType t,
767 : const unsigned int i,
768 : const Point & p)
769 : {
770 : libmesh_deprecated();
771 :
772 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
773 :
774 0 : if (is_InfFE_elem(t))
775 0 : return ifem_shape(dim, fe_t, t, i, p);
776 :
777 : #endif
778 :
779 0 : const Order o = fe_t.order;
780 :
781 0 : fe_switch(shape(t,o,i,p));
782 : }
783 :
784 0 : Real FEInterface::shape(const unsigned int dim,
785 : const FEType & fe_t,
786 : const Elem * elem,
787 : const unsigned int i,
788 : const Point & p)
789 : {
790 : libmesh_deprecated();
791 :
792 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
793 :
794 0 : if (elem && is_InfFE_elem(elem->type()))
795 0 : return ifem_shape(fe_t, elem, i, p);
796 :
797 : #endif
798 :
799 0 : const Order o = fe_t.order;
800 :
801 0 : fe_switch(shape(elem,o,i,p));
802 : }
803 : #endif // LIBMESH_ENABLE_DEPRECATED
804 :
805 :
806 :
807 : Real
808 223878891 : FEInterface::shape(const FEType & fe_t,
809 : const Elem * elem,
810 : const unsigned int i,
811 : const Point & p,
812 : const bool add_p_level)
813 : {
814 : // dim is required by the fe_switch macro
815 223878891 : auto dim = elem->dim();
816 :
817 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
818 :
819 51887423 : if (elem && is_InfFE_elem(elem->type()))
820 0 : return ifem_shape(fe_t, elem, i, p);
821 :
822 : #endif
823 :
824 : // We are calling
825 : //
826 : // FE<X,Y>::shape(Elem *, Order, unsigned, Point, true)
827 : //
828 : // See fe.h for more details.
829 223878891 : fe_switch(shape(elem, fe_t.order, i, p, add_p_level));
830 : }
831 :
832 :
833 :
834 : Real
835 1333151491 : FEInterface::shape(const FEType & fe_t,
836 : int extra_order,
837 : const Elem * elem,
838 : const unsigned int i,
839 : const Point & p)
840 : {
841 : // dim is required by the fe_switch macro
842 1333151491 : auto dim = elem->dim();
843 :
844 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
845 :
846 305113357 : if (elem && is_InfFE_elem(elem->type()))
847 0 : return ifem_shape(fe_t, elem, i, p);
848 :
849 : #endif
850 :
851 : // We are calling
852 : //
853 : // FE<X,Y>::shape(Elem *, Order, unsigned, Point, false)
854 : //
855 : // with the last parameter set to "false" so that the
856 : // Elem::p_level() is not used internally and the "total_order" that
857 : // we compute is used instead. See fe.h for more details.
858 217810650 : auto total_order = fe_t.order + extra_order;
859 :
860 1333151491 : fe_switch(shape(elem, total_order, i, p, false));
861 : }
862 :
863 :
864 :
865 : #ifdef LIBMESH_ENABLE_DEPRECATED
866 : template<>
867 0 : void FEInterface::shape<Real>(const unsigned int dim,
868 : const FEType & fe_t,
869 : const ElemType t,
870 : const unsigned int i,
871 : const Point & p,
872 : Real & phi)
873 : {
874 : libmesh_deprecated();
875 :
876 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
877 :
878 0 : if (is_InfFE_elem(t))
879 : {
880 0 : phi = ifem_shape(dim, fe_t, t, i, p);
881 0 : return;
882 : }
883 :
884 : #endif
885 :
886 0 : const Order o = fe_t.order;
887 :
888 0 : switch(dim)
889 : {
890 0 : case 0:
891 0 : fe_scalar_vec_error_switch(0, shape(t,o,i,p), phi = , ; break;);
892 0 : break;
893 0 : case 1:
894 0 : fe_scalar_vec_error_switch(1, shape(t,o,i,p), phi = , ; break;);
895 0 : break;
896 0 : case 2:
897 0 : fe_scalar_vec_error_switch(2, shape(t,o,i,p), phi = , ; break;);
898 0 : break;
899 0 : case 3:
900 0 : fe_scalar_vec_error_switch(3, shape(t,o,i,p), phi = , ; break;);
901 0 : break;
902 0 : default:
903 0 : libmesh_error_msg("Invalid dimension = " << dim);
904 : }
905 :
906 0 : return;
907 : }
908 :
909 :
910 :
911 : template<>
912 0 : void FEInterface::shape<Real>(const unsigned int dim,
913 : const FEType & fe_t,
914 : const Elem * elem,
915 : const unsigned int i,
916 : const Point & p,
917 : Real & phi)
918 : {
919 : libmesh_deprecated();
920 :
921 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
922 :
923 0 : if (elem && is_InfFE_elem(elem->type()))
924 : {
925 0 : phi = ifem_shape(fe_t, elem, i, p);
926 0 : return;
927 : }
928 : #endif
929 :
930 0 : const Order o = fe_t.order;
931 :
932 0 : switch(dim)
933 : {
934 0 : case 0:
935 0 : fe_scalar_vec_error_switch(0, shape(elem,o,i,p), phi = , ; break;);
936 0 : break;
937 0 : case 1:
938 0 : fe_scalar_vec_error_switch(1, shape(elem,o,i,p), phi = , ; break;);
939 0 : break;
940 0 : case 2:
941 0 : fe_scalar_vec_error_switch(2, shape(elem,o,i,p), phi = , ; break;);
942 0 : break;
943 0 : case 3:
944 0 : fe_scalar_vec_error_switch(3, shape(elem,o,i,p), phi = , ; break;);
945 0 : break;
946 0 : default:
947 0 : libmesh_error_msg("Invalid dimension = " << dim);
948 : }
949 :
950 0 : return;
951 : }
952 : #endif // LIBMESH_ENABLE_DEPRECATED
953 :
954 :
955 :
956 : template<>
957 0 : void FEInterface::shape<Real>(const FEType & fe_t,
958 : const Elem * elem,
959 : const unsigned int i,
960 : const Point & p,
961 : Real & phi)
962 : {
963 : // dim is required by the fe_switch macro
964 0 : auto dim = elem->dim();
965 :
966 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
967 :
968 0 : if (is_InfFE_elem(elem->type()))
969 : {
970 0 : phi = ifem_shape(fe_t, elem, i, p);
971 0 : return;
972 : }
973 :
974 : #endif
975 :
976 : // Below we call FE<X,Y>::shape(Elem *, Order, unsigned, Point, true)
977 : // so that the Elem::p_level() is accounted for internally.
978 0 : switch(dim)
979 : {
980 0 : case 0:
981 0 : fe_scalar_vec_error_switch(0, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
982 0 : break;
983 0 : case 1:
984 0 : fe_scalar_vec_error_switch(1, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
985 0 : break;
986 0 : case 2:
987 0 : fe_scalar_vec_error_switch(2, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
988 0 : break;
989 0 : case 3:
990 0 : fe_scalar_vec_error_switch(3, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
991 0 : break;
992 0 : default:
993 0 : libmesh_error_msg("Invalid dimension = " << dim);
994 : }
995 0 : }
996 :
997 :
998 :
999 : template<>
1000 0 : void FEInterface::shape<Real>(const FEType & fe_t,
1001 : int extra_order,
1002 : const Elem * elem,
1003 : const unsigned int i,
1004 : const Point & p,
1005 : Real & phi)
1006 : {
1007 : // dim is required by the fe_switch macro
1008 0 : auto dim = elem->dim();
1009 :
1010 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1011 :
1012 0 : if (is_InfFE_elem(elem->type()))
1013 : {
1014 0 : phi = ifem_shape(fe_t, elem, i, p);
1015 0 : return;
1016 : }
1017 :
1018 : #endif
1019 :
1020 : // Ignore Elem::p_level() and instead use extra_order to compute total_order
1021 0 : auto total_order = fe_t.order + extra_order;
1022 :
1023 : // Below we call
1024 : //
1025 : // FE<X,Y>::shape(Elem *, Order, unsigned, Point, false)
1026 : //
1027 : // so that the Elem::p_level() is ignored and the total_order that
1028 : // we compute is used instead.
1029 0 : switch(dim)
1030 : {
1031 0 : case 0:
1032 0 : fe_scalar_vec_error_switch(0, shape(elem, total_order, i, p, false), phi = , ; break;);
1033 0 : break;
1034 0 : case 1:
1035 0 : fe_scalar_vec_error_switch(1, shape(elem, total_order, i, p, false), phi = , ; break;);
1036 0 : break;
1037 0 : case 2:
1038 0 : fe_scalar_vec_error_switch(2, shape(elem, total_order, i, p, false), phi = , ; break;);
1039 0 : break;
1040 0 : case 3:
1041 0 : fe_scalar_vec_error_switch(3, shape(elem, total_order, i, p, false), phi = , ; break;);
1042 0 : break;
1043 0 : default:
1044 0 : libmesh_error_msg("Invalid dimension = " << dim);
1045 : }
1046 0 : }
1047 :
1048 :
1049 :
1050 : template<>
1051 5485828 : void FEInterface::shapes<Real>(const unsigned int dim,
1052 : const FEType & fe_t,
1053 : const Elem * elem,
1054 : const unsigned int i,
1055 : const std::vector<Point> & p,
1056 : std::vector<Real> & phi,
1057 : const bool add_p_level)
1058 : {
1059 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1060 :
1061 1318792 : if (elem && is_InfFE_elem(elem->type()))
1062 : {
1063 0 : FEType elevated = fe_t;
1064 0 : elevated.order = fe_t.order + add_p_level * elem->p_level();
1065 0 : for (auto qpi : index_range(p))
1066 0 : phi[qpi] = ifem_shape(elevated, elem, i, p[qpi]);
1067 0 : return;
1068 : }
1069 : #endif
1070 :
1071 937786 : const Order o = fe_t.order;
1072 :
1073 5485828 : switch(dim)
1074 : {
1075 0 : case 0:
1076 0 : fe_scalar_vec_error_switch(0, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
1077 : break;
1078 4188 : case 1:
1079 4188 : fe_scalar_vec_error_switch(1, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
1080 : break;
1081 2490672 : case 2:
1082 2490672 : fe_scalar_vec_error_switch(2, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
1083 : break;
1084 2990968 : case 3:
1085 2990968 : fe_scalar_vec_error_switch(3, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
1086 : break;
1087 0 : default:
1088 0 : libmesh_error_msg("Invalid dimension = " << dim);
1089 : }
1090 :
1091 : return;
1092 : }
1093 :
1094 :
1095 : template<>
1096 134715035 : void FEInterface::all_shapes<Real>(const unsigned int dim,
1097 : const FEType & fe_t,
1098 : const Elem * elem,
1099 : const std::vector<Point> & p,
1100 : std::vector<std::vector<Real>> & phi,
1101 : const bool add_p_level)
1102 : {
1103 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1104 :
1105 30684347 : if (elem && is_InfFE_elem(elem->type()))
1106 : {
1107 0 : for (auto i : index_range(phi))
1108 0 : FEInterface::shapes<Real>(dim, fe_t, elem, i, p, phi[i], add_p_level);
1109 0 : return;
1110 : }
1111 : #endif
1112 :
1113 24213036 : const Order o = fe_t.order;
1114 :
1115 134715035 : switch(dim)
1116 : {
1117 198780 : case 0:
1118 198780 : fe_scalar_vec_error_switch(0, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
1119 : break;
1120 2822426 : case 1:
1121 2822426 : fe_scalar_vec_error_switch(1, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
1122 : break;
1123 98406346 : case 2:
1124 98406346 : fe_scalar_vec_error_switch(2, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
1125 : break;
1126 33287483 : case 3:
1127 33287483 : fe_scalar_vec_error_switch(3, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
1128 : break;
1129 0 : default:
1130 0 : libmesh_error_msg("Invalid dimension = " << dim);
1131 : }
1132 :
1133 : return;
1134 : }
1135 :
1136 :
1137 :
1138 : #ifdef LIBMESH_ENABLE_DEPRECATED
1139 : template<>
1140 0 : void FEInterface::shape<RealGradient>(const unsigned int dim,
1141 : const FEType & fe_t,
1142 : const ElemType t,
1143 : const unsigned int i,
1144 : const Point & p,
1145 : RealGradient & phi)
1146 : {
1147 : libmesh_deprecated();
1148 :
1149 : // This API does not currently support infinite elements.
1150 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1151 0 : if (is_InfFE_elem(t))
1152 : {
1153 0 : libmesh_not_implemented();
1154 : }
1155 : #endif
1156 0 : const Order o = fe_t.order;
1157 :
1158 0 : switch(dim)
1159 : {
1160 0 : case 0:
1161 0 : fe_vector_scalar_error_switch(0, shape(t,o,i,p), phi = , ; break;);
1162 0 : break;
1163 0 : case 1:
1164 0 : fe_vector_scalar_error_switch(1, shape(t,o,i,p), phi = , ; break;);
1165 0 : break;
1166 0 : case 2:
1167 0 : fe_vector_scalar_error_switch(2, shape(t,o,i,p), phi = , ; break;);
1168 0 : break;
1169 0 : case 3:
1170 0 : fe_vector_scalar_error_switch(3, shape(t,o,i,p), phi = , ; break;);
1171 0 : break;
1172 0 : default:
1173 0 : libmesh_error_msg("Invalid dimension = " << dim);
1174 : }
1175 0 : }
1176 : #endif // LIBMESH_ENABLE_DEPRECATED
1177 :
1178 :
1179 :
1180 : template<>
1181 0 : void FEInterface::shape<RealGradient>(const FEType & fe_t,
1182 : const Elem * elem,
1183 : const unsigned int i,
1184 : const Point & p,
1185 : RealGradient & phi)
1186 : {
1187 : // This API does not currently support infinite elements.
1188 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1189 0 : if (is_InfFE_elem(elem->type()))
1190 : {
1191 0 : libmesh_not_implemented();
1192 : }
1193 : #endif
1194 :
1195 0 : auto dim = elem->dim();
1196 :
1197 : // We are calling
1198 : //
1199 : // FE<X,Y>::shape(Elem *, Order, unsigned, Point, true)
1200 : //
1201 : // with the last parameter set to "true" so that the Elem::p_level()
1202 : // is accounted for internally. See fe.h for more details.
1203 :
1204 0 : switch(dim)
1205 : {
1206 0 : case 0:
1207 0 : fe_vector_scalar_error_switch(0, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
1208 0 : break;
1209 0 : case 1:
1210 0 : fe_vector_scalar_error_switch(1, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
1211 0 : break;
1212 0 : case 2:
1213 0 : fe_vector_scalar_error_switch(2, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
1214 0 : break;
1215 0 : case 3:
1216 0 : fe_vector_scalar_error_switch(3, shape(elem, fe_t.order, i, p, true), phi = , ; break;);
1217 0 : break;
1218 0 : default:
1219 0 : libmesh_error_msg("Invalid dimension = " << dim);
1220 : }
1221 0 : }
1222 :
1223 :
1224 :
1225 : template<>
1226 166085800 : void FEInterface::shape<RealGradient>(const FEType & fe_t,
1227 : int extra_order,
1228 : const Elem * elem,
1229 : const unsigned int i,
1230 : const Point & p,
1231 : RealGradient & phi)
1232 : {
1233 : // This API does not currently support infinite elements.
1234 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1235 33003240 : if (is_InfFE_elem(elem->type()))
1236 : {
1237 0 : libmesh_not_implemented();
1238 : }
1239 : #endif
1240 :
1241 166085800 : auto dim = elem->dim();
1242 :
1243 : // We are calling
1244 : //
1245 : // FE<X,Y>::shape(Elem *, Order, unsigned, Point, false)
1246 : //
1247 : // with the last parameter set to "false" so that the
1248 : // Elem::p_level() is not used internally and the "total_order" that
1249 : // we compute is used instead. See fe.h for more details.
1250 22221960 : auto total_order = fe_t.order + extra_order;
1251 :
1252 166085800 : switch(dim)
1253 : {
1254 0 : case 0:
1255 0 : fe_vector_scalar_error_switch(0, shape(elem, total_order, i, p, false), phi = , ; break;);
1256 0 : break;
1257 0 : case 1:
1258 0 : fe_vector_scalar_error_switch(1, shape(elem, total_order, i, p, false), phi = , ; break;);
1259 0 : break;
1260 46325814 : case 2:
1261 46325814 : fe_vector_scalar_error_switch(2, shape(elem, total_order, i, p, false), phi = , ; break;);
1262 3641840 : break;
1263 119759986 : case 3:
1264 119759986 : fe_vector_scalar_error_switch(3, shape(elem, total_order, i, p, false), phi = , ; break;);
1265 7469140 : break;
1266 0 : default:
1267 0 : libmesh_error_msg("Invalid dimension = " << dim);
1268 : }
1269 166085800 : }
1270 :
1271 :
1272 :
1273 : template<>
1274 0 : void FEInterface::shapes<RealGradient>(const unsigned int dim,
1275 : const FEType & fe_t,
1276 : const Elem * elem,
1277 : const unsigned int i,
1278 : const std::vector<Point> & p,
1279 : std::vector<RealGradient> & phi,
1280 : const bool add_p_level)
1281 : {
1282 : // This is actually an issue for infinite elements: They require type 'Gradient'!
1283 0 : if (elem->infinite())
1284 0 : libmesh_not_implemented();
1285 :
1286 0 : const Order o = fe_t.order;
1287 :
1288 0 : switch(dim)
1289 : {
1290 0 : case 0:
1291 0 : fe_vector_scalar_error_switch(0, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
1292 : break;
1293 0 : case 1:
1294 0 : fe_vector_scalar_error_switch(1, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
1295 : break;
1296 0 : case 2:
1297 0 : fe_vector_scalar_error_switch(2, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
1298 : break;
1299 0 : case 3:
1300 0 : fe_vector_scalar_error_switch(3, shapes(elem,o,i,p,phi,add_p_level), , ; return;);
1301 : break;
1302 0 : default:
1303 0 : libmesh_error_msg("Invalid dimension = " << dim);
1304 : }
1305 :
1306 : return;
1307 : }
1308 :
1309 :
1310 :
1311 : template<>
1312 6445360 : void FEInterface::all_shapes<RealGradient>(const unsigned int dim,
1313 : const FEType & fe_t,
1314 : const Elem * elem,
1315 : const std::vector<Point> & p,
1316 : std::vector<std::vector<RealGradient>> & phi,
1317 : const bool add_p_level)
1318 : {
1319 : // This is actually an issue for infinite elements: They require type 'Gradient'!
1320 1597436 : if (elem->infinite())
1321 0 : libmesh_not_implemented();
1322 :
1323 1075052 : const Order o = fe_t.order;
1324 :
1325 6445360 : switch(dim)
1326 : {
1327 0 : case 0:
1328 0 : fe_vector_scalar_error_switch(0, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
1329 : break;
1330 0 : case 1:
1331 0 : fe_vector_scalar_error_switch(1, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
1332 : break;
1333 1994299 : case 2:
1334 1994299 : fe_vector_scalar_error_switch(2, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
1335 : break;
1336 4451061 : case 3:
1337 4451061 : fe_vector_scalar_error_switch(3, all_shapes(elem,o,p,phi,add_p_level), , ; return;);
1338 : break;
1339 0 : default:
1340 0 : libmesh_error_msg("Invalid dimension = " << dim);
1341 : }
1342 :
1343 : return;
1344 : }
1345 :
1346 :
1347 : #ifdef LIBMESH_ENABLE_DEPRECATED
1348 : FEInterface::shape_ptr
1349 0 : FEInterface::shape_function(const unsigned int dim,
1350 : const FEType & fe_t,
1351 : const ElemType libmesh_inf_var(t))
1352 : {
1353 : libmesh_deprecated();
1354 :
1355 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1356 0 : if (is_InfFE_elem(t))
1357 : {
1358 0 : inf_fe_switch(shape);
1359 : }
1360 : #endif
1361 0 : fe_switch(shape);
1362 : }
1363 : #endif // LIBMESH_ENABLE_DEPRECATED
1364 :
1365 :
1366 :
1367 : FEInterface::shape_ptr
1368 358084951 : FEInterface::shape_function(const FEType & fe_t,
1369 : const Elem * elem)
1370 : {
1371 : // dim is needed by the fe_switch macros below
1372 358084951 : auto dim = elem->dim();
1373 :
1374 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1375 66893619 : if (is_InfFE_elem(elem->type()))
1376 0 : inf_fe_switch(shape);
1377 : #endif
1378 358084951 : fe_switch(shape);
1379 : }
1380 :
1381 :
1382 :
1383 : #ifdef LIBMESH_ENABLE_DEPRECATED
1384 0 : Real FEInterface::shape_deriv(const unsigned int dim,
1385 : const FEType & fe_t,
1386 : const ElemType t,
1387 : const unsigned int i,
1388 : const unsigned int j,
1389 : const Point & p)
1390 : {
1391 : libmesh_deprecated();
1392 :
1393 0 : libmesh_assert_greater (dim,j);
1394 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1395 :
1396 0 : if (is_InfFE_elem(t)){
1397 0 : return ifem_shape_deriv(dim, fe_t, t, i, j, p);
1398 : }
1399 :
1400 : #endif
1401 :
1402 0 : const Order o = fe_t.order;
1403 0 : fe_switch(shape_deriv(t,o,i,j,p));
1404 : return 0;
1405 : }
1406 :
1407 :
1408 0 : Real FEInterface::shape_deriv(const unsigned int dim,
1409 : const FEType & fe_t,
1410 : const Elem * elem,
1411 : const unsigned int i,
1412 : const unsigned int j,
1413 : const Point & p)
1414 : {
1415 : libmesh_deprecated();
1416 :
1417 0 : libmesh_assert_greater (dim,j);
1418 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1419 :
1420 0 : if (elem->infinite()){
1421 0 : return ifem_shape_deriv(fe_t, elem, i, j, p);
1422 : }
1423 :
1424 : #endif
1425 :
1426 0 : const Order o = fe_t.order;
1427 :
1428 0 : switch(dim)
1429 : {
1430 0 : case 0:
1431 0 : fe_family_switch (0, shape_deriv(elem, o, i, j, p), return , ;);
1432 0 : case 1:
1433 0 : fe_family_switch (1, shape_deriv(elem, o, i, j, p), return , ;);
1434 0 : case 2:
1435 0 : fe_family_switch (2, shape_deriv(elem, o, i, j, p), return , ;);
1436 0 : case 3:
1437 0 : fe_family_switch (3, shape_deriv(elem, o, i, j, p), return , ;);
1438 0 : default:
1439 0 : libmesh_error_msg("Invalid dimension = " << dim);
1440 : }
1441 : return 0;
1442 : }
1443 : #endif // LIBMESH_ENABLE_DEPRECATED
1444 :
1445 :
1446 :
1447 0 : Real FEInterface::shape_deriv(const FEType & fe_t,
1448 : const Elem * elem,
1449 : const unsigned int i,
1450 : const unsigned int j,
1451 : const Point & p)
1452 : {
1453 0 : auto dim = elem->dim();
1454 :
1455 0 : libmesh_assert_greater (dim, j);
1456 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1457 :
1458 0 : if (is_InfFE_elem(elem->type())){
1459 0 : return ifem_shape_deriv(fe_t, elem, i, j, p);
1460 : }
1461 :
1462 : #endif
1463 :
1464 : // Account for Elem::p_level() when computing total order. Note: we are calling
1465 : // FE::shape_deriv() with the final argument == true so that the Elem::p_level()
1466 : // is accounted for automatically internally.
1467 0 : fe_switch(shape_deriv(elem, fe_t.order, i, j, p, true));
1468 :
1469 : // We'll never get here
1470 : return 0;
1471 : }
1472 :
1473 :
1474 :
1475 1181419464 : Real FEInterface::shape_deriv(const FEType & fe_t,
1476 : int extra_order,
1477 : const Elem * elem,
1478 : const unsigned int i,
1479 : const unsigned int j,
1480 : const Point & p)
1481 : {
1482 1181419464 : auto dim = elem->dim();
1483 :
1484 95937904 : libmesh_assert_greater (dim, j);
1485 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1486 :
1487 274572966 : if (elem->infinite()){
1488 0 : return ifem_shape_deriv(fe_t, elem, i, j, p);
1489 : }
1490 :
1491 : #endif
1492 :
1493 : // Ignore Elem::p_level() when computing total order, use
1494 : // extra_order instead.
1495 191875808 : auto total_order = fe_t.order + extra_order;
1496 :
1497 : // We call shape_deriv() with the final argument == false so that
1498 : // the Elem::p_level() is ignored internally.
1499 1181419464 : switch(dim)
1500 : {
1501 0 : case 0:
1502 0 : fe_family_switch (0, shape_deriv(elem, total_order, i, j, p, false), return , ;);
1503 1369218 : case 1:
1504 1369218 : fe_family_switch (1, shape_deriv(elem, total_order, i, j, p, false), return , ;);
1505 294841782 : case 2:
1506 294841782 : fe_family_switch (2, shape_deriv(elem, total_order, i, j, p, false), return , ;);
1507 885208464 : case 3:
1508 885208464 : fe_family_switch (3, shape_deriv(elem, total_order, i, j, p, false), return , ;);
1509 0 : default:
1510 0 : libmesh_error_msg("Invalid dimension = " << dim);
1511 : }
1512 :
1513 : // We'll never get here
1514 : return 0;
1515 : }
1516 :
1517 :
1518 :
1519 : template<>
1520 16140090 : void FEInterface::shape_derivs<Real>(const FEType & fe_t,
1521 : const Elem * elem,
1522 : const unsigned int i,
1523 : const unsigned int j,
1524 : const std::vector<Point> & p,
1525 : std::vector<Real> & dphi,
1526 : const bool add_p_level)
1527 : {
1528 2767348 : const Order o = fe_t.order;
1529 :
1530 16140090 : switch(elem->dim())
1531 : {
1532 0 : case 0:
1533 0 : fe_scalar_vec_error_switch(0, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
1534 0 : break;
1535 4800 : case 1:
1536 4800 : fe_scalar_vec_error_switch(1, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
1537 401 : break;
1538 7182564 : case 2:
1539 7182564 : fe_scalar_vec_error_switch(2, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
1540 676944 : break;
1541 8952726 : case 3:
1542 8952726 : fe_scalar_vec_error_switch(3, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
1543 706329 : break;
1544 0 : default:
1545 0 : libmesh_error_msg("Invalid dimension = " << elem->dim());
1546 : }
1547 :
1548 16140090 : return;
1549 : }
1550 :
1551 :
1552 :
1553 : // Only instantiating Real because we don't expect vector-valued
1554 : // mapping functions, and that's what's using this interface.
1555 : template<>
1556 38822226 : void FEInterface::all_shape_derivs<Real>(const unsigned int dim,
1557 : const FEType & fe_t,
1558 : const Elem * elem,
1559 : const std::vector<Point> & p,
1560 : std::vector<std::vector<Real>> * comps[3],
1561 : const bool add_p_level)
1562 : {
1563 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1564 :
1565 9877300 : if (elem && is_InfFE_elem(elem->type()))
1566 : {
1567 0 : for (auto j : make_range(dim))
1568 0 : for (auto i : index_range(*comps[j]))
1569 0 : FEInterface::shape_derivs<Real>(fe_t, elem, i, j, p, (*comps[j])[i], add_p_level);
1570 0 : return;
1571 : }
1572 : #endif
1573 :
1574 6837356 : const Order o = fe_t.order;
1575 :
1576 38822226 : switch(dim)
1577 : {
1578 0 : case 0:
1579 0 : fe_scalar_vec_error_switch(0, all_shape_derivs(elem,o,p,comps,add_p_level), , ; return;);
1580 : break;
1581 145248 : case 1:
1582 145248 : fe_scalar_vec_error_switch(1, all_shape_derivs(elem,o,p,comps,add_p_level), , ; return;);
1583 : break;
1584 14592427 : case 2:
1585 14592427 : fe_scalar_vec_error_switch(2, all_shape_derivs(elem,o,p,comps,add_p_level), , ; return;);
1586 : break;
1587 24084551 : case 3:
1588 24084551 : fe_scalar_vec_error_switch(3, all_shape_derivs(elem,o,p,comps,add_p_level), , ; return;);
1589 : break;
1590 0 : default:
1591 0 : libmesh_error_msg("Invalid dimension = " << dim);
1592 : }
1593 :
1594 : return;
1595 : }
1596 :
1597 :
1598 :
1599 : template<>
1600 0 : void FEInterface::shape_derivs<RealGradient>(const FEType & fe_t,
1601 : const Elem * elem,
1602 : const unsigned int i,
1603 : const unsigned int j,
1604 : const std::vector<Point> & p,
1605 : std::vector<RealGradient> & dphi,
1606 : const bool add_p_level)
1607 : {
1608 0 : const Order o = fe_t.order;
1609 :
1610 0 : switch(elem->dim())
1611 : {
1612 0 : case 0:
1613 0 : fe_vector_scalar_error_switch(0, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
1614 0 : break;
1615 0 : case 1:
1616 0 : fe_vector_scalar_error_switch(1, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
1617 0 : break;
1618 0 : case 2:
1619 0 : fe_vector_scalar_error_switch(2, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
1620 0 : break;
1621 0 : case 3:
1622 0 : fe_vector_scalar_error_switch(3, shape_derivs(elem,o,i,j,p,dphi,add_p_level), , ; break;);
1623 0 : break;
1624 0 : default:
1625 0 : libmesh_error_msg("Invalid dimension = " << elem->dim());
1626 : }
1627 :
1628 0 : return;
1629 : }
1630 :
1631 :
1632 :
1633 : #ifdef LIBMESH_ENABLE_DEPRECATED
1634 : FEInterface::shape_deriv_ptr
1635 0 : FEInterface::shape_deriv_function(const unsigned int dim,
1636 : const FEType & fe_t,
1637 : const ElemType libmesh_inf_var(t))
1638 : {
1639 : libmesh_deprecated();
1640 :
1641 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1642 0 : if (is_InfFE_elem(t))
1643 : {
1644 0 : inf_fe_switch(shape_deriv);
1645 : }
1646 : #endif
1647 0 : fe_switch(shape_deriv);
1648 : }
1649 : #endif // LIBMESH_ENABLE_DEPRECATED
1650 :
1651 :
1652 :
1653 : FEInterface::shape_deriv_ptr
1654 1203091436 : FEInterface::shape_deriv_function(const FEType & fe_t,
1655 : const Elem * elem)
1656 : {
1657 : // dim is needed by the fe_switch macros below
1658 1203091436 : auto dim = elem->dim();
1659 :
1660 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1661 216396481 : if (is_InfFE_elem(elem->type()))
1662 : {
1663 0 : inf_fe_switch(shape_deriv);
1664 : }
1665 : #endif
1666 1203091436 : fe_switch(shape_deriv);
1667 : }
1668 :
1669 :
1670 : #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
1671 : #ifdef LIBMESH_ENABLE_DEPRECATED
1672 0 : Real FEInterface::shape_second_deriv(const unsigned int dim,
1673 : const FEType & fe_t,
1674 : const ElemType t,
1675 : const unsigned int i,
1676 : const unsigned int j,
1677 : const Point & p)
1678 : {
1679 : libmesh_deprecated();
1680 :
1681 0 : libmesh_assert_greater_equal (dim*(dim-1),j);
1682 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1683 0 : if (is_InfFE_elem(t))
1684 0 : libmesh_not_implemented();
1685 : #endif
1686 :
1687 0 : const Order o = fe_t.order;
1688 :
1689 0 : switch(dim)
1690 : {
1691 0 : case 0:
1692 0 : fe_family_switch (0, shape_second_deriv(t, o, i, j, p), return , ;);
1693 0 : case 1:
1694 0 : fe_family_switch (1, shape_second_deriv(t, o, i, j, p), return , ;);
1695 0 : case 2:
1696 0 : fe_family_switch (2, shape_second_deriv(t, o, i, j, p), return , ;);
1697 0 : case 3:
1698 0 : fe_family_switch (3, shape_second_deriv(t, o, i, j, p), return , ;);
1699 0 : default:
1700 0 : libmesh_error_msg("Invalid dimension = " << dim);
1701 : }
1702 : return 0;
1703 : }
1704 :
1705 :
1706 0 : Real FEInterface::shape_second_deriv(const unsigned int dim,
1707 : const FEType & fe_t,
1708 : const Elem * elem,
1709 : const unsigned int i,
1710 : const unsigned int j,
1711 : const Point & p)
1712 : {
1713 : libmesh_deprecated();
1714 :
1715 0 : libmesh_assert_greater_equal (dim*(dim-1),j);
1716 :
1717 0 : if (elem->infinite())
1718 0 : libmesh_not_implemented();
1719 :
1720 0 : const Order o = fe_t.order;
1721 :
1722 0 : switch(dim)
1723 : {
1724 0 : case 0:
1725 0 : fe_family_switch (0, shape_second_deriv(elem, o, i, j, p), return , ;);
1726 0 : case 1:
1727 0 : fe_family_switch (1, shape_second_deriv(elem, o, i, j, p), return , ;);
1728 0 : case 2:
1729 0 : fe_family_switch (2, shape_second_deriv(elem, o, i, j, p), return , ;);
1730 0 : case 3:
1731 0 : fe_family_switch (3, shape_second_deriv(elem, o, i, j, p), return , ;);
1732 0 : default:
1733 0 : libmesh_error_msg("Invalid dimension = " << dim);
1734 : }
1735 : return 0;
1736 : }
1737 : #endif // LIBMESH_ENABLE_DEPRECATED
1738 :
1739 :
1740 :
1741 0 : Real FEInterface::shape_second_deriv(const FEType & fe_t,
1742 : const Elem * elem,
1743 : const unsigned int i,
1744 : const unsigned int j,
1745 : const Point & p)
1746 : {
1747 0 : auto dim = elem->dim();
1748 :
1749 0 : libmesh_assert_greater_equal (dim*(dim-1),j);
1750 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1751 0 : if (is_InfFE_elem(elem->type()))
1752 0 : libmesh_not_implemented();
1753 : #endif
1754 :
1755 : // We are calling FE::shape_second_deriv() with the final argument
1756 : // == true so that the Elem::p_level() is accounted for
1757 : // automatically internally.
1758 0 : switch(dim)
1759 : {
1760 0 : case 0:
1761 0 : fe_family_switch (0, shape_second_deriv(elem, fe_t.order, i, j, p, true), return , ;);
1762 0 : case 1:
1763 0 : fe_family_switch (1, shape_second_deriv(elem, fe_t.order, i, j, p, true), return , ;);
1764 0 : case 2:
1765 0 : fe_family_switch (2, shape_second_deriv(elem, fe_t.order, i, j, p, true), return , ;);
1766 0 : case 3:
1767 0 : fe_family_switch (3, shape_second_deriv(elem, fe_t.order, i, j, p, true), return , ;);
1768 0 : default:
1769 0 : libmesh_error_msg("Invalid dimension = " << dim);
1770 : }
1771 :
1772 : // We'll never get here
1773 : return 0;
1774 : }
1775 :
1776 :
1777 :
1778 317113182 : Real FEInterface::shape_second_deriv(const FEType & fe_t,
1779 : int extra_order,
1780 : const Elem * elem,
1781 : const unsigned int i,
1782 : const unsigned int j,
1783 : const Point & p)
1784 : {
1785 317113182 : auto dim = elem->dim();
1786 :
1787 26273056 : libmesh_assert_greater_equal (dim*(dim-1),j);
1788 :
1789 78761391 : if (elem->infinite())
1790 0 : libmesh_not_implemented();
1791 :
1792 : // Ignore Elem::p_level() when computing total order, use
1793 : // extra_order instead.
1794 52546112 : auto total_order = fe_t.order + extra_order;
1795 :
1796 : // We are calling FE::shape_second_deriv() with the final argument
1797 : // == false so that the Elem::p_level() is ignored and the
1798 : // total_order we compute is used instead.
1799 317113182 : switch(dim)
1800 : {
1801 0 : case 0:
1802 0 : fe_family_switch (0, shape_second_deriv(elem, total_order, i, j, p, false), return , ;);
1803 10308 : case 1:
1804 10308 : fe_family_switch (1, shape_second_deriv(elem, total_order, i, j, p, false), return , ;);
1805 2246994 : case 2:
1806 2246994 : fe_family_switch (2, shape_second_deriv(elem, total_order, i, j, p, false), return , ;);
1807 314855880 : case 3:
1808 314855880 : fe_family_switch (3, shape_second_deriv(elem, total_order, i, j, p, false), return , ;);
1809 0 : default:
1810 0 : libmesh_error_msg("Invalid dimension = " << dim);
1811 : }
1812 :
1813 : // We'll never get here
1814 : return 0;
1815 : }
1816 :
1817 :
1818 :
1819 : #ifdef LIBMESH_ENABLE_DEPRECATED
1820 : FEInterface::shape_second_deriv_ptr
1821 0 : FEInterface::shape_second_deriv_function(const unsigned int dim,
1822 : const FEType & fe_t,
1823 : const ElemType libmesh_inf_var(t))
1824 : {
1825 : libmesh_deprecated();
1826 :
1827 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1828 0 : if (is_InfFE_elem(t))
1829 0 : libmesh_not_implemented();
1830 : #endif
1831 0 : fe_switch(shape_second_deriv);
1832 : }
1833 : #endif // LIBMESH_ENABLE_DEPRECATED
1834 :
1835 :
1836 :
1837 : FEInterface::shape_second_deriv_ptr
1838 70982232 : FEInterface::shape_second_deriv_function(const FEType & fe_t,
1839 : const Elem * elem)
1840 : {
1841 70982232 : auto dim = elem->dim();
1842 :
1843 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1844 17144266 : if (is_InfFE_elem(elem->type()))
1845 0 : libmesh_not_implemented();
1846 : #endif
1847 70982232 : fe_switch(shape_second_deriv);
1848 : }
1849 :
1850 : #endif //LIBMESH_ENABLE_SECOND_DERIVATIVES
1851 :
1852 :
1853 : #ifdef LIBMESH_ENABLE_DEPRECATED
1854 : template<>
1855 0 : void FEInterface::shape<RealGradient>(const unsigned int dim,
1856 : const FEType & fe_t,
1857 : const Elem * elem,
1858 : const unsigned int i,
1859 : const Point & p,
1860 : RealGradient & phi)
1861 : {
1862 : libmesh_deprecated();
1863 :
1864 : // This is actually an issue for infinite elements: They require type 'Gradient'!
1865 0 : if (elem->infinite())
1866 0 : libmesh_not_implemented();
1867 :
1868 0 : const Order o = fe_t.order;
1869 :
1870 0 : switch(dim)
1871 : {
1872 0 : case 0:
1873 0 : fe_vector_scalar_error_switch(0, shape(elem,o,i,p), phi = , ; break;);
1874 0 : break;
1875 0 : case 1:
1876 0 : fe_vector_scalar_error_switch(1, shape(elem,o,i,p), phi = , ; break;);
1877 0 : break;
1878 0 : case 2:
1879 0 : fe_vector_scalar_error_switch(2, shape(elem,o,i,p), phi = , ; break;);
1880 0 : break;
1881 0 : case 3:
1882 0 : fe_vector_scalar_error_switch(3, shape(elem,o,i,p), phi = , ; break;);
1883 0 : break;
1884 0 : default:
1885 0 : libmesh_error_msg("Invalid dimension = " << dim);
1886 : }
1887 :
1888 0 : return;
1889 : }
1890 : #endif // LIBMESH_ENABLE_DEPRECATED
1891 :
1892 :
1893 7793931 : void FEInterface::compute_data(const unsigned int dim,
1894 : const FEType & fe_t,
1895 : const Elem * elem,
1896 : FEComputeData & data)
1897 : {
1898 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
1899 :
1900 721454 : if (elem && is_InfFE_elem(elem->type()))
1901 : {
1902 0 : data.init();
1903 0 : ifem_compute_data(dim, fe_t, elem, data);
1904 0 : return;
1905 : }
1906 :
1907 : #endif
1908 :
1909 7793931 : const unsigned int n_dof = n_dofs (fe_t, elem);
1910 7793931 : const Point & p = data.p;
1911 7793931 : data.shape.resize(n_dof);
1912 :
1913 7793931 : if (data.need_derivative())
1914 : {
1915 0 : data.dshape.resize(n_dof);
1916 0 : data.local_transform.resize(dim);
1917 :
1918 0 : for (unsigned int d=0; d<dim; d++)
1919 0 : data.local_transform[d].resize(dim);
1920 :
1921 0 : auto fe = FEBase::build(dim, fe_t);
1922 0 : std::vector<Point> pt = {p};
1923 0 : fe->get_dphideta(); // to compute the map
1924 0 : fe->reinit(elem, &pt);
1925 :
1926 : // compute the reference->physical map.
1927 0 : data.local_transform[0][0] = fe->get_dxidx()[0];
1928 0 : if (dim > 1)
1929 : {
1930 0 : data.local_transform[1][0] = fe->get_detadx()[0];
1931 0 : data.local_transform[1][1] = fe->get_detady()[0];
1932 0 : data.local_transform[0][1] = fe->get_dxidy()[0];
1933 0 : if (dim > 2)
1934 : {
1935 0 : data.local_transform[2][0] = fe->get_dzetadx()[0];
1936 0 : data.local_transform[2][1] = fe->get_dzetady()[0];
1937 0 : data.local_transform[2][2] = fe->get_dzetadz()[0];
1938 0 : data.local_transform[1][2] = fe->get_detadz()[0];
1939 0 : data.local_transform[0][2] = fe->get_dxidz()[0];
1940 : }
1941 : }
1942 0 : }
1943 :
1944 : // set default values for all the output fields
1945 7793931 : data.init();
1946 :
1947 49189544 : for (unsigned int n=0; n<n_dof; n++)
1948 : {
1949 : // Here we pass the original fe_t object. Additional p-levels
1950 : // (if any) are handled internally by the shape() and
1951 : // shape_deriv() functions since they have access to the elem
1952 : // pointer. Note that we are already using the n_dof value
1953 : // appropriate to the elevated p-level.
1954 41395613 : data.shape[n] = shape(fe_t, elem, n, p);
1955 41395613 : if (data.need_derivative())
1956 : {
1957 0 : for (unsigned int j=0; j<dim; j++)
1958 0 : data.dshape[n](j) = shape_deriv(fe_t, elem, n, j, p);
1959 : }
1960 : }
1961 7072477 : }
1962 :
1963 :
1964 :
1965 : #ifdef LIBMESH_ENABLE_AMR
1966 :
1967 7863979 : void FEInterface::compute_constraints (DofConstraints & constraints,
1968 : DofMap & dof_map,
1969 : const unsigned int variable_number,
1970 : const Elem * elem)
1971 : {
1972 698537 : libmesh_assert(elem);
1973 :
1974 698537 : const FEType & fe_t = dof_map.variable_type(variable_number);
1975 :
1976 7863979 : switch (elem->dim())
1977 : {
1978 13356 : case 0:
1979 : case 1:
1980 : {
1981 : // No constraints in 0D/1D.
1982 13356 : return;
1983 : }
1984 :
1985 :
1986 4295201 : case 2:
1987 : {
1988 4295201 : switch (fe_t.family)
1989 : {
1990 38660 : case CLOUGH:
1991 38660 : FE<2,CLOUGH>::compute_constraints (constraints,
1992 : dof_map,
1993 : variable_number,
1994 38660 : elem); return;
1995 :
1996 18240 : case HERMITE:
1997 18240 : FE<2,HERMITE>::compute_constraints (constraints,
1998 : dof_map,
1999 : variable_number,
2000 18240 : elem); return;
2001 :
2002 3209263 : case LAGRANGE:
2003 3209263 : FE<2,LAGRANGE>::compute_constraints (constraints,
2004 : dof_map,
2005 : variable_number,
2006 3209263 : elem); return;
2007 :
2008 292412 : case HIERARCHIC:
2009 292412 : FE<2,HIERARCHIC>::compute_constraints (constraints,
2010 : dof_map,
2011 : variable_number,
2012 292412 : elem); return;
2013 :
2014 7860 : case HIERARCHIC_VEC:
2015 7860 : FE<2,HIERARCHIC_VEC>::compute_constraints (constraints,
2016 : dof_map,
2017 : variable_number,
2018 7860 : elem); return;
2019 :
2020 65168 : case SIDE_HIERARCHIC:
2021 65168 : FE<2,SIDE_HIERARCHIC>::compute_constraints (constraints,
2022 : dof_map,
2023 : variable_number,
2024 65168 : elem); return;
2025 :
2026 7256 : case LAGRANGE_VEC:
2027 7256 : FE<2,LAGRANGE_VEC>::compute_constraints (constraints,
2028 : dof_map,
2029 : variable_number,
2030 7256 : elem); return;
2031 :
2032 58726 : fe_family_horder_case_func(2, compute_constraints (constraints,
2033 : dof_map,
2034 : variable_number,
2035 : elem), , ; return;)
2036 49713 : default:
2037 49713 : return;
2038 : }
2039 : }
2040 :
2041 :
2042 3412974 : case 3:
2043 : {
2044 3412974 : switch (fe_t.family)
2045 : {
2046 156 : case HERMITE:
2047 156 : FE<3,HERMITE>::compute_constraints (constraints,
2048 : dof_map,
2049 : variable_number,
2050 156 : elem); return;
2051 :
2052 1310021 : case LAGRANGE:
2053 1310021 : FE<3,LAGRANGE>::compute_constraints (constraints,
2054 : dof_map,
2055 : variable_number,
2056 1310021 : elem); return;
2057 :
2058 30012 : case HIERARCHIC:
2059 30012 : FE<3,HIERARCHIC>::compute_constraints (constraints,
2060 : dof_map,
2061 : variable_number,
2062 30012 : elem); return;
2063 :
2064 145248 : case SIDE_HIERARCHIC:
2065 145248 : FE<3,SIDE_HIERARCHIC>::compute_constraints (constraints,
2066 : dof_map,
2067 : variable_number,
2068 145248 : elem); return;
2069 :
2070 11400 : case LAGRANGE_VEC:
2071 11400 : FE<3,LAGRANGE_VEC>::compute_constraints (constraints,
2072 : dof_map,
2073 : variable_number,
2074 11400 : elem); return;
2075 :
2076 0 : case HIERARCHIC_VEC:
2077 0 : FE<3,HIERARCHIC_VEC>::compute_constraints (constraints,
2078 : dof_map,
2079 : variable_number,
2080 0 : elem); return;
2081 :
2082 16120 : fe_family_horder_case_func(3, compute_constraints (constraints,
2083 : dof_map,
2084 : variable_number,
2085 : elem), , ; return;)
2086 154914 : default:
2087 154914 : return;
2088 : }
2089 : }
2090 :
2091 :
2092 0 : default:
2093 0 : libmesh_error_msg("Invalid dimension = " << elem->dim());
2094 : }
2095 : }
2096 :
2097 : #endif // #ifdef LIBMESH_ENABLE_AMR
2098 :
2099 :
2100 :
2101 : #ifdef LIBMESH_ENABLE_PERIODIC
2102 :
2103 264164 : void FEInterface::compute_periodic_constraints (DofConstraints & constraints,
2104 : DofMap & dof_map,
2105 : const PeriodicBoundaries & boundaries,
2106 : const MeshBase & mesh,
2107 : const PointLocatorBase * point_locator,
2108 : const unsigned int variable_number,
2109 : const Elem * elem)
2110 : {
2111 67082 : const FEType & fe_t = dof_map.variable_type(variable_number);
2112 : // No element-specific optimizations currently exist, although
2113 : // we do have to select the right compute_periodic_constraints
2114 : // for the OutputType of this FEType.
2115 264164 : switch (field_type(fe_t))
2116 : {
2117 264164 : case TYPE_SCALAR:
2118 264164 : FEBase::compute_periodic_constraints(
2119 : constraints, dof_map, boundaries, mesh, point_locator, variable_number, elem);
2120 264164 : break;
2121 0 : case TYPE_VECTOR:
2122 0 : FEVectorBase::compute_periodic_constraints(
2123 : constraints, dof_map, boundaries, mesh, point_locator, variable_number, elem);
2124 0 : break;
2125 0 : default:
2126 0 : libmesh_error_msg(
2127 : "compute_periodic_constraints only set up for vector or scalar FEFieldTypes");
2128 : }
2129 264164 : }
2130 :
2131 : #endif // #ifdef LIBMESH_ENABLE_PERIODIC
2132 :
2133 :
2134 :
2135 31314218 : unsigned int FEInterface::max_order(const FEType & fe_t,
2136 : const ElemType & el_t)
2137 : {
2138 : // Yeah, I know, infinity is much larger than 11, but our
2139 : // solvers don't seem to like high degree polynomials, and our
2140 : // quadrature rules and number_lookups tables
2141 : // need to go up higher.
2142 1917518 : const unsigned int unlimited = 11;
2143 :
2144 : // If we used 0 as a default, then elements missing from this
2145 : // table (e.g. infinite elements) would be considered broken.
2146 1917518 : const unsigned int unknown = unlimited;
2147 :
2148 31314218 : switch (fe_t.family)
2149 : {
2150 18733672 : case LAGRANGE:
2151 : case LAGRANGE_VEC:
2152 18733672 : switch (el_t)
2153 : {
2154 121838 : case EDGE2:
2155 : case EDGE3:
2156 : case EDGE4:
2157 121838 : return 3;
2158 229940 : case TRI3:
2159 : case TRISHELL3:
2160 : case C0POLYGON:
2161 229940 : return 1;
2162 7896 : case TRI6:
2163 7896 : return 2;
2164 856 : case TRI7:
2165 856 : return 3;
2166 458168 : case QUAD4:
2167 : case QUADSHELL4:
2168 458168 : return 1;
2169 159952 : case QUAD8:
2170 : case QUADSHELL8:
2171 : case QUAD9:
2172 : case QUADSHELL9:
2173 159952 : return 2;
2174 78044 : case TET4:
2175 78044 : return 1;
2176 2976 : case TET10:
2177 2976 : return 2;
2178 3648 : case TET14:
2179 3648 : return 3;
2180 129848 : case HEX8:
2181 129848 : return 1;
2182 8452 : case HEX20:
2183 : case HEX27:
2184 8452 : return 2;
2185 4328 : case PRISM6:
2186 4328 : return 1;
2187 4672 : case PRISM15:
2188 : case PRISM18:
2189 4672 : return 2;
2190 2376 : case PRISM20:
2191 : case PRISM21:
2192 2376 : return 3;
2193 1848 : case PYRAMID5:
2194 1848 : return 1;
2195 1008 : case PYRAMID13:
2196 : case PYRAMID14:
2197 1008 : return 2;
2198 672 : case PYRAMID18:
2199 672 : return 3;
2200 52 : case C0POLYHEDRON:
2201 52 : return 1;
2202 4716 : default:
2203 4716 : return unknown;
2204 : }
2205 : break;
2206 14040 : case L2_LAGRANGE_GLL:
2207 14040 : switch (el_t)
2208 : {
2209 1872 : case EDGE2:
2210 : case EDGE3:
2211 : case EDGE4:
2212 : case QUAD4:
2213 : case QUADSHELL4:
2214 : case QUAD8:
2215 : case QUADSHELL8:
2216 : case QUAD9:
2217 : case QUADSHELL9:
2218 : case HEX8:
2219 : case HEX20:
2220 : case HEX27:
2221 : // A basis of degree p needs p+1 Gauss-Lobatto points, and QGaussLobatto tabulates
2222 : // at most fe_lagrange_gll_max_points_1D
2223 1872 : return fe_lagrange_gll_max_points_1D - 1;
2224 0 : default:
2225 0 : return unknown;
2226 : }
2227 : break;
2228 660808 : case MONOMIAL:
2229 : case L2_LAGRANGE:
2230 : case L2_LAGRANGE_VEC:
2231 : case L2_HIERARCHIC:
2232 : case L2_HIERARCHIC_VEC:
2233 : case MONOMIAL_VEC:
2234 330404 : switch (el_t)
2235 : {
2236 330396 : case EDGE2:
2237 : case EDGE3:
2238 : case EDGE4:
2239 : case C0POLYGON:
2240 : case TRI3:
2241 : case TRISHELL3:
2242 : case TRI6:
2243 : case TRI7:
2244 : case QUAD4:
2245 : case QUADSHELL4:
2246 : case QUAD8:
2247 : case QUADSHELL8:
2248 : case QUAD9:
2249 : case QUADSHELL9:
2250 : case TET4:
2251 : case TET10:
2252 : case TET14:
2253 : case HEX8:
2254 : case HEX20:
2255 : case HEX27:
2256 : case PRISM6:
2257 : case PRISM15:
2258 : case PRISM18:
2259 : case PRISM20:
2260 : case PRISM21:
2261 : case PYRAMID5:
2262 : case PYRAMID13:
2263 : case PYRAMID14:
2264 : case PYRAMID18:
2265 : case C0POLYHEDRON:
2266 330396 : return unlimited;
2267 8 : default:
2268 8 : return unknown;
2269 : }
2270 : break;
2271 : #ifdef LIBMESH_ENABLE_HIGHER_ORDER_SHAPES
2272 383476 : case BERNSTEIN:
2273 : case RATIONAL_BERNSTEIN:
2274 383476 : switch (el_t)
2275 : {
2276 312 : case EDGE2:
2277 : case EDGE3:
2278 : case EDGE4:
2279 312 : return unlimited;
2280 208 : case TRI3:
2281 : case TRISHELL3:
2282 208 : return 1;
2283 624 : case TRI6:
2284 : case TRI7:
2285 624 : return 6;
2286 104 : case QUAD4:
2287 : case QUADSHELL4:
2288 104 : return 1;
2289 7392 : case QUAD8:
2290 : case QUADSHELL8:
2291 : case QUAD9:
2292 : case QUADSHELL9:
2293 7392 : return unlimited;
2294 2496 : case TET4:
2295 2496 : return 1;
2296 2496 : case TET10:
2297 : case TET14:
2298 2496 : return 2;
2299 104 : case HEX8:
2300 104 : return 1;
2301 0 : case HEX20:
2302 0 : return 2;
2303 2920 : case HEX27:
2304 2920 : return 4;
2305 0 : case C0POLYGON:
2306 : case PRISM6:
2307 : case PRISM15:
2308 : case PRISM18:
2309 : case PRISM20:
2310 : case PRISM21:
2311 : case PYRAMID5:
2312 : case PYRAMID13:
2313 : case PYRAMID14:
2314 : case PYRAMID18:
2315 : case C0POLYHEDRON:
2316 0 : return 0;
2317 9668 : default:
2318 9668 : return unknown;
2319 : }
2320 : break;
2321 12588 : case SZABAB:
2322 12588 : switch (el_t)
2323 : {
2324 52 : case EDGE2:
2325 52 : return 1;
2326 156 : case EDGE3:
2327 : case EDGE4:
2328 156 : return 7;
2329 104 : case TRI3:
2330 : case TRISHELL3:
2331 104 : return 1;
2332 688 : case TRI6:
2333 : case TRI7:
2334 688 : return 7;
2335 52 : case QUAD4:
2336 : case QUADSHELL4:
2337 52 : return 1;
2338 156 : case QUAD8:
2339 : case QUADSHELL8:
2340 : case QUAD9:
2341 : case QUADSHELL9:
2342 156 : return 7;
2343 0 : case C0POLYGON:
2344 : case TET4:
2345 : case TET10:
2346 : case TET14:
2347 : case HEX8:
2348 : case HEX20:
2349 : case HEX27:
2350 : case PRISM6:
2351 : case PRISM15:
2352 : case PRISM18:
2353 : case PRISM20:
2354 : case PRISM21:
2355 : case PYRAMID5:
2356 : case PYRAMID13:
2357 : case PYRAMID14:
2358 : case PYRAMID18:
2359 : case C0POLYHEDRON:
2360 0 : return 0;
2361 0 : default:
2362 0 : return unknown;
2363 : }
2364 : break;
2365 : #endif
2366 50720 : case XYZ:
2367 25360 : switch (el_t)
2368 : {
2369 25360 : case EDGE2:
2370 : case EDGE3:
2371 : case EDGE4:
2372 : case C0POLYGON:
2373 : case TRI3:
2374 : case TRISHELL3:
2375 : case TRI6:
2376 : case TRI7:
2377 : case QUAD4:
2378 : case QUADSHELL4:
2379 : case QUAD8:
2380 : case QUADSHELL8:
2381 : case QUAD9:
2382 : case QUADSHELL9:
2383 : case TET4:
2384 : case TET10:
2385 : case TET14:
2386 : case HEX8:
2387 : case HEX20:
2388 : case HEX27:
2389 : case PRISM6:
2390 : case PRISM15:
2391 : case PRISM18:
2392 : case PRISM20:
2393 : case PRISM21:
2394 : case PYRAMID5:
2395 : case PYRAMID13:
2396 : case PYRAMID14:
2397 : case PYRAMID18:
2398 : case C0POLYHEDRON:
2399 25360 : return unlimited;
2400 0 : default:
2401 0 : return unknown;
2402 : }
2403 : break;
2404 112492 : case CLOUGH:
2405 112492 : switch (el_t)
2406 : {
2407 0 : case EDGE2:
2408 : case EDGE3:
2409 0 : return 3;
2410 0 : case EDGE4:
2411 : case TRI3:
2412 : case TRISHELL3:
2413 0 : return 0;
2414 9900 : case TRI6:
2415 : case TRI7:
2416 9900 : return 3;
2417 0 : case C0POLYGON:
2418 : case QUAD4:
2419 : case QUADSHELL4:
2420 : case QUAD8:
2421 : case QUADSHELL8:
2422 : case QUAD9:
2423 : case QUADSHELL9:
2424 : case TET4:
2425 : case TET10:
2426 : case TET14:
2427 : case HEX8:
2428 : case HEX20:
2429 : case HEX27:
2430 : case PRISM6:
2431 : case PRISM15:
2432 : case PRISM18:
2433 : case PRISM20:
2434 : case PRISM21:
2435 : case PYRAMID5:
2436 : case PYRAMID13:
2437 : case PYRAMID14:
2438 : case PYRAMID18:
2439 : case C0POLYHEDRON:
2440 0 : return 0;
2441 0 : default:
2442 0 : return unknown;
2443 : }
2444 : break;
2445 667232 : case HERMITE:
2446 667232 : switch (el_t)
2447 : {
2448 21152 : case EDGE2:
2449 : case EDGE3:
2450 21152 : return unlimited;
2451 0 : case EDGE4:
2452 : case TRI3:
2453 : case TRISHELL3:
2454 : case TRI6:
2455 : case TRI7:
2456 0 : return 0;
2457 0 : case QUAD4:
2458 : case QUADSHELL4:
2459 0 : return 3;
2460 4596 : case QUAD8:
2461 : case QUADSHELL8:
2462 : case QUAD9:
2463 : case QUADSHELL9:
2464 4596 : return unlimited;
2465 0 : case TET4:
2466 : case TET10:
2467 : case TET14:
2468 0 : return 0;
2469 0 : case HEX8:
2470 0 : return 3;
2471 52 : case HEX20:
2472 : case HEX27:
2473 52 : return unlimited;
2474 0 : case C0POLYGON:
2475 : case PRISM6:
2476 : case PRISM15:
2477 : case PRISM18:
2478 : case PRISM20:
2479 : case PRISM21:
2480 : case PYRAMID5:
2481 : case PYRAMID13:
2482 : case PYRAMID14:
2483 : case PYRAMID18:
2484 : case C0POLYHEDRON:
2485 0 : return 0;
2486 0 : default:
2487 0 : return unknown;
2488 : }
2489 : break;
2490 2843630 : case HIERARCHIC:
2491 : case HIERARCHIC_VEC:
2492 2843630 : switch (el_t)
2493 : {
2494 856 : case EDGE2:
2495 : case EDGE3:
2496 : case EDGE4:
2497 856 : return unlimited;
2498 104 : case TRI3:
2499 : case TRISHELL3:
2500 104 : return 1;
2501 27576 : case TRI6:
2502 : case TRI7:
2503 27576 : return unlimited;
2504 52 : case QUAD4:
2505 : case QUADSHELL4:
2506 52 : return 1;
2507 42068 : case QUAD8:
2508 : case QUADSHELL8:
2509 : case QUAD9:
2510 : case QUADSHELL9:
2511 42068 : return unlimited;
2512 1248 : case TET4:
2513 1248 : return 1;
2514 1248 : case TET10:
2515 1248 : return 2;
2516 4040 : case TET14:
2517 4040 : return unlimited;
2518 52 : case HEX8:
2519 : case HEX20:
2520 52 : return 1;
2521 2308 : case HEX27:
2522 2308 : return unlimited;
2523 1080 : case PRISM6:
2524 : case PRISM15:
2525 : case PRISM18:
2526 : case PRISM20:
2527 : case PRISM21:
2528 1080 : return unlimited;
2529 0 : case C0POLYGON:
2530 : case PYRAMID5:
2531 : case PYRAMID13:
2532 : case PYRAMID14:
2533 : case PYRAMID18:
2534 : case C0POLYHEDRON:
2535 0 : return 0;
2536 0 : default:
2537 0 : return unknown;
2538 : }
2539 : break;
2540 1157596 : case SIDE_HIERARCHIC:
2541 1157596 : switch (el_t)
2542 : {
2543 264 : case EDGE2:
2544 : case EDGE3:
2545 : case EDGE4:
2546 264 : return unlimited; // although it's all the same as 0...
2547 0 : case TRI3:
2548 : case TRISHELL3:
2549 0 : return 0;
2550 18568 : case TRI6:
2551 : case TRI7:
2552 18568 : return unlimited;
2553 0 : case C0POLYGON:
2554 : case QUAD4:
2555 : case QUADSHELL4:
2556 0 : return 0;
2557 2728 : case QUAD8:
2558 : case QUADSHELL8:
2559 : case QUAD9:
2560 : case QUADSHELL9:
2561 2728 : return unlimited;
2562 0 : case TET4:
2563 : case TET10:
2564 0 : return 0;
2565 43776 : case TET14:
2566 43776 : return unlimited;
2567 0 : case HEX8:
2568 : case HEX20:
2569 0 : return 0;
2570 1440 : case HEX27:
2571 1440 : return unlimited;
2572 0 : case PRISM6:
2573 : case PRISM15:
2574 : case PRISM18:
2575 0 : return 0;
2576 3200 : case PRISM20:
2577 : case PRISM21:
2578 3200 : return unlimited;
2579 0 : case PYRAMID5:
2580 : case PYRAMID13:
2581 : case PYRAMID14:
2582 : case PYRAMID18:
2583 : case C0POLYHEDRON:
2584 0 : return 0;
2585 0 : default:
2586 0 : return unknown;
2587 : }
2588 : break;
2589 2592 : case SUBDIVISION:
2590 1296 : switch (el_t)
2591 : {
2592 1296 : case TRI3SUBDIVISION:
2593 1296 : return unlimited;
2594 0 : default:
2595 0 : return unknown;
2596 : }
2597 : break;
2598 386618 : case NEDELEC_ONE:
2599 386618 : switch (el_t)
2600 : {
2601 11632 : case TRI6:
2602 : case TRI7:
2603 : case QUAD8:
2604 : case QUAD9:
2605 11632 : return 5;
2606 6400 : case TET10:
2607 : case TET14:
2608 : case HEX20:
2609 : case HEX27:
2610 6400 : return 1;
2611 0 : default:
2612 0 : return 0;
2613 : }
2614 : break;
2615 1514630 : case RAVIART_THOMAS:
2616 : case L2_RAVIART_THOMAS:
2617 1514630 : switch (el_t)
2618 : {
2619 33200 : case TRI6:
2620 : case TRI7:
2621 : case QUAD8:
2622 : case QUAD9:
2623 33200 : return 5;
2624 74872 : case TET14:
2625 : case HEX27:
2626 74872 : return 1;
2627 0 : default:
2628 0 : return 0;
2629 : }
2630 : break;
2631 0 : default:
2632 0 : return 0;
2633 : break;
2634 : }
2635 : }
2636 :
2637 :
2638 :
2639 320718417 : bool FEInterface::extra_hanging_dofs(const FEType & fe_t)
2640 : {
2641 320718417 : switch (fe_t.family)
2642 : {
2643 19662019 : case LAGRANGE:
2644 : case L2_LAGRANGE:
2645 : case L2_LAGRANGE_GLL:
2646 : case MONOMIAL:
2647 : case MONOMIAL_VEC:
2648 : case L2_HIERARCHIC:
2649 : case SIDE_HIERARCHIC:
2650 : case XYZ:
2651 : case SUBDIVISION:
2652 : case LAGRANGE_VEC:
2653 : case L2_LAGRANGE_VEC:
2654 : case NEDELEC_ONE:
2655 : case RAVIART_THOMAS:
2656 : case L2_RAVIART_THOMAS:
2657 19662019 : return false;
2658 92347059 : case CLOUGH:
2659 : case HERMITE:
2660 : case HIERARCHIC:
2661 : case HIERARCHIC_VEC:
2662 : case L2_HIERARCHIC_VEC:
2663 : fe_family_horder_case()
2664 : default:
2665 92347059 : return true;
2666 : }
2667 : }
2668 :
2669 3333426 : FEFieldType FEInterface::field_type(const FEType & fe_type)
2670 : {
2671 3333426 : return FEInterface::field_type(fe_type.family);
2672 : }
2673 :
2674 36469023 : FEFieldType FEInterface::field_type (const FEFamily & fe_family)
2675 : {
2676 36469023 : switch (fe_family)
2677 : {
2678 8317 : fe_family_vector_case()
2679 8317 : return TYPE_VECTOR;
2680 36182936 : default:
2681 36182936 : return TYPE_SCALAR;
2682 : }
2683 : }
2684 :
2685 123975797 : bool FEInterface::orientation_dependent (const FEFamily & fe_family)
2686 : {
2687 123975797 : switch (fe_family)
2688 : {
2689 604848 : case HIERARCHIC:
2690 : case L2_HIERARCHIC:
2691 : case HIERARCHIC_VEC:
2692 : case L2_HIERARCHIC_VEC:
2693 : case BERNSTEIN:
2694 : case RATIONAL_BERNSTEIN:
2695 : case SZABAB:
2696 : case NEDELEC_ONE:
2697 : case RAVIART_THOMAS:
2698 604848 : return true;
2699 106718257 : default:
2700 106718257 : return false;
2701 : }
2702 : }
2703 :
2704 32962742 : unsigned int FEInterface::n_vec_dim (const MeshBase & mesh,
2705 : const FEType & fe_type)
2706 : {
2707 : // We assume the number of vector components is the mesh spatial dimension.
2708 32962742 : return field_type(fe_type.family) == TYPE_VECTOR ? mesh.spatial_dimension() : 1;
2709 : }
2710 :
2711 :
2712 :
2713 :
2714 : bool
2715 6850 : FEInterface::is_hierarchic (const FEType & fe_type)
2716 : {
2717 6850 : switch (fe_type.family)
2718 : {
2719 284 : case HERMITE:
2720 : case HIERARCHIC:
2721 : case HIERARCHIC_VEC:
2722 : case L2_HIERARCHIC:
2723 : case L2_HIERARCHIC_VEC:
2724 : case MONOMIAL:
2725 : case MONOMIAL_VEC:
2726 : case SIDE_HIERARCHIC:
2727 : case SZABAB:
2728 : case XYZ:
2729 284 : return true;
2730 :
2731 2726 : case BERNSTEIN:
2732 : case CLOUGH: // maybe some day?
2733 : case LAGRANGE:
2734 : case LAGRANGE_VEC:
2735 : case L2_LAGRANGE:
2736 : case L2_LAGRANGE_GLL:
2737 : case L2_LAGRANGE_VEC:
2738 : case NEDELEC_ONE:
2739 : case RATIONAL_BERNSTEIN:
2740 : case RAVIART_THOMAS:
2741 : case L2_RAVIART_THOMAS:
2742 : case SCALAR:
2743 : case SUBDIVISION:
2744 2726 : return false;
2745 :
2746 0 : default:
2747 0 : libmesh_error_msg("Unknown FE Family " << Utility::enum_to_string(fe_type.family));
2748 : }
2749 : }
2750 :
2751 :
2752 :
2753 15112033 : FEContinuity FEInterface::get_continuity(const FEType & fe_type)
2754 : {
2755 15112033 : switch (fe_type.family)
2756 : {
2757 : // Discontinuous elements
2758 12784 : case MONOMIAL:
2759 : case MONOMIAL_VEC:
2760 : case L2_HIERARCHIC:
2761 : case L2_LAGRANGE:
2762 : case L2_LAGRANGE_GLL:
2763 : case XYZ:
2764 : case SCALAR:
2765 : case L2_RAVIART_THOMAS:
2766 : case L2_HIERARCHIC_VEC:
2767 : case L2_LAGRANGE_VEC:
2768 12784 : return DISCONTINUOUS;
2769 :
2770 : // C0 elements
2771 14580256 : case LAGRANGE:
2772 : case HIERARCHIC:
2773 : case BERNSTEIN:
2774 : case SZABAB:
2775 : case RATIONAL_BERNSTEIN:
2776 : case INFINITE_MAP:
2777 : case JACOBI_20_00:
2778 : case JACOBI_30_00:
2779 : case LEGENDRE:
2780 : case LAGRANGE_VEC:
2781 : case HIERARCHIC_VEC:
2782 14580256 : return C_ZERO;
2783 :
2784 : // C1 elements
2785 31988 : case CLOUGH:
2786 : case HERMITE:
2787 : case SUBDIVISION:
2788 31988 : return C_ONE;
2789 :
2790 3536 : case NEDELEC_ONE:
2791 3536 : return H_CURL;
2792 :
2793 6720 : case RAVIART_THOMAS:
2794 6720 : return H_DIV;
2795 :
2796 : // Side elements
2797 47478 : case SIDE_HIERARCHIC:
2798 47478 : return SIDE_DISCONTINUOUS;
2799 :
2800 0 : default:
2801 0 : libmesh_error_msg("Unknown FE Family " << Utility::enum_to_string(fe_type.family));
2802 : }
2803 : }
2804 :
2805 :
2806 : } // namespace libMesh
|