MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
lininteg_domain_kernels.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, 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_LININTEG_DOMAIN_KERNELS_HPP
13#define MFEM_LININTEG_DOMAIN_KERNELS_HPP
14
15#include "../../fem/kernels.hpp"
17#include "../fem.hpp"
18
19/// \cond DO_NOT_DOCUMENT
20
21namespace mfem
22{
23
24template <int T_D1D = 0, int T_Q1D = 0>
25static void DLFEvalAssemble1D(const int vdim, const int ne, const int d,
26 const int q, const int map_type,
27 const int *markers, const real_t *b,
28 const real_t *detj, const real_t *weights,
29 const Vector &coeff, real_t *y)
30{
31 {
32 constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
33 constexpr int D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
34 MFEM_VERIFY(q <= Q, "");
35 MFEM_VERIFY(d <= D, "");
36 }
37
38 const auto F = coeff.Read();
39 const auto B = Reshape(b, q, d);
40 const auto DETJ = Reshape(detj, q, ne);
41 const bool cst = coeff.Size() == vdim;
42 const auto C = cst ? Reshape(F, vdim, 1, 1) : Reshape(F, vdim, q, ne);
43 auto Y = Reshape(y, d, vdim, ne);
44
45 mfem::forall_2D(ne, d, 1, [=] MFEM_HOST_DEVICE(int e)
46 {
47 if (markers[e] == 0)
48 {
49 return;
50 } // ignore
51
52 constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
53 constexpr int D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
54
55 MFEM_SHARED real_t sBt[Q * D];
56 const DeviceMatrix Bt(sBt, d, q);
57 kernels::internal::LoadB<D, Q>(d, q, B, sBt);
58
59 for (int c = 0; c < vdim; ++c)
60 {
61 const real_t cst_val = C(c, 0, 0);
62 MFEM_FOREACH_THREAD(dx, x, d)
63 {
64 real_t u = 0;
65 for (int qx = 0; qx < q; ++qx)
66 {
67 const real_t detJ =
68 (map_type == FiniteElement::VALUE) ? DETJ(qx, e) : 1.0;
69 const real_t coeff_val = cst ? cst_val : C(c, qx, e);
70 u += weights[qx] * coeff_val * detJ * Bt(dx, qx);
71 }
72 Y(dx, c, e) += u;
73 }
74 }
75 });
76}
77
78template <int T_D1D = 0, int T_Q1D = 0>
79static void DLFEvalAssemble2D(const int vdim, const int ne, const int d,
80 const int q, const int map_type,
81 const int *markers, const real_t *b,
82 const real_t *detj, const real_t *weights,
83 const Vector &coeff, real_t *y)
84{
85 {
86 constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
87 constexpr int D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
88 MFEM_VERIFY(q <= Q, "");
89 MFEM_VERIFY(d <= D, "");
90 }
91
92 const auto F = coeff.Read();
93 const auto B = Reshape(b, q, d);
94 const auto DETJ = Reshape(detj, q, q, ne);
95 const auto W = Reshape(weights, q, q);
96 const bool cst = coeff.Size() == vdim;
97 const auto C = cst ? Reshape(F, vdim, 1, 1, 1) : Reshape(F, vdim, q, q, ne);
98 auto Y = Reshape(y, d, d, vdim, ne);
99
100 mfem::forall_2D(ne, q, q, [=] MFEM_HOST_DEVICE(int e)
101 {
102 if (markers[e] == 0)
103 {
104 return;
105 } // ignore
106
107 constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
108 constexpr int D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
109
110 MFEM_SHARED real_t sBt[Q * D];
111 MFEM_SHARED real_t sQQ[Q * Q];
112 MFEM_SHARED real_t sQD[Q * D];
113
114 const DeviceMatrix Bt(sBt, d, q);
115 kernels::internal::LoadB<D, Q>(d, q, B, sBt);
116
117 const DeviceMatrix QQ(sQQ, q, q);
118 const DeviceMatrix QD(sQD, q, d);
119
120 for (int c = 0; c < vdim; ++c)
121 {
122 const real_t cst_val = C(c, 0, 0, 0);
123 MFEM_FOREACH_THREAD(x, x, q)
124 {
125 MFEM_FOREACH_THREAD(y, y, q)
126 {
127 const real_t detJ =
128 (map_type == FiniteElement::VALUE) ? DETJ(x, y, e) : 1.0;
129 const real_t coeff_val = cst ? cst_val : C(c, x, y, e);
130 QQ(y, x) = W(x, y) * coeff_val * detJ;
131 }
132 }
133 MFEM_SYNC_THREAD;
134 MFEM_FOREACH_THREAD(qy, y, q)
135 {
136 MFEM_FOREACH_THREAD(dx, x, d)
137 {
138 real_t u = 0.0;
139 for (int qx = 0; qx < q; ++qx)
140 {
141 u += QQ(qy, qx) * Bt(dx, qx);
142 }
143 QD(qy, dx) = u;
144 }
145 }
146 MFEM_SYNC_THREAD;
147 MFEM_FOREACH_THREAD(dy, y, d)
148 {
149 MFEM_FOREACH_THREAD(dx, x, d)
150 {
151 real_t u = 0.0;
152 for (int qy = 0; qy < q; ++qy)
153 {
154 u += QD(qy, dx) * Bt(dy, qy);
155 }
156 Y(dx, dy, c, e) += u;
157 }
158 }
159 MFEM_SYNC_THREAD;
160 }
161 });
162}
163
164template <int T_D1D = 0, int T_Q1D = 0>
165static void DLFEvalAssemble3D(const int vdim, const int ne, const int d,
166 const int q, const int map_type,
167 const int* markers, const real_t *b,
168 const real_t *detj, const real_t *weights,
169 const Vector &coeff, real_t *y)
170{
171 {
172 constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
173 constexpr int D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
174 MFEM_VERIFY(q <= Q, "");
175 MFEM_VERIFY(d <= D, "");
176 }
177
178 const auto F = coeff.Read();
179 const auto B = Reshape(b, q, d);
180 const auto DETJ = Reshape(detj, q, q, q, ne);
181 const auto W = Reshape(weights, q, q, q);
182 const bool cst_coeff = coeff.Size() == vdim;
183 const auto C =
184 cst_coeff ? Reshape(F, vdim, 1, 1, 1, 1) : Reshape(F, vdim, q, q, q, ne);
185
186 auto Y = Reshape(y, d, d, d, vdim, ne);
187
188 mfem::forall_2D(ne, q, q, [=] MFEM_HOST_DEVICE(int e)
189 {
190 if (markers[e] == 0)
191 {
192 return;
193 } // ignore
194
195 constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
196 constexpr int D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
197 constexpr int MQD = (Q >= D) ? Q : D;
198
199 real_t u[D];
200
201 MFEM_SHARED real_t sBt[Q * D];
202 const DeviceMatrix Bt(sBt, d, q);
203 kernels::internal::LoadB<D, Q>(d, q, B, sBt);
204
205 MFEM_SHARED real_t sQQQ[MQD * MQD * MQD];
206 const DeviceCube QQQ(sQQQ, MQD, MQD, MQD);
207
208 for (int c = 0; c < vdim; ++c)
209 {
210 const real_t cst_val = C(c, 0, 0, 0, 0);
211 MFEM_FOREACH_THREAD(x, x, q)
212 {
213 MFEM_FOREACH_THREAD(y, y, q)
214 {
215 for (int z = 0; z < q; ++z)
216 {
217 const real_t detJ = (map_type == FiniteElement::VALUE)
218 ? DETJ(x, y, z, e)
219 : 1.0;
220 const real_t coeff_val =
221 cst_coeff ? cst_val : C(c, x, y, z, e);
222 QQQ(z, y, x) = W(x, y, z) * coeff_val * detJ;
223 }
224 }
225 }
226 MFEM_SYNC_THREAD;
227 MFEM_FOREACH_THREAD(qx, x, q)
228 {
229 MFEM_FOREACH_THREAD(qy, y, q)
230 {
231 for (int dz = 0; dz < d; ++dz)
232 {
233 u[dz] = 0.0;
234 }
235 for (int qz = 0; qz < q; ++qz)
236 {
237 const real_t ZYX = QQQ(qz, qy, qx);
238 for (int dz = 0; dz < d; ++dz)
239 {
240 u[dz] += ZYX * Bt(dz, qz);
241 }
242 }
243 for (int dz = 0; dz < d; ++dz)
244 {
245 QQQ(dz, qy, qx) = u[dz];
246 }
247 }
248 }
249 MFEM_SYNC_THREAD;
250 MFEM_FOREACH_THREAD(dz, y, d)
251 {
252 MFEM_FOREACH_THREAD(qx, x, q)
253 {
254 for (int dy = 0; dy < d; ++dy)
255 {
256 u[dy] = 0.0;
257 }
258 for (int qy = 0; qy < q; ++qy)
259 {
260 const real_t zYX = QQQ(dz, qy, qx);
261 for (int dy = 0; dy < d; ++dy)
262 {
263 u[dy] += zYX * Bt(dy, qy);
264 }
265 }
266 for (int dy = 0; dy < d; ++dy)
267 {
268 QQQ(dz, dy, qx) = u[dy];
269 }
270 }
271 }
272 MFEM_SYNC_THREAD;
273 MFEM_FOREACH_THREAD(dz, y, d)
274 {
275 MFEM_FOREACH_THREAD(dy, x, d)
276 {
277 for (int dx = 0; dx < d; ++dx)
278 {
279 u[dx] = 0.0;
280 }
281 for (int qx = 0; qx < q; ++qx)
282 {
283 const real_t zyX = QQQ(dz, dy, qx);
284 for (int dx = 0; dx < d; ++dx)
285 {
286 u[dx] += zyX * Bt(dx, qx);
287 }
288 }
289 for (int dx = 0; dx < d; ++dx)
290 {
291 Y(dx, dy, dz, c, e) += u[dx];
292 }
293 }
294 }
295 MFEM_SYNC_THREAD;
296 }
297 });
298}
299
300template <int DIM, int T_D1D, int T_Q1D>
302DomainLFIntegrator::AssembleKernels::Kernel()
303{
304 switch (DIM)
305 {
306 case 1:
307 return DLFEvalAssemble1D<T_D1D, T_Q1D>;
308 case 2:
309 return DLFEvalAssemble2D<T_D1D, T_Q1D>;
310 case 3:
311 return DLFEvalAssemble3D<T_D1D, T_Q1D>;
312 }
313 MFEM_ABORT("");
314}
315/// \endcond DO_NOT_DOCUMENT
316
317} // namespace mfem
318#endif
void(*)(const int, const int, const int, const int, const int, const int *, const real_t *, const real_t *, const real_t *, const Vector &coeff, real_t *y) AssembleKernelType
args: vdim, ne, d1d, q1d, map_type, markers, B, detJ, W, coeff, y
Definition lininteg.hpp:141
real_t b
Definition lissajous.cpp:42
constexpr int DIM
mfem::real_t real_t
DeviceTensor< 3, real_t > DeviceCube
Definition dtensor.hpp:153
real_t u(const Vector &xvec)
Definition lor_mms.hpp:22
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_2D(int N, int X, int Y, lambda &&body)
Definition forall.hpp:925
DeviceTensor< 2, real_t > DeviceMatrix
Definition dtensor.hpp:150