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