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>
134 typename dof_layout_t,
typename dof_data_t>
135 inline MFEM_ALWAYS_INLINE
136 void Extract(
const glob_dof_data_t &glob_dof_data,
137 const dof_layout_t &dof_layout,
138 dof_data_t &dof_data)
const
140 const int NE = dof_layout_t::dim_2;
141 MFEM_STATIC_ASSERT(FE::dofs == dof_layout_t::dim_1,
142 "invalid number of dofs");
143 for (
int j = 0; j < NE; j++)
145 for (
int i = 0; i < FE::dofs; i++)
147 Assign<Op>(dof_data[dof_layout.ind(i,j)],
148 glob_dof_data[
ind.map(i,j)]);
153 template <
typename glob_dof_data_t,
154 typename dof_layout_t,
typename dof_data_t>
155 inline MFEM_ALWAYS_INLINE
156 void Extract(
const glob_dof_data_t &glob_dof_data,
157 const dof_layout_t &dof_layout,
158 dof_data_t &dof_data)
const
160 Extract<AssignOp::Set>(glob_dof_data, dof_layout, dof_data);
165 typename dof_layout_t,
typename dof_data_t,
166 typename glob_dof_data_t>
167 inline MFEM_ALWAYS_INLINE
169 const dof_data_t &dof_data,
170 glob_dof_data_t &glob_dof_data)
const
172 const int NE = dof_layout_t::dim_2;
173 MFEM_STATIC_ASSERT(FE::dofs == dof_layout_t::dim_1,
174 "invalid number of dofs");
175 for (
int j = 0; j < NE; j++)
177 for (
int i = 0; i < FE::dofs; i++)
179 Assign<Op>(glob_dof_data[
ind.map(i,j)],
180 dof_data[dof_layout.ind(i,j)]);
185 template <
typename dof_layout_t,
typename dof_data_t,
186 typename glob_dof_data_t>
187 inline MFEM_ALWAYS_INLINE
189 const dof_data_t &dof_data,
190 glob_dof_data_t &glob_dof_data)
const
192 Assemble<AssignOp::Add>(dof_layout, dof_data, glob_dof_data);
197 typename vec_layout_t,
typename glob_vdof_data_t,
198 typename vdof_layout_t,
typename vdof_data_t>
199 inline MFEM_ALWAYS_INLINE
201 const glob_vdof_data_t &glob_vdof_data,
202 const vdof_layout_t &vdof_layout,
203 vdof_data_t &vdof_data)
const
205 const int NC = vdof_layout_t::dim_2;
206 const int NE = vdof_layout_t::dim_3;
207 MFEM_STATIC_ASSERT(FE::dofs == vdof_layout_t::dim_1,
208 "invalid number of dofs");
209 MFEM_ASSERT(NC == vl.NumComponents(),
"invalid number of components");
210 for (
int k = 0; k < NC; k++)
212 for (
int j = 0; j < NE; j++)
214 for (
int i = 0; i < FE::dofs; i++)
216 Assign<Op>(vdof_data[vdof_layout.ind(i,k,j)],
217 glob_vdof_data[vl.ind(
ind.map(i,j), k)]);
223 template <
typename vec_layout_t,
typename glob_vdof_data_t,
224 typename vdof_layout_t,
typename vdof_data_t>
225 inline MFEM_ALWAYS_INLINE
227 const glob_vdof_data_t &glob_vdof_data,
228 const vdof_layout_t &vdof_layout,
229 vdof_data_t &vdof_data)
const
231 VectorExtract<AssignOp::Set>(vl, glob_vdof_data, vdof_layout, vdof_data);
236 typename vdof_layout_t,
typename vdof_data_t,
237 typename vec_layout_t,
typename glob_vdof_data_t>
238 inline MFEM_ALWAYS_INLINE
240 const vdof_data_t &vdof_data,
241 const vec_layout_t &vl,
242 glob_vdof_data_t &glob_vdof_data)
const
244 const int NC = vdof_layout_t::dim_2;
245 const int NE = vdof_layout_t::dim_3;
246 MFEM_STATIC_ASSERT(FE::dofs == vdof_layout_t::dim_1,
247 "invalid number of dofs");
248 MFEM_ASSERT(NC == vl.NumComponents(),
"invalid number of components");
249 for (
int k = 0; k < NC; k++)
251 for (
int j = 0; j < NE; j++)
253 for (
int i = 0; i < FE::dofs; i++)
255 Assign<Op>(glob_vdof_data[vl.ind(
ind.map(i,j), k)],
256 vdof_data[vdof_layout.ind(i,k,j)]);
262 template <
typename vdof_layout_t,
typename vdof_data_t,
263 typename vec_layout_t,
typename glob_vdof_data_t>
264 inline MFEM_ALWAYS_INLINE
266 const vdof_data_t &vdof_data,
267 const vec_layout_t &vl,
268 glob_vdof_data_t &glob_vdof_data)
const
270 VectorAssemble<AssignOp::Add>(vdof_layout, vdof_data, vl, glob_vdof_data);
276 template <
typename vdof_layout_t,
typename vdof_data_t,
277 typename vec_layout_t,
typename glob_vdof_data_t>
278 inline MFEM_ALWAYS_INLINE
280 const vec_layout_t &vl,
281 const glob_vdof_data_t &glob_vdof_data,
282 const vdof_layout_t &vdof_layout,
283 vdof_data_t &vdof_data)
const
285 const int NC = vdof_layout_t::dim_2;
286 const int NE = vdof_layout_t::dim_3;
287 MFEM_STATIC_ASSERT(FE::dofs == vdof_layout_t::dim_1,
288 "invalid number of dofs");
289 MFEM_ASSERT(first_comp + NC <= vl.NumComponents(),
290 "invalid number of components");
291 for (
int k = 0; k < NC; k++)
293 for (
int j = 0; j < NE; j++)
295 for (
int i = 0; i < FE::dofs; i++)
297 Assign<AssignOp::Set>(
298 vdof_data[vdof_layout.ind(i,k,j)],
299 glob_vdof_data[vl.ind(
ind.map(i,j), first_comp+k)]);
308 template <
typename vdof_layout_t,
typename vdof_data_t,
309 typename vec_layout_t,
typename glob_vdof_data_t>
310 inline MFEM_ALWAYS_INLINE
312 const vdof_layout_t &vdof_layout,
313 const vdof_data_t &vdof_data,
314 const vec_layout_t &vl,
315 glob_vdof_data_t &glob_vdof_data)
const
317 const int NC = vdof_layout_t::dim_2;
318 const int NE = vdof_layout_t::dim_3;
319 MFEM_STATIC_ASSERT(FE::dofs == vdof_layout_t::dim_1,
320 "invalid number of dofs");
321 MFEM_ASSERT(first_comp + NC <= vl.NumComponents(),
322 "invalid number of components");
323 for (
int k = 0; k < NC; k++)
325 for (
int j = 0; j < NE; j++)
327 for (
int i = 0; i < FE::dofs; i++)
329 Assign<AssignOp::Add>(
330 glob_vdof_data[vl.ind(
ind.map(i,j), first_comp+k)],
331 vdof_data[vdof_layout.ind(i,k,j)]);
340 MFEM_FLOPS_ADD(FE::dofs*FE::dofs);
341 for (
int i = 0; i < FE::dofs; i++)
344 for (
int j = 0; j < FE::dofs; j++)
352 template <
typename vec_layout_t>
357 MFEM_FLOPS_ADD(FE::dofs*FE::dofs);
358 for (
int i = 0; i < FE::dofs; i++)
361 for (
int j = 0; j < FE::dofs; j++)
363 M.
_Add_(vl.ind(
ind.map(j,0), block_j), m(i,j));
372 template <
typename FE>
391 if (!h1_fec) {
return false; }
393 if (fe->
GetOrder() != FE_type::degree) {
return false; }
397 template <
typename vec_layout_t>
400 return Matches(fes) && vec_layout_t::Matches(fes);
407 template <
typename FE>
419 "the FE space is not compatible with this FE!");
425 inline MFEM_ALWAYS_INLINE
428 offset = FE::dofs * elem_idx;
431 inline MFEM_ALWAYS_INLINE
432 int map(
int loc_dof_idx,
int elem_offset)
const
434 return offset + loc_dof_idx + elem_offset * FE::dofs;
441 template <
typename FE>
460 if (!l2_fec) {
return false; }
462 if (fe->
GetOrder() != FE_type::degree) {
return false; }
466 template <
typename vec_layout_t>
469 return Matches(fes) && vec_layout_t::Matches(fes);
475 #endif // MFEM_TEMPLATE_FESPACE
Abstract class for Finite Elements.
H1_FiniteElementSpace(const FE &fe, const FiniteElementSpace &fes)
void _Add_(const int col, const double a)
int GetNDofs() const
Returns number of degrees of freedom.
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 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)
void Assemble(const TMatrix< FE::dofs, FE::dofs, double > &m, SparseMatrix &M) 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
int GetNE() const
Returns number of elements in the mesh.
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
void SetColPtr(const int row) const
TFiniteElementSpace_simple< FE, ElementDofIndexer< FE > > base_class
DGIndexer(const FE &fe, const FiniteElementSpace &fes)
TFiniteElementSpace_simple(const FE &fe, const FiniteElementSpace &fes)
virtual const FiniteElement * FiniteElementForGeometry(int GeomType) const
MFEM_ALWAYS_INLINE ~ElementDofIndexer()
virtual const FiniteElement * FiniteElementForGeometry(int GeomType) const
TFiniteElementSpace_simple< FE, DGIndexer< FE > > base_class
void AssembleBlock(int block_i, int block_j, const vec_layout_t &vl, const TMatrix< FE::dofs, FE::dofs, double > &m, SparseMatrix &M) const
const FiniteElementCollection * FEColl() const
MFEM_ALWAYS_INLINE ElementDofIndexer(const ElementDofIndexer &orig)
Arbitrary order H1-conforming (continuous) finite elements.
const Table & GetElementToDofTable() const
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.