MFEM  v4.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
fe_coll.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
3 // reserved. See file COPYRIGHT for details.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability see http://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the GNU Lesser General Public License (as published by the Free
10 // Software Foundation) version 2.1 dated February 1999.
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 
20 namespace mfem
21 {
22 
23 using namespace std;
24 
26 {
27  switch (GeomType)
28  {
29  case Geometry::TETRAHEDRON: return DofForGeometry (Geometry::TRIANGLE);
30  case Geometry::CUBE: return DofForGeometry (Geometry::SQUARE);
31  case Geometry::PRISM:
32  return max(DofForGeometry (Geometry::TRIANGLE),
33  DofForGeometry (Geometry::SQUARE));
34  default:
35  mfem_error ("FiniteElementCollection::HasFaceDofs:"
36  " unknown geometry type.");
37  }
38  return 0;
39 }
40 
42 {
43  MFEM_ABORT("this method is not implemented in this derived class!");
44  return NULL;
45 }
46 
48 {
49  FiniteElementCollection *fec = NULL;
50 
51  if (!strcmp(name, "Linear"))
52  {
53  fec = new LinearFECollection;
54  }
55  else if (!strcmp(name, "Quadratic"))
56  {
57  fec = new QuadraticFECollection;
58  }
59  else if (!strcmp(name, "QuadraticPos"))
60  {
61  fec = new QuadraticPosFECollection;
62  }
63  else if (!strcmp(name, "Cubic"))
64  {
65  fec = new CubicFECollection;
66  }
67  else if (!strcmp(name, "Const3D"))
68  {
69  fec = new Const3DFECollection;
70  }
71  else if (!strcmp(name, "Const2D"))
72  {
73  fec = new Const2DFECollection;
74  }
75  else if (!strcmp(name, "LinearDiscont2D"))
76  {
78  }
79  else if (!strcmp(name, "GaussLinearDiscont2D"))
80  {
82  }
83  else if (!strcmp(name, "P1OnQuad"))
84  {
85  fec = new P1OnQuadFECollection;
86  }
87  else if (!strcmp(name, "QuadraticDiscont2D"))
88  {
90  }
91  else if (!strcmp(name, "QuadraticPosDiscont2D"))
92  {
94  }
95  else if (!strcmp(name, "GaussQuadraticDiscont2D"))
96  {
98  }
99  else if (!strcmp(name, "CubicDiscont2D"))
100  {
101  fec = new CubicDiscont2DFECollection;
102  }
103  else if (!strcmp(name, "LinearDiscont3D"))
104  {
105  fec = new LinearDiscont3DFECollection;
106  }
107  else if (!strcmp(name, "QuadraticDiscont3D"))
108  {
110  }
111  else if (!strcmp(name, "LinearNonConf3D"))
112  {
113  fec = new LinearNonConf3DFECollection;
114  }
115  else if (!strcmp(name, "CrouzeixRaviart"))
116  {
117  fec = new CrouzeixRaviartFECollection;
118  }
119  else if (!strcmp(name, "ND1_3D"))
120  {
121  fec = new ND1_3DFECollection;
122  }
123  else if (!strcmp(name, "RT0_2D"))
124  {
125  fec = new RT0_2DFECollection;
126  }
127  else if (!strcmp(name, "RT1_2D"))
128  {
129  fec = new RT1_2DFECollection;
130  }
131  else if (!strcmp(name, "RT2_2D"))
132  {
133  fec = new RT2_2DFECollection;
134  }
135  else if (!strcmp(name, "RT0_3D"))
136  {
137  fec = new RT0_3DFECollection;
138  }
139  else if (!strcmp(name, "RT1_3D"))
140  {
141  fec = new RT1_3DFECollection;
142  }
143  else if (!strncmp(name, "H1_Trace_", 9))
144  {
145  fec = new H1_Trace_FECollection(atoi(name + 13), atoi(name + 9));
146  }
147  else if (!strncmp(name, "H1_Trace@", 9))
148  {
149  fec = new H1_Trace_FECollection(atoi(name + 15), atoi(name + 11),
150  BasisType::GetType(name[9]));
151  }
152  else if (!strncmp(name, "H1_", 3))
153  {
154  fec = new H1_FECollection(atoi(name + 7), atoi(name + 3));
155  }
156  else if (!strncmp(name, "H1Pos_Trace_", 12))
157  {
158  fec = new H1_Trace_FECollection(atoi(name + 16), atoi(name + 12),
160  }
161  else if (!strncmp(name, "H1Pos_", 6))
162  {
163  fec = new H1Pos_FECollection(atoi(name + 10), atoi(name + 6));
164  }
165  else if (!strncmp(name, "H1@", 3))
166  {
167  fec = new H1_FECollection(atoi(name + 9), atoi(name + 5),
168  BasisType::GetType(name[3]));
169  }
170  else if (!strncmp(name, "L2_T", 4))
171  fec = new L2_FECollection(atoi(name + 10), atoi(name + 6),
172  atoi(name + 4));
173  else if (!strncmp(name, "L2_", 3))
174  {
175  fec = new L2_FECollection(atoi(name + 7), atoi(name + 3));
176  }
177  else if (!strncmp(name, "L2Int_T", 7))
178  {
179  fec = new L2_FECollection(atoi(name + 13), atoi(name + 9),
180  atoi(name + 7), FiniteElement::INTEGRAL);
181  }
182  else if (!strncmp(name, "L2Int_", 6))
183  {
184  fec = new L2_FECollection(atoi(name + 10), atoi(name + 6),
187  }
188  else if (!strncmp(name, "RT_Trace_", 9))
189  {
190  fec = new RT_Trace_FECollection(atoi(name + 13), atoi(name + 9));
191  }
192  else if (!strncmp(name, "RT_ValTrace_", 12))
193  {
194  fec = new RT_Trace_FECollection(atoi(name + 16), atoi(name + 12),
196  }
197  else if (!strncmp(name, "RT_Trace@", 9))
198  {
199  fec = new RT_Trace_FECollection(atoi(name + 15), atoi(name + 11),
201  BasisType::GetType(name[9]));
202  }
203  else if (!strncmp(name, "RT_ValTrace@", 12))
204  {
205  fec = new RT_Trace_FECollection(atoi(name + 18), atoi(name + 14),
207  BasisType::GetType(name[12]));
208  }
209  else if (!strncmp(name, "DG_Iface_", 9))
210  {
211  fec = new DG_Interface_FECollection(atoi(name + 13), atoi(name + 9));
212  }
213  else if (!strncmp(name, "DG_Iface@", 9))
214  {
215  fec = new DG_Interface_FECollection(atoi(name + 15), atoi(name + 11),
217  BasisType::GetType(name[9]));
218  }
219  else if (!strncmp(name, "DG_IntIface_", 12))
220  {
221  fec = new DG_Interface_FECollection(atoi(name + 16), atoi(name + 12),
223  }
224  else if (!strncmp(name, "DG_IntIface@", 12))
225  {
226  fec = new DG_Interface_FECollection(atoi(name + 18), atoi(name + 14),
228  BasisType::GetType(name[12]));
229  }
230  else if (!strncmp(name, "RT_", 3))
231  {
232  fec = new RT_FECollection(atoi(name + 7), atoi(name + 3));
233  }
234  else if (!strncmp(name, "RT@", 3))
235  {
236  fec = new RT_FECollection(atoi(name + 10), atoi(name + 6),
237  BasisType::GetType(name[3]),
238  BasisType::GetType(name[4]));
239  }
240  else if (!strncmp(name, "ND_Trace_", 9))
241  {
242  fec = new ND_Trace_FECollection(atoi(name + 13), atoi(name + 9));
243  }
244  else if (!strncmp(name, "ND_Trace@", 9))
245  {
246  fec = new ND_Trace_FECollection(atoi(name + 16), atoi(name + 12),
247  BasisType::GetType(name[9]),
248  BasisType::GetType(name[10]));
249  }
250  else if (!strncmp(name, "ND_", 3))
251  {
252  fec = new ND_FECollection(atoi(name + 7), atoi(name + 3));
253  }
254  else if (!strncmp(name, "ND@", 3))
255  {
256  fec = new ND_FECollection(atoi(name + 10), atoi(name + 6),
257  BasisType::GetType(name[3]),
258  BasisType::GetType(name[4]));
259  }
260  else if (!strncmp(name, "Local_", 6))
261  {
262  fec = new Local_FECollection(name + 6);
263  }
264  else if (!strncmp(name, "NURBS", 5))
265  {
266  if (name[5] != '\0')
267  {
268  // "NURBS" + "number" --> fixed order nurbs collection
269  fec = new NURBSFECollection(atoi(name + 5));
270  }
271  else
272  {
273  // "NURBS" --> variable order nurbs collection
274  fec = new NURBSFECollection();
275  }
276  }
277  else
278  {
279  MFEM_ABORT("unknown FiniteElementCollection: " << name);
280  }
281  MFEM_VERIFY(!strcmp(fec->Name(), name), "input name: \"" << name
282  << "\" does not match the created collection name: \""
283  << fec->Name() << '"');
284 
285  return fec;
286 }
287 
288 template <Geometry::Type geom>
289 inline void FiniteElementCollection::GetNVE(int &nv, int &ne)
290 {
291  typedef typename Geometry::Constants<geom> g_consts;
292 
293  nv = g_consts::NumVert;
294  ne = g_consts::NumEdges;
295 }
296 
297 template <Geometry::Type geom, typename v_t>
298 inline void FiniteElementCollection::
299 GetEdge(int &nv, v_t &v, int &ne, int &e, int &eo, const int edge_info)
300 {
301  typedef typename Geometry::Constants<Geometry::SEGMENT> e_consts;
302  typedef typename Geometry::Constants<geom> g_consts;
303 
304  nv = e_consts::NumVert;
305  ne = 1;
306  e = edge_info/64;
307  eo = edge_info%64;
308  MFEM_ASSERT(0 <= e && e < g_consts::NumEdges, "");
309  MFEM_ASSERT(0 <= eo && eo < e_consts::NumOrient, "");
310  v[0] = g_consts::Edges[e][0];
311  v[1] = g_consts::Edges[e][1];
312  v[0] = e_consts::Orient[eo][v[0]];
313  v[1] = e_consts::Orient[eo][v[1]];
314 }
315 
316 template <Geometry::Type geom, Geometry::Type f_geom,
317  typename v_t, typename e_t, typename eo_t>
318 inline void FiniteElementCollection::
319 GetFace(int &nv, v_t &v, int &ne, e_t &e, eo_t &eo,
320  int &nf, int &f, Geometry::Type &fg, int &fo, const int face_info)
321 {
322  typedef typename Geometry::Constants< geom> g_consts;
323  typedef typename Geometry::Constants<f_geom> f_consts;
324 
325  nv = f_consts::NumVert;
326  nf = 1;
327  f = face_info/64;
328  fg = f_geom;
329  fo = face_info%64;
330  MFEM_ASSERT(0 <= f && f < g_consts::NumFaces, "");
331  MFEM_ASSERT(0 <= fo && fo < f_consts::NumOrient, "");
332  for (int i = 0; i < f_consts::NumVert; i++)
333  {
334  v[i] = f_consts::Orient[fo][i];
335  v[i] = g_consts::FaceVert[f][v[i]];
336  }
337  ne = f_consts::NumEdges;
338  for (int i = 0; i < f_consts::NumEdges; i++)
339  {
340  int v0 = v[f_consts::Edges[i][0]];
341  int v1 = v[f_consts::Edges[i][1]];
342  int eor = 0;
343  if (v0 > v1) { swap(v0, v1); eor = 1; }
344  for (int j = g_consts::VertToVert::I[v0]; true; j++)
345  {
346  MFEM_ASSERT(j < g_consts::VertToVert::I[v0+1],
347  "internal error, edge not found");
348  if (v1 == g_consts::VertToVert::J[j][0])
349  {
350  int en = g_consts::VertToVert::J[j][1];
351  if (en < 0)
352  {
353  en = -1-en;
354  eor = 1-eor;
355  }
356  e[i] = en;
357  eo[i] = eor;
358  break;
359  }
360  }
361  }
362 }
363 
365  int Info,
366  Array<int> &dofs) const
367 {
368  // Info = 64 * SubIndex + SubOrientation
369  MFEM_ASSERT(0 <= Geom && Geom < Geometry::NumGeom,
370  "invalid Geom = " << Geom);
371  MFEM_ASSERT(0 <= SDim && SDim <= Geometry::Dimension[Geom],
372  "invalid SDim = " << SDim <<
373  " for Geom = " << Geometry::Name[Geom]);
374 
375  const int nvd = DofForGeometry(Geometry::POINT);
376  if (SDim == 0) // vertex
377  {
378  const int off = nvd*(Info/64);
379  dofs.SetSize(nvd);
380  for (int i = 0; i < nvd; i++)
381  {
382  dofs[i] = off + i;
383  }
384  }
385  else
386  {
387  int v[4], e[4], eo[4], f[1], fo[1];
388  int av = 0, nv = 0, ae = 0, ne = 0, nf = 0;
389  Geometry::Type fg[1];
390 
391  switch (Geom)
392  {
393  case Geometry::SEGMENT:
394  {
395  GetNVE<Geometry::SEGMENT>(av, ae);
396  GetEdge<Geometry::SEGMENT>(nv, v, ne, e[0], eo[0], Info);
397  break;
398  }
399 
400  case Geometry::TRIANGLE:
401  {
402  GetNVE<Geometry::TRIANGLE>(av, ae);
403  switch (SDim)
404  {
405  case 1:
406  GetEdge<Geometry::TRIANGLE>(nv, v, ne, e[0], eo[0], Info);
407  break;
408  case 2:
409  GetFace<Geometry::TRIANGLE,Geometry::TRIANGLE>(
410  nv, v, ne, e, eo, nf, f[0], fg[0], fo[0], Info);
411  break;
412  default:
413  goto not_supp;
414  }
415  break;
416  }
417 
418  case Geometry::SQUARE:
419  {
420  GetNVE<Geometry::SQUARE>(av, ae);
421  switch (SDim)
422  {
423  case 1:
424  GetEdge<Geometry::SQUARE>(nv, v, ne, e[0], eo[0], Info);
425  break;
426  case 2:
427  GetFace<Geometry::SQUARE,Geometry::SQUARE>(
428  nv, v, ne, e, eo, nf, f[0], fg[0], fo[0], Info);
429  break;
430  default:
431  goto not_supp;
432  }
433  break;
434  }
435 
437  {
438  GetNVE<Geometry::TETRAHEDRON>(av, ae);
439  switch (SDim)
440  {
441  case 1:
442  GetEdge<Geometry::TETRAHEDRON>(nv, v, ne, e[0], eo[0], Info);
443  break;
444  case 2:
445  GetFace<Geometry::TETRAHEDRON,Geometry::TRIANGLE>(
446  nv, v, ne, e, eo, nf, f[0], fg[0], fo[0], Info);
447  break;
448  default:
449  goto not_supp;
450  }
451  break;
452  }
453 
454  case Geometry::CUBE:
455  {
456  GetNVE<Geometry::CUBE>(av, ae);
457  switch (SDim)
458  {
459  case 1:
460  GetEdge<Geometry::CUBE>(nv, v, ne, e[0], eo[0], Info);
461  break;
462  case 2:
463  GetFace<Geometry::CUBE,Geometry::SQUARE>(
464  nv, v, ne, e, eo, nf, f[0], fg[0], fo[0], Info);
465  break;
466  default:
467  goto not_supp;
468  }
469  break;
470  }
471 
472  default:
473  MFEM_ABORT("invalid Geom = " << Geom);
474  }
475 
476  int ned = (ne > 0) ? DofForGeometry(Geometry::SEGMENT) : 0;
477 
478  // add vertex dofs
479  dofs.SetSize(nv*nvd+ne*ned);
480  for (int i = 0; i < nv; i++)
481  {
482  for (int j = 0; j < nvd; j++)
483  {
484  dofs[i*nvd+j] = v[i]*nvd+j;
485  }
486  }
487  int l_off = nv*nvd, g_off = av*nvd;
488 
489  // add edge dofs
490  if (ned > 0)
491  {
492  for (int i = 0; i < ne; i++)
493  {
494  const int *ed = DofOrderForOrientation(Geometry::SEGMENT,
495  eo[i] ? -1 : 1);
496  for (int j = 0; j < ned; j++)
497  {
498  dofs[l_off+i*ned+j] =
499  ed[j] >= 0 ?
500  g_off+e[i]*ned+ed[j] :
501  -1-(g_off+e[i]*ned+(-1-ed[j]));
502  }
503  }
504  l_off += ne*ned;
505  g_off += ae*ned;
506  }
507 
508  // add face dofs
509  if (nf > 0)
510  {
511  const int nfd = DofForGeometry(fg[0]); // assume same face geometry
512  dofs.SetSize(dofs.Size()+nf*nfd);
513  for (int i = 0; i < nf; i++)
514  {
515  const int *fd = DofOrderForOrientation(fg[i], fo[i]);
516  for (int j = 0; j < nfd; j++)
517  {
518  dofs[l_off+i*nfd+j] =
519  fd[j] >= 0 ?
520  g_off+f[i]*nfd+fd[j] :
521  -1-(g_off+f[i]*nfd+(-1-fd[j]));
522  }
523  }
524  }
525 
526  // add volume dofs ...
527  }
528  return;
529 
530 not_supp:
531  MFEM_ABORT("Geom = " << Geometry::Name[Geom] <<
532  ", SDim = " << SDim << " is not supported");
533 }
534 
535 const FiniteElement *
537 {
538  switch (GeomType)
539  {
540  case Geometry::POINT: return &PointFE;
541  case Geometry::SEGMENT: return &SegmentFE;
542  case Geometry::TRIANGLE: return &TriangleFE;
543  case Geometry::SQUARE: return &QuadrilateralFE;
544  case Geometry::TETRAHEDRON: return &TetrahedronFE;
545  case Geometry::CUBE: return &ParallelepipedFE;
546  case Geometry::PRISM: return &WedgeFE;
547  default:
548  mfem_error ("LinearFECollection: unknown geometry type.");
549  }
550  return &SegmentFE; // Make some compilers happy
551 }
552 
554 {
555  switch (GeomType)
556  {
557  case Geometry::POINT: return 1;
558  case Geometry::SEGMENT: return 0;
559  case Geometry::TRIANGLE: return 0;
560  case Geometry::SQUARE: return 0;
561  case Geometry::TETRAHEDRON: return 0;
562  case Geometry::CUBE: return 0;
563  case Geometry::PRISM: return 0;
564  default:
565  mfem_error ("LinearFECollection: unknown geometry type.");
566  }
567  return 0; // Make some compilers happy
568 }
569 
571  int Or) const
572 {
573  return NULL;
574 }
575 
576 
577 const FiniteElement *
579 {
580  switch (GeomType)
581  {
582  case Geometry::POINT: return &PointFE;
583  case Geometry::SEGMENT: return &SegmentFE;
584  case Geometry::TRIANGLE: return &TriangleFE;
585  case Geometry::SQUARE: return &QuadrilateralFE;
586  case Geometry::TETRAHEDRON: return &TetrahedronFE;
587  case Geometry::CUBE: return &ParallelepipedFE;
588  case Geometry::PRISM: return &WedgeFE;
589  default:
590  mfem_error ("QuadraticFECollection: unknown geometry type.");
591  }
592  return &SegmentFE; // Make some compilers happy
593 }
594 
596 {
597  switch (GeomType)
598  {
599  case Geometry::POINT: return 1;
600  case Geometry::SEGMENT: return 1;
601  case Geometry::TRIANGLE: return 0;
602  case Geometry::SQUARE: return 1;
603  case Geometry::TETRAHEDRON: return 0;
604  case Geometry::CUBE: return 1;
605  case Geometry::PRISM: return 0;
606  default:
607  mfem_error ("QuadraticFECollection: unknown geometry type.");
608  }
609  return 0; // Make some compilers happy
610 }
611 
613  Geometry::Type GeomType, int Or) const
614 {
615  static int indexes[] = { 0 };
616 
617  return indexes;
618 }
619 
620 
621 const FiniteElement *
623  Geometry::Type GeomType) const
624 {
625  switch (GeomType)
626  {
627  case Geometry::SEGMENT: return &SegmentFE;
628  case Geometry::SQUARE: return &QuadrilateralFE;
629  default:
630  mfem_error ("QuadraticPosFECollection: unknown geometry type.");
631  }
632  return NULL; // Make some compilers happy
633 }
634 
636 {
637  switch (GeomType)
638  {
639  case Geometry::POINT: return 1;
640  case Geometry::SEGMENT: return 1;
641  case Geometry::SQUARE: return 1;
642  default:
643  mfem_error ("QuadraticPosFECollection: unknown geometry type.");
644  }
645  return 0; // Make some compilers happy
646 }
647 
649  Geometry::Type GeomType, int Or) const
650 {
651  static int indexes[] = { 0 };
652 
653  return indexes;
654 }
655 
656 
657 const FiniteElement *
659 {
660  switch (GeomType)
661  {
662  case Geometry::POINT: return &PointFE;
663  case Geometry::SEGMENT: return &SegmentFE;
664  case Geometry::TRIANGLE: return &TriangleFE;
665  case Geometry::SQUARE: return &QuadrilateralFE;
666  case Geometry::TETRAHEDRON: return &TetrahedronFE;
667  case Geometry::CUBE: return &ParallelepipedFE;
668  case Geometry::PRISM: return &WedgeFE;
669  default:
670  mfem_error ("CubicFECollection: unknown geometry type.");
671  }
672  return &SegmentFE; // Make some compilers happy
673 }
674 
676 {
677  switch (GeomType)
678  {
679  case Geometry::POINT: return 1;
680  case Geometry::SEGMENT: return 2;
681  case Geometry::TRIANGLE: return 1;
682  case Geometry::SQUARE: return 4;
683  case Geometry::TETRAHEDRON: return 0;
684  case Geometry::CUBE: return 8;
685  case Geometry::PRISM: return 2;
686  default:
687  mfem_error ("CubicFECollection: unknown geometry type.");
688  }
689  return 0; // Make some compilers happy
690 }
691 
693  int Or) const
694 {
695  if (GeomType == Geometry::SEGMENT)
696  {
697  static int ind_pos[] = { 0, 1 };
698  static int ind_neg[] = { 1, 0 };
699 
700  if (Or < 0)
701  {
702  return ind_neg;
703  }
704  return ind_pos;
705  }
706  else if (GeomType == Geometry::TRIANGLE)
707  {
708  static int indexes[] = { 0 };
709 
710  return indexes;
711  }
712  else if (GeomType == Geometry::SQUARE)
713  {
714  static int sq_ind[8][4] = {{0, 1, 2, 3}, {0, 2, 1, 3},
715  {2, 0, 3, 1}, {1, 0, 3, 2},
716  {3, 2, 1, 0}, {3, 1, 2, 0},
717  {1, 3, 0, 2}, {2, 3, 0, 1}
718  };
719  return sq_ind[Or];
720  }
721 
722  return NULL;
723 }
724 
725 
726 const FiniteElement *
728  Geometry::Type GeomType) const
729 {
730  switch (GeomType)
731  {
732  case Geometry::SEGMENT: return &SegmentFE;
733  case Geometry::TRIANGLE: return &TriangleFE;
734  case Geometry::SQUARE: return &QuadrilateralFE;
735  default:
736  mfem_error ("CrouzeixRaviartFECollection: unknown geometry type.");
737  }
738  return &SegmentFE; // Make some compilers happy
739 }
740 
742 {
743  switch (GeomType)
744  {
745  case Geometry::POINT: return 0;
746  case Geometry::SEGMENT: return 1;
747  case Geometry::TRIANGLE: return 0;
748  case Geometry::SQUARE: return 0;
749  default:
750  mfem_error ("CrouzeixRaviartFECollection: unknown geometry type.");
751  }
752  return 0; // Make some compilers happy
753 }
754 
756  Geometry::Type GeomType, int Or) const
757 {
758  static int indexes[] = { 0 };
759 
760  return indexes;
761 }
762 
763 
764 const FiniteElement *
766 {
767  switch (GeomType)
768  {
769  case Geometry::SEGMENT: return &SegmentFE;
770  case Geometry::TRIANGLE: return &TriangleFE;
771  case Geometry::SQUARE: return &QuadrilateralFE;
772  default:
773  mfem_error ("RT0_2DFECollection: unknown geometry type.");
774  }
775  return &SegmentFE; // Make some compilers happy
776 }
777 
779 {
780  switch (GeomType)
781  {
782  case Geometry::POINT: return 0;
783  case Geometry::SEGMENT: return 1;
784  case Geometry::TRIANGLE: return 0;
785  case Geometry::SQUARE: return 0;
786  default:
787  mfem_error ("RT0_2DFECollection: unknown geometry type.");
788  }
789  return 0; // Make some compilers happy
790 }
791 
793  int Or) const
794 {
795  static int ind_pos[] = { 0 };
796  static int ind_neg[] = { -1 };
797 
798  if (Or > 0)
799  {
800  return ind_pos;
801  }
802  return ind_neg;
803 }
804 
805 
806 const FiniteElement *
808 {
809  switch (GeomType)
810  {
811  case Geometry::SEGMENT: return &SegmentFE;
812  case Geometry::TRIANGLE: return &TriangleFE;
813  case Geometry::SQUARE: return &QuadrilateralFE;
814  default:
815  mfem_error ("RT1_2DFECollection: unknown geometry type.");
816  }
817  return &SegmentFE; // Make some compilers happy
818 }
819 
821 {
822  switch (GeomType)
823  {
824  case Geometry::POINT: return 0;
825  case Geometry::SEGMENT: return 2;
826  case Geometry::TRIANGLE: return 2;
827  case Geometry::SQUARE: return 4;
828  default:
829  mfem_error ("RT1_2DFECollection: unknown geometry type.");
830  }
831  return 0; // Make some compilers happy
832 }
833 
835  int Or) const
836 {
837  static int ind_pos[] = { 0, 1 };
838  static int ind_neg[] = { -2, -1 };
839 
840  if (Or > 0)
841  {
842  return ind_pos;
843  }
844  return ind_neg;
845 }
846 
847 const FiniteElement *
849 {
850  switch (GeomType)
851  {
852  case Geometry::SEGMENT: return &SegmentFE;
853  case Geometry::TRIANGLE: return &TriangleFE;
854  case Geometry::SQUARE: return &QuadrilateralFE;
855  default:
856  mfem_error ("RT2_2DFECollection: unknown geometry type.");
857  }
858  return &SegmentFE; // Make some compilers happy
859 }
860 
862 {
863  switch (GeomType)
864  {
865  case Geometry::POINT: return 0;
866  case Geometry::SEGMENT: return 3;
867  case Geometry::TRIANGLE: return 6;
868  case Geometry::SQUARE: return 12;
869  default:
870  mfem_error ("RT2_2DFECollection: unknown geometry type.");
871  }
872  return 0; // Make some compilers happy
873 }
874 
876  int Or) const
877 {
878  static int ind_pos[] = { 0, 1, 2 };
879  static int ind_neg[] = { -3, -2, -1 };
880 
881  if (Or > 0)
882  {
883  return ind_pos;
884  }
885  return ind_neg;
886 }
887 
888 
889 const FiniteElement *
891 {
892  switch (GeomType)
893  {
894  case Geometry::TRIANGLE: return &TriangleFE;
895  case Geometry::SQUARE: return &QuadrilateralFE;
896  default:
897  mfem_error ("Const2DFECollection: unknown geometry type.");
898  }
899  return &TriangleFE; // Make some compilers happy
900 }
901 
903 {
904  switch (GeomType)
905  {
906  case Geometry::POINT: return 0;
907  case Geometry::SEGMENT: return 0;
908  case Geometry::TRIANGLE: return 1;
909  case Geometry::SQUARE: return 1;
910  default:
911  mfem_error ("Const2DFECollection: unknown geometry type.");
912  }
913  return 0; // Make some compilers happy
914 }
915 
917  int Or) const
918 {
919  return NULL;
920 }
921 
922 
923 const FiniteElement *
925  Geometry::Type GeomType) const
926 {
927  switch (GeomType)
928  {
929  case Geometry::TRIANGLE: return &TriangleFE;
930  case Geometry::SQUARE: return &QuadrilateralFE;
931  default:
932  mfem_error ("LinearDiscont2DFECollection: unknown geometry type.");
933  }
934  return &TriangleFE; // Make some compilers happy
935 }
936 
938 {
939  switch (GeomType)
940  {
941  case Geometry::POINT: return 0;
942  case Geometry::SEGMENT: return 0;
943  case Geometry::TRIANGLE: return 3;
944  case Geometry::SQUARE: return 4;
945  default:
946  mfem_error ("LinearDiscont2DFECollection: unknown geometry type.");
947  }
948  return 0; // Make some compilers happy
949 }
950 
952  Geometry::Type GeomType, int Or) const
953 {
954  return NULL;
955 }
956 
957 
958 const FiniteElement *
960  Geometry::Type GeomType) const
961 {
962  switch (GeomType)
963  {
964  case Geometry::TRIANGLE: return &TriangleFE;
965  case Geometry::SQUARE: return &QuadrilateralFE;
966  default:
967  mfem_error ("GaussLinearDiscont2DFECollection:"
968  " unknown geometry type.");
969  }
970  return &TriangleFE; // Make some compilers happy
971 }
972 
974 const
975 {
976  switch (GeomType)
977  {
978  case Geometry::POINT: return 0;
979  case Geometry::SEGMENT: return 0;
980  case Geometry::TRIANGLE: return 3;
981  case Geometry::SQUARE: return 4;
982  default:
983  mfem_error ("GaussLinearDiscont2DFECollection:"
984  " unknown geometry type.");
985  }
986  return 0; // Make some compilers happy
987 }
988 
990  Geometry::Type GeomType, int Or) const
991 {
992  return NULL;
993 }
994 
995 
996 const FiniteElement *
998 {
999  if (GeomType != Geometry::SQUARE)
1000  {
1001  mfem_error ("P1OnQuadFECollection: unknown geometry type.");
1002  }
1003  return &QuadrilateralFE;
1004 }
1005 
1007 {
1008  switch (GeomType)
1009  {
1010  case Geometry::POINT: return 0;
1011  case Geometry::SEGMENT: return 0;
1012  case Geometry::SQUARE: return 3;
1013  default:
1014  mfem_error ("P1OnQuadFECollection: unknown geometry type.");
1015  }
1016  return 0; // Make some compilers happy
1017 }
1018 
1020  Geometry::Type GeomType, int Or) const
1021 {
1022  return NULL;
1023 }
1024 
1025 
1026 const FiniteElement *
1028  Geometry::Type GeomType) const
1029 {
1030  switch (GeomType)
1031  {
1032  case Geometry::TRIANGLE: return &TriangleFE;
1033  case Geometry::SQUARE: return &QuadrilateralFE;
1034  default:
1035  mfem_error ("QuadraticDiscont2DFECollection: unknown geometry type.");
1036  }
1037  return &TriangleFE; // Make some compilers happy
1038 }
1039 
1041 const
1042 {
1043  switch (GeomType)
1044  {
1045  case Geometry::POINT: return 0;
1046  case Geometry::SEGMENT: return 0;
1047  case Geometry::TRIANGLE: return 6;
1048  case Geometry::SQUARE: return 9;
1049  default:
1050  mfem_error ("QuadraticDiscont2DFECollection: unknown geometry type.");
1051  }
1052  return 0; // Make some compilers happy
1053 }
1054 
1056  Geometry::Type GeomType, int Or) const
1057 {
1058  return NULL;
1059 }
1060 
1061 
1062 const FiniteElement *
1064  Geometry::Type GeomType) const
1065 {
1066  switch (GeomType)
1067  {
1068  case Geometry::SQUARE: return &QuadrilateralFE;
1069  default:
1070  mfem_error ("QuadraticPosDiscont2DFECollection: unknown geometry type.");
1071  }
1072  return NULL; // Make some compilers happy
1073 }
1074 
1076 const
1077 {
1078  switch (GeomType)
1079  {
1080  case Geometry::POINT: return 0;
1081  case Geometry::SEGMENT: return 0;
1082  case Geometry::SQUARE: return 9;
1083  default:
1084  mfem_error ("QuadraticPosDiscont2DFECollection: unknown geometry type.");
1085  }
1086  return 0; // Make some compilers happy
1087 }
1088 
1089 
1090 const FiniteElement *
1092  Geometry::Type GeomType)
1093 const
1094 {
1095  switch (GeomType)
1096  {
1097  case Geometry::TRIANGLE: return &TriangleFE;
1098  case Geometry::SQUARE: return &QuadrilateralFE;
1099  default:
1100  mfem_error ("GaussQuadraticDiscont2DFECollection:"
1101  " unknown geometry type.");
1102  }
1103  return &QuadrilateralFE; // Make some compilers happy
1104 }
1105 
1107  Geometry::Type GeomType) const
1108 {
1109  switch (GeomType)
1110  {
1111  case Geometry::POINT: return 0;
1112  case Geometry::SEGMENT: return 0;
1113  case Geometry::TRIANGLE: return 6;
1114  case Geometry::SQUARE: return 9;
1115  default:
1116  mfem_error ("GaussQuadraticDiscont2DFECollection:"
1117  " unknown geometry type.");
1118  }
1119  return 0; // Make some compilers happy
1120 }
1121 
1123  Geometry::Type GeomType, int Or) const
1124 {
1125  return NULL;
1126 }
1127 
1128 
1129 const FiniteElement *
1131  Geometry::Type GeomType) const
1132 {
1133  switch (GeomType)
1134  {
1135  case Geometry::TRIANGLE: return &TriangleFE;
1136  case Geometry::SQUARE: return &QuadrilateralFE;
1137  default:
1138  mfem_error ("CubicDiscont2DFECollection: unknown geometry type.");
1139  }
1140  return &TriangleFE; // Make some compilers happy
1141 }
1142 
1144 {
1145  switch (GeomType)
1146  {
1147  case Geometry::POINT: return 0;
1148  case Geometry::SEGMENT: return 0;
1149  case Geometry::TRIANGLE: return 10;
1150  case Geometry::SQUARE: return 16;
1151  default:
1152  mfem_error ("CubicDiscont2DFECollection: unknown geometry type.");
1153  }
1154  return 0; // Make some compilers happy
1155 }
1156 
1158  Geometry::Type GeomType, int Or) const
1159 {
1160  return NULL;
1161 }
1162 
1163 
1164 const FiniteElement *
1166  Geometry::Type GeomType) const
1167 {
1168  switch (GeomType)
1169  {
1170  case Geometry::TRIANGLE: return &TriangleFE;
1171  case Geometry::SQUARE: return &QuadrilateralFE;
1172  case Geometry::TETRAHEDRON: return &TetrahedronFE;
1173  case Geometry::CUBE: return &ParallelepipedFE;
1174  default:
1175  mfem_error ("LinearNonConf3DFECollection: unknown geometry type.");
1176  }
1177  return &TriangleFE; // Make some compilers happy
1178 }
1179 
1181 {
1182  switch (GeomType)
1183  {
1184  case Geometry::POINT: return 0;
1185  case Geometry::SEGMENT: return 0;
1186  case Geometry::TRIANGLE: return 1;
1187  case Geometry::SQUARE: return 1;
1188  case Geometry::TETRAHEDRON: return 0;
1189  case Geometry::CUBE: return 0;
1190  default:
1191  mfem_error ("LinearNonConf3DFECollection: unknown geometry type.");
1192  }
1193  return 0; // Make some compilers happy
1194 }
1195 
1197  Geometry::Type GeomType, int Or) const
1198 {
1199  static int indexes[] = { 0 };
1200 
1201  return indexes;
1202 }
1203 
1204 
1205 const FiniteElement *
1207 {
1208  switch (GeomType)
1209  {
1210  case Geometry::TETRAHEDRON: return &TetrahedronFE;
1211  case Geometry::CUBE: return &ParallelepipedFE;
1212  case Geometry::PRISM: return &WedgeFE;
1213  default:
1214  mfem_error ("Const3DFECollection: unknown geometry type.");
1215  }
1216  return &TetrahedronFE; // Make some compilers happy
1217 }
1218 
1220 {
1221  switch (GeomType)
1222  {
1223  case Geometry::POINT: return 0;
1224  case Geometry::SEGMENT: return 0;
1225  case Geometry::TRIANGLE: return 0;
1226  case Geometry::SQUARE: return 0;
1227  case Geometry::TETRAHEDRON: return 1;
1228  case Geometry::CUBE: return 1;
1229  case Geometry::PRISM: return 1;
1230  default:
1231  mfem_error ("Const3DFECollection: unknown geometry type.");
1232  }
1233  return 0; // Make some compilers happy
1234 }
1235 
1237  int Or) const
1238 {
1239  return NULL;
1240 }
1241 
1242 
1243 const FiniteElement *
1245  Geometry::Type GeomType) const
1246 {
1247  switch (GeomType)
1248  {
1249  case Geometry::TETRAHEDRON: return &TetrahedronFE;
1250  case Geometry::CUBE: return &ParallelepipedFE;
1251  default:
1252  mfem_error ("LinearDiscont3DFECollection: unknown geometry type.");
1253  }
1254  return &TetrahedronFE; // Make some compilers happy
1255 }
1256 
1258 {
1259  switch (GeomType)
1260  {
1261  case Geometry::POINT: return 0;
1262  case Geometry::SEGMENT: return 0;
1263  case Geometry::TRIANGLE: return 0;
1264  case Geometry::SQUARE: return 0;
1265  case Geometry::TETRAHEDRON: return 4;
1266  case Geometry::CUBE: return 8;
1267  default:
1268  mfem_error ("LinearDiscont3DFECollection: unknown geometry type.");
1269  }
1270  return 0; // Make some compilers happy
1271 }
1272 
1274  Geometry::Type GeomType, int Or) const
1275 {
1276  return NULL;
1277 }
1278 
1279 
1280 const FiniteElement *
1282  Geometry::Type GeomType) const
1283 {
1284  switch (GeomType)
1285  {
1286  case Geometry::TETRAHEDRON: return &TetrahedronFE;
1287  case Geometry::CUBE: return &ParallelepipedFE;
1288  default:
1289  mfem_error ("QuadraticDiscont3DFECollection: unknown geometry type.");
1290  }
1291  return &TetrahedronFE; // Make some compilers happy
1292 }
1293 
1295 const
1296 {
1297  switch (GeomType)
1298  {
1299  case Geometry::POINT: return 0;
1300  case Geometry::SEGMENT: return 0;
1301  case Geometry::TRIANGLE: return 0;
1302  case Geometry::SQUARE: return 0;
1303  case Geometry::TETRAHEDRON: return 10;
1304  case Geometry::CUBE: return 27;
1305  default:
1306  mfem_error ("QuadraticDiscont3DFECollection: unknown geometry type.");
1307  }
1308  return 0; // Make some compilers happy
1309 }
1310 
1312  Geometry::Type GeomType, int Or) const
1313 {
1314  return NULL;
1315 }
1316 
1317 const FiniteElement *
1319  Geometry::Type GeomType) const
1320 {
1321  switch (GeomType)
1322  {
1323  case Geometry::POINT: return &PointFE;
1324  case Geometry::SEGMENT: return &SegmentFE;
1325  case Geometry::TRIANGLE: return &TriangleFE;
1326  case Geometry::SQUARE: return &QuadrilateralFE;
1327  case Geometry::TETRAHEDRON: return &TetrahedronFE;
1328  case Geometry::CUBE: return &ParallelepipedFE;
1329  default:
1330  mfem_error ("RefinedLinearFECollection: unknown geometry type.");
1331  }
1332  return &SegmentFE; // Make some compilers happy
1333 }
1334 
1336 {
1337  switch (GeomType)
1338  {
1339  case Geometry::POINT: return 1;
1340  case Geometry::SEGMENT: return 1;
1341  case Geometry::TRIANGLE: return 0;
1342  case Geometry::SQUARE: return 1;
1343  case Geometry::TETRAHEDRON: return 0;
1344  case Geometry::CUBE: return 1;
1345  default:
1346  mfem_error ("RefinedLinearFECollection: unknown geometry type.");
1347  }
1348  return 0; // Make some compilers happy
1349 }
1350 
1352  Geometry::Type GeomType, int Or) const
1353 {
1354  static int indexes[] = { 0 };
1355 
1356  return indexes;
1357 }
1358 
1359 
1360 const FiniteElement *
1362 {
1363  switch (GeomType)
1364  {
1365  case Geometry::CUBE: return &HexahedronFE;
1366  case Geometry::TETRAHEDRON: return &TetrahedronFE;
1367  default:
1368  mfem_error ("ND1_3DFECollection: unknown geometry type.");
1369  }
1370  return &HexahedronFE; // Make some compilers happy
1371 }
1372 
1374 {
1375  switch (GeomType)
1376  {
1377  case Geometry::POINT: return 0;
1378  case Geometry::SEGMENT: return 1;
1379  case Geometry::TRIANGLE: return 0;
1380  case Geometry::SQUARE: return 0;
1381  case Geometry::TETRAHEDRON: return 0;
1382  case Geometry::CUBE: return 0;
1383  default:
1384  mfem_error ("ND1_3DFECollection: unknown geometry type.");
1385  }
1386  return 0; // Make some compilers happy
1387 }
1388 
1390  int Or) const
1391 {
1392  static int ind_pos[] = { 0 };
1393  static int ind_neg[] = { -1 };
1394 
1395  if (Or > 0)
1396  {
1397  return ind_pos;
1398  }
1399  return ind_neg;
1400 }
1401 
1402 
1403 const FiniteElement *
1405 {
1406  switch (GeomType)
1407  {
1408  case Geometry::TRIANGLE: return &TriangleFE;
1409  case Geometry::SQUARE: return &QuadrilateralFE;
1410  case Geometry::CUBE: return &HexahedronFE;
1411  case Geometry::TETRAHEDRON: return &TetrahedronFE;
1412  default:
1413  mfem_error ("RT0_3DFECollection: unknown geometry type.");
1414  }
1415  return &HexahedronFE; // Make some compilers happy
1416 }
1417 
1419 {
1420  switch (GeomType)
1421  {
1422  case Geometry::POINT: return 0;
1423  case Geometry::SEGMENT: return 0;
1424  case Geometry::TRIANGLE: return 1;
1425  case Geometry::SQUARE: return 1;
1426  case Geometry::TETRAHEDRON: return 0;
1427  case Geometry::CUBE: return 0;
1428  default:
1429  mfem_error ("RT0_3DFECollection: unknown geometry type.");
1430  }
1431  return 0; // Make some compilers happy
1432 }
1433 
1435  int Or) const
1436 {
1437  static int ind_pos[] = { 0 };
1438  static int ind_neg[] = { -1 };
1439 
1440  if ((GeomType == Geometry::TRIANGLE) || (GeomType == Geometry::SQUARE))
1441  {
1442  if (Or % 2 == 0)
1443  {
1444  return ind_pos;
1445  }
1446  return ind_neg;
1447  }
1448  return NULL;
1449 }
1450 
1451 const FiniteElement *
1453 {
1454  switch (GeomType)
1455  {
1456  case Geometry::TRIANGLE: return &TriangleFE;
1457  case Geometry::SQUARE: return &QuadrilateralFE;
1458  case Geometry::CUBE: return &HexahedronFE;
1459  default:
1460  mfem_error ("RT1_3DFECollection: unknown geometry type.");
1461  }
1462  return &HexahedronFE; // Make some compilers happy
1463 }
1464 
1466 {
1467  switch (GeomType)
1468  {
1469  case Geometry::POINT: return 0;
1470  case Geometry::SEGMENT: return 0;
1471  case Geometry::TRIANGLE: return 2;
1472  case Geometry::SQUARE: return 4;
1473  case Geometry::CUBE: return 12;
1474  default:
1475  mfem_error ("RT1_3DFECollection: unknown geometry type.");
1476  }
1477  return 0; // Make some compilers happy
1478 }
1479 
1481  int Or) const
1482 {
1483  if (GeomType == Geometry::SQUARE)
1484  {
1485  static int sq_ind[8][4] =
1486  {
1487  {0, 1, 2, 3}, {-1, -3, -2, -4},
1488  {2, 0, 3, 1}, {-2, -1, -4, -3},
1489  {3, 2, 1, 0}, {-4, -2, -3, -1},
1490  {1, 3, 0, 2}, {-3, -4, -1, -2}
1491  };
1492 
1493  return sq_ind[Or];
1494  }
1495  else
1496  {
1497  return NULL;
1498  }
1499 }
1500 
1501 
1502 H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
1503 {
1504  MFEM_VERIFY(p >= 1, "H1_FECollection requires order >= 1.");
1505  MFEM_VERIFY(dim >= 0 && dim <= 3, "H1_FECollection requires 0 <= dim <= 3.");
1506 
1507  const int pm1 = p - 1, pm2 = pm1 - 1, pm3 = pm2 - 1;
1508 
1509  int pt_type = BasisType::GetQuadrature1D(btype);
1510  b_type = BasisType::Check(btype);
1511  switch (btype)
1512  {
1514  {
1515  snprintf(h1_name, 32, "H1_%dD_P%d", dim, p);
1516  break;
1517  }
1518  case BasisType::Positive:
1519  {
1520  snprintf(h1_name, 32, "H1Pos_%dD_P%d", dim, p);
1521  break;
1522  }
1523  default:
1524  {
1525  MFEM_VERIFY(Quadrature1D::CheckClosed(pt_type) !=
1527  "unsupported BasisType: " << BasisType::Name(btype));
1528 
1529  snprintf(h1_name, 32, "H1@%c_%dD_P%d",
1530  (int)BasisType::GetChar(btype), dim, p);
1531  }
1532  }
1533 
1534  for (int g = 0; g < Geometry::NumGeom; g++)
1535  {
1536  H1_dof[g] = 0;
1537  H1_Elements[g] = NULL;
1538  }
1539  for (int i = 0; i < 2; i++)
1540  {
1541  SegDofOrd[i] = NULL;
1542  }
1543  for (int i = 0; i < 6; i++)
1544  {
1545  TriDofOrd[i] = NULL;
1546  }
1547  for (int i = 0; i < 8; i++)
1548  {
1549  QuadDofOrd[i] = NULL;
1550  }
1551 
1552  H1_dof[Geometry::POINT] = 1;
1553  H1_Elements[Geometry::POINT] = new PointFiniteElement;
1554 
1555  if (dim >= 1)
1556  {
1557  H1_dof[Geometry::SEGMENT] = pm1;
1558  if (b_type == BasisType::Positive)
1559  {
1560  H1_Elements[Geometry::SEGMENT] = new H1Pos_SegmentElement(p);
1561  }
1562  else
1563  {
1564  H1_Elements[Geometry::SEGMENT] = new H1_SegmentElement(p, btype);
1565  }
1566 
1567  SegDofOrd[0] = new int[2*pm1];
1568  SegDofOrd[1] = SegDofOrd[0] + pm1;
1569  for (int i = 0; i < pm1; i++)
1570  {
1571  SegDofOrd[0][i] = i;
1572  SegDofOrd[1][i] = pm2 - i;
1573  }
1574  }
1575 
1576  if (dim >= 2)
1577  {
1578  H1_dof[Geometry::TRIANGLE] = (pm1*pm2)/2;
1579  H1_dof[Geometry::SQUARE] = pm1*pm1;
1580  if (b_type == BasisType::Positive)
1581  {
1582  H1_Elements[Geometry::TRIANGLE] = new H1Pos_TriangleElement(p);
1583  H1_Elements[Geometry::SQUARE] = new H1Pos_QuadrilateralElement(p);
1584  }
1585  else
1586  {
1587  H1_Elements[Geometry::TRIANGLE] = new H1_TriangleElement(p, btype);
1588  H1_Elements[Geometry::SQUARE] = new H1_QuadrilateralElement(p, btype);
1589  }
1590 
1591  const int &TriDof = H1_dof[Geometry::TRIANGLE];
1592  const int &QuadDof = H1_dof[Geometry::SQUARE];
1593  TriDofOrd[0] = new int[6*TriDof];
1594  for (int i = 1; i < 6; i++)
1595  {
1596  TriDofOrd[i] = TriDofOrd[i-1] + TriDof;
1597  }
1598  // see Mesh::GetTriOrientation in mesh/mesh.cpp
1599  for (int j = 0; j < pm2; j++)
1600  {
1601  for (int i = 0; i + j < pm2; i++)
1602  {
1603  int o = TriDof - ((pm1 - j)*(pm2 - j))/2 + i;
1604  int k = pm3 - j - i;
1605  TriDofOrd[0][o] = o; // (0,1,2)
1606  TriDofOrd[1][o] = TriDof - ((pm1-j)*(pm2-j))/2 + k; // (1,0,2)
1607  TriDofOrd[2][o] = TriDof - ((pm1-i)*(pm2-i))/2 + k; // (2,0,1)
1608  TriDofOrd[3][o] = TriDof - ((pm1-k)*(pm2-k))/2 + i; // (2,1,0)
1609  TriDofOrd[4][o] = TriDof - ((pm1-k)*(pm2-k))/2 + j; // (1,2,0)
1610  TriDofOrd[5][o] = TriDof - ((pm1-i)*(pm2-i))/2 + j; // (0,2,1)
1611  }
1612  }
1613 
1614  QuadDofOrd[0] = new int[8*QuadDof];
1615  for (int i = 1; i < 8; i++)
1616  {
1617  QuadDofOrd[i] = QuadDofOrd[i-1] + QuadDof;
1618  }
1619  // see Mesh::GetQuadOrientation in mesh/mesh.cpp
1620  for (int j = 0; j < pm1; j++)
1621  {
1622  for (int i = 0; i < pm1; i++)
1623  {
1624  int o = i + j*pm1;
1625  QuadDofOrd[0][o] = i + j*pm1; // (0,1,2,3)
1626  QuadDofOrd[1][o] = j + i*pm1; // (0,3,2,1)
1627  QuadDofOrd[2][o] = j + (pm2 - i)*pm1; // (1,2,3,0)
1628  QuadDofOrd[3][o] = (pm2 - i) + j*pm1; // (1,0,3,2)
1629  QuadDofOrd[4][o] = (pm2 - i) + (pm2 - j)*pm1; // (2,3,0,1)
1630  QuadDofOrd[5][o] = (pm2 - j) + (pm2 - i)*pm1; // (2,1,0,3)
1631  QuadDofOrd[6][o] = (pm2 - j) + i*pm1; // (3,0,1,2)
1632  QuadDofOrd[7][o] = i + (pm2 - j)*pm1; // (3,2,1,0)
1633  }
1634  }
1635 
1636  if (dim >= 3)
1637  {
1638  H1_dof[Geometry::TETRAHEDRON] = (TriDof*pm3)/3;
1639  H1_dof[Geometry::CUBE] = QuadDof*pm1;
1640  H1_dof[Geometry::PRISM] = TriDof*pm1;
1641  if (b_type == BasisType::Positive)
1642  {
1643  H1_Elements[Geometry::TETRAHEDRON] = new H1Pos_TetrahedronElement(p);
1644  H1_Elements[Geometry::CUBE] = new H1Pos_HexahedronElement(p);
1645  H1_Elements[Geometry::PRISM] = new H1Pos_WedgeElement(p);
1646  }
1647  else
1648  {
1649  H1_Elements[Geometry::TETRAHEDRON] =
1650  new H1_TetrahedronElement(p, btype);
1651  H1_Elements[Geometry::CUBE] = new H1_HexahedronElement(p, btype);
1652  H1_Elements[Geometry::PRISM] = new H1_WedgeElement(p, btype);
1653  }
1654  }
1655  }
1656 }
1657 
1659  int Or) const
1660 {
1661  if (GeomType == Geometry::SEGMENT)
1662  {
1663  return (Or > 0) ? SegDofOrd[0] : SegDofOrd[1];
1664  }
1665  else if (GeomType == Geometry::TRIANGLE)
1666  {
1667  return TriDofOrd[Or%6];
1668  }
1669  else if (GeomType == Geometry::SQUARE)
1670  {
1671  return QuadDofOrd[Or%8];
1672  }
1673  return NULL;
1674 }
1675 
1677 {
1678  int p = H1_dof[Geometry::SEGMENT] + 1;
1679  int dim = -1;
1680  if (!strncmp(h1_name, "H1_", 3))
1681  {
1682  dim = atoi(h1_name + 3);
1683  }
1684  else if (!strncmp(h1_name, "H1Pos_", 6))
1685  {
1686  dim = atoi(h1_name + 6);
1687  }
1688  else if (!strncmp(h1_name, "H1@", 3))
1689  {
1690  dim = atoi(h1_name + 5);
1691  }
1692  return (dim < 0) ? NULL : new H1_Trace_FECollection(p, dim, b_type);
1693 }
1694 
1695 const int *H1_FECollection::GetDofMap(Geometry::Type GeomType) const
1696 {
1697  const int *dof_map = NULL;
1698  const FiniteElement *fe = H1_Elements[GeomType];
1699  switch (GeomType)
1700  {
1701  case Geometry::SEGMENT:
1702  case Geometry::SQUARE:
1703  case Geometry::CUBE:
1704  dof_map = dynamic_cast<const TensorBasisElement *>(fe)
1705  ->GetDofMap().GetData();
1706  break;
1707  default:
1708  MFEM_ABORT("Geometry type " << Geometry::Name[GeomType] << " is not "
1709  "implemented");
1710  // The "Cartesian" ordering for other geometries is defined by the
1711  // class GeometryRefiner.
1712  }
1713  return dof_map;
1714 }
1715 
1717 {
1718  delete [] SegDofOrd[0];
1719  delete [] TriDofOrd[0];
1720  delete [] QuadDofOrd[0];
1721  for (int g = 0; g < Geometry::NumGeom; g++)
1722  {
1723  delete H1_Elements[g];
1724  }
1725 }
1726 
1727 
1729  const int btype)
1730  : H1_FECollection(p, dim-1, btype)
1731 {
1732  if (btype == BasisType::GaussLobatto)
1733  {
1734  snprintf(h1_name, 32, "H1_Trace_%dD_P%d", dim, p);
1735  }
1736  else if (btype == BasisType::Positive)
1737  {
1738  snprintf(h1_name, 32, "H1Pos_Trace_%dD_P%d", dim, p);
1739  }
1740  else // base class checks that type is closed
1741  {
1742  snprintf(h1_name, 32, "H1_Trace@%c_%dD_P%d",
1743  (int)BasisType::GetChar(btype), dim, p);
1744  }
1745 }
1746 
1747 
1748 L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
1749  const int map_type)
1750 {
1751  MFEM_VERIFY(p >= 0, "L2_FECollection requires order >= 0.");
1752 
1753  b_type = BasisType::Check(btype);
1754  const char *prefix = NULL;
1755  switch (map_type)
1756  {
1757  case FiniteElement::VALUE: prefix = "L2"; break;
1758  case FiniteElement::INTEGRAL: prefix = "L2Int"; break;
1759  default:
1760  MFEM_ABORT("invalid map_type: " << map_type);
1761  }
1762  switch (btype)
1763  {
1765  snprintf(d_name, 32, "%s_%dD_P%d", prefix, dim, p);
1766  break;
1767  default:
1768  snprintf(d_name, 32, "%s_T%d_%dD_P%d", prefix, btype, dim, p);
1769  }
1770 
1771  for (int g = 0; g < Geometry::NumGeom; g++)
1772  {
1773  L2_Elements[g] = NULL;
1774  Tr_Elements[g] = NULL;
1775  }
1776  for (int i = 0; i < 2; i++)
1777  {
1778  SegDofOrd[i] = NULL;
1779  }
1780  for (int i = 0; i < 6; i++)
1781  {
1782  TriDofOrd[i] = NULL;
1783  }
1784  OtherDofOrd = NULL;
1785 
1786  if (dim == 0)
1787  {
1788  L2_Elements[Geometry::POINT] = new PointFiniteElement;
1789  }
1790  else if (dim == 1)
1791  {
1792  if (b_type == BasisType::Positive)
1793  {
1794  L2_Elements[Geometry::SEGMENT] = new L2Pos_SegmentElement(p);
1795  }
1796  else
1797  {
1798  L2_Elements[Geometry::SEGMENT] = new L2_SegmentElement(p, btype);
1799  }
1800  L2_Elements[Geometry::SEGMENT]->SetMapType(map_type);
1801 
1802  Tr_Elements[Geometry::POINT] = new PointFiniteElement;
1803  // No need to set the map_type for Tr_Elements.
1804 
1805  const int pp1 = p + 1;
1806  SegDofOrd[0] = new int[2*pp1];
1807  SegDofOrd[1] = SegDofOrd[0] + pp1;
1808  for (int i = 0; i <= p; i++)
1809  {
1810  SegDofOrd[0][i] = i;
1811  SegDofOrd[1][i] = p - i;
1812  }
1813  }
1814  else if (dim == 2)
1815  {
1816  if (b_type == BasisType::Positive)
1817  {
1818  L2_Elements[Geometry::TRIANGLE] = new L2Pos_TriangleElement(p);
1819  L2_Elements[Geometry::SQUARE] = new L2Pos_QuadrilateralElement(p);
1820  }
1821  else
1822  {
1823  L2_Elements[Geometry::TRIANGLE] = new L2_TriangleElement(p, btype);
1824  L2_Elements[Geometry::SQUARE] = new L2_QuadrilateralElement(p, btype);
1825  }
1826  L2_Elements[Geometry::TRIANGLE]->SetMapType(map_type);
1827  L2_Elements[Geometry::SQUARE]->SetMapType(map_type);
1828  // All trace elements use the default Gauss-Legendre points
1829  Tr_Elements[Geometry::SEGMENT] = new L2_SegmentElement(p);
1830 
1831  const int TriDof = L2_Elements[Geometry::TRIANGLE]->GetDof();
1832  TriDofOrd[0] = new int[6*TriDof];
1833  for (int i = 1; i < 6; i++)
1834  {
1835  TriDofOrd[i] = TriDofOrd[i-1] + TriDof;
1836  }
1837  const int pp1 = p + 1, pp2 = pp1 + 1;
1838  for (int j = 0; j <= p; j++)
1839  {
1840  for (int i = 0; i + j <= p; i++)
1841  {
1842  int o = TriDof - ((pp2 - j)*(pp1 - j))/2 + i;
1843  int k = p - j - i;
1844  TriDofOrd[0][o] = o; // (0,1,2)
1845  TriDofOrd[1][o] = TriDof - ((pp2-j)*(pp1-j))/2 + k; // (1,0,2)
1846  TriDofOrd[2][o] = TriDof - ((pp2-i)*(pp1-i))/2 + k; // (2,0,1)
1847  TriDofOrd[3][o] = TriDof - ((pp2-k)*(pp1-k))/2 + i; // (2,1,0)
1848  TriDofOrd[4][o] = TriDof - ((pp2-k)*(pp1-k))/2 + j; // (1,2,0)
1849  TriDofOrd[5][o] = TriDof - ((pp2-i)*(pp1-i))/2 + j; // (0,2,1)
1850  }
1851  }
1852  const int QuadDof = L2_Elements[Geometry::SQUARE]->GetDof();
1853  OtherDofOrd = new int[QuadDof];
1854  for (int j = 0; j < QuadDof; j++)
1855  {
1856  OtherDofOrd[j] = j; // for Or == 0
1857  }
1858  }
1859  else if (dim == 3)
1860  {
1861  if (b_type == BasisType::Positive)
1862  {
1863  L2_Elements[Geometry::TETRAHEDRON] = new L2Pos_TetrahedronElement(p);
1864  L2_Elements[Geometry::CUBE] = new L2Pos_HexahedronElement(p);
1865  L2_Elements[Geometry::PRISM] = new L2Pos_WedgeElement(p);
1866  }
1867  else
1868  {
1869  L2_Elements[Geometry::TETRAHEDRON] =
1870  new L2_TetrahedronElement(p, btype);
1871  L2_Elements[Geometry::CUBE] = new L2_HexahedronElement(p, btype);
1872  L2_Elements[Geometry::PRISM] = new L2_WedgeElement(p, btype);
1873  }
1874  L2_Elements[Geometry::TETRAHEDRON]->SetMapType(map_type);
1875  L2_Elements[Geometry::CUBE]->SetMapType(map_type);
1876  L2_Elements[Geometry::PRISM]->SetMapType(map_type);
1877  // All trace element use the default Gauss-Legendre nodal points
1878  Tr_Elements[Geometry::TRIANGLE] = new L2_TriangleElement(p);
1879  Tr_Elements[Geometry::SQUARE] = new L2_QuadrilateralElement(p);
1880 
1881  const int TetDof = L2_Elements[Geometry::TETRAHEDRON]->GetDof();
1882  const int HexDof = L2_Elements[Geometry::CUBE]->GetDof();
1883  const int PriDof = L2_Elements[Geometry::PRISM]->GetDof();
1884  const int MaxDof = std::max(TetDof, std::max(PriDof, HexDof));
1885  OtherDofOrd = new int[MaxDof];
1886  for (int j = 0; j < MaxDof; j++)
1887  {
1888  OtherDofOrd[j] = j; // for Or == 0
1889  }
1890  }
1891  else
1892  {
1893  mfem::err << "L2_FECollection::L2_FECollection : dim = "
1894  << dim << endl;
1895  mfem_error();
1896  }
1897 }
1898 
1900  int Or) const
1901 {
1902  switch (GeomType)
1903  {
1904  case Geometry::SEGMENT:
1905  return (Or > 0) ? SegDofOrd[0] : SegDofOrd[1];
1906 
1907  case Geometry::TRIANGLE:
1908  return TriDofOrd[Or%6];
1909 
1910  default:
1911  return (Or == 0) ? OtherDofOrd : NULL;
1912  }
1913 }
1914 
1916 {
1917  delete [] OtherDofOrd;
1918  delete [] SegDofOrd[0];
1919  delete [] TriDofOrd[0];
1920  for (int i = 0; i < Geometry::NumGeom; i++)
1921  {
1922  delete L2_Elements[i];
1923  delete Tr_Elements[i];
1924  }
1925 }
1926 
1927 
1928 RT_FECollection::RT_FECollection(const int p, const int dim,
1929  const int cb_type, const int ob_type)
1930  : ob_type(ob_type)
1931 {
1932  MFEM_VERIFY(p >= 0, "RT_FECollection requires order >= 0.");
1933 
1934  int cp_type = BasisType::GetQuadrature1D(cb_type);
1935  int op_type = BasisType::GetQuadrature1D(ob_type);
1936 
1938  {
1939  const char *cb_name = BasisType::Name(cb_type); // this may abort
1940  MFEM_ABORT("unknown closed BasisType: " << cb_name);
1941  }
1943  {
1944  const char *ob_name = BasisType::Name(ob_type); // this may abort
1945  MFEM_ABORT("unknown open BasisType: " << ob_name);
1946  }
1947 
1948  InitFaces(p, dim, FiniteElement::INTEGRAL, true);
1949 
1950  if (cb_type == BasisType::GaussLobatto &&
1951  ob_type == BasisType::GaussLegendre)
1952  {
1953  snprintf(rt_name, 32, "RT_%dD_P%d", dim, p);
1954  }
1955  else
1956  {
1957  snprintf(rt_name, 32, "RT@%c%c_%dD_P%d", (int)BasisType::GetChar(cb_type),
1958  (int)BasisType::GetChar(ob_type), dim, p);
1959  }
1960 
1961  const int pp1 = p + 1;
1962  if (dim == 2)
1963  {
1964  // TODO: cb_type, ob_type for triangles
1966  RT_dof[Geometry::TRIANGLE] = p*pp1;
1967 
1969  ob_type);
1970  // two vector components * n_unk_face *
1971  RT_dof[Geometry::SQUARE] = 2*p*pp1;
1972  }
1973  else if (dim == 3)
1974  {
1975  // TODO: cb_type, ob_type for tets
1977  RT_dof[Geometry::TETRAHEDRON] = p*pp1*(p + 2)/2;
1978 
1979  RT_Elements[Geometry::CUBE] = new RT_HexahedronElement(p, cb_type, ob_type);
1980  RT_dof[Geometry::CUBE] = 3*p*pp1*pp1;
1981  }
1982  else
1983  {
1984  MFEM_ABORT("invalid dim = " << dim);
1985  }
1986 }
1987 
1988 // This is a special protected constructor only used by RT_Trace_FECollection
1989 // and DG_Interface_FECollection
1990 RT_FECollection::RT_FECollection(const int p, const int dim, const int map_type,
1991  const bool signs, const int ob_type)
1992  : ob_type(ob_type)
1993 {
1996  {
1997  const char *ob_name = BasisType::Name(ob_type); // this may abort
1998  MFEM_ABORT("Invalid open basis type: " << ob_name);
1999  }
2000  InitFaces(p, dim, map_type, signs);
2001 }
2002 
2003 void RT_FECollection::InitFaces(const int p, const int dim, const int map_type,
2004  const bool signs)
2005 {
2006  int op_type = BasisType::GetQuadrature1D(ob_type);
2007 
2008  MFEM_VERIFY(Quadrature1D::CheckOpen(op_type) != Quadrature1D::Invalid,
2009  "invalid open point type");
2010 
2011  const int pp1 = p + 1, pp2 = p + 2;
2012 
2013  for (int g = 0; g < Geometry::NumGeom; g++)
2014  {
2015  RT_Elements[g] = NULL;
2016  RT_dof[g] = 0;
2017  }
2018  // Degree of Freedom orderings
2019  for (int i = 0; i < 2; i++)
2020  {
2021  SegDofOrd[i] = NULL;
2022  }
2023  for (int i = 0; i < 6; i++)
2024  {
2025  TriDofOrd[i] = NULL;
2026  }
2027  for (int i = 0; i < 8; i++)
2028  {
2029  QuadDofOrd[i] = NULL;
2030  }
2031 
2032  if (dim == 2)
2033  {
2034  L2_SegmentElement *l2_seg = new L2_SegmentElement(p, ob_type);
2035  l2_seg->SetMapType(map_type);
2036  RT_Elements[Geometry::SEGMENT] = l2_seg;
2037  RT_dof[Geometry::SEGMENT] = pp1;
2038 
2039  SegDofOrd[0] = new int[2*pp1];
2040  SegDofOrd[1] = SegDofOrd[0] + pp1;
2041  for (int i = 0; i <= p; i++)
2042  {
2043  SegDofOrd[0][i] = i;
2044  SegDofOrd[1][i] = signs ? (-1 - (p - i)) : (p - i);
2045  }
2046  }
2047  else if (dim == 3)
2048  {
2049  L2_TriangleElement *l2_tri = new L2_TriangleElement(p, ob_type);
2050  l2_tri->SetMapType(map_type);
2051  RT_Elements[Geometry::TRIANGLE] = l2_tri;
2052  RT_dof[Geometry::TRIANGLE] = pp1*pp2/2;
2053 
2055  l2_quad->SetMapType(map_type);
2056  RT_Elements[Geometry::SQUARE] = l2_quad;
2057  RT_dof[Geometry::SQUARE] = pp1*pp1;
2058 
2059  int TriDof = RT_dof[Geometry::TRIANGLE];
2060  TriDofOrd[0] = new int[6*TriDof];
2061  for (int i = 1; i < 6; i++)
2062  {
2063  TriDofOrd[i] = TriDofOrd[i-1] + TriDof;
2064  }
2065  // see Mesh::GetTriOrientation in mesh/mesh.cpp,
2066  // the constructor of H1_FECollection
2067  for (int j = 0; j <= p; j++)
2068  {
2069  for (int i = 0; i + j <= p; i++)
2070  {
2071  int o = TriDof - ((pp2 - j)*(pp1 - j))/2 + i;
2072  int k = p - j - i;
2073  TriDofOrd[0][o] = o; // (0,1,2)
2074  TriDofOrd[1][o] = -1-(TriDof-((pp2-j)*(pp1-j))/2+k); // (1,0,2)
2075  TriDofOrd[2][o] = TriDof-((pp2-i)*(pp1-i))/2+k; // (2,0,1)
2076  TriDofOrd[3][o] = -1-(TriDof-((pp2-k)*(pp1-k))/2+i); // (2,1,0)
2077  TriDofOrd[4][o] = TriDof-((pp2-k)*(pp1-k))/2+j; // (1,2,0)
2078  TriDofOrd[5][o] = -1-(TriDof-((pp2-i)*(pp1-i))/2+j); // (0,2,1)
2079  if (!signs)
2080  {
2081  for (int k = 1; k < 6; k += 2)
2082  {
2083  TriDofOrd[k][o] = -1 - TriDofOrd[k][o];
2084  }
2085  }
2086  }
2087  }
2088 
2089  int QuadDof = RT_dof[Geometry::SQUARE];
2090  QuadDofOrd[0] = new int[8*QuadDof];
2091  for (int i = 1; i < 8; i++)
2092  {
2093  QuadDofOrd[i] = QuadDofOrd[i-1] + QuadDof;
2094  }
2095  // see Mesh::GetQuadOrientation in mesh/mesh.cpp
2096  for (int j = 0; j <= p; j++)
2097  {
2098  for (int i = 0; i <= p; i++)
2099  {
2100  int o = i + j*pp1;
2101  QuadDofOrd[0][o] = i + j*pp1; // (0,1,2,3)
2102  QuadDofOrd[1][o] = -1 - (j + i*pp1); // (0,3,2,1)
2103  QuadDofOrd[2][o] = j + (p - i)*pp1; // (1,2,3,0)
2104  QuadDofOrd[3][o] = -1 - ((p - i) + j*pp1); // (1,0,3,2)
2105  QuadDofOrd[4][o] = (p - i) + (p - j)*pp1; // (2,3,0,1)
2106  QuadDofOrd[5][o] = -1 - ((p - j) + (p - i)*pp1); // (2,1,0,3)
2107  QuadDofOrd[6][o] = (p - j) + i*pp1; // (3,0,1,2)
2108  QuadDofOrd[7][o] = -1 - (i + (p - j)*pp1); // (3,2,1,0)
2109  if (!signs)
2110  {
2111  for (int k = 1; k < 8; k += 2)
2112  {
2113  QuadDofOrd[k][o] = -1 - QuadDofOrd[k][o];
2114  }
2115  }
2116  }
2117  }
2118  }
2119 }
2120 
2122  int Or) const
2123 {
2124  if (GeomType == Geometry::SEGMENT)
2125  {
2126  return (Or > 0) ? SegDofOrd[0] : SegDofOrd[1];
2127  }
2128  else if (GeomType == Geometry::TRIANGLE)
2129  {
2130  return TriDofOrd[Or%6];
2131  }
2132  else if (GeomType == Geometry::SQUARE)
2133  {
2134  return QuadDofOrd[Or%8];
2135  }
2136  return NULL;
2137 }
2138 
2140 {
2141  int dim, p;
2142  if (!strncmp(rt_name, "RT_", 3))
2143  {
2144  dim = atoi(rt_name + 3);
2145  p = atoi(rt_name + 7);
2146  }
2147  else // rt_name = RT@.._.D_P*
2148  {
2149  dim = atoi(rt_name + 6);
2150  p = atoi(rt_name + 10);
2151  }
2153 }
2154 
2156 {
2157  delete [] SegDofOrd[0];
2158  delete [] TriDofOrd[0];
2159  delete [] QuadDofOrd[0];
2160  for (int g = 0; g < Geometry::NumGeom; g++)
2161  {
2162  delete RT_Elements[g];
2163  }
2164 }
2165 
2166 
2168  const int map_type,
2169  const int ob_type)
2170  : RT_FECollection(p, dim, map_type, true, ob_type)
2171 {
2172  const char *prefix =
2173  (map_type == FiniteElement::INTEGRAL) ? "RT_Trace" : "RT_ValTrace";
2174  char ob_str[3] = { '\0', '\0', '\0' };
2175 
2176  if (ob_type != BasisType::GaussLegendre)
2177  {
2178  ob_str[0] = '@';
2179  ob_str[1] = BasisType::GetChar(ob_type);
2180  }
2181  snprintf(rt_name, 32, "%s%s_%dD_P%d", prefix, ob_str, dim, p);
2182 
2183  MFEM_VERIFY(dim == 2 || dim == 3, "Wrong dimension, dim = " << dim);
2184 }
2185 
2186 
2188  const int map_type,
2189  const int ob_type)
2190  : RT_FECollection(p, dim, map_type, false, ob_type)
2191 {
2192  MFEM_VERIFY(dim == 2 || dim == 3, "Wrong dimension, dim = " << dim);
2193 
2194  const char *prefix =
2195  (map_type == FiniteElement::VALUE) ? "DG_Iface" : "DG_IntIface";
2196  if (ob_type == BasisType::GaussLegendre)
2197  {
2198  snprintf(rt_name, 32, "%s_%dD_P%d", prefix, dim, p);
2199  }
2200  else
2201  {
2202  snprintf(rt_name, 32, "%s@%c_%dD_P%d", prefix,
2203  (int)BasisType::GetChar(ob_type), dim, p);
2204  }
2205 }
2206 
2207 ND_FECollection::ND_FECollection(const int p, const int dim,
2208  const int cb_type, const int ob_type)
2209 {
2210  MFEM_VERIFY(p >= 1, "ND_FECollection requires order >= 1.");
2211  MFEM_VERIFY(dim >= 1 && dim <= 3, "ND_FECollection requires 1 <= dim <= 3.");
2212 
2213  const int pm1 = p - 1, pm2 = p - 2;
2214 
2215  if (cb_type == BasisType::GaussLobatto &&
2216  ob_type == BasisType::GaussLegendre)
2217  {
2218  snprintf(nd_name, 32, "ND_%dD_P%d", dim, p);
2219  }
2220  else
2221  {
2222  snprintf(nd_name, 32, "ND@%c%c_%dD_P%d", (int)BasisType::GetChar(cb_type),
2223  (int)BasisType::GetChar(ob_type), dim, p);
2224  }
2225 
2226  for (int g = 0; g < Geometry::NumGeom; g++)
2227  {
2228  ND_Elements[g] = NULL;
2229  ND_dof[g] = 0;
2230  }
2231  for (int i = 0; i < 2; i++)
2232  {
2233  SegDofOrd[i] = NULL;
2234  }
2235  for (int i = 0; i < 6; i++)
2236  {
2237  TriDofOrd[i] = NULL;
2238  }
2239  for (int i = 0; i < 8; i++)
2240  {
2241  QuadDofOrd[i] = NULL;
2242  }
2243 
2244  int op_type = BasisType::GetQuadrature1D(ob_type);
2245  int cp_type = BasisType::GetQuadrature1D(cb_type);
2246 
2247  // Error checking
2249  {
2250  const char *ob_name = BasisType::Name(ob_type);
2251  MFEM_ABORT("Invalid open basis point type: " << ob_name);
2252  }
2254  {
2255  const char *cb_name = BasisType::Name(cb_type);
2256  MFEM_ABORT("Invalid closed basis point type: " << cb_name);
2257  }
2258 
2259  if (dim >= 1)
2260  {
2261  ND_Elements[Geometry::SEGMENT] = new ND_SegmentElement(p, ob_type);
2263 
2264  SegDofOrd[0] = new int[2*p];
2265  SegDofOrd[1] = SegDofOrd[0] + p;
2266  for (int i = 0; i < p; i++)
2267  {
2268  SegDofOrd[0][i] = i;
2269  SegDofOrd[1][i] = -1 - (pm1 - i);
2270  }
2271  }
2272 
2273  if (dim >= 2)
2274  {
2276  ob_type);
2277  ND_dof[Geometry::SQUARE] = 2*p*pm1;
2278 
2279  // TODO: cb_type and ob_type for triangles
2281  ND_dof[Geometry::TRIANGLE] = p*pm1;
2282 
2283  int QuadDof = ND_dof[Geometry::SQUARE];
2284  QuadDofOrd[0] = new int[8*QuadDof];
2285  for (int i = 1; i < 8; i++)
2286  {
2287  QuadDofOrd[i] = QuadDofOrd[i-1] + QuadDof;
2288  }
2289  // see Mesh::GetQuadOrientation in mesh/mesh.cpp
2290  for (int j = 0; j < pm1; j++)
2291  {
2292  for (int i = 0; i < p; i++)
2293  {
2294  int d1 = i + j*p; // x-component
2295  int d2 = p*pm1 + j + i*pm1; // y-component
2296  // (0,1,2,3)
2297  QuadDofOrd[0][d1] = d1;
2298  QuadDofOrd[0][d2] = d2;
2299  // (0,3,2,1)
2300  QuadDofOrd[1][d1] = d2;
2301  QuadDofOrd[1][d2] = d1;
2302  // (1,2,3,0)
2303  // QuadDofOrd[2][d1] = p*pm1 + (pm2 - j) + i*pm1;
2304  // QuadDofOrd[2][d2] = -1 - ((pm1 - i) + j*p);
2305  QuadDofOrd[2][d1] = -1 - (p*pm1 + j + (pm1 - i)*pm1);
2306  QuadDofOrd[2][d2] = i + (pm2 - j)*p;
2307  // (1,0,3,2)
2308  QuadDofOrd[3][d1] = -1 - ((pm1 - i) + j*p);
2309  QuadDofOrd[3][d2] = p*pm1 + (pm2 - j) + i*pm1;
2310  // (2,3,0,1)
2311  QuadDofOrd[4][d1] = -1 - ((pm1 - i) + (pm2 - j)*p);
2312  QuadDofOrd[4][d2] = -1 - (p*pm1 + (pm2 - j) + (pm1 - i)*pm1);
2313  // (2,1,0,3)
2314  QuadDofOrd[5][d1] = -1 - (p*pm1 + (pm2 - j) + (pm1 - i)*pm1);
2315  QuadDofOrd[5][d2] = -1 - ((pm1 - i) + (pm2 - j)*p);
2316  // (3,0,1,2)
2317  // QuadDofOrd[6][d1] = -1 - (p*pm1 + j + (pm1 - i)*pm1);
2318  // QuadDofOrd[6][d2] = i + (pm2 - j)*p;
2319  QuadDofOrd[6][d1] = p*pm1 + (pm2 - j) + i*pm1;
2320  QuadDofOrd[6][d2] = -1 - ((pm1 - i) + j*p);
2321  // (3,2,1,0)
2322  QuadDofOrd[7][d1] = i + (pm2 - j)*p;
2323  QuadDofOrd[7][d2] = -1 - (p*pm1 + j + (pm1 - i)*pm1);
2324  }
2325  }
2326 
2327  int TriDof = ND_dof[Geometry::TRIANGLE];
2328  TriDofOrd[0] = new int[6*TriDof];
2329  for (int i = 1; i < 6; i++)
2330  {
2331  TriDofOrd[i] = TriDofOrd[i-1] + TriDof;
2332  }
2333  // see Mesh::GetTriOrientation in mesh/mesh.cpp,
2334  // the constructor of H1_FECollection
2335  for (int j = 0; j <= pm2; j++)
2336  {
2337  for (int i = 0; i + j <= pm2; i++)
2338  {
2339  int k1 = p*pm1 - (p - j)*(pm1 - j) + 2*i;
2340  int k2 = p*pm1 - (p - i)*(pm1 - i) + 2*j;
2341  // (0,1,2)
2342  TriDofOrd[0][k1 ] = k1;
2343  TriDofOrd[0][k1+1] = k1 + 1;
2344  // (0,2,1)
2345  TriDofOrd[5][k1 ] = k2 + 1;
2346  TriDofOrd[5][k1+1] = k2;
2347 
2348  // The other orientations can not be supported with the current
2349  // interface. The method Mesh::ReorientTetMesh will ensure that
2350  // only orientations 0 and 5 are generated.
2351  }
2352  }
2353  }
2354 
2355  if (dim >= 3)
2356  {
2357  ND_Elements[Geometry::CUBE] = new ND_HexahedronElement(p, cb_type, ob_type);
2358  ND_dof[Geometry::CUBE] = 3*p*pm1*pm1;
2359 
2360  // TODO: cb_type and ob_type for tets
2362  ND_dof[Geometry::TETRAHEDRON] = p*pm1*pm2/2;
2363  }
2364 }
2365 
2367  int Or) const
2368 {
2369  if (GeomType == Geometry::SEGMENT)
2370  {
2371  return (Or > 0) ? SegDofOrd[0] : SegDofOrd[1];
2372  }
2373  else if (GeomType == Geometry::TRIANGLE)
2374  {
2375  if (Or != 0 && Or != 5)
2376  {
2377  MFEM_ABORT("triangle face orientation " << Or << " is not supported! "
2378  "Use Mesh::ReorientTetMesh to fix it.");
2379  }
2380  return TriDofOrd[Or%6];
2381  }
2382  else if (GeomType == Geometry::SQUARE)
2383  {
2384  return QuadDofOrd[Or%8];
2385  }
2386  return NULL;
2387 }
2388 
2390 {
2391  int p, dim, cb_type, ob_type;
2392 
2394  if (nd_name[2] == '_') // ND_
2395  {
2396  dim = atoi(nd_name + 3);
2397  cb_type = BasisType::GaussLobatto;
2398  ob_type = BasisType::GaussLegendre;
2399  }
2400  else // ND@
2401  {
2402  dim = atoi(nd_name + 6);
2403  cb_type = BasisType::GetType(nd_name[3]);
2404  ob_type = BasisType::GetType(nd_name[4]);
2405  }
2406  return new ND_Trace_FECollection(p, dim, cb_type, ob_type);
2407 }
2408 
2410 {
2411  delete [] SegDofOrd[0];
2412  delete [] TriDofOrd[0];
2413  delete [] QuadDofOrd[0];
2414  for (int g = 0; g < Geometry::NumGeom; g++)
2415  {
2416  delete ND_Elements[g];
2417  }
2418 }
2419 
2420 
2422  const int cb_type,
2423  const int ob_type)
2424  : ND_FECollection(p, dim-1, cb_type, ob_type)
2425 {
2426  if (cb_type == BasisType::GaussLobatto &&
2427  ob_type == BasisType::GaussLegendre)
2428  {
2429  snprintf(nd_name, 32, "ND_Trace_%dD_P%d", dim, p);
2430  }
2431  else
2432  {
2433  snprintf(nd_name, 32, "ND_Trace@%c%c_%dD_P%d",
2434  (int)BasisType::GetChar(cb_type),
2435  (int)BasisType::GetChar(ob_type), dim, p);
2436  }
2437 }
2438 
2439 
2441 {
2442  snprintf(d_name, 32, "Local_%s", fe_name);
2443 
2444  Local_Element = NULL;
2445 
2446  if (!strcmp(fe_name, "BiCubic2DFiniteElement") ||
2447  !strcmp(fe_name, "Quad_Q3"))
2448  {
2449  GeomType = Geometry::SQUARE;
2450  Local_Element = new BiCubic2DFiniteElement;
2451  }
2452  else if (!strcmp(fe_name, "Nedelec1HexFiniteElement") ||
2453  !strcmp(fe_name, "Hex_ND1"))
2454  {
2455  GeomType = Geometry::CUBE;
2456  Local_Element = new Nedelec1HexFiniteElement;
2457  }
2458  else if (!strncmp(fe_name, "H1_", 3))
2459  {
2460  GeomType = Geometry::SQUARE;
2461  Local_Element = new H1_QuadrilateralElement(atoi(fe_name + 7));
2462  }
2463  else if (!strncmp(fe_name, "H1Pos_", 6))
2464  {
2465  GeomType = Geometry::SQUARE;
2466  Local_Element = new H1Pos_QuadrilateralElement(atoi(fe_name + 10));
2467  }
2468  else if (!strncmp(fe_name, "L2_", 3))
2469  {
2470  GeomType = Geometry::SQUARE;
2471  Local_Element = new L2_QuadrilateralElement(atoi(fe_name + 7));
2472  }
2473  else
2474  {
2475  mfem::err << "Local_FECollection::Local_FECollection : fe_name = "
2476  << fe_name << endl;
2477  mfem_error();
2478  }
2479 }
2480 
2481 
2483 {
2484  const int order = (Order == VariableOrder) ? 1 : Order;
2485  SegmentFE = new NURBS1DFiniteElement(order);
2486  QuadrilateralFE = new NURBS2DFiniteElement(order);
2487  ParallelepipedFE = new NURBS3DFiniteElement(order);
2488 
2489  SetOrder(Order);
2490 }
2491 
2492 void NURBSFECollection::SetOrder(int Order) const
2493 {
2494  mOrder = Order;
2495  if (Order != VariableOrder)
2496  {
2497  snprintf(name, 16, "NURBS%i", Order);
2498  }
2499  else
2500  {
2501  snprintf(name, 16, "NURBS");
2502  }
2503 }
2504 
2506 {
2507  delete ParallelepipedFE;
2508  delete QuadrilateralFE;
2509  delete SegmentFE;
2510 }
2511 
2512 const FiniteElement *
2514 {
2515  switch (GeomType)
2516  {
2517  case Geometry::SEGMENT: return SegmentFE;
2518  case Geometry::SQUARE: return QuadrilateralFE;
2519  case Geometry::CUBE: return ParallelepipedFE;
2520  default:
2521  mfem_error ("NURBSFECollection: unknown geometry type.");
2522  }
2523  return SegmentFE; // Make some compilers happy
2524 }
2525 
2527 {
2528  mfem_error("NURBSFECollection::DofForGeometry");
2529  return 0; // Make some compilers happy
2530 }
2531 
2533  int Or) const
2534 {
2535  mfem_error("NURBSFECollection::DofOrderForOrientation");
2536  return NULL;
2537 }
2538 
2540 {
2541  MFEM_ABORT("NURBS finite elements can not be statically condensed!");
2542  return NULL;
2543 }
2544 
2545 }
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:834
Abstract class for Finite Elements.
Definition: fe.hpp:229
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:951
Arbitrary order non-uniform rational B-splines (NURBS) finite elements.
Definition: fe_coll.hpp:278
H1_Trace_FECollection(const int p, const int dim, const int btype=BasisType::GaussLobatto)
Definition: fe_coll.cpp:1728
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1165
int Size() const
Logical size of the array.
Definition: array.hpp:118
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:1157
Version of QuadraticDiscont2DFECollection with dofs in the Gaussian points.
Definition: fe_coll.hpp:661
int RT_dof[Geometry::NumGeom]
Definition: fe_coll.hpp:186
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1027
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:973
FiniteElement * ND_Elements[Geometry::NumGeom]
Definition: fe_coll.hpp:244
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1206
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:1122
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:1236
static int Check(int b_type)
If the input does not represents a valid BasisType, abort with an error; otherwise return the input...
Definition: fe.hpp:44
For scalar fields; preserves volume integrals.
Definition: fe.hpp:274
virtual FiniteElementCollection * GetTraceCollection() const
Definition: fe_coll.cpp:41
virtual ~NURBSFECollection()
Definition: fe_coll.cpp:2505
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:1899
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:1990
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:570
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:2121
FiniteElementCollection * GetTraceCollection() const
Definition: fe_coll.cpp:2539
static const int NumGeom
Definition: geom.hpp:41
const Geometry::Type geom
Definition: ex1.cpp:40
virtual ~L2_FECollection()
Definition: fe_coll.cpp:1915
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:2513
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:755
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:612
Bernstein polynomials.
Definition: fe.hpp:35
Piecewise-(bi)linear continuous finite elements.
Definition: fe_coll.hpp:332
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:1658
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:924
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1373
static int GetQuadrature1D(int b_type)
Get the corresponding Quadrature1D constant, when that makes sense; otherwise return Quadrature1D::In...
Definition: fe.hpp:60
FiniteElementCollection * GetTraceCollection() const
Definition: fe_coll.cpp:2389
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:989
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:658
void InitFaces(const int p, const int dim, const int map_type, const bool signs)
Definition: fe_coll.cpp:2003
FiniteElementCollection * GetTraceCollection() const
Definition: fe_coll.cpp:2139
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:2187
int HasFaceDofs(Geometry::Type GeomType) const
Definition: fe_coll.cpp:25
static const char * Name(int b_type)
Check and convert a BasisType constant to a string identifier.
Definition: fe.hpp:87
static int GetType(char b_ident)
Convert char basis identifier to a BasisType constant.
Definition: fe.hpp:103
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:916
NURBSFECollection(int Order=VariableOrder)
The parameter Order must be either a positive number, for fixed order, or VariableOrder (default)...
Definition: fe_coll.cpp:2482
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1180
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1244
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:622
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:648
void SetMapType(int M)
Definition: fe.hpp:581
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:692
virtual ~RT_FECollection()
Definition: fe_coll.cpp:2155
L2_FECollection(const int p, const int dim, const int btype=BasisType::GaussLegendre, const int map_type=FiniteElement::VALUE)
Definition: fe_coll.cpp:1748
Piecewise-(bi)cubic continuous finite elements.
Definition: fe_coll.hpp:404
PointFiniteElement PointFE
Definition: point.cpp:30
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:820
const int * GetDofMap(Geometry::Type GeomType) const
Get the Cartesian to local H1 dof map.
Definition: fe_coll.cpp:1695
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:875
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:536
int dim
Definition: ex3.cpp:48
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:319
FiniteElement * RT_Elements[Geometry::NumGeom]
Definition: fe_coll.hpp:185
static const int Dimension[NumGeom]
Definition: geom.hpp:46
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:902
static void GetNVE(int &nv, int &ne)
Definition: fe_coll.cpp:289
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1361
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:1351
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
Definition: error.cpp:146
H1_FECollection(const int p, const int dim=3, const int btype=BasisType::GaussLobatto)
Definition: fe_coll.cpp:1502
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:2421
TriLinear3DFiniteElement HexahedronFE
Definition: hexahedron.cpp:52
ND_FECollection(const int p, const int dim, const int cb_type=BasisType::GaussLobatto, const int ob_type=BasisType::GaussLegendre)
Definition: fe_coll.cpp:2207
Discontinuous collection defined locally by a given finite element.
Definition: fe_coll.hpp:864
Version of QuadraticDiscont2DFECollection with positive basis functions.
Definition: fe_coll.hpp:644
virtual ~ND_FECollection()
Definition: fe_coll.cpp:2409
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:807
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:959
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:778
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:364
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:1055
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1257
Version of QuadraticFECollection with positive basis functions.
Definition: fe_coll.hpp:383
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:578
virtual ~H1_FECollection()
Definition: fe_coll.cpp:1716
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:1311
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:1273
FiniteElementCollection * GetTraceCollection() const
Definition: fe_coll.cpp:1676
static const char * Name[NumGeom]
Definition: geom.hpp:44
Piecewise-linear nonconforming finite elements in 3D.
Definition: fe_coll.hpp:452
Crouzeix-Raviart nonconforming elements in 2D.
Definition: fe_coll.hpp:431
class H1_WedgeElement WedgeFE
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:765
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1294
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1106
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
Definition: fe_coll.hpp:180
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:997
static void GetEdge(int &nv, v_t &v, int &ne, int &e, int &eo, const int edge_info)
Definition: fe_coll.cpp:299
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:1434
static int CheckClosed(int type)
If the Quadrature1D type is not closed return Invalid; otherwise return type.
Definition: intrules.cpp:812
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:2492
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:861
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition: fe.hpp:311
OutStream err(std::cerr)
Global stream used by the library for standard error output. Initially it uses the same std::streambu...
Definition: globals.hpp:69
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:2366
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:741
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
Definition: array.hpp:618
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:595
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1281
class Linear3DFiniteElement TetrahedronFE
Definition: fe.cpp:11963
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1404
Linear2DFiniteElement TriangleFE
Definition: fe.cpp:11959
static int CheckOpen(int type)
If the Quadrature1D type is not open return Invalid; otherwise return type.
Definition: intrules.cpp:824
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1335
Version of LinearDiscont2DFECollection with dofs in the Gaussian points.
Definition: fe_coll.hpp:585
static FiniteElementCollection * New(const char *name)
Factory method: return a newly allocated FiniteElementCollection according to the given name...
Definition: fe_coll.cpp:47
static char GetChar(int b_type)
Check and convert a BasisType constant to a char basis identifier.
Definition: fe.hpp:97
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1318
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:1019
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:727
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1006
virtual const char * Name() const
Definition: fe_coll.hpp:53
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1465
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:1480
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:2532
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:635
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1063
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1075
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1219
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:792
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:675
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1418
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:2167
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:553
Piecewise-(bi)quadratic continuous finite elements.
Definition: fe_coll.hpp:357
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:1196
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:848
Arbitrary order H(curl)-conforming Nedelec finite elements.
Definition: fe_coll.hpp:240
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1040
For scalar fields; preserves point values.
Definition: fe.hpp:273
Arbitrary order H1-conforming (continuous) finite elements.
Definition: fe_coll.hpp:83
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1091
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:2526
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:937
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:890
Local_FECollection(const char *fe_name)
Definition: fe_coll.cpp:2440
virtual int DofForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1143
BiLinear2DFiniteElement QuadrilateralFE
Linear (P1) finite elements on quadrilaterals.
Definition: fe_coll.hpp:607
Linear1DFiniteElement SegmentFE
Definition: segment.cpp:49
virtual const int * DofOrderForOrientation(Geometry::Type GeomType, int Or) const
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:1389
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1130
int ND_dof[Geometry::NumGeom]
Definition: fe_coll.hpp:245
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1452
Arbitrary order &quot;L2-conforming&quot; discontinuous finite elements.
Definition: fe_coll.hpp:134