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().
void SetColPtr(const int row) const
Initialize the SparseMatrix for fast access to the entries of the given row which becomes the "curren...
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
T * GetData()
Returns the data.
int GetNDofs() const
Returns number of degrees of freedom.
MFEM_ALWAYS_INLINE int map(int loc_dof_idx, int elem_offset) const
static bool VectorMatches(const FiniteElementSpace &fes)
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 SetElement(int elem_idx)
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const
L2_FiniteElementSpace(const FE &fe, const FiniteElementSpace &fes)
void Assemble(const TMatrix< FE::dofs, FE::dofs, vcomplex_t > &m, SparseMatrix &M) const
void ClearColPtr() const
Reset the "current row" set by calling SetColPtr(). This method must be called between any two calls ...
ElementDofIndexer(const FE &fe, const FiniteElementSpace &fes)
const FiniteElementCollection * FEColl() 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 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 GetNE() const
Returns number of elements in the mesh.
static bool Matches(const FiniteElementSpace &fes)
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
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
static bool Matches(const FiniteElementSpace &fes)
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
TFiniteElementSpace_simple< FE, ElementDofIndexer< FE > > base_class
DGIndexer(const FE &fe, const FiniteElementSpace &fes)
TFiniteElementSpace_simple(const FE &fe, const FiniteElementSpace &fes)
int Size() const
Returns the number of TYPE I elements.
MFEM_ALWAYS_INLINE ~ElementDofIndexer()
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 Assemble(const dof_layout_t &dof_layout, const dof_data_t &dof_data, glob_dof_data_t &glob_dof_data) const
MFEM_ALWAYS_INLINE int map(int loc_dof_idx, int elem_offset) const
int Size_of_connections() const
TFiniteElementSpace_simple< FE, DGIndexer< FE > > base_class
MFEM_ALWAYS_INLINE ElementDofIndexer(const ElementDofIndexer &orig)
Arbitrary order H1-conforming (continuous) finite elements.
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 Assemble(const dof_layout_t &dof_layout, const dof_data_t &dof_data, glob_dof_data_t &glob_dof_data) const
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 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
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
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
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
Arbitrary order "L2-conforming" discontinuous finite elements.