12 #include "../tmop.hpp" 14 #include "../../general/forall.hpp" 15 #include "../../linalg/kernels.hpp" 16 #include "../../linalg/dinvariants.hpp" 21 using Args = kernels::InvariantsEvaluator3D::Buffers;
24 static MFEM_HOST_DEVICE
inline 25 void EvalH_302(
const int e,
const int qx,
const int qy,
const int qz,
26 const double weight,
const double *J, DeviceTensor<8,double> dP,
27 double *B,
double *dI1b,
double *ddI1b,
28 double *dI2,
double *dI2b,
double *ddI2,
double *ddI2b,
31 constexpr
int DIM = 3;
32 kernels::InvariantsEvaluator3D ie(
Args()
34 .dI1b(dI1b).ddI1b(ddI1b)
35 .dI2(dI2).dI2b(dI2b).ddI2(ddI2).ddI2b(ddI2b)
37 const double c1 = weight/9.;
38 const double I1b = ie.Get_I1b();
39 const double I2b = ie.Get_I2b();
42 for (
int i = 0; i <
DIM; i++)
44 for (
int j = 0; j <
DIM; j++)
48 for (
int r = 0; r <
DIM; r++)
50 for (
int c = 0; c <
DIM; c++)
53 (di2b(r,c)*di1b(i,j) + di1b(r,c)*di2b(i,j))
56 dP(r,c,i,j,qx,qy,qz,e) = c1 * dp;
64 static MFEM_HOST_DEVICE
inline 65 void EvalH_303(
const int e,
const int qx,
const int qy,
const int qz,
66 const double weight,
const double *J, DeviceTensor<8,double> dP,
67 double *B,
double *dI1b,
double *ddI1,
double *ddI1b,
68 double *dI2,
double *dI2b,
double *ddI2,
double *ddI2b,
69 double *dI3b,
double *ddI3b)
71 constexpr
int DIM = 3;
72 kernels::InvariantsEvaluator3D ie(
Args()
74 .dI1b(dI1b).ddI1(ddI1).ddI1b(ddI1b)
75 .dI2(dI2).dI2b(dI2b).ddI2(ddI2).ddI2b(ddI2b)
76 .dI3b(dI3b).ddI3b(ddI3b));
77 const double c1 = weight/3.;
78 for (
int i = 0; i <
DIM; i++)
80 for (
int j = 0; j <
DIM; j++)
83 for (
int r = 0; r <
DIM; r++)
85 for (
int c = 0; c <
DIM; c++)
87 const double dp = ddi1b(r,c);
88 dP(r,c,i,j,qx,qy,qz,e) = c1 * dp;
96 static MFEM_HOST_DEVICE
inline 97 void EvalH_315(
const int e,
const int qx,
const int qy,
const int qz,
98 const double weight,
const double *J, DeviceTensor<8,double> dP,
99 double *dI3b,
double *ddI3b)
101 constexpr
int DIM = 3;
102 kernels::InvariantsEvaluator3D ie(
Args().
104 dI3b(dI3b).ddI3b(ddI3b));
107 const double I3b = ie.Get_I3b(sign_detJ);
110 for (
int i = 0; i <
DIM; i++)
112 for (
int j = 0; j <
DIM; j++)
115 for (
int r = 0; r <
DIM; r++)
117 for (
int c = 0; c <
DIM; c++)
119 const double dp = 2.0 * weight * (I3b - 1.0) * ddi3b(r,c) +
120 2.0 * weight * di3b(r,c) * di3b(i,j);
121 dP(r,c,i,j,qx,qy,qz,e) = dp;
130 static MFEM_HOST_DEVICE
inline 131 void EvalH_318(
const int e,
const int qx,
const int qy,
const int qz,
132 const double weight,
const double *J, DeviceTensor<8,double> dP,
133 double *dI3b,
double *ddI3b)
135 constexpr
int DIM = 3;
136 kernels::InvariantsEvaluator3D ie(
Args().
138 dI3b(dI3b).ddI3b(ddI3b));
141 const double I3b = ie.Get_I3b(sign_detJ);
144 for (
int i = 0; i <
DIM; i++)
146 for (
int j = 0; j <
DIM; j++)
149 for (
int r = 0; r <
DIM; r++)
151 for (
int c = 0; c <
DIM; c++)
154 weight * (I3b - 1.0/(I3b*I3b*I3b)) * ddi3b(r,c) +
155 weight * (1.0 + 3.0/(I3b*I3b*I3b*I3b)) * di3b(r,c)*di3b(i,j);
156 dP(r,c,i,j,qx,qy,qz,e) = dp;
167 static MFEM_HOST_DEVICE
inline 168 void EvalH_321(
const int e,
const int qx,
const int qy,
const int qz,
169 const double weight,
const double *J, DeviceTensor<8,double> dP,
170 double *B,
double *dI1b,
double *ddI1,
double *ddI1b,
171 double *dI2,
double *dI2b,
double *ddI2,
double *ddI2b,
172 double *dI3b,
double *ddI3b)
174 constexpr
int DIM = 3;
175 kernels::InvariantsEvaluator3D ie(
Args()
177 .dI1b(dI1b).ddI1(ddI1).ddI1b(ddI1b)
178 .dI2(dI2).dI2b(dI2b).ddI2(ddI2).ddI2b(ddI2b)
179 .dI3b(dI3b).ddI3b(ddI3b));
181 const double I2 = ie.Get_I2();
182 const double I3b = ie.Get_I3b(sign_detJ);
187 const double c0 = 1.0/I3b;
188 const double c1 = weight*c0*c0;
189 const double c2 = -2*c0*c1;
190 const double c3 = c2*I2;
192 for (
int i = 0; i <
DIM; i++)
194 for (
int j = 0; j <
DIM; j++)
199 for (
int r = 0; r <
DIM; r++)
201 for (
int c = 0; c <
DIM; c++)
207 + c2 * ((di2(r,c)*di3b(i,j) + di3b(r,c)*di2(i,j)))
208 -3*c0*c3 * di3b(r,c)*di3b(i,j);
209 dP(r,c,i,j,qx,qy,qz,e) = dp;
217 static MFEM_HOST_DEVICE
inline 218 void EvalH_332(
const int e,
const int qx,
const int qy,
const int qz,
219 const double weight,
const double *w,
220 const double *J, DeviceTensor<8,double> dP,
221 double *B,
double *dI1b,
double *ddI1b,
222 double *dI2,
double *dI2b,
double *ddI2,
double *ddI2b,
223 double *dI3b,
double *ddI3b)
225 constexpr
int DIM = 3;
226 kernels::InvariantsEvaluator3D ie(
Args()
228 .dI1b(dI1b).ddI1b(ddI1b)
229 .dI2(dI2).dI2b(dI2b).ddI2(ddI2).ddI2b(ddI2b)
230 .dI3b(dI3b).ddI3b(ddI3b));
232 const double c1 = weight/9.;
233 const double I1b = ie.Get_I1b();
234 const double I2b = ie.Get_I2b();
235 const double I3b = ie.Get_I3b(sign_detJ);
239 for (
int i = 0; i <
DIM; i++)
241 for (
int j = 0; j <
DIM; j++)
246 for (
int r = 0; r <
DIM; r++)
248 for (
int c = 0; c <
DIM; c++)
250 const double dp_302 =
251 (di2b(r,c)*di1b(i,j) + di1b(r,c)*di2b(i,j))
254 const double dp_315 = 2.0 * weight * (I3b - 1.0) * ddi3b(r,c) +
255 2.0 * weight * di3b(r,c) * di3b(i,j);
256 dP(r,c,i,j,qx,qy,qz,e) = w[0] * c1 * dp_302 +
265 static MFEM_HOST_DEVICE
inline 266 void EvalH_338(
const int e,
const int qx,
const int qy,
const int qz,
267 const double weight,
const double *w,
268 const double *J, DeviceTensor<8,double> dP,
269 double *B,
double *dI1b,
double *ddI1b,
270 double *dI2,
double *dI2b,
double *ddI2,
double *ddI2b,
271 double *dI3b,
double *ddI3b)
273 constexpr
int DIM = 3;
274 kernels::InvariantsEvaluator3D ie(
Args()
276 .dI1b(dI1b).ddI1b(ddI1b)
277 .dI2(dI2).dI2b(dI2b).ddI2(ddI2).ddI2b(ddI2b)
278 .dI3b(dI3b).ddI3b(ddI3b));
280 const double c1 = weight/9.;
281 const double I1b = ie.Get_I1b();
282 const double I2b = ie.Get_I2b();
283 const double I3b = ie.Get_I3b(sign_detJ);
287 for (
int i = 0; i <
DIM; i++)
289 for (
int j = 0; j <
DIM; j++)
294 for (
int r = 0; r <
DIM; r++)
296 for (
int c = 0; c <
DIM; c++)
298 const double dp_302 =
299 (di2b(r,c)*di1b(i,j) + di1b(r,c)*di2b(i,j))
302 const double dp_318 =
303 weight * (I3b - 1.0/(I3b*I3b*I3b)) * ddi3b(r,c) +
304 weight * (1.0 + 3.0/(I3b*I3b*I3b*I3b)) * di3b(r,c)*di3b(i,j);
305 dP(r,c,i,j,qx,qy,qz,e) = w[0] * c1 * dp_302 +
314 const double metric_normal,
327 MFEM_VERIFY(mid == 302 || mid == 303 || mid == 315 || mid == 318 ||
328 mid == 321 || mid == 332 || mid == 338,
329 "3D metric not yet implemented!");
331 constexpr
int DIM = 3;
332 const int D1D = T_D1D ? T_D1D : d1d;
333 const int Q1D = T_Q1D ? T_Q1D : q1d;
342 const double *metric_data = metric_param.
Read();
346 const int D1D = T_D1D ? T_D1D : d1d;
347 const int Q1D = T_Q1D ? T_Q1D : q1d;
348 constexpr
int MQ1 = T_Q1D ? T_Q1D : T_MAX;
349 constexpr
int MD1 = T_D1D ? T_D1D : T_MAX;
351 MFEM_SHARED
double s_BG[2][MQ1*MD1];
352 MFEM_SHARED
double s_DDD[3][MD1*MD1*MD1];
353 MFEM_SHARED
double s_DDQ[9][MD1*MD1*MQ1];
354 MFEM_SHARED
double s_DQQ[9][MD1*MQ1*MQ1];
355 MFEM_SHARED
double s_QQQ[9][MQ1*MQ1*MQ1];
357 kernels::internal::LoadX<MD1>(e,D1D,X,s_DDD);
358 kernels::internal::LoadBG<MD1,MQ1>(D1D,Q1D,
b,g,s_BG);
360 kernels::internal::GradX<MD1,MQ1>(D1D,Q1D,s_BG,s_DDD,s_DDQ);
361 kernels::internal::GradY<MD1,MQ1>(D1D,Q1D,s_BG,s_DDQ,s_DQQ);
362 kernels::internal::GradZ<MD1,MQ1>(D1D,Q1D,s_BG,s_DQQ,s_QQQ);
364 MFEM_FOREACH_THREAD(qz,z,Q1D)
366 MFEM_FOREACH_THREAD(qy,y,Q1D)
368 MFEM_FOREACH_THREAD(qx,x,Q1D)
370 const double *Jtr = &J(0,0,qx,qy,qz,e);
371 const double detJtr = kernels::Det<3>(Jtr);
372 const double weight = metric_normal * W(qx,qy,qz) * detJtr;
376 kernels::CalcInverse<3>(Jtr, Jrt);
380 kernels::internal::PullGrad<MQ1>(Q1D,qx,qy,qz, s_QQQ, Jpr);
388 double dI1b[9], ddI1[9], ddI1b[9];
389 double dI2[9], dI2b[9], ddI2[9], ddI2b[9];
391 double *dI3b=Jrt, *ddI3b=Jpr;
396 EvalH_302(e,qx,qy,qz,weight,Jpt,H,
397 B,dI1b,ddI1b,dI2,dI2b,ddI2,ddI2b,dI3b);
401 EvalH_303(e,qx,qy,qz,weight,Jpt,H,
402 B,dI1b,ddI1,ddI1b,dI2,dI2b,ddI2,ddI2b,dI3b,ddI3b);
406 EvalH_315(e,qx,qy,qz,weight,Jpt,H, dI3b,ddI3b);
410 EvalH_318(e,qx,qy,qz,weight,Jpt,H, dI3b,ddI3b);
414 EvalH_321(e,qx,qy,qz,weight,Jpt,H,
415 B,dI1b,ddI1,ddI1b,dI2,dI2b,ddI2,ddI2b,dI3b,ddI3b);
419 EvalH_332(e,qx,qy,qz,weight,metric_data,Jpt,H,
420 B,dI1b,ddI1b,dI2,dI2b,ddI2,ddI2b,dI3b,ddI3b);
424 EvalH_338(e,qx,qy,qz,weight,metric_data,Jpt,H,
425 B,dI1b,ddI1b,dI2,dI2b,ddI2,ddI2b,dI3b,ddI3b);
436 const int D1D =
PA.maps->ndof;
437 const int Q1D =
PA.maps->nqpt;
439 const int id = (D1D << 4 ) | Q1D;
448 if (
auto m = dynamic_cast<TMOP_Combo_QualityMetric *>(
metric))
453 MFEM_LAUNCH_TMOP_KERNEL(SetupGradPA_3D,
id,mn,mp,M,X,N,W,B,G,J,
H);
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
void forall_3D(int N, int X, int Y, int Z, lambda &&body)
DeviceTensor< 2, const double > ConstDeviceMatrix
struct mfem::TMOP_Integrator::@23 PA
TMOP_QualityMetric * metric
virtual const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
const double * Read(bool on_dev=true) const
Shortcut for mfem::Read( GetMemory(), TotalSize(), on_dev).
MFEM_REGISTER_TMOP_KERNELS(void, DatcSize, const int NE, const int ncomp, const int sizeidx, const double input_min_size, const DenseMatrix &w_, const Array< double > &b_, const Vector &x_, const Vector &nc_reduce, DenseTensor &j_, const int d1d, const int q1d)
virtual int Id() const
Return the metric ID.
virtual double * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
MFEM_HOST_DEVICE void Mult(const int height, const int width, const TA *data, const TX *x, TY *y)
Matrix vector multiplication: y = A x, where the matrix A is of size height x width with given data...
kernels::InvariantsEvaluator2D::Buffers Args
void AssembleGradPA_3D(const Vector &) const
MFEM_HOST_DEVICE DeviceTensor< sizeof...(Dims), T > Reshape(T *ptr, Dims... dims)
Wrap a pointer as a DeviceTensor with automatically deduced template parameters.
Rank 3 tensor (array of matrices)