21template <Ordering::Type Order,
bool Atomic>
22static void DerefMultKernelImpl(
const DerefineMatrixOp &op,
const Vector &x,
25 DerefineMatrixOpMultFunctor<Order, Atomic> func;
29 func.yptr = y.ReadWrite();
30 func.bsptr = op.block_storage.Read();
31 func.boptr = op.block_offsets.Read();
32 func.brptr = op.block_row_idcs_offsets.Read();
33 func.bcptr = op.block_col_idcs_offsets.Read();
34 func.rptr = op.row_idcs.Read();
35 func.cptr = op.col_idcs.Read();
36 func.vdims = op.fespace->GetVDim();
37 func.nblocks = op.block_offsets.Size();
38 func.width = op.Width() / func.vdims;
39 func.height = op.Height() / func.vdims;
40 func.Run(op.max_rows);
45DerefineMatrixOp::DerefineMatrixOp(FiniteElementSpace &fespace_,
int old_ndofs,
46 const Table *old_elem_dof,
47 const Table *old_elem_fos)
52 constexpr int max_team_size = 256;
55 MFEM_VERIFY(fespace->Nonconforming(),
56 "Not implemented for conforming meshes.");
57 MFEM_VERIFY(old_ndofs,
"Missing previous (finer) space.");
58 MFEM_VERIFY(fespace->GetNDofs() <= old_ndofs,
59 "Previous space is not finer.");
61 const CoarseFineTransformations &dtrans =
62 fespace->GetMesh()->ncmesh->GetDerefinementTransforms();
64 MFEM_ASSERT(dtrans.embeddings.Size() == old_elem_dof->Size(),
"");
66 const bool is_dg = fespace->FEColl()->GetContType()
67 == FiniteElementCollection::DISCONTINUOUS;
70 DenseTensor localR[Geometry::NumGeom];
73 block_offsets.SetSize(dtrans.embeddings.Size());
74 block_offsets.HostWrite();
75 if (fespace->IsVariableOrder())
81 for (
int k = 0; k < dtrans.embeddings.Size(); ++k)
83 const Embedding &emb = dtrans.embeddings[k];
84 const FiniteElement *fe = fespace->GetFE(emb.parent);
85 const int ldof = fe->GetDof();
86 if (k + 1 < dtrans.embeddings.Size())
88 block_offsets[k + 1] = block_offsets[k] + ldof * ldof;
92 total_size += ldof * ldof;
94 block_storage.SetSize(total_size);
101 Mesh::GeometryList elem_geoms(*fespace->GetMesh());
103 int geom_offsets[Geometry::NumGeom];
106 for (
int i = 0; i < elem_geoms.Size(); ++i)
108 fespace->GetLocalDerefinementMatrices(elem_geoms[i],
109 localR[elem_geoms[i]]);
110 geom_offsets[elem_geoms[i]] = size;
111 size += localR[elem_geoms[i]].TotalSize();
113 block_storage.SetSize(size);
115 auto bs_ptr = block_storage.HostWrite();
116 for (
int i = 0; i < elem_geoms.Size(); ++i)
118 std::copy(localR[elem_geoms[i]].Data(),
119 localR[elem_geoms[i]].Data()
120 + localR[elem_geoms[i]].TotalSize(),
122 bs_ptr += localR[elem_geoms[i]].TotalSize();
125 for (
int k = 0; k < dtrans.embeddings.Size(); ++k)
127 const Embedding &emb = dtrans.embeddings[k];
128 Geometry::Type geom =
129 fespace->GetMesh()->GetElementBaseGeometry(emb.parent);
131 auto size = localR[geom].SizeI() * localR[geom].SizeJ();
132 total_rows += localR[geom].SizeI();
133 total_cols += localR[geom].SizeJ();
135 block_offsets[k] = geom_offsets[geom] + size * emb.matrix;
138 row_idcs.SetSize(total_rows);
139 row_idcs.HostWrite();
140 col_idcs.SetSize(total_cols);
141 col_idcs.HostWrite();
142 block_row_idcs_offsets.SetSize(dtrans.embeddings.Size() + 1);
143 block_row_idcs_offsets.HostWrite();
144 block_col_idcs_offsets.SetSize(dtrans.embeddings.Size() + 1);
145 block_col_idcs_offsets.HostWrite();
146 block_row_idcs_offsets[0] = 0;
147 block_col_idcs_offsets[0] = 0;
150 Array<int> dofs, old_dofs;
154 Array<int> mark(fespace->GetNDofs());
156 auto bs_ptr = block_storage.HostWrite();
160 for (
int k = 0; k < dtrans.embeddings.Size(); k++)
162 const Embedding &emb = dtrans.embeddings[k];
163 Geometry::Type geom =
164 fespace->GetMesh()->GetElementBaseGeometry(emb.parent);
166 if (fespace->IsVariableOrder())
168 const FiniteElement *fe = fespace->GetFE(emb.parent);
169 const DenseTensor &pmats = dtrans.point_matrices[geom];
170 const int ldof = fe->GetDof();
172 IsoparametricTransformation isotr;
173 isotr.SetIdentityTransformation(geom);
175 localRVO.SetSize(ldof, ldof);
176 isotr.SetPointMat(pmats(emb.matrix));
179 fe->GetLocalRestriction(isotr, localRVO);
181 auto size = localRVO.Height() * localRVO.Width();
182 std::copy(localRVO.Data(), localRVO.Data() + size, bs_ptr);
186 fespace->IsVariableOrder() ? localRVO : localR[geom](emb.matrix);
187 block_row_idcs_offsets[k + 1] =
188 block_row_idcs_offsets[k] + lR.Height();
189 block_col_idcs_offsets[k + 1] = block_col_idcs_offsets[k] + lR.Width();
190 max_rows = std::max(lR.Height(), max_rows);
192 fespace->elem_dof->GetRow(emb.parent, dofs);
193 old_elem_dof->GetRow(k, old_dofs);
194 MFEM_VERIFY(old_dofs.Size() == dofs.Size(),
195 "Parent and child must have same #dofs.");
196 for (
int i = 0; i < lR.Height(); ++i, ++ridx)
198 if (!std::isfinite(lR(i, 0)))
200 row_idcs[ridx] = INT_MAX;
204 int m = (r >= 0) ? r : (-1 - r);
205 if (is_dg || !mark[m])
213 row_idcs[ridx] = INT_MAX;
216 for (
int i = 0; i < lR.Width(); ++i, ++cidx)
218 col_idcs[cidx] = old_dofs[i];
221 if (!is_dg && !fespace->IsVariableOrder())
223 MFEM_VERIFY(num_marked * fespace->GetVDim() == Height(),
224 "internal error: not all rows were set.");
228 if (Device::Allows(Backend::DEVICE_MASK))
230 max_rows = std::min(max_rows, max_team_size);
238void DerefineMatrixOp::Mult(
const Vector &x, Vector &y)
const
240 const bool is_dg = fespace->FEColl()->GetContType()
241 == FiniteElementCollection::DISCONTINUOUS;
243 MultKernel::Run(fespace->GetOrdering(), is_dg, *
this, x, y);
246DerefineMatrixOp::Kernels::Kernels()
248 MultKernel::Specialization<Ordering::byNODES, false>::Add();
249 MultKernel::Specialization<Ordering::byVDIM, false>::Add();
250 MultKernel::Specialization<Ordering::byNODES, true>::Add();
251 MultKernel::Specialization<Ordering::byVDIM, true>::Add();
254template <Ordering::Type Order,
bool Atomic>
255DerefineMatrixOp::MultKernelType DerefineMatrixOp::MultKernel::Kernel()
257 return internal::DerefMultKernelImpl<Order, Atomic>;
260DerefineMatrixOp::MultKernelType
261DerefineMatrixOp::MultKernel::Fallback(Ordering::Type,
bool)
263 MFEM_ABORT(
"invalid MultKernel parameters");
int GetVDim(const FieldDescriptor &f)
Get the vdim of a field descriptor.
int GetVSize(const FieldDescriptor &f)
Get the vdof size of a field descriptor.
SchrodingerBaseKernels< ParMesh, ParFiniteElementSpace, ParComplexGridFunction, ParGridFunction, ParBilinearForm, ParMixedBilinearForm, ParLinearForm > Kernels