MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
tfespace.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#ifndef MFEM_TEMPLATE_FESPACE
13#define MFEM_TEMPLATE_FESPACE
14
15#include "../config/tconfig.hpp"
17#include "../linalg/ttensor.hpp"
18#include "tfe.hpp" // for TFiniteElementSpace_simple
19#include "fespace.hpp"
20
21namespace mfem
22{
23
24// Templated finite element space classes, cf. fespace.?pp and fe_coll.?pp
25
26// Index types
27
28// IndexType must define:
29// - constructor IndexType(const FE &fe, const FiniteElementSpace &fes)
30// - copy constructor
31// - void SetElement(int elem_idx)
32// - int map(int loc_dof_idx, int elem_offset) const --> glob_dof_idx, for
33// single component; elem_offset is relative to the currently set element.
34
35// Index type based on an array listing the dofs for each element where all
36// elements are assumed to have the same number of dofs. Such an array is
37// constructed from the J array of an element-to-dof Table with optional local
38// renumbering to ensure tensor-product local dof ordering when needed.
39template <typename FE>
41{
42protected:
45
46public:
47 typedef FE FE_type;
48
49 ElementDofIndexer(const FE &fe, const FiniteElementSpace &fes)
50 {
51 const Array<int> *loc_dof_map = fe.GetDofMap();
52 // fes.BuildElementToDofTable();
53 const Table &el_dof = fes.GetElementToDofTable();
54 MFEM_ASSERT(el_dof.Size_of_connections() == el_dof.Size() * FE::dofs,
55 "the element-to-dof Table is not compatible with this FE!");
56 int num_dofs = el_dof.Size() * FE::dofs;
57 if (!loc_dof_map)
58 {
59 // no local dof reordering
60 el_dof_list = el_dof.GetJ();
61 own_list = false;
62 }
63 else
64 {
65 // reorder the local dofs according to loc_dof_map
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++)
69 {
70 MFEM_ASSERT(el_dof.RowSize(i) == FE::dofs,
71 "incompatible element-to-dof Table!");
72 for (int j = 0; j < FE::dofs; j++)
73 {
74 el_dof_list_[j+FE::dofs*i] =
75 el_dof.GetJ()[loc_dof_map_[j]+FE::dofs*i];
76 }
77 }
78 el_dof_list = el_dof_list_;
79 own_list = true;
80 }
81 loc_dof_list = el_dof_list; // point to element 0
82 }
83
84 // Shallow copy constructor
85 inline MFEM_ALWAYS_INLINE
91
92 inline MFEM_ALWAYS_INLINE
93 ~ElementDofIndexer() { if (own_list) { delete [] el_dof_list; } }
94
95 inline MFEM_ALWAYS_INLINE
96 void SetElement(int elem_idx)
97 {
98 loc_dof_list = el_dof_list + elem_idx * FE::dofs;
99 }
100
101 inline MFEM_ALWAYS_INLINE
102 int map(int loc_dof_idx, int elem_offset) const
103 {
104 return loc_dof_list[loc_dof_idx + elem_offset * FE::dofs];
105 }
106};
107
108
109// Simple template Finite Element Space, built using an IndexType. For a
110// description of the requirements on IndexType, see above.
111template <typename FE, typename IndexType>
113{
114public:
115 typedef FE FE_type;
116 typedef IndexType index_type;
117 static const int dofs = FE::dofs;
118
119protected:
122
123public:
125 : ind(fe, fes), num_elems(fes.GetNE()), remain_elems(num_elems) { }
126
127 // default copy constructor
128
129 int GetNE() const { return num_elems; }
130
131 void SetElement(int el) { ind.SetElement(el); remain_elems = num_elems-el; }
132
133#if 0
134 // Multi-element Extract:
135 // Extract dofs for multiple elements starting with the current element.
136 // The number of elements to extract is given by the second dimension of
137 // dof_layout_t: dof_layout is (DOFS x NumElems).
138 template <AssignOp::Type Op, typename glob_dof_data_t,
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
144 {
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++)
150 {
151 for (int i = 0; i < FE::dofs; i++)
152 {
153 for (int s = 0; s < SS; s++)
154 {
155 Assign<Op>(dof_data[dof_layout.ind(i,j)][s],
156 glob_dof_data[ind.map(i,s+SS*j)]);
157 }
158 }
159 }
160 }
161
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
168 {
169 Extract<AssignOp::Set>(glob_dof_data, dof_layout, dof_data);
170 }
171
172 // Multi-element assemble.
173 template <AssignOp::Type Op,
174 typename dof_layout_t, typename dof_data_t,
175 typename glob_dof_data_t>
176 inline MFEM_ALWAYS_INLINE
177 void Assemble(const dof_layout_t &dof_layout,
178 const dof_data_t &dof_data,
179 glob_dof_data_t &glob_dof_data) const
180 {
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++)
186 {
187 for (int i = 0; i < FE::dofs; i++)
188 {
189 for (int s = 0; s < SS; s++)
190 {
191 Assign<Op>(glob_dof_data[ind.map(i,s+SS*j)],
192 dof_data[dof_layout.ind(i,j)][s]);
193 }
194 }
195 }
196 }
197
198 template <typename dof_layout_t, typename dof_data_t,
199 typename glob_dof_data_t>
200 inline MFEM_ALWAYS_INLINE
201 void Assemble(const dof_layout_t &dof_layout,
202 const dof_data_t &dof_data,
203 glob_dof_data_t &glob_dof_data) const
204 {
205 Assemble<AssignOp::Add>(dof_layout, dof_data, glob_dof_data);
206 }
207#endif
208
209 // Multi-element VectorExtract: vdof_layout is (DOFS x NumComp x NumElems).
210 template <AssignOp::Type Op,
211 typename vec_layout_t, typename glob_vdof_data_t,
212 typename vdof_layout_t, typename vdof_data_t>
213 inline MFEM_ALWAYS_INLINE
214 void VectorExtract(const vec_layout_t &vl,
215 const glob_vdof_data_t &glob_vdof_data,
216 const vdof_layout_t &vdof_layout,
217 vdof_data_t &vdof_data) const
218 {
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");
225 const int TE = std::min(SS*NE, remain_elems);
226 // const int TE = SS*NE;
227 for (int k = 0; k < NC; k++)
228 {
229#if 0
230 for (int j = 0; j < NE; j++)
231 {
232 for (int i = 0; i < FE::dofs; i++)
233 {
234 for (int s = 0; s < SS; s++)
235 {
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)]);
238 }
239 }
240 }
241#else
242 for (int js = 0; js < TE; js++)
243 {
244 for (int i = 0; i < FE::dofs; i++)
245 {
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)]);
249 }
250 }
251#endif
252 }
253 }
254
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
258 void VectorExtract(const vec_layout_t &vl,
259 const glob_vdof_data_t &glob_vdof_data,
260 const vdof_layout_t &vdof_layout,
261 vdof_data_t &vdof_data) const
262 {
263 VectorExtract<AssignOp::Set>(vl, glob_vdof_data, vdof_layout, vdof_data);
264 }
265
266 // Multi-element VectorAssemble: vdof_layout is (DOFS x NumComp x NumElems).
267 template <AssignOp::Type Op,
268 typename vdof_layout_t, typename vdof_data_t,
269 typename vec_layout_t, typename glob_vdof_data_t>
270 inline MFEM_ALWAYS_INLINE
271 void VectorAssemble(const vdof_layout_t &vdof_layout,
272 const vdof_data_t &vdof_data,
273 const vec_layout_t &vl,
274 glob_vdof_data_t &glob_vdof_data) const
275 {
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");
282 const int TE = std::min(SS*NE, remain_elems);
283 // const int TE = SS*NE;
284 for (int k = 0; k < NC; k++)
285 {
286#if 0
287 for (int j = 0; j < NE; j++)
288 {
289 for (int i = 0; i < FE::dofs; i++)
290 {
291 for (int s = 0; s < SS; s++)
292 {
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]);
295 }
296 }
297 }
298#else
299 for (int js = 0; js < TE; js++)
300 {
301 for (int i = 0; i < FE::dofs; i++)
302 {
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]);
306 }
307 }
308#endif
309 }
310 }
311
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
315 void VectorAssemble(const vdof_layout_t &vdof_layout,
316 const vdof_data_t &vdof_data,
317 const vec_layout_t &vl,
318 glob_vdof_data_t &glob_vdof_data) const
319 {
320 VectorAssemble<AssignOp::Add>(vdof_layout, vdof_data, vl, glob_vdof_data);
321 }
322
323 // Extract a static number of consecutive components; vdof_layout is
324 // (dofs x NC x NE), where NC is the number of components to extract. It is
325 // assumed that: first_comp + NC <= vl.NumComponents().
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
329 void ExtractComponents(int first_comp,
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
334 {
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;
338 const int TE = std::min(SS*NE, remain_elems);
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++)
344 {
345 for (int js = 0; js < TE; js++)
346 {
347 for (int i = 0; i < FE::dofs; i++)
348 {
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)]);
353 }
354 }
355 }
356 }
357
358 // Assemble a static number of consecutive components; vdof_layout is
359 // (dofs x NC x NE), where NC is the number of components to add. It is
360 // assumed that: first_comp + NC <= vl.NumComponents().
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
364 void AssembleComponents(int first_comp,
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
369 {
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;
373 const int TE = std::min(SS*NE, remain_elems);
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++)
379 {
380 for (int js = 0; js < TE; js++)
381 {
382 for (int i = 0; i < FE::dofs; i++)
383 {
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]);
388 }
389 }
390 }
391 }
392
393 template <typename vcomplex_t>
395 SparseMatrix &M) const
396 {
397 const int SS = sizeof(m[0])/sizeof(m[0][0]);
398 const int TE = std::min(SS, remain_elems);
399 MFEM_FLOPS_ADD(FE::dofs*FE::dofs);
400 for (int s = 0; s < TE; s++)
401 {
402 for (int i = 0; i < FE::dofs; i++)
403 {
404 M.SetColPtr(ind.map(i,s));
405 for (int j = 0; j < FE::dofs; j++)
406 {
407 M._Add_(ind.map(j,s), m(i,j)[s]);
408 }
409 M.ClearColPtr();
410 }
411 }
412 }
413
414 template <typename vec_layout_t, typename vcomplex_t>
415 void AssembleBlock(int block_i, int block_j, const vec_layout_t &vl,
417 SparseMatrix &M) const
418 {
419 const int SS = sizeof(m[0])/sizeof(m[0][0]);
420 const int TE = std::min(SS, remain_elems);
421 MFEM_FLOPS_ADD(FE::dofs*FE::dofs);
422 for (int s = 0; s < TE; s++)
423 {
424 for (int i = 0; i < FE::dofs; i++)
425 {
426 M.SetColPtr(vl.ind(ind.map(i,s), block_i));
427 for (int j = 0; j < FE::dofs; j++)
428 {
429 M._Add_(vl.ind(ind.map(j,s), block_j), m(i,j)[s]);
430 }
431 M.ClearColPtr();
432 }
433 }
434 }
435};
436
437// H1 Finite Element Space
438
439template <typename FE>
441 : public TFiniteElementSpace_simple<FE,ElementDofIndexer<FE> >
442{
443public:
444 typedef FE FE_type;
446
448 : base_class(fe, fes)
449 { }
450
451 // default copy constructor
452
453 static bool Matches(const FiniteElementSpace &fes)
454 {
455 const FiniteElementCollection *fec = fes.FEColl();
456 const H1_FECollection *h1_fec =
457 dynamic_cast<const H1_FECollection *>(fec);
458 if (!h1_fec) { return false; }
459 const FiniteElement *fe = h1_fec->FiniteElementForGeometry(FE_type::geom);
460 if (fe->GetOrder() != FE_type::degree) { return false; }
461 return true;
462 }
463
464 template <typename vec_layout_t>
465 static bool VectorMatches(const FiniteElementSpace &fes)
466 {
467 return Matches(fes) && vec_layout_t::Matches(fes);
468 }
469};
470
471
472// Simple index type for DG spaces, where the map method is given by:
473// glob_dof_idx = loc_dof_idx + elem_idx * num_dofs.
474template <typename FE>
476{
477protected:
479
480public:
481 typedef FE FE_type;
482
483 DGIndexer(const FE &fe, const FiniteElementSpace &fes)
484 {
485 MFEM_ASSERT(fes.GetNDofs() == fes.GetNE() * FE::dofs,
486 "the FE space is not compatible with this FE!");
487 offset = 0;
488 }
489
490 // default copy constructor
491
492 inline MFEM_ALWAYS_INLINE
493 void SetElement(int elem_idx)
494 {
495 offset = FE::dofs * elem_idx;
496 }
497
498 inline MFEM_ALWAYS_INLINE
499 int map(int loc_dof_idx, int elem_offset) const
500 {
501 return offset + loc_dof_idx + elem_offset * FE::dofs;
502 }
503};
504
505
506// L2 Finite Element Space
507
508template <typename FE>
510 : public TFiniteElementSpace_simple<FE,DGIndexer<FE> >
511{
512public:
513 typedef FE FE_type;
515
517 : base_class(fe, fes)
518 { }
519
520 // default copy constructor
521
522 static bool Matches(const FiniteElementSpace &fes)
523 {
524 const FiniteElementCollection *fec = fes.FEColl();
525 const L2_FECollection *l2_fec =
526 dynamic_cast<const L2_FECollection *>(fec);
527 if (!l2_fec) { return false; }
528 const FiniteElement *fe = l2_fec->FiniteElementForGeometry(FE_type::geom);
529 if (fe->GetOrder() != FE_type::degree) { return false; }
530 return true;
531 }
532
533 template <typename vec_layout_t>
534 static bool VectorMatches(const FiniteElementSpace &fes)
535 {
536 return Matches(fes) && vec_layout_t::Matches(fes);
537 }
538};
539
540} // namespace mfem
541
542#endif // MFEM_TEMPLATE_FESPACE
T * GetData()
Returns the data.
Definition array.hpp:118
MFEM_ALWAYS_INLINE int map(int loc_dof_idx, int elem_offset) const
Definition tfespace.hpp:499
MFEM_ALWAYS_INLINE void SetElement(int elem_idx)
Definition tfespace.hpp:493
DGIndexer(const FE &fe, const FiniteElementSpace &fes)
Definition tfespace.hpp:483
const int * el_dof_list
Definition tfespace.hpp:43
MFEM_ALWAYS_INLINE void SetElement(int elem_idx)
Definition tfespace.hpp:96
MFEM_ALWAYS_INLINE ElementDofIndexer(const ElementDofIndexer &orig)
Definition tfespace.hpp:86
MFEM_ALWAYS_INLINE ~ElementDofIndexer()
Definition tfespace.hpp:93
MFEM_ALWAYS_INLINE int map(int loc_dof_idx, int elem_offset) const
Definition tfespace.hpp:102
const int * loc_dof_list
Definition tfespace.hpp:43
ElementDofIndexer(const FE &fe, const FiniteElementSpace &fes)
Definition tfespace.hpp:49
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Definition fe_coll.hpp:27
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:220
const Table & GetElementToDofTable() const
Return a reference to the internal Table that stores the lists of scalar dofs, for each mesh element,...
Definition fespace.hpp:1136
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
Definition fespace.hpp:710
int GetNE() const
Returns number of elements in the mesh.
Definition fespace.hpp:740
const FiniteElementCollection * FEColl() const
Definition fespace.hpp:727
Abstract class for all finite elements.
Definition fe_base.hpp:239
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Definition fe_base.hpp:333
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:260
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:1961
TFiniteElementSpace_simple< FE, ElementDofIndexer< FE > > base_class
Definition tfespace.hpp:445
static bool Matches(const FiniteElementSpace &fes)
Definition tfespace.hpp:453
H1_FiniteElementSpace(const FE &fe, const FiniteElementSpace &fes)
Definition tfespace.hpp:447
static bool VectorMatches(const FiniteElementSpace &fes)
Definition tfespace.hpp:465
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:330
const FiniteElement * FiniteElementForGeometry(Geometry::Type GeomType) const override
Definition fe_coll.cpp:2342
TFiniteElementSpace_simple< FE, DGIndexer< FE > > base_class
Definition tfespace.hpp:514
static bool Matches(const FiniteElementSpace &fes)
Definition tfespace.hpp:522
static bool VectorMatches(const FiniteElementSpace &fes)
Definition tfespace.hpp:534
L2_FiniteElementSpace(const FE &fe, const FiniteElementSpace &fes)
Definition tfespace.hpp:516
Data type sparse matrix.
Definition sparsemat.hpp:51
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
Definition tfespace.hpp:141
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
Definition tfespace.hpp:214
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
Definition tfespace.hpp:165
void Assemble(const TMatrix< FE::dofs, FE::dofs, vcomplex_t > &m, SparseMatrix &M) const
Definition tfespace.hpp:394
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
Definition tfespace.hpp:271
TFiniteElementSpace_simple(const FE &fe, const FiniteElementSpace &fes)
Definition tfespace.hpp:124
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
Definition tfespace.hpp:201
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
Definition tfespace.hpp:364
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
Definition tfespace.hpp:258
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
Definition tfespace.hpp:315
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
Definition tfespace.hpp:329
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
Definition tfespace.hpp:177
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
Definition tfespace.hpp:415
int * GetJ()
Definition table.hpp:114
int RowSize(int i) const
Definition table.hpp:108
int Size() const
Returns the number of TYPE I elements.
Definition table.hpp:92
int Size_of_connections() const
Definition table.hpp:98
lvalue_t & Assign(lvalue_t &a, const rvalue_t &b)
Definition tassign.hpp:137
RefCoord s[3]