MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
det.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_QUADINTERP_DET_HPP
13#define MFEM_QUADINTERP_DET_HPP
14
18#include "../../fem/kernels.hpp"
20
21namespace mfem
22{
23
24namespace internal
25{
26namespace quadrature_interpolator
27{
28
29inline void Det1D(const int NE,
30 const real_t *b,
31 const real_t *g,
32 const real_t *x,
33 real_t *y,
34 const int d1d,
35 const int q1d,
36 Vector *d_buff = nullptr)
37{
38 MFEM_CONTRACT_VAR(b);
39 MFEM_CONTRACT_VAR(d_buff);
40 const auto G = Reshape(g, q1d, d1d);
41 const auto X = Reshape(x, d1d, NE);
42
43 auto Y = Reshape(y, q1d, NE);
44
45 mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
46 {
47 for (int q = 0; q < q1d; q++)
48 {
49 real_t u = 0.0;
50 for (int d = 0; d < d1d; d++)
51 {
52 u += G(q, d) * X(d, e);
53 }
54 Y(q, e) = u;
55 }
56 });
57}
58
59template<int T_D1D = 0, int T_Q1D = 0, int T_SDIM = 3>
60inline void Det1DSurface(const int NE,
61 const real_t *b,
62 const real_t *g,
63 const real_t *x,
64 real_t *y,
65 const int d1d = 0,
66 const int q1d = 0,
67 Vector *d_buff = nullptr)
68{
69 MFEM_CONTRACT_VAR(b);
70 MFEM_CONTRACT_VAR(d_buff);
71
72 const int D1D = T_D1D ? T_D1D : d1d;
73 const int Q1D = T_Q1D ? T_Q1D : q1d;
74
75 const auto G = Reshape(g, Q1D, D1D);
76 const auto X = Reshape(x, D1D, T_SDIM, NE);
77 auto Y = Reshape(y, Q1D, NE);
78
79 mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
80 {
81 for (int q = 0; q < Q1D; q++)
82 {
83 real_t grad[T_SDIM];
84 for (int s = 0; s < T_SDIM; s++) { grad[s] = 0.0; }
85 for (int d = 0; d < D1D; d++)
86 {
87 const real_t gval = G(q, d);
88 for (int s = 0; s < T_SDIM; s++)
89 {
90 grad[s] += gval * X(d, s, e);
91 }
92 }
93 real_t norm2 = 0.0;
94 for (int s = 0; s < T_SDIM; s++)
95 {
96 norm2 += grad[s] * grad[s];
97 }
98 Y(q, e) = std::sqrt(norm2);
99 }
100 });
101}
102
103template<int T_D1D = 0, int T_Q1D = 0>
104inline void Det2D(const int NE,
105 const real_t *b,
106 const real_t *g,
107 const real_t *x,
108 real_t *y,
109 const int d1d = 0,
110 const int q1d = 0,
111 Vector *d_buff = nullptr)
112{
113 MFEM_CONTRACT_VAR(d_buff);
114 static constexpr int SDIM = 2;
115 static constexpr int NBZ = 1;
116
117 const int D1D = T_D1D ? T_D1D : d1d;
118 const int Q1D = T_Q1D ? T_Q1D : q1d;
119
120 const auto B = Reshape(b, Q1D, D1D);
121 const auto G = Reshape(g, Q1D, D1D);
122 const auto X = Reshape(x, D1D, D1D, SDIM, NE);
123 auto Y = Reshape(y, Q1D, Q1D, NE);
124
125 mfem::forall_2D_batch(NE, Q1D, Q1D, NBZ, [=] MFEM_HOST_DEVICE (int e)
126 {
127 constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
128 constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
129 const int D1D = T_D1D ? T_D1D : d1d;
130 const int Q1D = T_Q1D ? T_Q1D : q1d;
131
132 MFEM_SHARED real_t BG[2][MQ1*MD1];
133 MFEM_SHARED real_t XY[SDIM][NBZ][MD1*MD1];
134 MFEM_SHARED real_t DQ[2*SDIM][NBZ][MD1*MQ1];
135 MFEM_SHARED real_t QQ[2*SDIM][NBZ][MQ1*MQ1];
136
137 kernels::internal::LoadX<MD1,NBZ>(e,D1D,X,XY);
138 kernels::internal::LoadBG<MD1,MQ1>(D1D,Q1D,B,G,BG);
139
140 kernels::internal::GradX<MD1,MQ1,NBZ>(D1D,Q1D,BG,XY,DQ);
141 kernels::internal::GradY<MD1,MQ1,NBZ>(D1D,Q1D,BG,DQ,QQ);
142
143 MFEM_FOREACH_THREAD(qy,y,Q1D)
144 {
145 MFEM_FOREACH_THREAD(qx,x,Q1D)
146 {
147 real_t J[4];
148 kernels::internal::PullGrad<MQ1,NBZ>(Q1D,qx,qy,QQ,J);
149 Y(qx,qy,e) = kernels::Det<2>(J);
150 }
151 }
152 });
153}
154
155template<int T_D1D = 0, int T_Q1D = 0>
156inline void Det2DSurface(const int NE,
157 const real_t *b,
158 const real_t *g,
159 const real_t *x,
160 real_t *y,
161 const int d1d = 0,
162 const int q1d = 0,
163 Vector *d_buff = nullptr)
164{
165 MFEM_CONTRACT_VAR(d_buff);
166
167 static constexpr int SDIM = 3;
168 static constexpr int NBZ = 1;
169
170 const int D1D = T_D1D ? T_D1D : d1d;
171 const int Q1D = T_Q1D ? T_Q1D : q1d;
172
173 const auto B = Reshape(b, Q1D, D1D);
174 const auto G = Reshape(g, Q1D, D1D);
175 const auto X = Reshape(x, D1D, D1D, SDIM, NE);
176 auto Y = Reshape(y, Q1D, Q1D, NE);
177
178 mfem::forall_2D_batch(NE, Q1D, Q1D, NBZ, [=] MFEM_HOST_DEVICE (int e)
179 {
180 constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
181 constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
182 const int D1D = T_D1D ? T_D1D : d1d;
183 const int Q1D = T_Q1D ? T_Q1D : q1d;
184 const int tidz = MFEM_THREAD_ID(z);
185
186 MFEM_SHARED real_t BG[2][MQ1*MD1];
187 MFEM_SHARED real_t XYZ[SDIM][NBZ][MD1*MD1];
188 MFEM_SHARED real_t DQ[2*SDIM][NBZ][MD1*MQ1];
189
190 kernels::internal::LoadBG<MD1,MQ1>(D1D,Q1D,B,G,BG);
191
192 // Load XYZ components
193 MFEM_FOREACH_THREAD(dy,y,D1D)
194 {
195 MFEM_FOREACH_THREAD(dx,x,D1D)
196 {
197 for (int d = 0; d < SDIM; ++d)
198 {
199 XYZ[d][tidz][dx + dy*D1D] = X(dx,dy,d,e);
200 }
201 }
202 }
203 MFEM_SYNC_THREAD;
204
205 ConstDeviceMatrix B_mat(BG[0], D1D, Q1D);
206 ConstDeviceMatrix G_mat(BG[1], D1D, Q1D);
207
208 // x contraction
209 MFEM_FOREACH_THREAD(dy,y,D1D)
210 {
211 MFEM_FOREACH_THREAD(qx,x,Q1D)
212 {
213 for (int d = 0; d < SDIM; ++d)
214 {
215 real_t u = 0.0;
216 real_t v = 0.0;
217 for (int dx = 0; dx < D1D; ++dx)
218 {
219 const real_t xval = XYZ[d][tidz][dx + dy*D1D];
220 u += xval * G_mat(dx,qx);
221 v += xval * B_mat(dx,qx);
222 }
223 DQ[d][tidz][dy + qx*D1D] = u;
224 DQ[3 + d][tidz][dy + qx*D1D] = v;
225 }
226 }
227 }
228 MFEM_SYNC_THREAD;
229 // y contraction and determinant computation
230 MFEM_FOREACH_THREAD(qy,y,Q1D)
231 {
232 MFEM_FOREACH_THREAD(qx,x,Q1D)
233 {
234 real_t J_[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
235 for (int d = 0; d < SDIM; ++d)
236 {
237 for (int dy = 0; dy < D1D; ++dy)
238 {
239 J_[d] += DQ[d][tidz][dy + qx*D1D] * B_mat(dy,qy);
240 J_[3 + d] += DQ[3 + d][tidz][dy + qx*D1D] * G_mat(dy,qy);
241 }
242 }
243 DeviceTensor<2> J(J_, 3, 2);
244 const real_t E = J(0,0)*J(0,0) + J(1,0)*J(1,0) + J(2,0)*J(2,0);
245 const real_t F = J(0,0)*J(0,1) + J(1,0)*J(1,1) + J(2,0)*J(2,1);
246 const real_t G = J(0,1)*J(0,1) + J(1,1)*J(1,1) + J(2,1)*J(2,1);
247 Y(qx,qy,e) = std::sqrt(E*G - F*F);
248 }
249 }
250 });
251}
252
253template<int T_D1D = 0, int T_Q1D = 0, bool SMEM = true>
254inline void Det3D(const int NE,
255 const real_t *b,
256 const real_t *g,
257 const real_t *x,
258 real_t *y,
259 const int d1d = 0,
260 const int q1d = 0,
261 Vector *d_buff = nullptr) // used only with SMEM = false
262{
263 constexpr int DIM = 3;
264 static constexpr int GRID = SMEM ? 0 : 128;
265
266 const int D1D = T_D1D ? T_D1D : d1d;
267 const int Q1D = T_Q1D ? T_Q1D : q1d;
268
269 const auto B = Reshape(b, Q1D, D1D);
270 const auto G = Reshape(g, Q1D, D1D);
271 const auto X = Reshape(x, D1D, D1D, D1D, DIM, NE);
272 auto Y = Reshape(y, Q1D, Q1D, Q1D, NE);
273
274 real_t *GM = nullptr;
275 if (!SMEM)
276 {
277 const DeviceDofQuadLimits &limits = DeviceDofQuadLimits::Get();
278 const int max_q1d = T_Q1D ? T_Q1D : limits.MAX_Q1D;
279 const int max_d1d = T_D1D ? T_D1D : limits.MAX_D1D;
280 const int max_qd = std::max(max_q1d, max_d1d);
281 const int mem_size = max_qd * max_qd * max_qd * 9;
282 d_buff->SetSize(2*mem_size*GRID);
283 GM = d_buff->Write();
284 }
285
286 mfem::forall_3D_grid(NE, Q1D, Q1D, Q1D, GRID, [=] MFEM_HOST_DEVICE (int e)
287 {
288 static constexpr int MQ1 = T_Q1D ? T_Q1D :
289 (SMEM ? DofQuadLimits::MAX_DET_1D : DofQuadLimits::MAX_Q1D);
290 static constexpr int MD1 = T_D1D ? T_D1D :
291 (SMEM ? DofQuadLimits::MAX_DET_1D : DofQuadLimits::MAX_D1D);
292 static constexpr int MDQ = MQ1 > MD1 ? MQ1 : MD1;
293 static constexpr int MSZ = MDQ * MDQ * MDQ * 9;
294
295 const int bid = MFEM_BLOCK_ID(x);
296 MFEM_SHARED real_t BG[2][MQ1*MD1];
297 MFEM_SHARED real_t SM0[SMEM?MSZ:1];
298 MFEM_SHARED real_t SM1[SMEM?MSZ:1];
299 real_t *lm0 = SMEM ? SM0 : GM + MSZ*bid;
300 real_t *lm1 = SMEM ? SM1 : GM + MSZ*(GRID+bid);
301 real_t (*DDD)[MD1*MD1*MD1] = (real_t (*)[MD1*MD1*MD1]) (lm0);
302 real_t (*DDQ)[MD1*MD1*MQ1] = (real_t (*)[MD1*MD1*MQ1]) (lm1);
303 real_t (*DQQ)[MD1*MQ1*MQ1] = (real_t (*)[MD1*MQ1*MQ1]) (lm0);
304 real_t (*QQQ)[MQ1*MQ1*MQ1] = (real_t (*)[MQ1*MQ1*MQ1]) (lm1);
305
306 kernels::internal::LoadX<MD1>(e,D1D,X,DDD);
307 kernels::internal::LoadBG<MD1,MQ1>(D1D,Q1D,B,G,BG);
308
309 kernels::internal::GradX<MD1,MQ1>(D1D,Q1D,BG,DDD,DDQ);
310 kernels::internal::GradY<MD1,MQ1>(D1D,Q1D,BG,DDQ,DQQ);
311 kernels::internal::GradZ<MD1,MQ1>(D1D,Q1D,BG,DQQ,QQQ);
312
313 MFEM_FOREACH_THREAD(qz,z,Q1D)
314 {
315 MFEM_FOREACH_THREAD(qy,y,Q1D)
316 {
317 MFEM_FOREACH_THREAD(qx,x,Q1D)
318 {
319 real_t J[9];
320 kernels::internal::PullGrad<MQ1>(Q1D, qx,qy,qz, QQQ, J);
321 Y(qx,qy,qz,e) = kernels::Det<3>(J);
322 }
323 }
324 }
325 });
326}
327
328} // namespace quadrature_interpolator
329} // namespace internal
330
331/// @cond Suppress_Doxygen_warnings
332
333template<int DIM, int SDIM, int D1D, int Q1D>
335QuadratureInterpolator::DetKernels::Kernel()
336{
337 if constexpr (DIM == 1)
338 {
339 if constexpr (SDIM == 1) { return internal::quadrature_interpolator::Det1D; }
340 else if constexpr (SDIM == 2) { return internal::quadrature_interpolator::Det1DSurface<D1D, Q1D, 2>; }
341 else if constexpr (SDIM == 3) { return internal::quadrature_interpolator::Det1DSurface<D1D, Q1D, 3>; }
342 }
343 else if constexpr (DIM == 2 && SDIM == 2) { return internal::quadrature_interpolator::Det2D<D1D, Q1D>; }
344 else if constexpr (DIM == 2 && SDIM == 3) { return internal::quadrature_interpolator::Det2DSurface<D1D, Q1D>; }
345 else if constexpr (DIM == 3) { return internal::quadrature_interpolator::Det3D<D1D, Q1D>; }
346 MFEM_ABORT("");
347}
348
349/// @endcond
350
351} // namespace mfem
352
353#endif // MFEM_QUADINTERP_DET_HPP
void(*)(const int NE, const real_t *B, const real_t *G, const real_t *e_vec, real_t *q_det, const int nd, const int nq, Vector *d_buffer) DetKernelType
real_t b
Definition lissajous.cpp:42
constexpr int SDIM
constexpr int DIM
mfem::real_t real_t
MFEM_HOST_DEVICE T Det(const T *data)
Compute the determinant of a square matrix of size dim with given data.
Definition kernels.hpp:297
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_batch(int N, int X, int Y, int BZ, lambda &&body)
Definition forall.hpp:1232
MFEM_HOST_DEVICE real_t Det3D(DeviceMatrix &J)
Definition lor_util.hpp:28
float real_t
Definition config.hpp:46
void forall_3D_grid(int N, int X, int Y, int Z, int G, lambda &&body)
Definition forall.hpp:1256
DeviceTensor< 2, const real_t > ConstDeviceMatrix
Definition dtensor.hpp:151
MFEM_HOST_DEVICE real_t Det2D(DeviceMatrix &J)
Definition lor_util.hpp:23
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