MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
fe_coll.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#include "fem.hpp"
13#include <cstdlib>
14#include <cstring>
15#include <cstdio>
16#ifdef _WIN32
17#define snprintf _snprintf_s
18#endif
19
20namespace mfem
21{
22
23using namespace std;
24
25const FiniteElement *
27{
28 ErrorMode save_error_mode = error_mode;
30 const FiniteElement *fe = nullptr;
31 for (int g = Geometry::DimStart[dim]; g < Geometry::DimStart[dim+1]; g++)
32 {
34 if (fe != nullptr) { break; }
35 }
36 error_mode = save_error_mode;
37 return fe;
38}
39
41{
43 if (fe)
44 {
45 return fe->GetRangeType();
46 }
48}
49
51{
53 if (fe)
54 {
55 return fe->GetDerivRangeType();
56 }
58}
59
61{
63 if (fe)
64 {
65 return fe->GetMapType();
66 }
68}
69
71{
73 if (fe)
74 {
75 return fe->GetDerivType();
76 }
78}
79
81{
83 if (fe)
84 {
85 return fe->GetDerivMapType();
86 }
88}
89
91{
93 if (fe)
94 {
95 return fe->GetRangeDim();
96 }
97 return 0;
98}
99
101{
102 switch (geom)
103 {
106 case Geometry::CUBE:
108 case Geometry::PRISM:
110 return max(GetNumDof(Geometry::TRIANGLE, p),
112 default:
113 MFEM_ABORT("unknown geometry type");
114 }
115 return 0;
116}
117
119{
120 MFEM_ABORT("this method is not implemented in this derived class!");
121 return NULL;
122}
123
125{
126 FiniteElementCollection *fec = NULL;
127
128 if (!strcmp(name, "Linear"))
129 {
130 fec = new LinearFECollection;
131 }
132 else if (!strcmp(name, "Quadratic"))
133 {
134 fec = new QuadraticFECollection;
135 }
136 else if (!strcmp(name, "QuadraticPos"))
137 {
138 fec = new QuadraticPosFECollection;
139 }
140 else if (!strcmp(name, "Cubic"))
141 {
142 fec = new CubicFECollection;
143 }
144 else if (!strcmp(name, "Const3D"))
145 {
146 fec = new Const3DFECollection;
147 }
148 else if (!strcmp(name, "Const2D"))
149 {
150 fec = new Const2DFECollection;
151 }
152 else if (!strcmp(name, "LinearDiscont2D"))
153 {
155 }
156 else if (!strcmp(name, "GaussLinearDiscont2D"))
157 {
159 }
160 else if (!strcmp(name, "P1OnQuad"))
161 {
162 fec = new P1OnQuadFECollection;
163 }
164 else if (!strcmp(name, "QuadraticDiscont2D"))
165 {
167 }
168 else if (!strcmp(name, "QuadraticPosDiscont2D"))
169 {
171 }
172 else if (!strcmp(name, "GaussQuadraticDiscont2D"))
173 {
175 }
176 else if (!strcmp(name, "CubicDiscont2D"))
177 {
179 }
180 else if (!strcmp(name, "LinearDiscont3D"))
181 {
183 }
184 else if (!strcmp(name, "QuadraticDiscont3D"))
185 {
187 }
188 else if (!strcmp(name, "LinearNonConf3D"))
189 {
191 }
192 else if (!strcmp(name, "CrouzeixRaviart"))
193 {
195 }
196 else if (!strcmp(name, "ND1_3D"))
197 {
198 fec = new ND1_3DFECollection;
199 }
200 else if (!strcmp(name, "RT0_2D"))
201 {
202 fec = new RT0_2DFECollection;
203 }
204 else if (!strcmp(name, "RT1_2D"))
205 {
206 fec = new RT1_2DFECollection;
207 }
208 else if (!strcmp(name, "RT2_2D"))
209 {
210 fec = new RT2_2DFECollection;
211 }
212 else if (!strcmp(name, "RT0_3D"))
213 {
214 fec = new RT0_3DFECollection;
215 }
216 else if (!strcmp(name, "RT1_3D"))
217 {
218 fec = new RT1_3DFECollection;
219 }
220 else if (!strncmp(name, "H1_Trace_", 9))
221 {
222 fec = new H1_Trace_FECollection(atoi(name + 13), atoi(name + 9));
223 }
224 else if (!strncmp(name, "H1_Trace@", 9))
225 {
226 fec = new H1_Trace_FECollection(atoi(name + 15), atoi(name + 11),
227 BasisType::GetType(name[9]));
228 }
229 else if (!strncmp(name, "H1_", 3))
230 {
231 // Parse pyramid basis type if included in the name
232 const char *pyr = strstr(name, "Pyr");
233 if (pyr == NULL)
234 {
235 // Use default pyramid type elements
236 fec = new H1_FECollection(atoi(name + 7), atoi(name + 3));
237 }
238 else
239 {
240 // Use specific pyramid type elements
241 fec = new H1_FECollection(atoi(name + 7), atoi(name + 3),
242 BasisType::GaussLobatto, atoi(pyr + 3));
243 }
244 }
245 else if (!strncmp(name, "H1Pos_Trace_", 12))
246 {
247 fec = new H1_Trace_FECollection(atoi(name + 16), atoi(name + 12),
249 }
250 else if (!strncmp(name, "H1Pos_", 6))
251 {
252 fec = new H1Pos_FECollection(atoi(name + 10), atoi(name + 6));
253 }
254 else if (!strncmp(name, "H1Ser_", 6))
255 {
256 fec = new H1Ser_FECollection(atoi(name + 10), atoi(name + 6));
257 }
258 else if (!strncmp(name, "H1@", 3))
259 {
260 // Parse pyramid basis type if included in the name
261 const char *pyr = strstr(name, "Pyr");
262 if (pyr == NULL)
263 {
264 // Use default pyramid type elements
265 fec = new H1_FECollection(atoi(name + 9), atoi(name + 5),
266 BasisType::GetType(name[3]));
267 }
268 else
269 {
270 // Use specific pyramid type elements
271 fec = new H1_FECollection(atoi(name + 9), atoi(name + 5),
272 BasisType::GetType(name[3]),
273 atoi(pyr + 3));
274 }
275 }
276 else if (!strncmp(name, "L2", 2))
277 {
278 // Parse Map Type
279 const int mtype = strstr(name, "Int") == NULL ?
281
282 // Parse the base order
283 const int p = atoi(strstr(name, "_P") + 2);
284
285 // Parse the mesh dimension
286 const int dim = atoi(strstr(name, "D") - 1);
287
288 // Parse basis type if specified
289 const char *t = strstr(name, "_T");
290 const int btype = t == NULL ? BasisType::GaussLegendre : atoi(t + 2);
291
292 // Parse the pyramid type if specified
293 const char *pyr = strstr(name, "Pyr");
294 const int ptype = pyr == NULL ? 1 : atoi(pyr + 3);
295
296 // Create collection
297 fec = new L2_FECollection(p, dim, btype, mtype, ptype);
298 }
299 else if (!strncmp(name, "RT_Trace_", 9))
300 {
301 fec = new RT_Trace_FECollection(atoi(name + 13), atoi(name + 9));
302 }
303 else if (!strncmp(name, "RT_ValTrace_", 12))
304 {
305 fec = new RT_Trace_FECollection(atoi(name + 16), atoi(name + 12),
307 }
308 else if (!strncmp(name, "RT_Trace@", 9))
309 {
310 fec = new RT_Trace_FECollection(atoi(name + 15), atoi(name + 11),
312 BasisType::GetType(name[9]));
313 }
314 else if (!strncmp(name, "RT_ValTrace@", 12))
315 {
316 fec = new RT_Trace_FECollection(atoi(name + 18), atoi(name + 14),
318 BasisType::GetType(name[12]));
319 }
320 else if (!strncmp(name, "DG_Iface_", 9))
321 {
322 fec = new DG_Interface_FECollection(atoi(name + 13), atoi(name + 9));
323 }
324 else if (!strncmp(name, "DG_Iface@", 9))
325 {
326 fec = new DG_Interface_FECollection(atoi(name + 15), atoi(name + 11),
328 BasisType::GetType(name[9]));
329 }
330 else if (!strncmp(name, "DG_IntIface_", 12))
331 {
332 fec = new DG_Interface_FECollection(atoi(name + 16), atoi(name + 12),
334 }
335 else if (!strncmp(name, "DG_IntIface@", 12))
336 {
337 fec = new DG_Interface_FECollection(atoi(name + 18), atoi(name + 14),
339 BasisType::GetType(name[12]));
340 }
341 else if (!strncmp(name, "RT_R1D_", 7))
342 {
343 fec = new RT_R1D_FECollection(atoi(name + 11), atoi(name + 7));
344 }
345 else if (!strncmp(name, "RT_R1D@", 7))
346 {
347 fec = new RT_R1D_FECollection(atoi(name + 14), atoi(name + 10),
348 BasisType::GetType(name[7]),
349 BasisType::GetType(name[8]));
350 }
351 else if (!strncmp(name, "RT_R2D_", 7))
352 {
353 fec = new RT_R2D_FECollection(atoi(name + 11), atoi(name + 7));
354 }
355 else if (!strncmp(name, "RT_R2D@", 7))
356 {
357 fec = new RT_R2D_FECollection(atoi(name + 14), atoi(name + 10),
358 BasisType::GetType(name[7]),
359 BasisType::GetType(name[8]));
360 }
361 else if (!strncmp(name, "RT_", 3))
362 {
363 fec = new RT_FECollection(atoi(name + 7), atoi(name + 3));
364 }
365 else if (!strncmp(name, "RT@", 3))
366 {
367 fec = new RT_FECollection(atoi(name + 10), atoi(name + 6),
368 BasisType::GetType(name[3]),
369 BasisType::GetType(name[4]));
370 }
371 else if (!strncmp(name, "ND_Trace_", 9))
372 {
373 fec = new ND_Trace_FECollection(atoi(name + 13), atoi(name + 9));
374 }
375 else if (!strncmp(name, "ND_Trace@", 9))
376 {
377 fec = new ND_Trace_FECollection(atoi(name + 16), atoi(name + 12),
378 BasisType::GetType(name[9]),
379 BasisType::GetType(name[10]));
380 }
381 else if (!strncmp(name, "ND_R1D_", 7))
382 {
383 fec = new ND_R1D_FECollection(atoi(name + 11), atoi(name + 7));
384 }
385 else if (!strncmp(name, "ND_R1D@", 7))
386 {
387 fec = new ND_R1D_FECollection(atoi(name + 14), atoi(name + 10),
388 BasisType::GetType(name[7]),
389 BasisType::GetType(name[8]));
390 }
391 else if (!strncmp(name, "ND_R2D_", 7))
392 {
393 fec = new ND_R2D_FECollection(atoi(name + 11), atoi(name + 7));
394 }
395 else if (!strncmp(name, "ND_R2D@", 7))
396 {
397 fec = new ND_R2D_FECollection(atoi(name + 14), atoi(name + 10),
398 BasisType::GetType(name[7]),
399 BasisType::GetType(name[8]));
400 }
401 else if (!strncmp(name, "ND_", 3))
402 {
403 fec = new ND_FECollection(atoi(name + 7), atoi(name + 3));
404 }
405 else if (!strncmp(name, "ND@", 3))
406 {
407 fec = new ND_FECollection(atoi(name + 10), atoi(name + 6),
408 BasisType::GetType(name[3]),
409 BasisType::GetType(name[4]));
410 }
411 else if (!strncmp(name, "Local_", 6))
412 {
413 fec = new Local_FECollection(name + 6);
414 }
415 else if (!strncmp(name, "NURBS_HDiv", 10))
416 {
417 if (name[10] != '\0')
418 {
419 // "NURBS" + "number" --> fixed order nurbs collection
420 fec = new NURBS_HDivFECollection(atoi(name + 10));
421 }
422 else
423 {
424 // "NURBS" --> variable order nurbs collection
425 fec = new NURBS_HDivFECollection();
426 }
427 }
428 else if (!strncmp(name, "NURBS_HCurl", 11))
429 {
430 if (name[11] != '\0')
431 {
432 // "NURBS" + "number" --> fixed order nurbs collection
433 fec = new NURBS_HCurlFECollection(atoi(name + 11));
434 }
435 else
436 {
437 // "NURBS" --> variable order nurbs collection
438 fec = new NURBS_HCurlFECollection();
439 }
440 }
441 else if (!strncmp(name, "NURBS", 5))
442 {
443 if (name[5] != '\0')
444 {
445 // "NURBS" + "number" --> fixed order nurbs collection
446 fec = new NURBSFECollection(atoi(name + 5));
447 }
448 else
449 {
450 // "NURBS" --> variable order nurbs collection
451 fec = new NURBSFECollection();
452 }
453 }
454 else
455 {
456 MFEM_ABORT("unknown FiniteElementCollection: " << name);
457 }
458
459 return fec;
460}
461
463{
464 // default implementation for collections that don't care about variable p
465 MFEM_ABORT("Collection " << Name() << " does not support variable orders.");
466 (void) p;
467 return NULL;
468}
469
471{
472 if (p >= var_orders.Size())
473 {
474 var_orders.SetSize(p+1, NULL);
475 }
476 var_orders[p] = Clone(p);
477}
478
480{
481 for (int i = 0; i < var_orders.Size(); i++)
482 {
483 delete var_orders[i];
484 }
485}
486
487template <Geometry::Type geom>
488inline void FiniteElementCollection::GetNVE(int &nv, int &ne)
489{
490 typedef typename Geometry::Constants<geom> g_consts;
491
492 nv = g_consts::NumVert;
493 ne = g_consts::NumEdges;
494}
495
496template <Geometry::Type geom, typename v_t>
498GetEdge(int &nv, v_t &v, int &ne, int &e, int &eo, const int edge_info)
499{
500 typedef typename Geometry::Constants<Geometry::SEGMENT> e_consts;
501 typedef typename Geometry::Constants<geom> g_consts;
502
503 nv = e_consts::NumVert;
504 ne = 1;
505 e = edge_info/64;
506 eo = edge_info%64;
507 MFEM_ASSERT(0 <= e && e < g_consts::NumEdges, "");
508 MFEM_ASSERT(0 <= eo && eo < e_consts::NumOrient, "");
509 v[0] = e_consts::Orient[eo][0];
510 v[1] = e_consts::Orient[eo][1];
511 v[0] = g_consts::Edges[e][v[0]];
512 v[1] = g_consts::Edges[e][v[1]];
513}
514
515template <Geometry::Type geom, Geometry::Type f_geom,
516 typename v_t, typename e_t, typename eo_t>
518GetFace(int &nv, v_t &v, int &ne, e_t &e, eo_t &eo,
519 int &nf, int &f, Geometry::Type &fg, int &fo, const int face_info)
520{
521 typedef typename Geometry::Constants< geom> g_consts;
522 typedef typename Geometry::Constants<f_geom> f_consts;
523
524 nv = f_consts::NumVert;
525 nf = 1;
526 f = face_info/64;
527 fg = f_geom;
528 fo = face_info%64;
529 MFEM_ASSERT(0 <= f && f < g_consts::NumFaces, "");
530 MFEM_ASSERT(0 <= fo && fo < f_consts::NumOrient, "");
531 for (int i = 0; i < f_consts::NumVert; i++)
532 {
533 v[i] = f_consts::Orient[fo][i];
534 v[i] = g_consts::FaceVert[f][v[i]];
535 }
536 ne = f_consts::NumEdges;
537 for (int i = 0; i < f_consts::NumEdges; i++)
538 {
539 int v0 = v[f_consts::Edges[i][0]];
540 int v1 = v[f_consts::Edges[i][1]];
541 int eor = 0;
542 if (v0 > v1) { std::swap(v0, v1); eor = 1; }
543 for (int j = g_consts::VertToVert::I[v0]; true; j++)
544 {
545 MFEM_ASSERT(j < g_consts::VertToVert::I[v0+1],
546 "internal error, edge not found");
547 if (v1 == g_consts::VertToVert::J[j][0])
548 {
549 int en = g_consts::VertToVert::J[j][1];
550 if (en < 0)
551 {
552 en = -1-en;
553 eor = 1-eor;
554 }
555 e[i] = en;
556 eo[i] = eor;
557 break;
558 }
559 }
560 }
561}
562
564 int Info,
565 Array<int> &dofs) const
566{
567 // Info = 64 * SubIndex + SubOrientation
568 MFEM_ASSERT(0 <= Geom && Geom < Geometry::NumGeom,
569 "invalid Geom = " << Geom);
570 MFEM_ASSERT(0 <= SDim && SDim <= Geometry::Dimension[Geom],
571 "invalid SDim = " << SDim <<
572 " for Geom = " << Geometry::Name[Geom]);
573
574 const int nvd = DofForGeometry(Geometry::POINT);
575 if (SDim == 0) // vertex
576 {
577 const int off = nvd*(Info/64);
578 dofs.SetSize(nvd);
579 for (int i = 0; i < nvd; i++)
580 {
581 dofs[i] = off + i;
582 }
583 }
584 else
585 {
586 int v[4], e[4], eo[4], f[1], fo[1];
587 int av = 0, nv = 0, ae = 0, ne = 0, nf = 0;
588 Geometry::Type fg[1];
589
590 switch (Geom)
591 {
593 {
595 GetEdge<Geometry::SEGMENT>(nv, v, ne, e[0], eo[0], Info);
596 break;
597 }
598
600 {
602 switch (SDim)
603 {
604 case 1:
605 GetEdge<Geometry::TRIANGLE>(nv, v, ne, e[0], eo[0], Info);
606 break;
607 case 2:
609 nv, v, ne, e, eo, nf, f[0], fg[0], fo[0], Info);
610 break;
611 default:
612 goto not_supp;
613 }
614 break;
615 }
616
617 case Geometry::SQUARE:
618 {
620 switch (SDim)
621 {
622 case 1:
623 GetEdge<Geometry::SQUARE>(nv, v, ne, e[0], eo[0], Info);
624 break;
625 case 2:
627 nv, v, ne, e, eo, nf, f[0], fg[0], fo[0], Info);
628 break;
629 default:
630 goto not_supp;
631 }
632 break;
633 }
634
636 {
638 switch (SDim)
639 {
640 case 1:
641 GetEdge<Geometry::TETRAHEDRON>(nv, v, ne, e[0], eo[0], Info);
642 break;
643 case 2:
645 nv, v, ne, e, eo, nf, f[0], fg[0], fo[0], Info);
646 break;
647 default:
648 goto not_supp;
649 }
650 break;
651 }
652
653 case Geometry::CUBE:
654 {
656 switch (SDim)
657 {
658 case 1:
659 GetEdge<Geometry::CUBE>(nv, v, ne, e[0], eo[0], Info);
660 break;
661 case 2:
663 nv, v, ne, e, eo, nf, f[0], fg[0], fo[0], Info);
664 break;
665 default:
666 goto not_supp;
667 }
668 break;
669 }
670
671 default:
672 MFEM_ABORT("invalid Geom = " << Geom);
673 }
674
675 int ned = (ne > 0) ? DofForGeometry(Geometry::SEGMENT) : 0;
676
677 // add vertex dofs
678 dofs.SetSize(nv*nvd+ne*ned);
679 for (int i = 0; i < nv; i++)
680 {
681 for (int j = 0; j < nvd; j++)
682 {
683 dofs[i*nvd+j] = v[i]*nvd+j;
684 }
685 }
686 int l_off = nv*nvd, g_off = av*nvd;
687
688 // add edge dofs
689 if (ned > 0)
690 {
691 for (int i = 0; i < ne; i++)
692 {
694 eo[i] ? -1 : 1);
695 for (int j = 0; j < ned; j++)
696 {
697 dofs[l_off+i*ned+j] =
698 ed[j] >= 0 ?
699 g_off+e[i]*ned+ed[j] :
700 -1-(g_off+e[i]*ned+(-1-ed[j]));
701 }
702 }
703 l_off += ne*ned;
704 g_off += ae*ned;
705 }
706
707 // add face dofs
708 if (nf > 0)
709 {
710 const int nfd = DofForGeometry(fg[0]); // assume same face geometry
711 dofs.SetSize(dofs.Size()+nf*nfd);
712 for (int i = 0; i < nf; i++)
713 {
714 const int *fd = DofOrderForOrientation(fg[i], fo[i]);
715 for (int j = 0; j < nfd; j++)
716 {
717 dofs[l_off+i*nfd+j] =
718 fd[j] >= 0 ?
719 g_off+f[i]*nfd+fd[j] :
720 -1-(g_off+f[i]*nfd+(-1-fd[j]));
721 }
722 }
723 }
724
725 // add volume dofs ...
726 }
727 return;
728
729not_supp:
730 MFEM_ABORT("Geom = " << Geometry::Name[Geom] <<
731 ", SDim = " << SDim << " is not supported");
732}
733
734const FiniteElement *
736{
737 switch (GeomType)
738 {
739 case Geometry::POINT: return &PointFE;
740 case Geometry::SEGMENT: return &SegmentFE;
741 case Geometry::TRIANGLE: return &TriangleFE;
742 case Geometry::SQUARE: return &QuadrilateralFE;
743 case Geometry::TETRAHEDRON: return &TetrahedronFE;
744 case Geometry::CUBE: return &ParallelepipedFE;
745 case Geometry::PRISM: return &WedgeFE;
746 case Geometry::PYRAMID: return &PyramidFE;
747 default:
748 if (error_mode == RETURN_NULL) { return nullptr; }
749 mfem_error ("LinearFECollection: unknown geometry type.");
750 }
751 return &SegmentFE; // Make some compilers happy
752}
753
755{
756 switch (GeomType)
757 {
758 case Geometry::POINT: return 1;
759 case Geometry::SEGMENT: return 0;
760 case Geometry::TRIANGLE: return 0;
761 case Geometry::SQUARE: return 0;
762 case Geometry::TETRAHEDRON: return 0;
763 case Geometry::CUBE: return 0;
764 case Geometry::PRISM: return 0;
765 case Geometry::PYRAMID: return 0;
766 default:
767 mfem_error ("LinearFECollection: unknown geometry type.");
768 }
769 return 0; // Make some compilers happy
770}
771
773 int Or) const
774{
775 return NULL;
776}
777
778
779const FiniteElement *
781{
782 switch (GeomType)
783 {
784 case Geometry::POINT: return &PointFE;
785 case Geometry::SEGMENT: return &SegmentFE;
786 case Geometry::TRIANGLE: return &TriangleFE;
787 case Geometry::SQUARE: return &QuadrilateralFE;
788 case Geometry::TETRAHEDRON: return &TetrahedronFE;
789 case Geometry::CUBE: return &ParallelepipedFE;
790 case Geometry::PRISM: return &WedgeFE;
791 default:
792 if (error_mode == RETURN_NULL) { return nullptr; }
793 mfem_error ("QuadraticFECollection: unknown geometry type.");
794 }
795 return &SegmentFE; // Make some compilers happy
796}
797
799{
800 switch (GeomType)
801 {
802 case Geometry::POINT: return 1;
803 case Geometry::SEGMENT: return 1;
804 case Geometry::TRIANGLE: return 0;
805 case Geometry::SQUARE: return 1;
806 case Geometry::TETRAHEDRON: return 0;
807 case Geometry::CUBE: return 1;
808 case Geometry::PRISM: return 0;
809 default:
810 mfem_error ("QuadraticFECollection: unknown geometry type.");
811 }
812 return 0; // Make some compilers happy
813}
814
816 Geometry::Type GeomType, int Or) const
817{
818 static int indexes[] = { 0 };
819
820 return indexes;
821}
822
823
824const FiniteElement *
826 Geometry::Type GeomType) const
827{
828 switch (GeomType)
829 {
830 case Geometry::SEGMENT: return &SegmentFE;
831 case Geometry::SQUARE: return &QuadrilateralFE;
832 default:
833 if (error_mode == RETURN_NULL) { return nullptr; }
834 mfem_error ("QuadraticPosFECollection: unknown geometry type.");
835 }
836 return NULL; // Make some compilers happy
837}
838
840{
841 switch (GeomType)
842 {
843 case Geometry::POINT: return 1;
844 case Geometry::SEGMENT: return 1;
845 case Geometry::SQUARE: return 1;
846 default:
847 mfem_error ("QuadraticPosFECollection: unknown geometry type.");
848 }
849 return 0; // Make some compilers happy
850}
851
853 Geometry::Type GeomType, int Or) const
854{
855 static int indexes[] = { 0 };
856
857 return indexes;
858}
859
860
861const FiniteElement *
863{
864 switch (GeomType)
865 {
866 case Geometry::POINT: return &PointFE;
867 case Geometry::SEGMENT: return &SegmentFE;
868 case Geometry::TRIANGLE: return &TriangleFE;
869 case Geometry::SQUARE: return &QuadrilateralFE;
870 case Geometry::TETRAHEDRON: return &TetrahedronFE;
871 case Geometry::CUBE: return &ParallelepipedFE;
872 case Geometry::PRISM: return &WedgeFE;
873 default:
874 if (error_mode == RETURN_NULL) { return nullptr; }
875 mfem_error ("CubicFECollection: unknown geometry type.");
876 }
877 return &SegmentFE; // Make some compilers happy
878}
879
881{
882 switch (GeomType)
883 {
884 case Geometry::POINT: return 1;
885 case Geometry::SEGMENT: return 2;
886 case Geometry::TRIANGLE: return 1;
887 case Geometry::SQUARE: return 4;
888 case Geometry::TETRAHEDRON: return 0;
889 case Geometry::CUBE: return 8;
890 case Geometry::PRISM: return 2;
891 default:
892 mfem_error ("CubicFECollection: unknown geometry type.");
893 }
894 return 0; // Make some compilers happy
895}
896
898 int Or) const
899{
900 if (GeomType == Geometry::SEGMENT)
901 {
902 static int ind_pos[] = { 0, 1 };
903 static int ind_neg[] = { 1, 0 };
904
905 if (Or < 0)
906 {
907 return ind_neg;
908 }
909 return ind_pos;
910 }
911 else if (GeomType == Geometry::TRIANGLE)
912 {
913 static int indexes[] = { 0 };
914
915 return indexes;
916 }
917 else if (GeomType == Geometry::SQUARE)
918 {
919 static int sq_ind[8][4] = {{0, 1, 2, 3}, {0, 2, 1, 3},
920 {2, 0, 3, 1}, {1, 0, 3, 2},
921 {3, 2, 1, 0}, {3, 1, 2, 0},
922 {1, 3, 0, 2}, {2, 3, 0, 1}
923 };
924 return sq_ind[Or];
925 }
926
927 return NULL;
928}
929
930
931const FiniteElement *
933 Geometry::Type GeomType) const
934{
935 switch (GeomType)
936 {
937 case Geometry::SEGMENT: return &SegmentFE;
938 case Geometry::TRIANGLE: return &TriangleFE;
939 case Geometry::SQUARE: return &QuadrilateralFE;
940 default:
941 if (error_mode == RETURN_NULL) { return nullptr; }
942 mfem_error ("CrouzeixRaviartFECollection: unknown geometry type.");
943 }
944 return &SegmentFE; // Make some compilers happy
945}
946
948{
949 switch (GeomType)
950 {
951 case Geometry::POINT: return 0;
952 case Geometry::SEGMENT: return 1;
953 case Geometry::TRIANGLE: return 0;
954 case Geometry::SQUARE: return 0;
955 default:
956 mfem_error ("CrouzeixRaviartFECollection: unknown geometry type.");
957 }
958 return 0; // Make some compilers happy
959}
960
962 Geometry::Type GeomType, int Or) const
963{
964 static int indexes[] = { 0 };
965
966 return indexes;
967}
968
969
970const FiniteElement *
972{
973 switch (GeomType)
974 {
975 case Geometry::SEGMENT: return &SegmentFE;
976 case Geometry::TRIANGLE: return &TriangleFE;
977 case Geometry::SQUARE: return &QuadrilateralFE;
978 default:
979 if (error_mode == RETURN_NULL) { return nullptr; }
980 mfem_error ("RT0_2DFECollection: unknown geometry type.");
981 }
982 return &SegmentFE; // Make some compilers happy
983}
984
986{
987 switch (GeomType)
988 {
989 case Geometry::POINT: return 0;
990 case Geometry::SEGMENT: return 1;
991 case Geometry::TRIANGLE: return 0;
992 case Geometry::SQUARE: return 0;
993 default:
994 mfem_error ("RT0_2DFECollection: unknown geometry type.");
995 }
996 return 0; // Make some compilers happy
997}
998
1000 int Or) const
1001{
1002 static int ind_pos[] = { 0 };
1003 static int ind_neg[] = { -1 };
1004
1005 if (Or > 0)
1006 {
1007 return ind_pos;
1008 }
1009 return ind_neg;
1010}
1011
1012
1013const FiniteElement *
1015{
1016 switch (GeomType)
1017 {
1018 case Geometry::SEGMENT: return &SegmentFE;
1019 case Geometry::TRIANGLE: return &TriangleFE;
1020 case Geometry::SQUARE: return &QuadrilateralFE;
1021 default:
1022 if (error_mode == RETURN_NULL) { return nullptr; }
1023 mfem_error ("RT1_2DFECollection: unknown geometry type.");
1024 }
1025 return &SegmentFE; // Make some compilers happy
1026}
1027
1029{
1030 switch (GeomType)
1031 {
1032 case Geometry::POINT: return 0;
1033 case Geometry::SEGMENT: return 2;
1034 case Geometry::TRIANGLE: return 2;
1035 case Geometry::SQUARE: return 4;
1036 default:
1037 mfem_error ("RT1_2DFECollection: unknown geometry type.");
1038 }
1039 return 0; // Make some compilers happy
1040}
1041
1043 int Or) const
1044{
1045 static int ind_pos[] = { 0, 1 };
1046 static int ind_neg[] = { -2, -1 };
1047
1048 if (Or > 0)
1049 {
1050 return ind_pos;
1051 }
1052 return ind_neg;
1053}
1054
1055const FiniteElement *
1057{
1058 switch (GeomType)
1059 {
1060 case Geometry::SEGMENT: return &SegmentFE;
1061 case Geometry::TRIANGLE: return &TriangleFE;
1062 case Geometry::SQUARE: return &QuadrilateralFE;
1063 default:
1064 if (error_mode == RETURN_NULL) { return nullptr; }
1065 mfem_error ("RT2_2DFECollection: unknown geometry type.");
1066 }
1067 return &SegmentFE; // Make some compilers happy
1068}
1069
1071{
1072 switch (GeomType)
1073 {
1074 case Geometry::POINT: return 0;
1075 case Geometry::SEGMENT: return 3;
1076 case Geometry::TRIANGLE: return 6;
1077 case Geometry::SQUARE: return 12;
1078 default:
1079 mfem_error ("RT2_2DFECollection: unknown geometry type.");
1080 }
1081 return 0; // Make some compilers happy
1082}
1083
1085 int Or) const
1086{
1087 static int ind_pos[] = { 0, 1, 2 };
1088 static int ind_neg[] = { -3, -2, -1 };
1089
1090 if (Or > 0)
1091 {
1092 return ind_pos;
1093 }
1094 return ind_neg;
1095}
1096
1097
1098const FiniteElement *
1100{
1101 switch (GeomType)
1102 {
1103 case Geometry::TRIANGLE: return &TriangleFE;
1104 case Geometry::SQUARE: return &QuadrilateralFE;
1105 default:
1106 if (error_mode == RETURN_NULL) { return nullptr; }
1107 mfem_error ("Const2DFECollection: unknown geometry type.");
1108 }
1109 return &TriangleFE; // Make some compilers happy
1110}
1111
1113{
1114 switch (GeomType)
1115 {
1116 case Geometry::POINT: return 0;
1117 case Geometry::SEGMENT: return 0;
1118 case Geometry::TRIANGLE: return 1;
1119 case Geometry::SQUARE: return 1;
1120 default:
1121 mfem_error ("Const2DFECollection: unknown geometry type.");
1122 }
1123 return 0; // Make some compilers happy
1124}
1125
1127 int Or) const
1128{
1129 return NULL;
1130}
1131
1132
1133const FiniteElement *
1135 Geometry::Type GeomType) const
1136{
1137 switch (GeomType)
1138 {
1139 case Geometry::TRIANGLE: return &TriangleFE;
1140 case Geometry::SQUARE: return &QuadrilateralFE;
1141 default:
1142 if (error_mode == RETURN_NULL) { return nullptr; }
1143 mfem_error ("LinearDiscont2DFECollection: unknown geometry type.");
1144 }
1145 return &TriangleFE; // Make some compilers happy
1146}
1147
1149{
1150 switch (GeomType)
1151 {
1152 case Geometry::POINT: return 0;
1153 case Geometry::SEGMENT: return 0;
1154 case Geometry::TRIANGLE: return 3;
1155 case Geometry::SQUARE: return 4;
1156 default:
1157 mfem_error ("LinearDiscont2DFECollection: unknown geometry type.");
1158 }
1159 return 0; // Make some compilers happy
1160}
1161
1163 Geometry::Type GeomType, int Or) const
1164{
1165 return NULL;
1166}
1167
1168
1169const FiniteElement *
1171 Geometry::Type GeomType) const
1172{
1173 switch (GeomType)
1174 {
1175 case Geometry::TRIANGLE: return &TriangleFE;
1176 case Geometry::SQUARE: return &QuadrilateralFE;
1177 default:
1178 if (error_mode == RETURN_NULL) { return nullptr; }
1179 mfem_error ("GaussLinearDiscont2DFECollection:"
1180 " unknown geometry type.");
1181 }
1182 return &TriangleFE; // Make some compilers happy
1183}
1184
1186const
1187{
1188 switch (GeomType)
1189 {
1190 case Geometry::POINT: return 0;
1191 case Geometry::SEGMENT: return 0;
1192 case Geometry::TRIANGLE: return 3;
1193 case Geometry::SQUARE: return 4;
1194 default:
1195 mfem_error ("GaussLinearDiscont2DFECollection:"
1196 " unknown geometry type.");
1197 }
1198 return 0; // Make some compilers happy
1199}
1200
1202 Geometry::Type GeomType, int Or) const
1203{
1204 return NULL;
1205}
1206
1207
1208const FiniteElement *
1210{
1211 if (GeomType != Geometry::SQUARE)
1212 {
1213 if (error_mode == RETURN_NULL) { return nullptr; }
1214 mfem_error ("P1OnQuadFECollection: unknown geometry type.");
1215 }
1216 return &QuadrilateralFE;
1217}
1218
1220{
1221 switch (GeomType)
1222 {
1223 case Geometry::POINT: return 0;
1224 case Geometry::SEGMENT: return 0;
1225 case Geometry::SQUARE: return 3;
1226 default:
1227 mfem_error ("P1OnQuadFECollection: unknown geometry type.");
1228 }
1229 return 0; // Make some compilers happy
1230}
1231
1233 Geometry::Type GeomType, int Or) const
1234{
1235 return NULL;
1236}
1237
1238
1239const FiniteElement *
1241 Geometry::Type GeomType) const
1242{
1243 switch (GeomType)
1244 {
1245 case Geometry::TRIANGLE: return &TriangleFE;
1246 case Geometry::SQUARE: return &QuadrilateralFE;
1247 default:
1248 if (error_mode == RETURN_NULL) { return nullptr; }
1249 mfem_error ("QuadraticDiscont2DFECollection: unknown geometry type.");
1250 }
1251 return &TriangleFE; // Make some compilers happy
1252}
1253
1255const
1256{
1257 switch (GeomType)
1258 {
1259 case Geometry::POINT: return 0;
1260 case Geometry::SEGMENT: return 0;
1261 case Geometry::TRIANGLE: return 6;
1262 case Geometry::SQUARE: return 9;
1263 default:
1264 mfem_error ("QuadraticDiscont2DFECollection: unknown geometry type.");
1265 }
1266 return 0; // Make some compilers happy
1267}
1268
1270 Geometry::Type GeomType, int Or) const
1271{
1272 return NULL;
1273}
1274
1275
1276const FiniteElement *
1278 Geometry::Type GeomType) const
1279{
1280 switch (GeomType)
1281 {
1282 case Geometry::SQUARE: return &QuadrilateralFE;
1283 default:
1284 if (error_mode == RETURN_NULL) { return nullptr; }
1285 mfem_error ("QuadraticPosDiscont2DFECollection: unknown geometry type.");
1286 }
1287 return NULL; // Make some compilers happy
1288}
1289
1291const
1292{
1293 switch (GeomType)
1294 {
1295 case Geometry::POINT: return 0;
1296 case Geometry::SEGMENT: return 0;
1297 case Geometry::SQUARE: return 9;
1298 default:
1299 mfem_error ("QuadraticPosDiscont2DFECollection: unknown geometry type.");
1300 }
1301 return 0; // Make some compilers happy
1302}
1303
1304
1305const FiniteElement *
1307 Geometry::Type GeomType)
1308const
1309{
1310 switch (GeomType)
1311 {
1312 case Geometry::TRIANGLE: return &TriangleFE;
1313 case Geometry::SQUARE: return &QuadrilateralFE;
1314 default:
1315 if (error_mode == RETURN_NULL) { return nullptr; }
1316 mfem_error ("GaussQuadraticDiscont2DFECollection:"
1317 " unknown geometry type.");
1318 }
1319 return &QuadrilateralFE; // Make some compilers happy
1320}
1321
1323 Geometry::Type GeomType) const
1324{
1325 switch (GeomType)
1326 {
1327 case Geometry::POINT: return 0;
1328 case Geometry::SEGMENT: return 0;
1329 case Geometry::TRIANGLE: return 6;
1330 case Geometry::SQUARE: return 9;
1331 default:
1332 mfem_error ("GaussQuadraticDiscont2DFECollection:"
1333 " unknown geometry type.");
1334 }
1335 return 0; // Make some compilers happy
1336}
1337
1339 Geometry::Type GeomType, int Or) const
1340{
1341 return NULL;
1342}
1343
1344
1345const FiniteElement *
1347 Geometry::Type GeomType) const
1348{
1349 switch (GeomType)
1350 {
1351 case Geometry::TRIANGLE: return &TriangleFE;
1352 case Geometry::SQUARE: return &QuadrilateralFE;
1353 default:
1354 if (error_mode == RETURN_NULL) { return nullptr; }
1355 mfem_error ("CubicDiscont2DFECollection: unknown geometry type.");
1356 }
1357 return &TriangleFE; // Make some compilers happy
1358}
1359
1361{
1362 switch (GeomType)
1363 {
1364 case Geometry::POINT: return 0;
1365 case Geometry::SEGMENT: return 0;
1366 case Geometry::TRIANGLE: return 10;
1367 case Geometry::SQUARE: return 16;
1368 default:
1369 mfem_error ("CubicDiscont2DFECollection: unknown geometry type.");
1370 }
1371 return 0; // Make some compilers happy
1372}
1373
1375 Geometry::Type GeomType, int Or) const
1376{
1377 return NULL;
1378}
1379
1380
1381const FiniteElement *
1383 Geometry::Type GeomType) const
1384{
1385 switch (GeomType)
1386 {
1387 case Geometry::TRIANGLE: return &TriangleFE;
1388 case Geometry::SQUARE: return &QuadrilateralFE;
1389 case Geometry::TETRAHEDRON: return &TetrahedronFE;
1390 case Geometry::CUBE: return &ParallelepipedFE;
1391 default:
1392 if (error_mode == RETURN_NULL) { return nullptr; }
1393 mfem_error ("LinearNonConf3DFECollection: unknown geometry type.");
1394 }
1395 return &TriangleFE; // Make some compilers happy
1396}
1397
1399{
1400 switch (GeomType)
1401 {
1402 case Geometry::POINT: return 0;
1403 case Geometry::SEGMENT: return 0;
1404 case Geometry::TRIANGLE: return 1;
1405 case Geometry::SQUARE: return 1;
1406 case Geometry::TETRAHEDRON: return 0;
1407 case Geometry::CUBE: return 0;
1408 default:
1409 mfem_error ("LinearNonConf3DFECollection: unknown geometry type.");
1410 }
1411 return 0; // Make some compilers happy
1412}
1413
1415 Geometry::Type GeomType, int Or) const
1416{
1417 static int indexes[] = { 0 };
1418
1419 return indexes;
1420}
1421
1422
1423const FiniteElement *
1425{
1426 switch (GeomType)
1427 {
1428 case Geometry::TETRAHEDRON: return &TetrahedronFE;
1429 case Geometry::CUBE: return &ParallelepipedFE;
1430 case Geometry::PRISM: return &WedgeFE;
1431 case Geometry::PYRAMID: return &PyramidFE;
1432 default:
1433 if (error_mode == RETURN_NULL) { return nullptr; }
1434 mfem_error ("Const3DFECollection: unknown geometry type.");
1435 }
1436 return &TetrahedronFE; // Make some compilers happy
1437}
1438
1440{
1441 switch (GeomType)
1442 {
1443 case Geometry::POINT: return 0;
1444 case Geometry::SEGMENT: return 0;
1445 case Geometry::TRIANGLE: return 0;
1446 case Geometry::SQUARE: return 0;
1447 case Geometry::TETRAHEDRON: return 1;
1448 case Geometry::CUBE: return 1;
1449 case Geometry::PRISM: return 1;
1450 case Geometry::PYRAMID: return 1;
1451 default:
1452 mfem_error ("Const3DFECollection: unknown geometry type.");
1453 }
1454 return 0; // Make some compilers happy
1455}
1456
1458 int Or) const
1459{
1460 return NULL;
1461}
1462
1463
1464const FiniteElement *
1466 Geometry::Type GeomType) const
1467{
1468 switch (GeomType)
1469 {
1470 case Geometry::TETRAHEDRON: return &TetrahedronFE;
1471 case Geometry::PYRAMID: return &PyramidFE;
1472 case Geometry::PRISM: return &WedgeFE;
1473 case Geometry::CUBE: return &ParallelepipedFE;
1474 default:
1475 if (error_mode == RETURN_NULL) { return nullptr; }
1476 mfem_error ("LinearDiscont3DFECollection: unknown geometry type.");
1477 }
1478 return &TetrahedronFE; // Make some compilers happy
1479}
1480
1482{
1483 switch (GeomType)
1484 {
1485 case Geometry::POINT: return 0;
1486 case Geometry::SEGMENT: return 0;
1487 case Geometry::TRIANGLE: return 0;
1488 case Geometry::SQUARE: return 0;
1489 case Geometry::TETRAHEDRON: return 4;
1490 case Geometry::PYRAMID: return 5;
1491 case Geometry::PRISM: return 6;
1492 case Geometry::CUBE: return 8;
1493 default:
1494 mfem_error ("LinearDiscont3DFECollection: unknown geometry type.");
1495 }
1496 return 0; // Make some compilers happy
1497}
1498
1500 Geometry::Type GeomType, int Or) const
1501{
1502 return NULL;
1503}
1504
1505
1506const FiniteElement *
1508 Geometry::Type GeomType) const
1509{
1510 switch (GeomType)
1511 {
1512 case Geometry::TETRAHEDRON: return &TetrahedronFE;
1513 case Geometry::CUBE: return &ParallelepipedFE;
1514 default:
1515 if (error_mode == RETURN_NULL) { return nullptr; }
1516 mfem_error ("QuadraticDiscont3DFECollection: unknown geometry type.");
1517 }
1518 return &TetrahedronFE; // Make some compilers happy
1519}
1520
1522const
1523{
1524 switch (GeomType)
1525 {
1526 case Geometry::POINT: return 0;
1527 case Geometry::SEGMENT: return 0;
1528 case Geometry::TRIANGLE: return 0;
1529 case Geometry::SQUARE: return 0;
1530 case Geometry::TETRAHEDRON: return 10;
1531 case Geometry::CUBE: return 27;
1532 default:
1533 mfem_error ("QuadraticDiscont3DFECollection: unknown geometry type.");
1534 }
1535 return 0; // Make some compilers happy
1536}
1537
1539 Geometry::Type GeomType, int Or) const
1540{
1541 return NULL;
1542}
1543
1544const FiniteElement *
1546 Geometry::Type GeomType) const
1547{
1548 switch (GeomType)
1549 {
1550 case Geometry::POINT: return &PointFE;
1551 case Geometry::SEGMENT: return &SegmentFE;
1552 case Geometry::TRIANGLE: return &TriangleFE;
1553 case Geometry::SQUARE: return &QuadrilateralFE;
1554 case Geometry::TETRAHEDRON: return &TetrahedronFE;
1555 case Geometry::CUBE: return &ParallelepipedFE;
1556 default:
1557 if (error_mode == RETURN_NULL) { return nullptr; }
1558 mfem_error ("RefinedLinearFECollection: unknown geometry type.");
1559 }
1560 return &SegmentFE; // Make some compilers happy
1561}
1562
1564{
1565 switch (GeomType)
1566 {
1567 case Geometry::POINT: return 1;
1568 case Geometry::SEGMENT: return 1;
1569 case Geometry::TRIANGLE: return 0;
1570 case Geometry::SQUARE: return 1;
1571 case Geometry::TETRAHEDRON: return 0;
1572 case Geometry::CUBE: return 1;
1573 default:
1574 mfem_error ("RefinedLinearFECollection: unknown geometry type.");
1575 }
1576 return 0; // Make some compilers happy
1577}
1578
1580 Geometry::Type GeomType, int Or) const
1581{
1582 static int indexes[] = { 0 };
1583
1584 return indexes;
1585}
1586
1587
1588const FiniteElement *
1590{
1591 switch (GeomType)
1592 {
1593 case Geometry::CUBE: return &HexahedronFE;
1594 case Geometry::TETRAHEDRON: return &TetrahedronFE;
1595 case Geometry::PRISM: return &WedgeFE;
1596 case Geometry::PYRAMID: return &PyramidFE;
1597 default:
1598 if (error_mode == RETURN_NULL) { return nullptr; }
1599 mfem_error ("ND1_3DFECollection: unknown geometry type.");
1600 }
1601 return &HexahedronFE; // Make some compilers happy
1602}
1603
1605{
1606 switch (GeomType)
1607 {
1608 case Geometry::POINT: return 0;
1609 case Geometry::SEGMENT: return 1;
1610 case Geometry::TRIANGLE: return 0;
1611 case Geometry::SQUARE: return 0;
1612 case Geometry::TETRAHEDRON: return 0;
1613 case Geometry::CUBE: return 0;
1614 case Geometry::PRISM: return 0;
1615 case Geometry::PYRAMID: return 0;
1616 default:
1617 mfem_error ("ND1_3DFECollection: unknown geometry type.");
1618 }
1619 return 0; // Make some compilers happy
1620}
1621
1623 int Or) const
1624{
1625 static int ind_pos[] = { 0 };
1626 static int ind_neg[] = { -1 };
1627
1628 if (Or > 0)
1629 {
1630 return ind_pos;
1631 }
1632 return ind_neg;
1633}
1634
1635
1636const FiniteElement *
1638{
1639 switch (GeomType)
1640 {
1641 case Geometry::TRIANGLE: return &TriangleFE;
1642 case Geometry::SQUARE: return &QuadrilateralFE;
1643 case Geometry::CUBE: return &HexahedronFE;
1644 case Geometry::TETRAHEDRON: return &TetrahedronFE;
1645 case Geometry::PRISM: return &WedgeFE;
1646 case Geometry::PYRAMID: return &PyramidFE;
1647 default:
1648 if (error_mode == RETURN_NULL) { return nullptr; }
1649 mfem_error ("RT0_3DFECollection: unknown geometry type.");
1650 }
1651 return &HexahedronFE; // Make some compilers happy
1652}
1653
1655{
1656 switch (GeomType)
1657 {
1658 case Geometry::POINT: return 0;
1659 case Geometry::SEGMENT: return 0;
1660 case Geometry::TRIANGLE: return 1;
1661 case Geometry::SQUARE: return 1;
1662 case Geometry::TETRAHEDRON: return 0;
1663 case Geometry::CUBE: return 0;
1664 case Geometry::PRISM: return 0;
1665 case Geometry::PYRAMID: return 0;
1666 default:
1667 mfem_error ("RT0_3DFECollection: unknown geometry type.");
1668 }
1669 return 0; // Make some compilers happy
1670}
1671
1673 int Or) const
1674{
1675 static int ind_pos[] = { 0 };
1676 static int ind_neg[] = { -1 };
1677
1678 if ((GeomType == Geometry::TRIANGLE) || (GeomType == Geometry::SQUARE))
1679 {
1680 if (Or % 2 == 0)
1681 {
1682 return ind_pos;
1683 }
1684 return ind_neg;
1685 }
1686 return NULL;
1687}
1688
1689const FiniteElement *
1691{
1692 switch (GeomType)
1693 {
1694 case Geometry::TRIANGLE: return &TriangleFE;
1695 case Geometry::SQUARE: return &QuadrilateralFE;
1696 case Geometry::CUBE: return &HexahedronFE;
1697 default:
1698 if (error_mode == RETURN_NULL) { return nullptr; }
1699 mfem_error ("RT1_3DFECollection: unknown geometry type.");
1700 }
1701 return &HexahedronFE; // Make some compilers happy
1702}
1703
1705{
1706 switch (GeomType)
1707 {
1708 case Geometry::POINT: return 0;
1709 case Geometry::SEGMENT: return 0;
1710 case Geometry::TRIANGLE: return 2;
1711 case Geometry::SQUARE: return 4;
1712 case Geometry::CUBE: return 12;
1713 default:
1714 mfem_error ("RT1_3DFECollection: unknown geometry type.");
1715 }
1716 return 0; // Make some compilers happy
1717}
1718
1720 int Or) const
1721{
1722 if (GeomType == Geometry::SQUARE)
1723 {
1724 static int sq_ind[8][4] =
1725 {
1726 {0, 1, 2, 3}, {-1, -3, -2, -4},
1727 {2, 0, 3, 1}, {-2, -1, -4, -3},
1728 {3, 2, 1, 0}, {-4, -2, -3, -1},
1729 {1, 3, 0, 2}, {-3, -4, -1, -2}
1730 };
1731
1732 return sq_ind[Or];
1733 }
1734 else
1735 {
1736 return NULL;
1737 }
1738}
1739
1740
1741H1_FECollection::H1_FECollection(const int p, const int dim, const int btype,
1742 const int pyr_type)
1744 , dim(dim)
1745 , p_type(pyr_type)
1746{
1747 MFEM_VERIFY(p >= 1, "H1_FECollection requires order >= 1.");
1748 MFEM_VERIFY(dim >= 0 && dim <= 3, "H1_FECollection requires 0 <= dim <= 3.");
1749
1750 const int pm1 = p - 1, pm2 = pm1 - 1, pm3 = pm2 - 1, pm4 = pm3 - 1;
1751
1752 int pt_type = BasisType::GetQuadrature1D(btype);
1753 b_type = BasisType::Check(btype);
1754 switch (btype)
1755 {
1757 {
1758 if (pyr_type == ScalarPyramid::DefaultType)
1759 {
1760 snprintf(h1_name, 32, "H1_%dD_P%d", dim, p);
1761 }
1762 else
1763 {
1764 snprintf(h1_name, 32, "H1_%dD_P%d_Pyr%d", dim, p, pyr_type);
1765 }
1766 break;
1767 }
1769 {
1770 snprintf(h1_name, 32, "H1Pos_%dD_P%d", dim, p);
1771 break;
1772 }
1774 {
1775 snprintf(h1_name, 32, "H1Ser_%dD_P%d", dim, p);
1776 break;
1777 }
1778 default:
1779 {
1780 MFEM_VERIFY(Quadrature1D::CheckClosed(pt_type) !=
1782 "unsupported BasisType: " << BasisType::Name(btype));
1783
1784 snprintf(h1_name, 32, "H1@%c_%dD_P%d",
1785 (int)BasisType::GetChar(btype), dim, p);
1786 }
1787 }
1788
1789 for (int g = 0; g < Geometry::NumGeom; g++)
1790 {
1791 H1_dof[g] = 0;
1792 H1_Elements[g] = NULL;
1793 }
1794 for (int i = 0; i < 2; i++)
1795 {
1796 SegDofOrd[i] = NULL;
1797 }
1798 for (int i = 0; i < 6; i++)
1799 {
1800 TriDofOrd[i] = NULL;
1801 }
1802 for (int i = 0; i < 8; i++)
1803 {
1804 QuadDofOrd[i] = NULL;
1805 }
1806 for (int i = 0; i < 24; i++)
1807 {
1808 TetDofOrd[i] = NULL;
1809 }
1810
1813
1814 if (dim >= 1)
1815 {
1818 {
1820 }
1821 else
1822 {
1824 }
1825
1826 SegDofOrd[0] = (pm1 > 0) ? new int[2*pm1] : nullptr;
1827 SegDofOrd[1] = SegDofOrd[0] + pm1;
1828 for (int i = 0; i < pm1; i++)
1829 {
1830 SegDofOrd[0][i] = i;
1831 SegDofOrd[1][i] = pm2 - i;
1832 }
1833 }
1834
1835 if (dim >= 2)
1836 {
1837 H1_dof[Geometry::TRIANGLE] = (pm1*pm2)/2;
1838 H1_dof[Geometry::SQUARE] = pm1*pm1;
1840 {
1843 }
1844 else if (b_type == BasisType::Serendipity)
1845 {
1846 // Note: in fe_coll.hpp the DofForGeometry(Geometry::Type) method
1847 // returns H1_dof[GeomType], so we need to fix the value of H1_dof here
1848 // for the serendipity case.
1849
1850 // formula for number of interior serendipity DoFs (when p>1)
1851 H1_dof[Geometry::SQUARE] = (pm3*pm2)/2;
1853 // allows for mixed tri/quad meshes
1855 }
1856 else
1857 {
1860 }
1861
1862 const int &TriDof = H1_dof[Geometry::TRIANGLE];
1863 const int &QuadDof = H1_dof[Geometry::SQUARE];
1864 TriDofOrd[0] = (TriDof > 0) ? new int[6*TriDof] : nullptr;
1865 for (int i = 1; i < 6; i++)
1866 {
1867 TriDofOrd[i] = TriDofOrd[i-1] + TriDof;
1868 }
1869 // see Mesh::GetTriOrientation in mesh/mesh.cpp
1870 for (int j = 0; j < pm2; j++)
1871 {
1872 for (int i = 0; i + j < pm2; i++)
1873 {
1874 int o = TriDof - ((pm1 - j)*(pm2 - j))/2 + i;
1875 int k = pm3 - j - i;
1876 TriDofOrd[0][o] = o; // (0,1,2)
1877 TriDofOrd[1][o] = TriDof - ((pm1-j)*(pm2-j))/2 + k; // (1,0,2)
1878 TriDofOrd[2][o] = TriDof - ((pm1-i)*(pm2-i))/2 + k; // (2,0,1)
1879 TriDofOrd[3][o] = TriDof - ((pm1-k)*(pm2-k))/2 + i; // (2,1,0)
1880 TriDofOrd[4][o] = TriDof - ((pm1-k)*(pm2-k))/2 + j; // (1,2,0)
1881 TriDofOrd[5][o] = TriDof - ((pm1-i)*(pm2-i))/2 + j; // (0,2,1)
1882 }
1883 }
1884
1885 QuadDofOrd[0] = (QuadDof > 0) ? new int[8*QuadDof] : nullptr;
1886 for (int i = 1; i < 8; i++)
1887 {
1888 QuadDofOrd[i] = QuadDofOrd[i-1] + QuadDof;
1889 }
1890
1891 // For serendipity order >=4, the QuadDofOrd array must be re-defined. We
1892 // do this by computing the corresponding tensor product QuadDofOrd array
1893 // or two orders less, which contains enough DoFs for their serendipity
1894 // basis. This could be optimized.
1896 {
1897 if (p < 4)
1898 {
1899 // no face dofs --> don't need to adjust QuadDofOrd
1900 }
1901 else // p >= 4 --> have face dofs
1902 {
1903 // Exactly the same as tensor product case, but with all orders
1904 // reduced by 2 e.g. in case p=5 it builds a 2x2 array, even though
1905 // there are only 3 serendipity dofs.
1906 // In the tensor product case, the i and j index tensor directions,
1907 // and o index from 0 to (pm1)^2,
1908
1909 for (int j = 0; j < pm3; j++) // pm3 instead of pm1, etc
1910 {
1911 for (int i = 0; i < pm3; i++)
1912 {
1913 int o = i + j*pm3;
1914 QuadDofOrd[0][o] = i + j*pm3; // (0,1,2,3)
1915 QuadDofOrd[1][o] = j + i*pm3; // (0,3,2,1)
1916 QuadDofOrd[2][o] = j + (pm4 - i)*pm3; // (1,2,3,0)
1917 QuadDofOrd[3][o] = (pm4 - i) + j*pm3; // (1,0,3,2)
1918 QuadDofOrd[4][o] = (pm4 - i) + (pm4 - j)*pm3; // (2,3,0,1)
1919 QuadDofOrd[5][o] = (pm4 - j) + (pm4 - i)*pm3; // (2,1,0,3)
1920 QuadDofOrd[6][o] = (pm4 - j) + i*pm3; // (3,0,1,2)
1921 QuadDofOrd[7][o] = i + (pm4 - j)*pm3; // (3,2,1,0)
1922 }
1923 }
1924
1925 }
1926 }
1927 else // not serendipity
1928 {
1929 for (int j = 0; j < pm1; j++)
1930 {
1931 for (int i = 0; i < pm1; i++)
1932 {
1933 int o = i + j*pm1;
1934 QuadDofOrd[0][o] = i + j*pm1; // (0,1,2,3)
1935 QuadDofOrd[1][o] = j + i*pm1; // (0,3,2,1)
1936 QuadDofOrd[2][o] = j + (pm2 - i)*pm1; // (1,2,3,0)
1937 QuadDofOrd[3][o] = (pm2 - i) + j*pm1; // (1,0,3,2)
1938 QuadDofOrd[4][o] = (pm2 - i) + (pm2 - j)*pm1; // (2,3,0,1)
1939 QuadDofOrd[5][o] = (pm2 - j) + (pm2 - i)*pm1; // (2,1,0,3)
1940 QuadDofOrd[6][o] = (pm2 - j) + i*pm1; // (3,0,1,2)
1941 QuadDofOrd[7][o] = i + (pm2 - j)*pm1; // (3,2,1,0)
1942 }
1943 }
1944 }
1945
1946 if (dim >= 3)
1947 {
1948 H1_dof[Geometry::TETRAHEDRON] = (TriDof*pm3)/3;
1949 H1_dof[Geometry::CUBE] = QuadDof*pm1;
1950 H1_dof[Geometry::PRISM] = TriDof*pm1;
1951 if (pyr_type == 0 || b_type == BasisType::Positive)
1952 {
1953 H1_dof[Geometry::PYRAMID] = pm2*pm1*(2*p-3)/6; // Bergot (JSC)
1954 }
1955 else if (pyr_type == 1)
1956 {
1957 H1_dof[Geometry::PYRAMID] = pm1*pm1*pm1; // Fuentes
1958 }
1959 else
1960 {
1961 H1_dof[Geometry::PYRAMID] = (p-1)*(p-2)/2;
1962 }
1964 {
1969 }
1970 else
1971 {
1973 new H1_TetrahedronElement(p, btype);
1976 if (pyr_type == 0)
1977 {
1979 new H1_BergotPyramidElement(p, btype);
1980 }
1981 else
1982 {
1984 new H1_FuentesPyramidElement(p, btype);
1985 }
1986 }
1987
1988 const int &TetDof = H1_dof[Geometry::TETRAHEDRON];
1989 TetDofOrd[0] = (TetDof > 0) ? new int[24*TetDof] : nullptr;
1990 for (int i = 1; i < 24; i++)
1991 {
1992 TetDofOrd[i] = TetDofOrd[i-1] + TetDof;
1993 }
1994 // see Mesh::GetTetOrientation in mesh/mesh.cpp
1995 for (int k = 0; k < pm3; k++)
1996 {
1997 for (int j = 0; j + k < pm3; j++)
1998 {
1999 for (int i = 0; i + j + k < pm3; i++)
2000 {
2001 int l = pm4 - k - j - i;
2002 int o = TetDof - ((pm1 - k) * (pm2 - k) * (pm3 - k)) / 6
2003 + (j * (2 * p - 5 - j - 2 * k)) / 2 + i;
2004 int o1 = TetDof - ((pm1 - j) * (pm2 - j) * (pm3 - j)) / 6
2005 + (k * (2 * p - 5 - k - 2 * j)) / 2 + i;
2006 int o2 = TetDof - ((pm1 - i) * (pm2 - i) * (pm3 - i)) / 6
2007 + (k * (2 * p - 5 - k - 2 * i)) / 2 + j;
2008 int o3 = TetDof - ((pm1 - k) * (pm2 - k) * (pm3 - k)) / 6
2009 + (i * (2 * p - 5 - i - 2 * k)) / 2 + j;
2010 int o4 = TetDof - ((pm1 - j) * (pm2 - j) * (pm3 - j)) / 6
2011 + (i * (2 * p - 5 - i - 2 * j)) / 2 + k;
2012 int o5 = TetDof - ((pm1 - i) * (pm2 - i) * (pm3 - i)) / 6
2013 + (j * (2 * p - 5 - j - 2 * i)) / 2 + k;
2014 int o6 = TetDof - ((pm1 - k) * (pm2 - k) * (pm3 - k)) / 6
2015 + (l * (2 * p - 5 - l - 2 * k)) / 2 + j;
2016 int o7 = TetDof - ((pm1 - l) * (pm2 - l) * (pm3 - l)) / 6
2017 + (k * (2 * p - 5 - k - 2 * l)) / 2 + j;
2018 int o8 = TetDof - ((pm1 - l) * (pm2 - l) * (pm3 - l)) / 6
2019 + (j * (2 * p - 5 - j - 2 * l)) / 2 + k;
2020 int o9 = TetDof - ((pm1 - j) * (pm2 - j) * (pm3 - j)) / 6
2021 + (l * (2 * p - 5 - l - 2 * j)) / 2 + k;
2022 int o10 = TetDof - ((pm1 - j) * (pm2 - j) * (pm3 - j)) / 6
2023 + (k * (2 * p - 5 - k - 2 * j)) / 2 + l;
2024 int o11 = TetDof - ((pm1 - k) * (pm2 - k) * (pm3 - k)) / 6
2025 + (j * (2 * p - 5 - j - 2 * k)) / 2 + l;
2026 int o12 = TetDof - ((pm1 - i) * (pm2 - i) * (pm3 - i)) / 6
2027 + (l * (2 * p - 5 - l - 2 * i)) / 2 + k;
2028 int o13 = TetDof - ((pm1 - l) * (pm2 - l) * (pm3 - l)) / 6
2029 + (i * (2 * p - 5 - i - 2 * l)) / 2 + k;
2030 int o14 = TetDof - ((pm1 - k) * (pm2 - k) * (pm3 - k)) / 6
2031 + (i * (2 * p - 5 - i - 2 * k)) / 2 + l;
2032 int o15 = TetDof - ((pm1 - i) * (pm2 - i) * (pm3 - i)) / 6
2033 + (k * (2 * p - 5 - k - 2 * i)) / 2 + l;
2034 int o16 = TetDof - ((pm1 - l) * (pm2 - l) * (pm3 - l)) / 6
2035 + (k * (2 * p - 5 - k - 2 * l)) / 2 + i;
2036 int o17 = TetDof - ((pm1 - k) * (pm2 - k) * (pm3 - k)) / 6
2037 + (l * (2 * p - 5 - l - 2 * k)) / 2 + i;
2038 int o18 = TetDof - ((pm1 - i) * (pm2 - i) * (pm3 - i)) / 6
2039 + (j * (2 * p - 5 - j - 2 * i)) / 2 + l;
2040 int o19 = TetDof - ((pm1 - j) * (pm2 - j) * (pm3 - j)) / 6
2041 + (i * (2 * p - 5 - i - 2 * j)) / 2 + l;
2042 int o20 = TetDof - ((pm1 - j) * (pm2 - j) * (pm3 - j)) / 6
2043 + (l * (2 * p - 5 - l - 2 * j)) / 2 + i;
2044 int o21 = TetDof - ((pm1 - l) * (pm2 - l) * (pm3 - l)) / 6
2045 + (j * (2 * p - 5 - j - 2 * l)) / 2 + i;
2046 int o22 = TetDof - ((pm1 - l) * (pm2 - l) * (pm3 - l)) / 6
2047 + (i * (2 * p - 5 - i - 2 * l)) / 2 + j;
2048 int o23 = TetDof - ((pm1 - i) * (pm2 - i) * (pm3 - i)) / 6
2049 + (l * (2 * p - 5 - l - 2 * i)) / 2 + j;
2050 TetDofOrd[ 0][o] = o; // (0,1,2,3)
2051 TetDofOrd[ 1][o] = o1; // (0,1,3,2)
2052 TetDofOrd[ 2][o] = o2; // (0,2,3,1)
2053 TetDofOrd[ 3][o] = o3; // (0,2,1,3)
2054 TetDofOrd[ 4][o] = o4; // (0,3,1,2)
2055 TetDofOrd[ 5][o] = o5; // (0,3,2,1)
2056 TetDofOrd[ 6][o] = o6; // (1,2,0,3)
2057 TetDofOrd[ 7][o] = o7; // (1,2,3,0)
2058 TetDofOrd[ 8][o] = o8; // (1,3,2,0)
2059 TetDofOrd[ 9][o] = o9; // (1,3,0,2)
2060 TetDofOrd[10][o] = o10; // (1,0,3,2)
2061 TetDofOrd[11][o] = o11; // (1,0,2,3)
2062 TetDofOrd[12][o] = o12; // (2,3,0,1)
2063 TetDofOrd[13][o] = o13; // (2,3,1,0)
2064 TetDofOrd[14][o] = o14; // (2,0,1,3)
2065 TetDofOrd[15][o] = o15; // (2,0,3,1)
2066 TetDofOrd[16][o] = o16; // (2,1,3,0)
2067 TetDofOrd[17][o] = o17; // (2,1,0,3)
2068 TetDofOrd[18][o] = o18; // (3,0,2,1)
2069 TetDofOrd[19][o] = o19; // (3,0,1,2)
2070 TetDofOrd[20][o] = o20; // (3,1,0,2)
2071 TetDofOrd[21][o] = o21; // (3,1,2,0)
2072 TetDofOrd[22][o] = o22; // (3,2,1,0)
2073 TetDofOrd[23][o] = o23; // (3,2,0,1)
2074 }
2075 }
2076 }
2077 }
2078 }
2079}
2080
2081const FiniteElement *
2083{
2084 return H1_Elements[GeomType];
2085}
2086
2088 int Or) const
2089{
2090 if (GeomType == Geometry::SEGMENT)
2091 {
2092 return (Or > 0) ? SegDofOrd[0] : SegDofOrd[1];
2093 }
2094 else if (GeomType == Geometry::TRIANGLE)
2095 {
2096 return TriDofOrd[Or%6];
2097 }
2098 else if (GeomType == Geometry::SQUARE)
2099 {
2100 return QuadDofOrd[Or%8];
2101 }
2102 else if (GeomType == Geometry::TETRAHEDRON)
2103 {
2104 return TetDofOrd[Or%24];
2105 }
2106 return NULL;
2107}
2108
2110{
2111 int tr_p = H1_dof[Geometry::SEGMENT] + 1;
2112 int tr_dim = -1;
2113 if (!strncmp(h1_name, "H1_", 3))
2114 {
2115 tr_dim = atoi(h1_name + 3);
2116 }
2117 else if (!strncmp(h1_name, "H1Pos_", 6))
2118 {
2119 tr_dim = atoi(h1_name + 6);
2120 }
2121 else if (!strncmp(h1_name, "H1@", 3))
2122 {
2123 tr_dim = atoi(h1_name + 5);
2124 }
2125 return (dim < 0) ? NULL : new H1_Trace_FECollection(tr_p, tr_dim, b_type);
2126}
2127
2129{
2130 const int *dof_map = NULL;
2131 const FiniteElement *fe = H1_Elements[GeomType];
2132 const NodalFiniteElement *nodal_fe =
2133 dynamic_cast<const NodalFiniteElement*>(fe);
2134 if (nodal_fe)
2135 {
2136 dof_map = nodal_fe->GetLexicographicOrdering().GetData();
2137 }
2138 else
2139 {
2140 MFEM_ABORT("Geometry type " << Geometry::Name[GeomType] << " is not "
2141 "implemented");
2142 }
2143 return dof_map;
2144}
2145
2146const int *H1_FECollection::GetDofMap(Geometry::Type GeomType, int p) const
2147{
2148 if (p == base_p) { return GetDofMap(GeomType); }
2149 if (p >= var_orders.Size() || !var_orders[p]) { InitVarOrder(p); }
2150 return ((H1_FECollection*) var_orders[p])->GetDofMap(GeomType);
2151}
2152
2154{
2155 delete [] SegDofOrd[0];
2156 delete [] TriDofOrd[0];
2157 delete [] QuadDofOrd[0];
2158 delete [] TetDofOrd[0];
2159 for (int g = 0; g < Geometry::NumGeom; g++)
2160 {
2161 delete H1_Elements[g];
2162 }
2163}
2164
2165
2167 const int btype)
2168 : H1_FECollection(p, dim-1, btype)
2169{
2170 if (btype == BasisType::GaussLobatto)
2171 {
2172 snprintf(h1_name, 32, "H1_Trace_%dD_P%d", dim, p);
2173 }
2174 else if (btype == BasisType::Positive)
2175 {
2176 snprintf(h1_name, 32, "H1Pos_Trace_%dD_P%d", dim, p);
2177 }
2178 else // base class checks that type is closed
2179 {
2180 snprintf(h1_name, 32, "H1_Trace@%c_%dD_P%d",
2181 (int)BasisType::GetChar(btype), dim, p);
2182 }
2183}
2184
2185
2186L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
2187 const int map_type, const int pyr_type)
2189 , dim(dim)
2190 , m_type(map_type)
2191 , p_type(pyr_type)
2192{
2193 MFEM_VERIFY(p >= 0, "L2_FECollection requires order >= 0.");
2194
2195 b_type = BasisType::Check(btype);
2196 const char *prefix = NULL;
2197 switch (map_type)
2198 {
2199 case FiniteElement::VALUE: prefix = "L2"; break;
2200 case FiniteElement::INTEGRAL: prefix = "L2Int"; break;
2201 default:
2202 MFEM_ABORT("invalid map_type: " << map_type);
2203 }
2204 switch (btype)
2205 {
2207 if (pyr_type == ScalarPyramid::DefaultType)
2208 {
2209 snprintf(d_name, 32, "%s_%dD_P%d", prefix, dim, p);
2210 }
2211 else
2212 {
2213 snprintf(d_name, 32, "%s_%dD_P%d_Pyr%d", prefix, dim, p, pyr_type);
2214 }
2215 break;
2216 default:
2217 if (pyr_type == ScalarPyramid::DefaultType)
2218 {
2219 snprintf(d_name, 32, "%s_T%d_%dD_P%d", prefix, btype, dim, p);
2220 }
2221 else
2222 {
2223 snprintf(d_name, 32, "%s_T%d_%dD_P%d_Pyr%d",
2224 prefix, btype, dim, p, pyr_type);
2225 }
2226 }
2227
2228 for (int g = 0; g < Geometry::NumGeom; g++)
2229 {
2230 L2_Elements[g] = NULL;
2231 Tr_Elements[g] = NULL;
2232 }
2233 for (int i = 0; i < 2; i++)
2234 {
2235 SegDofOrd[i] = NULL;
2236 }
2237 for (int i = 0; i < 6; i++)
2238 {
2239 TriDofOrd[i] = NULL;
2240 }
2241 for (int i = 0; i < 24; i++)
2242 {
2243 TetDofOrd[i] = NULL;
2244 }
2245 OtherDofOrd = NULL;
2246
2247 if (dim == 0)
2248 {
2249 L2_Elements[Geometry::POINT] = new PointFiniteElement;
2250 }
2251 else if (dim == 1)
2252 {
2253 if (b_type == BasisType::Positive)
2254 {
2255 L2_Elements[Geometry::SEGMENT] = new L2Pos_SegmentElement(p);
2256 }
2257 else
2258 {
2259 L2_Elements[Geometry::SEGMENT] = new L2_SegmentElement(p, btype);
2260 }
2261 L2_Elements[Geometry::SEGMENT]->SetMapType(map_type);
2262
2263 Tr_Elements[Geometry::POINT] = new PointFiniteElement;
2264 // No need to set the map_type for Tr_Elements.
2265
2266 const int pp1 = p + 1;
2267 SegDofOrd[0] = (pp1 > 0) ? new int[2*pp1] : nullptr;
2268 SegDofOrd[1] = SegDofOrd[0] + pp1;
2269 for (int i = 0; i <= p; i++)
2270 {
2271 SegDofOrd[0][i] = i;
2272 SegDofOrd[1][i] = p - i;
2273 }
2274 }
2275 else if (dim == 2)
2276 {
2277 if (b_type == BasisType::Positive)
2278 {
2279 L2_Elements[Geometry::TRIANGLE] = new L2Pos_TriangleElement(p);
2280 L2_Elements[Geometry::SQUARE] = new L2Pos_QuadrilateralElement(p);
2281 }
2282 else
2283 {
2284 L2_Elements[Geometry::TRIANGLE] = new L2_TriangleElement(p, btype);
2285 L2_Elements[Geometry::SQUARE] = new L2_QuadrilateralElement(p, btype);
2286 }
2287 L2_Elements[Geometry::TRIANGLE]->SetMapType(map_type);
2288 L2_Elements[Geometry::SQUARE]->SetMapType(map_type);
2289 // Trace element use the default Gauss-Legendre nodal points for positive basis
2290 if (b_type == BasisType::Positive)
2291 {
2292 Tr_Elements[Geometry::SEGMENT] = new L2Pos_SegmentElement(p);
2293 }
2294 else
2295 {
2296 Tr_Elements[Geometry::SEGMENT] = new L2_SegmentElement(p, btype);
2297 }
2298
2299 const int TriDof = L2_Elements[Geometry::TRIANGLE]->GetDof();
2300 TriDofOrd[0] = (TriDof > 0) ? new int[6*TriDof] : nullptr;
2301 for (int i = 1; i < 6; i++)
2302 {
2303 TriDofOrd[i] = TriDofOrd[i-1] + TriDof;
2304 }
2305 const int pp1 = p + 1, pp2 = pp1 + 1;
2306 for (int j = 0; j <= p; j++)
2307 {
2308 for (int i = 0; i + j <= p; i++)
2309 {
2310 int o = TriDof - ((pp2 - j)*(pp1 - j))/2 + i;
2311 int k = p - j - i;
2312 TriDofOrd[0][o] = o; // (0,1,2)
2313 TriDofOrd[1][o] = TriDof - ((pp2-j)*(pp1-j))/2 + k; // (1,0,2)
2314 TriDofOrd[2][o] = TriDof - ((pp2-i)*(pp1-i))/2 + k; // (2,0,1)
2315 TriDofOrd[3][o] = TriDof - ((pp2-k)*(pp1-k))/2 + i; // (2,1,0)
2316 TriDofOrd[4][o] = TriDof - ((pp2-k)*(pp1-k))/2 + j; // (1,2,0)
2317 TriDofOrd[5][o] = TriDof - ((pp2-i)*(pp1-i))/2 + j; // (0,2,1)
2318 }
2319 }
2320 const int QuadDof = L2_Elements[Geometry::SQUARE]->GetDof();
2321 OtherDofOrd = (QuadDof > 0) ? new int[QuadDof] : nullptr;
2322 for (int j = 0; j < QuadDof; j++)
2323 {
2324 OtherDofOrd[j] = j; // for Or == 0
2325 }
2326 }
2327 else if (dim == 3)
2328 {
2329 if (b_type == BasisType::Positive)
2330 {
2332 L2_Elements[Geometry::CUBE] = new L2Pos_HexahedronElement(p);
2333 L2_Elements[Geometry::PRISM] = new L2Pos_WedgeElement(p);
2334 L2_Elements[Geometry::PYRAMID] = new L2Pos_PyramidElement(p);
2335 }
2336 else
2337 {
2338 L2_Elements[Geometry::TETRAHEDRON] =
2339 new L2_TetrahedronElement(p, btype);
2340 L2_Elements[Geometry::CUBE] = new L2_HexahedronElement(p, btype);
2341 L2_Elements[Geometry::PRISM] = new L2_WedgeElement(p, btype);
2342 if (pyr_type == 0)
2343 {
2344 L2_Elements[Geometry::PYRAMID] =
2345 new L2_BergotPyramidElement(p, btype);
2346 }
2347 else
2348 {
2349 L2_Elements[Geometry::PYRAMID] =
2350 new L2_FuentesPyramidElement(p, btype);
2351 }
2352 }
2353
2354 L2_Elements[Geometry::TETRAHEDRON]->SetMapType(map_type);
2355 L2_Elements[Geometry::CUBE]->SetMapType(map_type);
2356 L2_Elements[Geometry::PRISM]->SetMapType(map_type);
2357 L2_Elements[Geometry::PYRAMID]->SetMapType(map_type);
2358 if (b_type != BasisType::Positive)
2359 {
2360 L2_Elements[Geometry::PYRAMID]->SetMapType(map_type);
2361 }
2362 // Trace element use the default Gauss-Legendre nodal points for positive basis
2363 if (b_type == BasisType::Positive)
2364 {
2365 Tr_Elements[Geometry::TRIANGLE] = new L2Pos_TriangleElement(p);
2366 Tr_Elements[Geometry::SQUARE] = new L2Pos_QuadrilateralElement(p);
2367 }
2368 else
2369 {
2370 Tr_Elements[Geometry::TRIANGLE] = new L2_TriangleElement(p, btype);
2371 Tr_Elements[Geometry::SQUARE] = new L2_QuadrilateralElement(p, btype);
2372 }
2373
2374 const int TetDof = L2_Elements[Geometry::TETRAHEDRON]->GetDof();
2375 const int HexDof = L2_Elements[Geometry::CUBE]->GetDof();
2376 const int PriDof = L2_Elements[Geometry::PRISM]->GetDof();
2377 const int PyrDof = L2_Elements[Geometry::PYRAMID]->GetDof();
2378 const int MaxDof = std::max(std::max(TetDof, PyrDof),
2379 std::max(PriDof, HexDof));
2380
2381 TetDofOrd[0] = (TetDof > 0) ? new int[24*TetDof] : nullptr;
2382 for (int i = 1; i < 24; i++)
2383 {
2384 TetDofOrd[i] = TetDofOrd[i-1] + TetDof;
2385 }
2386 // see Mesh::GetTetOrientation in mesh/mesh.cpp
2387 const int pp1 = p + 1, pp2 = pp1 + 1, pp3 = pp2 + 1;
2388 for (int k = 0; k <= p; k++)
2389 {
2390 for (int j = 0; j + k <= p; j++)
2391 {
2392 for (int i = 0; i + j + k <= p; i++)
2393 {
2394 int l = p - k - j - i;
2395 int o = TetDof - ((pp1 - k) * (pp2 - k) * (pp3 - k)) / 6
2396 + (j * (2 * p + 3 - j - 2 * k)) / 2 + i;
2397 int o1 = TetDof - ((pp1 - j) * (pp2 - j) * (pp3 - j)) / 6
2398 + (k * (2 * p + 3 - k - 2 * j)) / 2 + i;
2399 int o2 = TetDof - ((pp1 - i) * (pp2 - i) * (pp3 - i)) / 6
2400 + (k * (2 * p + 3 - k - 2 * i)) / 2 + j;
2401 int o3 = TetDof - ((pp1 - k) * (pp2 - k) * (pp3 - k)) / 6
2402 + (i * (2 * p + 3 - i - 2 * k)) / 2 + j;
2403 int o4 = TetDof - ((pp1 - j) * (pp2 - j) * (pp3 - j)) / 6
2404 + (i * (2 * p + 3 - i - 2 * j)) / 2 + k;
2405 int o5 = TetDof - ((pp1 - i) * (pp2 - i) * (pp3 - i)) / 6
2406 + (j * (2 * p + 3 - j - 2 * i)) / 2 + k;
2407 int o6 = TetDof - ((pp1 - k) * (pp2 - k) * (pp3 - k)) / 6
2408 + (l * (2 * p + 3 - l - 2 * k)) / 2 + j;
2409 int o7 = TetDof - ((pp1 - l) * (pp2 - l) * (pp3 - l)) / 6
2410 + (k * (2 * p + 3 - k - 2 * l)) / 2 + j;
2411 int o8 = TetDof - ((pp1 - l) * (pp2 - l) * (pp3 - l)) / 6
2412 + (j * (2 * p + 3 - j - 2 * l)) / 2 + k;
2413 int o9 = TetDof - ((pp1 - j) * (pp2 - j) * (pp3 - j)) / 6
2414 + (l * (2 * p + 3 - l - 2 * j)) / 2 + k;
2415 int o10 = TetDof - ((pp1 - j) * (pp2 - j) * (pp3 - j)) / 6
2416 + (k * (2 * p + 3 - k - 2 * j)) / 2 + l;
2417 int o11 = TetDof - ((pp1 - k) * (pp2 - k) * (pp3 - k)) / 6
2418 + (j * (2 * p + 3 - j - 2 * k)) / 2 + l;
2419 int o12 = TetDof - ((pp1 - i) * (pp2 - i) * (pp3 - i)) / 6
2420 + (l * (2 * p + 3 - l - 2 * i)) / 2 + k;
2421 int o13 = TetDof - ((pp1 - l) * (pp2 - l) * (pp3 - l)) / 6
2422 + (i * (2 * p + 3 - i - 2 * l)) / 2 + k;
2423 int o14 = TetDof - ((pp1 - k) * (pp2 - k) * (pp3 - k)) / 6
2424 + (i * (2 * p + 3 - i - 2 * k)) / 2 + l;
2425 int o15 = TetDof - ((pp1 - i) * (pp2 - i) * (pp3 - i)) / 6
2426 + (k * (2 * p + 3 - k - 2 * i)) / 2 + l;
2427 int o16 = TetDof - ((pp1 - l) * (pp2 - l) * (pp3 - l)) / 6
2428 + (k * (2 * p + 3 - k - 2 * l)) / 2 + i;
2429 int o17 = TetDof - ((pp1 - k) * (pp2 - k) * (pp3 - k)) / 6
2430 + (l * (2 * p + 3 - l - 2 * k)) / 2 + i;
2431 int o18 = TetDof - ((pp1 - i) * (pp2 - i) * (pp3 - i)) / 6
2432 + (j * (2 * p + 3 - j - 2 * i)) / 2 + l;
2433 int o19 = TetDof - ((pp1 - j) * (pp2 - j) * (pp3 - j)) / 6
2434 + (i * (2 * p + 3 - i - 2 * j)) / 2 + l;
2435 int o20 = TetDof - ((pp1 - j) * (pp2 - j) * (pp3 - j)) / 6
2436 + (l * (2 * p + 3 - l - 2 * j)) / 2 + i;
2437 int o21 = TetDof - ((pp1 - l) * (pp2 - l) * (pp3 - l)) / 6
2438 + (j * (2 * p + 3 - j - 2 * l)) / 2 + i;
2439 int o22 = TetDof - ((pp1 - l) * (pp2 - l) * (pp3 - l)) / 6
2440 + (i * (2 * p + 3 - i - 2 * l)) / 2 + j;
2441 int o23 = TetDof - ((pp1 - i) * (pp2 - i) * (pp3 - i)) / 6
2442 + (l * (2 * p + 3 - l - 2 * i)) / 2 + j;
2443 TetDofOrd[ 0][o] = o; // (0,1,2,3)
2444 TetDofOrd[ 1][o] = o1; // (0,1,3,2)
2445 TetDofOrd[ 2][o] = o2; // (0,2,3,1)
2446 TetDofOrd[ 3][o] = o3; // (0,2,1,3)
2447 TetDofOrd[ 4][o] = o4; // (0,3,1,2)
2448 TetDofOrd[ 5][o] = o5; // (0,3,2,1)
2449 TetDofOrd[ 6][o] = o6; // (1,2,0,3)
2450 TetDofOrd[ 7][o] = o7; // (1,2,3,0)
2451 TetDofOrd[ 8][o] = o8; // (1,3,2,0)
2452 TetDofOrd[ 9][o] = o9; // (1,3,0,2)
2453 TetDofOrd[10][o] = o10; // (1,0,3,2)
2454 TetDofOrd[11][o] = o11; // (1,0,2,3)
2455 TetDofOrd[12][o] = o12; // (2,3,0,1)
2456 TetDofOrd[13][o] = o13; // (2,3,1,0)
2457 TetDofOrd[14][o] = o14; // (2,0,1,3)
2458 TetDofOrd[15][o] = o15; // (2,0,3,1)
2459 TetDofOrd[16][o] = o16; // (2,1,3,0)
2460 TetDofOrd[17][o] = o17; // (2,1,0,3)
2461 TetDofOrd[18][o] = o18; // (3,0,2,1)
2462 TetDofOrd[19][o] = o19; // (3,0,1,2)
2463 TetDofOrd[20][o] = o20; // (3,1,0,2)
2464 TetDofOrd[21][o] = o21; // (3,1,2,0)
2465 TetDofOrd[22][o] = o22; // (3,2,1,0)
2466 TetDofOrd[23][o] = o23; // (3,2,0,1)
2467 }
2468 }
2469 }
2470 OtherDofOrd = (MaxDof > 0) ? new int[MaxDof] : nullptr;
2471 for (int j = 0; j < MaxDof; j++)
2472 {
2473 OtherDofOrd[j] = j; // for Or == 0
2474 }
2475 }
2476 else
2477 {
2478 mfem::err << "L2_FECollection::L2_FECollection : dim = "
2479 << dim << endl;
2480 mfem_error();
2481 }
2482}
2483
2484const FiniteElement *
2486{
2487 return L2_Elements[GeomType];
2488}
2489
2491 int Or) const
2492{
2493 switch (GeomType)
2494 {
2495 case Geometry::SEGMENT:
2496 return (Or > 0) ? SegDofOrd[0] : SegDofOrd[1];
2497
2498 case Geometry::TRIANGLE:
2499 return TriDofOrd[Or%6];
2500
2502 return TetDofOrd[Or%24];
2503
2504 default:
2505 return (Or == 0) ? OtherDofOrd : NULL;
2506 }
2507}
2508
2510{
2511 delete [] OtherDofOrd;
2512 delete [] SegDofOrd[0];
2513 delete [] TriDofOrd[0];
2514 delete [] TetDofOrd[0];
2515 for (int i = 0; i < Geometry::NumGeom; i++)
2516 {
2517 delete L2_Elements[i];
2518 delete Tr_Elements[i];
2519 }
2520}
2521
2522
2523RT_FECollection::RT_FECollection(const int order, const int dim,
2524 const int cb_type, const int ob_type)
2525 : FiniteElementCollection(order + 1)
2526 , dim(dim)
2527 , cb_type(cb_type)
2528 , ob_type(ob_type)
2529{
2530 int p = order;
2531 MFEM_VERIFY(p >= 0, "RT_FECollection requires order >= 0.");
2532
2533 int cp_type = BasisType::GetQuadrature1D(cb_type);
2534 int op_type = BasisType::GetQuadrature1D(ob_type);
2535
2537 {
2538 const char *cb_name = BasisType::Name(cb_type); // this may abort
2539 MFEM_ABORT("unknown closed BasisType: " << cb_name);
2540 }
2542 {
2543 const char *ob_name = BasisType::Name(ob_type); // this may abort
2544 MFEM_ABORT("unknown open BasisType: " << ob_name);
2545 }
2546
2548
2551 {
2552 snprintf(rt_name, 32, "RT_%dD_P%d", dim, p);
2553 }
2554 else
2555 {
2556 snprintf(rt_name, 32, "RT@%c%c_%dD_P%d", (int)BasisType::GetChar(cb_type),
2558 }
2559
2560 const int pp1 = p + 1;
2561 if (dim == 2)
2562 {
2563 // TODO: cb_type, ob_type for triangles
2566
2568 ob_type);
2569 // two vector components * n_unk_face *
2570 RT_dof[Geometry::SQUARE] = 2*p*pp1;
2571 }
2572 else if (dim == 3)
2573 {
2574 // TODO: cb_type, ob_type for tets
2576 RT_dof[Geometry::TETRAHEDRON] = p*pp1*(p + 2)/2;
2577
2579 RT_dof[Geometry::CUBE] = 3*p*pp1*pp1;
2580
2582 RT_dof[Geometry::PRISM] = p*pp1*(3*p + 4)/2;
2583
2585 RT_dof[Geometry::PYRAMID] = 3*p*pp1*pp1;
2586 }
2587 else
2588 {
2589 MFEM_ABORT("invalid dim = " << dim);
2590 }
2591}
2592
2593// This is a special protected constructor only used by RT_Trace_FECollection
2594// and DG_Interface_FECollection
2596 const int map_type, const bool signs,
2597 const int ob_type)
2599 , dim(dim)
2600 , ob_type(ob_type)
2601{
2604 {
2605 const char *ob_name = BasisType::Name(ob_type); // this may abort
2606 MFEM_ABORT("Invalid open basis type: " << ob_name);
2607 }
2608 InitFaces(p, dim, map_type, signs);
2609}
2610
2611void RT_FECollection::InitFaces(const int p, const int dim_,
2612 const int map_type,
2613 const bool signs)
2614{
2615 int op_type = BasisType::GetQuadrature1D(ob_type);
2616
2617 MFEM_VERIFY(Quadrature1D::CheckOpen(op_type) != Quadrature1D::Invalid,
2618 "invalid open point type");
2619
2620 const int pp1 = p + 1, pp2 = p + 2;
2621
2622 for (int g = 0; g < Geometry::NumGeom; g++)
2623 {
2624 RT_Elements[g] = NULL;
2625 RT_dof[g] = 0;
2626 }
2627 // Degree of Freedom orderings
2628 for (int i = 0; i < 2; i++)
2629 {
2630 SegDofOrd[i] = NULL;
2631 }
2632 for (int i = 0; i < 6; i++)
2633 {
2634 TriDofOrd[i] = NULL;
2635 }
2636 for (int i = 0; i < 8; i++)
2637 {
2638 QuadDofOrd[i] = NULL;
2639 }
2640
2641 if (dim_ == 2)
2642 {
2644 l2_seg->SetMapType(map_type);
2647
2648 SegDofOrd[0] = (pp1 > 0) ? new int[2*pp1] : nullptr;
2649 SegDofOrd[1] = SegDofOrd[0] + pp1;
2650 for (int i = 0; i <= p; i++)
2651 {
2652 SegDofOrd[0][i] = i;
2653 SegDofOrd[1][i] = signs ? (-1 - (p - i)) : (p - i);
2654 }
2655 }
2656 else if (dim_ == 3)
2657 {
2659 l2_tri->SetMapType(map_type);
2661 RT_dof[Geometry::TRIANGLE] = pp1*pp2/2;
2662
2664 l2_quad->SetMapType(map_type);
2665 RT_Elements[Geometry::SQUARE] = l2_quad;
2666 RT_dof[Geometry::SQUARE] = pp1*pp1;
2667
2668 int TriDof = RT_dof[Geometry::TRIANGLE];
2669 TriDofOrd[0] = (TriDof > 0) ? new int[6*TriDof] : nullptr;
2670 for (int i = 1; i < 6; i++)
2671 {
2672 TriDofOrd[i] = TriDofOrd[i-1] + TriDof;
2673 }
2674 // see Mesh::GetTriOrientation in mesh/mesh.cpp,
2675 // the constructor of H1_FECollection
2676 for (int j = 0; j <= p; j++)
2677 {
2678 for (int i = 0; i + j <= p; i++)
2679 {
2680 int o = TriDof - ((pp2 - j)*(pp1 - j))/2 + i;
2681 int k = p - j - i;
2682 TriDofOrd[0][o] = o; // (0,1,2)
2683 TriDofOrd[1][o] = -1-(TriDof-((pp2-j)*(pp1-j))/2+k); // (1,0,2)
2684 TriDofOrd[2][o] = TriDof-((pp2-i)*(pp1-i))/2+k; // (2,0,1)
2685 TriDofOrd[3][o] = -1-(TriDof-((pp2-k)*(pp1-k))/2+i); // (2,1,0)
2686 TriDofOrd[4][o] = TriDof-((pp2-k)*(pp1-k))/2+j; // (1,2,0)
2687 TriDofOrd[5][o] = -1-(TriDof-((pp2-i)*(pp1-i))/2+j); // (0,2,1)
2688 if (!signs)
2689 {
2690 for (int kk = 1; kk < 6; kk += 2)
2691 {
2692 TriDofOrd[kk][o] = -1 - TriDofOrd[kk][o];
2693 }
2694 }
2695 }
2696 }
2697
2698 int QuadDof = RT_dof[Geometry::SQUARE];
2699 QuadDofOrd[0] = (QuadDof > 0) ? new int[8*QuadDof] : nullptr;
2700 for (int i = 1; i < 8; i++)
2701 {
2702 QuadDofOrd[i] = QuadDofOrd[i-1] + QuadDof;
2703 }
2704 // see Mesh::GetQuadOrientation in mesh/mesh.cpp
2705 for (int j = 0; j <= p; j++)
2706 {
2707 for (int i = 0; i <= p; i++)
2708 {
2709 int o = i + j*pp1;
2710 QuadDofOrd[0][o] = i + j*pp1; // (0,1,2,3)
2711 QuadDofOrd[1][o] = -1 - (j + i*pp1); // (0,3,2,1)
2712 QuadDofOrd[2][o] = j + (p - i)*pp1; // (1,2,3,0)
2713 QuadDofOrd[3][o] = -1 - ((p - i) + j*pp1); // (1,0,3,2)
2714 QuadDofOrd[4][o] = (p - i) + (p - j)*pp1; // (2,3,0,1)
2715 QuadDofOrd[5][o] = -1 - ((p - j) + (p - i)*pp1); // (2,1,0,3)
2716 QuadDofOrd[6][o] = (p - j) + i*pp1; // (3,0,1,2)
2717 QuadDofOrd[7][o] = -1 - (i + (p - j)*pp1); // (3,2,1,0)
2718 if (!signs)
2719 {
2720 for (int k = 1; k < 8; k += 2)
2721 {
2722 QuadDofOrd[k][o] = -1 - QuadDofOrd[k][o];
2723 }
2724 }
2725 }
2726 }
2727 }
2728}
2729
2730const FiniteElement *
2732{
2733 return RT_Elements[GeomType];
2734}
2735
2737 int Or) const
2738{
2739 if (GeomType == Geometry::SEGMENT)
2740 {
2741 return (Or > 0) ? SegDofOrd[0] : SegDofOrd[1];
2742 }
2743 else if (GeomType == Geometry::TRIANGLE)
2744 {
2745 return TriDofOrd[Or%6];
2746 }
2747 else if (GeomType == Geometry::SQUARE)
2748 {
2749 return QuadDofOrd[Or%8];
2750 }
2751 return NULL;
2752}
2753
2755{
2756 int tr_dim, tr_p;
2757 if (!strncmp(rt_name, "RT_", 3))
2758 {
2759 tr_dim = atoi(rt_name + 3);
2760 tr_p = atoi(rt_name + 7);
2761 }
2762 else // rt_name = RT@.._.D_P*
2763 {
2764 tr_dim = atoi(rt_name + 6);
2765 tr_p = atoi(rt_name + 10);
2766 }
2767 return new RT_Trace_FECollection(tr_p, tr_dim, FiniteElement::INTEGRAL,
2768 ob_type);
2769}
2770
2772{
2773 delete [] SegDofOrd[0];
2774 delete [] TriDofOrd[0];
2775 delete [] QuadDofOrd[0];
2776 for (int g = 0; g < Geometry::NumGeom; g++)
2777 {
2778 delete RT_Elements[g];
2779 }
2780}
2781
2782
2784 const int map_type,
2785 const int ob_type)
2786 : RT_FECollection(p, dim, map_type, true, ob_type)
2787{
2788 const char *prefix =
2789 (map_type == FiniteElement::INTEGRAL) ? "RT_Trace" : "RT_ValTrace";
2790 char ob_str[3] = { '\0', '\0', '\0' };
2791
2793 {
2794 ob_str[0] = '@';
2795 ob_str[1] = BasisType::GetChar(ob_type);
2796 }
2797 snprintf(rt_name, 32, "%s%s_%dD_P%d", prefix, ob_str, dim, p);
2798
2799 MFEM_VERIFY(dim == 2 || dim == 3, "Wrong dimension, dim = " << dim);
2800}
2801
2802
2804 const int map_type,
2805 const int ob_type)
2806 : RT_FECollection(p, dim, map_type, false, ob_type)
2807{
2808 MFEM_VERIFY(dim == 2 || dim == 3, "Wrong dimension, dim = " << dim);
2809
2810 const char *prefix =
2811 (map_type == FiniteElement::VALUE) ? "DG_Iface" : "DG_IntIface";
2813 {
2814 snprintf(rt_name, 32, "%s_%dD_P%d", prefix, dim, p);
2815 }
2816 else
2817 {
2818 snprintf(rt_name, 32, "%s@%c_%dD_P%d", prefix,
2820 }
2821}
2822
2824 const int cb_type, const int ob_type)
2825 : FiniteElementCollection(dim > 1 ? p : p - 1)
2826 , dim(dim)
2827 , cb_type(cb_type)
2828 , ob_type(ob_type)
2829{
2830 MFEM_VERIFY(p >= 1, "ND_FECollection requires order >= 1.");
2831 MFEM_VERIFY(dim >= 1 && dim <= 3, "ND_FECollection requires 1 <= dim <= 3.");
2832
2833 const int pm1 = p - 1, pm2 = p - 2;
2834
2837 {
2838 snprintf(nd_name, 32, "ND_%dD_P%d", dim, p);
2839 }
2840 else
2841 {
2842 snprintf(nd_name, 32, "ND@%c%c_%dD_P%d", (int)BasisType::GetChar(cb_type),
2844 }
2845
2846 for (int g = 0; g < Geometry::NumGeom; g++)
2847 {
2848 ND_Elements[g] = NULL;
2849 ND_dof[g] = 0;
2850 }
2851 for (int i = 0; i < 2; i++)
2852 {
2853 SegDofOrd[i] = NULL;
2854 }
2855 for (int i = 0; i < 6; i++)
2856 {
2857 TriDofOrd[i] = NULL;
2858 }
2859 for (int i = 0; i < 8; i++)
2860 {
2861 QuadDofOrd[i] = NULL;
2862 }
2863
2864 int op_type = BasisType::GetQuadrature1D(ob_type);
2865 int cp_type = BasisType::GetQuadrature1D(cb_type);
2866
2867 // Error checking
2869 {
2870 const char *ob_name = BasisType::Name(ob_type);
2871 MFEM_ABORT("Invalid open basis point type: " << ob_name);
2872 }
2874 {
2875 const char *cb_name = BasisType::Name(cb_type);
2876 MFEM_ABORT("Invalid closed basis point type: " << cb_name);
2877 }
2878
2879 if (dim >= 1)
2880 {
2883
2884 SegDofOrd[0] = (p > 0) ? new int[2*p] : nullptr;
2885 SegDofOrd[1] = SegDofOrd[0] + p;
2886 for (int i = 0; i < p; i++)
2887 {
2888 SegDofOrd[0][i] = i;
2889 SegDofOrd[1][i] = -1 - (pm1 - i);
2890 }
2891 }
2892
2893 if (dim >= 2)
2894 {
2896 ob_type);
2897 ND_dof[Geometry::SQUARE] = 2*p*pm1;
2898
2899 // TODO: cb_type and ob_type for triangles
2902
2903 int QuadDof = ND_dof[Geometry::SQUARE];
2904 QuadDofOrd[0] = (QuadDof > 0) ? new int[8*QuadDof] : nullptr;
2905 for (int i = 1; i < 8; i++)
2906 {
2907 QuadDofOrd[i] = QuadDofOrd[i-1] + QuadDof;
2908 }
2909 // see Mesh::GetQuadOrientation in mesh/mesh.cpp
2910 for (int j = 0; j < pm1; j++)
2911 {
2912 for (int i = 0; i < p; i++)
2913 {
2914 int d1 = i + j*p; // x-component
2915 int d2 = p*pm1 + j + i*pm1; // y-component
2916 // (0,1,2,3)
2917 QuadDofOrd[0][d1] = d1;
2918 QuadDofOrd[0][d2] = d2;
2919 // (0,3,2,1)
2920 QuadDofOrd[1][d1] = d2;
2921 QuadDofOrd[1][d2] = d1;
2922 // (1,2,3,0)
2923 // QuadDofOrd[2][d1] = p*pm1 + (pm2 - j) + i*pm1;
2924 // QuadDofOrd[2][d2] = -1 - ((pm1 - i) + j*p);
2925 QuadDofOrd[2][d1] = -1 - (p*pm1 + j + (pm1 - i)*pm1);
2926 QuadDofOrd[2][d2] = i + (pm2 - j)*p;
2927 // (1,0,3,2)
2928 QuadDofOrd[3][d1] = -1 - ((pm1 - i) + j*p);
2929 QuadDofOrd[3][d2] = p*pm1 + (pm2 - j) + i*pm1;
2930 // (2,3,0,1)
2931 QuadDofOrd[4][d1] = -1 - ((pm1 - i) + (pm2 - j)*p);
2932 QuadDofOrd[4][d2] = -1 - (p*pm1 + (pm2 - j) + (pm1 - i)*pm1);
2933 // (2,1,0,3)
2934 QuadDofOrd[5][d1] = -1 - (p*pm1 + (pm2 - j) + (pm1 - i)*pm1);
2935 QuadDofOrd[5][d2] = -1 - ((pm1 - i) + (pm2 - j)*p);
2936 // (3,0,1,2)
2937 // QuadDofOrd[6][d1] = -1 - (p*pm1 + j + (pm1 - i)*pm1);
2938 // QuadDofOrd[6][d2] = i + (pm2 - j)*p;
2939 QuadDofOrd[6][d1] = p*pm1 + (pm2 - j) + i*pm1;
2940 QuadDofOrd[6][d2] = -1 - ((pm1 - i) + j*p);
2941 // (3,2,1,0)
2942 QuadDofOrd[7][d1] = i + (pm2 - j)*p;
2943 QuadDofOrd[7][d2] = -1 - (p*pm1 + j + (pm1 - i)*pm1);
2944 }
2945 }
2946
2947 int TriDof = ND_dof[Geometry::TRIANGLE];
2948 TriDofOrd[0] = (TriDof > 0) ? new int[6*TriDof] : nullptr;
2949 for (int i = 1; i < 6; i++)
2950 {
2951 TriDofOrd[i] = TriDofOrd[i-1] + TriDof;
2952 }
2953 // see Mesh::GetTriOrientation in mesh/mesh.cpp,
2954 // the constructor of H1_FECollection
2955 for (int j = 0; j <= pm2; j++)
2956 {
2957 for (int i = 0; i + j <= pm2; i++)
2958 {
2959 int k0 = p*pm1 - (p - j)*(pm1 - j) + 2*i;
2960 int k1 = 2*pm2 - 2*i + ((2*p-3)-j)*j;
2961 int k2 = 2*pm2 - 2*j + ((2*p-3)-i)*i;
2962 int k3 = p*pm1 - 2 - 3*j - i - (i+j)*(i+j);
2963 int k4 = p*pm1 - 2 - 3*i - j - (i+j)*(i+j);
2964 int k5 = p*pm1 - (p - i)*(pm1 - i) + 2*j;
2965
2966 // (0,1,2)
2967 TriDofOrd[0][k0 ] = k0;
2968 TriDofOrd[0][k0+1] = k0 + 1;
2969 // (1,0,2)
2970 TriDofOrd[1][k0 ] = k1;
2971 TriDofOrd[1][k0+1] = k1 + 1;
2972 // (2,0,1)
2973 TriDofOrd[2][k0 ] = k2;
2974 TriDofOrd[2][k0+1] = k2 + 1;
2975 // (2,1,0)
2976 TriDofOrd[3][k0 ] = k3;
2977 TriDofOrd[3][k0+1] = k3 + 1;
2978 // (1,2,0)
2979 TriDofOrd[4][k0 ] = k4;
2980 TriDofOrd[4][k0+1] = k4 + 1;
2981 // (0,2,1)
2982 TriDofOrd[5][k0 ] = k5;
2983 TriDofOrd[5][k0+1] = k5 + 1;
2984 }
2985 }
2986 }
2987
2988 if (dim >= 3)
2989 {
2991 ND_dof[Geometry::CUBE] = 3*p*pm1*pm1;
2992
2993 // TODO: cb_type and ob_type for tets
2995 ND_dof[Geometry::TETRAHEDRON] = p*pm1*pm2/2;
2996
2998 ND_dof[Geometry::PRISM] = p*pm1*(3*p-4)/2;
2999
3001 ND_dof[Geometry::PYRAMID] = 3*p*pm1*pm1;
3002 }
3003}
3004
3005const FiniteElement *
3007{
3008 return ND_Elements[GeomType];
3009}
3010
3013{
3014 if (!Geometry::IsTensorProduct(GeomType) && this->GetOrder() > 1)
3015 {
3017 }
3018 else
3019 {
3020 return NULL;
3021 }
3022}
3023
3025 int Or) const
3026{
3027 if (GeomType == Geometry::SEGMENT)
3028 {
3029 return (Or > 0) ? SegDofOrd[0] : SegDofOrd[1];
3030 }
3031 else if (GeomType == Geometry::TRIANGLE)
3032 {
3033 return TriDofOrd[Or%6];
3034 }
3035 else if (GeomType == Geometry::SQUARE)
3036 {
3037 return QuadDofOrd[Or%8];
3038 }
3039 return NULL;
3040}
3041
3043{
3044 int tr_p, tr_dim, tr_cb_type, tr_ob_type;
3045
3046 tr_p = ND_dof[Geometry::SEGMENT];
3047 if (nd_name[2] == '_') // ND_
3048 {
3049 tr_dim = atoi(nd_name + 3);
3050 tr_cb_type = BasisType::GaussLobatto;
3051 tr_ob_type = BasisType::GaussLegendre;
3052 }
3053 else // ND@
3054 {
3055 tr_dim = atoi(nd_name + 6);
3056 tr_cb_type = BasisType::GetType(nd_name[3]);
3057 tr_ob_type = BasisType::GetType(nd_name[4]);
3058 }
3059 return new ND_Trace_FECollection(tr_p, tr_dim, tr_cb_type, tr_ob_type);
3060}
3061
3063{
3064 delete [] SegDofOrd[0];
3065 delete [] TriDofOrd[0];
3066 delete [] QuadDofOrd[0];
3067 for (int g = 0; g < Geometry::NumGeom; g++)
3068 {
3069 delete ND_Elements[g];
3070 }
3071}
3072
3073
3075 const int cb_type,
3076 const int ob_type)
3077 : ND_FECollection(p, dim-1, cb_type, ob_type)
3078{
3081 {
3082 snprintf(nd_name, 32, "ND_Trace_%dD_P%d", dim, p);
3083 }
3084 else
3085 {
3086 snprintf(nd_name, 32, "ND_Trace@%c%c_%dD_P%d",
3089 }
3090}
3091
3092
3094 const int cb_type, const int ob_type)
3096{
3097 MFEM_VERIFY(p >= 1, "ND_R1D_FECollection requires order >= 1.");
3098 MFEM_VERIFY(dim == 1, "ND_R1D_FECollection requires dim == 1.");
3099
3100 if (cb_type == BasisType::GaussLobatto &&
3101 ob_type == BasisType::GaussLegendre)
3102 {
3103 snprintf(nd_name, 32, "ND_R1D_%dD_P%d", dim, p);
3104 }
3105 else
3106 {
3107 snprintf(nd_name, 32, "ND_R1D@%c%c_%dD_P%d",
3108 (int)BasisType::GetChar(cb_type),
3109 (int)BasisType::GetChar(ob_type), dim, p);
3110 }
3111
3112 for (int g = 0; g < Geometry::NumGeom; g++)
3113 {
3114 ND_Elements[g] = NULL;
3115 ND_dof[g] = 0;
3116 }
3117
3118 int op_type = BasisType::GetQuadrature1D(ob_type);
3119 int cp_type = BasisType::GetQuadrature1D(cb_type);
3120
3121 // Error checking
3123 {
3124 const char *ob_name = BasisType::Name(ob_type);
3125 MFEM_ABORT("Invalid open basis point type: " << ob_name);
3126 }
3128 {
3129 const char *cb_name = BasisType::Name(cb_type);
3130 MFEM_ABORT("Invalid closed basis point type: " << cb_name);
3131 }
3132
3135
3137 cb_type,
3138 ob_type);
3139 ND_dof[Geometry::SEGMENT] = 3 * p - 2;
3140}
3141
3143 int Or) const
3144{
3145 return NULL;
3146}
3147
3152
3154{
3155 for (int g = 0; g < Geometry::NumGeom; g++)
3156 {
3157 delete ND_Elements[g];
3158 }
3159}
3160
3161
3163 const int cb_type, const int ob_type)
3165{
3166 MFEM_VERIFY(p >= 0, "RT_R1D_FECollection requires order >= 0.");
3167 MFEM_VERIFY(dim == 1, "RT_R1D_FECollection requires dim == 1.");
3168
3169 if (cb_type == BasisType::GaussLobatto &&
3170 ob_type == BasisType::GaussLegendre)
3171 {
3172 snprintf(rt_name, 32, "RT_R1D_%dD_P%d", dim, p);
3173 }
3174 else
3175 {
3176 snprintf(rt_name, 32, "RT_R1D@%c%c_%dD_P%d",
3177 (int)BasisType::GetChar(cb_type),
3178 (int)BasisType::GetChar(ob_type), dim, p);
3179 }
3180
3181 for (int g = 0; g < Geometry::NumGeom; g++)
3182 {
3183 RT_Elements[g] = NULL;
3184 RT_dof[g] = 0;
3185 }
3186
3187 int op_type = BasisType::GetQuadrature1D(ob_type);
3188 int cp_type = BasisType::GetQuadrature1D(cb_type);
3189
3190 // Error checking
3192 {
3193 const char *ob_name = BasisType::Name(ob_type);
3194 MFEM_ABORT("Invalid open basis point type: " << ob_name);
3195 }
3197 {
3198 const char *cb_name = BasisType::Name(cb_type);
3199 MFEM_ABORT("Invalid closed basis point type: " << cb_name);
3200 }
3201
3204
3206 cb_type,
3207 ob_type);
3208 RT_dof[Geometry::SEGMENT] = 3 * p + 2;
3209}
3210
3212 int Or) const
3213{
3214 return NULL;
3215}
3216
3218{
3219 MFEM_ABORT("this method is not implemented in RT_R1D_FECollection!");
3220 return NULL;
3221}
3222
3224{
3225 for (int g = 0; g < Geometry::NumGeom; g++)
3226 {
3227 delete RT_Elements[g];
3228 }
3229}
3230
3231
3233 const int cb_type, const int ob_type)
3235{
3236 MFEM_VERIFY(p >= 1, "ND_R2D_FECollection requires order >= 1.");
3237 MFEM_VERIFY(dim >= 1 && dim <= 2,
3238 "ND_R2D_FECollection requires 1 <= dim <= 2.");
3239
3240 const int pm1 = p - 1, pm2 = p - 2;
3241
3242 if (cb_type == BasisType::GaussLobatto &&
3243 ob_type == BasisType::GaussLegendre)
3244 {
3245 snprintf(nd_name, 32, "ND_R2D_%dD_P%d", dim, p);
3246 }
3247 else
3248 {
3249 snprintf(nd_name, 32, "ND_R2D@%c%c_%dD_P%d",
3250 (int)BasisType::GetChar(cb_type),
3251 (int)BasisType::GetChar(ob_type), dim, p);
3252 }
3253
3254 for (int g = 0; g < Geometry::NumGeom; g++)
3255 {
3256 ND_Elements[g] = NULL;
3257 ND_dof[g] = 0;
3258 }
3259 for (int i = 0; i < 2; i++)
3260 {
3261 SegDofOrd[i] = NULL;
3262 }
3263
3264 int op_type = BasisType::GetQuadrature1D(ob_type);
3265 int cp_type = BasisType::GetQuadrature1D(cb_type);
3266
3267 // Error checking
3269 {
3270 const char *ob_name = BasisType::Name(ob_type);
3271 MFEM_ABORT("Invalid open basis point type: " << ob_name);
3272 }
3274 {
3275 const char *cb_name = BasisType::Name(cb_type);
3276 MFEM_ABORT("Invalid closed basis point type: " << cb_name);
3277 }
3278
3280
3281 if (dim >= 1)
3282 {
3284 cb_type,
3285 ob_type);
3286 ND_dof[Geometry::SEGMENT] = 2 * p - 1;
3287
3288 SegDofOrd[0] = (4*p > 2) ? new int[4 * p - 2] : nullptr;
3289 SegDofOrd[1] = SegDofOrd[0] + 2 * p - 1;
3290 for (int i = 0; i < p; i++)
3291 {
3292 SegDofOrd[0][i] = i;
3293 SegDofOrd[1][i] = -1 - (pm1 - i);
3294 }
3295 for (int i = 0; i < pm1; i++)
3296 {
3297 SegDofOrd[0][p+i] = p + i;
3298 SegDofOrd[1][p+i] = 2 * pm1 - i;
3299 }
3300 }
3301
3302 if (dim >= 2)
3303 {
3305 cb_type,
3306 ob_type);
3307 ND_dof[Geometry::SQUARE] = 2*p*pm1 + pm1*pm1;
3308
3309 // TODO: cb_type and ob_type for triangles
3311 ND_dof[Geometry::TRIANGLE] = p*pm1 + (pm1*pm2)/2;
3312 }
3313}
3314
3316 int Or) const
3317{
3318 if (GeomType == Geometry::SEGMENT)
3319 {
3320 return (Or > 0) ? SegDofOrd[0] : SegDofOrd[1];
3321 }
3322 return NULL;
3323}
3324
3326{
3327 int p, dim, cb_type, ob_type;
3328
3330 if (nd_name[5] == '_') // ND_R2D_
3331 {
3332 dim = atoi(nd_name + 6);
3333 cb_type = BasisType::GaussLobatto;
3334 ob_type = BasisType::GaussLegendre;
3335 }
3336 else // ND_R2D@
3337 {
3338 dim = atoi(nd_name + 9);
3339 cb_type = BasisType::GetType(nd_name[6]);
3340 ob_type = BasisType::GetType(nd_name[7]);
3341 }
3342 return new ND_R2D_Trace_FECollection(p, dim, cb_type, ob_type);
3343}
3344
3346{
3347 delete [] SegDofOrd[0];
3348 for (int g = 0; g < Geometry::NumGeom; g++)
3349 {
3350 delete ND_Elements[g];
3351 }
3352}
3353
3354
3356 const int cb_type,
3357 const int ob_type)
3358 : ND_R2D_FECollection(p, dim-1, cb_type, ob_type)
3359{
3360 if (cb_type == BasisType::GaussLobatto &&
3361 ob_type == BasisType::GaussLegendre)
3362 {
3363 snprintf(nd_name, 32, "ND_R2D_Trace_%dD_P%d", dim, p);
3364 }
3365 else
3366 {
3367 snprintf(nd_name, 32, "ND_R2D_Trace@%c%c_%dD_P%d",
3368 (int)BasisType::GetChar(cb_type),
3369 (int)BasisType::GetChar(ob_type), dim, p);
3370 }
3371}
3372
3373
3375 const int cb_type, const int ob_type)
3377 ob_type(ob_type)
3378{
3379 MFEM_VERIFY(p >= 0, "RT_R2D_FECollection requires order >= 0.");
3380 MFEM_VERIFY(dim >= 1 && dim <= 2,
3381 "RT_R2D_FECollection requires 1 <= dim <= 2.");
3382
3383 int cp_type = BasisType::GetQuadrature1D(cb_type);
3384 int op_type = BasisType::GetQuadrature1D(ob_type);
3385
3387 {
3388 const char *cb_name = BasisType::Name(cb_type); // this may abort
3389 MFEM_ABORT("unknown closed BasisType: " << cb_name);
3390 }
3392 {
3393 const char *ob_name = BasisType::Name(ob_type); // this may abort
3394 MFEM_ABORT("unknown open BasisType: " << ob_name);
3395 }
3396
3398
3399 if (cb_type == BasisType::GaussLobatto &&
3401 {
3402 snprintf(rt_name, 32, "RT_R2D_%dD_P%d", dim, p);
3403 }
3404 else
3405 {
3406 snprintf(rt_name, 32, "RT_R2D@%c%c_%dD_P%d",
3407 (int)BasisType::GetChar(cb_type),
3409 }
3410
3411 const int pp1 = p + 1;
3412 const int pp2 = p + 2;
3413 if (dim == 2)
3414 {
3415 // TODO: cb_type, ob_type for triangles
3417 RT_dof[Geometry::TRIANGLE] = p*pp1 + (pp1 * pp2) / 2;
3418
3420 cb_type,
3421 ob_type);
3422 // two vector components * n_unk_face *
3423 RT_dof[Geometry::SQUARE] = 2*p*pp1 + pp1*pp1;
3424 }
3425}
3426
3427// This is a special protected constructor only used by RT_Trace_FECollection
3428// and DG_Interface_FECollection
3430 const int map_type,
3431 const bool signs, const int ob_type)
3432 : ob_type(ob_type)
3433{
3436 {
3437 const char *ob_name = BasisType::Name(ob_type); // this may abort
3438 MFEM_ABORT("Invalid open basis type: " << ob_name);
3439 }
3440 InitFaces(p, dim, map_type, signs);
3441}
3442
3443void RT_R2D_FECollection::InitFaces(const int p, const int dim,
3444 const int map_type,
3445 const bool signs)
3446{
3447 int op_type = BasisType::GetQuadrature1D(ob_type);
3448
3449 MFEM_VERIFY(Quadrature1D::CheckOpen(op_type) != Quadrature1D::Invalid,
3450 "invalid open point type");
3451
3452 const int pp1 = p + 1;
3453
3454 for (int g = 0; g < Geometry::NumGeom; g++)
3455 {
3456 RT_Elements[g] = NULL;
3457 RT_dof[g] = 0;
3458 }
3459 // Degree of Freedom orderings
3460 for (int i = 0; i < 2; i++)
3461 {
3462 SegDofOrd[i] = NULL;
3463 }
3464
3465 if (dim == 2)
3466 {
3468 l2_seg->SetMapType(map_type);
3471
3472 SegDofOrd[0] = (pp1 > 0) ? new int[2*pp1] : nullptr;
3473 SegDofOrd[1] = SegDofOrd[0] + pp1;
3474 for (int i = 0; i <= p; i++)
3475 {
3476 SegDofOrd[0][i] = i;
3477 SegDofOrd[1][i] = signs ? (-1 - (p - i)) : (p - i);
3478 }
3479 }
3480}
3481
3483 int Or) const
3484{
3485 if (GeomType == Geometry::SEGMENT)
3486 {
3487 return (Or > 0) ? SegDofOrd[0] : SegDofOrd[1];
3488 }
3489 return NULL;
3490}
3491
3493{
3494 int dim, p;
3495 if (!strncmp(rt_name, "RT_R2D_", 7))
3496 {
3497 dim = atoi(rt_name + 7);
3498 p = atoi(rt_name + 11);
3499 }
3500 else // rt_name = RT_R2D@.._.D_P*
3501 {
3502 dim = atoi(rt_name + 10);
3503 p = atoi(rt_name + 14);
3504 }
3506}
3507
3509{
3510 delete [] SegDofOrd[0];
3511 for (int g = 0; g < Geometry::NumGeom; g++)
3512 {
3513 delete RT_Elements[g];
3514 }
3515}
3516
3517
3519 const int map_type,
3520 const int ob_type)
3521 : RT_R2D_FECollection(p, dim-1, map_type, true, ob_type)
3522{
3523 const char *prefix =
3524 (map_type == FiniteElement::INTEGRAL) ? "RT_R2D_Trace" : "RT_R2D_ValTrace";
3525 char ob_str[3] = { '\0', '\0', '\0' };
3526
3528 {
3529 ob_str[0] = '@';
3530 ob_str[1] = BasisType::GetChar(ob_type);
3531 }
3532 snprintf(rt_name, 32, "%s%s_%dD_P%d", prefix, ob_str, dim, p);
3533
3534 MFEM_VERIFY(dim == 2, "Wrong dimension, dim = " << dim);
3535}
3536
3537
3539{
3540 snprintf(d_name, 32, "Local_%s", fe_name);
3541
3542 Local_Element = NULL;
3543
3544 if (!strcmp(fe_name, "BiCubic2DFiniteElement") ||
3545 !strcmp(fe_name, "Quad_Q3"))
3546 {
3547 GeomType = Geometry::SQUARE;
3548 Local_Element = new BiCubic2DFiniteElement;
3549 }
3550 else if (!strcmp(fe_name, "Nedelec1HexFiniteElement") ||
3551 !strcmp(fe_name, "Hex_ND1"))
3552 {
3553 GeomType = Geometry::CUBE;
3554 Local_Element = new Nedelec1HexFiniteElement;
3555 }
3556 else if (!strncmp(fe_name, "H1_", 3))
3557 {
3558 GeomType = Geometry::SQUARE;
3559 Local_Element = new H1_QuadrilateralElement(atoi(fe_name + 7));
3560 }
3561 else if (!strncmp(fe_name, "H1Pos_", 6))
3562 {
3563 GeomType = Geometry::SQUARE;
3564 Local_Element = new H1Pos_QuadrilateralElement(atoi(fe_name + 10));
3565 }
3566 else if (!strncmp(fe_name, "L2_", 3))
3567 {
3568 GeomType = Geometry::SQUARE;
3569 Local_Element = new L2_QuadrilateralElement(atoi(fe_name + 7));
3570 }
3571 else
3572 {
3573 mfem::err << "Local_FECollection::Local_FECollection : fe_name = "
3574 << fe_name << endl;
3575 mfem_error();
3576 }
3577}
3578
3579
3581 : FiniteElementCollection((Order == VariableOrder) ? 1 : Order)
3582{
3583 const int order = (Order == VariableOrder) ? 1 : Order;
3585 SegmentFE = new NURBS1DFiniteElement(order);
3588
3589 SetOrder(Order);
3590}
3591
3592void NURBSFECollection::SetOrder(int Order) const
3593{
3594 mOrder = Order;
3595 if (Order != VariableOrder)
3596 {
3597 snprintf(name, 16, "NURBS%i", Order);
3598 }
3599 else
3600 {
3601 snprintf(name, 16, "NURBS");
3602 }
3603}
3604
3606{
3607 delete PointFE;
3608 delete SegmentFE;
3609 delete QuadrilateralFE;
3610 delete ParallelepipedFE;
3611}
3612
3613const FiniteElement *
3615{
3616 switch (GeomType)
3617 {
3618 case Geometry::POINT: return PointFE;
3619 case Geometry::SEGMENT: return SegmentFE;
3620 case Geometry::SQUARE: return QuadrilateralFE;
3621 case Geometry::CUBE: return ParallelepipedFE;
3622 default:
3623 if (error_mode == RETURN_NULL) { return nullptr; }
3624 mfem_error ("NURBSFECollection: unknown geometry type.");
3625 }
3626 return SegmentFE; // Make some compilers happy
3627}
3628
3630{
3631 mfem_error("NURBSFECollection::DofForGeometry");
3632 return 0; // Make some compilers happy
3633}
3634
3636 int Or) const
3637{
3638 mfem_error("NURBSFECollection::DofOrderForOrientation");
3639 return NULL;
3640}
3641
3643{
3644 MFEM_ABORT("NURBS finite elements can not be statically condensed!");
3645 return NULL;
3646}
3647
3648
3650 : NURBSFECollection((Order == VariableOrder) ? 1 : Order)
3651{
3652 const int order = (Order == VariableOrder) ? 1 : Order;
3653
3654 SegmentFE = new NURBS1DFiniteElement(order);
3655 QuadrilateralFE = new NURBS2DFiniteElement(order);
3656
3657 QuadrilateralVFE = new NURBS_HDiv2DFiniteElement(order);
3658 ParallelepipedVFE = new NURBS_HDiv3DFiniteElement(order);
3659
3660 if (dim != -1) { SetDim(dim); }
3661 SetOrder(Order);
3662}
3663
3665{
3666 if (dim == 2)
3667 {
3668 sFE = SegmentFE;
3669 qFE = QuadrilateralVFE;
3670 hFE = nullptr;
3671 }
3672 else if (dim == 3)
3673 {
3674 sFE = nullptr;
3675 qFE = QuadrilateralFE;
3676 hFE = ParallelepipedVFE;
3677 }
3678 else
3679 {
3680 mfem::err<<"Dimension = "<<dim<<endl;
3681 mfem_error ("NURBS_HDivFECollection: wrong dimension!");
3682 }
3683}
3684
3686{
3687 delete SegmentFE;
3688 delete QuadrilateralFE;
3689 delete QuadrilateralVFE;
3690 delete ParallelepipedVFE;
3691}
3692
3693const FiniteElement *
3695{
3696 switch (GeomType)
3697 {
3698 case Geometry::SEGMENT: return sFE;
3699 case Geometry::SQUARE: return qFE;
3700 case Geometry::CUBE: return hFE;
3701 default:
3702 if (error_mode == RETURN_NULL) { return nullptr; }
3703 mfem_error ("NURBS_HDivFECollection: unknown geometry type.");
3704 }
3705 return QuadrilateralFE; // Make some compilers happy
3706}
3707
3709{
3710 mOrder = Order;
3711 if (Order != VariableOrder)
3712 {
3713 snprintf(name, 16, "NURBS_HDiv%i", Order);
3714 }
3715 else
3716 {
3717 snprintf(name, 16, "NURBS_HDiv");
3718 }
3719}
3720
3722{
3723 mfem_error("NURBS_HDivFECollection::DofForGeometry");
3724 return 0; // Make some compilers happy
3725}
3726
3728 Geometry::Type GeomType,
3729 int Or) const
3730{
3731 mfem_error("NURBS_HDivFECollection::DofOrderForOrientation");
3732 return NULL;
3733}
3734
3736{
3737 MFEM_ABORT("NURBS finite elements can not be statically condensed!");
3738 return NULL;
3739}
3740
3742 : NURBSFECollection((Order == VariableOrder) ? 1 : Order)
3743{
3744 const int order = (Order == VariableOrder) ? 1 : Order;
3745
3746 SegmentFE = new NURBS1DFiniteElement(order+1);
3747 QuadrilateralFE = new NURBS2DFiniteElement(order+1);
3748
3749 QuadrilateralVFE = new NURBS_HCurl2DFiniteElement(order);
3750 ParallelepipedVFE = new NURBS_HCurl3DFiniteElement(order);
3751 if (dim != -1) { SetDim(dim); }
3752 SetOrder(Order);
3753}
3754
3756{
3757 if (dim == 2)
3758 {
3759 sFE = SegmentFE;
3760 qFE = QuadrilateralVFE;
3761 hFE = nullptr;
3762 }
3763 else if (dim == 3)
3764 {
3765 sFE = nullptr;
3766 qFE = QuadrilateralFE;
3767 hFE = ParallelepipedVFE;
3768 }
3769 else
3770 {
3771 mfem::err<<"Dimension = "<<dim<<endl;
3772 mfem_error ("NURBS_HCurlFECollection: wrong dimension!");
3773 }
3774}
3775
3776
3777
3779{
3780 delete SegmentFE;
3781 delete QuadrilateralFE;
3782 delete QuadrilateralVFE;
3783 delete ParallelepipedVFE;
3784}
3785
3786const FiniteElement *
3788{
3789 switch (GeomType)
3790 {
3791 case Geometry::SEGMENT: return sFE;
3792 case Geometry::SQUARE: return qFE;
3793 case Geometry::CUBE: return hFE;
3794 default:
3795 if (error_mode == RETURN_NULL) { return nullptr; }
3796 mfem_error ("NURBS_HCurlFECollection: unknown geometry type.");
3797 }
3798 return QuadrilateralFE; // Make some compilers happy
3799}
3800
3802{
3803 mOrder = Order;
3804 if (Order != VariableOrder)
3805 {
3806 snprintf(name, 16, "NURBS_HCurl%i", Order);
3807 }
3808 else
3809 {
3810 snprintf(name, 16, "NURBS_HCurl");
3811 }
3812}
3813
3815{
3816 mfem_error("NURBS_HCurlFECollection::DofForGeometry");
3817 return 0; // Make some compilers happy
3818}
3819
3821 Geometry::Type GeomType,
3822 int Or) const
3823{
3824 mfem_error("NURBS_HCurlFECollection::DofOrderForOrientation");
3825 return NULL;
3826}
3827
3829{
3830 MFEM_ABORT("NURBS finite elements can not be statically condensed!");
3831 return NULL;
3832}
3833
3834
3835
3836}
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:869
int Size() const
Return the logical size of the array.
Definition array.hpp:192
T * GetData()
Returns the data.
Definition array.hpp:159
static int GetQuadrature1D(int b_type)
Get the corresponding Quadrature1D constant, when that makes sense; otherwise return Quadrature1D::In...
Definition fe_base.hpp:65
static int Check(int b_type)
If the input does not represent a valid BasisType, abort with an error; otherwise return the input.
Definition fe_base.hpp:49
static char GetChar(int b_type)
Check and convert a BasisType constant to a char basis identifier.
Definition fe_base.hpp:108
static const char * Name(int b_type)
Check and convert a BasisType constant to a string identifier.
Definition fe_base.hpp:96
static int GetType(char b_ident)
Convert char basis identifier to a BasisType constant.
Definition fe_base.hpp:115
@ Serendipity
Serendipity basis (squares / cubes)
Definition fe_base.hpp:41
@ GaussLobatto
Closed type.
Definition fe_base.hpp:36
@ GaussLegendre
Open type.
Definition fe_base.hpp:35
@ Positive
Bernstein polynomials.
Definition fe_base.hpp:37
A 2D bi-cubic element on a square with uniformly spaces nodes.
Piecewise-constant discontinuous finite elements in 2D. This class is kept only for backward compatib...
Definition fe_coll.hpp:1144
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1112
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1126
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1099
Piecewise-constant discontinuous finite elements in 3D. This class is kept only for backward compatib...
Definition fe_coll.hpp:1335
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1439
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1424
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1457
Crouzeix-Raviart nonconforming elements in 2D.
Definition fe_coll.hpp:1022
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:947
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:961
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:932
Piecewise-cubic discontinuous finite elements in 2D. This class is kept only for backward compatibili...
Definition fe_coll.hpp:1310
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1374
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1360
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1346
Piecewise-(bi)cubic continuous finite elements.
Definition fe_coll.hpp:991
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:880
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:897
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:862
DG_Interface_FECollection(const int p, const int dim, const int map_type=FiniteElement::VALUE, const int ob_type=BasisType::GaussLegendre)
Definition fe_coll.cpp:2803
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Definition fe_coll.hpp:27
ErrorMode error_mode
How to treat errors in FiniteElementForGeometry() calls.
Definition fe_coll.hpp:286
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const =0
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
int GetRangeType(int dim) const
Definition fe_coll.cpp:40
static FiniteElementCollection * New(const char *name)
Factory method: return a newly allocated FiniteElementCollection according to the given name.
Definition fe_coll.cpp:124
int GetOrder() const
Return the order (polynomial degree) of the FE collection, corresponding to the order/degree returned...
Definition fe_coll.hpp:248
int HasFaceDofs(Geometry::Type geom, int p) const
Definition fe_coll.cpp:100
int GetDerivRangeType(int dim) const
Definition fe_coll.cpp:50
virtual FiniteElementCollection * Clone(int p) const
Instantiate a new collection of the same type with a different order.
Definition fe_coll.cpp:462
virtual int DofForGeometry(Geometry::Type GeomType) const =0
int GetNumDof(Geometry::Type geom, int p) const
Variable order version of DofForGeometry().
Definition fe_coll.hpp:226
virtual const FiniteElement * FiniteElementForDim(int dim) const
Returns the first non-NULL FiniteElement for the given dimension.
Definition fe_coll.cpp:26
static void GetEdge(int &nv, v_t &v, int &ne, int &e, int &eo, const int edge_info)
Definition fe_coll.cpp:498
void InitVarOrder(int p) const
Definition fe_coll.cpp:470
int GetDerivType(int dim) const
Definition fe_coll.cpp:70
const int base_p
Order as returned by GetOrder().
Definition fe_coll.hpp:266
virtual const char * Name() const
Definition fe_coll.hpp:79
int GetRangeDim(int dim) const
Definition fe_coll.cpp:90
int GetDerivMapType(int dim) const
Definition fe_coll.cpp:80
static void GetFace(int &nv, v_t &v, int &ne, e_t &e, eo_t &eo, int &nf, int &f, Geometry::Type &fg, int &fo, const int face_info)
Definition fe_coll.cpp:518
int GetMapType(int dim) const
Definition fe_coll.cpp:60
Array< FiniteElementCollection * > var_orders
Definition fe_coll.hpp:273
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const =0
virtual FiniteElementCollection * GetTraceCollection() const
Returns a collection of the trace elements.
Definition fe_coll.cpp:118
void SubDofOrder(Geometry::Type Geom, int SDim, int Info, Array< int > &dofs) const
Get the local dofs for a given sub-manifold.
Definition fe_coll.cpp:563
static void GetNVE(int &nv, int &ne)
Definition fe_coll.cpp:488
ErrorMode
How to treat errors in FiniteElementForGeometry() calls.
Definition fe_coll.hpp:277
@ RETURN_NULL
Return NULL on errors.
Definition fe_coll.hpp:278
Abstract class for all finite elements.
Definition fe_base.hpp:294
int GetDerivMapType() const
Returns the FiniteElement::DerivType of the element describing how reference function derivatives are...
Definition fe_base.hpp:446
int GetRangeDim() const
Returns the vector dimension for vector-valued finite elements, which is also the dimension of the in...
Definition fe_base.hpp:387
int GetDerivType() const
Returns the FiniteElement::DerivType of the element describing the spatial derivative method implemen...
Definition fe_base.hpp:441
virtual const StatelessDofTransformation * GetDofTransformation() const
Return a DoF transformation object for this particular type of basis.
Definition fe_base.hpp:687
int GetMapType() const
Returns the FiniteElement::MapType of the element describing how reference functions are mapped to ph...
Definition fe_base.hpp:436
int GetRangeType() const
Returns the FiniteElement::RangeType of the element, one of {SCALAR, VECTOR}.
Definition fe_base.hpp:427
@ NONE
No derivatives implemented.
Definition fe_base.hpp:364
int GetDerivRangeType() const
Returns the FiniteElement::RangeType of the element derivative, either SCALAR or VECTOR.
Definition fe_base.hpp:431
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition fe_base.hpp:410
Version of LinearDiscont2DFECollection with dofs in the Gaussian points.
Definition fe_coll.hpp:1191
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1201
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1170
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1185
Version of QuadraticDiscont2DFECollection with dofs in the Gaussian points.
Definition fe_coll.hpp:1284
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1322
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1306
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1338
static const int NumGeom
Definition geom.hpp:46
static const int Dimension[NumGeom]
Definition geom.hpp:51
static const char * Name[NumGeom]
Definition geom.hpp:49
static bool IsTensorProduct(Type geom)
Definition geom.hpp:112
static const int DimStart[MaxDim+2]
Definition geom.hpp:52
Arbitrary order H1-conforming (continuous) finite elements with positive basis functions.
Definition fe_coll.hpp:338
Arbitrary order H1 elements in 3D utilizing the Bernstein basis on a cube.
Definition fe_pos.hpp:163
Arbitrary order H1 elements in 2D utilizing the Bernstein basis on a square.
Definition fe_pos.hpp:144
Arbitrary order H1 elements in 1D utilizing the Bernstein basis.
Definition fe_pos.hpp:121
Arbitrary order H1 elements in 2D utilizing the Bernstein basis on a triangle.
Definition fe_pos.hpp:182
Arbitrary order H1 elements in 3D utilizing the Bernstein basis on a wedge.
Definition fe_pos.hpp:269
Arbitrary order H1 serendipity elements in 2D on a quad.
Definition fe_ser.hpp:22
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:291
H1_FECollection(const int p, const int dim=3, const int btype=BasisType::GaussLobatto, const int pyr_type=ScalarPyramid::DefaultType)
Definition fe_coll.cpp:1741
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:2082
virtual ~H1_FECollection()
Definition fe_coll.cpp:2153
FiniteElementCollection * GetTraceCollection() const override
Returns a collection of the trace elements.
Definition fe_coll.cpp:2109
int H1_dof[Geometry::NumGeom]
Definition fe_coll.hpp:296
FiniteElement * H1_Elements[Geometry::NumGeom]
Definition fe_coll.hpp:295
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:2087
const int * GetDofMap(Geometry::Type GeomType) const
Get the Cartesian to local H1 dof map.
Definition fe_coll.cpp:2128
Arbitrary order H1 elements in 3D on a cube.
Definition fe_h1.hpp:64
Arbitrary order H1 elements in 2D on a square.
Definition fe_h1.hpp:43
Arbitrary order H1 elements in 1D.
Definition fe_h1.hpp:23
Arbitrary order H1 elements in 3D on a tetrahedron.
Definition fe_h1.hpp:107
Arbitrary order "H^{1/2}-conforming" trace finite elements defined on the interface between mesh elem...
Definition fe_coll.hpp:357
H1_Trace_FECollection(const int p, const int dim, const int btype=BasisType::GaussLobatto)
Definition fe_coll.cpp:2166
Arbitrary order H1 elements in 2D on a triangle.
Definition fe_h1.hpp:85
Arbitrary order H1 elements in 3D on a wedge.
Definition fe_h1.hpp:132
Arbitrary order L2 elements in 3D utilizing the Bernstein basis on a cube.
Definition fe_pos.hpp:391
Arbitrary order L2 elements in 3D utilizing the Bernstein basis on a pyramid.
Definition fe_pos.hpp:468
Arbitrary order L2 elements in 2D utilizing the Bernstein basis on a square.
Definition fe_pos.hpp:373
Arbitrary order L2 elements in 1D utilizing the Bernstein basis on a segment.
Definition fe_pos.hpp:355
Arbitrary order L2 elements in 2D utilizing the Bernstein basis on a triangle.
Definition fe_pos.hpp:409
Arbitrary order L2 elements in 3D utilizing the Bernstein basis on a wedge.
Definition fe_pos.hpp:446
Arbitrary order L2 elements in 3D on a pyramid.
Definition fe_l2.hpp:218
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:369
virtual ~L2_FECollection()
Definition fe_coll.cpp:2509
L2_FECollection(const int p, const int dim, const int btype=BasisType::GaussLegendre, const int map_type=FiniteElement::VALUE, const int pyr_type=ScalarPyramid::DefaultType)
Definition fe_coll.cpp:2186
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:2485
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:2490
Arbitrary order L2 elements in 3D on a cube.
Definition fe_l2.hpp:80
Arbitrary order L2 elements in 2D on a square.
Definition fe_l2.hpp:46
Arbitrary order L2 elements in 1D on a segment.
Definition fe_l2.hpp:23
Arbitrary order L2 elements in 3D on a tetrahedron.
Definition fe_l2.hpp:140
Arbitrary order L2 elements in 2D on a triangle.
Definition fe_l2.hpp:110
Arbitrary order L2 elements in 3D on a wedge.
Definition fe_l2.hpp:167
Piecewise-linear discontinuous finite elements in 2D. This class is kept only for backward compatibil...
Definition fe_coll.hpp:1168
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1134
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1148
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1162
Piecewise-linear discontinuous finite elements in 3D. This class is kept only for backward compatibil...
Definition fe_coll.hpp:1362
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1499
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1465
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1481
Piecewise-(bi/tri)linear continuous finite elements.
Definition fe_coll.hpp:911
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:754
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:735
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:772
Piecewise-linear nonconforming finite elements in 3D.
Definition fe_coll.hpp:1045
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1398
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1414
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1382
Discontinuous collection defined locally by a given finite element.
Definition fe_coll.hpp:1518
Local_FECollection(const char *fe_name)
Definition fe_coll.cpp:3538
Lowest order Nedelec finite elements in 3D. This class is kept only for backward compatibility,...
Definition fe_coll.hpp:1442
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1604
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1589
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1622
Arbitrary order H(curl)-conforming Nedelec finite elements.
Definition fe_coll.hpp:526
int ND_dof[Geometry::NumGeom]
Definition fe_coll.hpp:533
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:3006
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:3024
FiniteElementCollection * GetTraceCollection() const override
Returns a collection of the trace elements.
Definition fe_coll.cpp:3042
virtual ~ND_FECollection()
Definition fe_coll.cpp:3062
const StatelessDofTransformation * DofTransformationForGeometry(Geometry::Type GeomType) const override
Returns a DoF transformation object compatible with this basis and geometry type.
Definition fe_coll.cpp:3012
FiniteElement * ND_Elements[Geometry::NumGeom]
Definition fe_coll.hpp:532
ND_FECollection(const int p, const int dim, const int cb_type=BasisType::GaussLobatto, const int ob_type=BasisType::GaussLegendre)
Definition fe_coll.cpp:2823
Arbitrary order Nedelec elements in 3D on a cube.
Definition fe_nd.hpp:24
Arbitrary order Nedelec elements in 2D on a square.
Definition fe_nd.hpp:107
Arbitrary order 3D H(curl)-conforming Nedelec finite elements in 1D.
Definition fe_coll.hpp:587
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:3142
int ND_dof[Geometry::NumGeom]
Definition fe_coll.hpp:591
ND_R1D_FECollection(const int p, const int dim, const int cb_type=BasisType::GaussLobatto, const int ob_type=BasisType::GaussLegendre)
Definition fe_coll.cpp:3093
FiniteElement * ND_Elements[Geometry::NumGeom]
Definition fe_coll.hpp:590
FiniteElementCollection * GetTraceCollection() const override
Returns a collection of the trace elements.
Definition fe_coll.cpp:3148
A 0D Nedelec finite element for the boundary of a 1D domain.
Definition fe_nd.hpp:551
Arbitrary order, three component, Nedelec elements in 1D on a segment.
Definition fe_nd.hpp:572
Arbitrary order 3D H(curl)-conforming Nedelec finite elements in 2D.
Definition fe_coll.hpp:651
FiniteElementCollection * GetTraceCollection() const override
Returns a collection of the trace elements.
Definition fe_coll.cpp:3325
ND_R2D_FECollection(const int p, const int dim, const int cb_type=BasisType::GaussLobatto, const int ob_type=BasisType::GaussLegendre)
Definition fe_coll.cpp:3232
FiniteElement * ND_Elements[Geometry::NumGeom]
Definition fe_coll.hpp:654
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:3315
int ND_dof[Geometry::NumGeom]
Definition fe_coll.hpp:655
Arbitrary order Nedelec 3D elements in 2D on a square.
Definition fe_nd.hpp:788
Arbitrary order 3D H(curl)-trace finite elements in 2D defined on the interface between mesh elements...
Definition fe_coll.hpp:686
ND_R2D_Trace_FECollection(const int p, const int dim, const int cb_type=BasisType::GaussLobatto, const int ob_type=BasisType::GaussLegendre)
Definition fe_coll.cpp:3355
Arbitrary order Nedelec 3D elements in 2D on a triangle.
Definition fe_nd.hpp:757
Arbitrary order Nedelec elements in 1D on a segment.
Definition fe_nd.hpp:297
Arbitrary order Nedelec elements in 3D on a tetrahedron.
Definition fe_nd.hpp:174
Arbitrary order H(curl)-trace finite elements defined on the interface between mesh elements (faces,...
Definition fe_coll.hpp:575
ND_Trace_FECollection(const int p, const int dim, const int cb_type=BasisType::GaussLobatto, const int ob_type=BasisType::GaussLegendre)
Definition fe_coll.cpp:3074
Arbitrary order Nedelec elements in 2D on a triangle.
Definition fe_nd.hpp:237
An arbitrary order 1D NURBS element on a segment.
Definition fe_nurbs.hpp:72
An arbitrary order 2D NURBS element on a square.
Definition fe_nurbs.hpp:106
An arbitrary order 3D NURBS element on a cube.
Definition fe_nurbs.hpp:153
Arbitrary order non-uniform rational B-splines (NURBS) finite elements.
Definition fe_coll.hpp:749
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:3629
virtual void SetOrder(int Order) const
Set the order and the name, based on the given Order: either a positive number for fixed order,...
Definition fe_coll.cpp:3592
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:3614
NURBS2DFiniteElement * QuadrilateralFE
Definition fe_coll.hpp:753
NURBS1DFiniteElement * SegmentFE
Definition fe_coll.hpp:752
NURBSFECollection(int Order=VariableOrder)
The parameter Order must be either a positive number, for fixed order, or VariableOrder (default).
Definition fe_coll.cpp:3580
FiniteElementCollection * GetTraceCollection() const override
Returns a collection of the trace elements.
Definition fe_coll.cpp:3642
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:3635
NURBS3DFiniteElement * ParallelepipedFE
Definition fe_coll.hpp:754
PointFiniteElement * PointFE
Definition fe_coll.hpp:751
Arbitrary order H(curl) NURBS finite elements.
Definition fe_coll.hpp:860
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:3820
void SetOrder(int Order) const override
Set the order and the name, based on the given Order: either a positive number for fixed order,...
Definition fe_coll.cpp:3801
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:3787
NURBS_HCurlFECollection(int Order=VariableOrder, const int vdim=-1)
The parameter Order must be either a positive number, for fixed order, or VariableOrder (default).
Definition fe_coll.cpp:3741
void SetDim(const int dim) override
Definition fe_coll.cpp:3755
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:3814
FiniteElementCollection * GetTraceCollection() const override
Returns a collection of the trace elements.
Definition fe_coll.cpp:3828
Arbitrary order H(div) NURBS finite elements.
Definition fe_coll.hpp:808
void SetDim(const int dim) override
Definition fe_coll.cpp:3664
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:3721
void SetOrder(int Order) const override
Set the order and the name, based on the given Order: either a positive number for fixed order,...
Definition fe_coll.cpp:3708
FiniteElementCollection * GetTraceCollection() const override
Returns a collection of the trace elements.
Definition fe_coll.cpp:3735
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:3727
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:3694
NURBS_HDivFECollection(int Order=VariableOrder, const int vdim=-1)
The parameter Order must be either a positive number, for fixed order, or VariableOrder (default).
Definition fe_coll.cpp:3649
A 3D 1st order Nedelec element on a cube.
Class for standard nodal finite elements.
Definition fe_base.hpp:798
const Array< int > & GetLexicographicOrdering() const
Get an Array<int> that maps lexicographically ordered indices to the indices of the respective nodes/...
Definition fe_base.hpp:878
void SetMapType(const int map_type_) override
Set the FiniteElement::MapType of the element to either VALUE or INTEGRAL. Also sets the FiniteElemen...
Definition fe_base.cpp:2753
Linear (P1) finite elements on quadrilaterals.
Definition fe_coll.hpp:1215
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1209
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1232
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1219
A 0D point finite element.
Piecewise-quadratic discontinuous finite elements in 2D. This class is kept only for backward compati...
Definition fe_coll.hpp:1238
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1254
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1240
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1269
Piecewise-quadratic discontinuous finite elements in 3D. This class is kept only for backward compati...
Definition fe_coll.hpp:1389
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1507
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1521
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1538
Piecewise-(bi)quadratic continuous finite elements.
Definition fe_coll.hpp:939
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:798
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:815
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:780
Version of QuadraticDiscont2DFECollection with positive basis functions.
Definition fe_coll.hpp:1261
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1277
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1290
Version of QuadraticFECollection with positive basis functions.
Definition fe_coll.hpp:968
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:825
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:852
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:839
static int CheckOpen(int type)
If the Quadrature1D type is not open return Invalid; otherwise return type.
static int CheckClosed(int type)
If the Quadrature1D type is not closed return Invalid; otherwise return type.
First order Raviart-Thomas finite elements in 2D. This class is kept only for backward compatibility,...
Definition fe_coll.hpp:1071
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:971
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:999
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:985
First order Raviart-Thomas finite elements in 3D. This class is kept only for backward compatibility,...
Definition fe_coll.hpp:1468
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1672
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1637
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1654
Second order Raviart-Thomas finite elements in 2D. This class is kept only for backward compatibility...
Definition fe_coll.hpp:1095
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1014
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1042
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1028
Second order Raviart-Thomas finite elements in 3D. This class is kept only for backward compatibility...
Definition fe_coll.hpp:1495
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1704
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1690
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1719
Third order Raviart-Thomas finite elements in 2D. This class is kept only for backward compatibility,...
Definition fe_coll.hpp:1119
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1070
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1084
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1056
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
Definition fe_coll.hpp:430
int RT_dof[Geometry::NumGeom]
Definition fe_coll.hpp:437
FiniteElement * RT_Elements[Geometry::NumGeom]
Definition fe_coll.hpp:436
void InitFaces(const int p, const int dim, const int map_type, const bool signs)
Definition fe_coll.cpp:2611
virtual ~RT_FECollection()
Definition fe_coll.cpp:2771
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:2736
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:2731
FiniteElementCollection * GetTraceCollection() const override
Returns a collection of the trace elements.
Definition fe_coll.cpp:2754
RT_FECollection(const int p, const int dim, const int map_type, const bool signs, const int ob_type=BasisType::GaussLegendre)
Definition fe_coll.cpp:2595
Arbitrary order Raviart-Thomas elements in 3D on a cube.
Definition fe_rt.hpp:92
Arbitrary order Raviart-Thomas elements in 2D on a square.
Definition fe_rt.hpp:25
Arbitrary order 3D H(div)-conforming Raviart-Thomas finite elements in 1D.
Definition fe_coll.hpp:619
FiniteElementCollection * GetTraceCollection() const override
Returns a collection of the trace elements.
Definition fe_coll.cpp:3217
FiniteElement * RT_Elements[Geometry::NumGeom]
Definition fe_coll.hpp:622
RT_R1D_FECollection(const int p, const int dim, const int cb_type=BasisType::GaussLobatto, const int ob_type=BasisType::GaussLegendre)
Definition fe_coll.cpp:3162
int RT_dof[Geometry::NumGeom]
Definition fe_coll.hpp:623
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:3211
Arbitrary order, three component, Raviart-Thomas elements in 1D on a segment.
Definition fe_rt.hpp:438
Arbitrary order 3D H(div)-conforming Raviart-Thomas finite elements in 2D.
Definition fe_coll.hpp:695
void InitFaces(const int p, const int dim, const int map_type, const bool signs)
Definition fe_coll.cpp:3443
RT_R2D_FECollection(const int p, const int dim, const int map_type, const bool signs, const int ob_type=BasisType::GaussLegendre)
Definition fe_coll.cpp:3429
FiniteElement * RT_Elements[Geometry::NumGeom]
Definition fe_coll.hpp:699
int RT_dof[Geometry::NumGeom]
Definition fe_coll.hpp:700
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:3482
FiniteElementCollection * GetTraceCollection() const override
Returns a collection of the trace elements.
Definition fe_coll.cpp:3492
Arbitrary order Raviart-Thomas 3D elements in 2D on a square.
Definition fe_rt.hpp:606
Arbitrary order 3D "H^{-1/2}-conforming" face finite elements defined on the interface between mesh e...
Definition fe_coll.hpp:740
RT_R2D_Trace_FECollection(const int p, const int dim, const int map_type=FiniteElement::INTEGRAL, const int ob_type=BasisType::GaussLegendre)
Definition fe_coll.cpp:3518
Arbitrary order Raviart-Thomas 3D elements in 2D on a triangle.
Definition fe_rt.hpp:578
Arbitrary order Raviart-Thomas elements in 3D on a tetrahedron.
Definition fe_rt.hpp:218
Arbitrary order "H^{-1/2}-conforming" face finite elements defined on the interface between mesh elem...
Definition fe_coll.hpp:492
RT_Trace_FECollection(const int p, const int dim, const int map_type=FiniteElement::INTEGRAL, const int ob_type=BasisType::GaussLegendre)
Definition fe_coll.cpp:2783
Arbitrary order Raviart-Thomas elements in 2D on a triangle.
Definition fe_rt.hpp:162
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1545
int DofForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1563
const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const override
Returns an array, say p, that maps a local permuted index i to a local base index: base_i = p[i].
Definition fe_coll.cpp:1579
virtual void SetMapType(int M)
Set the FiniteElement::MapType of the element to either VALUE or INTEGRAL. Also sets the FiniteElemen...
Definition fe_base.hpp:764
int dim
Definition ex24.cpp:53
void mfem_error(const char *msg)
Definition error.cpp:154
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
Definition globals.hpp:71
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
STL namespace.
real_t p(const Vector &x, real_t t)
static int DefaultType