12 #include "../general/forall.hpp"
28 if (mesh->
GetNE() == 0) {
return; }
32 = IntRule ? IntRule : &MassIntegrator::GetRule(el, el, *T);
37 GeometricFactors::JACOBIANS);
41 pa_data.SetSize(ne*nq, Device::GetDeviceMemoryType());
46 MFEM_VERIFY(cQ != NULL,
"Only ConstantCoefficient is supported.");
49 if (!(
dim == 2 ||
dim == 3))
51 MFEM_ABORT(
"Dimension not supported.");
55 const double constant = coeff;
60 auto v =
Reshape(pa_data.Write(), NQ, NE);
63 for (
int q = 0; q < NQ; ++q)
65 const double J11 = J(q,0,0,e);
66 const double J12 = J(q,1,0,e);
67 const double J21 = J(q,0,1,e);
68 const double J22 = J(q,1,1,e);
69 const double detJ = (J11*J22)-(J21*J12);
70 v(q,e) = w[q] * constant * detJ;
76 const double constant = coeff;
81 auto v =
Reshape(pa_data.Write(), NQ,NE);
84 for (
int q = 0; q < NQ; ++q)
86 const double J11 = J(q,0,0,e), J12 = J(q,0,1,e), J13 = J(q,0,2,e);
87 const double J21 = J(q,1,0,e), J22 = J(q,1,1,e), J23 = J(q,1,2,e);
88 const double J31 = J(q,2,0,e), J32 = J(q,2,1,e), J33 = J(q,2,2,e);
89 const double detJ = J11 * (J22 * J33 - J32 * J23) -
90 J21 * (J12 * J33 - J32 * J13) +
91 J31 * (J12 * J23 - J22 * J13);
92 v(q,e) = W[q] * constant * detJ;
98 template<
const int T_D1D = 0,
100 static void PAVectorMassApply2D(
const int NE,
109 const int D1D = T_D1D ? T_D1D : d1d;
110 const int Q1D = T_Q1D ? T_Q1D : q1d;
111 constexpr
int VDIM = 2;
112 MFEM_VERIFY(D1D <=
MAX_D1D,
"");
113 MFEM_VERIFY(Q1D <=
MAX_Q1D,
"");
121 const int D1D = T_D1D ? T_D1D : d1d;
122 const int Q1D = T_Q1D ? T_Q1D : q1d;
124 constexpr
int max_D1D = T_D1D ? T_D1D :
MAX_D1D;
125 constexpr
int max_Q1D = T_Q1D ? T_Q1D :
MAX_Q1D;
126 double sol_xy[max_Q1D][max_Q1D];
127 for (
int c = 0; c < VDIM; ++c)
129 for (
int qy = 0; qy < Q1D; ++qy)
131 for (
int qx = 0; qx < Q1D; ++qx)
133 sol_xy[qy][qx] = 0.0;
136 for (
int dy = 0; dy < D1D; ++dy)
138 double sol_x[max_Q1D];
139 for (
int qy = 0; qy < Q1D; ++qy)
143 for (
int dx = 0; dx < D1D; ++dx)
145 const double s = x(dx,dy,c,e);
146 for (
int qx = 0; qx < Q1D; ++qx)
148 sol_x[qx] += B(qx,dx)* s;
151 for (
int qy = 0; qy < Q1D; ++qy)
153 const double d2q = B(qy,dy);
154 for (
int qx = 0; qx < Q1D; ++qx)
156 sol_xy[qy][qx] += d2q * sol_x[qx];
160 for (
int qy = 0; qy < Q1D; ++qy)
162 for (
int qx = 0; qx < Q1D; ++qx)
164 sol_xy[qy][qx] *= op(qx,qy,e);
167 for (
int qy = 0; qy < Q1D; ++qy)
169 double sol_x[max_D1D];
170 for (
int dx = 0; dx < D1D; ++dx)
174 for (
int qx = 0; qx < Q1D; ++qx)
176 const double s = sol_xy[qy][qx];
177 for (
int dx = 0; dx < D1D; ++dx)
179 sol_x[dx] += Bt(dx,qx) * s;
182 for (
int dy = 0; dy < D1D; ++dy)
184 const double q2d = Bt(dy,qy);
185 for (
int dx = 0; dx < D1D; ++dx)
187 y(dx,dy,c,e) += q2d * sol_x[dx];
195 template<
const int T_D1D = 0,
197 static void PAVectorMassApply3D(
const int NE,
198 const Array<double> &_B,
199 const Array<double> &_Bt,
206 const int D1D = T_D1D ? T_D1D : d1d;
207 const int Q1D = T_Q1D ? T_Q1D : q1d;
208 constexpr
int VDIM = 3;
209 MFEM_VERIFY(D1D <=
MAX_D1D,
"");
210 MFEM_VERIFY(Q1D <=
MAX_Q1D,
"");
211 auto B =
Reshape(_B.Read(), Q1D, D1D);
212 auto Bt =
Reshape(_Bt.Read(), D1D, Q1D);
213 auto op =
Reshape(_op.Read(), Q1D, Q1D, Q1D, NE);
214 auto x =
Reshape(_x.Read(), D1D, D1D, D1D, VDIM, NE);
215 auto y =
Reshape(_y.ReadWrite(), D1D, D1D, D1D, VDIM, NE);
218 const int D1D = T_D1D ? T_D1D : d1d;
219 const int Q1D = T_Q1D ? T_Q1D : q1d;
220 constexpr
int max_D1D = T_D1D ? T_D1D :
MAX_D1D;
221 constexpr
int max_Q1D = T_Q1D ? T_Q1D :
MAX_Q1D;
222 double sol_xyz[max_Q1D][max_Q1D][max_Q1D];
223 for (
int c = 0; c < VDIM; ++ c)
225 for (
int qz = 0; qz < Q1D; ++qz)
227 for (
int qy = 0; qy < Q1D; ++qy)
229 for (
int qx = 0; qx < Q1D; ++qx)
231 sol_xyz[qz][qy][qx] = 0.0;
235 for (
int dz = 0; dz < D1D; ++dz)
237 double sol_xy[max_Q1D][max_Q1D];
238 for (
int qy = 0; qy < Q1D; ++qy)
240 for (
int qx = 0; qx < Q1D; ++qx)
242 sol_xy[qy][qx] = 0.0;
245 for (
int dy = 0; dy < D1D; ++dy)
247 double sol_x[max_Q1D];
248 for (
int qx = 0; qx < Q1D; ++qx)
252 for (
int dx = 0; dx < D1D; ++dx)
254 const double s = x(dx,dy,dz,c,e);
255 for (
int qx = 0; qx < Q1D; ++qx)
257 sol_x[qx] += B(qx,dx) * s;
260 for (
int qy = 0; qy < Q1D; ++qy)
262 const double wy = B(qy,dy);
263 for (
int qx = 0; qx < Q1D; ++qx)
265 sol_xy[qy][qx] += wy * sol_x[qx];
269 for (
int qz = 0; qz < Q1D; ++qz)
271 const double wz = B(qz,dz);
272 for (
int qy = 0; qy < Q1D; ++qy)
274 for (
int qx = 0; qx < Q1D; ++qx)
276 sol_xyz[qz][qy][qx] += wz * sol_xy[qy][qx];
281 for (
int qz = 0; qz < Q1D; ++qz)
283 for (
int qy = 0; qy < Q1D; ++qy)
285 for (
int qx = 0; qx < Q1D; ++qx)
287 sol_xyz[qz][qy][qx] *= op(qx,qy,qz,e);
291 for (
int qz = 0; qz < Q1D; ++qz)
293 double sol_xy[max_D1D][max_D1D];
294 for (
int dy = 0; dy < D1D; ++dy)
296 for (
int dx = 0; dx < D1D; ++dx)
301 for (
int qy = 0; qy < Q1D; ++qy)
303 double sol_x[max_D1D];
304 for (
int dx = 0; dx < D1D; ++dx)
308 for (
int qx = 0; qx < Q1D; ++qx)
310 const double s = sol_xyz[qz][qy][qx];
311 for (
int dx = 0; dx < D1D; ++dx)
313 sol_x[dx] += Bt(dx,qx) * s;
316 for (
int dy = 0; dy < D1D; ++dy)
318 const double wy = Bt(dy,qy);
319 for (
int dx = 0; dx < D1D; ++dx)
321 sol_xy[dy][dx] += wy * sol_x[dx];
325 for (
int dz = 0; dz < D1D; ++dz)
327 const double wz = Bt(dz,qz);
328 for (
int dy = 0; dy < D1D; ++dy)
330 for (
int dx = 0; dx < D1D; ++dx)
332 y(dx,dy,dz,c,e) += wz * sol_xy[dy][dx];
341 static void PAVectorMassApply(
const int dim,
345 const Array<double> &B,
346 const Array<double> &Bt,
353 return PAVectorMassApply2D(NE, B, Bt, op, x, y, D1D, Q1D);
357 return PAVectorMassApply3D(NE, B, Bt, op, x, y, D1D, Q1D);
359 MFEM_ABORT(
"Unknown kernel.");
364 PAVectorMassApply(dim, dofs1D, quad1D, ne, maps->B, maps->Bt, pa_data, x, y);
367 template<const
int T_D1D = 0, const
int T_Q1D = 0>
368 static void PAVectorMassAssembleDiagonal2D(
const int NE,
376 const int D1D = T_D1D ? T_D1D : d1d;
377 const int Q1D = T_Q1D ? T_Q1D : q1d;
378 constexpr
int VDIM = 2;
379 MFEM_VERIFY(D1D <=
MAX_D1D,
"");
380 MFEM_VERIFY(Q1D <=
MAX_Q1D,
"");
386 const int D1D = T_D1D ? T_D1D : d1d;
387 const int Q1D = T_Q1D ? T_Q1D : q1d;
388 constexpr
int max_D1D = T_D1D ? T_D1D :
MAX_D1D;
389 constexpr
int max_Q1D = T_Q1D ? T_Q1D :
MAX_Q1D;
391 double temp[max_Q1D][max_D1D];
392 for (
int qx = 0; qx < Q1D; ++qx)
394 for (
int dy = 0; dy < D1D; ++dy)
397 for (
int qy = 0; qy < Q1D; ++qy)
399 temp[qx][dy] += B(qy, dy) * B(qy, dy) * op(qx, qy, e);
403 for (
int dy = 0; dy < D1D; ++dy)
405 for (
int dx = 0; dx < D1D; ++dx)
408 for (
int qx = 0; qx < Q1D; ++qx)
410 temp1 += B(qx, dx) * B(qx, dx) * temp[qx][dy];
412 y(dx, dy, 0, e) = temp1;
413 y(dx, dy, 1, e) = temp1;
419 template<const
int T_D1D = 0, const
int T_Q1D = 0>
420 static void PAVectorMassAssembleDiagonal3D(
const int NE,
421 const Array<double> &_B,
422 const Array<double> &_Bt,
428 const int D1D = T_D1D ? T_D1D : d1d;
429 const int Q1D = T_Q1D ? T_Q1D : q1d;
430 constexpr
int VDIM = 3;
431 MFEM_VERIFY(D1D <=
MAX_D1D,
"");
432 MFEM_VERIFY(Q1D <=
MAX_Q1D,
"");
433 auto B =
Reshape(_B.Read(), Q1D, D1D);
434 auto op =
Reshape(_op.Read(), Q1D, Q1D, Q1D, NE);
435 auto y =
Reshape(_diag.ReadWrite(), D1D, D1D, D1D, VDIM, NE);
438 const int D1D = T_D1D ? T_D1D : d1d;
439 const int Q1D = T_Q1D ? T_Q1D : q1d;
441 constexpr
int max_D1D = T_D1D ? T_D1D :
MAX_D1D;
442 constexpr
int max_Q1D = T_Q1D ? T_Q1D :
MAX_Q1D;
444 double temp[max_Q1D][max_Q1D][max_D1D];
445 for (
int qx = 0; qx < Q1D; ++qx)
447 for (
int qy = 0; qy < Q1D; ++qy)
449 for (
int dz = 0; dz < D1D; ++dz)
451 temp[qx][qy][dz] = 0.0;
452 for (
int qz = 0; qz < Q1D; ++qz)
454 temp[qx][qy][dz] += B(qz, dz) * B(qz, dz) * op(qx, qy, qz, e);
459 double temp2[max_Q1D][max_D1D][max_D1D];
460 for (
int qx = 0; qx < Q1D; ++qx)
462 for (
int dz = 0; dz < D1D; ++dz)
464 for (
int dy = 0; dy < D1D; ++dy)
466 temp2[qx][dy][dz] = 0.0;
467 for (
int qy = 0; qy < Q1D; ++qy)
469 temp2[qx][dy][dz] += B(qy, dy) * B(qy, dy) * temp[qx][qy][dz];
474 for (
int dz = 0; dz < D1D; ++dz)
476 for (
int dy = 0; dy < D1D; ++dy)
478 for (
int dx = 0; dx < D1D; ++dx)
481 for (
int qx = 0; qx < Q1D; ++qx)
483 temp3 += B(qx, dx) * B(qx, dx)
486 y(dx, dy, dz, 0, e) = temp3;
487 y(dx, dy, dz, 1, e) = temp3;
488 y(dx, dy, dz, 2, e) = temp3;
495 static void PAVectorMassAssembleDiagonal(
const int dim,
499 const Array<double> &B,
500 const Array<double> &Bt,
506 return PAVectorMassAssembleDiagonal2D(NE, B, Bt, op, y, D1D, Q1D);
510 return PAVectorMassAssembleDiagonal3D(NE, B, Bt, op, y, D1D, Q1D);
512 MFEM_ABORT(
"Dimension not implemented.");
515 void VectorMassIntegrator::AssembleDiagonalPA(
Vector &diag)
517 PAVectorMassAssembleDiagonal(dim,
int GetNPoints() const
Returns the number of the points in the integration rule.
Abstract class for Finite Elements.
Class for an integration rule - an Array of IntegrationPoint.
Subclass constant coefficient.
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
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 associated with i'th element.