12#ifndef MFEM_QUADINTERP_DET_HPP
13#define MFEM_QUADINTERP_DET_HPP
26namespace quadrature_interpolator
29inline void Det1D(
const int NE,
36 Vector *d_buff =
nullptr)
39 MFEM_CONTRACT_VAR(d_buff);
40 const auto G =
Reshape(g, q1d, d1d);
41 const auto X =
Reshape(x, d1d, NE);
47 for (
int q = 0; q < q1d; q++)
50 for (
int d = 0; d < d1d; d++)
52 u += G(q, d) * X(d, e);
59template<
int T_D1D = 0,
int T_Q1D = 0,
int T_SDIM = 3>
60inline void Det1DSurface(
const int NE,
67 Vector *d_buff =
nullptr)
70 MFEM_CONTRACT_VAR(d_buff);
72 const int D1D = T_D1D ? T_D1D : d1d;
73 const int Q1D = T_Q1D ? T_Q1D : q1d;
75 const auto G =
Reshape(g, Q1D, D1D);
76 const auto X =
Reshape(x, D1D, T_SDIM, NE);
81 for (
int q = 0; q < Q1D; q++)
84 for (
int s = 0; s < T_SDIM; s++) { grad[s] = 0.0; }
85 for (
int d = 0; d < D1D; d++)
87 const real_t gval = G(q, d);
88 for (
int s = 0; s < T_SDIM; s++)
90 grad[s] += gval * X(d, s, e);
94 for (
int s = 0; s < T_SDIM; s++)
96 norm2 += grad[s] * grad[s];
98 Y(q, e) = std::sqrt(norm2);
103template<
int T_D1D = 0,
int T_Q1D = 0>
104inline void Det2D(
const int NE,
111 Vector *d_buff =
nullptr)
113 MFEM_CONTRACT_VAR(d_buff);
114 static constexpr int SDIM = 2;
115 static constexpr int NBZ = 1;
117 const int D1D = T_D1D ? T_D1D : d1d;
118 const int Q1D = T_Q1D ? T_Q1D : q1d;
120 const auto B =
Reshape(
b, Q1D, D1D);
121 const auto G =
Reshape(g, Q1D, D1D);
123 auto Y =
Reshape(y, Q1D, Q1D, NE);
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;
132 MFEM_SHARED
real_t BG[2][MQ1*MD1];
137 kernels::internal::LoadX<MD1,NBZ>(e,D1D,X,XY);
138 kernels::internal::LoadBG<MD1,MQ1>(D1D,Q1D,B,G,BG);
140 kernels::internal::GradX<MD1,MQ1,NBZ>(D1D,Q1D,BG,XY,DQ);
141 kernels::internal::GradY<MD1,MQ1,NBZ>(D1D,Q1D,BG,DQ,QQ);
143 MFEM_FOREACH_THREAD(qy,y,Q1D)
145 MFEM_FOREACH_THREAD(qx,x,Q1D)
148 kernels::internal::PullGrad<MQ1,NBZ>(Q1D,qx,qy,QQ,J);
155template<
int T_D1D = 0,
int T_Q1D = 0>
156inline void Det2DSurface(
const int NE,
163 Vector *d_buff =
nullptr)
165 MFEM_CONTRACT_VAR(d_buff);
167 static constexpr int SDIM = 3;
168 static constexpr int NBZ = 1;
170 const int D1D = T_D1D ? T_D1D : d1d;
171 const int Q1D = T_Q1D ? T_Q1D : q1d;
173 const auto B =
Reshape(
b, Q1D, D1D);
174 const auto G =
Reshape(g, Q1D, D1D);
176 auto Y =
Reshape(y, Q1D, Q1D, NE);
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);
186 MFEM_SHARED
real_t BG[2][MQ1*MD1];
190 kernels::internal::LoadBG<MD1,MQ1>(D1D,Q1D,B,G,BG);
193 MFEM_FOREACH_THREAD(dy,y,D1D)
195 MFEM_FOREACH_THREAD(dx,x,D1D)
197 for (
int d = 0; d <
SDIM; ++d)
199 XYZ[d][tidz][dx + dy*D1D] = X(dx,dy,d,e);
209 MFEM_FOREACH_THREAD(dy,y,D1D)
211 MFEM_FOREACH_THREAD(qx,x,Q1D)
213 for (
int d = 0; d <
SDIM; ++d)
217 for (
int dx = 0; dx < D1D; ++dx)
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);
223 DQ[d][tidz][dy + qx*D1D] =
u;
224 DQ[3 + d][tidz][dy + qx*D1D] = v;
230 MFEM_FOREACH_THREAD(qy,y,Q1D)
232 MFEM_FOREACH_THREAD(qx,x,Q1D)
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)
237 for (
int dy = 0; dy < D1D; ++dy)
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);
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);
253template<
int T_D1D = 0,
int T_Q1D = 0,
bool SMEM = true>
254inline void Det3D(
const int NE,
261 Vector *d_buff =
nullptr)
263 constexpr int DIM = 3;
264 static constexpr int GRID = SMEM ? 0 : 128;
266 const int D1D = T_D1D ? T_D1D : d1d;
267 const int Q1D = T_Q1D ? T_Q1D : q1d;
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);
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();
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;
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);
306 kernels::internal::LoadX<MD1>(e,D1D,X,DDD);
307 kernels::internal::LoadBG<MD1,MQ1>(D1D,Q1D,B,G,BG);
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);
313 MFEM_FOREACH_THREAD(qz,z,Q1D)
315 MFEM_FOREACH_THREAD(qy,y,Q1D)
317 MFEM_FOREACH_THREAD(qx,x,Q1D)
320 kernels::internal::PullGrad<MQ1>(Q1D, qx,qy,qz, QQQ, J);
333template<
int DIM,
int SDIM,
int D1D,
int Q1D>
335QuadratureInterpolator::DetKernels::Kernel()
337 if constexpr (
DIM == 1)
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>; }
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>; }
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
MFEM_HOST_DEVICE T Det(const T *data)
Compute the determinant of a square matrix of size dim with given data.
real_t u(const Vector &xvec)
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_2D_batch(int N, int X, int Y, int BZ, lambda &&body)
MFEM_HOST_DEVICE real_t Det3D(DeviceMatrix &J)
void forall_3D_grid(int N, int X, int Y, int Z, int G, lambda &&body)
DeviceTensor< 2, const real_t > ConstDeviceMatrix
MFEM_HOST_DEVICE real_t Det2D(DeviceMatrix &J)
void forall(int N, lambda &&body)
static const DeviceDofQuadLimits & Get()
Return a const reference to the DeviceDofQuadLimits singleton.