56 MFEM_VERIFY(cQ != NULL,
"Only ConstantCoefficient is supported.");
59 if (!(
dim == 2 ||
dim == 3))
61 MFEM_ABORT(
"Dimension not supported.");
65 const real_t constant = coeff;
73 for (
int q = 0; q < NQ; ++q)
75 const real_t J11 = J(q,0,0,e);
76 const real_t J12 = J(q,1,0,e);
77 const real_t J21 = J(q,0,1,e);
78 const real_t J22 = J(q,1,1,e);
79 const real_t detJ = (J11*J22)-(J21*J12);
80 v(q,e) = w[q] * constant * detJ;
86 const real_t constant = coeff;
94 for (
int q = 0; q < NQ; ++q)
96 const real_t J11 = J(q,0,0,e), J12 = J(q,0,1,e), J13 = J(q,0,2,e);
97 const real_t J21 = J(q,1,0,e), J22 = J(q,1,1,e), J23 = J(q,1,2,e);
98 const real_t J31 = J(q,2,0,e), J32 = J(q,2,1,e), J33 = J(q,2,2,e);
99 const real_t detJ = J11 * (J22 * J33 - J32 * J23) -
100 J21 * (J12 * J33 - J32 * J13) +
101 J31 * (J12 * J23 - J22 * J13);
102 v(q,e) = W[q] * constant * detJ;
108template<const
int T_D1D = 0, const
int T_Q1D = 0>
109static void PAVectorMassAssembleDiagonal2D(
const int NE,
117 const int D1D = T_D1D ? T_D1D : d1d;
118 const int Q1D = T_Q1D ? T_Q1D : q1d;
119 constexpr int VDIM = 2;
127 const int D1D = T_D1D ? T_D1D : d1d;
128 const int Q1D = T_Q1D ? T_Q1D : q1d;
129 constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
130 constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
132 real_t temp[max_Q1D][max_D1D];
133 for (
int qx = 0; qx < Q1D; ++qx)
135 for (
int dy = 0; dy < D1D; ++dy)
138 for (
int qy = 0; qy < Q1D; ++qy)
140 temp[qx][dy] += B(qy, dy) * B(qy, dy) * op(qx, qy, e);
144 for (
int dy = 0; dy < D1D; ++dy)
146 for (
int dx = 0; dx < D1D; ++dx)
149 for (
int qx = 0; qx < Q1D; ++qx)
151 temp1 += B(qx, dx) * B(qx, dx) * temp[qx][dy];
153 y(dx, dy, 0, e) = temp1;
154 y(dx, dy, 1, e) = temp1;
160template<const
int T_D1D = 0, const
int T_Q1D = 0>
161static void PAVectorMassAssembleDiagonal3D(
const int NE,
162 const Array<real_t> &B_,
163 const Array<real_t> &Bt_,
169 const int D1D = T_D1D ? T_D1D : d1d;
170 const int Q1D = T_Q1D ? T_Q1D : q1d;
171 constexpr int VDIM = 3;
174 auto B =
Reshape(B_.Read(), Q1D, D1D);
175 auto op =
Reshape(op_.Read(), Q1D, Q1D, Q1D, NE);
176 auto y =
Reshape(diag_.ReadWrite(), D1D, D1D, D1D, VDIM, NE);
179 const int D1D = T_D1D ? T_D1D : d1d;
180 const int Q1D = T_Q1D ? T_Q1D : q1d;
182 constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
183 constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
185 real_t temp[max_Q1D][max_Q1D][max_D1D];
186 for (
int qx = 0; qx < Q1D; ++qx)
188 for (
int qy = 0; qy < Q1D; ++qy)
190 for (
int dz = 0; dz < D1D; ++dz)
192 temp[qx][qy][dz] = 0.0;
193 for (
int qz = 0; qz < Q1D; ++qz)
195 temp[qx][qy][dz] += B(qz, dz) * B(qz, dz) * op(qx, qy, qz, e);
200 real_t temp2[max_Q1D][max_D1D][max_D1D];
201 for (
int qx = 0; qx < Q1D; ++qx)
203 for (
int dz = 0; dz < D1D; ++dz)
205 for (
int dy = 0; dy < D1D; ++dy)
207 temp2[qx][dy][dz] = 0.0;
208 for (
int qy = 0; qy < Q1D; ++qy)
210 temp2[qx][dy][dz] += B(qy, dy) * B(qy, dy) * temp[qx][qy][dz];
215 for (
int dz = 0; dz < D1D; ++dz)
217 for (
int dy = 0; dy < D1D; ++dy)
219 for (
int dx = 0; dx < D1D; ++dx)
222 for (
int qx = 0; qx < Q1D; ++qx)
224 temp3 += B(qx, dx) * B(qx, dx)
227 y(dx, dy, dz, 0, e) = temp3;
228 y(dx, dy, dz, 1, e) = temp3;
229 y(dx, dy, dz, 2, e) = temp3;
236static void PAVectorMassAssembleDiagonal(
const int dim,
240 const Array<real_t> &B,
241 const Array<real_t> &Bt,
247 return PAVectorMassAssembleDiagonal2D(NE, B, Bt, op, y, D1D, Q1D);
251 return PAVectorMassAssembleDiagonal3D(NE, B, Bt, op, y, D1D, Q1D);
253 MFEM_ABORT(
"Dimension not implemented.");
270template<const
int T_D1D = 0, const
int T_Q1D = 0>
271static void PAVectorMassApply2D(
const int NE,
280 const int D1D = T_D1D ? T_D1D : d1d;
281 const int Q1D = T_Q1D ? T_Q1D : q1d;
282 constexpr int VDIM = 2;
292 const int D1D = T_D1D ? T_D1D : d1d;
293 const int Q1D = T_Q1D ? T_Q1D : q1d;
295 constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
296 constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
297 real_t sol_xy[max_Q1D][max_Q1D];
298 for (
int c = 0; c < VDIM; ++c)
300 for (
int qy = 0; qy < Q1D; ++qy)
302 for (
int qx = 0; qx < Q1D; ++qx)
304 sol_xy[qy][qx] = 0.0;
307 for (
int dy = 0; dy < D1D; ++dy)
310 for (
int qy = 0; qy < Q1D; ++qy)
314 for (
int dx = 0; dx < D1D; ++dx)
316 const real_t s = x(dx,dy,c,e);
317 for (
int qx = 0; qx < Q1D; ++qx)
319 sol_x[qx] += B(qx,dx)* s;
322 for (
int qy = 0; qy < Q1D; ++qy)
324 const real_t d2q = B(qy,dy);
325 for (
int qx = 0; qx < Q1D; ++qx)
327 sol_xy[qy][qx] += d2q * sol_x[qx];
331 for (
int qy = 0; qy < Q1D; ++qy)
333 for (
int qx = 0; qx < Q1D; ++qx)
335 sol_xy[qy][qx] *= op(qx,qy,e);
338 for (
int qy = 0; qy < Q1D; ++qy)
341 for (
int dx = 0; dx < D1D; ++dx)
345 for (
int qx = 0; qx < Q1D; ++qx)
347 const real_t s = sol_xy[qy][qx];
348 for (
int dx = 0; dx < D1D; ++dx)
350 sol_x[dx] += Bt(dx,qx) * s;
353 for (
int dy = 0; dy < D1D; ++dy)
355 const real_t q2d = Bt(dy,qy);
356 for (
int dx = 0; dx < D1D; ++dx)
358 y(dx,dy,c,e) += q2d * sol_x[dx];
366template<const
int T_D1D = 0, const
int T_Q1D = 0>
367static void PAVectorMassApply3D(
const int NE,
368 const Array<real_t> &B_,
369 const Array<real_t> &Bt_,
376 const int D1D = T_D1D ? T_D1D : d1d;
377 const int Q1D = T_Q1D ? T_Q1D : q1d;
378 constexpr int VDIM = 3;
381 auto B =
Reshape(B_.Read(), Q1D, D1D);
382 auto Bt =
Reshape(Bt_.Read(), D1D, Q1D);
383 auto op =
Reshape(op_.Read(), Q1D, Q1D, Q1D, NE);
384 auto x =
Reshape(x_.Read(), D1D, D1D, D1D, VDIM, NE);
385 auto y =
Reshape(y_.ReadWrite(), D1D, D1D, D1D, VDIM, NE);
388 const int D1D = T_D1D ? T_D1D : d1d;
389 const int Q1D = T_Q1D ? T_Q1D : q1d;
390 constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
391 constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
392 real_t sol_xyz[max_Q1D][max_Q1D][max_Q1D];
393 for (
int c = 0; c < VDIM; ++ c)
395 for (
int qz = 0; qz < Q1D; ++qz)
397 for (
int qy = 0; qy < Q1D; ++qy)
399 for (
int qx = 0; qx < Q1D; ++qx)
401 sol_xyz[qz][qy][qx] = 0.0;
405 for (
int dz = 0; dz < D1D; ++dz)
407 real_t sol_xy[max_Q1D][max_Q1D];
408 for (
int qy = 0; qy < Q1D; ++qy)
410 for (
int qx = 0; qx < Q1D; ++qx)
412 sol_xy[qy][qx] = 0.0;
415 for (
int dy = 0; dy < D1D; ++dy)
418 for (
int qx = 0; qx < Q1D; ++qx)
422 for (
int dx = 0; dx < D1D; ++dx)
424 const real_t s = x(dx,dy,dz,c,e);
425 for (
int qx = 0; qx < Q1D; ++qx)
427 sol_x[qx] += B(qx,dx) * s;
430 for (
int qy = 0; qy < Q1D; ++qy)
432 const real_t wy = B(qy,dy);
433 for (
int qx = 0; qx < Q1D; ++qx)
435 sol_xy[qy][qx] += wy * sol_x[qx];
439 for (
int qz = 0; qz < Q1D; ++qz)
441 const real_t wz = B(qz,dz);
442 for (
int qy = 0; qy < Q1D; ++qy)
444 for (
int qx = 0; qx < Q1D; ++qx)
446 sol_xyz[qz][qy][qx] += wz * sol_xy[qy][qx];
451 for (
int qz = 0; qz < Q1D; ++qz)
453 for (
int qy = 0; qy < Q1D; ++qy)
455 for (
int qx = 0; qx < Q1D; ++qx)
457 sol_xyz[qz][qy][qx] *= op(qx,qy,qz,e);
461 for (
int qz = 0; qz < Q1D; ++qz)
463 real_t sol_xy[max_D1D][max_D1D];
464 for (
int dy = 0; dy < D1D; ++dy)
466 for (
int dx = 0; dx < D1D; ++dx)
471 for (
int qy = 0; qy < Q1D; ++qy)
474 for (
int dx = 0; dx < D1D; ++dx)
478 for (
int qx = 0; qx < Q1D; ++qx)
480 const real_t s = sol_xyz[qz][qy][qx];
481 for (
int dx = 0; dx < D1D; ++dx)
483 sol_x[dx] += Bt(dx,qx) * s;
486 for (
int dy = 0; dy < D1D; ++dy)
488 const real_t wy = Bt(dy,qy);
489 for (
int dx = 0; dx < D1D; ++dx)
491 sol_xy[dy][dx] += wy * sol_x[dx];
495 for (
int dz = 0; dz < D1D; ++dz)
497 const real_t wz = Bt(dz,qz);
498 for (
int dy = 0; dy < D1D; ++dy)
500 for (
int dx = 0; dx < D1D; ++dx)
502 y(dx,dy,dz,c,e) += wz * sol_xy[dy][dx];
511static void PAVectorMassApply(
const int dim,
515 const Array<real_t> &B,
516 const Array<real_t> &Bt,
523 return PAVectorMassApply2D(NE, B, Bt, op, x, y, D1D, Q1D);
527 return PAVectorMassApply3D(NE, B, Bt, op, x, y, D1D, Q1D);
529 MFEM_ABORT(
"Unknown kernel.");
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
A coefficient that is constant across space and time.
static MemoryType GetDeviceMemoryType()
Get the current Device MemoryType. This is the MemoryType used by most MFEM classes when allocating m...
@ 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.
int nqpt
Number of quadrature points. 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.
Mesh * GetMesh() const
Returns the mesh.
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...
Vector J
Jacobians of the element transformations at all quadrature points.
Class for an integration rule - an Array of IntegrationPoint.
int GetNPoints() const
Returns the number of the points in the integration rule.
const Array< real_t > & GetWeights() const
Return the quadrature weights in a contiguous array.
const IntegrationRule * IntRule
static const IntegrationRule & GetRule(const FiniteElement &trial_fe, const FiniteElement &test_fe, const ElementTransformation &Trans)
int GetNE() const
Returns number of elements.
int Dimension() const
Dimension of the reference space used within the elements.
ElementTransformation * GetTypicalElementTransformation()
If the local mesh is not empty return GetElementTransformation(0); otherwise, return the identity tra...
const GeometricFactors * GetGeometricFactors(const IntegrationRule &ir, const int flags, MemoryType d_mt=MemoryType::DEFAULT)
Return the mesh geometric factors corresponding to the given integration rule.
int GetNumGeometries(int dim) const
Return the number of geometries of the given dimension present in the mesh.
void AssembleDiagonalPA(Vector &diag) override
Assemble diagonal and add it to Vector diag.
const DofToQuad * maps
Not owned.
void AddMultPA(const Vector &x, Vector &y) const override
Method for partially assembled action.
void AssemblePA(const FiniteElementSpace &fes) override
Method defining partial assembly.
const GeometricFactors * geom
Not owned.
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.
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
void GetDiagonal(mfem::Vector &diag) const
void AddMult(const mfem::Vector &x, mfem::Vector &y, const real_t a=1.0) const override
Operator application: y+=A(x) (default) or y+=a*A(x).
Represent a MassIntegrator with AssemblyLevel::Partial using libCEED.
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
bool DeviceCanUseCeed()
Function that determines if a CEED kernel should be used, based on the current mfem::Device configura...
void forall(int N, lambda &&body)
static const DeviceDofQuadLimits & Get()
Return a const reference to the DeviceDofQuadLimits singleton.