32 interpolations(fes, f_ordering, type)
34 if (
nf==0) {
return; }
39 MFEM_VERIFY(is_h1,
"ParNCH1FaceRestriction is only implemented for H1 spaces.")
43 ComputeScatterIndicesAndOffsets(f_ordering,
type);
45 ComputeGatherIndices(f_ordering,
type);
61 const int num_nc_faces = nc_interp_config.Size();
62 if ( num_nc_faces == 0 ) {
return; }
63 auto interp_config_ptr = nc_interp_config.Read();
66 nface_dofs, nface_dofs, nc_size);
67 static constexpr int max_nd = 16*16;
68 MFEM_VERIFY(nface_dofs<=max_nd,
"Too many degrees of freedom.");
69 mfem::forall_2D(num_nc_faces, nface_dofs, 1, [=] MFEM_HOST_DEVICE (
int nc_face)
71 MFEM_SHARED
real_t dof_values[max_nd];
75 const int interp_index = conf.index;
76 const int face = conf.face_index;
77 for (int c = 0; c < vd; ++c)
79 MFEM_FOREACH_THREAD(dof,x,nface_dofs)
81 dof_values[dof] = d_y(dof, c, face);
84 MFEM_FOREACH_THREAD(dof_out,x,nface_dofs)
87 for (int dof_in = 0; dof_in<nface_dofs; dof_in++)
89 res += d_interp(dof_out, dof_in, interp_index)*dof_values[dof_in];
91 d_y(dof_out, c, face) = res;
99void ParNCH1FaceRestriction::AddMultTranspose(
const Vector &x,
Vector &y,
102 MFEM_VERIFY(
a == 1.0,
"General coefficient case is not yet supported!");
103 if (nf==0) {
return; }
104 NonconformingTransposeInterpolation(x);
105 H1FaceRestriction::AddMultTranspose(x_interp, y);
108void ParNCH1FaceRestriction::AddMultTransposeInPlace(
Vector &x,
Vector &y)
const
110 if (nf==0) {
return; }
111 NonconformingTransposeInterpolationInPlace(x);
112 H1FaceRestriction::AddMultTranspose(x, y);
115void ParNCH1FaceRestriction::NonconformingTransposeInterpolation(
118 if (x_interp.Size()==0)
120 x_interp.SetSize(x.
Size());
123 NonconformingTransposeInterpolationInPlace(x_interp);
126void ParNCH1FaceRestriction::NonconformingTransposeInterpolationInPlace(
130 const int nface_dofs = face_dofs;
132 if ( type==FaceType::Interior )
136 auto &nc_interp_config = interpolations.GetNCFaceInterpConfig();
137 const int num_nc_faces = nc_interp_config.Size();
138 if ( num_nc_faces == 0 ) {
return; }
139 auto interp_config_ptr = nc_interp_config.Read();
140 const int nc_size = interpolations.GetNumInterpolators();
141 auto d_interp =
Reshape(interpolations.GetInterpolators().Read(),
142 nface_dofs, nface_dofs, nc_size);
143 static constexpr int max_nd = 1024;
144 MFEM_VERIFY(nface_dofs<=max_nd,
"Too many degrees of freedom.");
146 [=] MFEM_HOST_DEVICE (
int nc_face)
148 MFEM_SHARED
real_t dof_values[max_nd];
153 const int interp_index = conf.index;
154 const int face = conf.face_index;
156 for (int c = 0; c < vd; ++c)
158 MFEM_FOREACH_THREAD(dof,x,nface_dofs)
160 dof_values[dof] = d_x(dof, c, face);
163 MFEM_FOREACH_THREAD(dof_out,x,nface_dofs)
166 for (int dof_in = 0; dof_in<nface_dofs; dof_in++)
168 res += d_interp(dof_in, dof_out, interp_index)*dof_values[dof_in];
170 d_x(dof_out, c, face) = res;
179void ParNCH1FaceRestriction::ComputeScatterIndicesAndOffsets(
180 const ElementDofOrdering f_ordering,
181 const FaceType face_type)
183 Mesh &mesh = *fes.GetMesh();
186 for (
int i = 0; i <= ndofs; ++i)
188 gather_offsets[i] = 0;
193 for (
int f = 0;
f < mesh.GetNumFacesWithGhost(); ++
f)
195 Mesh::FaceInformation face = mesh.GetFaceInformation(
f);
196 if ( face.IsNonconformingCoarse() )
202 else if (face_type==FaceType::Interior && face.IsInterior())
204 if ( face.IsConforming() )
206 interpolations.RegisterFaceConformingInterpolation(face,f_ind);
207 SetFaceDofsScatterIndices(face, f_ind, f_ordering);
212 SetFaceDofsScatterIndices(face, f_ind, f_ordering);
213 if ( face.element[0].conformity==Mesh::ElementConformity::Superset )
217 interpolations.RegisterFaceCoarseToFineInterpolation(face,f_ind);
223 interpolations.RegisterFaceConformingInterpolation(face,f_ind);
228 else if (face_type==FaceType::Boundary && face.IsBoundary())
230 interpolations.RegisterFaceConformingInterpolation(face,f_ind);
231 SetFaceDofsScatterIndices(face, f_ind, f_ordering);
235 MFEM_VERIFY(f_ind==nf,
"Unexpected number of faces.");
238 for (
int i = 1; i <= ndofs; ++i)
240 gather_offsets[i] += gather_offsets[i - 1];
244 interpolations.LinearizeInterpolatorMapIntoVector();
245 interpolations.InitializeNCInterpConfig();
248void ParNCH1FaceRestriction::ComputeGatherIndices(
249 const ElementDofOrdering f_ordering,
250 const FaceType face_type)
252 Mesh &mesh = *fes.GetMesh();
256 for (
int f = 0;
f < mesh.GetNumFacesWithGhost(); ++
f)
258 Mesh::FaceInformation face = mesh.GetFaceInformation(
f);
259 if ( face.IsNonconformingCoarse() )
265 else if (face.IsOfFaceType(face_type))
267 SetFaceDofsGatherIndices(face, f_ind, f_ordering);
271 MFEM_VERIFY(f_ind==nf,
"Unexpected number of faces.");
274 for (
int i = ndofs; i > 0; --i)
276 gather_offsets[i] = gather_offsets[i - 1];
278 gather_offsets[0] = 0;
289 if (!build) {
return; }
290 if (
nf==0) {
return; }
294 ComputeScatterIndicesAndOffsets();
296 ComputeGatherIndices();
311 "This method should be called when m == L2FaceValues::DoubleValued.");
317 if (
nf == 0) {
return; }
323 const int threshold =
ndofs;
328 const int ne_shared = nsdofs /
elem_dofs;
338 const int dof = i % nface_dofs;
339 const int face = i / nface_dofs;
340 const int idx1 = d_indices1[i];
341 for (
int c = 0; c < vd; ++c)
343 d_y(dof, c, 0, face) = d_x(t?c:idx1, t?idx1:c);
345 const int idx2 = d_indices2[i];
346 for (
int c = 0; c < vd; ++c)
348 if (idx2>-1 && idx2<threshold)
350 d_y(dof, c, 1, face) = d_x(t?c:idx2, t?idx2:c);
352 else if (idx2>=threshold)
354 const int e_shared = (idx2 - threshold) / nedof;
355 const int i_shared = (idx2 - threshold) % nedof;
356 d_y(dof, c, 1, face) = d_x_shared(i_shared,c,e_shared);
360 d_y(dof, c, 1, face) = 0.0;
378static MFEM_HOST_DEVICE
int AddNnz(
const int iE,
int *I,
const int dofs)
385 const bool keep_nbr_block)
const
392 const int Ndofs =
ndofs;
398 const int f = fdof/nface_dofs;
399 const int iF = fdof%nface_dofs;
400 const int iE1 = d_indices1[
f*nface_dofs+iF];
403 AddNnz(iE1,I,nface_dofs);
405 const int iE2 = d_indices2[
f*nface_dofs+iF];
408 AddNnz(iE2,I,nface_dofs);
417 const int Ndofs =
ndofs;
428 const int f = fdof/nface_dofs;
429 const int iF = fdof%nface_dofs;
430 const int iE1 = d_indices1[
f*nface_dofs+iF];
433 for (
int jF = 0; jF < nface_dofs; jF++)
435 const int jE2 = d_indices2[
f*nface_dofs+jF];
442 AddNnz(iE1,I_face,1);
446 const int iE2 = d_indices2[
f*nface_dofs+iF];
449 for (
int jF = 0; jF < nface_dofs; jF++)
451 const int jE1 = d_indices1[
f*nface_dofs+jF];
458 AddNnz(iE2,I_face,1);
467 const bool keep_nbr_block)
const
474 const int Ndofs =
ndofs;
477 auto mat_fea =
Reshape(ea_data.
Read(), nface_dofs, nface_dofs, 2,
nf);
483 const int f = fdof/nface_dofs;
484 const int iF = fdof%nface_dofs;
485 const int iE1 = d_indices1[
f*nface_dofs+iF];
488 const int offset = AddNnz(iE1,I,nface_dofs);
489 for (
int jF = 0; jF < nface_dofs; jF++)
491 const int jE2 = d_indices2[
f*nface_dofs+jF];
493 Data[offset+jF] = mat_fea(jF,iF,1,
f);
496 const int iE2 = d_indices2[
f*nface_dofs+iF];
499 const int offset = AddNnz(iE2,I,nface_dofs);
500 for (
int jF = 0; jF < nface_dofs; jF++)
502 const int jE1 = d_indices1[
f*nface_dofs+jF];
504 Data[offset+jF] = mat_fea(jF,iF,0,
f);
515 const int Ndofs =
ndofs;
518 auto mat_fea =
Reshape(ea_data.
Read(), nface_dofs, nface_dofs, 2,
nf);
522 auto J_face = face_mat.
WriteJ();
527 const int f = fdof/nface_dofs;
528 const int iF = fdof%nface_dofs;
529 const int iE1 = d_indices1[
f*nface_dofs+iF];
532 for (
int jF = 0; jF < nface_dofs; jF++)
534 const int jE2 = d_indices2[
f*nface_dofs+jF];
537 const int offset = AddNnz(iE1,I,1);
539 Data[offset] = mat_fea(jF,iF,1,
f);
543 const int offset = AddNnz(iE1,I_face,1);
544 J_face[offset] = jE2-Ndofs;
545 Data_face[offset] = mat_fea(jF,iF,1,
f);
549 const int iE2 = d_indices2[
f*nface_dofs+iF];
552 for (
int jF = 0; jF < nface_dofs; jF++)
554 const int jE1 = d_indices1[
f*nface_dofs+jF];
557 const int offset = AddNnz(iE2,I,1);
559 Data[offset] = mat_fea(jF,iF,0,
f);
563 const int offset = AddNnz(iE2,I_face,1);
564 J_face[offset] = jE1-Ndofs;
565 Data_face[offset] = mat_fea(jF,iF,0,
f);
572void ParL2FaceRestriction::ComputeScatterIndicesAndOffsets()
577 for (
int i = 0; i <=
ndofs; ++i)
613 MFEM_VERIFY(f_ind==
nf,
"Unexpected number of faces.");
616 for (
int i = 1; i <=
ndofs; ++i)
623void ParL2FaceRestriction::ComputeGatherIndices()
632 if (face.IsOfFaceType(
type))
644 MFEM_VERIFY(f_ind==
nf,
"Unexpected number of faces.");
647 for (
int i =
ndofs; i > 0; --i)
662 if (
nf==0) {
return; }
667 ComputeScatterIndicesAndOffsets();
669 ComputeGatherIndices();
675 if (
nf == 0) {
return; }
678 "This method should be called when m == L2FaceValues::SingleValued.");
683 const int threshold =
ndofs;
690 auto d_interp =
Reshape(interpolators, nface_dofs, nface_dofs, nc_size);
691 static constexpr int max_nd = 16*16;
692 MFEM_VERIFY(nface_dofs<=max_nd,
"Too many degrees of freedom.");
695 MFEM_SHARED
real_t dof_values[max_nd];
698 const int interp_index = conf.
index;
702 MFEM_FOREACH_THREAD(dof,x,nface_dofs)
704 const int i = face*nface_dofs + dof;
705 const int idx = d_indices1[i];
706 if (idx>-1 && idx<threshold)
708 for (int c = 0; c < vd; ++c)
710 d_y(dof, c, face) = d_x(t?c:idx, t?idx:c);
715 for (int c = 0; c < vd; ++c)
717 d_y(dof, c, face) = 0.0;
724 for (
int c = 0; c < vd; ++c)
726 MFEM_FOREACH_THREAD(dof,x,nface_dofs)
728 const int i = face*nface_dofs + dof;
729 const int idx = d_indices1[i];
730 if (idx>-1 && idx<threshold)
732 dof_values[dof] = d_x(t?c:idx, t?idx:c);
736 dof_values[dof] = 0.0;
740 MFEM_FOREACH_THREAD(dof_out,x,nface_dofs)
743 for (
int dof_in = 0; dof_in<nface_dofs; dof_in++)
745 res += d_interp(dof_out, dof_in, interp_index)*dof_values[dof_in];
747 d_y(dof_out, c, face) = res;
782 MFEM_ABORT(
"Unknown type and multiplicity combination.");
789 MFEM_VERIFY(
a == 1.0,
"General coefficient case is not yet supported!");
790 if (
nf==0) {
return; }
819 if (
nf==0) {
return; }
847 const bool keep_nbr_block)
const
854 const int Ndofs =
ndofs;
860 const int f = fdof/nface_dofs;
861 const int iF = fdof%nface_dofs;
862 const int iE1 = d_indices1[
f*nface_dofs+iF];
865 AddNnz(iE1,I,nface_dofs);
867 const int iE2 = d_indices2[
f*nface_dofs+iF];
870 AddNnz(iE2,I,nface_dofs);
878 MFEM_ABORT(
"Not yet implemented.");
883 const bool keep_nbr_block)
const
890 const int Ndofs =
ndofs;
894 auto mat_fea =
Reshape(fea_data.
Read(), nface_dofs, nface_dofs, 2,
nf);
900 auto d_interp =
Reshape(interpolators, nface_dofs, nface_dofs, nc_size);
903 const int f = fdof/nface_dofs;
906 const int interp_index = conf.
index;
907 const int iF = fdof%nface_dofs;
908 const int iE1 = d_indices1[
f*nface_dofs+iF];
911 const int offset1 = AddNnz(iE1,I,nface_dofs);
912 for (
int jF = 0; jF < nface_dofs; jF++)
914 const int jE2 = d_indices2[
f*nface_dofs+jF];
919 for (
int kF = 0; kF < nface_dofs; kF++)
921 val2 += d_interp(kF, iF, interp_index) * mat_fea(jF,kF,1,
f);
926 for (
int kF = 0; kF < nface_dofs; kF++)
928 val2 += mat_fea(kF,iF,1,
f) * d_interp(kF, jF, interp_index);
933 val2 = mat_fea(jF,iF,1,
f);
935 Data[offset1+jF] = val2;
938 const int iE2 = d_indices2[
f*nface_dofs+iF];
941 const int offset2 = AddNnz(iE2,I,nface_dofs);
942 for (
int jF = 0; jF < nface_dofs; jF++)
944 const int jE1 = d_indices1[
f*nface_dofs+jF];
949 for (
int kF = 0; kF < nface_dofs; kF++)
951 val1 += mat_fea(kF,iF,0,
f) * d_interp(kF, jF, interp_index);
956 for (
int kF = 0; kF < nface_dofs; kF++)
958 val1 += d_interp(kF, iF, interp_index) * mat_fea(jF,kF,0,
f);
963 val1 = mat_fea(jF,iF,0,
f);
965 Data[offset2+jF] = val1;
975 MFEM_ABORT(
"Not yet implemented.");
978void ParNCL2FaceRestriction::ComputeScatterIndicesAndOffsets()
983 for (
int i = 0; i <=
ndofs; ++i)
993 if ( face.IsNonconformingCoarse() )
1001 if ( face.IsConforming() )
1006 if ( face.IsShared() )
1021 if ( face.IsShared() )
1043 MFEM_VERIFY(f_ind==
nf,
"Unexpected number of " <<
1045 " faces: " << f_ind <<
" vs " <<
nf );
1048 for (
int i = 1; i <=
ndofs; ++i)
1054void ParNCL2FaceRestriction::ComputeGatherIndices()
1060 for (
int f = 0;
f < mesh.GetNumFacesWithGhost(); ++
f)
1063 if ( face.IsNonconformingCoarse() )
1069 else if ( face.IsOfFaceType(
type) )
1081 MFEM_VERIFY(f_ind==
nf,
"Unexpected number of " <<
1083 " faces: " << f_ind <<
" vs " <<
nf );
1086 for (
int i =
ndofs; i > 0; --i)
MFEM_HOST_DEVICE T AtomicAdd(T &add, const T val)
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
int GetNF() const
Returns number of faces (i.e. co-dimension 1 entities) in the mesh.
const FiniteElementCollection * FEColl() const
Mesh * GetMesh() const
Returns the mesh.
Arbitrary order H1-conforming (continuous) finite elements.
const Array< NCInterpConfig > & GetNCFaceInterpConfig() const
Return an array containing the interpolation configuration for each face registered with RegisterFace...
int GetNumInterpolators() const
Return the total number of interpolators.
const Vector & GetInterpolators() const
Return an mfem::Vector containing the interpolators in the following format: face_dofs x face_dofs x ...
const Array< InterpConfig > & GetFaceInterpConfig() const
Return an array containing the interpolation configuration for each face registered with RegisterFace...
Operator that extracts Face degrees of freedom for L2 spaces.
void PermuteAndSetFaceDofsGatherIndices2(const Mesh::FaceInformation &face, const int face_index)
Permute and set the gathering indices of elem2 for the interior face described by the face....
virtual void FillI(SparseMatrix &mat, const bool keep_nbr_block=false) const
Fill the I array of SparseMatrix corresponding to the sparsity pattern given by this L2FaceRestrictio...
Array< int > scatter_indices2
void SingleValuedConformingMult(const Vector &x, Vector &y) const
Scatter the degrees of freedom, i.e. goes from L-Vector to face E-Vector. Should only be used with co...
void SingleValuedConformingAddMultTranspose(const Vector &x, Vector &y) const
Gather the degrees of freedom, i.e. goes from face E-Vector to L-Vector. Should only be used with con...
void PermuteAndSetSharedFaceDofsScatterIndices2(const Mesh::FaceInformation &face, const int face_index)
Permute and set the scattering indices of elem2 for the shared face described by the face....
void CheckFESpace()
Verify that L2FaceRestriction is built from an L2 FESpace.
Array< int > gather_offsets
void PermuteAndSetFaceDofsScatterIndices2(const Mesh::FaceInformation &face, const int face_index)
Permute and set the scattering indices of elem2, and increment the offsets for the face described by ...
Array< int > scatter_indices1
const FiniteElementSpace & fes
void SetBoundaryDofsScatterIndices2(const Mesh::FaceInformation &face, const int face_index)
Set the scattering indices of elem2 for the boundary face described by the face.
void SetFaceDofsScatterIndices1(const Mesh::FaceInformation &face, const int face_index)
Set the scattering indices of elem1, and increment the offsets for the face described by the face....
void SetFaceDofsGatherIndices1(const Mesh::FaceInformation &face, const int face_index)
Set the gathering indices of elem1 for the interior face described by the face.
void DoubleValuedConformingAddMultTranspose(const Vector &x, Vector &y) const
Gather the degrees of freedom, i.e. goes from face E-Vector to L-Vector. Should only be used with con...
virtual void FillJAndData(const Vector &fea_data, SparseMatrix &mat, const bool keep_nbr_block=false) const
Fill the J and Data arrays of the SparseMatrix corresponding to the sparsity pattern given by this L2...
FaceInformation GetFaceInformation(int f) const
int GetNumFacesWithGhost() const
Return the number of faces (3D), edges (2D) or vertices (1D) including ghost faces.
Operator that extracts face degrees of freedom for L2 nonconforming spaces.
void FillI(SparseMatrix &mat, const bool keep_nbr_block=false) const override
Fill the I array of SparseMatrix corresponding to the sparsity pattern given by this NCL2FaceRestrict...
void FillJAndData(const Vector &fea_data, SparseMatrix &mat, const bool keep_nbr_block=false) const override
Fill the J and Data arrays of the SparseMatrix corresponding to the sparsity pattern given by this NC...
void SingleValuedNonconformingTransposeInterpolation(const Vector &x) const
Apply a change of basis from fine element basis to coarse element basis for the coarse face dofs....
void SingleValuedNonconformingTransposeInterpolationInPlace(Vector &x) const
Apply a change of basis from fine element basis to coarse element basis for the coarse face dofs....
const InterpolationManager & interpolations
void DoubleValuedNonconformingTransposeInterpolation(const Vector &x) const
Apply a change of basis from fine element basis to coarse element basis for the coarse face dofs....
void DoubleValuedNonconformingInterpolation(Vector &x) const
Apply a change of basis from coarse element basis to fine element basis for the coarse face dofs.
void DoubleValuedNonconformingTransposeInterpolationInPlace(Vector &x) const
Apply a change of basis from fine element basis to coarse element basis for the coarse face dofs....
Abstract parallel finite element space.
int GetFaceNbrVSize() const
Operator that extracts Face degrees of freedom in parallel.
const ParFiniteElementSpace & pfes
void DoubleValuedConformingMult(const Vector &x, Vector &y) const override
Scatter the degrees of freedom, i.e. goes from L-Vector to face E-Vector. Should only be used with co...
void Mult(const Vector &x, Vector &y) const override
Scatter the degrees of freedom, i.e. goes from L-Vector to face E-Vector.
void FillJAndData(const Vector &ea_data, SparseMatrix &mat, SparseMatrix &face_mat) const
void FillI(SparseMatrix &mat, const bool keep_nbr_block=false) const override
ParL2FaceRestriction(const ParFiniteElementSpace &pfes_, ElementDofOrdering f_ordering, FaceType type, L2FaceValues m, bool build)
Constructs an ParL2FaceRestriction.
ParNCH1FaceRestriction(const ParFiniteElementSpace &fes, ElementDofOrdering f_ordering, FaceType type)
Constructs an ParNCH1FaceRestriction.
void Mult(const Vector &x, Vector &y) const override
Scatter the degrees of freedom, i.e. goes from L-Vector to face E-Vector.
void NonconformingInterpolation(Vector &x) const
Apply a change of basis from coarse element basis to fine element basis for the coarse face dofs.
InterpolationManager interpolations
void AddMultTranspose(const Vector &x, Vector &y, const real_t a=1.0) const override
Gather the degrees of freedom, i.e. goes from face E-Vector to L-Vector.
void Mult(const Vector &x, Vector &y) const override
Scatter the degrees of freedom, i.e. goes from L-Vector to face E-Vector.
ParNCL2FaceRestriction(const ParFiniteElementSpace &fes, ElementDofOrdering f_ordering, FaceType type, L2FaceValues m=L2FaceValues::DoubleValued)
Constructs an ParNCL2FaceRestriction.
void SingleValuedNonconformingMult(const Vector &x, Vector &y) const
Scatter the degrees of freedom, i.e. goes from L-Vector to face E-Vector. Should only be used with no...
void DoubleValuedNonconformingMult(const Vector &x, Vector &y) const override
Scatter the degrees of freedom, i.e. goes from L-Vector to face E-Vector. Should only be used with no...
void FillI(SparseMatrix &mat, const bool keep_nbr_block=false) const override
Fill the I array of SparseMatrix corresponding to the sparsity pattern given by this ParNCL2FaceRestr...
void AddMultTransposeInPlace(Vector &x, Vector &y) const override
Gather the degrees of freedom, i.e. goes from face E-Vector to L-Vector.
void FillJAndData(const Vector &fea_data, SparseMatrix &mat, SparseMatrix &face_mat) const
int * ReadWriteI(bool on_dev=true)
int * WriteJ(bool on_dev=true)
real_t * WriteData(bool on_dev=true)
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
virtual real_t * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
int Size() const
Returns the size of the vector.
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
real_t f(const Vector &p)
Vector GetLVectorFaceNbrData(const FiniteElementSpace &fes, const Vector &x, FaceType ftype)
Return the face-neighbor data given the L-vector x.
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
void forall_2D(int N, int X, int Y, lambda &&body)
ElementDofOrdering
Constants describing the possible orderings of the DOFs in one element.
std::function< real_t(const Vector &)> f(real_t mass_coeff)
void forall(int N, lambda &&body)
uint32_t is_non_conforming
uint32_t is_non_conforming