12 #include "../general/forall.hpp"
15 #include "ceed/mass.hpp"
29 if (mesh->
GetNE() == 0) {
return; }
33 = IntRule ? IntRule : &MassIntegrator::GetRule(el, el, *T);
34 if (DeviceCanUseCeed())
37 ceedOp =
new ceed::PAMassIntegrator(fes, *ir, Q);
44 GeometricFactors::JACOBIANS);
48 pa_data.SetSize(ne*nq, Device::GetDeviceMemoryType());
53 MFEM_VERIFY(cQ != NULL,
"Only ConstantCoefficient is supported.");
56 if (!(
dim == 2 ||
dim == 3))
58 MFEM_ABORT(
"Dimension not supported.");
62 const double constant = coeff;
67 auto v =
Reshape(pa_data.Write(), NQ, NE);
70 for (
int q = 0; q < NQ; ++q)
72 const double J11 = J(q,0,0,e);
73 const double J12 = J(q,1,0,e);
74 const double J21 = J(q,0,1,e);
75 const double J22 = J(q,1,1,e);
76 const double detJ = (J11*J22)-(J21*J12);
77 v(q,e) = w[q] * constant * detJ;
83 const double constant = coeff;
88 auto v =
Reshape(pa_data.Write(), NQ,NE);
91 for (
int q = 0; q < NQ; ++q)
93 const double J11 = J(q,0,0,e), J12 = J(q,0,1,e), J13 = J(q,0,2,e);
94 const double J21 = J(q,1,0,e), J22 = J(q,1,1,e), J23 = J(q,1,2,e);
95 const double J31 = J(q,2,0,e), J32 = J(q,2,1,e), J33 = J(q,2,2,e);
96 const double detJ = J11 * (J22 * J33 - J32 * J23) -
97 J21 * (J12 * J33 - J32 * J13) +
98 J31 * (J12 * J23 - J22 * J13);
99 v(q,e) = W[q] * constant * detJ;
105 template<
const int T_D1D = 0,
107 static void PAVectorMassApply2D(
const int NE,
116 const int D1D = T_D1D ? T_D1D : d1d;
117 const int Q1D = T_Q1D ? T_Q1D : q1d;
118 constexpr
int VDIM = 2;
119 MFEM_VERIFY(D1D <=
MAX_D1D,
"");
120 MFEM_VERIFY(Q1D <=
MAX_Q1D,
"");
128 const int D1D = T_D1D ? T_D1D : d1d;
129 const int Q1D = T_Q1D ? T_Q1D : q1d;
131 constexpr
int max_D1D = T_D1D ? T_D1D :
MAX_D1D;
132 constexpr
int max_Q1D = T_Q1D ? T_Q1D :
MAX_Q1D;
133 double sol_xy[max_Q1D][max_Q1D];
134 for (
int c = 0; c < VDIM; ++c)
136 for (
int qy = 0; qy < Q1D; ++qy)
138 for (
int qx = 0; qx < Q1D; ++qx)
140 sol_xy[qy][qx] = 0.0;
143 for (
int dy = 0; dy < D1D; ++dy)
145 double sol_x[max_Q1D];
146 for (
int qy = 0; qy < Q1D; ++qy)
150 for (
int dx = 0; dx < D1D; ++dx)
152 const double s = x(dx,dy,c,e);
153 for (
int qx = 0; qx < Q1D; ++qx)
155 sol_x[qx] += B(qx,dx)*
s;
158 for (
int qy = 0; qy < Q1D; ++qy)
160 const double d2q = B(qy,dy);
161 for (
int qx = 0; qx < Q1D; ++qx)
163 sol_xy[qy][qx] += d2q * sol_x[qx];
167 for (
int qy = 0; qy < Q1D; ++qy)
169 for (
int qx = 0; qx < Q1D; ++qx)
171 sol_xy[qy][qx] *= op(qx,qy,e);
174 for (
int qy = 0; qy < Q1D; ++qy)
176 double sol_x[max_D1D];
177 for (
int dx = 0; dx < D1D; ++dx)
181 for (
int qx = 0; qx < Q1D; ++qx)
183 const double s = sol_xy[qy][qx];
184 for (
int dx = 0; dx < D1D; ++dx)
186 sol_x[dx] += Bt(dx,qx) *
s;
189 for (
int dy = 0; dy < D1D; ++dy)
191 const double q2d = Bt(dy,qy);
192 for (
int dx = 0; dx < D1D; ++dx)
194 y(dx,dy,c,e) += q2d * sol_x[dx];
202 template<
const int T_D1D = 0,
204 static void PAVectorMassApply3D(
const int NE,
205 const Array<double> &B_,
206 const Array<double> &Bt_,
213 const int D1D = T_D1D ? T_D1D : d1d;
214 const int Q1D = T_Q1D ? T_Q1D : q1d;
215 constexpr
int VDIM = 3;
216 MFEM_VERIFY(D1D <=
MAX_D1D,
"");
217 MFEM_VERIFY(Q1D <=
MAX_Q1D,
"");
218 auto B =
Reshape(B_.Read(), Q1D, D1D);
219 auto Bt =
Reshape(Bt_.Read(), D1D, Q1D);
220 auto op =
Reshape(op_.Read(), Q1D, Q1D, Q1D, NE);
221 auto x =
Reshape(x_.Read(), D1D, D1D, D1D, VDIM, NE);
222 auto y =
Reshape(y_.ReadWrite(), D1D, D1D, D1D, VDIM, NE);
225 const int D1D = T_D1D ? T_D1D : d1d;
226 const int Q1D = T_Q1D ? T_Q1D : q1d;
227 constexpr
int max_D1D = T_D1D ? T_D1D :
MAX_D1D;
228 constexpr
int max_Q1D = T_Q1D ? T_Q1D :
MAX_Q1D;
229 double sol_xyz[max_Q1D][max_Q1D][max_Q1D];
230 for (
int c = 0; c < VDIM; ++ c)
232 for (
int qz = 0; qz < Q1D; ++qz)
234 for (
int qy = 0; qy < Q1D; ++qy)
236 for (
int qx = 0; qx < Q1D; ++qx)
238 sol_xyz[qz][qy][qx] = 0.0;
242 for (
int dz = 0; dz < D1D; ++dz)
244 double sol_xy[max_Q1D][max_Q1D];
245 for (
int qy = 0; qy < Q1D; ++qy)
247 for (
int qx = 0; qx < Q1D; ++qx)
249 sol_xy[qy][qx] = 0.0;
252 for (
int dy = 0; dy < D1D; ++dy)
254 double sol_x[max_Q1D];
255 for (
int qx = 0; qx < Q1D; ++qx)
259 for (
int dx = 0; dx < D1D; ++dx)
261 const double s = x(dx,dy,dz,c,e);
262 for (
int qx = 0; qx < Q1D; ++qx)
264 sol_x[qx] += B(qx,dx) *
s;
267 for (
int qy = 0; qy < Q1D; ++qy)
269 const double wy = B(qy,dy);
270 for (
int qx = 0; qx < Q1D; ++qx)
272 sol_xy[qy][qx] += wy * sol_x[qx];
276 for (
int qz = 0; qz < Q1D; ++qz)
278 const double wz = B(qz,dz);
279 for (
int qy = 0; qy < Q1D; ++qy)
281 for (
int qx = 0; qx < Q1D; ++qx)
283 sol_xyz[qz][qy][qx] += wz * sol_xy[qy][qx];
288 for (
int qz = 0; qz < Q1D; ++qz)
290 for (
int qy = 0; qy < Q1D; ++qy)
292 for (
int qx = 0; qx < Q1D; ++qx)
294 sol_xyz[qz][qy][qx] *= op(qx,qy,qz,e);
298 for (
int qz = 0; qz < Q1D; ++qz)
300 double sol_xy[max_D1D][max_D1D];
301 for (
int dy = 0; dy < D1D; ++dy)
303 for (
int dx = 0; dx < D1D; ++dx)
308 for (
int qy = 0; qy < Q1D; ++qy)
310 double sol_x[max_D1D];
311 for (
int dx = 0; dx < D1D; ++dx)
315 for (
int qx = 0; qx < Q1D; ++qx)
317 const double s = sol_xyz[qz][qy][qx];
318 for (
int dx = 0; dx < D1D; ++dx)
320 sol_x[dx] += Bt(dx,qx) *
s;
323 for (
int dy = 0; dy < D1D; ++dy)
325 const double wy = Bt(dy,qy);
326 for (
int dx = 0; dx < D1D; ++dx)
328 sol_xy[dy][dx] += wy * sol_x[dx];
332 for (
int dz = 0; dz < D1D; ++dz)
334 const double wz = Bt(dz,qz);
335 for (
int dy = 0; dy < D1D; ++dy)
337 for (
int dx = 0; dx < D1D; ++dx)
339 y(dx,dy,dz,c,e) += wz * sol_xy[dy][dx];
348 static void PAVectorMassApply(
const int dim,
352 const Array<double> &B,
353 const Array<double> &Bt,
360 return PAVectorMassApply2D(NE, B, Bt, op, x, y, D1D, Q1D);
364 return PAVectorMassApply3D(NE, B, Bt, op, x, y, D1D, Q1D);
366 MFEM_ABORT(
"Unknown kernel.");
371 if (DeviceCanUseCeed())
373 ceedOp->AddMult(x, y);
377 PAVectorMassApply(dim, dofs1D, quad1D, ne, maps->B, maps->Bt, pa_data, x, y);
381 template<const
int T_D1D = 0, const
int T_Q1D = 0>
382 static void PAVectorMassAssembleDiagonal2D(
const int NE,
390 const int D1D = T_D1D ? T_D1D : d1d;
391 const int Q1D = T_Q1D ? T_Q1D : q1d;
392 constexpr
int VDIM = 2;
393 MFEM_VERIFY(D1D <=
MAX_D1D,
"");
394 MFEM_VERIFY(Q1D <=
MAX_Q1D,
"");
400 const int D1D = T_D1D ? T_D1D : d1d;
401 const int Q1D = T_Q1D ? T_Q1D : q1d;
402 constexpr
int max_D1D = T_D1D ? T_D1D :
MAX_D1D;
403 constexpr
int max_Q1D = T_Q1D ? T_Q1D :
MAX_Q1D;
405 double temp[max_Q1D][max_D1D];
406 for (
int qx = 0; qx < Q1D; ++qx)
408 for (
int dy = 0; dy < D1D; ++dy)
411 for (
int qy = 0; qy < Q1D; ++qy)
413 temp[qx][dy] += B(qy, dy) * B(qy, dy) * op(qx, qy, e);
417 for (
int dy = 0; dy < D1D; ++dy)
419 for (
int dx = 0; dx < D1D; ++dx)
422 for (
int qx = 0; qx < Q1D; ++qx)
424 temp1 += B(qx, dx) * B(qx, dx) * temp[qx][dy];
426 y(dx, dy, 0, e) = temp1;
427 y(dx, dy, 1, e) = temp1;
433 template<const
int T_D1D = 0, const
int T_Q1D = 0>
434 static void PAVectorMassAssembleDiagonal3D(
const int NE,
435 const Array<double> &B_,
436 const Array<double> &Bt_,
442 const int D1D = T_D1D ? T_D1D : d1d;
443 const int Q1D = T_Q1D ? T_Q1D : q1d;
444 constexpr
int VDIM = 3;
445 MFEM_VERIFY(D1D <=
MAX_D1D,
"");
446 MFEM_VERIFY(Q1D <=
MAX_Q1D,
"");
447 auto B =
Reshape(B_.Read(), Q1D, D1D);
448 auto op =
Reshape(op_.Read(), Q1D, Q1D, Q1D, NE);
449 auto y =
Reshape(diag_.ReadWrite(), D1D, D1D, D1D, VDIM, NE);
452 const int D1D = T_D1D ? T_D1D : d1d;
453 const int Q1D = T_Q1D ? T_Q1D : q1d;
455 constexpr
int max_D1D = T_D1D ? T_D1D :
MAX_D1D;
456 constexpr
int max_Q1D = T_Q1D ? T_Q1D :
MAX_Q1D;
458 double temp[max_Q1D][max_Q1D][max_D1D];
459 for (
int qx = 0; qx < Q1D; ++qx)
461 for (
int qy = 0; qy < Q1D; ++qy)
463 for (
int dz = 0; dz < D1D; ++dz)
465 temp[qx][qy][dz] = 0.0;
466 for (
int qz = 0; qz < Q1D; ++qz)
468 temp[qx][qy][dz] += B(qz, dz) * B(qz, dz) * op(qx, qy, qz, e);
473 double temp2[max_Q1D][max_D1D][max_D1D];
474 for (
int qx = 0; qx < Q1D; ++qx)
476 for (
int dz = 0; dz < D1D; ++dz)
478 for (
int dy = 0; dy < D1D; ++dy)
480 temp2[qx][dy][dz] = 0.0;
481 for (
int qy = 0; qy < Q1D; ++qy)
483 temp2[qx][dy][dz] += B(qy, dy) * B(qy, dy) * temp[qx][qy][dz];
488 for (
int dz = 0; dz < D1D; ++dz)
490 for (
int dy = 0; dy < D1D; ++dy)
492 for (
int dx = 0; dx < D1D; ++dx)
495 for (
int qx = 0; qx < Q1D; ++qx)
497 temp3 += B(qx, dx) * B(qx, dx)
500 y(dx, dy, dz, 0, e) = temp3;
501 y(dx, dy, dz, 1, e) = temp3;
502 y(dx, dy, dz, 2, e) = temp3;
509 static void PAVectorMassAssembleDiagonal(
const int dim,
513 const Array<double> &B,
514 const Array<double> &Bt,
520 return PAVectorMassAssembleDiagonal2D(NE, B, Bt, op, y, D1D, Q1D);
524 return PAVectorMassAssembleDiagonal3D(NE, B, Bt, op, y, D1D, Q1D);
526 MFEM_ABORT(
"Dimension not implemented.");
529 void VectorMassIntegrator::AssembleDiagonalPA(
Vector &diag)
531 if (DeviceCanUseCeed())
533 ceedOp->GetDiagonal(diag);
537 PAVectorMassAssembleDiagonal(dim,
int GetNPoints() const
Returns the number of the points in the integration rule.
Abstract class for all finite elements.
Class for an integration rule - an Array of IntegrationPoint.
A coefficient that is constant across space and time.
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 ndof
Number of degrees of freedom = number of basis functions. When mode is TENSOR, this is the 1D number...
int GetNE() const
Returns number of elements.
const Array< double > & GetWeights() const
Return the quadrature weights in a contiguous array.
DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims...dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
Mesh * GetMesh() const
Returns the mesh.
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
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...
virtual double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
virtual const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).