12 #include "../general/forall.hpp"
15 #include "libceed/mass.hpp"
29 if (mesh->
GetNE() == 0) {
return; }
33 = IntRule ? IntRule : &MassIntegrator::GetRule(el, el, *T);
34 if (DeviceCanUseCeed())
37 ceedDataPtr =
new CeedData;
38 InitCeedCoeff(Q, *mesh, *ir, ceedDataPtr);
39 return CeedPAMassAssemble(fes, *ir, *ceedDataPtr);
45 GeometricFactors::JACOBIANS);
49 pa_data.SetSize(ne*nq, Device::GetDeviceMemoryType());
54 MFEM_VERIFY(cQ != NULL,
"Only ConstantCoefficient is supported.");
57 if (!(
dim == 2 ||
dim == 3))
59 MFEM_ABORT(
"Dimension not supported.");
63 const double constant = coeff;
68 auto v =
Reshape(pa_data.Write(), NQ, NE);
71 for (
int q = 0; q < NQ; ++q)
73 const double J11 = J(q,0,0,e);
74 const double J12 = J(q,1,0,e);
75 const double J21 = J(q,0,1,e);
76 const double J22 = J(q,1,1,e);
77 const double detJ = (J11*J22)-(J21*J12);
78 v(q,e) = w[q] * constant * detJ;
84 const double constant = coeff;
89 auto v =
Reshape(pa_data.Write(), NQ,NE);
92 for (
int q = 0; q < NQ; ++q)
94 const double J11 = J(q,0,0,e), J12 = J(q,0,1,e), J13 = J(q,0,2,e);
95 const double J21 = J(q,1,0,e), J22 = J(q,1,1,e), J23 = J(q,1,2,e);
96 const double J31 = J(q,2,0,e), J32 = J(q,2,1,e), J33 = J(q,2,2,e);
97 const double detJ = J11 * (J22 * J33 - J32 * J23) -
98 J21 * (J12 * J33 - J32 * J13) +
99 J31 * (J12 * J23 - J22 * J13);
100 v(q,e) = W[q] * constant * detJ;
106 template<
const int T_D1D = 0,
108 static void PAVectorMassApply2D(
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;
120 MFEM_VERIFY(D1D <=
MAX_D1D,
"");
121 MFEM_VERIFY(Q1D <=
MAX_Q1D,
"");
129 const int D1D = T_D1D ? T_D1D : d1d;
130 const int Q1D = T_Q1D ? T_Q1D : q1d;
132 constexpr
int max_D1D = T_D1D ? T_D1D :
MAX_D1D;
133 constexpr
int max_Q1D = T_Q1D ? T_Q1D :
MAX_Q1D;
134 double sol_xy[max_Q1D][max_Q1D];
135 for (
int c = 0; c < VDIM; ++c)
137 for (
int qy = 0; qy < Q1D; ++qy)
139 for (
int qx = 0; qx < Q1D; ++qx)
141 sol_xy[qy][qx] = 0.0;
144 for (
int dy = 0; dy < D1D; ++dy)
146 double sol_x[max_Q1D];
147 for (
int qy = 0; qy < Q1D; ++qy)
151 for (
int dx = 0; dx < D1D; ++dx)
153 const double s = x(dx,dy,c,e);
154 for (
int qx = 0; qx < Q1D; ++qx)
156 sol_x[qx] += B(qx,dx)* s;
159 for (
int qy = 0; qy < Q1D; ++qy)
161 const double d2q = B(qy,dy);
162 for (
int qx = 0; qx < Q1D; ++qx)
164 sol_xy[qy][qx] += d2q * sol_x[qx];
168 for (
int qy = 0; qy < Q1D; ++qy)
170 for (
int qx = 0; qx < Q1D; ++qx)
172 sol_xy[qy][qx] *= op(qx,qy,e);
175 for (
int qy = 0; qy < Q1D; ++qy)
177 double sol_x[max_D1D];
178 for (
int dx = 0; dx < D1D; ++dx)
182 for (
int qx = 0; qx < Q1D; ++qx)
184 const double s = sol_xy[qy][qx];
185 for (
int dx = 0; dx < D1D; ++dx)
187 sol_x[dx] += Bt(dx,qx) * s;
190 for (
int dy = 0; dy < D1D; ++dy)
192 const double q2d = Bt(dy,qy);
193 for (
int dx = 0; dx < D1D; ++dx)
195 y(dx,dy,c,e) += q2d * sol_x[dx];
203 template<
const int T_D1D = 0,
205 static void PAVectorMassApply3D(
const int NE,
206 const Array<double> &_B,
207 const Array<double> &_Bt,
214 const int D1D = T_D1D ? T_D1D : d1d;
215 const int Q1D = T_Q1D ? T_Q1D : q1d;
216 constexpr
int VDIM = 3;
217 MFEM_VERIFY(D1D <=
MAX_D1D,
"");
218 MFEM_VERIFY(Q1D <=
MAX_Q1D,
"");
219 auto B =
Reshape(_B.Read(), Q1D, D1D);
220 auto Bt =
Reshape(_Bt.Read(), D1D, Q1D);
221 auto op =
Reshape(_op.Read(), Q1D, Q1D, Q1D, NE);
222 auto x =
Reshape(_x.Read(), D1D, D1D, D1D, VDIM, NE);
223 auto y =
Reshape(_y.ReadWrite(), D1D, D1D, D1D, VDIM, NE);
226 const int D1D = T_D1D ? T_D1D : d1d;
227 const int Q1D = T_Q1D ? T_Q1D : q1d;
228 constexpr
int max_D1D = T_D1D ? T_D1D :
MAX_D1D;
229 constexpr
int max_Q1D = T_Q1D ? T_Q1D :
MAX_Q1D;
230 double sol_xyz[max_Q1D][max_Q1D][max_Q1D];
231 for (
int c = 0; c < VDIM; ++ c)
233 for (
int qz = 0; qz < Q1D; ++qz)
235 for (
int qy = 0; qy < Q1D; ++qy)
237 for (
int qx = 0; qx < Q1D; ++qx)
239 sol_xyz[qz][qy][qx] = 0.0;
243 for (
int dz = 0; dz < D1D; ++dz)
245 double sol_xy[max_Q1D][max_Q1D];
246 for (
int qy = 0; qy < Q1D; ++qy)
248 for (
int qx = 0; qx < Q1D; ++qx)
250 sol_xy[qy][qx] = 0.0;
253 for (
int dy = 0; dy < D1D; ++dy)
255 double sol_x[max_Q1D];
256 for (
int qx = 0; qx < Q1D; ++qx)
260 for (
int dx = 0; dx < D1D; ++dx)
262 const double s = x(dx,dy,dz,c,e);
263 for (
int qx = 0; qx < Q1D; ++qx)
265 sol_x[qx] += B(qx,dx) * s;
268 for (
int qy = 0; qy < Q1D; ++qy)
270 const double wy = B(qy,dy);
271 for (
int qx = 0; qx < Q1D; ++qx)
273 sol_xy[qy][qx] += wy * sol_x[qx];
277 for (
int qz = 0; qz < Q1D; ++qz)
279 const double wz = B(qz,dz);
280 for (
int qy = 0; qy < Q1D; ++qy)
282 for (
int qx = 0; qx < Q1D; ++qx)
284 sol_xyz[qz][qy][qx] += wz * sol_xy[qy][qx];
289 for (
int qz = 0; qz < Q1D; ++qz)
291 for (
int qy = 0; qy < Q1D; ++qy)
293 for (
int qx = 0; qx < Q1D; ++qx)
295 sol_xyz[qz][qy][qx] *= op(qx,qy,qz,e);
299 for (
int qz = 0; qz < Q1D; ++qz)
301 double sol_xy[max_D1D][max_D1D];
302 for (
int dy = 0; dy < D1D; ++dy)
304 for (
int dx = 0; dx < D1D; ++dx)
309 for (
int qy = 0; qy < Q1D; ++qy)
311 double sol_x[max_D1D];
312 for (
int dx = 0; dx < D1D; ++dx)
316 for (
int qx = 0; qx < Q1D; ++qx)
318 const double s = sol_xyz[qz][qy][qx];
319 for (
int dx = 0; dx < D1D; ++dx)
321 sol_x[dx] += Bt(dx,qx) * s;
324 for (
int dy = 0; dy < D1D; ++dy)
326 const double wy = Bt(dy,qy);
327 for (
int dx = 0; dx < D1D; ++dx)
329 sol_xy[dy][dx] += wy * sol_x[dx];
333 for (
int dz = 0; dz < D1D; ++dz)
335 const double wz = Bt(dz,qz);
336 for (
int dy = 0; dy < D1D; ++dy)
338 for (
int dx = 0; dx < D1D; ++dx)
340 y(dx,dy,dz,c,e) += wz * sol_xy[dy][dx];
349 static void PAVectorMassApply(
const int dim,
353 const Array<double> &B,
354 const Array<double> &Bt,
361 return PAVectorMassApply2D(NE, B, Bt, op, x, y, D1D, Q1D);
365 return PAVectorMassApply3D(NE, B, Bt, op, x, y, D1D, Q1D);
367 MFEM_ABORT(
"Unknown kernel.");
372 if (DeviceCanUseCeed())
374 CeedAddMult(ceedDataPtr, x, y);
378 PAVectorMassApply(dim, dofs1D, quad1D, ne, maps->B, maps->Bt, pa_data, x, y);
382 template<const
int T_D1D = 0, const
int T_Q1D = 0>
383 static void PAVectorMassAssembleDiagonal2D(
const int NE,
391 const int D1D = T_D1D ? T_D1D : d1d;
392 const int Q1D = T_Q1D ? T_Q1D : q1d;
393 constexpr
int VDIM = 2;
394 MFEM_VERIFY(D1D <=
MAX_D1D,
"");
395 MFEM_VERIFY(Q1D <=
MAX_Q1D,
"");
401 const int D1D = T_D1D ? T_D1D : d1d;
402 const int Q1D = T_Q1D ? T_Q1D : q1d;
403 constexpr
int max_D1D = T_D1D ? T_D1D :
MAX_D1D;
404 constexpr
int max_Q1D = T_Q1D ? T_Q1D :
MAX_Q1D;
406 double temp[max_Q1D][max_D1D];
407 for (
int qx = 0; qx < Q1D; ++qx)
409 for (
int dy = 0; dy < D1D; ++dy)
412 for (
int qy = 0; qy < Q1D; ++qy)
414 temp[qx][dy] += B(qy, dy) * B(qy, dy) * op(qx, qy, e);
418 for (
int dy = 0; dy < D1D; ++dy)
420 for (
int dx = 0; dx < D1D; ++dx)
423 for (
int qx = 0; qx < Q1D; ++qx)
425 temp1 += B(qx, dx) * B(qx, dx) * temp[qx][dy];
427 y(dx, dy, 0, e) = temp1;
428 y(dx, dy, 1, e) = temp1;
434 template<const
int T_D1D = 0, const
int T_Q1D = 0>
435 static void PAVectorMassAssembleDiagonal3D(
const int NE,
436 const Array<double> &_B,
437 const Array<double> &_Bt,
443 const int D1D = T_D1D ? T_D1D : d1d;
444 const int Q1D = T_Q1D ? T_Q1D : q1d;
445 constexpr
int VDIM = 3;
446 MFEM_VERIFY(D1D <=
MAX_D1D,
"");
447 MFEM_VERIFY(Q1D <=
MAX_Q1D,
"");
448 auto B =
Reshape(_B.Read(), Q1D, D1D);
449 auto op =
Reshape(_op.Read(), Q1D, Q1D, Q1D, NE);
450 auto y =
Reshape(_diag.ReadWrite(), D1D, D1D, D1D, VDIM, NE);
453 const int D1D = T_D1D ? T_D1D : d1d;
454 const int Q1D = T_Q1D ? T_Q1D : q1d;
456 constexpr
int max_D1D = T_D1D ? T_D1D :
MAX_D1D;
457 constexpr
int max_Q1D = T_Q1D ? T_Q1D :
MAX_Q1D;
459 double temp[max_Q1D][max_Q1D][max_D1D];
460 for (
int qx = 0; qx < Q1D; ++qx)
462 for (
int qy = 0; qy < Q1D; ++qy)
464 for (
int dz = 0; dz < D1D; ++dz)
466 temp[qx][qy][dz] = 0.0;
467 for (
int qz = 0; qz < Q1D; ++qz)
469 temp[qx][qy][dz] += B(qz, dz) * B(qz, dz) * op(qx, qy, qz, e);
474 double temp2[max_Q1D][max_D1D][max_D1D];
475 for (
int qx = 0; qx < Q1D; ++qx)
477 for (
int dz = 0; dz < D1D; ++dz)
479 for (
int dy = 0; dy < D1D; ++dy)
481 temp2[qx][dy][dz] = 0.0;
482 for (
int qy = 0; qy < Q1D; ++qy)
484 temp2[qx][dy][dz] += B(qy, dy) * B(qy, dy) * temp[qx][qy][dz];
489 for (
int dz = 0; dz < D1D; ++dz)
491 for (
int dy = 0; dy < D1D; ++dy)
493 for (
int dx = 0; dx < D1D; ++dx)
496 for (
int qx = 0; qx < Q1D; ++qx)
498 temp3 += B(qx, dx) * B(qx, dx)
501 y(dx, dy, dz, 0, e) = temp3;
502 y(dx, dy, dz, 1, e) = temp3;
503 y(dx, dy, dz, 2, e) = temp3;
510 static void PAVectorMassAssembleDiagonal(
const int dim,
514 const Array<double> &B,
515 const Array<double> &Bt,
521 return PAVectorMassAssembleDiagonal2D(NE, B, Bt, op, y, D1D, Q1D);
525 return PAVectorMassAssembleDiagonal3D(NE, B, Bt, op, y, D1D, Q1D);
527 MFEM_ABORT(
"Dimension not implemented.");
530 void VectorMassIntegrator::AssembleDiagonalPA(
Vector &diag)
532 if (DeviceCanUseCeed())
534 CeedAssembleDiagonal(ceedDataPtr, diag);
538 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.
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.
const GeometricFactors * GetGeometricFactors(const IntegrationRule &ir, const int flags)
Return the mesh geometric factors corresponding to the given integration rule.
double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
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...
const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...