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)
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
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
virtual const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) 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
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
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.