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;
329 t?vd:nsdofs,
t?nsdofs:vd);
333 const int dof = i % nface_dofs;
334 const int face = i / nface_dofs;
335 const int idx1 = d_indices1[i];
336 for (
int c = 0; c < vd; ++c)
338 d_y(dof, c, 0, face) = d_x(
t?c:idx1,
t?idx1:c);
340 const int idx2 = d_indices2[i];
341 for (
int c = 0; c < vd; ++c)
343 if (idx2>-1 && idx2<threshold)
345 d_y(dof, c, 1, face) = d_x(
t?c:idx2,
t?idx2:c);
347 else if (idx2>=threshold)
349 d_y(dof, c, 1, face) = d_x_shared(
t?c:(idx2-threshold),
350 t?(idx2-threshold):c);
354 d_y(dof, c, 1, face) = 0.0;
372static MFEM_HOST_DEVICE
int AddNnz(
const int iE,
int *I,
const int dofs)
379 const bool keep_nbr_block)
const
386 const int Ndofs =
ndofs;
392 const int f = fdof/nface_dofs;
393 const int iF = fdof%nface_dofs;
394 const int iE1 = d_indices1[
f*nface_dofs+iF];
397 AddNnz(iE1,I,nface_dofs);
399 const int iE2 = d_indices2[
f*nface_dofs+iF];
402 AddNnz(iE2,I,nface_dofs);
411 const int Ndofs =
ndofs;
422 const int f = fdof/nface_dofs;
423 const int iF = fdof%nface_dofs;
424 const int iE1 = d_indices1[
f*nface_dofs+iF];
427 for (
int jF = 0; jF < nface_dofs; jF++)
429 const int jE2 = d_indices2[
f*nface_dofs+jF];
436 AddNnz(iE1,I_face,1);
440 const int iE2 = d_indices2[
f*nface_dofs+iF];
443 for (
int jF = 0; jF < nface_dofs; jF++)
445 const int jE1 = d_indices1[
f*nface_dofs+jF];
452 AddNnz(iE2,I_face,1);
461 const bool keep_nbr_block)
const
468 const int Ndofs =
ndofs;
471 auto mat_fea =
Reshape(ea_data.
Read(), nface_dofs, nface_dofs, 2,
nf);
477 const int f = fdof/nface_dofs;
478 const int iF = fdof%nface_dofs;
479 const int iE1 = d_indices1[
f*nface_dofs+iF];
482 const int offset = AddNnz(iE1,I,nface_dofs);
483 for (
int jF = 0; jF < nface_dofs; jF++)
485 const int jE2 = d_indices2[
f*nface_dofs+jF];
487 Data[offset+jF] = mat_fea(jF,iF,1,
f);
490 const int iE2 = d_indices2[
f*nface_dofs+iF];
493 const int offset = AddNnz(iE2,I,nface_dofs);
494 for (
int jF = 0; jF < nface_dofs; jF++)
496 const int jE1 = d_indices1[
f*nface_dofs+jF];
498 Data[offset+jF] = mat_fea(jF,iF,0,
f);
509 const int Ndofs =
ndofs;
512 auto mat_fea =
Reshape(ea_data.
Read(), nface_dofs, nface_dofs, 2,
nf);
516 auto J_face = face_mat.
WriteJ();
521 const int f = fdof/nface_dofs;
522 const int iF = fdof%nface_dofs;
523 const int iE1 = d_indices1[
f*nface_dofs+iF];
526 for (
int jF = 0; jF < nface_dofs; jF++)
528 const int jE2 = d_indices2[
f*nface_dofs+jF];
531 const int offset = AddNnz(iE1,I,1);
533 Data[offset] = mat_fea(jF,iF,1,
f);
537 const int offset = AddNnz(iE1,I_face,1);
538 J_face[offset] = jE2-Ndofs;
539 Data_face[offset] = mat_fea(jF,iF,1,
f);
543 const int iE2 = d_indices2[
f*nface_dofs+iF];
546 for (
int jF = 0; jF < nface_dofs; jF++)
548 const int jE1 = d_indices1[
f*nface_dofs+jF];
551 const int offset = AddNnz(iE2,I,1);
553 Data[offset] = mat_fea(jF,iF,0,
f);
557 const int offset = AddNnz(iE2,I_face,1);
558 J_face[offset] = jE1-Ndofs;
559 Data_face[offset] = mat_fea(jF,iF,0,
f);
566void ParL2FaceRestriction::ComputeScatterIndicesAndOffsets()
571 for (
int i = 0; i <=
ndofs; ++i)
607 MFEM_VERIFY(f_ind==
nf,
"Unexpected number of faces.");
610 for (
int i = 1; i <=
ndofs; ++i)
617void ParL2FaceRestriction::ComputeGatherIndices()
626 if (face.IsOfFaceType(
type))
638 MFEM_VERIFY(f_ind==
nf,
"Unexpected number of faces.");
641 for (
int i =
ndofs; i > 0; --i)
656 if (
nf==0) {
return; }
661 ComputeScatterIndicesAndOffsets();
663 ComputeGatherIndices();
669 if (
nf == 0) {
return; }
672 "This method should be called when m == L2FaceValues::SingleValued.");
677 const int threshold =
ndofs;
684 auto d_interp =
Reshape(interpolators, nface_dofs, nface_dofs, nc_size);
685 static constexpr int max_nd = 16*16;
686 MFEM_VERIFY(nface_dofs<=max_nd,
"Too many degrees of freedom.");
689 MFEM_SHARED
real_t dof_values[max_nd];
692 const int interp_index = conf.
index;
696 MFEM_FOREACH_THREAD(dof,x,nface_dofs)
698 const int i = face*nface_dofs + dof;
699 const int idx = d_indices1[i];
700 if (idx>-1 && idx<threshold)
702 for (int c = 0; c < vd; ++c)
704 d_y(dof, c, face) = d_x(t?c:idx, t?idx:c);
709 for (int c = 0; c < vd; ++c)
711 d_y(dof, c, face) = 0.0;
718 for (
int c = 0; c < vd; ++c)
720 MFEM_FOREACH_THREAD(dof,x,nface_dofs)
722 const int i = face*nface_dofs + dof;
723 const int idx = d_indices1[i];
724 if (idx>-1 && idx<threshold)
726 dof_values[dof] = d_x(
t?c:idx,
t?idx:c);
730 dof_values[dof] = 0.0;
734 MFEM_FOREACH_THREAD(dof_out,x,nface_dofs)
737 for (
int dof_in = 0; dof_in<nface_dofs; dof_in++)
739 res += d_interp(dof_out, dof_in, interp_index)*dof_values[dof_in];
741 d_y(dof_out, c, face) = res;
776 MFEM_ABORT(
"Unknown type and multiplicity combination.");
783 MFEM_VERIFY(
a == 1.0,
"General coefficient case is not yet supported!");
784 if (
nf==0) {
return; }
813 if (
nf==0) {
return; }
841 const bool keep_nbr_block)
const
848 const int Ndofs =
ndofs;
854 const int f = fdof/nface_dofs;
855 const int iF = fdof%nface_dofs;
856 const int iE1 = d_indices1[
f*nface_dofs+iF];
859 AddNnz(iE1,I,nface_dofs);
861 const int iE2 = d_indices2[
f*nface_dofs+iF];
864 AddNnz(iE2,I,nface_dofs);
872 MFEM_ABORT(
"Not yet implemented.");
877 const bool keep_nbr_block)
const
884 const int Ndofs =
ndofs;
888 auto mat_fea =
Reshape(fea_data.
Read(), nface_dofs, nface_dofs, 2,
nf);
894 auto d_interp =
Reshape(interpolators, nface_dofs, nface_dofs, nc_size);
897 const int f = fdof/nface_dofs;
900 const int interp_index = conf.
index;
901 const int iF = fdof%nface_dofs;
902 const int iE1 = d_indices1[
f*nface_dofs+iF];
905 const int offset1 = AddNnz(iE1,I,nface_dofs);
906 for (
int jF = 0; jF < nface_dofs; jF++)
908 const int jE2 = d_indices2[
f*nface_dofs+jF];
913 for (
int kF = 0; kF < nface_dofs; kF++)
915 val2 += d_interp(kF, iF, interp_index) * mat_fea(jF,kF,1,
f);
920 for (
int kF = 0; kF < nface_dofs; kF++)
922 val2 += mat_fea(kF,iF,1,
f) * d_interp(kF, jF, interp_index);
927 val2 = mat_fea(jF,iF,1,
f);
929 Data[offset1+jF] = val2;
932 const int iE2 = d_indices2[
f*nface_dofs+iF];
935 const int offset2 = AddNnz(iE2,I,nface_dofs);
936 for (
int jF = 0; jF < nface_dofs; jF++)
938 const int jE1 = d_indices1[
f*nface_dofs+jF];
943 for (
int kF = 0; kF < nface_dofs; kF++)
945 val1 += mat_fea(kF,iF,0,
f) * d_interp(kF, jF, interp_index);
950 for (
int kF = 0; kF < nface_dofs; kF++)
952 val1 += d_interp(kF, iF, interp_index) * mat_fea(jF,kF,0,
f);
957 val1 = mat_fea(jF,iF,0,
f);
959 Data[offset2+jF] = val1;
969 MFEM_ABORT(
"Not yet implemented.");
972void ParNCL2FaceRestriction::ComputeScatterIndicesAndOffsets()
977 for (
int i = 0; i <=
ndofs; ++i)
987 if ( face.IsNonconformingCoarse() )
995 if ( face.IsConforming() )
1001 if ( face.IsShared() )
1017 if ( face.IsShared() )
1040 MFEM_VERIFY(f_ind==
nf,
"Unexpected number of " <<
1042 " faces: " << f_ind <<
" vs " <<
nf );
1045 for (
int i = 1; i <=
ndofs; ++i)
1055void ParNCL2FaceRestriction::ComputeGatherIndices()
1061 for (
int f = 0;
f < mesh.GetNumFacesWithGhost(); ++
f)
1064 if ( face.IsNonconformingCoarse() )
1070 else if ( face.IsOfFaceType(
type) )
1082 MFEM_VERIFY(f_ind==
nf,
"Unexpected number of " <<
1084 " faces: " << f_ind <<
" vs " <<
nf );
1087 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...
void RegisterFaceCoarseToFineInterpolation(const Mesh::FaceInformation &face, int face_index)
Register the face with face and index face_index as a conforming face for the interpolation of the de...
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 ...
void InitializeNCInterpConfig()
void LinearizeInterpolatorMapIntoVector()
Transform the interpolation matrix map into a contiguous memory structure.
void RegisterFaceConformingInterpolation(const Mesh::FaceInformation &face, int face_index)
Register the face with face and index face_index as a conforming face for the interpolation of the de...
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....
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