MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
tmop_pa_h2s.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"
17
18namespace mfem
19{
20
22
23// weight * ddI1
24static MFEM_HOST_DEVICE inline
25void EvalH_001(const int e, const int qx, const int qy,
26 const real_t weight, const real_t *Jpt,
28{
29 constexpr int DIM = 2;
30 real_t ddI1[4];
31 kernels::InvariantsEvaluator2D ie(Args().J(Jpt).ddI1(ddI1));
32 for (int i = 0; i < DIM; i++)
33 {
34 for (int j = 0; j < DIM; j++)
35 {
36 ConstDeviceMatrix ddi1(ie.Get_ddI1(i,j),DIM,DIM);
37 for (int r = 0; r < DIM; r++)
38 {
39 for (int c = 0; c < DIM; c++)
40 {
41 const real_t h = ddi1(r,c);
42 H(r,c,i,j,qx,qy,e) = weight * h;
43 }
44 }
45 }
46 }
47}
48
49// 0.5 * weight * dI1b
50static MFEM_HOST_DEVICE inline
51void EvalH_002(const int e, const int qx, const int qy,
52 const real_t weight, const real_t *Jpt,
53 DeviceTensor<7,real_t> H)
54{
55 constexpr int DIM = 2;
56 real_t ddI1[4], ddI1b[4], dI2b[4];
57 kernels::InvariantsEvaluator2D ie(Args()
58 .J(Jpt)
59 .ddI1(ddI1)
60 .ddI1b(ddI1b)
61 .dI2b(dI2b));
62 const real_t w = 0.5 * weight;
63 for (int i = 0; i < DIM; i++)
64 {
65 for (int j = 0; j < DIM; j++)
66 {
67 ConstDeviceMatrix ddi1b(ie.Get_ddI1b(i,j),DIM,DIM);
68 for (int r = 0; r < DIM; r++)
69 {
70 for (int c = 0; c < DIM; c++)
71 {
72 const real_t h = ddi1b(r,c);
73 H(r,c,i,j,qx,qy,e) = w * h;
74 }
75 }
76 }
77 }
78}
79
80static MFEM_HOST_DEVICE inline
81void EvalH_007(const int e, const int qx, const int qy,
82 const real_t weight, const real_t *Jpt,
83 DeviceTensor<7,real_t> H)
84{
85 constexpr int DIM = 2;
86 real_t ddI1[4], ddI2[4], dI1[4], dI2[4], dI2b[4];
87 kernels::InvariantsEvaluator2D ie(Args()
88 .J(Jpt)
89 .ddI1(ddI1)
90 .ddI2(ddI2)
91 .dI1(dI1)
92 .dI2(dI2)
93 .dI2b(dI2b));
94 const real_t c1 = 1./ie.Get_I2();
95 const real_t c2 = weight*c1*c1;
96 const real_t c3 = ie.Get_I1()*c2;
97 ConstDeviceMatrix di1(ie.Get_dI1(),DIM,DIM);
98 ConstDeviceMatrix di2(ie.Get_dI2(),DIM,DIM);
99
100 for (int i = 0; i < DIM; i++)
101 {
102 for (int j = 0; j < DIM; j++)
103 {
104 ConstDeviceMatrix ddi1(ie.Get_ddI1(i,j),DIM,DIM);
105 ConstDeviceMatrix ddi2(ie.Get_ddI2(i,j),DIM,DIM);
106 for (int r = 0; r < DIM; r++)
107 {
108 for (int c = 0; c < DIM; c++)
109 {
110 H(r,c,i,j,qx,qy,e) =
111 weight * (1.0 + c1) * ddi1(r,c)
112 - c3 * ddi2(r,c)
113 - c2 * ( di1(i,j) * di2(r,c) + di2(i,j) * di1(r,c) )
114 + 2.0 * c1 * c3 * di2(r,c) * di2(i,j);
115 }
116 }
117 }
118 }
119}
120
121// dP_56 = (0.5 - 0.5/I2b^2)*ddI2b + (1/I2b^3)*(dI2b x dI2b).
122static MFEM_HOST_DEVICE inline
123void EvalH_056(const int e, const int qx, const int qy,
124 const real_t weight, const real_t *Jpt,
125 DeviceTensor<7,real_t> H)
126{
127 constexpr int DIM = 2;
128 real_t dI2b[4], ddI2b[4];
129 kernels::InvariantsEvaluator2D ie(Args().J(Jpt)
130 .dI2b(dI2b)
131 .ddI2b(ddI2b));
132 const real_t I2b = ie.Get_I2b();
133 ConstDeviceMatrix di2b(ie.Get_dI2b(),DIM,DIM);
134 for (int i = 0; i < DIM; i++)
135 {
136 for (int j = 0; j < DIM; j++)
137 {
138 ConstDeviceMatrix ddi2b(ie.Get_ddI2b(i,j),DIM,DIM);
139 for (int r = 0; r < DIM; r++)
140 {
141 for (int c = 0; c < DIM; c++)
142 {
143 H(r,c,i,j,qx,qy,e) =
144 weight * (0.5 - 0.5/(I2b*I2b)) * ddi2b(r,c) +
145 weight / (I2b*I2b*I2b) * di2b(r,c) * di2b(i,j);
146 }
147 }
148 }
149 }
150}
151
152static MFEM_HOST_DEVICE inline
153void EvalH_077(const int e, const int qx, const int qy,
154 const real_t weight, const real_t *Jpt,
155 DeviceTensor<7,real_t> H)
156{
157 constexpr int DIM = 2;
158 real_t dI2[4], dI2b[4], ddI2[4];
159 kernels::InvariantsEvaluator2D ie(Args()
160 .J(Jpt)
161 .dI2(dI2)
162 .dI2b(dI2b)
163 .ddI2(ddI2));
164 const real_t I2 = ie.Get_I2(), I2inv_sq = 1.0 / (I2 * I2);
165 ConstDeviceMatrix di2(ie.Get_dI2(),DIM,DIM);
166 for (int i = 0; i < DIM; i++)
167 {
168 for (int j = 0; j < DIM; j++)
169 {
170 ConstDeviceMatrix ddi2(ie.Get_ddI2(i,j),DIM,DIM);
171 for (int r = 0; r < DIM; r++)
172 {
173 for (int c = 0; c < DIM; c++)
174 {
175 H(r,c,i,j,qx,qy,e) =
176 weight * 0.5 * (1.0 - I2inv_sq) * ddi2(r,c)
177 + weight * (I2inv_sq / I2) * di2(r,c) * di2(i,j);
178 }
179 }
180 }
181 }
182}
183
184// H_80 = w0 H_2 + w1 H_77.
185static MFEM_HOST_DEVICE inline
186void EvalH_080(const int e, const int qx, const int qy,
187 const real_t weight, const real_t *w, const real_t *Jpt,
188 DeviceTensor<7,real_t> H)
189{
190 constexpr int DIM = 2;
191 real_t ddI1[4], ddI1b[4], dI2[4], dI2b[4], ddI2[4];
192 kernels::InvariantsEvaluator2D ie(Args()
193 .J(Jpt)
194 .dI2(dI2)
195 .ddI1(ddI1)
196 .ddI1b(ddI1b)
197 .dI2b(dI2b)
198 .ddI2(ddI2));
199
200 const real_t I2 = ie.Get_I2(), I2inv_sq = 1.0 / (I2 * I2);
201 ConstDeviceMatrix di2(ie.Get_dI2(),DIM,DIM);
202 for (int i = 0; i < DIM; i++)
203 {
204 for (int j = 0; j < DIM; j++)
205 {
206 ConstDeviceMatrix ddi1b(ie.Get_ddI1b(i,j),DIM,DIM);
207 ConstDeviceMatrix ddi2(ie.Get_ddI2(i,j),DIM,DIM);
208 for (int r = 0; r < DIM; r++)
209 {
210 for (int c = 0; c < DIM; c++)
211 {
212 H(r,c,i,j,qx,qy,e) =
213 w[0] * 0.5 * weight * ddi1b(r,c) +
214 w[1] * ( weight * 0.5 * (1.0 - I2inv_sq) * ddi2(r,c) +
215 weight * (I2inv_sq / I2) * di2(r,c) * di2(i,j) );
216 }
217 }
218 }
219 }
220}
221
222// H_94 = w0 H_2 + w1 H_56.
223static MFEM_HOST_DEVICE inline
224void EvalH_094(const int e, const int qx, const int qy,
225 const real_t weight, const real_t *w, const real_t *Jpt,
226 DeviceTensor<7,real_t> H)
227{
228 constexpr int DIM = 2;
229 real_t ddI1[4], ddI1b[4], dI2b[4], ddI2b[4];
230 kernels::InvariantsEvaluator2D ie(Args().J(Jpt)
231 .ddI1(ddI1)
232 .ddI1b(ddI1b)
233 .dI2b(dI2b)
234 .ddI2b(ddI2b));
235
236 const real_t I2b = ie.Get_I2b();
237 ConstDeviceMatrix di2b(ie.Get_dI2b(),DIM,DIM);
238 for (int i = 0; i < DIM; i++)
239 {
240 for (int j = 0; j < DIM; j++)
241 {
242 ConstDeviceMatrix ddi1b(ie.Get_ddI1b(i,j),DIM,DIM);
243 ConstDeviceMatrix ddi2b(ie.Get_ddI2b(i,j),DIM,DIM);
244 for (int r = 0; r < DIM; r++)
245 {
246 for (int c = 0; c < DIM; c++)
247 {
248 H(r,c,i,j,qx,qy,e) =
249 w[0] * 0.5 * weight * ddi1b(r,c) +
250 w[1] * ( weight * (0.5 - 0.5/(I2b*I2b)) * ddi2b(r,c) +
251 weight / (I2b*I2b*I2b) * di2b(r,c) * di2b(i,j) );
252 }
253 }
254 }
255 }
256}
257
258MFEM_REGISTER_TMOP_KERNELS(void, SetupGradPA_2D,
259 const Vector &x_,
260 const real_t metric_normal,
261 const Vector &mc_,
262 const Array<real_t> &metric_param,
263 const int mid,
264 const int NE,
265 const Array<real_t> &w_,
266 const Array<real_t> &b_,
267 const Array<real_t> &g_,
268 const DenseTensor &j_,
269 Vector &h_,
270 const int d1d,
271 const int q1d)
272{
273 MFEM_VERIFY(mid == 1 || mid == 2 || mid == 7 || mid == 77
274 || mid == 80 || mid == 94,
275 "2D metric not yet implemented!");
276
277 const bool const_m0 = mc_.Size() == 1;
278
279 constexpr int DIM = 2;
280 constexpr int NBZ = 1;
281 const int D1D = T_D1D ? T_D1D : d1d;
282 const int Q1D = T_Q1D ? T_Q1D : q1d;
283
284 const auto MC = const_m0 ?
285 Reshape(mc_.Read(), 1, 1, 1) :
286 Reshape(mc_.Read(), Q1D, Q1D, NE);
287 const auto W = Reshape(w_.Read(), Q1D, Q1D);
288 const auto b = Reshape(b_.Read(), Q1D, D1D);
289 const auto g = Reshape(g_.Read(), Q1D, D1D);
290 const auto J = Reshape(j_.Read(), DIM, DIM, Q1D, Q1D, NE);
291 const auto X = Reshape(x_.Read(), D1D, D1D, DIM, NE);
292 auto H = Reshape(h_.Write(), DIM, DIM, DIM, DIM, Q1D, Q1D, NE);
293
294 const real_t *metric_data = metric_param.Read();
295
296 mfem::forall_2D_batch(NE, Q1D, Q1D, NBZ, [=] MFEM_HOST_DEVICE (int e)
297 {
298 const int D1D = T_D1D ? T_D1D : d1d;
299 const int Q1D = T_Q1D ? T_Q1D : q1d;
300 constexpr int NBZ = 1;
301 constexpr int MQ1 = T_Q1D ? T_Q1D : T_MAX;
302 constexpr int MD1 = T_D1D ? T_D1D : T_MAX;
303
304 MFEM_SHARED real_t s_BG[2][MQ1*MD1];
305 MFEM_SHARED real_t s_X[2][NBZ][MD1*MD1];
306 MFEM_SHARED real_t s_DQ[4][NBZ][MD1*MQ1];
307 MFEM_SHARED real_t s_QQ[4][NBZ][MQ1*MQ1];
308
309 kernels::internal::LoadX<MD1,NBZ>(e,D1D,X,s_X);
310 kernels::internal::LoadBG<MD1,MQ1>(D1D, Q1D, b, g, s_BG);
311
312 kernels::internal::GradX<MD1,MQ1,NBZ>(D1D, Q1D, s_BG, s_X, s_DQ);
313 kernels::internal::GradY<MD1,MQ1,NBZ>(D1D, Q1D, s_BG, s_DQ, s_QQ);
314
315 MFEM_FOREACH_THREAD(qy,y,Q1D)
316 {
317 MFEM_FOREACH_THREAD(qx,x,Q1D)
318 {
319 const real_t *Jtr = &J(0,0,qx,qy,e);
320 const real_t detJtr = kernels::Det<2>(Jtr);
321 const real_t m_coef = const_m0 ? MC(0,0,0) : MC(qx,qy,e);
322 const real_t weight = metric_normal * m_coef * W(qx,qy) * detJtr;
323
324 // Jrt = Jtr^{-1}
325 real_t Jrt[4];
326 kernels::CalcInverse<2>(Jtr, Jrt);
327
328 // Jpr = X^t.DSh
329 real_t Jpr[4];
330 kernels::internal::PullGrad<MQ1,NBZ>(Q1D,qx,qy,s_QQ,Jpr);
331
332 // Jpt = Jpr.Jrt
333 real_t Jpt[4];
334 kernels::Mult(2,2,2, Jpr, Jrt, Jpt);
335
336 // metric->AssembleH
337 if (mid == 1) { EvalH_001(e,qx,qy,weight,Jpt,H); }
338 if (mid == 2) { EvalH_002(e,qx,qy,weight,Jpt,H); }
339 if (mid == 7) { EvalH_007(e,qx,qy,weight,Jpt,H); }
340 if (mid == 77) { EvalH_077(e,qx,qy,weight,Jpt,H); }
341 if (mid == 56) { EvalH_056(e,qx,qy,weight,Jpt,H); }
342 if (mid == 80) { EvalH_080(e,qx,qy,weight,metric_data,Jpt,H); }
343 if (mid == 94) { EvalH_094(e,qx,qy,weight,metric_data,Jpt,H); }
344 } // qx
345 } // qy
346 });
347}
348
350{
351 const int N = PA.ne;
352 const int M = metric->Id();
353 const int D1D = PA.maps->ndof;
354 const int Q1D = PA.maps->nqpt;
355 const int id = (D1D << 4 ) | Q1D;
356 const real_t mn = metric_normal;
357 const Vector &MC = PA.MC;
358 const DenseTensor &J = PA.Jtr;
359 const Array<real_t> &W = PA.ir->GetWeights();
360 const Array<real_t> &B = PA.maps->B;
361 const Array<real_t> &G = PA.maps->G;
362 Vector &H = PA.H;
363
364 Array<real_t> mp;
365 if (auto m = dynamic_cast<TMOP_Combo_QualityMetric *>(metric))
366 {
367 m->GetWeights(mp);
368 }
369
370 MFEM_LAUNCH_TMOP_KERNEL(SetupGradPA_2D,id,X,mn,MC,mp,M,N,W,B,G,J,H);
371}
372
373} // 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).
A basic generic Tensor class, appropriate for use on the GPU.
Definition dtensor.hpp:82
TMOP_QualityMetric * metric
Definition tmop.hpp:1744
struct mfem::TMOP_Integrator::@23 PA
void AssembleGradPA_2D(const 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
int Size() const
Returns the size of the vector.
Definition vector.hpp:218
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
Definition vector.hpp:482
MFEM_HOST_DEVICE real_t * Get_ddI1(int i, int j)
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 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 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
void forall_2D_batch(int N, int X, int Y, int BZ, lambda &&body)
Definition forall.hpp:769
DeviceTensor< 2, const real_t > ConstDeviceMatrix
Definition dtensor.hpp:144
kernels::InvariantsEvaluator2D::Buffers Args
float real_t
Definition config.hpp:43