MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
tmop_pa_p3.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, 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#include "../tmop.hpp"
13#include "tmop_pa.hpp"
14#include "../linearform.hpp"
18
19namespace mfem
20{
21
22using Args = kernels::InvariantsEvaluator3D::Buffers;
23
24// P_302 = (I1b/9)*dI2b + (I2b/9)*dI1b
25static MFEM_HOST_DEVICE inline
26void EvalP_302(const real_t *J, real_t *P)
27{
28 real_t B[9];
29 real_t dI1b[9], dI2[9], dI2b[9], dI3b[9];
30 kernels::InvariantsEvaluator3D ie(Args()
31 .J(J).B(B)
32 .dI1b(dI1b)
33 .dI2(dI2).dI2b(dI2b)
34 .dI3b(dI3b));
35 const real_t alpha = ie.Get_I1b()/9.;
36 const real_t beta = ie.Get_I2b()/9.;
37 kernels::Add(3,3, alpha, ie.Get_dI2b(), beta, ie.Get_dI1b(), P);
38}
39
40// P_303 = dI1b/3
41static MFEM_HOST_DEVICE inline
42void EvalP_303(const real_t *J, real_t *P)
43{
44 real_t B[9];
45 real_t dI1b[9], dI3b[9];
46 kernels::InvariantsEvaluator3D ie(Args().J(J).B(B).dI1b(dI1b).dI3b(dI3b));
47 kernels::Set(3,3, 1./3., ie.Get_dI1b(), P);
48}
49
50// P_315 = 2*(I3b - 1)*dI3b
51static MFEM_HOST_DEVICE inline
52void EvalP_315(const real_t *J, real_t *P)
53{
54 real_t dI3b[9];
55 kernels::InvariantsEvaluator3D ie(Args().J(J).dI3b(dI3b));
56
57 real_t sign_detJ;
58 const real_t I3b = ie.Get_I3b(sign_detJ);
59 kernels::Set(3,3, 2.0 * (I3b - 1.0), ie.Get_dI3b(sign_detJ), P);
60}
61
62// P_318 = (I3b - 1/I3b^3)*dI3b.
63// Uses the I3b form, as dI3 and ddI3 were not implemented at the time.
64static MFEM_HOST_DEVICE inline
65void EvalP_318(const real_t *J, real_t *P)
66{
67 real_t dI3b[9];
68 kernels::InvariantsEvaluator3D ie(Args().J(J).dI3b(dI3b));
69
70 real_t sign_detJ;
71 const real_t I3b = ie.Get_I3b(sign_detJ);
72 kernels::Set(3,3, I3b - 1.0/(I3b * I3b * I3b), ie.Get_dI3b(sign_detJ), P);
73}
74
75// P_321 = dI1 + (1/I3)*dI2 - (2*I2/I3b^3)*dI3b
76static MFEM_HOST_DEVICE inline
77void EvalP_321(const real_t *J, real_t *P)
78{
79 real_t B[9];
80 real_t dI1[9], dI2[9], dI3b[9];
81 kernels::InvariantsEvaluator3D ie(Args().J(J).B(B)
82 .dI1(dI1).dI2(dI2).dI3b(dI3b));
83 real_t sign_detJ;
84 const real_t I3 = ie.Get_I3();
85 const real_t alpha = 1.0/I3;
86 const real_t beta = -2.*ie.Get_I2()/(I3*ie.Get_I3b(sign_detJ));
87 kernels::Add(3,3, alpha, ie.Get_dI2(), beta, ie.Get_dI3b(sign_detJ), P);
88 kernels::Add(3,3, ie.Get_dI1(), P);
89}
90
91// P_332 = w0 P_302 + w1 P_315.
92static MFEM_HOST_DEVICE inline
93void EvalP_332(const real_t *J, const real_t *w, real_t *P)
94{
95 real_t B[9];
96 real_t dI1b[9], dI2[9], dI2b[9], dI3b[9];
97 kernels::InvariantsEvaluator3D ie(Args()
98 .J(J).B(B)
99 .dI1b(dI1b)
100 .dI2(dI2).dI2b(dI2b)
101 .dI3b(dI3b));
102 const real_t alpha = w[0] * ie.Get_I1b()/9.;
103 const real_t beta = w[0]* ie.Get_I2b()/9.;
104 kernels::Add(3,3, alpha, ie.Get_dI2b(), beta, ie.Get_dI1b(), P);
105
106 real_t sign_detJ;
107 const real_t I3b = ie.Get_I3b(sign_detJ);
108 kernels::Add(3,3, w[1] * 2.0 * (I3b - 1.0), ie.Get_dI3b(sign_detJ), P);
109}
110
111// P_338 = w0 P_302 + w1 P_318.
112static MFEM_HOST_DEVICE inline
113void EvalP_338(const real_t *J, const real_t *w, real_t *P)
114{
115 real_t B[9];
116 real_t dI1b[9], dI2[9], dI2b[9], dI3b[9];
117 kernels::InvariantsEvaluator3D ie(Args()
118 .J(J).B(B)
119 .dI1b(dI1b)
120 .dI2(dI2).dI2b(dI2b)
121 .dI3b(dI3b));
122 const real_t alpha = w[0] * ie.Get_I1b()/9.;
123 const real_t beta = w[0]* ie.Get_I2b()/9.;
124 kernels::Add(3,3, alpha, ie.Get_dI2b(), beta, ie.Get_dI1b(), P);
125
126 real_t sign_detJ;
127 const real_t I3b = ie.Get_I3b(sign_detJ);
128 kernels::Add(3,3, w[1] * (I3b - 1.0/(I3b * I3b * I3b)),
129 ie.Get_dI3b(sign_detJ), P);
130}
131
132MFEM_REGISTER_TMOP_KERNELS(void, AddMultPA_Kernel_3D,
133 const real_t metric_normal,
134 const Vector &mc_,
135 const Array<real_t> &metric_param,
136 const int mid,
137 const int NE,
138 const DenseTensor &j_,
139 const Array<real_t> &w_,
140 const Array<real_t> &b_,
141 const Array<real_t> &g_,
142 const Vector &x_,
143 Vector &y_,
144 const int d1d,
145 const int q1d)
146{
147 MFEM_VERIFY(mid == 302 || mid == 303 || mid == 315 || mid == 318 ||
148 mid == 321 || mid == 332 || mid == 338,
149 "3D metric not yet implemented!");
150
151 const bool const_m0 = mc_.Size() == 1;
152
153 constexpr int DIM = 3;
154 const int D1D = T_D1D ? T_D1D : d1d;
155 const int Q1D = T_Q1D ? T_Q1D : q1d;
156
157 const auto MC = const_m0 ?
158 Reshape(mc_.Read(), 1, 1, 1, 1) :
159 Reshape(mc_.Read(), Q1D, Q1D, Q1D, NE);
160 const auto J = Reshape(j_.Read(), DIM, DIM, Q1D, Q1D, Q1D, NE);
161 const auto W = Reshape(w_.Read(), Q1D, Q1D, Q1D);
162 const auto b = Reshape(b_.Read(), Q1D, D1D);
163 const auto g = Reshape(g_.Read(), Q1D, D1D);
164 const auto X = Reshape(x_.Read(), D1D, D1D, D1D, DIM, NE);
165 auto Y = Reshape(y_.ReadWrite(), D1D, D1D, D1D, DIM, NE);
166
167 const real_t *metric_data = metric_param.Read();
168
169 mfem::forall_3D(NE, Q1D, Q1D, Q1D, [=] MFEM_HOST_DEVICE (int e)
170 {
171 const int D1D = T_D1D ? T_D1D : d1d;
172 const int Q1D = T_Q1D ? T_Q1D : q1d;
173 constexpr int MQ1 = T_Q1D ? T_Q1D : T_MAX;
174 constexpr int MD1 = T_D1D ? T_D1D : T_MAX;
175
176 MFEM_SHARED real_t s_BG[2][MQ1*MD1];
177 MFEM_SHARED real_t s_DDD[3][MD1*MD1*MD1];
178 MFEM_SHARED real_t s_DDQ[9][MD1*MD1*MQ1];
179 MFEM_SHARED real_t s_DQQ[9][MD1*MQ1*MQ1];
180 MFEM_SHARED real_t s_QQQ[9][MQ1*MQ1*MQ1];
181
182 kernels::internal::LoadX<MD1>(e,D1D,X,s_DDD);
183 kernels::internal::LoadBG<MD1,MQ1>(D1D,Q1D,b,g,s_BG);
184
185 kernels::internal::GradX<MD1,MQ1>(D1D,Q1D,s_BG,s_DDD,s_DDQ);
186 kernels::internal::GradY<MD1,MQ1>(D1D,Q1D,s_BG,s_DDQ,s_DQQ);
187 kernels::internal::GradZ<MD1,MQ1>(D1D,Q1D,s_BG,s_DQQ,s_QQQ);
188
189 MFEM_FOREACH_THREAD(qz,z,Q1D)
190 {
191 MFEM_FOREACH_THREAD(qy,y,Q1D)
192 {
193 MFEM_FOREACH_THREAD(qx,x,Q1D)
194 {
195 const real_t *Jtr = &J(0,0,qx,qy,qz,e);
196 const real_t detJtr = kernels::Det<3>(Jtr);
197 const real_t m_coef = const_m0 ? MC(0,0,0,0) : MC(qx,qy,qz,e);
198 const real_t weight = metric_normal * m_coef *
199 W(qx,qy,qz) * detJtr;
200
201 // Jrt = Jtr^{-1}
202 real_t Jrt[9];
203 kernels::CalcInverse<3>(Jtr, Jrt);
204
205 // Jpr = X^T.DSh
206 real_t Jpr[9];
207 kernels::internal::PullGrad<MQ1>(Q1D,qx,qy,qz,s_QQQ,Jpr);
208
209 // Jpt = X^T.DS = (X^T.DSh).Jrt = Jpr.Jrt
210 real_t Jpt[9];
211 kernels::Mult(3,3,3, Jpr, Jrt, Jpt);
212
213 // metric->EvalP(Jpt, P);
214 real_t P[9];
215 if (mid == 302) { EvalP_302(Jpt, P); }
216 if (mid == 303) { EvalP_303(Jpt, P); }
217 if (mid == 315) { EvalP_315(Jpt, P); }
218 if (mid == 318) { EvalP_318(Jpt, P); }
219 if (mid == 321) { EvalP_321(Jpt, P); }
220 if (mid == 332) { EvalP_332(Jpt, metric_data, P); }
221 if (mid == 338) { EvalP_338(Jpt, metric_data, P); }
222 for (int i = 0; i < 9; i++) { P[i] *= weight; }
223
224 // Y += DS . P^t += DSh . (Jrt . P^t)
225 real_t A[9];
226 kernels::MultABt(3,3,3, Jrt, P, A);
227 kernels::internal::PushGrad<MQ1>(Q1D,qx,qy,qz,A,s_QQQ);
228 }
229 }
230 }
231 MFEM_SYNC_THREAD;
232 kernels::internal::LoadBGt<MD1,MQ1>(D1D,Q1D,b,g,s_BG);
233 kernels::internal::GradZt<MD1,MQ1>(D1D,Q1D,s_BG,s_QQQ,s_DQQ);
234 kernels::internal::GradYt<MD1,MQ1>(D1D,Q1D,s_BG,s_DQQ,s_DDQ);
235 kernels::internal::GradXt<MD1,MQ1>(D1D,Q1D,s_BG,s_DDQ,Y,e);
236 });
237}
238
240{
241 const int N = PA.ne;
242 const int M = metric->Id();
243 const int D1D = PA.maps->ndof;
244 const int Q1D = PA.maps->nqpt;
245 const int id = (D1D << 4 ) | Q1D;
246 const DenseTensor &J = PA.Jtr;
247 const Array<real_t> &W = PA.ir->GetWeights();
248 const Array<real_t> &B = PA.maps->B;
249 const Array<real_t> &G = PA.maps->G;
250 const real_t mn = metric_normal;
251 const Vector &MC = PA.MC;
252
253 Array<real_t> mp;
254 if (auto m = dynamic_cast<TMOP_Combo_QualityMetric *>(metric))
255 {
256 m->GetWeights(mp);
257 }
258
259 MFEM_LAUNCH_TMOP_KERNEL(AddMultPA_Kernel_3D,id,mn,MC,mp,M,N,J,W,B,G,X,Y);
260}
261
262} // namespace mfem
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Definition array.hpp:317
Rank 3 tensor (array of matrices)
const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read( GetMemory(), TotalSize(), on_dev).
TMOP_QualityMetric * metric
Definition tmop.hpp:1744
struct mfem::TMOP_Integrator::@23 PA
void AddMultPA_3D(const Vector &, Vector &) const
virtual int Id() const
Return the metric ID.
Definition tmop.hpp:78
Vector data type.
Definition vector.hpp:80
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:474
virtual real_t * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:490
int Size() const
Returns the size of the vector.
Definition vector.hpp:218
Vector beta
const real_t alpha
Definition ex15.cpp:369
real_t b
Definition lissajous.cpp:42
constexpr int DIM
MFEM_HOST_DEVICE void CalcInverse(const T *data, T *inv_data)
Return the inverse of a matrix with given size and data into the matrix with data inv_data.
Definition kernels.hpp:246
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,...
Definition kernels.hpp:266
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,...
Definition kernels.hpp:163
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...
Definition kernels.hpp:363
MFEM_HOST_DEVICE void Set(const int height, const int width, const real_t 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.
Definition kernels.hpp:326
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
MFEM_REGISTER_TMOP_KERNELS(void, DatcSize, const int NE, const int ncomp, const int sizeidx, const real_t input_min_size, const DenseMatrix &w_, const Array< real_t > &b_, const Vector &x_, const Vector &nc_reduce, DenseTensor &j_, const int d1d, const int q1d)
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
kernels::InvariantsEvaluator2D::Buffers Args
void forall_3D(int N, int X, int Y, int Z, lambda &&body)
Definition forall.hpp:775
float real_t
Definition config.hpp:43