MFEM  v4.6.0
Finite element discretization library
tmop_pa_h2s.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2023, 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 "../../general/forall.hpp"
15 #include "../../linalg/kernels.hpp"
16 #include "../../linalg/dinvariants.hpp"
17 
18 namespace mfem
19 {
20 
22 
23 // weight * ddI1
24 static MFEM_HOST_DEVICE inline
25 void EvalH_001(const int e, const int qx, const int qy,
26  const double weight, const double *Jpt,
28 {
29  constexpr int DIM = 2;
30  double 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 double 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
50 static MFEM_HOST_DEVICE inline
51 void EvalH_002(const int e, const int qx, const int qy,
52  const double weight, const double *Jpt,
53  DeviceTensor<7,double> H)
54 {
55  constexpr int DIM = 2;
56  double 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 double 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 double h = ddi1b(r,c);
73  H(r,c,i,j,qx,qy,e) = w * h;
74  }
75  }
76  }
77  }
78 }
79 
80 static MFEM_HOST_DEVICE inline
81 void EvalH_007(const int e, const int qx, const int qy,
82  const double weight, const double *Jpt,
83  DeviceTensor<7,double> H)
84 {
85  constexpr int DIM = 2;
86  double 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 double c1 = 1./ie.Get_I2();
95  const double c2 = weight*c1*c1;
96  const double 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).
122 static MFEM_HOST_DEVICE inline
123 void EvalH_056(const int e, const int qx, const int qy,
124  const double weight, const double *Jpt,
125  DeviceTensor<7,double> H)
126 {
127  constexpr int DIM = 2;
128  double dI2b[4], ddI2b[4];
129  kernels::InvariantsEvaluator2D ie(Args().J(Jpt)
130  .dI2b(dI2b)
131  .ddI2b(ddI2b));
132  const double 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 
152 static MFEM_HOST_DEVICE inline
153 void EvalH_077(const int e, const int qx, const int qy,
154  const double weight, const double *Jpt,
155  DeviceTensor<7,double> H)
156 {
157  constexpr int DIM = 2;
158  double 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 double 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.
185 static MFEM_HOST_DEVICE inline
186 void EvalH_080(const int e, const int qx, const int qy,
187  const double weight, const double *w, const double *Jpt,
188  DeviceTensor<7,double> H)
189 {
190  constexpr int DIM = 2;
191  double 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 double 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.
223 static MFEM_HOST_DEVICE inline
224 void EvalH_094(const int e, const int qx, const int qy,
225  const double weight, const double *w, const double *Jpt,
226  DeviceTensor<7,double> H)
227 {
228  constexpr int DIM = 2;
229  double 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 double 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 
258 MFEM_REGISTER_TMOP_KERNELS(void, SetupGradPA_2D,
259  const Vector &x_,
260  const double metric_normal,
261  const Array<double> &metric_param,
262  const int mid,
263  const int NE,
264  const Array<double> &w_,
265  const Array<double> &b_,
266  const Array<double> &g_,
267  const DenseTensor &j_,
268  Vector &h_,
269  const int d1d,
270  const int q1d)
271 {
272  MFEM_VERIFY(mid == 1 || mid == 2 || mid == 7 || mid == 77
273  || mid == 80 || mid == 94,
274  "2D metric not yet implemented!");
275 
276  constexpr int DIM = 2;
277  constexpr int NBZ = 1;
278  const int D1D = T_D1D ? T_D1D : d1d;
279  const int Q1D = T_Q1D ? T_Q1D : q1d;
280 
281  const auto W = Reshape(w_.Read(), Q1D, Q1D);
282  const auto b = Reshape(b_.Read(), Q1D, D1D);
283  const auto g = Reshape(g_.Read(), Q1D, D1D);
284  const auto J = Reshape(j_.Read(), DIM, DIM, Q1D, Q1D, NE);
285  const auto X = Reshape(x_.Read(), D1D, D1D, DIM, NE);
286  auto H = Reshape(h_.Write(), DIM, DIM, DIM, DIM, Q1D, Q1D, NE);
287 
288  const double *metric_data = metric_param.Read();
289 
290  mfem::forall_2D_batch(NE, Q1D, Q1D, NBZ, [=] MFEM_HOST_DEVICE (int e)
291  {
292  const int D1D = T_D1D ? T_D1D : d1d;
293  const int Q1D = T_Q1D ? T_Q1D : q1d;
294  constexpr int NBZ = 1;
295  constexpr int MQ1 = T_Q1D ? T_Q1D : T_MAX;
296  constexpr int MD1 = T_D1D ? T_D1D : T_MAX;
297 
298  MFEM_SHARED double s_BG[2][MQ1*MD1];
299  MFEM_SHARED double s_X[2][NBZ][MD1*MD1];
300  MFEM_SHARED double s_DQ[4][NBZ][MD1*MQ1];
301  MFEM_SHARED double s_QQ[4][NBZ][MQ1*MQ1];
302 
303  kernels::internal::LoadX<MD1,NBZ>(e,D1D,X,s_X);
304  kernels::internal::LoadBG<MD1,MQ1>(D1D, Q1D, b, g, s_BG);
305 
306  kernels::internal::GradX<MD1,MQ1,NBZ>(D1D, Q1D, s_BG, s_X, s_DQ);
307  kernels::internal::GradY<MD1,MQ1,NBZ>(D1D, Q1D, s_BG, s_DQ, s_QQ);
308 
309  MFEM_FOREACH_THREAD(qy,y,Q1D)
310  {
311  MFEM_FOREACH_THREAD(qx,x,Q1D)
312  {
313  const double *Jtr = &J(0,0,qx,qy,e);
314  const double detJtr = kernels::Det<2>(Jtr);
315  const double weight = metric_normal * W(qx,qy) * detJtr;
316 
317  // Jrt = Jtr^{-1}
318  double Jrt[4];
319  kernels::CalcInverse<2>(Jtr, Jrt);
320 
321  // Jpr = X^t.DSh
322  double Jpr[4];
323  kernels::internal::PullGrad<MQ1,NBZ>(Q1D,qx,qy,s_QQ,Jpr);
324 
325  // Jpt = Jpr.Jrt
326  double Jpt[4];
327  kernels::Mult(2,2,2, Jpr, Jrt, Jpt);
328 
329  // metric->AssembleH
330  if (mid == 1) { EvalH_001(e,qx,qy,weight,Jpt,H); }
331  if (mid == 2) { EvalH_002(e,qx,qy,weight,Jpt,H); }
332  if (mid == 7) { EvalH_007(e,qx,qy,weight,Jpt,H); }
333  if (mid == 77) { EvalH_077(e,qx,qy,weight,Jpt,H); }
334  if (mid == 56) { EvalH_056(e,qx,qy,weight,Jpt,H); }
335  if (mid == 80) { EvalH_080(e,qx,qy,weight,metric_data,Jpt,H); }
336  if (mid == 94) { EvalH_094(e,qx,qy,weight,metric_data,Jpt,H); }
337  } // qx
338  } // qy
339  });
340 }
341 
343 {
344  const int N = PA.ne;
345  const int M = metric->Id();
346  const int D1D = PA.maps->ndof;
347  const int Q1D = PA.maps->nqpt;
348  const int id = (D1D << 4 ) | Q1D;
349  const double mn = metric_normal;
350  const DenseTensor &J = PA.Jtr;
351  const Array<double> &W = PA.ir->GetWeights();
352  const Array<double> &B = PA.maps->B;
353  const Array<double> &G = PA.maps->G;
354  Vector &H = PA.H;
355 
356  Array<double> mp;
357  if (auto m = dynamic_cast<TMOP_Combo_QualityMetric *>(metric))
358  {
359  m->GetWeights(mp);
360  }
361 
362  MFEM_LAUNCH_TMOP_KERNEL(SetupGradPA_2D,id,X,mn,mp,M,N,W,B,G,J,H);
363 }
364 
365 } // namespace mfem
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Definition: array.hpp:307
DeviceTensor< 2, const double > ConstDeviceMatrix
Definition: dtensor.hpp:144
struct mfem::TMOP_Integrator::@23 PA
void AssembleGradPA_2D(const Vector &) const
TMOP_QualityMetric * metric
Definition: tmop.hpp:1740
virtual const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
Definition: vector.hpp:453
constexpr int DIM
const double * Read(bool on_dev=true) const
Shortcut for mfem::Read( GetMemory(), TotalSize(), on_dev).
Definition: densemat.hpp:1230
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)
Definition: tmop_pa_da3.cpp:20
virtual int Id() const
Return the metric ID.
Definition: tmop.hpp:78
MFEM_HOST_DEVICE double * Get_ddI1(int i, int j)
virtual double * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
Definition: vector.hpp:461
double b
Definition: lissajous.cpp:42
void forall_2D_batch(int N, int X, int Y, int BZ, lambda &&body)
Definition: forall.hpp:757
A basic generic Tensor class, appropriate for use on the GPU.
Definition: dtensor.hpp:81
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
kernels::InvariantsEvaluator2D::Buffers Args
Definition: tmop_pa_h2s.cpp:21
Vector data type.
Definition: vector.hpp:58
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
Rank 3 tensor (array of matrices)
Definition: densemat.hpp:1096