12 #ifndef MFEM_TEMPLATE_FESPACE
13 #define MFEM_TEMPLATE_FESPACE
15 #include "../config/tconfig.hpp"
16 #include "../general/tassign.hpp"
17 #include "../linalg/ttensor.hpp"
39 template <
typename FE>
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];
111 template <
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++)
155 Assign<Op>(dof_data[dof_layout.ind(i,j)][
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
169 Extract<AssignOp::Set>(glob_dof_data, dof_layout, dof_data);
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++)
191 Assign<Op>(glob_dof_data[
ind.map(i,
s+SS*j)],
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
205 Assemble<AssignOp::Add>(dof_layout, dof_data, glob_dof_data);
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++)
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)]);
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;
247 Assign<Op>(vdof_data[vdof_layout.ind(i,k,j)][
s],
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
263 VectorExtract<AssignOp::Set>(vl, glob_vdof_data, vdof_layout, vdof_data);
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++)
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]);
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;
304 Assign<Op>(glob_vdof_data[vl.ind(
ind.map(i,js), k)],
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
320 VectorAssemble<AssignOp::Add>(vdof_layout, vdof_data, vl, glob_vdof_data);
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;
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)]);
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;
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]);
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]);
439 template <
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);
474 template <
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;
508 template <
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);
542 #endif // MFEM_TEMPLATE_FESPACE
Abstract class for all finite elements.
H1_FiniteElementSpace(const FE &fe, const FiniteElementSpace &fes)
void _Add_(const int col, const double a)
Add a value to an entry in the "current row". See SetColPtr().
int GetNDofs() const
Returns number of degrees of freedom.
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) 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
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
void Assemble(const TMatrix< FE::dofs, FE::dofs, vcomplex_t > &m, SparseMatrix &M) const
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
MFEM_ALWAYS_INLINE int map(int loc_dof_idx, int elem_offset) const
T * GetData()
Returns the data.
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
static bool VectorMatches(const FiniteElementSpace &fes)
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
int Size_of_connections() const
MFEM_ALWAYS_INLINE void SetElement(int elem_idx)
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
int GetNE() const
Returns number of elements in the mesh.
void ClearColPtr() const
Reset the "current row" set by calling SetColPtr(). This method must be called between any two calls ...
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
L2_FiniteElementSpace(const FE &fe, const FiniteElementSpace &fes)
ElementDofIndexer(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 Extract(const glob_dof_data_t &glob_dof_data, const dof_layout_t &dof_layout, dof_data_t &dof_data) const
static bool VectorMatches(const FiniteElementSpace &fes)
MFEM_ALWAYS_INLINE void SetElement(int elem_idx)
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
int Size() const
Returns the number of TYPE I elements.
static bool Matches(const FiniteElementSpace &fes)
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
static bool Matches(const FiniteElementSpace &fes)
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
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
void SetColPtr(const int row) const
Initialize the SparseMatrix for fast access to the entries of the given row which becomes the "curren...
TFiniteElementSpace_simple< FE, ElementDofIndexer< FE > > base_class
DGIndexer(const FE &fe, const FiniteElementSpace &fes)
TFiniteElementSpace_simple(const FE &fe, const FiniteElementSpace &fes)
MFEM_ALWAYS_INLINE ~ElementDofIndexer()
TFiniteElementSpace_simple< FE, DGIndexer< FE > > base_class
const FiniteElementCollection * FEColl() const
MFEM_ALWAYS_INLINE ElementDofIndexer(const ElementDofIndexer &orig)
Arbitrary order H1-conforming (continuous) finite elements.
const Table & GetElementToDofTable() const
Return a reference to the internal Table that stores the lists of scalar dofs, for each mesh element...
MFEM_ALWAYS_INLINE int map(int loc_dof_idx, int elem_offset) 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
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
Arbitrary order "L2-conforming" discontinuous finite elements.