12#ifndef MFEM_TEMPLATE_FESPACE
13#define MFEM_TEMPLATE_FESPACE
51 const Array<int> *loc_dof_map = fe.GetDofMap();
55 "the element-to-dof Table is not compatible with this FE!");
56 int num_dofs = el_dof.
Size() * FE::dofs;
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++)
70 MFEM_ASSERT(el_dof.
RowSize(i) == FE::dofs,
71 "incompatible element-to-dof Table!");
72 for (
int j = 0; j < FE::dofs; j++)
74 el_dof_list_[j+FE::dofs*i] =
75 el_dof.
GetJ()[loc_dof_map_[j]+FE::dofs*i];
85 inline MFEM_ALWAYS_INLINE
92 inline MFEM_ALWAYS_INLINE
95 inline MFEM_ALWAYS_INLINE
101 inline MFEM_ALWAYS_INLINE
102 int map(
int loc_dof_idx,
int elem_offset)
const
104 return loc_dof_list[loc_dof_idx + elem_offset * FE::dofs];
111template <
typename FE,
typename IndexType>
117 static const int dofs = FE::dofs;
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
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++)
151 for (
int i = 0; i < FE::dofs; i++)
153 for (
int s = 0;
s < SS;
s++)
156 glob_dof_data[
ind.map(i,
s+SS*j)]);
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
174 typename dof_layout_t,
typename dof_data_t,
175 typename glob_dof_data_t>
176 inline MFEM_ALWAYS_INLINE
178 const dof_data_t &dof_data,
179 glob_dof_data_t &glob_dof_data)
const
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++)
187 for (
int i = 0; i < FE::dofs; i++)
189 for (
int s = 0;
s < SS;
s++)
192 dof_data[dof_layout.ind(i,j)][
s]);
198 template <
typename dof_layout_t,
typename dof_data_t,
199 typename glob_dof_data_t>
200 inline MFEM_ALWAYS_INLINE
202 const dof_data_t &dof_data,
203 glob_dof_data_t &glob_dof_data)
const
211 typename vec_layout_t,
typename glob_vdof_data_t,
212 typename vdof_layout_t,
typename vdof_data_t>
213 inline MFEM_ALWAYS_INLINE
215 const glob_vdof_data_t &glob_vdof_data,
216 const vdof_layout_t &vdof_layout,
217 vdof_data_t &vdof_data)
const
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");
227 for (
int k = 0; k < NC; k++)
230 for (
int j = 0; j < NE; j++)
232 for (
int i = 0; i < FE::dofs; i++)
234 for (
int s = 0;
s < SS;
s++)
237 glob_vdof_data[vl.ind(
ind.map(i,
s+SS*j), k)]);
242 for (
int js = 0; js < TE; js++)
244 for (
int i = 0; i < FE::dofs; i++)
246 const int s = js % SS, j = js / SS;
248 glob_vdof_data[vl.ind(
ind.map(i,js), k)]);
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
259 const glob_vdof_data_t &glob_vdof_data,
260 const vdof_layout_t &vdof_layout,
261 vdof_data_t &vdof_data)
const
268 typename vdof_layout_t,
typename vdof_data_t,
269 typename vec_layout_t,
typename glob_vdof_data_t>
270 inline MFEM_ALWAYS_INLINE
272 const vdof_data_t &vdof_data,
273 const vec_layout_t &vl,
274 glob_vdof_data_t &glob_vdof_data)
const
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");
284 for (
int k = 0; k < NC; k++)
287 for (
int j = 0; j < NE; j++)
289 for (
int i = 0; i < FE::dofs; i++)
291 for (
int s = 0;
s < SS;
s++)
294 vdof_data[vdof_layout.ind(i,k,j)][
s]);
299 for (
int js = 0; js < TE; js++)
301 for (
int i = 0; i < FE::dofs; i++)
303 const int s = js % SS, j = js / SS;
305 vdof_data[vdof_layout.ind(i,k,j)][
s]);
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
316 const vdof_data_t &vdof_data,
317 const vec_layout_t &vl,
318 glob_vdof_data_t &glob_vdof_data)
const
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
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
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;
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++)
345 for (
int js = 0; js < TE; js++)
347 for (
int i = 0; i < FE::dofs; i++)
349 const int s = js % SS, j = js / SS;
351 vdof_data[vdof_layout.ind(i,k,j)][
s],
352 glob_vdof_data[vl.ind(
ind.map(i,js), first_comp+k)]);
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
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
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;
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++)
380 for (
int js = 0; js < TE; js++)
382 for (
int i = 0; i < FE::dofs; i++)
384 const int s = js % SS, j = js / SS;
386 glob_vdof_data[vl.ind(
ind.map(i,js), first_comp+k)],
387 vdof_data[vdof_layout.ind(i,k,j)][
s]);
393 template <
typename vcomplex_t>
397 const int SS =
sizeof(m[0])/
sizeof(m[0][0]);
399 MFEM_FLOPS_ADD(FE::dofs*FE::dofs);
400 for (
int s = 0;
s < TE;
s++)
402 for (
int i = 0; i < FE::dofs; i++)
405 for (
int j = 0; j < FE::dofs; j++)
414 template <
typename vec_layout_t,
typename vcomplex_t>
419 const int SS =
sizeof(m[0])/
sizeof(m[0][0]);
421 MFEM_FLOPS_ADD(FE::dofs*FE::dofs);
422 for (
int s = 0;
s < TE;
s++)
424 for (
int i = 0; i < FE::dofs; i++)
427 for (
int j = 0; j < FE::dofs; j++)
429 M.
_Add_(vl.ind(
ind.map(j,
s), block_j), m(i,j)[
s]);
439template <
typename FE>
458 if (!h1_fec) {
return false; }
460 if (fe->
GetOrder() != FE_type::degree) {
return false; }
464 template <
typename vec_layout_t>
467 return Matches(fes) && vec_layout_t::Matches(fes);
474template <
typename FE>
486 "the FE space is not compatible with this FE!");
492 inline MFEM_ALWAYS_INLINE
495 offset = FE::dofs * elem_idx;
498 inline MFEM_ALWAYS_INLINE
499 int map(
int loc_dof_idx,
int elem_offset)
const
501 return offset + loc_dof_idx + elem_offset * FE::dofs;
508template <
typename FE>
527 if (!l2_fec) {
return false; }
529 if (fe->
GetOrder() != FE_type::degree) {
return false; }
533 template <
typename vec_layout_t>
536 return Matches(fes) && vec_layout_t::Matches(fes);
T * GetData()
Returns the data.
MFEM_ALWAYS_INLINE int map(int loc_dof_idx, int elem_offset) const
MFEM_ALWAYS_INLINE void SetElement(int elem_idx)
DGIndexer(const FE &fe, const FiniteElementSpace &fes)
MFEM_ALWAYS_INLINE void SetElement(int elem_idx)
MFEM_ALWAYS_INLINE ElementDofIndexer(const ElementDofIndexer &orig)
MFEM_ALWAYS_INLINE ~ElementDofIndexer()
MFEM_ALWAYS_INLINE int map(int loc_dof_idx, int elem_offset) const
ElementDofIndexer(const FE &fe, const FiniteElementSpace &fes)
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
const Table & GetElementToDofTable() const
Return a reference to the internal Table that stores the lists of scalar dofs, for each mesh element,...
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
int GetNE() const
Returns number of elements in the mesh.
const FiniteElementCollection * FEColl() const
Abstract class for all finite elements.
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Arbitrary order H1-conforming (continuous) finite elements.
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
TFiniteElementSpace_simple< FE, ElementDofIndexer< FE > > base_class
static bool Matches(const FiniteElementSpace &fes)
H1_FiniteElementSpace(const FE &fe, const FiniteElementSpace &fes)
static bool VectorMatches(const FiniteElementSpace &fes)
Arbitrary order "L2-conforming" discontinuous finite elements.
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
TFiniteElementSpace_simple< FE, DGIndexer< FE > > base_class
static bool Matches(const FiniteElementSpace &fes)
static bool VectorMatches(const FiniteElementSpace &fes)
L2_FiniteElementSpace(const FE &fe, const FiniteElementSpace &fes)
void ClearColPtr() const
Reset the "current row" set by calling SetColPtr(). This method must be called between any two calls ...
void SetColPtr(const int row) const
Initialize the SparseMatrix for fast access to the entries of the given row which becomes the "curren...
void _Add_(const int col, const real_t a)
Add a value to an entry in the "current row". See SetColPtr().
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
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
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
void Assemble(const TMatrix< FE::dofs, FE::dofs, vcomplex_t > &m, SparseMatrix &M) const
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
TFiniteElementSpace_simple(const FE &fe, const FiniteElementSpace &fes)
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
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
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
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
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
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
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
int Size() const
Returns the number of TYPE I elements.
int Size_of_connections() const
lvalue_t & Assign(lvalue_t &a, const rvalue_t &b)