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