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