1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2020 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 // Local includes
19 #include "libmesh/dof_map.h"
20 #include "libmesh/fe.h"
21 #include "libmesh/fe_interface.h"
22 #include "libmesh/elem.h"
23 #include "libmesh/tensor_value.h"
24
25
26 namespace libMesh
27 {
28
29
30 LIBMESH_DEFAULT_VECTORIZED_FE(0,MONOMIAL_VEC)
31 LIBMESH_DEFAULT_VECTORIZED_FE(1,MONOMIAL_VEC)
32 LIBMESH_DEFAULT_VECTORIZED_FE(2,MONOMIAL_VEC)
33 LIBMESH_DEFAULT_VECTORIZED_FE(3,MONOMIAL_VEC)
34
35
36 // ------------------------------------------------------------
37 // Vector monomial specific implementations
38
39 // Anonymous namespace for local helper functions
40 namespace
41 {
42 void
monomial_vec_nodal_soln(const Elem * elem,const Order order,const std::vector<Number> & elem_soln,const int dim,std::vector<Number> & nodal_soln)43 monomial_vec_nodal_soln(const Elem * elem,
44 const Order order,
45 const std::vector<Number> & elem_soln,
46 const int dim,
47 std::vector<Number> & nodal_soln)
48 {
49 const unsigned int n_nodes = elem->n_nodes();
50
51 const ElemType elem_type = elem->type();
52
53 nodal_soln.resize(dim * n_nodes);
54
55 const Order totalorder = static_cast<Order>(order + elem->p_level());
56
57 switch (totalorder)
58 {
59 // Constant shape functions
60 case CONSTANT:
61 {
62 switch (dim)
63 {
64 case 2:
65 {
66 libmesh_assert_equal_to(elem_soln.size(), 2);
67 for (unsigned int n = 0; n < n_nodes; n++)
68 {
69 nodal_soln[2 * n] = elem_soln[0];
70 nodal_soln[1 + 2 * n] = elem_soln[1];
71 }
72 return;
73 }
74 case 3:
75 {
76 libmesh_assert_equal_to(elem_soln.size(), 3);
77 for (unsigned int n = 0; n < n_nodes; n++)
78 {
79 nodal_soln[3 * n] = elem_soln[0];
80 nodal_soln[1 + 3 * n] = elem_soln[1];
81 nodal_soln[2 + 3 * n] = elem_soln[2];
82 }
83 return;
84 }
85 default:
86 libmesh_error_msg(
87 "The monomial_vec_nodal_soln helper should only be called for 2 and 3 dimensions");
88 }
89 }
90
91 // For other orders, do interpolation at the nodes
92 // explicitly.
93 default:
94 {
95 // FEType object to be passed to various FEInterface functions below.
96 FEType fe_type(order, MONOMIAL);
97
98 const unsigned int n_sf = FEInterface::n_shape_functions(fe_type, elem);
99
100 std::vector<Point> refspace_nodes;
101 FEBase::get_refspace_nodes(elem_type, refspace_nodes);
102 libmesh_assert_equal_to(refspace_nodes.size(), n_nodes);
103 libmesh_assert_equal_to(elem_soln.size(), n_sf * dim);
104
105 for (unsigned int d = 0; d < static_cast<unsigned int>(dim); d++)
106 for (unsigned int n = 0; n < n_nodes; n++)
107 {
108
109 // Zero before summation
110 nodal_soln[d + dim * n] = 0;
111
112 // u_i = Sum (alpha_i phi_i)
113 for (unsigned int i = 0; i < n_sf; i++)
114 nodal_soln[d + dim * n] += elem_soln[d + dim * i] *
115 FEInterface::shape(fe_type, elem, i, refspace_nodes[n]);
116 }
117
118 return;
119 } // default
120 } // switch
121 }
122 } // anonymous namespace
123
124 // Do full-specialization for every dimension, instead
125 // of explicit instantiation at the end of this file.
126 // This could be macro-ified so that it fits on one line...
127 template <>
128 void
nodal_soln(const Elem * elem,const Order order,const std::vector<Number> & elem_soln,std::vector<Number> & nodal_soln)129 FE<0, MONOMIAL_VEC>::nodal_soln(const Elem * elem,
130 const Order order,
131 const std::vector<Number> & elem_soln,
132 std::vector<Number> & nodal_soln)
133 {
134 FE<0, MONOMIAL>::nodal_soln(elem, order, elem_soln, nodal_soln);
135 }
136
137 template <>
138 void
nodal_soln(const Elem * elem,const Order order,const std::vector<Number> & elem_soln,std::vector<Number> & nodal_soln)139 FE<1, MONOMIAL_VEC>::nodal_soln(const Elem * elem,
140 const Order order,
141 const std::vector<Number> & elem_soln,
142 std::vector<Number> & nodal_soln)
143 {
144 FE<1, MONOMIAL>::nodal_soln(elem, order, elem_soln, nodal_soln);
145 }
146
147 template <>
148 void
nodal_soln(const Elem * elem,const Order order,const std::vector<Number> & elem_soln,std::vector<Number> & nodal_soln)149 FE<2, MONOMIAL_VEC>::nodal_soln(const Elem * elem,
150 const Order order,
151 const std::vector<Number> & elem_soln,
152 std::vector<Number> & nodal_soln)
153 {
154 monomial_vec_nodal_soln(elem, order, elem_soln, 2 /*dimension*/, nodal_soln);
155 }
156
157 template <>
158 void
nodal_soln(const Elem * elem,const Order order,const std::vector<Number> & elem_soln,std::vector<Number> & nodal_soln)159 FE<3, MONOMIAL_VEC>::nodal_soln(const Elem * elem,
160 const Order order,
161 const std::vector<Number> & elem_soln,
162 std::vector<Number> & nodal_soln)
163 {
164 monomial_vec_nodal_soln(elem, order, elem_soln, 3 /*dimension*/, nodal_soln);
165 }
166
167 // Specialize for shape function routines by leveraging scalar MONOMIAL elements
168
169 // 0-D
170 template <>
171 RealVectorValue
shape(const ElemType type,const Order order,const unsigned int i,const Point & p)172 FE<0, MONOMIAL_VEC>::shape(const ElemType type,
173 const Order order,
174 const unsigned int i,
175 const Point & p)
176 {
177 Real value = FE<0, MONOMIAL>::shape(type, order, i, p);
178 return libMesh::RealVectorValue(value);
179 }
180 template <>
181 RealVectorValue
shape_deriv(const ElemType type,const Order order,const unsigned int i,const unsigned int j,const Point & p)182 FE<0, MONOMIAL_VEC>::shape_deriv(const ElemType type,
183 const Order order,
184 const unsigned int i,
185 const unsigned int j,
186 const Point & p)
187 {
188 Real value = FE<0, MONOMIAL>::shape_deriv(type, order, i, j, p);
189 return libMesh::RealVectorValue(value);
190 }
191
192 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
193
194 template <>
195 RealVectorValue
shape_second_deriv(const ElemType type,const Order order,const unsigned int i,const unsigned int j,const Point & p)196 FE<0, MONOMIAL_VEC>::shape_second_deriv(const ElemType type,
197 const Order order,
198 const unsigned int i,
199 const unsigned int j,
200 const Point & p)
201 {
202 Real value = FE<0, MONOMIAL>::shape_second_deriv(type, order, i, j, p);
203 return libMesh::RealVectorValue(value);
204 }
205 #endif
206
207 // 1-D
208 template <>
209 RealVectorValue
shape(const ElemType type,const Order order,const unsigned int i,const Point & p)210 FE<1, MONOMIAL_VEC>::shape(const ElemType type,
211 const Order order,
212 const unsigned int i,
213 const Point & p)
214 {
215 Real value = FE<1, MONOMIAL>::shape(type, order, i, p);
216 return libMesh::RealVectorValue(value);
217 }
218 template <>
219 RealVectorValue
shape_deriv(const ElemType type,const Order order,const unsigned int i,const unsigned int j,const Point & p)220 FE<1, MONOMIAL_VEC>::shape_deriv(const ElemType type,
221 const Order order,
222 const unsigned int i,
223 const unsigned int j,
224 const Point & p)
225 {
226 Real value = FE<1, MONOMIAL>::shape_deriv(type, order, i, j, p);
227 return libMesh::RealVectorValue(value);
228 }
229 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
230 template <>
231 RealVectorValue
shape_second_deriv(const ElemType type,const Order order,const unsigned int i,const unsigned int j,const Point & p)232 FE<1, MONOMIAL_VEC>::shape_second_deriv(const ElemType type,
233 const Order order,
234 const unsigned int i,
235 const unsigned int j,
236 const Point & p)
237 {
238 Real value = FE<1, MONOMIAL>::shape_second_deriv(type, order, i, j, p);
239 return libMesh::RealVectorValue(value);
240 }
241
242 #endif
243
244 // 2-D
245 template <>
246 RealVectorValue
shape(const ElemType type,const Order order,const unsigned int i,const Point & p)247 FE<2, MONOMIAL_VEC>::shape(const ElemType type,
248 const Order order,
249 const unsigned int i,
250 const Point & p)
251 {
252 Real value = FE<2, MONOMIAL>::shape(type, order, i / 2, p);
253
254 switch (i % 2)
255 {
256 case 0:
257 return libMesh::RealVectorValue(value);
258
259 case 1:
260 return libMesh::RealVectorValue(Real(0), value);
261
262 default:
263 libmesh_error_msg("i%2 must be either 0 or 1!");
264 }
265
266 // dummy
267 return libMesh::RealVectorValue();
268 }
269 template <>
270 RealVectorValue
shape_deriv(const ElemType type,const Order order,const unsigned int i,const unsigned int j,const Point & p)271 FE<2, MONOMIAL_VEC>::shape_deriv(const ElemType type,
272 const Order order,
273 const unsigned int i,
274 const unsigned int j,
275 const Point & p)
276 {
277 Real value = FE<2, MONOMIAL>::shape_deriv(type, order, i / 2, j, p);
278
279 switch (i % 2)
280 {
281 case 0:
282 return libMesh::RealVectorValue(value);
283
284 case 1:
285 return libMesh::RealVectorValue(Real(0), value);
286
287 default:
288 libmesh_error_msg("i%2 must be either 0 or 1!");
289 }
290
291 // dummy
292 return libMesh::RealVectorValue();
293 }
294
295 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
296 template <>
297 RealVectorValue
shape_second_deriv(const ElemType type,const Order order,const unsigned int i,const unsigned int j,const Point & p)298 FE<2, MONOMIAL_VEC>::shape_second_deriv(const ElemType type,
299 const Order order,
300 const unsigned int i,
301 const unsigned int j,
302 const Point & p)
303 {
304 Real value = FE<2, MONOMIAL>::shape_second_deriv(type, order, i / 2, j, p);
305
306 switch (i % 2)
307 {
308 case 0:
309 return libMesh::RealVectorValue(value);
310
311 case 1:
312 return libMesh::RealVectorValue(Real(0), value);
313
314 default:
315 libmesh_error_msg("i%2 must be either 0 or 1!");
316 }
317
318 // dummy
319 return libMesh::RealVectorValue();
320 }
321
322 #endif
323
324 // 3-D
325 template <>
326 RealVectorValue
shape(const ElemType type,const Order order,const unsigned int i,const Point & p)327 FE<3, MONOMIAL_VEC>::shape(const ElemType type,
328 const Order order,
329 const unsigned int i,
330 const Point & p)
331 {
332 Real value = FE<3, MONOMIAL>::shape(type, order, i / 3, p);
333
334 switch (i % 3)
335 {
336 case 0:
337 return libMesh::RealVectorValue(value);
338
339 case 1:
340 return libMesh::RealVectorValue(Real(0), value);
341
342 case 2:
343 return libMesh::RealVectorValue(Real(0), Real(0), value);
344
345 default:
346 libmesh_error_msg("i%3 must be 0, 1, or 2!");
347 }
348
349 // dummy
350 return libMesh::RealVectorValue();
351 }
352 template <>
353 RealVectorValue
shape_deriv(const ElemType type,const Order order,const unsigned int i,const unsigned int j,const Point & p)354 FE<3, MONOMIAL_VEC>::shape_deriv(const ElemType type,
355 const Order order,
356 const unsigned int i,
357 const unsigned int j,
358 const Point & p)
359 {
360 Real value = FE<3, MONOMIAL>::shape_deriv(type, order, i / 3, j, p);
361
362 switch (i % 3)
363 {
364 case 0:
365 return libMesh::RealVectorValue(value);
366
367 case 1:
368 return libMesh::RealVectorValue(Real(0), value);
369
370 case 2:
371 return libMesh::RealVectorValue(Real(0), Real(0), value);
372
373 default:
374 libmesh_error_msg("i%3 must be 0, 1, or 2!");
375 }
376
377 // dummy
378 return libMesh::RealVectorValue();
379 }
380
381 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
382
383 template <>
384 RealVectorValue
shape_second_deriv(const ElemType type,const Order order,const unsigned int i,const unsigned int j,const Point & p)385 FE<3, MONOMIAL_VEC>::shape_second_deriv(const ElemType type,
386 const Order order,
387 const unsigned int i,
388 const unsigned int j,
389 const Point & p)
390 {
391 Real value = FE<3, MONOMIAL>::shape_second_deriv(type, order, i / 3, j, p);
392
393 switch (i % 3)
394 {
395 case 0:
396 return libMesh::RealVectorValue(value);
397
398 case 1:
399 return libMesh::RealVectorValue(Real(0), value);
400
401 case 2:
402 return libMesh::RealVectorValue(Real(0), Real(0), value);
403
404 default:
405 libmesh_error_msg("i%3 must be 0, 1, or 2!");
406 }
407
408 // dummy
409 return libMesh::RealVectorValue();
410 }
411
412 #endif
413
414 // 0-D
415 template <>
416 RealVectorValue
shape(const Elem * elem,const Order order,const unsigned int i,const Point & p,const bool add_p_level)417 FE<0, MONOMIAL_VEC>::shape(const Elem * elem,
418 const Order order,
419 const unsigned int i,
420 const Point & p,
421 const bool add_p_level)
422 {
423 Real value =
424 FE<0, MONOMIAL>::shape(elem->type(), static_cast<Order>(order + add_p_level * elem->p_level()), i, p);
425 return libMesh::RealVectorValue(value);
426 }
427 template <>
428 RealVectorValue
shape_deriv(const Elem * elem,const Order order,const unsigned int i,const unsigned int j,const Point & p,const bool add_p_level)429 FE<0, MONOMIAL_VEC>::shape_deriv(const Elem * elem,
430 const Order order,
431 const unsigned int i,
432 const unsigned int j,
433 const Point & p,
434 const bool add_p_level)
435 {
436 Real value = FE<0, MONOMIAL>::shape_deriv(
437 elem->type(), static_cast<Order>(order + add_p_level * elem->p_level()), i, j, p);
438 return libMesh::RealVectorValue(value);
439 }
440
441 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
442
443 template <>
444 RealVectorValue
shape_second_deriv(const Elem * elem,const Order order,const unsigned int i,const unsigned int j,const Point & p,const bool add_p_level)445 FE<0, MONOMIAL_VEC>::shape_second_deriv(const Elem * elem,
446 const Order order,
447 const unsigned int i,
448 const unsigned int j,
449 const Point & p,
450 const bool add_p_level)
451 {
452 Real value = FE<0, MONOMIAL>::shape_second_deriv(
453 elem->type(), static_cast<Order>(order + add_p_level * elem->p_level()), i, j, p);
454 return libMesh::RealVectorValue(value);
455 }
456
457 #endif
458
459 // 1-D
460 template <>
461 RealVectorValue
shape(const Elem * elem,const Order order,const unsigned int i,const Point & p,const bool add_p_level)462 FE<1, MONOMIAL_VEC>::shape(const Elem * elem,
463 const Order order,
464 const unsigned int i,
465 const Point & p,
466 const bool add_p_level)
467 {
468 Real value =
469 FE<1, MONOMIAL>::shape(elem->type(), static_cast<Order>(order + add_p_level * elem->p_level()), i, p);
470 return libMesh::RealVectorValue(value);
471 }
472 template <>
473 RealVectorValue
shape_deriv(const Elem * elem,const Order order,const unsigned int i,const unsigned int j,const Point & p,const bool add_p_level)474 FE<1, MONOMIAL_VEC>::shape_deriv(const Elem * elem,
475 const Order order,
476 const unsigned int i,
477 const unsigned int j,
478 const Point & p,
479 const bool add_p_level)
480 {
481 Real value = FE<1, MONOMIAL>::shape_deriv(
482 elem->type(), static_cast<Order>(order + add_p_level * elem->p_level()), i, j, p);
483 return libMesh::RealVectorValue(value);
484 }
485
486 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
487 template <>
488 RealVectorValue
shape_second_deriv(const Elem * elem,const Order order,const unsigned int i,const unsigned int j,const Point & p,const bool add_p_level)489 FE<1, MONOMIAL_VEC>::shape_second_deriv(const Elem * elem,
490 const Order order,
491 const unsigned int i,
492 const unsigned int j,
493 const Point & p,
494 const bool add_p_level)
495 {
496 Real value = FE<1, MONOMIAL>::shape_second_deriv(
497 elem->type(), static_cast<Order>(order + add_p_level * elem->p_level()), i, j, p);
498 return libMesh::RealVectorValue(value);
499 }
500
501 #endif
502
503 // 2-D
504 template <>
505 RealVectorValue
shape(const Elem * elem,const Order order,const unsigned int i,const Point & p,const bool add_p_level)506 FE<2, MONOMIAL_VEC>::shape(const Elem * elem,
507 const Order order,
508 const unsigned int i,
509 const Point & p,
510 const bool add_p_level)
511 {
512 Real value =
513 FE<2, MONOMIAL>::shape(elem->type(), static_cast<Order>(order + add_p_level * elem->p_level()), i / 2, p);
514
515 switch (i % 2)
516 {
517 case 0:
518 return libMesh::RealVectorValue(value);
519
520 case 1:
521 return libMesh::RealVectorValue(Real(0), value);
522
523 default:
524 libmesh_error_msg("i%2 must be either 0 or 1!");
525 }
526
527 // dummy
528 return libMesh::RealVectorValue();
529 }
530 template <>
531 RealVectorValue
shape_deriv(const Elem * elem,const Order order,const unsigned int i,const unsigned int j,const Point & p,const bool add_p_level)532 FE<2, MONOMIAL_VEC>::shape_deriv(const Elem * elem,
533 const Order order,
534 const unsigned int i,
535 const unsigned int j,
536 const Point & p,
537 const bool add_p_level)
538 {
539 Real value = FE<2, MONOMIAL>::shape_deriv(
540 elem->type(), static_cast<Order>(order + add_p_level * elem->p_level()), i / 2, j, p);
541
542 switch (i % 2)
543 {
544 case 0:
545 return libMesh::RealVectorValue(value);
546
547 case 1:
548 return libMesh::RealVectorValue(Real(0), value);
549
550 default:
551 libmesh_error_msg("i%2 must be either 0 or 1!");
552 }
553
554 // dummy
555 return libMesh::RealVectorValue();
556 }
557
558 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
559 template <>
560 RealVectorValue
shape_second_deriv(const Elem * elem,const Order order,const unsigned int i,const unsigned int j,const Point & p,const bool add_p_level)561 FE<2, MONOMIAL_VEC>::shape_second_deriv(const Elem * elem,
562 const Order order,
563 const unsigned int i,
564 const unsigned int j,
565 const Point & p,
566 const bool add_p_level)
567 {
568 Real value = FE<2, MONOMIAL>::shape_second_deriv(
569 elem->type(), static_cast<Order>(order + add_p_level * elem->p_level()), i / 2, j, p);
570
571 switch (i % 2)
572 {
573 case 0:
574 return libMesh::RealVectorValue(value);
575
576 case 1:
577 return libMesh::RealVectorValue(Real(0), value);
578
579 default:
580 libmesh_error_msg("i%2 must be either 0 or 1!");
581 }
582
583 // dummy
584 return libMesh::RealVectorValue();
585 }
586
587 #endif
588
589 // 3-D
590 template <>
591 RealVectorValue
shape(const Elem * elem,const Order order,const unsigned int i,const Point & p,const bool add_p_level)592 FE<3, MONOMIAL_VEC>::shape(const Elem * elem,
593 const Order order,
594 const unsigned int i,
595 const Point & p,
596 const bool add_p_level)
597 {
598 Real value =
599 FE<3, MONOMIAL>::shape(elem->type(), static_cast<Order>(order + add_p_level * elem->p_level()), i / 3, p);
600
601 switch (i % 3)
602 {
603 case 0:
604 return libMesh::RealVectorValue(value);
605
606 case 1:
607 return libMesh::RealVectorValue(Real(0), value);
608
609 case 2:
610 return libMesh::RealVectorValue(Real(0), Real(0), value);
611
612 default:
613 libmesh_error_msg("i%3 must be 0, 1, or 2!");
614 }
615
616 // dummy
617 return libMesh::RealVectorValue();
618 }
619 template <>
620 RealVectorValue
shape_deriv(const Elem * elem,const Order order,const unsigned int i,const unsigned int j,const Point & p,const bool add_p_level)621 FE<3, MONOMIAL_VEC>::shape_deriv(const Elem * elem,
622 const Order order,
623 const unsigned int i,
624 const unsigned int j,
625 const Point & p,
626 const bool add_p_level)
627 {
628 Real value = FE<3, MONOMIAL>::shape_deriv(
629 elem->type(), static_cast<Order>(order + add_p_level * elem->p_level()), i / 3, j, p);
630
631 switch (i % 3)
632 {
633 case 0:
634 return libMesh::RealVectorValue(value);
635
636 case 1:
637 return libMesh::RealVectorValue(Real(0), value);
638
639 case 2:
640 return libMesh::RealVectorValue(Real(0), Real(0), value);
641
642 default:
643 libmesh_error_msg("i%3 must be 0, 1, or 2!");
644 }
645
646 // dummy
647 return libMesh::RealVectorValue();
648 }
649
650 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
651
652 template <>
653 RealVectorValue
shape_second_deriv(const Elem * elem,const Order order,const unsigned int i,const unsigned int j,const Point & p,const bool add_p_level)654 FE<3, MONOMIAL_VEC>::shape_second_deriv(const Elem * elem,
655 const Order order,
656 const unsigned int i,
657 const unsigned int j,
658 const Point & p,
659 const bool add_p_level)
660 {
661 Real value = FE<3, MONOMIAL>::shape_second_deriv(
662 elem->type(), static_cast<Order>(order + add_p_level * elem->p_level()), i / 3, j, p);
663
664 switch (i % 3)
665 {
666 case 0:
667 return libMesh::RealVectorValue(value);
668
669 case 1:
670 return libMesh::RealVectorValue(Real(0), value);
671
672 case 2:
673 return libMesh::RealVectorValue(Real(0), Real(0), value);
674
675 default:
676 libmesh_error_msg("i%3 must be 0, 1, or 2!");
677 }
678
679 // dummy
680 return libMesh::RealVectorValue();
681 }
682
683 #endif
684
685 // Do full-specialization for every dimension, instead
686 // of explicit instantiation at the end of this function.
687 // This could be macro-ified.
688 template <>
689 unsigned int
n_dofs(const ElemType t,const Order o)690 FE<0, MONOMIAL_VEC>::n_dofs(const ElemType t, const Order o)
691 {
692 return FE<0, MONOMIAL>::n_dofs(t, o);
693 }
694 template <>
695 unsigned int
n_dofs(const ElemType t,const Order o)696 FE<1, MONOMIAL_VEC>::n_dofs(const ElemType t, const Order o)
697 {
698 return FE<1, MONOMIAL>::n_dofs(t, o);
699 }
700 template <>
701 unsigned int
n_dofs(const ElemType t,const Order o)702 FE<2, MONOMIAL_VEC>::n_dofs(const ElemType t, const Order o)
703 {
704 return 2 * FE<2, MONOMIAL>::n_dofs(t, o);
705 }
706 template <>
707 unsigned int
n_dofs(const ElemType t,const Order o)708 FE<3, MONOMIAL_VEC>::n_dofs(const ElemType t, const Order o)
709 {
710 return 3 * FE<3, MONOMIAL>::n_dofs(t, o);
711 }
712
713 template <>
714 unsigned int
n_dofs_at_node(const ElemType,const Order,const unsigned int)715 FE<0, MONOMIAL_VEC>::n_dofs_at_node(const ElemType, const Order, const unsigned int)
716 {
717 return 0;
718 }
719 template <>
720 unsigned int
n_dofs_at_node(const ElemType,const Order,const unsigned int)721 FE<1, MONOMIAL_VEC>::n_dofs_at_node(const ElemType, const Order, const unsigned int)
722 {
723 return 0;
724 }
725 template <>
726 unsigned int
n_dofs_at_node(const ElemType,const Order,const unsigned int)727 FE<2, MONOMIAL_VEC>::n_dofs_at_node(const ElemType, const Order, const unsigned int)
728 {
729 return 0;
730 }
731 template <>
732 unsigned int
n_dofs_at_node(const ElemType,const Order,const unsigned int)733 FE<3, MONOMIAL_VEC>::n_dofs_at_node(const ElemType, const Order, const unsigned int)
734 {
735 return 0;
736 }
737
738 template <>
739 unsigned int
n_dofs_per_elem(const ElemType t,const Order o)740 FE<0, MONOMIAL_VEC>::n_dofs_per_elem(const ElemType t, const Order o)
741 {
742 return FE<0, MONOMIAL>::n_dofs_per_elem(t, o);
743 }
744 template <>
745 unsigned int
n_dofs_per_elem(const ElemType t,const Order o)746 FE<1, MONOMIAL_VEC>::n_dofs_per_elem(const ElemType t, const Order o)
747 {
748 return FE<1, MONOMIAL>::n_dofs_per_elem(t, o);
749 }
750 template <>
751 unsigned int
n_dofs_per_elem(const ElemType t,const Order o)752 FE<2, MONOMIAL_VEC>::n_dofs_per_elem(const ElemType t, const Order o)
753 {
754 return 2 * FE<2, MONOMIAL>::n_dofs_per_elem(t, o);
755 }
756 template <>
757 unsigned int
n_dofs_per_elem(const ElemType t,const Order o)758 FE<3, MONOMIAL_VEC>::n_dofs_per_elem(const ElemType t, const Order o)
759 {
760 return 3 * FE<3, MONOMIAL>::n_dofs_per_elem(t, o);
761 }
762
763 // Monomial FEMs are always C^0 continuous
764 template <>
765 FEContinuity
get_continuity()766 FE<0, MONOMIAL_VEC>::get_continuity() const
767 {
768 return DISCONTINUOUS;
769 }
770 template <>
771 FEContinuity
get_continuity()772 FE<1, MONOMIAL_VEC>::get_continuity() const
773 {
774 return DISCONTINUOUS;
775 }
776 template <>
777 FEContinuity
get_continuity()778 FE<2, MONOMIAL_VEC>::get_continuity() const
779 {
780 return DISCONTINUOUS;
781 }
782 template <>
783 FEContinuity
get_continuity()784 FE<3, MONOMIAL_VEC>::get_continuity() const
785 {
786 return DISCONTINUOUS;
787 }
788
789 // Monomial FEMs are not hierarchic
790 template <>
791 bool
is_hierarchic()792 FE<0, MONOMIAL_VEC>::is_hierarchic() const
793 {
794 return true;
795 }
796 template <>
797 bool
is_hierarchic()798 FE<1, MONOMIAL_VEC>::is_hierarchic() const
799 {
800 return true;
801 }
802 template <>
803 bool
is_hierarchic()804 FE<2, MONOMIAL_VEC>::is_hierarchic() const
805 {
806 return true;
807 }
808 template <>
809 bool
is_hierarchic()810 FE<3, MONOMIAL_VEC>::is_hierarchic() const
811 {
812 return true;
813 }
814
815 // Monomial FEM shapes do not need reinit (is this always true?)
816 template <>
817 bool
shapes_need_reinit()818 FE<0, MONOMIAL_VEC>::shapes_need_reinit() const
819 {
820 return false;
821 }
822 template <>
823 bool
shapes_need_reinit()824 FE<1, MONOMIAL_VEC>::shapes_need_reinit() const
825 {
826 return false;
827 }
828 template <>
829 bool
shapes_need_reinit()830 FE<2, MONOMIAL_VEC>::shapes_need_reinit() const
831 {
832 return false;
833 }
834 template <>
835 bool
shapes_need_reinit()836 FE<3, MONOMIAL_VEC>::shapes_need_reinit() const
837 {
838 return false;
839 }
840
841 // we only need instantiations of this function for
842 // Dim==2 and 3. There are no constraints for discontinuous elements, so
843 // we do nothing.
844 #ifdef LIBMESH_ENABLE_AMR
845 template <>
846 void
compute_constraints(DofConstraints &,DofMap &,const unsigned int,const Elem *)847 FE<2, MONOMIAL_VEC>::compute_constraints(DofConstraints &,
848 DofMap &,
849 const unsigned int,
850 const Elem *)
851 {
852 }
853
854 template <>
855 void
compute_constraints(DofConstraints &,DofMap &,const unsigned int,const Elem *)856 FE<3, MONOMIAL_VEC>::compute_constraints(DofConstraints &,
857 DofMap &,
858 const unsigned int,
859 const Elem *)
860 {
861 }
862 #endif // LIBMESH_ENABLE_AMR
863
864 } // namespace libMesh
865