12#ifndef MFEM_BILININTEG_VECDIFFUSION_KERNELS_HPP
13#define MFEM_BILININTEG_VECDIFFUSION_KERNELS_HPP
22namespace mfem::internal
26template <
int T_D1D = 0,
int T_Q1D = 0,
int T_VDIM = 0>
27void PAVectorDiffusionApply2D(
const int NE,
const Array<real_t> &
b,
28 const Array<real_t> &g,
const Array<real_t> &bt,
29 const Array<real_t> >,
const Vector &d_,
30 const Vector &x_, Vector &y_,
const int d1d = 0,
31 const int q1d = 0,
const int vdim = 0)
33 const int D1D = T_D1D ? T_D1D : d1d;
34 const int Q1D = T_Q1D ? T_Q1D : q1d;
35 const int VDIM = T_VDIM ? T_VDIM : vdim;
38 auto B =
Reshape(
b.Read(), Q1D, D1D);
39 auto G =
Reshape(g.Read(), Q1D, D1D);
40 auto Bt =
Reshape(bt.Read(), D1D, Q1D);
41 auto Gt =
Reshape(gt.Read(), D1D, Q1D);
42 auto D =
Reshape(d_.Read(), Q1D * Q1D, 3, NE);
43 auto x =
Reshape(x_.Read(), D1D, D1D, VDIM, NE);
44 auto y =
Reshape(y_.ReadWrite(), D1D, D1D, VDIM, NE);
47 const int D1D = T_D1D ? T_D1D : d1d;
48 const int Q1D = T_Q1D ? T_Q1D : q1d;
49 const int VDIM = T_VDIM ? T_VDIM : vdim;
50 constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
51 constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
53 real_t grad[max_Q1D][max_Q1D][2];
54 for (
int c = 0; c < VDIM; c++)
56 for (
int qy = 0; qy < Q1D; ++qy)
58 for (
int qx = 0; qx < Q1D; ++qx)
60 grad[qy][qx][0] = 0.0;
61 grad[qy][qx][1] = 0.0;
64 for (
int dy = 0; dy < D1D; ++dy)
67 for (
int qx = 0; qx < Q1D; ++qx)
72 for (
int dx = 0; dx < D1D; ++dx)
74 const real_t s = x(dx, dy, c, e);
75 for (
int qx = 0; qx < Q1D; ++qx)
77 gradX[qx][0] += s * B(qx, dx);
78 gradX[qx][1] += s * G(qx, dx);
81 for (
int qy = 0; qy < Q1D; ++qy)
83 const real_t wy = B(qy, dy);
84 const real_t wDy = G(qy, dy);
85 for (
int qx = 0; qx < Q1D; ++qx)
87 grad[qy][qx][0] += gradX[qx][1] * wy;
88 grad[qy][qx][1] += gradX[qx][0] * wDy;
93 for (
int qy = 0; qy < Q1D; ++qy)
95 for (
int qx = 0; qx < Q1D; ++qx)
97 const int q = qx + qy * Q1D;
98 const real_t O11 = D(q, 0, e);
99 const real_t O12 = D(q, 1, e);
100 const real_t O22 = D(q, 2, e);
101 const real_t gradX = grad[qy][qx][0];
102 const real_t gradY = grad[qy][qx][1];
103 grad[qy][qx][0] = (O11 * gradX) + (O12 * gradY);
104 grad[qy][qx][1] = (O12 * gradX) + (O22 * gradY);
107 for (
int qy = 0; qy < Q1D; ++qy)
110 for (
int dx = 0; dx < D1D; ++dx)
115 for (
int qx = 0; qx < Q1D; ++qx)
117 const real_t gX = grad[qy][qx][0];
118 const real_t gY = grad[qy][qx][1];
119 for (
int dx = 0; dx < D1D; ++dx)
121 const real_t wx = Bt(dx, qx);
122 const real_t wDx = Gt(dx, qx);
123 gradX[dx][0] += gX * wDx;
124 gradX[dx][1] += gY * wx;
127 for (
int dy = 0; dy < D1D; ++dy)
129 const real_t wy = Bt(dy, qy);
130 const real_t wDy = Gt(dy, qy);
131 for (
int dx = 0; dx < D1D; ++dx)
134 ((gradX[dx][0] * wy) + (gradX[dx][1] * wDy));
143template <const
int T_D1D = 0, const
int T_Q1D = 0>
144void PAVectorDiffusionApply3D(
const int NE,
const Array<real_t> &
b,
145 const Array<real_t> &g,
const Array<real_t> &bt,
146 const Array<real_t> >,
const Vector &op_,
147 const Vector &x_, Vector &y_,
const int d1d = 0,
148 const int q1d = 0,
const int sdim = 0)
150 const int D1D = T_D1D ? T_D1D : d1d;
151 const int Q1D = T_Q1D ? T_Q1D : q1d;
152 constexpr int VDIM = 3;
155 auto B =
Reshape(
b.Read(), Q1D, D1D);
156 auto G =
Reshape(g.Read(), Q1D, D1D);
157 auto Bt =
Reshape(bt.Read(), D1D, Q1D);
158 auto Gt =
Reshape(gt.Read(), D1D, Q1D);
159 auto op =
Reshape(op_.Read(), Q1D * Q1D * Q1D, 6, NE);
160 auto x =
Reshape(x_.Read(), D1D, D1D, D1D, VDIM, NE);
161 auto y =
Reshape(y_.ReadWrite(), D1D, D1D, D1D, VDIM, NE);
164 const int D1D = T_D1D ? T_D1D : d1d;
165 const int Q1D = T_Q1D ? T_Q1D : q1d;
166 constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
167 constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
168 for (
int c = 0; c < VDIM; ++c)
170 real_t grad[max_Q1D][max_Q1D][max_Q1D][3];
171 for (
int qz = 0; qz < Q1D; ++qz)
173 for (
int qy = 0; qy < Q1D; ++qy)
175 for (
int qx = 0; qx < Q1D; ++qx)
177 grad[qz][qy][qx][0] = 0.0;
178 grad[qz][qy][qx][1] = 0.0;
179 grad[qz][qy][qx][2] = 0.0;
183 for (
int dz = 0; dz < D1D; ++dz)
185 real_t gradXY[max_Q1D][max_Q1D][3];
186 for (
int qy = 0; qy < Q1D; ++qy)
188 for (
int qx = 0; qx < Q1D; ++qx)
190 gradXY[qy][qx][0] = 0.0;
191 gradXY[qy][qx][1] = 0.0;
192 gradXY[qy][qx][2] = 0.0;
195 for (
int dy = 0; dy < D1D; ++dy)
198 for (
int qx = 0; qx < Q1D; ++qx)
203 for (
int dx = 0; dx < D1D; ++dx)
205 const real_t s = x(dx, dy, dz, c, e);
206 for (
int qx = 0; qx < Q1D; ++qx)
208 gradX[qx][0] += s * B(qx, dx);
209 gradX[qx][1] += s * G(qx, dx);
212 for (
int qy = 0; qy < Q1D; ++qy)
214 const real_t wy = B(qy, dy);
215 const real_t wDy = G(qy, dy);
216 for (
int qx = 0; qx < Q1D; ++qx)
218 const real_t wx = gradX[qx][0];
219 const real_t wDx = gradX[qx][1];
220 gradXY[qy][qx][0] += wDx * wy;
221 gradXY[qy][qx][1] += wx * wDy;
222 gradXY[qy][qx][2] += wx * wy;
226 for (
int qz = 0; qz < Q1D; ++qz)
228 const real_t wz = B(qz, dz);
229 const real_t wDz = G(qz, dz);
230 for (
int qy = 0; qy < Q1D; ++qy)
232 for (
int qx = 0; qx < Q1D; ++qx)
234 grad[qz][qy][qx][0] += gradXY[qy][qx][0] * wz;
235 grad[qz][qy][qx][1] += gradXY[qy][qx][1] * wz;
236 grad[qz][qy][qx][2] += gradXY[qy][qx][2] * wDz;
242 for (
int qz = 0; qz < Q1D; ++qz)
244 for (
int qy = 0; qy < Q1D; ++qy)
246 for (
int qx = 0; qx < Q1D; ++qx)
248 const int q = qx + (qy + qz * Q1D) * Q1D;
249 const real_t O11 = op(q, 0, e);
250 const real_t O12 = op(q, 1, e);
251 const real_t O13 = op(q, 2, e);
252 const real_t O22 = op(q, 3, e);
253 const real_t O23 = op(q, 4, e);
254 const real_t O33 = op(q, 5, e);
255 const real_t gradX = grad[qz][qy][qx][0];
256 const real_t gradY = grad[qz][qy][qx][1];
257 const real_t gradZ = grad[qz][qy][qx][2];
258 grad[qz][qy][qx][0] =
259 (O11 * gradX) + (O12 * gradY) + (O13 * gradZ);
260 grad[qz][qy][qx][1] =
261 (O12 * gradX) + (O22 * gradY) + (O23 * gradZ);
262 grad[qz][qy][qx][2] =
263 (O13 * gradX) + (O23 * gradY) + (O33 * gradZ);
267 for (
int qz = 0; qz < Q1D; ++qz)
269 real_t gradXY[max_D1D][max_D1D][3];
270 for (
int dy = 0; dy < D1D; ++dy)
272 for (
int dx = 0; dx < D1D; ++dx)
274 gradXY[dy][dx][0] = 0;
275 gradXY[dy][dx][1] = 0;
276 gradXY[dy][dx][2] = 0;
279 for (
int qy = 0; qy < Q1D; ++qy)
282 for (
int dx = 0; dx < D1D; ++dx)
288 for (
int qx = 0; qx < Q1D; ++qx)
290 const real_t gX = grad[qz][qy][qx][0];
291 const real_t gY = grad[qz][qy][qx][1];
292 const real_t gZ = grad[qz][qy][qx][2];
293 for (
int dx = 0; dx < D1D; ++dx)
295 const real_t wx = Bt(dx, qx);
296 const real_t wDx = Gt(dx, qx);
297 gradX[dx][0] += gX * wDx;
298 gradX[dx][1] += gY * wx;
299 gradX[dx][2] += gZ * wx;
302 for (
int dy = 0; dy < D1D; ++dy)
304 const real_t wy = Bt(dy, qy);
305 const real_t wDy = Gt(dy, qy);
306 for (
int dx = 0; dx < D1D; ++dx)
308 gradXY[dy][dx][0] += gradX[dx][0] * wy;
309 gradXY[dy][dx][1] += gradX[dx][1] * wDy;
310 gradXY[dy][dx][2] += gradX[dx][2] * wy;
314 for (
int dz = 0; dz < D1D; ++dz)
316 const real_t wz = Bt(dz, qz);
317 const real_t wDz = Gt(dz, qz);
318 for (
int dy = 0; dy < D1D; ++dy)
320 for (
int dx = 0; dx < D1D; ++dx)
322 y(dx, dy, dz, c, e) +=
323 ((gradXY[dy][dx][0] * wz) + (gradXY[dy][dx][1] * wz) +
324 (gradXY[dy][dx][2] * wDz));
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(int N, lambda &&body)
static const DeviceDofQuadLimits & Get()
Return a const reference to the DeviceDofQuadLimits singleton.