12 #include "../general/forall.hpp"
28 if (mesh->
GetNE() == 0) {
return; }
36 GeometricFactors::JACOBIANS);
43 if (
dim==1) { MFEM_ABORT(
"Not supported yet... stay tuned!"); }
46 double constant = 0.0;
53 MFEM_ABORT(
"Coefficient type not supported");
59 auto v =
Reshape(pa_data.Write(), NQ, NE);
62 for (
int q = 0; q < NQ; ++q)
64 const double J11 = J(q,0,0,e);
65 const double J12 = J(q,1,0,e);
66 const double J21 = J(q,0,1,e);
67 const double J22 = J(q,1,1,e);
68 const double detJ = (J11*J22)-(J21*J12);
69 v(q,e) = w[q] * constant * detJ;
75 double constant = 0.0;
82 MFEM_ABORT(
"Coefficient type not supported");
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;
107 static void OccaPAMassApply2D(
const int D1D,
116 occa::properties props;
117 props[
"defines/D1D"] = D1D;
118 props[
"defines/Q1D"] = Q1D;
124 const occa_id_t id = std::make_pair(D1D,Q1D);
125 if (!Device::Allows(Backend::OCCA_CUDA))
128 if (OccaMassApply2D_cpu.find(
id) == OccaMassApply2D_cpu.end())
130 const occa::kernel MassApply2D_CPU =
132 "MassApply2D_CPU", props);
133 OccaMassApply2D_cpu.emplace(
id, MassApply2D_CPU);
135 OccaMassApply2D_cpu.at(
id)(NE, o_B, o_Bt, o_op, o_x, o_y);
140 if (OccaMassApply2D_gpu.find(
id) == OccaMassApply2D_gpu.end())
142 const occa::kernel MassApply2D_GPU =
144 "MassApply2D_GPU", props);
145 OccaMassApply2D_gpu.emplace(
id, MassApply2D_GPU);
147 OccaMassApply2D_gpu.at(
id)(NE, o_B, o_Bt, o_op, o_x, o_y);
152 static void OccaPAMassApply3D(
const int D1D,
155 const Array<double> &B,
156 const Array<double> &Bt,
161 occa::properties props;
162 props[
"defines/D1D"] = D1D;
163 props[
"defines/Q1D"] = Q1D;
165 const occa::memory o_Bt =
OccaMemoryRead(Bt.GetMemory(), Bt.Size());
166 const occa::memory o_op =
OccaMemoryRead(op.GetMemory(), op.Size());
169 const occa_id_t id = std::make_pair(D1D,Q1D);
170 if (!Device::Allows(Backend::OCCA_CUDA))
173 if (OccaMassApply3D_cpu.find(
id) == OccaMassApply3D_cpu.end())
175 const occa::kernel MassApply3D_CPU =
177 "MassApply3D_CPU", props);
178 OccaMassApply3D_cpu.emplace(
id, MassApply3D_CPU);
180 OccaMassApply3D_cpu.at(
id)(NE, o_B, o_Bt, o_op, o_x, o_y);
185 if (OccaMassApply3D_gpu.find(
id) == OccaMassApply3D_gpu.end())
187 const occa::kernel MassApply3D_GPU =
189 "MassApply3D_GPU", props);
190 OccaMassApply3D_gpu.emplace(
id, MassApply3D_GPU);
192 OccaMassApply3D_gpu.at(
id)(NE, o_B, o_Bt, o_op, o_x, o_y);
195 #endif // MFEM_USE_OCCA
197 template<
const int T_D1D = 0,
199 static void PAMassApply2D(
const int NE,
200 const Array<double> &_B,
201 const Array<double> &_Bt,
208 const int D1D = T_D1D ? T_D1D : d1d;
209 const int Q1D = T_Q1D ? T_Q1D : q1d;
210 MFEM_VERIFY(D1D <=
MAX_D1D,
"");
211 MFEM_VERIFY(Q1D <=
MAX_Q1D,
"");
212 auto B =
Reshape(_B.Read(), Q1D, D1D);
213 auto Bt =
Reshape(_Bt.Read(), D1D, Q1D);
214 auto op =
Reshape(_op.Read(), Q1D, Q1D, NE);
215 auto x =
Reshape(_x.Read(), D1D, D1D, NE);
216 auto y =
Reshape(_y.ReadWrite(), D1D, D1D, NE);
219 const int D1D = T_D1D ? T_D1D : d1d;
220 const int Q1D = T_Q1D ? T_Q1D : q1d;
222 constexpr
int max_D1D = T_D1D ? T_D1D :
MAX_D1D;
223 constexpr
int max_Q1D = T_Q1D ? T_Q1D :
MAX_Q1D;
224 double sol_xy[max_Q1D][max_Q1D];
225 for (
int qy = 0; qy < Q1D; ++qy)
227 for (
int qx = 0; qx < Q1D; ++qx)
229 sol_xy[qy][qx] = 0.0;
232 for (
int dy = 0; dy < D1D; ++dy)
234 double sol_x[max_Q1D];
235 for (
int qy = 0; qy < Q1D; ++qy)
239 for (
int dx = 0; dx < D1D; ++dx)
241 const double s = x(dx,dy,e);
242 for (
int qx = 0; qx < Q1D; ++qx)
244 sol_x[qx] += B(qx,dx)* s;
247 for (
int qy = 0; qy < Q1D; ++qy)
249 const double d2q = B(qy,dy);
250 for (
int qx = 0; qx < Q1D; ++qx)
252 sol_xy[qy][qx] += d2q * sol_x[qx];
256 for (
int qy = 0; qy < Q1D; ++qy)
258 for (
int qx = 0; qx < Q1D; ++qx)
260 sol_xy[qy][qx] *= op(qx,qy,e);
263 for (
int qy = 0; qy < Q1D; ++qy)
265 double sol_x[max_D1D];
266 for (
int dx = 0; dx < D1D; ++dx)
270 for (
int qx = 0; qx < Q1D; ++qx)
272 const double s = sol_xy[qy][qx];
273 for (
int dx = 0; dx < D1D; ++dx)
275 sol_x[dx] += Bt(dx,qx) * s;
278 for (
int dy = 0; dy < D1D; ++dy)
280 const double q2d = Bt(dy,qy);
281 for (
int dx = 0; dx < D1D; ++dx)
283 y(dx,dy,e) += q2d * sol_x[dx];
290 template<
const int T_D1D = 0,
293 static void SmemPAMassApply2D(
const int NE,
294 const Array<double> &_b,
295 const Array<double> &_bt,
302 const int D1D = T_D1D ? T_D1D : d1d;
303 const int Q1D = T_Q1D ? T_Q1D : q1d;
304 constexpr
int NBZ = T_NBZ ? T_NBZ : 1;
305 constexpr
int MQ1 = T_Q1D ? T_Q1D :
MAX_Q1D;
306 constexpr
int MD1 = T_D1D ? T_D1D :
MAX_D1D;
307 MFEM_VERIFY(D1D <= MD1,
"");
308 MFEM_VERIFY(Q1D <= MQ1,
"");
309 auto b =
Reshape(_b.Read(), Q1D, D1D);
310 auto op =
Reshape(_op.Read(), Q1D, Q1D, NE);
311 auto x =
Reshape(_x.Read(), D1D, D1D, NE);
312 auto y =
Reshape(_y.ReadWrite(), D1D, D1D, NE);
313 MFEM_FORALL_2D(e, NE, Q1D, Q1D, NBZ,
315 const int tidz = MFEM_THREAD_ID(z);
316 const int D1D = T_D1D ? T_D1D : d1d;
317 const int Q1D = T_Q1D ? T_Q1D : q1d;
318 constexpr
int NBZ = T_NBZ ? T_NBZ : 1;
319 constexpr
int MQ1 = T_Q1D ? T_Q1D :
MAX_Q1D;
320 constexpr
int MD1 = T_D1D ? T_D1D :
MAX_D1D;
321 constexpr
int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
322 MFEM_SHARED
double BBt[MQ1*MD1];
323 double (*B)[MD1] = (double (*)[MD1]) BBt;
324 double (*Bt)[MQ1] = (double (*)[MQ1]) BBt;
325 MFEM_SHARED
double sm0[NBZ][MDQ*MDQ];
326 MFEM_SHARED
double sm1[NBZ][MDQ*MDQ];
327 double (*X)[MD1] = (double (*)[MD1]) (sm0 + tidz);
328 double (*DQ)[MQ1] = (double (*)[MQ1]) (sm1 + tidz);
329 double (*QQ)[MQ1] = (double (*)[MQ1]) (sm0 + tidz);
330 double (*QD)[MD1] = (double (*)[MD1]) (sm1 + tidz);
331 MFEM_FOREACH_THREAD(dy,y,D1D)
333 MFEM_FOREACH_THREAD(dx,x,D1D)
335 X[dy][dx] = x(dx,dy,e);
340 MFEM_FOREACH_THREAD(d,y,D1D)
342 MFEM_FOREACH_THREAD(q,x,Q1D)
349 MFEM_FOREACH_THREAD(dy,y,D1D)
351 MFEM_FOREACH_THREAD(qx,x,Q1D)
354 for (
int dx = 0; dx < D1D; ++dx)
356 dq += X[dy][dx] * B[qx][dx];
362 MFEM_FOREACH_THREAD(qy,y,Q1D)
364 MFEM_FOREACH_THREAD(qx,x,Q1D)
367 for (
int dy = 0; dy < D1D; ++dy)
369 qq += DQ[dy][qx] * B[qy][dy];
371 QQ[qy][qx] = qq * op(qx, qy, e);
377 MFEM_FOREACH_THREAD(d,y,D1D)
379 MFEM_FOREACH_THREAD(q,x,Q1D)
386 MFEM_FOREACH_THREAD(qy,y,Q1D)
388 MFEM_FOREACH_THREAD(dx,x,D1D)
391 for (
int qx = 0; qx < Q1D; ++qx)
393 dq += QQ[qy][qx] * Bt[dx][qx];
399 MFEM_FOREACH_THREAD(dy,y,D1D)
401 MFEM_FOREACH_THREAD(dx,x,D1D)
404 for (
int qy = 0; qy < Q1D; ++qy)
406 dd += (QD[qy][dx] * Bt[dy][qy]);
414 template<
const int T_D1D = 0,
416 static void PAMassApply3D(
const int NE,
417 const Array<double> &_B,
418 const Array<double> &_Bt,
425 const int D1D = T_D1D ? T_D1D : d1d;
426 const int Q1D = T_Q1D ? T_Q1D : q1d;
427 MFEM_VERIFY(D1D <=
MAX_D1D,
"");
428 MFEM_VERIFY(Q1D <=
MAX_Q1D,
"");
429 auto B =
Reshape(_B.Read(), Q1D, D1D);
430 auto Bt =
Reshape(_Bt.Read(), D1D, Q1D);
431 auto op =
Reshape(_op.Read(), Q1D, Q1D, Q1D, NE);
432 auto x =
Reshape(_x.Read(), D1D, D1D, D1D, NE);
433 auto y =
Reshape(_y.ReadWrite(), D1D, D1D, D1D, NE);
436 const int D1D = T_D1D ? T_D1D : d1d;
437 const int Q1D = T_Q1D ? T_Q1D : q1d;
438 constexpr
int max_D1D = T_D1D ? T_D1D :
MAX_D1D;
439 constexpr
int max_Q1D = T_Q1D ? T_Q1D :
MAX_Q1D;
440 double sol_xyz[max_Q1D][max_Q1D][max_Q1D];
441 for (
int qz = 0; qz < Q1D; ++qz)
443 for (
int qy = 0; qy < Q1D; ++qy)
445 for (
int qx = 0; qx < Q1D; ++qx)
447 sol_xyz[qz][qy][qx] = 0.0;
451 for (
int dz = 0; dz < D1D; ++dz)
453 double sol_xy[max_Q1D][max_Q1D];
454 for (
int qy = 0; qy < Q1D; ++qy)
456 for (
int qx = 0; qx < Q1D; ++qx)
458 sol_xy[qy][qx] = 0.0;
461 for (
int dy = 0; dy < D1D; ++dy)
463 double sol_x[max_Q1D];
464 for (
int qx = 0; qx < Q1D; ++qx)
468 for (
int dx = 0; dx < D1D; ++dx)
470 const double s = x(dx,dy,dz,e);
471 for (
int qx = 0; qx < Q1D; ++qx)
473 sol_x[qx] += B(qx,dx) * s;
476 for (
int qy = 0; qy < Q1D; ++qy)
478 const double wy = B(qy,dy);
479 for (
int qx = 0; qx < Q1D; ++qx)
481 sol_xy[qy][qx] += wy * sol_x[qx];
485 for (
int qz = 0; qz < Q1D; ++qz)
487 const double wz = B(qz,dz);
488 for (
int qy = 0; qy < Q1D; ++qy)
490 for (
int qx = 0; qx < Q1D; ++qx)
492 sol_xyz[qz][qy][qx] += wz * sol_xy[qy][qx];
497 for (
int qz = 0; qz < Q1D; ++qz)
499 for (
int qy = 0; qy < Q1D; ++qy)
501 for (
int qx = 0; qx < Q1D; ++qx)
503 sol_xyz[qz][qy][qx] *= op(qx,qy,qz,e);
507 for (
int qz = 0; qz < Q1D; ++qz)
509 double sol_xy[max_D1D][max_D1D];
510 for (
int dy = 0; dy < D1D; ++dy)
512 for (
int dx = 0; dx < D1D; ++dx)
517 for (
int qy = 0; qy < Q1D; ++qy)
519 double sol_x[max_D1D];
520 for (
int dx = 0; dx < D1D; ++dx)
524 for (
int qx = 0; qx < Q1D; ++qx)
526 const double s = sol_xyz[qz][qy][qx];
527 for (
int dx = 0; dx < D1D; ++dx)
529 sol_x[dx] += Bt(dx,qx) * s;
532 for (
int dy = 0; dy < D1D; ++dy)
534 const double wy = Bt(dy,qy);
535 for (
int dx = 0; dx < D1D; ++dx)
537 sol_xy[dy][dx] += wy * sol_x[dx];
541 for (
int dz = 0; dz < D1D; ++dz)
543 const double wz = Bt(dz,qz);
544 for (
int dy = 0; dy < D1D; ++dy)
546 for (
int dx = 0; dx < D1D; ++dx)
548 y(dx,dy,dz,e) += wz * sol_xy[dy][dx];
556 template<
const int T_D1D = 0,
558 static void SmemPAMassApply3D(
const int NE,
559 const Array<double> &_b,
560 const Array<double> &_bt,
567 const int D1D = T_D1D ? T_D1D : d1d;
568 const int Q1D = T_Q1D ? T_Q1D : q1d;
569 constexpr
int M1Q = T_Q1D ? T_Q1D :
MAX_Q1D;
570 constexpr
int M1D = T_D1D ? T_D1D :
MAX_D1D;
571 MFEM_VERIFY(D1D <= M1D,
"");
572 MFEM_VERIFY(Q1D <= M1Q,
"");
573 auto b =
Reshape(_b.Read(), Q1D, D1D);
574 auto op =
Reshape(_op.Read(), Q1D, Q1D, Q1D, NE);
575 auto x =
Reshape(_x.Read(), D1D, D1D, D1D, NE);
576 auto y =
Reshape(_y.ReadWrite(), D1D, D1D, D1D, NE);
577 MFEM_FORALL_3D(e, NE, Q1D, Q1D, Q1D,
579 const int tidz = MFEM_THREAD_ID(z);
580 const int D1D = T_D1D ? T_D1D : d1d;
581 const int Q1D = T_Q1D ? T_Q1D : q1d;
582 constexpr
int MQ1 = T_Q1D ? T_Q1D :
MAX_Q1D;
583 constexpr
int MD1 = T_D1D ? T_D1D :
MAX_D1D;
584 constexpr
int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
585 MFEM_SHARED
double sDQ[MQ1*MD1];
586 double (*B)[MD1] = (double (*)[MD1]) sDQ;
587 double (*Bt)[MQ1] = (double (*)[MQ1]) sDQ;
588 MFEM_SHARED
double sm0[MDQ*MDQ*MDQ];
589 MFEM_SHARED
double sm1[MDQ*MDQ*MDQ];
590 double (*X)[MD1][MD1] = (double (*)[MD1][MD1]) sm0;
591 double (*DDQ)[MD1][MQ1] = (double (*)[MD1][MQ1]) sm1;
592 double (*DQQ)[MQ1][MQ1] = (double (*)[MQ1][MQ1]) sm0;
593 double (*QQQ)[MQ1][MQ1] = (double (*)[MQ1][MQ1]) sm1;
594 double (*QQD)[MQ1][MD1] = (double (*)[MQ1][MD1]) sm0;
595 double (*QDD)[MD1][MD1] = (double (*)[MD1][MD1]) sm1;
596 MFEM_FOREACH_THREAD(dz,z,D1D)
598 MFEM_FOREACH_THREAD(dy,y,D1D)
600 MFEM_FOREACH_THREAD(dx,x,D1D)
602 X[dz][dy][dx] = x(dx,dy,dz,e);
608 MFEM_FOREACH_THREAD(d,y,D1D)
610 MFEM_FOREACH_THREAD(q,x,Q1D)
617 MFEM_FOREACH_THREAD(dz,z,D1D)
619 MFEM_FOREACH_THREAD(dy,y,D1D)
621 MFEM_FOREACH_THREAD(qx,x,Q1D)
624 for (
int dx = 0; dx < D1D; ++dx)
626 u += X[dz][dy][dx] * B[qx][dx];
633 MFEM_FOREACH_THREAD(dz,z,D1D)
635 MFEM_FOREACH_THREAD(qy,y,Q1D)
637 MFEM_FOREACH_THREAD(qx,x,Q1D)
640 for (
int dy = 0; dy < D1D; ++dy)
642 u += DDQ[dz][dy][qx] * B[qy][dy];
649 MFEM_FOREACH_THREAD(qz,z,Q1D)
651 MFEM_FOREACH_THREAD(qy,y,Q1D)
653 MFEM_FOREACH_THREAD(qx,x,Q1D)
656 for (
int dz = 0; dz < D1D; ++dz)
658 u += DQQ[dz][qy][qx] * B[qz][dz];
660 QQQ[qz][qy][qx] = u * op(qx,qy,qz,e);
667 MFEM_FOREACH_THREAD(d,y,D1D)
669 MFEM_FOREACH_THREAD(q,x,Q1D)
676 MFEM_FOREACH_THREAD(qz,z,Q1D)
678 MFEM_FOREACH_THREAD(qy,y,Q1D)
680 MFEM_FOREACH_THREAD(dx,x,D1D)
683 for (
int qx = 0; qx < Q1D; ++qx)
685 u += QQQ[qz][qy][qx] * Bt[dx][qx];
692 MFEM_FOREACH_THREAD(qz,z,Q1D)
694 MFEM_FOREACH_THREAD(dy,y,D1D)
696 MFEM_FOREACH_THREAD(dx,x,D1D)
699 for (
int qy = 0; qy < Q1D; ++qy)
701 u += QQD[qz][qy][dx] * Bt[dy][qy];
708 MFEM_FOREACH_THREAD(dz,z,D1D)
710 MFEM_FOREACH_THREAD(dy,y,D1D)
712 MFEM_FOREACH_THREAD(dx,x,D1D)
715 for (
int qz = 0; qz < Q1D; ++qz)
717 u += QDD[qz][dy][dx] * Bt[dz][qz];
726 static void PAMassApply(
const int dim,
730 const Array<double> &B,
731 const Array<double> &Bt,
741 OccaPAMassApply2D(D1D, Q1D, NE, B, Bt, op, x, y);
746 OccaPAMassApply3D(D1D, Q1D, NE, B, Bt, op, x, y);
749 MFEM_ABORT(
"OCCA PA Mass Apply unknown kernel!");
751 #endif // MFEM_USE_OCCA
753 if (Device::Allows(Backend::RAJA_CUDA))
757 switch ((D1D << 4 ) | Q1D)
759 case 0x22:
return PAMassApply2D<2,2>(NE, B, Bt, op, x, y);
760 case 0x33:
return PAMassApply2D<3,3>(NE, B, Bt, op, x, y);
761 case 0x44:
return PAMassApply2D<4,4>(NE, B, Bt, op, x, y);
762 case 0x55:
return PAMassApply2D<5,5>(NE, B, Bt, op, x, y);
763 case 0x66:
return PAMassApply2D<6,6>(NE, B, Bt, op, x, y);
764 case 0x77:
return PAMassApply2D<7,7>(NE, B, Bt, op, x, y);
765 case 0x88:
return PAMassApply2D<8,8>(NE, B, Bt, op, x, y);
766 case 0x99:
return PAMassApply2D<9,9>(NE, B, Bt, op, x, y);
767 default:
return PAMassApply2D(NE, B, Bt, op, x, y, D1D, Q1D);
772 switch ((D1D << 4 ) | Q1D)
774 case 0x23:
return PAMassApply3D<2,3>(NE, B, Bt, op, x, y);
775 case 0x34:
return PAMassApply3D<3,4>(NE, B, Bt, op, x, y);
776 case 0x45:
return PAMassApply3D<4,5>(NE, B, Bt, op, x, y);
777 case 0x56:
return PAMassApply3D<5,6>(NE, B, Bt, op, x, y);
778 case 0x67:
return PAMassApply3D<6,7>(NE, B, Bt, op, x, y);
779 case 0x78:
return PAMassApply3D<7,8>(NE, B, Bt, op, x, y);
780 case 0x89:
return PAMassApply3D<8,9>(NE, B, Bt, op, x, y);
781 default:
return PAMassApply3D(NE, B, Bt, op, x, y, D1D, Q1D);
787 switch ((D1D << 4 ) | Q1D)
789 case 0x22:
return SmemPAMassApply2D<2,2,16>(NE, B, Bt, op, x, y);
790 case 0x33:
return SmemPAMassApply2D<3,3,16>(NE, B, Bt, op, x, y);
791 case 0x44:
return SmemPAMassApply2D<4,4,8>(NE, B, Bt, op, x, y);
792 case 0x55:
return SmemPAMassApply2D<5,5,8>(NE, B, Bt, op, x, y);
793 case 0x66:
return SmemPAMassApply2D<6,6,4>(NE, B, Bt, op, x, y);
794 case 0x77:
return SmemPAMassApply2D<7,7,4>(NE, B, Bt, op, x, y);
795 case 0x88:
return SmemPAMassApply2D<8,8,2>(NE, B, Bt, op, x, y);
796 case 0x99:
return SmemPAMassApply2D<9,9,2>(NE, B, Bt, op, x, y);
797 default:
return PAMassApply2D(NE, B, Bt, op, x, y, D1D, Q1D);
802 switch ((D1D << 4 ) | Q1D)
804 case 0x23:
return SmemPAMassApply3D<2,3>(NE, B, Bt, op, x, y);
805 case 0x34:
return SmemPAMassApply3D<3,4>(NE, B, Bt, op, x, y);
806 case 0x45:
return SmemPAMassApply3D<4,5>(NE, B, Bt, op, x, y);
807 case 0x56:
return SmemPAMassApply3D<5,6>(NE, B, Bt, op, x, y);
808 case 0x67:
return SmemPAMassApply3D<6,7>(NE, B, Bt, op, x, y);
809 case 0x78:
return SmemPAMassApply3D<7,8>(NE, B, Bt, op, x, y);
810 case 0x89:
return SmemPAMassApply3D<8,9>(NE, B, Bt, op, x, y);
811 default:
return PAMassApply3D(NE, B, Bt, op, x, y, D1D, Q1D);
814 MFEM_ABORT(
"Unknown kernel.");
819 PAMassApply(dim, dofs1D, quad1D, ne, maps->B, maps->Bt, pa_data, x, y);
int GetNPoints() const
Returns the number of the points in the integration rule.
Abstract class for Finite Elements.
int Size() const
Logical size of the array.
Class for an integration rule - an Array of IntegrationPoint.
Memory< T > & GetMemory()
Return a reference to the Memory object used by the Array.
Subclass constant coefficient.
occa::device & OccaDev()
Return the default occa::device used by MFEM.
int Size() const
Returns the size of the vector.
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.
std::map< occa_id_t, occa::kernel > occa_kernel_t
Memory< double > & GetMemory()
Return a reference to the Memory object used by the Vector.
occa::memory OccaMemoryReadWrite(Memory< T > &mem, size_t size)
Wrap a Memory object as occa::memory for read-write access with the mfem::Device MemoryClass. The returned occa::memory is associated with the default occa::device used by MFEM.
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.
Mesh * GetMesh() const
Returns the mesh.
bool DeviceCanUseOcca()
Function that determines if an OCCA kernel should be used, based on the current mfem::Device configur...
const occa::memory OccaMemoryRead(const Memory< T > &mem, size_t size)
Wrap a Memory object as occa::memory for read only access with the mfem::Device MemoryClass. The returned occa::memory is associated with the default occa::device used by MFEM.
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
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
MemoryType GetMemoryType(MemoryClass mc)
Return a suitable MemoryType for a given MemoryClass.
const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement associated with i'th element.
std::pair< int, int > occa_id_t