12 #include "../tmop.hpp" 14 #include "../linearform.hpp" 15 #include "../../general/forall.hpp" 16 #include "../../linalg/kernels.hpp" 17 #include "../../linalg/dinvariants.hpp" 22 using Args = kernels::InvariantsEvaluator3D::Buffers;
25 static MFEM_HOST_DEVICE
inline 26 void EvalP_302(
const double *J,
double *P)
29 double dI1b[9], dI2[9], dI2b[9], dI3b[9];
30 kernels::InvariantsEvaluator3D ie(
Args()
35 const double alpha = ie.Get_I1b()/9.;
36 const double beta = ie.Get_I2b()/9.;
41 static MFEM_HOST_DEVICE
inline 42 void EvalP_303(
const double *J,
double *P)
45 double dI1b[9], dI3b[9];
46 kernels::InvariantsEvaluator3D ie(
Args().J(J).B(B).dI1b(dI1b).dI3b(dI3b));
51 static MFEM_HOST_DEVICE
inline 52 void EvalP_315(
const double *J,
double *P)
55 kernels::InvariantsEvaluator3D ie(
Args().J(J).dI3b(dI3b));
58 const double I3b = ie.Get_I3b(sign_detJ);
59 kernels::Set(3,3, 2.0 * (I3b - 1.0), ie.Get_dI3b(sign_detJ), P);
64 static MFEM_HOST_DEVICE
inline 65 void EvalP_318(
const double *J,
double *P)
68 kernels::InvariantsEvaluator3D ie(
Args().J(J).dI3b(dI3b));
71 const double I3b = ie.Get_I3b(sign_detJ);
72 kernels::Set(3,3, I3b - 1.0/(I3b * I3b * I3b), ie.Get_dI3b(sign_detJ), P);
76 static MFEM_HOST_DEVICE
inline 77 void EvalP_321(
const double *J,
double *P)
80 double dI1[9], dI2[9], dI3b[9];
81 kernels::InvariantsEvaluator3D ie(
Args().J(J).B(B)
82 .dI1(dI1).dI2(dI2).dI3b(dI3b));
84 const double I3 = ie.Get_I3();
85 const double alpha = 1.0/I3;
86 const double beta = -2.*ie.Get_I2()/(I3*ie.Get_I3b(sign_detJ));
92 static MFEM_HOST_DEVICE
inline 93 void EvalP_332(
const double *J,
const double *w,
double *P)
96 double dI1b[9], dI2[9], dI2b[9], dI3b[9];
97 kernels::InvariantsEvaluator3D ie(
Args()
102 const double alpha = w[0] * ie.Get_I1b()/9.;
103 const double beta = w[0]* ie.Get_I2b()/9.;
107 const double I3b = ie.Get_I3b(sign_detJ);
108 kernels::Add(3,3, w[1] * 2.0 * (I3b - 1.0), ie.Get_dI3b(sign_detJ), P);
112 static MFEM_HOST_DEVICE
inline 113 void EvalP_338(
const double *J,
const double *w,
double *P)
116 double dI1b[9], dI2[9], dI2b[9], dI3b[9];
117 kernels::InvariantsEvaluator3D ie(
Args()
122 const double alpha = w[0] * ie.Get_I1b()/9.;
123 const double beta = w[0]* ie.Get_I2b()/9.;
127 const double I3b = ie.Get_I3b(sign_detJ);
129 ie.Get_dI3b(sign_detJ), P);
133 const double metric_normal,
146 MFEM_VERIFY(mid == 302 || mid == 303 || mid == 315 || mid == 318 ||
147 mid == 321 || mid == 332 || mid == 338,
148 "3D metric not yet implemented!");
150 constexpr
int DIM = 3;
151 const int D1D = T_D1D ? T_D1D : d1d;
152 const int Q1D = T_Q1D ? T_Q1D : q1d;
161 const double *metric_data = metric_param.
Read();
165 const int D1D = T_D1D ? T_D1D : d1d;
166 const int Q1D = T_Q1D ? T_Q1D : q1d;
167 constexpr
int MQ1 = T_Q1D ? T_Q1D : T_MAX;
168 constexpr
int MD1 = T_D1D ? T_D1D : T_MAX;
170 MFEM_SHARED
double s_BG[2][MQ1*MD1];
171 MFEM_SHARED
double s_DDD[3][MD1*MD1*MD1];
172 MFEM_SHARED
double s_DDQ[9][MD1*MD1*MQ1];
173 MFEM_SHARED
double s_DQQ[9][MD1*MQ1*MQ1];
174 MFEM_SHARED
double s_QQQ[9][MQ1*MQ1*MQ1];
176 kernels::internal::LoadX<MD1>(e,D1D,X,s_DDD);
177 kernels::internal::LoadBG<MD1,MQ1>(D1D,Q1D,
b,g,s_BG);
179 kernels::internal::GradX<MD1,MQ1>(D1D,Q1D,s_BG,s_DDD,s_DDQ);
180 kernels::internal::GradY<MD1,MQ1>(D1D,Q1D,s_BG,s_DDQ,s_DQQ);
181 kernels::internal::GradZ<MD1,MQ1>(D1D,Q1D,s_BG,s_DQQ,s_QQQ);
183 MFEM_FOREACH_THREAD(qz,z,Q1D)
185 MFEM_FOREACH_THREAD(qy,y,Q1D)
187 MFEM_FOREACH_THREAD(qx,x,Q1D)
189 const double *Jtr = &J(0,0,qx,qy,qz,e);
190 const double detJtr = kernels::Det<3>(Jtr);
191 const double weight = metric_normal * W(qx,qy,qz) * detJtr;
195 kernels::CalcInverse<3>(Jtr, Jrt);
199 kernels::internal::PullGrad<MQ1>(Q1D,qx,qy,qz,s_QQQ,Jpr);
207 if (mid == 302) { EvalP_302(Jpt, P); }
208 if (mid == 303) { EvalP_303(Jpt, P); }
209 if (mid == 315) { EvalP_315(Jpt, P); }
210 if (mid == 318) { EvalP_318(Jpt, P); }
211 if (mid == 321) { EvalP_321(Jpt, P); }
212 if (mid == 332) { EvalP_332(Jpt, metric_data, P); }
213 if (mid == 338) { EvalP_338(Jpt, metric_data, P); }
214 for (
int i = 0; i < 9; i++) { P[i] *= weight; }
219 kernels::internal::PushGrad<MQ1>(Q1D,qx,qy,qz,A,s_QQQ);
224 kernels::internal::LoadBGt<MD1,MQ1>(D1D,Q1D,
b,g,s_BG);
225 kernels::internal::GradZt<MD1,MQ1>(D1D,Q1D,s_BG,s_QQQ,s_DQQ);
226 kernels::internal::GradYt<MD1,MQ1>(D1D,Q1D,s_BG,s_DQQ,s_DDQ);
227 kernels::internal::GradXt<MD1,MQ1>(D1D,Q1D,s_BG,s_DDQ,Y,e);
235 const int D1D =
PA.maps->ndof;
236 const int Q1D =
PA.maps->nqpt;
237 const int id = (D1D << 4 ) | Q1D;
245 if (
auto m = dynamic_cast<TMOP_Combo_QualityMetric *>(
metric))
250 MFEM_LAUNCH_TMOP_KERNEL(AddMultPA_Kernel_3D,
id,mn,mp,M,N,J,W,B,G,X,Y);
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)
MFEM_HOST_DEVICE void MultABt(const int Aheight, const int Awidth, const int Bheight, const TA *Adata, const TB *Bdata, TC *ABtdata)
Multiply a matrix of size Aheight x Awidth and data Adata with the transpose of a matrix of size Bhei...
struct mfem::TMOP_Integrator::@23 PA
TMOP_QualityMetric * metric
MFEM_HOST_DEVICE void Add(const int height, const int width, const TALPHA alpha, const TA *Adata, const TB *Bdata, TC *Cdata)
Compute C = A + alpha*B, where the matrices A, B and C are of size height x width with data Adata...
void AddMultPA_3D(const Vector &, Vector &) const
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.
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...
virtual double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
kernels::InvariantsEvaluator2D::Buffers Args
MFEM_HOST_DEVICE void Set(const int height, const int width, const double alpha, const TA *Adata, TB *Bdata)
Compute B = alpha*A, where the matrices A and B are of size height x width with data Adata and Bdata...
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)