MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
bilininteg_vecdiffusion_kernels.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#ifndef MFEM_BILININTEG_VECDIFFUSION_KERNELS_HPP
13#define MFEM_BILININTEG_VECDIFFUSION_KERNELS_HPP
14
16#include "../bilininteg.hpp"
18#include "../gridfunc.hpp"
19#include "../qfunction.hpp"
20
21/// \cond DO_NOT_DOCUMENT
22namespace mfem::internal
23{
24
25// PA Diffusion Apply 2D kernel
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> &gt, const Vector &d_,
30 const Vector &x_, Vector &y_, const int d1d = 0,
31 const int q1d = 0, const int vdim = 0)
32{
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;
36 MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
37 MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
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);
45 mfem::forall(NE, [=] MFEM_HOST_DEVICE(int e)
46 {
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;
52
53 real_t grad[max_Q1D][max_Q1D][2];
54 for (int c = 0; c < VDIM; c++)
55 {
56 for (int qy = 0; qy < Q1D; ++qy)
57 {
58 for (int qx = 0; qx < Q1D; ++qx)
59 {
60 grad[qy][qx][0] = 0.0;
61 grad[qy][qx][1] = 0.0;
62 }
63 }
64 for (int dy = 0; dy < D1D; ++dy)
65 {
66 real_t gradX[max_Q1D][2];
67 for (int qx = 0; qx < Q1D; ++qx)
68 {
69 gradX[qx][0] = 0.0;
70 gradX[qx][1] = 0.0;
71 }
72 for (int dx = 0; dx < D1D; ++dx)
73 {
74 const real_t s = x(dx, dy, c, e);
75 for (int qx = 0; qx < Q1D; ++qx)
76 {
77 gradX[qx][0] += s * B(qx, dx);
78 gradX[qx][1] += s * G(qx, dx);
79 }
80 }
81 for (int qy = 0; qy < Q1D; ++qy)
82 {
83 const real_t wy = B(qy, dy);
84 const real_t wDy = G(qy, dy);
85 for (int qx = 0; qx < Q1D; ++qx)
86 {
87 grad[qy][qx][0] += gradX[qx][1] * wy;
88 grad[qy][qx][1] += gradX[qx][0] * wDy;
89 }
90 }
91 }
92 // Calculate Dxy, xDy in plane
93 for (int qy = 0; qy < Q1D; ++qy)
94 {
95 for (int qx = 0; qx < Q1D; ++qx)
96 {
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);
105 }
106 }
107 for (int qy = 0; qy < Q1D; ++qy)
108 {
109 real_t gradX[max_D1D][2];
110 for (int dx = 0; dx < D1D; ++dx)
111 {
112 gradX[dx][0] = 0.0;
113 gradX[dx][1] = 0.0;
114 }
115 for (int qx = 0; qx < Q1D; ++qx)
116 {
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)
120 {
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;
125 }
126 }
127 for (int dy = 0; dy < D1D; ++dy)
128 {
129 const real_t wy = Bt(dy, qy);
130 const real_t wDy = Gt(dy, qy);
131 for (int dx = 0; dx < D1D; ++dx)
132 {
133 y(dx, dy, c, e) +=
134 ((gradX[dx][0] * wy) + (gradX[dx][1] * wDy));
135 }
136 }
137 }
138 }
139 });
140}
141
142// PA Diffusion Apply 3D kernel
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> &gt, const Vector &op_,
147 const Vector &x_, Vector &y_, const int d1d = 0,
148 const int q1d = 0, const int sdim = 0)
149{
150 const int D1D = T_D1D ? T_D1D : d1d;
151 const int Q1D = T_Q1D ? T_Q1D : q1d;
152 constexpr int VDIM = 3;
153 MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
154 MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
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);
162 mfem::forall(NE, [=] MFEM_HOST_DEVICE(int e)
163 {
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)
169 {
170 real_t grad[max_Q1D][max_Q1D][max_Q1D][3];
171 for (int qz = 0; qz < Q1D; ++qz)
172 {
173 for (int qy = 0; qy < Q1D; ++qy)
174 {
175 for (int qx = 0; qx < Q1D; ++qx)
176 {
177 grad[qz][qy][qx][0] = 0.0;
178 grad[qz][qy][qx][1] = 0.0;
179 grad[qz][qy][qx][2] = 0.0;
180 }
181 }
182 }
183 for (int dz = 0; dz < D1D; ++dz)
184 {
185 real_t gradXY[max_Q1D][max_Q1D][3];
186 for (int qy = 0; qy < Q1D; ++qy)
187 {
188 for (int qx = 0; qx < Q1D; ++qx)
189 {
190 gradXY[qy][qx][0] = 0.0;
191 gradXY[qy][qx][1] = 0.0;
192 gradXY[qy][qx][2] = 0.0;
193 }
194 }
195 for (int dy = 0; dy < D1D; ++dy)
196 {
197 real_t gradX[max_Q1D][2];
198 for (int qx = 0; qx < Q1D; ++qx)
199 {
200 gradX[qx][0] = 0.0;
201 gradX[qx][1] = 0.0;
202 }
203 for (int dx = 0; dx < D1D; ++dx)
204 {
205 const real_t s = x(dx, dy, dz, c, e);
206 for (int qx = 0; qx < Q1D; ++qx)
207 {
208 gradX[qx][0] += s * B(qx, dx);
209 gradX[qx][1] += s * G(qx, dx);
210 }
211 }
212 for (int qy = 0; qy < Q1D; ++qy)
213 {
214 const real_t wy = B(qy, dy);
215 const real_t wDy = G(qy, dy);
216 for (int qx = 0; qx < Q1D; ++qx)
217 {
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;
223 }
224 }
225 }
226 for (int qz = 0; qz < Q1D; ++qz)
227 {
228 const real_t wz = B(qz, dz);
229 const real_t wDz = G(qz, dz);
230 for (int qy = 0; qy < Q1D; ++qy)
231 {
232 for (int qx = 0; qx < Q1D; ++qx)
233 {
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;
237 }
238 }
239 }
240 }
241 // Calculate Dxyz, xDyz, xyDz in plane
242 for (int qz = 0; qz < Q1D; ++qz)
243 {
244 for (int qy = 0; qy < Q1D; ++qy)
245 {
246 for (int qx = 0; qx < Q1D; ++qx)
247 {
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);
264 }
265 }
266 }
267 for (int qz = 0; qz < Q1D; ++qz)
268 {
269 real_t gradXY[max_D1D][max_D1D][3];
270 for (int dy = 0; dy < D1D; ++dy)
271 {
272 for (int dx = 0; dx < D1D; ++dx)
273 {
274 gradXY[dy][dx][0] = 0;
275 gradXY[dy][dx][1] = 0;
276 gradXY[dy][dx][2] = 0;
277 }
278 }
279 for (int qy = 0; qy < Q1D; ++qy)
280 {
281 real_t gradX[max_D1D][3];
282 for (int dx = 0; dx < D1D; ++dx)
283 {
284 gradX[dx][0] = 0;
285 gradX[dx][1] = 0;
286 gradX[dx][2] = 0;
287 }
288 for (int qx = 0; qx < Q1D; ++qx)
289 {
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)
294 {
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;
300 }
301 }
302 for (int dy = 0; dy < D1D; ++dy)
303 {
304 const real_t wy = Bt(dy, qy);
305 const real_t wDy = Gt(dy, qy);
306 for (int dx = 0; dx < D1D; ++dx)
307 {
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;
311 }
312 }
313 }
314 for (int dz = 0; dz < D1D; ++dz)
315 {
316 const real_t wz = Bt(dz, qz);
317 const real_t wDz = Gt(dz, qz);
318 for (int dy = 0; dy < D1D; ++dy)
319 {
320 for (int dx = 0; dx < D1D; ++dx)
321 {
322 y(dx, dy, dz, c, e) +=
323 ((gradXY[dy][dx][0] * wz) + (gradXY[dy][dx][1] * wz) +
324 (gradXY[dy][dx][2] * wDz));
325 }
326 }
327 }
328 }
329 }
330 });
331}
332} // namespace mfem::internal
333
334/// \endcond DO_NOT_DOCUMENT
335
336#endif // MFEM_BILININTEG_VECDIFFUSION_KERNELS_HPP
real_t b
Definition lissajous.cpp:42
mfem::real_t real_t
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
Definition dtensor.hpp:138
void forall(int N, lambda &&body)
Definition forall.hpp:1134
static const DeviceDofQuadLimits & Get()
Return a const reference to the DeviceDofQuadLimits singleton.
Definition forall.hpp:138