MFEM  v4.6.0
Finite element discretization library
tfespace.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2023, 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 #ifndef MFEM_TEMPLATE_FESPACE
13 #define MFEM_TEMPLATE_FESPACE
14 
15 #include "../config/tconfig.hpp"
16 #include "../general/tassign.hpp"
17 #include "../linalg/ttensor.hpp"
18 #include "tfe.hpp" // for TFiniteElementSpace_simple
19 #include "fespace.hpp"
20 
21 namespace mfem
22 {
23 
24 // Templated finite element space classes, cf. fespace.?pp and fe_coll.?pp
25 
26 // Index types
27 
28 // IndexType must define:
29 // - constructor IndexType(const FE &fe, const FiniteElementSpace &fes)
30 // - copy constructor
31 // - void SetElement(int elem_idx)
32 // - int map(int loc_dof_idx, int elem_offset) const --> glob_dof_idx, for
33 // single component; elem_offset is relative to the currently set element.
34 
35 // Index type based on an array listing the dofs for each element where all
36 // elements are assumed to have the same number of dofs. Such an array is
37 // constructed from the J array of an element-to-dof Table with optional local
38 // renumbering to ensure tensor-product local dof ordering when needed.
39 template <typename FE>
41 {
42 protected:
43  const int *el_dof_list, *loc_dof_list;
44  bool own_list;
45 
46 public:
47  typedef FE FE_type;
48 
49  ElementDofIndexer(const FE &fe, const FiniteElementSpace &fes)
50  {
51  const Array<int> *loc_dof_map = fe.GetDofMap();
52  // fes.BuildElementToDofTable();
53  const Table &el_dof = fes.GetElementToDofTable();
54  MFEM_ASSERT(el_dof.Size_of_connections() == el_dof.Size() * FE::dofs,
55  "the element-to-dof Table is not compatible with this FE!");
56  int num_dofs = el_dof.Size() * FE::dofs;
57  if (!loc_dof_map)
58  {
59  // no local dof reordering
60  el_dof_list = el_dof.GetJ();
61  own_list = false;
62  }
63  else
64  {
65  // reorder the local dofs according to loc_dof_map
66  int *el_dof_list_ = new int[num_dofs];
67  const int *loc_dof_map_ = loc_dof_map->GetData();
68  for (int i = 0; i < el_dof.Size(); i++)
69  {
70  MFEM_ASSERT(el_dof.RowSize(i) == FE::dofs,
71  "incompatible element-to-dof Table!");
72  for (int j = 0; j < FE::dofs; j++)
73  {
74  el_dof_list_[j+FE::dofs*i] =
75  el_dof.GetJ()[loc_dof_map_[j]+FE::dofs*i];
76  }
77  }
78  el_dof_list = el_dof_list_;
79  own_list = true;
80  }
81  loc_dof_list = el_dof_list; // point to element 0
82  }
83 
84  // Shallow copy constructor
85  inline MFEM_ALWAYS_INLINE
87  : el_dof_list(orig.el_dof_list),
89  own_list(false)
90  { }
91 
92  inline MFEM_ALWAYS_INLINE
93  ~ElementDofIndexer() { if (own_list) { delete [] el_dof_list; } }
94 
95  inline MFEM_ALWAYS_INLINE
96  void SetElement(int elem_idx)
97  {
98  loc_dof_list = el_dof_list + elem_idx * FE::dofs;
99  }
100 
101  inline MFEM_ALWAYS_INLINE
102  int map(int loc_dof_idx, int elem_offset) const
103  {
104  return loc_dof_list[loc_dof_idx + elem_offset * FE::dofs];
105  }
106 };
107 
108 
109 // Simple template Finite Element Space, built using an IndexType. For a
110 // description of the requirements on IndexType, see above.
111 template <typename FE, typename IndexType>
113 {
114 public:
115  typedef FE FE_type;
116  typedef IndexType index_type;
117  static const int dofs = FE::dofs;
118 
119 protected:
122 
123 public:
125  : ind(fe, fes), num_elems(fes.GetNE()), remain_elems(num_elems) { }
126 
127  // default copy constructor
128 
129  int GetNE() const { return num_elems; }
130 
131  void SetElement(int el) { ind.SetElement(el); remain_elems = num_elems-el; }
132 
133 #if 0
134  // Multi-element Extract:
135  // Extract dofs for multiple elements starting with the current element.
136  // The number of elements to extract is given by the second dimension of
137  // dof_layout_t: dof_layout is (DOFS x NumElems).
138  template <AssignOp::Type Op, typename glob_dof_data_t,
139  typename dof_layout_t, typename dof_data_t>
140  inline MFEM_ALWAYS_INLINE
141  void Extract(const glob_dof_data_t &glob_dof_data,
142  const dof_layout_t &dof_layout,
143  dof_data_t &dof_data) const
144  {
145  const int SS = sizeof(dof_data[0])/sizeof(dof_data[0][0]);
146  const int NE = dof_layout_t::dim_2;
147  MFEM_STATIC_ASSERT(FE::dofs == dof_layout_t::dim_1,
148  "invalid number of dofs");
149  for (int j = 0; j < NE; j++)
150  {
151  for (int i = 0; i < FE::dofs; i++)
152  {
153  for (int s = 0; s < SS; s++)
154  {
155  Assign<Op>(dof_data[dof_layout.ind(i,j)][s],
156  glob_dof_data[ind.map(i,s+SS*j)]);
157  }
158  }
159  }
160  }
161 
162  template <typename glob_dof_data_t,
163  typename dof_layout_t, typename dof_data_t>
164  inline MFEM_ALWAYS_INLINE
165  void Extract(const glob_dof_data_t &glob_dof_data,
166  const dof_layout_t &dof_layout,
167  dof_data_t &dof_data) const
168  {
169  Extract<AssignOp::Set>(glob_dof_data, dof_layout, dof_data);
170  }
171 
172  // Multi-element assemble.
173  template <AssignOp::Type Op,
174  typename dof_layout_t, typename dof_data_t,
175  typename glob_dof_data_t>
176  inline MFEM_ALWAYS_INLINE
177  void Assemble(const dof_layout_t &dof_layout,
178  const dof_data_t &dof_data,
179  glob_dof_data_t &glob_dof_data) const
180  {
181  const int SS = sizeof(dof_data[0])/sizeof(dof_data[0][0]);
182  const int NE = dof_layout_t::dim_2;
183  MFEM_STATIC_ASSERT(FE::dofs == dof_layout_t::dim_1,
184  "invalid number of dofs");
185  for (int j = 0; j < NE; j++)
186  {
187  for (int i = 0; i < FE::dofs; i++)
188  {
189  for (int s = 0; s < SS; s++)
190  {
191  Assign<Op>(glob_dof_data[ind.map(i,s+SS*j)],
192  dof_data[dof_layout.ind(i,j)][s]);
193  }
194  }
195  }
196  }
197 
198  template <typename dof_layout_t, typename dof_data_t,
199  typename glob_dof_data_t>
200  inline MFEM_ALWAYS_INLINE
201  void Assemble(const dof_layout_t &dof_layout,
202  const dof_data_t &dof_data,
203  glob_dof_data_t &glob_dof_data) const
204  {
205  Assemble<AssignOp::Add>(dof_layout, dof_data, glob_dof_data);
206  }
207 #endif
208 
209  // Multi-element VectorExtract: vdof_layout is (DOFS x NumComp x NumElems).
210  template <AssignOp::Type Op,
211  typename vec_layout_t, typename glob_vdof_data_t,
212  typename vdof_layout_t, typename vdof_data_t>
213  inline MFEM_ALWAYS_INLINE
214  void VectorExtract(const vec_layout_t &vl,
215  const glob_vdof_data_t &glob_vdof_data,
216  const vdof_layout_t &vdof_layout,
217  vdof_data_t &vdof_data) const
218  {
219  const int SS = sizeof(vdof_data[0])/sizeof(vdof_data[0][0]);
220  const int NC = vdof_layout_t::dim_2;
221  const int NE = vdof_layout_t::dim_3;
222  MFEM_STATIC_ASSERT(FE::dofs == vdof_layout_t::dim_1,
223  "invalid number of dofs");
224  MFEM_ASSERT(NC == vl.NumComponents(), "invalid number of components");
225  const int TE = std::min(SS*NE, remain_elems);
226  // const int TE = SS*NE;
227  for (int k = 0; k < NC; k++)
228  {
229 #if 0
230  for (int j = 0; j < NE; j++)
231  {
232  for (int i = 0; i < FE::dofs; i++)
233  {
234  for (int s = 0; s < SS; s++)
235  {
236  Assign<Op>(vdof_data[vdof_layout.ind(i,k,j)][s],
237  glob_vdof_data[vl.ind(ind.map(i,s+SS*j), k)]);
238  }
239  }
240  }
241 #else
242  for (int js = 0; js < TE; js++)
243  {
244  for (int i = 0; i < FE::dofs; i++)
245  {
246  const int s = js % SS, j = js / SS;
247  Assign<Op>(vdof_data[vdof_layout.ind(i,k,j)][s],
248  glob_vdof_data[vl.ind(ind.map(i,js), k)]);
249  }
250  }
251 #endif
252  }
253  }
254 
255  template <typename vec_layout_t, typename glob_vdof_data_t,
256  typename vdof_layout_t, typename vdof_data_t>
257  inline MFEM_ALWAYS_INLINE
258  void VectorExtract(const vec_layout_t &vl,
259  const glob_vdof_data_t &glob_vdof_data,
260  const vdof_layout_t &vdof_layout,
261  vdof_data_t &vdof_data) const
262  {
263  VectorExtract<AssignOp::Set>(vl, glob_vdof_data, vdof_layout, vdof_data);
264  }
265 
266  // Multi-element VectorAssemble: vdof_layout is (DOFS x NumComp x NumElems).
267  template <AssignOp::Type Op,
268  typename vdof_layout_t, typename vdof_data_t,
269  typename vec_layout_t, typename glob_vdof_data_t>
270  inline MFEM_ALWAYS_INLINE
271  void VectorAssemble(const vdof_layout_t &vdof_layout,
272  const vdof_data_t &vdof_data,
273  const vec_layout_t &vl,
274  glob_vdof_data_t &glob_vdof_data) const
275  {
276  const int SS = sizeof(vdof_data[0])/sizeof(vdof_data[0][0]);
277  const int NC = vdof_layout_t::dim_2;
278  const int NE = vdof_layout_t::dim_3;
279  MFEM_STATIC_ASSERT(FE::dofs == vdof_layout_t::dim_1,
280  "invalid number of dofs");
281  MFEM_ASSERT(NC == vl.NumComponents(), "invalid number of components");
282  const int TE = std::min(SS*NE, remain_elems);
283  // const int TE = SS*NE;
284  for (int k = 0; k < NC; k++)
285  {
286 #if 0
287  for (int j = 0; j < NE; j++)
288  {
289  for (int i = 0; i < FE::dofs; i++)
290  {
291  for (int s = 0; s < SS; s++)
292  {
293  Assign<Op>(glob_vdof_data[vl.ind(ind.map(i,s+SS*j), k)],
294  vdof_data[vdof_layout.ind(i,k,j)][s]);
295  }
296  }
297  }
298 #else
299  for (int js = 0; js < TE; js++)
300  {
301  for (int i = 0; i < FE::dofs; i++)
302  {
303  const int s = js % SS, j = js / SS;
304  Assign<Op>(glob_vdof_data[vl.ind(ind.map(i,js), k)],
305  vdof_data[vdof_layout.ind(i,k,j)][s]);
306  }
307  }
308 #endif
309  }
310  }
311 
312  template <typename vdof_layout_t, typename vdof_data_t,
313  typename vec_layout_t, typename glob_vdof_data_t>
314  inline MFEM_ALWAYS_INLINE
315  void VectorAssemble(const vdof_layout_t &vdof_layout,
316  const vdof_data_t &vdof_data,
317  const vec_layout_t &vl,
318  glob_vdof_data_t &glob_vdof_data) const
319  {
320  VectorAssemble<AssignOp::Add>(vdof_layout, vdof_data, vl, glob_vdof_data);
321  }
322 
323  // Extract a static number of consecutive components; vdof_layout is
324  // (dofs x NC x NE), where NC is the number of components to extract. It is
325  // assumed that: first_comp + NC <= vl.NumComponents().
326  template <typename vdof_layout_t, typename vdof_data_t,
327  typename vec_layout_t, typename glob_vdof_data_t>
328  inline MFEM_ALWAYS_INLINE
329  void ExtractComponents(int first_comp,
330  const vec_layout_t &vl,
331  const glob_vdof_data_t &glob_vdof_data,
332  const vdof_layout_t &vdof_layout,
333  vdof_data_t &vdof_data) const
334  {
335  const int SS = sizeof(vdof_data[0])/sizeof(vdof_data[0][0]);
336  const int NC = vdof_layout_t::dim_2;
337  const int NE = vdof_layout_t::dim_3;
338  const int TE = std::min(SS*NE, remain_elems);
339  MFEM_STATIC_ASSERT(FE::dofs == vdof_layout_t::dim_1,
340  "invalid number of dofs");
341  MFEM_ASSERT(first_comp + NC <= vl.NumComponents(),
342  "invalid number of components");
343  for (int k = 0; k < NC; k++)
344  {
345  for (int js = 0; js < TE; js++)
346  {
347  for (int i = 0; i < FE::dofs; i++)
348  {
349  const int s = js % SS, j = js / SS;
350  Assign<AssignOp::Set>(
351  vdof_data[vdof_layout.ind(i,k,j)][s],
352  glob_vdof_data[vl.ind(ind.map(i,js), first_comp+k)]);
353  }
354  }
355  }
356  }
357 
358  // Assemble a static number of consecutive components; vdof_layout is
359  // (dofs x NC x NE), where NC is the number of components to add. It is
360  // assumed that: first_comp + NC <= vl.NumComponents().
361  template <typename vdof_layout_t, typename vdof_data_t,
362  typename vec_layout_t, typename glob_vdof_data_t>
363  inline MFEM_ALWAYS_INLINE
364  void AssembleComponents(int first_comp,
365  const vdof_layout_t &vdof_layout,
366  const vdof_data_t &vdof_data,
367  const vec_layout_t &vl,
368  glob_vdof_data_t &glob_vdof_data) const
369  {
370  const int SS = sizeof(vdof_data[0])/sizeof(vdof_data[0][0]);
371  const int NC = vdof_layout_t::dim_2;
372  const int NE = vdof_layout_t::dim_3;
373  const int TE = std::min(SS*NE, remain_elems);
374  MFEM_STATIC_ASSERT(FE::dofs == vdof_layout_t::dim_1,
375  "invalid number of dofs");
376  MFEM_ASSERT(first_comp + NC <= vl.NumComponents(),
377  "invalid number of components");
378  for (int k = 0; k < NC; k++)
379  {
380  for (int js = 0; js < TE; js++)
381  {
382  for (int i = 0; i < FE::dofs; i++)
383  {
384  const int s = js % SS, j = js / SS;
385  Assign<AssignOp::Add>(
386  glob_vdof_data[vl.ind(ind.map(i,js), first_comp+k)],
387  vdof_data[vdof_layout.ind(i,k,j)][s]);
388  }
389  }
390  }
391  }
392 
393  template <typename vcomplex_t>
395  SparseMatrix &M) const
396  {
397  const int SS = sizeof(m[0])/sizeof(m[0][0]);
398  const int TE = std::min(SS, remain_elems);
399  MFEM_FLOPS_ADD(FE::dofs*FE::dofs);
400  for (int s = 0; s < TE; s++)
401  {
402  for (int i = 0; i < FE::dofs; i++)
403  {
404  M.SetColPtr(ind.map(i,s));
405  for (int j = 0; j < FE::dofs; j++)
406  {
407  M._Add_(ind.map(j,s), m(i,j)[s]);
408  }
409  M.ClearColPtr();
410  }
411  }
412  }
413 
414  template <typename vec_layout_t, typename vcomplex_t>
415  void AssembleBlock(int block_i, int block_j, const vec_layout_t &vl,
417  SparseMatrix &M) const
418  {
419  const int SS = sizeof(m[0])/sizeof(m[0][0]);
420  const int TE = std::min(SS, remain_elems);
421  MFEM_FLOPS_ADD(FE::dofs*FE::dofs);
422  for (int s = 0; s < TE; s++)
423  {
424  for (int i = 0; i < FE::dofs; i++)
425  {
426  M.SetColPtr(vl.ind(ind.map(i,s), block_i));
427  for (int j = 0; j < FE::dofs; j++)
428  {
429  M._Add_(vl.ind(ind.map(j,s), block_j), m(i,j)[s]);
430  }
431  M.ClearColPtr();
432  }
433  }
434  }
435 };
436 
437 // H1 Finite Element Space
438 
439 template <typename FE>
441  : public TFiniteElementSpace_simple<FE,ElementDofIndexer<FE> >
442 {
443 public:
444  typedef FE FE_type;
446 
447  H1_FiniteElementSpace(const FE &fe, const FiniteElementSpace &fes)
448  : base_class(fe, fes)
449  { }
450 
451  // default copy constructor
452 
453  static bool Matches(const FiniteElementSpace &fes)
454  {
455  const FiniteElementCollection *fec = fes.FEColl();
456  const H1_FECollection *h1_fec =
457  dynamic_cast<const H1_FECollection *>(fec);
458  if (!h1_fec) { return false; }
459  const FiniteElement *fe = h1_fec->FiniteElementForGeometry(FE_type::geom);
460  if (fe->GetOrder() != FE_type::degree) { return false; }
461  return true;
462  }
463 
464  template <typename vec_layout_t>
465  static bool VectorMatches(const FiniteElementSpace &fes)
466  {
467  return Matches(fes) && vec_layout_t::Matches(fes);
468  }
469 };
470 
471 
472 // Simple index type for DG spaces, where the map method is given by:
473 // glob_dof_idx = loc_dof_idx + elem_idx * num_dofs.
474 template <typename FE>
476 {
477 protected:
478  int offset;
479 
480 public:
481  typedef FE FE_type;
482 
483  DGIndexer(const FE &fe, const FiniteElementSpace &fes)
484  {
485  MFEM_ASSERT(fes.GetNDofs() == fes.GetNE() * FE::dofs,
486  "the FE space is not compatible with this FE!");
487  offset = 0;
488  }
489 
490  // default copy constructor
491 
492  inline MFEM_ALWAYS_INLINE
493  void SetElement(int elem_idx)
494  {
495  offset = FE::dofs * elem_idx;
496  }
497 
498  inline MFEM_ALWAYS_INLINE
499  int map(int loc_dof_idx, int elem_offset) const
500  {
501  return offset + loc_dof_idx + elem_offset * FE::dofs;
502  }
503 };
504 
505 
506 // L2 Finite Element Space
507 
508 template <typename FE>
510  : public TFiniteElementSpace_simple<FE,DGIndexer<FE> >
511 {
512 public:
513  typedef FE FE_type;
515 
516  L2_FiniteElementSpace(const FE &fe, const FiniteElementSpace &fes)
517  : base_class(fe, fes)
518  { }
519 
520  // default copy constructor
521 
522  static bool Matches(const FiniteElementSpace &fes)
523  {
524  const FiniteElementCollection *fec = fes.FEColl();
525  const L2_FECollection *l2_fec =
526  dynamic_cast<const L2_FECollection *>(fec);
527  if (!l2_fec) { return false; }
528  const FiniteElement *fe = l2_fec->FiniteElementForGeometry(FE_type::geom);
529  if (fe->GetOrder() != FE_type::degree) { return false; }
530  return true;
531  }
532 
533  template <typename vec_layout_t>
534  static bool VectorMatches(const FiniteElementSpace &fes)
535  {
536  return Matches(fes) && vec_layout_t::Matches(fes);
537  }
538 };
539 
540 } // namespace mfem
541 
542 #endif // MFEM_TEMPLATE_FESPACE
Abstract class for all finite elements.
Definition: fe_base.hpp:233
H1_FiniteElementSpace(const FE &fe, const FiniteElementSpace &fes)
Definition: tfespace.hpp:447
void _Add_(const int col, const double a)
Add a value to an entry in the "current row". See SetColPtr().
Definition: sparsemat.hpp:585
int * GetJ()
Definition: table.hpp:114
void SetColPtr(const int row) const
Initialize the SparseMatrix for fast access to the entries of the given row which becomes the "curren...
Definition: sparsemat.hpp:792
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:1951
T * GetData()
Returns the data.
Definition: array.hpp:115
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
Definition: fespace.hpp:706
MFEM_ALWAYS_INLINE int map(int loc_dof_idx, int elem_offset) const
Definition: tfespace.hpp:499
static bool VectorMatches(const FiniteElementSpace &fes)
Definition: tfespace.hpp:534
MFEM_ALWAYS_INLINE void VectorAssemble(const vdof_layout_t &vdof_layout, const vdof_data_t &vdof_data, const vec_layout_t &vl, glob_vdof_data_t &glob_vdof_data) const
Definition: tfespace.hpp:315
int RowSize(int i) const
Definition: table.hpp:108
const int * loc_dof_list
Definition: tfespace.hpp:43
MFEM_ALWAYS_INLINE void SetElement(int elem_idx)
Definition: tfespace.hpp:96
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
Definition: fe_coll.cpp:2332
L2_FiniteElementSpace(const FE &fe, const FiniteElementSpace &fes)
Definition: tfespace.hpp:516
void Assemble(const TMatrix< FE::dofs, FE::dofs, vcomplex_t > &m, SparseMatrix &M) const
Definition: tfespace.hpp:394
void ClearColPtr() const
Reset the "current row" set by calling SetColPtr(). This method must be called between any two calls ...
Definition: sparsemat.hpp:827
Data type sparse matrix.
Definition: sparsemat.hpp:50
ElementDofIndexer(const FE &fe, const FiniteElementSpace &fes)
Definition: tfespace.hpp:49
const FiniteElementCollection * FEColl() const
Definition: fespace.hpp:723
MFEM_ALWAYS_INLINE void Extract(const glob_dof_data_t &glob_dof_data, const dof_layout_t &dof_layout, dof_data_t &dof_data) const
Definition: tfespace.hpp:165
static bool VectorMatches(const FiniteElementSpace &fes)
Definition: tfespace.hpp:465
MFEM_ALWAYS_INLINE void SetElement(int elem_idx)
Definition: tfespace.hpp:493
const int * el_dof_list
Definition: tfespace.hpp:43
MFEM_ALWAYS_INLINE void ExtractComponents(int first_comp, const vec_layout_t &vl, const glob_vdof_data_t &glob_vdof_data, const vdof_layout_t &vdof_layout, vdof_data_t &vdof_data) const
Definition: tfespace.hpp:329
int GetNE() const
Returns number of elements in the mesh.
Definition: fespace.hpp:736
static bool Matches(const FiniteElementSpace &fes)
Definition: tfespace.hpp:522
MFEM_ALWAYS_INLINE void Extract(const glob_dof_data_t &glob_dof_data, const dof_layout_t &dof_layout, dof_data_t &dof_data) const
Definition: tfespace.hpp:141
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:219
static bool Matches(const FiniteElementSpace &fes)
Definition: tfespace.hpp:453
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Definition: fe_coll.hpp:26
TFiniteElementSpace_simple< FE, ElementDofIndexer< FE > > base_class
Definition: tfespace.hpp:445
DGIndexer(const FE &fe, const FiniteElementSpace &fes)
Definition: tfespace.hpp:483
TFiniteElementSpace_simple(const FE &fe, const FiniteElementSpace &fes)
Definition: tfespace.hpp:124
int Size() const
Returns the number of TYPE I elements.
Definition: table.hpp:92
MFEM_ALWAYS_INLINE ~ElementDofIndexer()
Definition: tfespace.hpp:93
MFEM_ALWAYS_INLINE void AssembleComponents(int first_comp, const vdof_layout_t &vdof_layout, const vdof_data_t &vdof_data, const vec_layout_t &vl, glob_vdof_data_t &glob_vdof_data) const
Definition: tfespace.hpp:364
MFEM_ALWAYS_INLINE void Assemble(const dof_layout_t &dof_layout, const dof_data_t &dof_data, glob_dof_data_t &glob_dof_data) const
Definition: tfespace.hpp:201
MFEM_ALWAYS_INLINE int map(int loc_dof_idx, int elem_offset) const
Definition: tfespace.hpp:102
int Size_of_connections() const
Definition: table.hpp:98
TFiniteElementSpace_simple< FE, DGIndexer< FE > > base_class
Definition: tfespace.hpp:514
MFEM_ALWAYS_INLINE ElementDofIndexer(const ElementDofIndexer &orig)
Definition: tfespace.hpp:86
Arbitrary order H1-conforming (continuous) finite elements.
Definition: fe_coll.hpp:259
RefCoord s[3]
MFEM_ALWAYS_INLINE void VectorExtract(const vec_layout_t &vl, const glob_vdof_data_t &glob_vdof_data, const vdof_layout_t &vdof_layout, vdof_data_t &vdof_data) const
Definition: tfespace.hpp:214
MFEM_ALWAYS_INLINE void Assemble(const dof_layout_t &dof_layout, const dof_data_t &dof_data, glob_dof_data_t &glob_dof_data) const
Definition: tfespace.hpp:177
const Table & GetElementToDofTable() const
Return a reference to the internal Table that stores the lists of scalar dofs, for each mesh element...
Definition: fespace.hpp:1097
MFEM_ALWAYS_INLINE void VectorExtract(const vec_layout_t &vl, const glob_vdof_data_t &glob_vdof_data, const vdof_layout_t &vdof_layout, vdof_data_t &vdof_data) const
Definition: tfespace.hpp:258
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Definition: fe_base.hpp:327
MFEM_ALWAYS_INLINE void VectorAssemble(const vdof_layout_t &vdof_layout, const vdof_data_t &vdof_data, const vec_layout_t &vl, glob_vdof_data_t &glob_vdof_data) const
Definition: tfespace.hpp:271
void AssembleBlock(int block_i, int block_j, const vec_layout_t &vl, const TMatrix< FE::dofs, FE::dofs, vcomplex_t > &m, SparseMatrix &M) const
Definition: tfespace.hpp:415
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition: fe_coll.hpp:327