20struct DGMassInvKernels { DGMassInvKernels(); };
26 :
Solver(fes_orig.GetTrueVSize()),
27 fec(fes_orig.GetMaxElementOrder(),
28 fes_orig.
GetMesh()->Dimension(),
30 fes_orig.GetTypicalFE()->GetMapType()),
33 static DGMassInvKernels kernels;
38 const int btype_orig =
41 if (btype_orig == btype)
80 M->AddDomainIntegrator(
m);
104 MFEM_ABORT(
"SetOperator not supported with DGMassInverse.")
122template<
int DIM,
int D1D,
int Q1D>
125 using namespace internal;
131 const int ND =
static_cast<int>(pow(d1d,
DIM));
146 const bool CHANGE_BASIS = (
d2q !=
nullptr);
154 const real_t *b_orig =
nullptr;
155 const real_t *d2q_B =
nullptr;
156 const real_t *q2d_B =
nullptr;
157 const real_t *q2d_Bt =
nullptr;
173 static constexpr int NB = Q1D ? Q1D : 1;
181 DGMassBasis<DIM,D1D>(e, NE, q2d_Bt, b_orig, b2, d1d);
185 DGMassBasis<DIM,D1D>(e, NE, d2q_B,
u,
u, d1d);
189 const int tid = MFEM_THREAD_ID(x) + NB*MFEM_THREAD_ID(y);
194 DGMassApply<DIM,D1D,Q1D>(e, NE, B, Bt, pa_data,
u, r, d1d, q1d);
195 DGMassAxpy(e, NE, ND, 1.0,
b, -1.0, r, r);
200 const int BX = MFEM_THREAD_SIZE(x);
201 const int BY = MFEM_THREAD_SIZE(y);
202 const int bxy = BX*BY;
206 for (
int i = tid; i < ND; i += bxy)
214 DGMassPreconditioner(e, NE, ND, dinv, r, z);
215 DGMassAxpy(e, NE, ND, 1.0, z, 0.0, z, d);
217 real_t nom = DGMassDot<NB>(e, NE, ND, d, r);
218 if (nom < 0.0) {
return; }
219 real_t r0 = fmax(nom*RELTOL*RELTOL, ABSTOL*ABSTOL);
220 if (nom <= r0) {
return; }
222 DGMassApply<DIM,D1D,Q1D>(e, NE, B, Bt, pa_data, d, z, d1d, q1d);
223 real_t den = DGMassDot<NB>(e, NE, ND, z, d);
226 DGMassDot<NB>(e, NE, ND, d, d);
228 if (den == 0.0) {
return; }
236 DGMassAxpy(e, NE, ND, 1.0,
u,
alpha, d,
u);
237 DGMassAxpy(e, NE, ND, 1.0, r, -
alpha, z, r);
239 DGMassPreconditioner(e, NE, ND, dinv, r, z);
241 real_t betanom = DGMassDot<NB>(e, NE, ND, r, z);
242 if (betanom < 0.0) {
return; }
243 if (betanom <= r0) {
break; }
245 if (++i > MAXIT) {
break; }
247 const real_t beta = betanom/nom;
248 DGMassAxpy(e, NE, ND, 1.0, z, beta, d, d);
249 DGMassApply<DIM,D1D,Q1D>(e, NE, B, Bt, pa_data, d, z, d1d, q1d);
250 den = DGMassDot<NB>(e, NE, ND, d, z);
253 DGMassDot<NB>(e, NE, ND, d, d);
255 if (den == 0.0) {
break; }
262 DGMassBasis<DIM,D1D>(e, NE, q2d_B,
u,
u, d1d);
274 CGKernels::Run(
dim, d1d, q1d, *
this, Mu,
u);
277DGMassInvKernels::DGMassInvKernels()
279 using k = DGMassInverse::CGKernels;
281 k::Specialization<2,1,1>::Add();
282 k::Specialization<2,2,2>::Add();
283 k::Specialization<2,3,3>::Add();
284 k::Specialization<2,3,5>::Add();
285 k::Specialization<2,4,4>::Add();
286 k::Specialization<2,4,6>::Add();
287 k::Specialization<2,5,5>::Add();
288 k::Specialization<2,5,7>::Add();
289 k::Specialization<2,6,6>::Add();
290 k::Specialization<2,6,8>::Add();
292 k::Specialization<3,2,2>::Add();
293 k::Specialization<3,2,3>::Add();
294 k::Specialization<3,3,3>::Add();
295 k::Specialization<3,3,4>::Add();
296 k::Specialization<3,3,5>::Add();
297 k::Specialization<3,4,4>::Add();
298 k::Specialization<3,4,5>::Add();
299 k::Specialization<3,4,6>::Add();
300 k::Specialization<3,4,8>::Add();
301 k::Specialization<3,5,5>::Add();
302 k::Specialization<3,5,6>::Add();
303 k::Specialization<3,5,7>::Add();
304 k::Specialization<3,5,8>::Add();
305 k::Specialization<3,6,6>::Add();
306 k::Specialization<3,6,7>::Add();
311template <
int DIM,
int D1D,
int Q1D>
323 else { MFEM_ABORT(
"Unsupported dimension."); }
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
T * HostReadWrite()
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
T * HostWrite()
Shortcut for mfem::Write(a.GetMemory(), a.Size(), false).
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
Solver for the discontinuous Galerkin mass matrix.
Vector diag_inv
Jacobi preconditioner.
class MassIntegrator * m
Mass integrator, owned by the form M.
void(DGMassInverse::*)(const Vector &b_, Vector &u) const CGKernelType
real_t rel_tol
Relative CG tolerance.
int max_iter
Maximum number of CG iterations;.
Array< real_t > B_
Inverse of change of basis.
std::unique_ptr< class BilinearForm > M
Mass bilinear form.
real_t abs_tol
Absolute CG tolerance.
DGMassInverse(const FiniteElementSpace &fes_, Coefficient *coeff, const IntegrationRule *ir, int btype)
Protected constructor, used internally.
void SetMaxIter(const int max_iter_)
Set the maximum number of iterations.
Array< real_t > Bt_
Inverse of change of basis, transposed.
void SetOperator(const Operator &op) override
Not implemented. Aborts.
void Update()
Recompute operator and preconditioner (when coefficient or mesh changes).
void DGMassCGIteration(const Vector &b_, Vector &u_) const
Solve the system M b = u. Not part of the public interface.
void Mult(const Vector &b, Vector &u) const override
Solve the system M b = u.
void SetRelTol(const real_t rel_tol_)
Set the relative tolerance.
FiniteElementSpace fes
FE space in requested basis.
const DofToQuad * d2q
Change of basis. Not owned.
void SetAbsTol(const real_t abs_tol_)
Set the absolute tolerance.
Data type dense matrix using column-major storage.
void Transpose()
(*this) = (*this)^t
@ TENSOR
Tensor product representation using 1D matrices/tensors with dimensions using 1D number of quadrature...
Array< real_t > B
Basis functions evaluated at quadrature points.
int ndof
Number of degrees of freedom = number of basis functions. When mode is TENSOR, this is the 1D number.
Array< real_t > Bt
Transpose of B.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
bool IsVariableOrder() const
Returns true if the space contains elements of varying polynomial orders.
int GetNE() const
Returns number of elements in the mesh.
const FiniteElementCollection * FEColl() const
Mesh * GetMesh() const
Returns the mesh.
bool IsDGSpace() const
Return whether or not the space is discontinuous (L2)
const FiniteElement * GetTypicalFE() const
Return GetFE(0) if the local mesh is not empty; otherwise return a typical FE based on the Geometry t...
Abstract class for all finite elements.
virtual const DofToQuad & GetDofToQuad(const IntegrationRule &ir, DofToQuad::Mode mode) const
Return a DofToQuad structure corresponding to the given IntegrationRule using the given DofToQuad::Mo...
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Class for an integration rule - an Array of IntegrationPoint.
Arbitrary order "L2-conforming" discontinuous finite elements.
bool Factor(int m, real_t TOL=0.0) override
Compute the LU factorization of the current matrix.
void GetInverseMatrix(int m, real_t *X) const override
Assuming L.U = P.A factored data of size (m x m), compute X <- A^{-1}.
const DofToQuad * maps
Not owned.
int Dimension() const
Dimension of the reference space used within the elements.
int height
Dimension of the output / number of rows in the matrix.
virtual void AssembleDiagonal(Vector &diag) const
Computes the diagonal entries into diag. Typically, this operation only makes sense for linear Operat...
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
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).
void SetSize(int s)
Resize the vector to size s.
void Reciprocal()
(*this)(i) = 1.0 / (*this)(i)
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
real_t u(const Vector &xvec)
void forall_2D(int N, int X, int Y, lambda &&body)
DeviceTensor< 2, const real_t > ConstDeviceMatrix
DeviceTensor< 2, real_t > DeviceMatrix