12#ifndef MFEM_BILININTEG_DGDIFFUSION_KERNELS_HPP
13#define MFEM_BILININTEG_DGDIFFUSION_KERNELS_HPP
28template <
int T_D1D = 0,
int T_Q1D = 0>
29void PADGDiffusionApply2D(
const int NF,
const Array<real_t> &
b,
30 const Array<real_t> &bt,
const Array<real_t> &g,
32 const Vector &pa_data,
const Vector &x_,
33 const Vector &dxdn_, Vector &y_, Vector &dydn_,
34 const int d1d = 0,
const int q1d = 0)
36 const int D1D = T_D1D ? T_D1D : d1d;
37 const int Q1D = T_Q1D ? T_Q1D : q1d;
41 auto B_ =
Reshape(
b.Read(), Q1D, D1D);
42 auto G_ =
Reshape(g.Read(), Q1D, D1D);
45 Reshape(pa_data.Read(), 6, Q1D, NF);
47 auto x =
Reshape(x_.Read(), D1D, 2, NF);
48 auto y =
Reshape(y_.ReadWrite(), D1D, 2, NF);
49 auto dxdn =
Reshape(dxdn_.Read(), D1D, 2, NF);
50 auto dydn =
Reshape(dydn_.ReadWrite(), D1D, 2, NF);
52 const int NBX = std::max(D1D, Q1D);
56 constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
57 constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
59 MFEM_SHARED
real_t u0[max_D1D];
60 MFEM_SHARED
real_t u1[max_D1D];
61 MFEM_SHARED
real_t du0[max_D1D];
62 MFEM_SHARED
real_t du1[max_D1D];
64 MFEM_SHARED
real_t Bu0[max_Q1D];
65 MFEM_SHARED
real_t Bu1[max_Q1D];
66 MFEM_SHARED
real_t Bdu0[max_Q1D];
67 MFEM_SHARED
real_t Bdu1[max_Q1D];
69 MFEM_SHARED
real_t r[max_Q1D];
71 MFEM_SHARED
real_t BG[2 * max_D1D * max_Q1D];
75 if (MFEM_THREAD_ID(y) == 0)
77 MFEM_FOREACH_THREAD(
p, x, Q1D)
79 for (
int d = 0; d < D1D; ++d)
89 MFEM_FOREACH_THREAD(side, y, 2)
91 real_t *
u = (side == 0) ? u0 : u1;
92 real_t *du = (side == 0) ? du0 : du1;
93 MFEM_FOREACH_THREAD(d, x, D1D)
96 du[d] = dxdn(d, side,
f);
102 MFEM_FOREACH_THREAD(side, y, 2)
104 real_t *
u = (side == 0) ? u0 : u1;
105 real_t *du = (side == 0) ? du0 : du1;
106 real_t *Bu = (side == 0) ? Bu0 : Bu1;
107 real_t *Bdu = (side == 0) ? Bdu0 : Bdu1;
109 MFEM_FOREACH_THREAD(
p, x, Q1D)
111 const real_t Je_side[] = {pa(2 + 2 * side,
p,
f),
112 pa(2 + 2 * side + 1,
p,
f)
118 for (
int d = 0; d < D1D; ++d)
124 Bdu[
p] += Je_side[0] *
b * du[d] + Je_side[1] * g *
u[d];
131 if (MFEM_THREAD_ID(y) == 0)
133 MFEM_FOREACH_THREAD(
p, x, Q1D)
137 const real_t jump = Bu0[
p] - Bu1[
p];
138 const real_t avg = Bdu0[
p] + Bdu1[
p];
139 r[
p] = -avg + hi * q * jump;
144 MFEM_FOREACH_THREAD(d, x, D1D)
148 for (
int p = 0;
p < Q1D; ++
p)
150 Br += B(
p, d) * r[
p];
158 MFEM_FOREACH_THREAD(side, y, 2)
160 real_t *du = (side == 0) ? du0 : du1;
161 MFEM_FOREACH_THREAD(d, x, D1D) { du[d] = 0.0; }
166 MFEM_FOREACH_THREAD(side, y, 2)
168 real_t *
const du = (side == 0) ? du0 : du1;
169 real_t *
const u = (side == 0) ? u0 : u1;
171 MFEM_FOREACH_THREAD(d, x, D1D)
173 for (
int p = 0;
p < Q1D; ++
p)
175 const real_t Je[] = {pa(2 + 2 * side,
p,
f),
176 pa(2 + 2 * side + 1,
p,
f)
178 const real_t jump = Bu0[
p] - Bu1[
p];
179 const real_t r_p = Je[0] * jump;
180 const real_t w_p = Je[1] * jump;
181 du[d] +=
sigma * B(
p, d) * r_p;
188 MFEM_FOREACH_THREAD(side, y, 2)
190 real_t *
u = (side == 0) ? u0 : u1;
191 real_t *du = (side == 0) ? du0 : du1;
192 MFEM_FOREACH_THREAD(d, x, D1D)
194 y(d, side,
f) +=
u[d];
195 dydn(d, side,
f) += du[d];
201template <
int T_D1D = 0,
int T_Q1D = 0>
202void PADGDiffusionApply3D(
const int NF,
const Array<real_t> &
b,
203 const Array<real_t> &bt,
const Array<real_t> &g,
205 const Vector &pa_data,
const Vector &x_,
206 const Vector &dxdn_, Vector &y_, Vector &dydn_,
207 const int d1d = 0,
const int q1d = 0)
209 const int D1D = T_D1D ? T_D1D : d1d;
210 const int Q1D = T_Q1D ? T_Q1D : q1d;
214 auto B_ =
Reshape(
b.Read(), Q1D, D1D);
215 auto G_ =
Reshape(g.Read(), Q1D, D1D);
218 auto pa =
Reshape(pa_data.Read(), 7, Q1D, Q1D, NF);
220 auto x =
Reshape(x_.Read(), D1D, D1D, 2, NF);
221 auto y =
Reshape(y_.ReadWrite(), D1D, D1D, 2, NF);
222 auto dxdn =
Reshape(dxdn_.Read(), D1D, D1D, 2, NF);
223 auto dydn =
Reshape(dydn_.ReadWrite(), D1D, D1D, 2, NF);
225 const int NBX = std::max(D1D, Q1D);
229 constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
230 constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
232 MFEM_SHARED
real_t u0[max_Q1D][max_Q1D];
233 MFEM_SHARED
real_t u1[max_Q1D][max_Q1D];
235 MFEM_SHARED
real_t du0[max_Q1D][max_Q1D];
236 MFEM_SHARED
real_t du1[max_Q1D][max_Q1D];
238 MFEM_SHARED
real_t Gu0[max_Q1D][max_Q1D];
239 MFEM_SHARED
real_t Gu1[max_Q1D][max_Q1D];
241 MFEM_SHARED
real_t Bu0[max_Q1D][max_Q1D];
242 MFEM_SHARED
real_t Bu1[max_Q1D][max_Q1D];
244 MFEM_SHARED
real_t Bdu0[max_Q1D][max_Q1D];
245 MFEM_SHARED
real_t Bdu1[max_Q1D][max_Q1D];
247 MFEM_SHARED
real_t kappa_Qh[max_Q1D][max_Q1D];
249 MFEM_SHARED
real_t nJe[2][max_Q1D][max_Q1D][3];
250 MFEM_SHARED
real_t BG[2 * max_D1D * max_Q1D];
253 real_t(*Bj0)[max_Q1D] = Bu0;
254 real_t(*Bj1)[max_Q1D] = Bu1;
255 real_t(*Bjn0)[max_Q1D] = Bdu0;
256 real_t(*Bjn1)[max_Q1D] = Bdu1;
257 real_t(*Gj0)[max_Q1D] = Gu0;
258 real_t(*Gj1)[max_Q1D] = Gu1;
264 MFEM_FOREACH_THREAD(side, z, 2)
266 real_t(*
u)[max_Q1D] = (side == 0) ? u0 : u1;
267 real_t(*du)[max_Q1D] = (side == 0) ? du0 : du1;
269 MFEM_FOREACH_THREAD(d2, x, D1D)
271 MFEM_FOREACH_THREAD(d1, y, D1D)
273 u[d2][d1] = x(d1, d2, side,
275 du[d2][d1] = dxdn(d1, d2, side,
f);
279 MFEM_FOREACH_THREAD(p1, x, Q1D)
281 MFEM_FOREACH_THREAD(p2, y, Q1D)
283 for (
int l = 0; l < 3; ++l)
285 nJe[side][p2][p1][l] = pa(3 * side + l, p1, p2,
f);
290 kappa_Qh[p2][p1] = pa(6, p1, p2,
f);
297 MFEM_FOREACH_THREAD(
p, x, Q1D)
299 MFEM_FOREACH_THREAD(d, y, D1D)
310 MFEM_FOREACH_THREAD(side, z, 2)
312 real_t(*
u)[max_Q1D] = (side == 0) ? u0 : u1;
313 real_t(*du)[max_Q1D] = (side == 0) ? du0 : du1;
314 real_t(*Bu)[max_Q1D] = (side == 0) ? Bu0 : Bu1;
315 real_t(*Bdu)[max_Q1D] = (side == 0) ? Bdu0 : Bdu1;
316 real_t(*Gu)[max_Q1D] = (side == 0) ? Gu0 : Gu1;
318 MFEM_FOREACH_THREAD(p1, x, Q1D)
320 MFEM_FOREACH_THREAD(d2, y, D1D)
326 for (
int d1 = 0; d1 < D1D; ++d1)
329 const real_t g = G(p1, d1);
332 bdu +=
b * du[d2][d1];
344 MFEM_FOREACH_THREAD(side, z, 2)
346 real_t(*
u)[max_Q1D] = (side == 0) ? u0 : u1;
347 real_t(*du)[max_Q1D] = (side == 0) ? du0 : du1;
348 real_t(*Bu)[max_Q1D] = (side == 0) ? Bu0 : Bu1;
349 real_t(*Gu)[max_Q1D] = (side == 0) ? Gu0 : Gu1;
350 real_t(*Bdu)[max_Q1D] = (side == 0) ? Bdu0 : Bdu1;
352 MFEM_FOREACH_THREAD(p2, x, Q1D)
354 MFEM_FOREACH_THREAD(p1, y, Q1D)
356 const real_t *Je = nJe[side][p2][p1];
363 for (
int d2 = 0; d2 < D1D; ++d2)
366 const real_t g = G(p2, d2);
367 bbu +=
b * Bu[p1][d2];
368 gbu += g * Bu[p1][d2];
369 bgu +=
b * Gu[p1][d2];
370 bbdu +=
b * Bdu[p1][d2];
375 du[p2][p1] = Je[0] * bbdu + Je[1] * bgu + Je[2] * gbu;
381 MFEM_FOREACH_THREAD(side, z, 2)
383 real_t(*Bj)[max_Q1D] = (side == 0) ? Bj0 : Bj1;
384 real_t(*Bjn)[max_Q1D] = (side == 0) ? Bjn0 : Bjn1;
385 real_t(*Gj)[max_Q1D] = (side == 0) ? Gj0 : Gj1;
387 MFEM_FOREACH_THREAD(d1, x, D1D)
389 MFEM_FOREACH_THREAD(p2, y, Q1D)
396 for (
int p1 = 0; p1 < Q1D; ++p1)
399 const real_t g = G(p1, d1);
401 const real_t *Je = nJe[side][p2][p1];
403 const real_t jump = u0[p2][p1] - u1[p2][p1];
404 const real_t avg = du0[p2][p1] + du1[p2][p1];
407 const real_t r = -avg + kappa_Qh[p2][p1] * jump;
410 bj +=
b * Je[0] * jump;
411 gj += g * Je[1] * jump;
412 bjn +=
b * Je[2] * jump;
417 Bj[d1][p2] =
sigma * bj;
418 Bjn[d1][p2] =
sigma * bjn;
422 const real_t sgn = (side == 0) ? 1.0 : -1.0;
423 Gj[d1][p2] = sgn * br +
sigma * gj;
429 MFEM_FOREACH_THREAD(side, z, 2)
431 real_t(*
u)[max_Q1D] = (side == 0) ? u0 : u1;
432 real_t(*du)[max_Q1D] = (side == 0) ? du0 : du1;
433 real_t(*Bj)[max_Q1D] = (side == 0) ? Bj0 : Bj1;
434 real_t(*Bjn)[max_Q1D] = (side == 0) ? Bjn0 : Bjn1;
435 real_t(*Gj)[max_Q1D] = (side == 0) ? Gj0 : Gj1;
437 MFEM_FOREACH_THREAD(d2, x, D1D)
439 MFEM_FOREACH_THREAD(d1, y, D1D)
445 for (
int p2 = 0; p2 < Q1D; ++p2)
448 const real_t g = G(p2, d2);
450 bbj +=
b * Bj[d1][p2];
451 bgj +=
b * Gj[d1][p2];
452 gbj += g * Bjn[d1][p2];
456 u[d2][d1] = bgj + gbj;
463 MFEM_FOREACH_THREAD(side, z, 2)
465 const real_t(*
u)[max_Q1D] = (side == 0) ? u0 : u1;
466 const real_t(*du)[max_Q1D] = (side == 0) ? du0 : du1;
468 MFEM_FOREACH_THREAD(d2, x, D1D)
470 MFEM_FOREACH_THREAD(d1, y, D1D)
472 y(d1, d2, side,
f) +=
u[d2][d1];
473 dydn(d1, d2, side,
f) += du[d2][d1];
482template <
int DIM,
int D1D,
int Q1D>
484DGDiffusionIntegrator::ApplyPAKernels::Kernel()
486 if constexpr (
DIM == 2)
488 return internal::PADGDiffusionApply2D<D1D, Q1D>;
490 else if constexpr (
DIM == 3)
492 return internal::PADGDiffusionApply3D<D1D, Q1D>;
void(*)(const int, const Array< real_t > &, const Array< real_t > &, const Array< real_t > &, const Array< real_t > &, const real_t, const Vector &, const Vector &_, const Vector &, Vector &, Vector &, const int, const int) ApplyKernelType
real_t sigma(const Vector &x)
real_t u(const Vector &xvec)
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
void forall_2D(int N, int X, int Y, lambda &&body)
void forall_3D(int N, int X, int Y, int Z, lambda &&body)
std::function< real_t(const Vector &)> f(real_t mass_coeff)
DeviceTensor< 2, real_t > DeviceMatrix
real_t p(const Vector &x, real_t t)
static const DeviceDofQuadLimits & Get()
Return a const reference to the DeviceDofQuadLimits singleton.