MFEM  v4.5.2
Finite element discretization library
tmop.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 "linearform.hpp"
14 #include "pgridfunc.hpp"
15 #include "tmop_tools.hpp"
16 #include "../general/forall.hpp"
17 
18 namespace mfem
19 {
20 
21 // Target-matrix optimization paradigm (TMOP) mesh quality metrics.
22 
24 {
25  double metric = 0.;
26  for (int i = 0; i < tmop_q_arr.Size(); i++)
27  {
28  metric += wt_arr[i]*tmop_q_arr[i]->EvalWMatrixForm(Jpt);
29  }
30  return metric;
31 }
32 
34 {
35  double metric = 0.;
36  for (int i = 0; i < tmop_q_arr.Size(); i++)
37  {
38  metric += wt_arr[i]*tmop_q_arr[i]->EvalW(Jpt);
39  }
40  return metric;
41 }
42 
44  DenseMatrix &P) const
45 {
46  DenseMatrix Pt(P.Size());
47  P = 0.0;
48  for (int i = 0; i < tmop_q_arr.Size(); i++)
49  {
50  tmop_q_arr[i]->EvalP(Jpt, Pt);
51  P.Add(wt_arr[i], Pt);
52  }
53 }
54 
56  const DenseMatrix &DS,
57  const double weight,
58  DenseMatrix &A) const
59 {
60  DenseMatrix At(A.Size());
61  for (int i = 0; i < tmop_q_arr.Size(); i++)
62  {
63  At = 0.0;
64  tmop_q_arr[i]->AssembleH(Jpt, DS, weight * wt_arr[i], At);
65  A += At;
66  }
67 }
68 
71  const TargetConstructor &tc, Vector &weights) const
72 {
73  const int m_cnt = tmop_q_arr.Size();
74  Vector averages;
75  ComputeAvgMetrics(nodes, tc, averages);
76  weights.SetSize(m_cnt);
77 
78  // For [ combo_A_B_C = a m_A + b m_B + c m_C ] we would have:
79  // a = BC / (AB + AC + BC), b = AC / (AB + AC + BC), c = AB / (AB + AC + BC),
80  // where A = avg_m_A, B = avg_m_B, C = avg_m_C.
81  // Nested loop to avoid division, as some avg may be 0.
82  Vector products_no_m(m_cnt); products_no_m = 1.0;
83  for (int m_p = 0; m_p < m_cnt; m_p++)
84  {
85  for (int m_a = 0; m_a < m_cnt; m_a++)
86  {
87  if (m_p != m_a) { products_no_m(m_p) *= averages(m_a); }
88  }
89  }
90  const double pnm_sum = products_no_m.Sum();
91 
92  if (pnm_sum == 0.0) { weights = 1.0 / m_cnt; return; }
93  for (int m = 0; m < m_cnt; m++) { weights(m) = products_no_m(m) / pnm_sum; }
94 
95  MFEM_ASSERT(fabs(weights.Sum() - 1.0) < 1e-14,
96  "Error: sum should be 1 always: " << weights.Sum());
97 }
98 
100  const TargetConstructor &tc,
101  Vector &averages) const
102 {
103  const int m_cnt = tmop_q_arr.Size(),
104  NE = nodes.FESpace()->GetNE(),
105  dim = nodes.FESpace()->GetMesh()->Dimension();
106 
107  averages.SetSize(m_cnt);
108 
109  // Integrals of all metrics.
110  Array<int> pos_dofs;
111  averages = 0.0;
112  double volume = 0.0;
113  for (int e = 0; e < NE; e++)
114  {
115  const FiniteElement &fe_pos = *nodes.FESpace()->GetFE(e);
116  const IntegrationRule &ir = IntRules.Get(fe_pos.GetGeomType(),
117  2 * fe_pos.GetOrder());
118  const int nsp = ir.GetNPoints(), dof = fe_pos.GetDof();
119 
120  DenseMatrix dshape(dof, dim);
121  DenseMatrix pos(dof, dim);
122  pos.SetSize(dof, dim);
123  Vector posV(pos.Data(), dof * dim);
124 
125  nodes.FESpace()->GetElementVDofs(e, pos_dofs);
126  nodes.GetSubVector(pos_dofs, posV);
127 
128  DenseTensor W(dim, dim, nsp);
129  DenseMatrix Winv(dim), T(dim), A(dim);
130  tc.ComputeElementTargets(e, fe_pos, ir, posV, W);
131 
132  for (int q = 0; q < nsp; q++)
133  {
134  const DenseMatrix &Wj = W(q);
135  CalcInverse(Wj, Winv);
136 
137  const IntegrationPoint &ip = ir.IntPoint(q);
138  fe_pos.CalcDShape(ip, dshape);
139  MultAtB(pos, dshape, A);
140  Mult(A, Winv, T);
141 
142  const double w_detA = ip.weight * A.Det();
143  for (int m = 0; m < m_cnt; m++)
144  {
145  tmop_q_arr[m]->SetTargetJacobian(Wj);
146  averages(m) += tmop_q_arr[m]->EvalW(T) * w_detA;
147  }
148  volume += w_detA;
149  }
150  }
151 
152  // Parallel case.
153 #ifdef MFEM_USE_MPI
154  auto par_nodes = dynamic_cast<const ParGridFunction *>(&nodes);
155  if (par_nodes)
156  {
157  MPI_Allreduce(MPI_IN_PLACE, averages.GetData(), m_cnt,
158  MPI_DOUBLE, MPI_SUM, par_nodes->ParFESpace()->GetComm());
159  MPI_Allreduce(MPI_IN_PLACE, &volume, 1, MPI_DOUBLE, MPI_SUM,
160  par_nodes->ParFESpace()->GetComm());
161  }
162 #endif
163 
164  averages /= volume;
165 }
166 
168 const
169 {
170  double metric_tilde = EvalWBarrier(Jpt);
171  double metric = metric_tilde;
173  {
174  metric = std::pow(metric_tilde, exponent);
175  }
176  else if (wctype == WorstCaseType::Beta)
177  {
178  double beta = max_muT+muT_ep;
179  metric = metric_tilde/(beta-metric_tilde);
180  }
181  return metric;
182 }
183 
185  const DenseMatrix &Jpt) const
186 {
187  double denominator = 1.0;
189  {
190  denominator = 2.0*(Jpt.Det()-std::min(alpha*min_detT-detT_ep, 0.0));
191  }
192  else if (btype == BarrierType::Pseudo)
193  {
194  double detT = Jpt.Det();
195  denominator = detT + std::sqrt(detT*detT + detT_ep*detT_ep);
196  }
197  return tmop_metric.EvalW(Jpt)/denominator;
198 }
199 
200 double TMOP_Metric_001::EvalW(const DenseMatrix &Jpt) const
201 {
202  ie.SetJacobian(Jpt.GetData());
203  return ie.Get_I1();
204 }
205 
207 {
208  ie.SetJacobian(Jpt.GetData());
209  P = ie.Get_dI1();
210 }
211 
213  const DenseMatrix &DS,
214  const double weight,
215  DenseMatrix &A) const
216 {
217  ie.SetJacobian(Jpt.GetData());
218  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
219  ie.Assemble_ddI1(weight, A.GetData());
220 }
221 
222 double TMOP_Metric_skew2D::EvalW(const DenseMatrix &Jpt) const
223 {
224  MFEM_VERIFY(Jtr != NULL,
225  "Requires a target Jacobian, use SetTargetJacobian().");
226 
227  DenseMatrix Jpr(2, 2);
228  Mult(Jpt, *Jtr, Jpr);
229 
230  Vector col1, col2;
231  Jpr.GetColumn(0, col1);
232  Jpr.GetColumn(1, col2);
233  double norm_prod = col1.Norml2() * col2.Norml2();
234  const double cos_Jpr = (col1 * col2) / norm_prod,
235  sin_Jpr = fabs(Jpr.Det()) / norm_prod;
236 
237  Jtr->GetColumn(0, col1);
238  Jtr->GetColumn(1, col2);
239  norm_prod = col1.Norml2() * col2.Norml2();
240  const double cos_Jtr = (col1 * col2) / norm_prod,
241  sin_Jtr = fabs(Jtr->Det()) / norm_prod;
242 
243  return 0.5 * (1.0 - cos_Jpr * cos_Jtr - sin_Jpr * sin_Jtr);
244 }
245 
246 double TMOP_Metric_skew3D::EvalW(const DenseMatrix &Jpt) const
247 {
248  MFEM_VERIFY(Jtr != NULL,
249  "Requires a target Jacobian, use SetTargetJacobian().");
250 
251  DenseMatrix Jpr(3, 3);
252  Mult(Jpt, *Jtr, Jpr);
253 
254  Vector col1, col2, col3;
255  Jpr.GetColumn(0, col1);
256  Jpr.GetColumn(1, col2);
257  Jpr.GetColumn(2, col3);
258  double norm_c1 = col1.Norml2(),
259  norm_c2 = col2.Norml2(),
260  norm_c3 = col3.Norml2();
261  double cos_Jpr_12 = (col1 * col2) / (norm_c1 * norm_c2),
262  cos_Jpr_13 = (col1 * col3) / (norm_c1 * norm_c3),
263  cos_Jpr_23 = (col2 * col3) / (norm_c2 * norm_c3);
264  double sin_Jpr_12 = std::sqrt(1.0 - cos_Jpr_12 * cos_Jpr_12),
265  sin_Jpr_13 = std::sqrt(1.0 - cos_Jpr_13 * cos_Jpr_13),
266  sin_Jpr_23 = std::sqrt(1.0 - cos_Jpr_23 * cos_Jpr_23);
267 
268  Jtr->GetColumn(0, col1);
269  Jtr->GetColumn(1, col2);
270  Jtr->GetColumn(2, col3);
271  norm_c1 = col1.Norml2();
272  norm_c2 = col2.Norml2(),
273  norm_c3 = col3.Norml2();
274  double cos_Jtr_12 = (col1 * col2) / (norm_c1 * norm_c2),
275  cos_Jtr_13 = (col1 * col3) / (norm_c1 * norm_c3),
276  cos_Jtr_23 = (col2 * col3) / (norm_c2 * norm_c3);
277  double sin_Jtr_12 = std::sqrt(1.0 - cos_Jtr_12 * cos_Jtr_12),
278  sin_Jtr_13 = std::sqrt(1.0 - cos_Jtr_13 * cos_Jtr_13),
279  sin_Jtr_23 = std::sqrt(1.0 - cos_Jtr_23 * cos_Jtr_23);
280 
281  return (3.0 - cos_Jpr_12 * cos_Jtr_12 - sin_Jpr_12 * sin_Jtr_12
282  - cos_Jpr_13 * cos_Jtr_13 - sin_Jpr_13 * sin_Jtr_13
283  - cos_Jpr_23 * cos_Jtr_23 - sin_Jpr_23 * sin_Jtr_23) / 6.0;
284 }
285 
287 {
288  MFEM_VERIFY(Jtr != NULL,
289  "Requires a target Jacobian, use SetTargetJacobian().");
290 
291  DenseMatrix Jpr(2, 2);
292  Mult(Jpt, *Jtr, Jpr);
293 
294  Vector col1, col2;
295  Jpr.GetColumn(0, col1);
296  Jpr.GetColumn(1, col2);
297  const double ratio_Jpr = col2.Norml2() / col1.Norml2();
298 
299  Jtr->GetColumn(0, col1);
300  Jtr->GetColumn(1, col2);
301  const double ratio_Jtr = col2.Norml2() / col1.Norml2();
302 
303  return 0.5 * (ratio_Jpr / ratio_Jtr + ratio_Jtr / ratio_Jpr) - 1.0;
304 }
305 
307 {
308  MFEM_VERIFY(Jtr != NULL,
309  "Requires a target Jacobian, use SetTargetJacobian().");
310 
311  DenseMatrix Jpr(3, 3);
312  Mult(Jpt, *Jtr, Jpr);
313 
314  Vector col1, col2, col3;
315  Jpr.GetColumn(0, col1);
316  Jpr.GetColumn(1, col2);
317  Jpr.GetColumn(2, col3);
318  double norm_c1 = col1.Norml2(),
319  norm_c2 = col2.Norml2(),
320  norm_c3 = col3.Norml2();
321  double ratio_Jpr_1 = norm_c1 / std::sqrt(norm_c2 * norm_c3),
322  ratio_Jpr_2 = norm_c2 / std::sqrt(norm_c1 * norm_c3),
323  ratio_Jpr_3 = norm_c3 / std::sqrt(norm_c1 * norm_c2);
324 
325  Jtr->GetColumn(0, col1);
326  Jtr->GetColumn(1, col2);
327  Jtr->GetColumn(2, col3);
328  norm_c1 = col1.Norml2();
329  norm_c2 = col2.Norml2();
330  norm_c3 = col3.Norml2();
331  double ratio_Jtr_1 = norm_c1 / std::sqrt(norm_c2 * norm_c3),
332  ratio_Jtr_2 = norm_c2 / std::sqrt(norm_c1 * norm_c3),
333  ratio_Jtr_3 = norm_c3 / std::sqrt(norm_c1 * norm_c2);
334 
335  return ( 0.5 * (ratio_Jpr_1 / ratio_Jtr_1 + ratio_Jtr_1 / ratio_Jpr_1) +
336  0.5 * (ratio_Jpr_2 / ratio_Jtr_2 + ratio_Jtr_2 / ratio_Jpr_2) +
337  0.5 * (ratio_Jpr_3 / ratio_Jtr_3 + ratio_Jtr_3 / ratio_Jpr_3) - 3.0
338  ) / 3.0;
339 }
340 
342 {
343  return 0.5 * Jpt.FNorm2() / Jpt.Det() - 1.0;
344 }
345 
346 double TMOP_Metric_002::EvalW(const DenseMatrix &Jpt) const
347 {
348  ie.SetJacobian(Jpt.GetData());
349  return 0.5 * ie.Get_I1b() - 1.0;
350 }
351 
353 {
354  ie.SetJacobian(Jpt.GetData());
355  P.Set(0.5, ie.Get_dI1b());
356 }
357 
359  const DenseMatrix &DS,
360  const double weight,
361  DenseMatrix &A) const
362 {
363  ie.SetJacobian(Jpt.GetData());
364  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
365  ie.Assemble_ddI1b(0.5*weight, A.GetData());
366 }
367 
368 double TMOP_Metric_004::EvalW(const DenseMatrix &Jpt) const
369 {
370  ie.SetJacobian(Jpt.GetData());
371  return ie.Get_I1() - 2.0*ie.Get_I2b();
372 }
373 
375 {
376  ie.SetJacobian(Jpt.GetData());
377  Add(1.0, ie.Get_dI1(), -2.0, ie.Get_dI2b(), P);
378 }
379 
381  const DenseMatrix &DS,
382  const double weight,
383  DenseMatrix &A) const
384 {
385  ie.SetJacobian(Jpt.GetData());
386  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
387 
388  ie.Assemble_ddI1(weight, A.GetData());
389  ie.Assemble_ddI2b(-2.0*weight, A.GetData());
390 }
391 
392 double TMOP_Metric_007::EvalW(const DenseMatrix &Jpt) const
393 {
394  // mu_7 = |J-J^{-t}|^2 = |J|^2 + |J^{-1}|^2 - 4
395  ie.SetJacobian(Jpt.GetData());
396  return ie.Get_I1()*(1. + 1./ie.Get_I2()) - 4.0;
397 }
398 
400 {
401  // P = d(I1*(1 + 1/I2)) = (1 + 1/I2) dI1 - I1/I2^2 dI2
402  ie.SetJacobian(Jpt.GetData());
403  const double I2 = ie.Get_I2();
404  Add(1. + 1./I2, ie.Get_dI1(), -ie.Get_I1()/(I2*I2), ie.Get_dI2(), P);
405 }
406 
408  const DenseMatrix &DS,
409  const double weight,
410  DenseMatrix &A) const
411 {
412  // P = d(I1*(1 + 1/I2))
413  // = (1 + 1/I2) dI1 - I1/I2^2 dI2
414  //
415  // dP = (-1/I2^2) (dI1 x dI2) + (1 + 1/I2) ddI1 -
416  // (dI2 x d(I1/I2^2)) - I1/I2^2 ddI2
417  // = (-1/I2^2) (dI1 x dI2) + (1 + 1/I2) ddI1 +
418  // (-1/I2^2) (dI2 x [dI1 - 2 I1/I2 dI2]) - I1/I2^2 ddI2
419  // = (-1/I2^2) (dI1 x dI2 + dI2 x dI1) + (1 + 1/I2) ddI1 +
420  // (2 I1/I2^3) (dI2 x dI2) - I1/I2^2 ddI2
421  ie.SetJacobian(Jpt.GetData());
422  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
423  const double c1 = 1./ie.Get_I2();
424  const double c2 = weight*c1*c1;
425  const double c3 = ie.Get_I1()*c2;
426  ie.Assemble_ddI1(weight*(1. + c1), A.GetData());
427  ie.Assemble_ddI2(-c3, A.GetData());
428  ie.Assemble_TProd(-c2, ie.Get_dI1(), ie.Get_dI2(), A.GetData());
429  ie.Assemble_TProd(2*c1*c3, ie.Get_dI2(), A.GetData());
430 }
431 
432 double TMOP_Metric_009::EvalW(const DenseMatrix &Jpt) const
433 {
434  // mu_9 = det(J)*|J-J^{-t}|^2 = I1b * (I2b^2 + 1) - 4 * I2b
435  // = (I1 - 4)*I2b + I1b
436  ie.SetJacobian(Jpt.GetData());
437  return (ie.Get_I1() - 4.0)*ie.Get_I2b() + ie.Get_I1b();
438 }
439 
441 {
442  // mu_9 = (I1 - 4)*I2b + I1b
443  // P = (I1 - 4)*dI2b + I2b*dI1 + dI1b
444  ie.SetJacobian(Jpt.GetData());
445  Add(ie.Get_I1() - 4.0, ie.Get_dI2b(), ie.Get_I2b(), ie.Get_dI1(), P);
446  P += ie.Get_dI1b();
447 }
448 
450  const DenseMatrix &DS,
451  const double weight,
452  DenseMatrix &A) const
453 {
454  // P = (I1 - 4)*dI2b + I2b*dI1 + dI1b
455  // dP = dI2b x dI1 + (I1-4)*ddI2b + dI1 x dI2b + I2b*ddI1 + ddI1b
456  // = (dI1 x dI2b + dI2b x dI1) + (I1-4)*ddI2b + I2b*ddI1 + ddI1b
457  ie.SetJacobian(Jpt.GetData());
458  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
459  ie.Assemble_TProd(weight, ie.Get_dI1(), ie.Get_dI2b(), A.GetData());
460  ie.Assemble_ddI2b(weight*(ie.Get_I1()-4.0), A.GetData());
461  ie.Assemble_ddI1(weight*ie.Get_I2b(), A.GetData());
462  ie.Assemble_ddI1b(weight, A.GetData());
463 }
464 
465 // mu_14 = |T-I|^2
466 double TMOP_Metric_014::EvalW(const DenseMatrix &Jpt) const
467 {
468  MFEM_VERIFY(Jtr != NULL,
469  "Requires a target Jacobian, use SetTargetJacobian().");
470 
471  DenseMatrix Id(2,2);
472 
473  Id(0,0) = 1; Id(0,1) = 0;
474  Id(1,0) = 0; Id(1,1) = 1;
475 
476  DenseMatrix Mat(2,2);
477  Mat = Jpt;
478  Mat.Add(-1,Id);
479  return Mat.FNorm2();
480 }
481 
482 double TMOP_Metric_022::EvalW(const DenseMatrix &Jpt) const
483 {
484  // mu_22 = (0.5*|J|^2 - det(J)) / (det(J) - tau0)
485  // = (0.5*I1 - I2b) / (I2b - tau0)
486  ie.SetJacobian(Jpt.GetData());
487  const double I2b = ie.Get_I2b();
488 
489  double d = I2b - min_detT;
490  if (d < 0.0 && min_detT == 0.0)
491  {
492  // The mesh has been untangled, but it's still possible to get negative
493  // detJ in FD calculations, as they move the nodes around with some small
494  // increments and can produce negative determinants. Thus we put a small
495  // value in the denominator. Note that here I2b < 0.
496  d = - I2b * 0.1;
497  }
498 
499  return (0.5*ie.Get_I1() - I2b) / d;
500 }
501 
503 {
504  // mu_22 = (0.5*I1 - I2b) / (I2b - tau0)
505  // P = 1/(I2b - tau0)*(0.5*dI1 - dI2b) - (0.5*I1 - I2b)/(I2b - tau0)^2*dI2b
506  // = 0.5/(I2b - tau0)*dI1 + (tau0 - 0.5*I1)/(I2b - tau0)^2*dI2b
507  ie.SetJacobian(Jpt.GetData());
508  const double c1 = 1.0/(ie.Get_I2b() - min_detT);
509  Add(c1/2, ie.Get_dI1(), (min_detT - ie.Get_I1()/2)*c1*c1, ie.Get_dI2b(), P);
510 }
511 
513  const DenseMatrix &DS,
514  const double weight,
515  DenseMatrix &A) const
516 {
517  // P = 0.5/(I2b - tau0)*dI1 + (tau0 - 0.5*I1)/(I2b - tau0)^2*dI2b
518  // dP = -0.5/(I2b - tau0)^2*(dI1 x dI2b) + 0.5/(I2b - tau0)*ddI1
519  // + (dI2b x dz) + z*ddI2b
520  //
521  // z = (tau0 - 0.5*I1)/(I2b - tau0)^2
522  // dz = -0.5/(I2b - tau0)^2*dI1 - 2*(tau0 - 0.5*I1)/(I2b - tau0)^3*dI2b
523  //
524  // dP = -0.5/(I2b - tau0)^2*(dI1 x dI2b + dI2b x dI1)
525  // -2*z/(I2b - tau0)*(dI2b x dI2b)
526  // +0.5/(I2b - tau0)*ddI1 + z*ddI2b
527  ie.SetJacobian(Jpt.GetData());
528  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
529  const double c1 = 1.0/(ie.Get_I2b() - min_detT);
530  const double c2 = weight*c1/2;
531  const double c3 = c1*c2;
532  const double c4 = (2*min_detT - ie.Get_I1())*c3; // weight*z
533  ie.Assemble_TProd(-c3, ie.Get_dI1(), ie.Get_dI2b(), A.GetData());
534  ie.Assemble_TProd(-2*c1*c4, ie.Get_dI2b(), A.GetData());
535  ie.Assemble_ddI1(c2, A.GetData());
536  ie.Assemble_ddI2b(c4, A.GetData());
537 }
538 
539 double TMOP_Metric_050::EvalW(const DenseMatrix &Jpt) const
540 {
541  // mu_50 = 0.5*|J^t J|^2/det(J)^2 - 1
542  // = 0.5*(l1^4 + l2^4)/(l1*l2)^2 - 1
543  // = 0.5*((l1/l2)^2 + (l2/l1)^2) - 1 = 0.5*(l1/l2 - l2/l1)^2
544  // = 0.5*(l1/l2 + l2/l1)^2 - 2 = 0.5*I1b^2 - 2
545  ie.SetJacobian(Jpt.GetData());
546  const double I1b = ie.Get_I1b();
547  return 0.5*I1b*I1b - 2.0;
548 }
549 
551 {
552  // mu_50 = 0.5*I1b^2 - 2
553  // P = I1b*dI1b
554  ie.SetJacobian(Jpt.GetData());
555  P.Set(ie.Get_I1b(), ie.Get_dI1b());
556 }
557 
559  const DenseMatrix &DS,
560  const double weight,
561  DenseMatrix &A) const
562 {
563  // P = I1b*dI1b
564  // dP = dI1b x dI1b + I1b*ddI1b
565  ie.SetJacobian(Jpt.GetData());
566  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
567  ie.Assemble_TProd(weight, ie.Get_dI1b(), A.GetData());
568  ie.Assemble_ddI1b(weight*ie.Get_I1b(), A.GetData());
569 }
570 
571 double TMOP_Metric_055::EvalW(const DenseMatrix &Jpt) const
572 {
573  // mu_55 = (det(J) - 1)^2 = (I2b - 1)^2
574  ie.SetJacobian(Jpt.GetData());
575  const double c1 = ie.Get_I2b() - 1.0;
576  return c1*c1;
577 }
578 
580 {
581  // mu_55 = (I2b - 1)^2
582  // P = 2*(I2b - 1)*dI2b
583  ie.SetJacobian(Jpt.GetData());
584  P.Set(2*(ie.Get_I2b() - 1.0), ie.Get_dI2b());
585 }
586 
588  const DenseMatrix &DS,
589  const double weight,
590  DenseMatrix &A) const
591 {
592  // P = 2*(I2b - 1)*dI2b
593  // dP = 2*(dI2b x dI2b) + 2*(I2b - 1)*ddI2b
594  ie.SetJacobian(Jpt.GetData());
595  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
596  ie.Assemble_TProd(2*weight, ie.Get_dI2b(), A.GetData());
597  ie.Assemble_ddI2b(2*weight*(ie.Get_I2b() - 1.0), A.GetData());
598 }
599 
600 double TMOP_Metric_056::EvalW(const DenseMatrix &Jpt) const
601 {
602  // mu_56 = 0.5*(I2b + 1/I2b) - 1
603  ie.SetJacobian(Jpt.GetData());
604  const double I2b = ie.Get_I2b();
605  return 0.5*(I2b + 1.0/I2b) - 1.0;
606 }
607 
609 {
610  // mu_56 = 0.5*(I2b + 1/I2b) - 1
611  // P = 0.5*(1 - 1/I2b^2)*dI2b
612  ie.SetJacobian(Jpt.GetData());
613  P.Set(0.5 - 0.5/ie.Get_I2(), ie.Get_dI2b());
614 }
615 
617  const DenseMatrix &DS,
618  const double weight,
619  DenseMatrix &A) const
620 {
621  // P = 0.5*(1 - 1/I2b^2)*dI2b
622  // dP = (1/I2b^3)*(dI2b x dI2b) + (0.5 - 0.5/I2)*ddI2b
623  ie.SetJacobian(Jpt.GetData());
624  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
625  ie.Assemble_TProd(weight/(ie.Get_I2()*ie.Get_I2b()),
626  ie.Get_dI2b(), A.GetData());
627  ie.Assemble_ddI2b(weight*(0.5 - 0.5/ie.Get_I2()), A.GetData());
628 }
629 
631 {
632  // mu_58 = |J^t J|^2 / det(J)^2 - 2|J|^2 / det(J) + 2
633  DenseMatrix JtJ(2);
634  MultAAt(Jpt, JtJ);
635  JtJ.Transpose();
636  double det = Jpt.Det();
637 
638  return JtJ.FNorm2()/(det*det) - 2*Jpt.FNorm2()/det + 2.0;
639 }
640 
641 double TMOP_Metric_058::EvalW(const DenseMatrix &Jpt) const
642 {
643  // mu_58 = I1b*(I1b - 2)
644  ie.SetJacobian(Jpt.GetData());
645  const double I1b = ie.Get_I1b();
646  return I1b*(I1b - 2.0);
647 }
648 
650 {
651  // mu_58 = I1b*(I1b - 2)
652  // P = (2*I1b - 2)*dI1b
653  ie.SetJacobian(Jpt.GetData());
654  P.Set(2*ie.Get_I1b() - 2.0, ie.Get_dI1b());
655 }
656 
658  const DenseMatrix &DS,
659  const double weight,
660  DenseMatrix &A) const
661 {
662  // P = (2*I1b - 2)*dI1b
663  // dP = 2*(dI1b x dI1b) + (2*I1b - 2)*ddI1b
664  ie.SetJacobian(Jpt.GetData());
665  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
666  ie.Assemble_TProd(2*weight, ie.Get_dI1b(), A.GetData());
667  ie.Assemble_ddI1b(weight*(2*ie.Get_I1b() - 2.0), A.GetData());
668 }
669 
670 double TMOP_Metric_077::EvalW(const DenseMatrix &Jpt) const
671 {
672  ie.SetJacobian(Jpt.GetData());
673  const double I2b = ie.Get_I2b();
674  return 0.5*(I2b*I2b + 1./(I2b*I2b) - 2.);
675 }
676 
678 {
679  // Using I2b^2 = I2.
680  // dmu77_dJ = 1/2 (1 - 1/I2^2) dI2_dJ.
681  ie.SetJacobian(Jpt.GetData());
682  const double I2 = ie.Get_I2();
683  P.Set(0.5 * (1.0 - 1.0 / (I2 * I2)), ie.Get_dI2());
684 }
685 
687  const DenseMatrix &DS,
688  const double weight,
689  DenseMatrix &A) const
690 {
691  ie.SetJacobian(Jpt.GetData());
692  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
693  const double I2 = ie.Get_I2(), I2inv_sq = 1.0 / (I2 * I2);
694  ie.Assemble_ddI2(weight*0.5*(1.0 - I2inv_sq), A.GetData());
695  ie.Assemble_TProd(weight * I2inv_sq / I2, ie.Get_dI2(), A.GetData());
696 }
697 
698 // mu_85 = |T-T'|^2, where T'= |T|*I/sqrt(2)
699 double TMOP_Metric_085::EvalW(const DenseMatrix &Jpt) const
700 {
701  MFEM_VERIFY(Jtr != NULL,
702  "Requires a target Jacobian, use SetTargetJacobian().");
703 
704  DenseMatrix Id(2,2);
705  DenseMatrix Mat(2,2);
706  Mat = Jpt;
707 
708  Id(0,0) = 1; Id(0,1) = 0;
709  Id(1,0) = 0; Id(1,1) = 1;
710  Id *= Mat.FNorm()/pow(2,0.5);
711 
712  Mat.Add(-1.,Id);
713  return Mat.FNorm2();
714 }
715 
716 // mu_98 = 1/(tau)|T-I|^2
717 double TMOP_Metric_098::EvalW(const DenseMatrix &Jpt) const
718 {
719  MFEM_VERIFY(Jtr != NULL,
720  "Requires a target Jacobian, use SetTargetJacobian().");
721 
722  DenseMatrix Id(2,2);
723 
724  Id(0,0) = 1; Id(0,1) = 0;
725  Id(1,0) = 0; Id(1,1) = 1;
726 
727  DenseMatrix Mat(2,2);
728  Mat = Jpt;
729  Mat.Add(-1,Id);
730  return Mat.FNorm2()/Jtr->Det();
731 }
732 
733 double TMOP_Metric_211::EvalW(const DenseMatrix &Jpt) const
734 {
735  // mu_211 = (det(J) - 1)^2 - det(J) + (det(J)^2 + eps)^{1/2}
736  // = (I2b - 1)^2 - I2b + sqrt(I2b^2 + eps)
737  ie.SetJacobian(Jpt.GetData());
738  const double I2b = ie.Get_I2b();
739  return (I2b - 1.0)*(I2b - 1.0) - I2b + std::sqrt(I2b*I2b + eps);
740 }
741 
743 {
744  MFEM_ABORT("Metric not implemented yet. Use metric mu_55 instead.");
745 }
746 
748  const DenseMatrix &DS,
749  const double weight,
750  DenseMatrix &A) const
751 {
752  MFEM_ABORT("Metric not implemented yet. Use metric mu_55 instead.");
753 }
754 
755 double TMOP_Metric_252::EvalW(const DenseMatrix &Jpt) const
756 {
757  // mu_252 = 0.5*(det(J) - 1)^2 / (det(J) - tau0).
758  ie.SetJacobian(Jpt.GetData());
759  const double I2b = ie.Get_I2b();
760  return 0.5*(I2b - 1.0)*(I2b - 1.0)/(I2b - tau0);
761 }
762 
764 {
765  // mu_252 = 0.5*(det(J) - 1)^2 / (det(J) - tau0)
766  // P = (c - 0.5*c*c ) * dI2b
767  //
768  // c = (I2b - 1)/(I2b - tau0), see TMOP_Metric_352 for details
769  ie.SetJacobian(Jpt.GetData());
770  const double I2b = ie.Get_I2b();
771  const double c = (I2b - 1.0)/(I2b - tau0);
772  P.Set(c - 0.5*c*c, ie.Get_dI2b());
773 }
774 
776  const DenseMatrix &DS,
777  const double weight,
778  DenseMatrix &A) const
779 {
780  // c = (I2b - 1)/(I2b - tau0), see TMOP_Metric_352 for details
781  //
782  // P = (c - 0.5*c*c ) * dI2b
783  // dP = (1 - c)^2/(I2b - tau0)*(dI2b x dI2b) + (c - 0.5*c*c)*ddI2b
784  ie.SetJacobian(Jpt.GetData());
785  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
786  const double I2b = ie.Get_I2b();
787  const double c0 = 1.0/(I2b - tau0);
788  const double c = c0*(I2b - 1.0);
789  ie.Assemble_TProd(weight*c0*(1.0 - c)*(1.0 - c), ie.Get_dI2b(), A.GetData());
790  ie.Assemble_ddI2b(weight*(c - 0.5*c*c), A.GetData());
791 }
792 
794 {
795  // mu_301 = 1/3 |J| |J^-1| - 1.
796  ie.SetJacobian(Jpt.GetData());
797  DenseMatrix inv(3);
798  CalcInverse(Jpt, inv);
799  return Jpt.FNorm() * inv.FNorm() / 3.0 - 1.0;
800 }
801 
802 double TMOP_Metric_301::EvalW(const DenseMatrix &Jpt) const
803 {
804  // mu_301 = 1/3 sqrt(I1b * I2b) - 1
805  ie.SetJacobian(Jpt.GetData());
806  return std::sqrt(ie.Get_I1b()*ie.Get_I2b())/3. - 1.;
807 }
808 
810 {
811  // W = (1/3)*sqrt(I1b*I2b) - 1
812  // dW = (1/6)/sqrt(I1b*I2b)*[I2b*dI1b + I1b*dI2b]
813  ie.SetJacobian(Jpt.GetData());
814  const double a = 1./(6.*std::sqrt(ie.Get_I1b()*ie.Get_I2b()));
815  Add(a*ie.Get_I2b(), ie.Get_dI1b(), a*ie.Get_I1b(), ie.Get_dI2b(), P);
816 }
817 
819  const DenseMatrix &DS,
820  const double weight,
821  DenseMatrix &A) const
822 {
823  // dW = (1/6)/sqrt(I1b*I2b)*[I2b*dI1b + I1b*dI2b]
824  // dW = (1/6)*[z2*dI1b + z1*dI2b], z1 = sqrt(I1b/I2b), z2 = sqrt(I2b/I1b)
825  // ddW = (1/6)*[dI1b x dz2 + z2*ddI1b + dI2b x dz1 + z1*ddI2b]
826  //
827  // dz1 = (1/2)*sqrt(I2b/I1b) [ (1/I2b)*dI1b - (I1b/(I2b*I2b))*dI2b ]
828  // = (1/2)/sqrt(I1b*I2b) [ dI1b - (I1b/I2b)*dI2b ]
829  // dz2 = (1/2)/sqrt(I1b*I2b) [ dI2b - (I2b/I1b)*dI1b ]
830  //
831  // dI1b x dz2 + dI2b x dz1 =
832  // (1/2)/sqrt(I1b*I2b) dI1b x [ dI2b - (I2b/I1b)*dI1b ] +
833  // (1/2)/sqrt(I1b*I2b) dI2b x [ dI1b - (I1b/I2b)*dI2b ] =
834  // (1/2)/sqrt(I1b*I2b) [sqrt(I1b/I2b)*dI2b - sqrt(I2b/I1b)*dI1b] x
835  // [sqrt(I2b/I1b)*dI1b - sqrt(I1b/I2b)*dI2b] =
836  // (1/2)*(I1b*I2b)^{-3/2} (I1b*dI2b - I2b*dI1b) x (I2b*dI1b - I1b*dI2b)
837  // and the last two parentheses are the same up to a sign.
838  //
839  // z1 = I1b/sqrt(I1b*I2b), z2 = I2b/sqrt(I1b*I2b)
840 
841  ie.SetJacobian(Jpt.GetData());
842  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
843  double X_data[9];
844  DenseMatrix X(X_data, 3, 3);
845  Add(- ie.Get_I2b(), ie.Get_dI1b(), ie.Get_I1b(), ie.Get_dI2b(), X);
846  const double I1b_I2b = ie.Get_I1b()*ie.Get_I2b();
847  const double a = weight/(6*std::sqrt(I1b_I2b));
850  ie.Assemble_TProd(-a/(2*I1b_I2b), X_data, A.GetData());
851 }
852 
854 {
855  // mu_301 = |J|^2 |J^{-1}|^2 / 9 - 1.
856  ie.SetJacobian(Jpt.GetData());
857  DenseMatrix inv(3);
858  CalcInverse(Jpt, inv);
859  return Jpt.FNorm2() * inv.FNorm2() / 9.0 - 1.0;
860 }
861 
862 double TMOP_Metric_302::EvalW(const DenseMatrix &Jpt) const
863 {
864  // mu_2 = |J|^2 |J^{-1}|^2 / 9 - 1
865  // = (l1^2 + l2^2 + l3^3)*(l1^{-2} + l2^{-2} + l3^{-2}) / 9 - 1
866  // = I1*(l2^2*l3^2 + l1^2*l3^2 + l1^2*l2^2)/l1^2/l2^2/l3^2/9 - 1
867  // = I1*I2/det(J)^2/9 - 1 = I1b*I2b/9-1
868  ie.SetJacobian(Jpt.GetData());
869  return ie.Get_I1b()*ie.Get_I2b()/9. - 1.;
870 }
871 
873 {
874  // mu_2 = I1b*I2b/9-1
875  // P = (I1b/9)*dI2b + (I2b/9)*dI1b
876  ie.SetJacobian(Jpt.GetData());
877  Add(ie.Get_I1b()/9, ie.Get_dI2b(), ie.Get_I2b()/9, ie.Get_dI1b(), P);
878 }
879 
881  const DenseMatrix &DS,
882  const double weight,
883  DenseMatrix &A) const
884 {
885  // P = (I1b/9)*dI2b + (I2b/9)*dI1b
886  // dP = (dI2b x dI1b)/9 + (I1b/9)*ddI2b + (dI1b x dI2b)/9 + (I2b/9)*ddI1b
887  // = (dI2b x dI1b + dI1b x dI2b)/9 + (I1b/9)*ddI2b + (I2b/9)*ddI1b
888  ie.SetJacobian(Jpt.GetData());
889  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
890  const double c1 = weight/9;
891  ie.Assemble_TProd(c1, ie.Get_dI1b(), ie.Get_dI2b(), A.GetData());
892  ie.Assemble_ddI2b(c1*ie.Get_I1b(), A.GetData());
893  ie.Assemble_ddI1b(c1*ie.Get_I2b(), A.GetData());
894 }
895 
897 {
898  // mu_303 = |J|^2 / 3 / det(J)^(2/3) - 1.
899  ie.SetJacobian(Jpt.GetData());
900  return Jpt.FNorm2() / 3.0 / pow(Jpt.Det(), 2.0 / 3.0) - 1.0;
901 }
902 
903 double TMOP_Metric_303::EvalW(const DenseMatrix &Jpt) const
904 {
905  // mu_303 = |J|^2 / 3 / det(J)^(2/3) - 1 = I1b/3 - 1.
906  ie.SetJacobian(Jpt.GetData());
907  return ie.Get_I1b()/3.0 - 1.0;
908 }
909 
911 {
912  // mu_304 = I1b/3 - 1.
913  // P = dI1b/3.
914  ie.SetJacobian(Jpt.GetData());
915  P.Set(1./3., ie.Get_dI1b());
916 }
917 
919  const DenseMatrix &DS,
920  const double weight,
921  DenseMatrix &A) const
922 {
923  // P = dI1b/3.
924  // dP = ddI1b/3.
925  ie.SetJacobian(Jpt.GetData());
926  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
927  ie.Assemble_ddI1b(weight/3., A.GetData());
928 }
929 
931 {
932  // mu_304 = |J|^3 / 3^(3/2) / det(J) - 1
933  const double fnorm = Jpt.FNorm();
934  return fnorm * fnorm * fnorm / pow(3.0, 1.5) / Jpt.Det() - 1.0;
935 }
936 
937 double TMOP_Metric_304::EvalW(const DenseMatrix &Jpt) const
938 {
939  // mu_304 = (I1b/3)^3/2 - 1.
940  ie.SetJacobian(Jpt.GetData());
941  return pow(ie.Get_I1b()/3.0, 1.5) - 1.0;
942 }
943 
945 {
946  // mu_304 = (I1b/3)^3/2 - 1.
947  // P = 3/2 * (I1b/3)^1/2 * dI1b / 3 = 1/2 * (I1b/3)^1/2 * dI1b.
948  ie.SetJacobian(Jpt.GetData());
949  P.Set(0.5 * sqrt(ie.Get_I1b()/3.0), ie.Get_dI1b());
950 }
951 
953  const double weight, DenseMatrix &A) const
954 {
955  // P = 1/2 * (I1b/3)^1/2 * dI1b.
956  // dP = 1/12 * (I1b/3)^(-1/2) * (dI1b x dI1b) + 1/2 * (I1b/3)^1/2 * ddI1b.
957  ie.SetJacobian(Jpt.GetData());
958  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
959  ie.Assemble_TProd(weight / 12.0 / sqrt(ie.Get_I1b()/3.0),
960  ie.Get_dI1b(), A.GetData());
961  ie.Assemble_ddI1b(weight / 2.0 * sqrt(ie.Get_I1b()/3.0), A.GetData());
962 }
963 
964 double TMOP_Metric_311::EvalW(const DenseMatrix &Jpt) const
965 {
966  // mu_311 = (det(J) - 1)^2 - det(J) + (det(J)^2 + eps)^{1/2}
967  // = (I3b - 1)^2 - I3b + sqrt(I3b^2 + eps)
968  ie.SetJacobian(Jpt.GetData());
969  const double I3b = ie.Get_I3b();
970  return (I3b - 1.0)*(I3b - 1.0) - I3b + std::sqrt(I3b*I3b + eps);
971 }
972 
974 {
975  ie.SetJacobian(Jpt.GetData());
976  const double I3b = ie.Get_I3b();
977  const double c = 2*I3b-3+(I3b)/(std::pow((I3b*I3b+eps),0.5));
978  P.Set(c, ie.Get_dI3b());
979 }
980 
982  const DenseMatrix &DS,
983  const double weight,
984  DenseMatrix &A) const
985 {
986  ie.SetJacobian(Jpt.GetData());
987  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
988  const double I3b = ie.Get_I3b();
989  const double c0 = I3b*I3b+eps;
990  const double c1 = 2 + 1/(pow(c0,0.5)) - I3b*I3b/(pow(c0,1.5));
991  const double c2 = 2*I3b - 3 + I3b/(pow(c0,0.5));
992  ie.Assemble_TProd(weight*c1, ie.Get_dI3b(), A.GetData());
993  ie.Assemble_ddI3b(c2*weight, A.GetData());
994 }
995 
996 double TMOP_Metric_313::EvalW(const DenseMatrix &Jpt) const
997 {
998  ie.SetJacobian(Jpt.GetData());
999 
1000  const double I3b = ie.Get_I3b();
1001  double d = I3b - min_detT;
1002  if (d < 0.0 && min_detT == 0.0)
1003  {
1004  // The mesh has been untangled, but it's still possible to get negative
1005  // detJ in FD calculations, as they move the nodes around with some small
1006  // increments and can produce negative determinants. Thus we put a small
1007  // value in the denominator. Note that here I3b < 0.
1008  d = - I3b * 0.1;
1009  }
1010 
1011  const double c = std::pow(d, -2.0/3.0);
1012 
1013  return ie.Get_I1() * c / 3.0;
1014 }
1015 
1017 {
1018  MFEM_ABORT("Metric not implemented yet.");
1019 }
1020 
1022  const DenseMatrix &DS,
1023  const double weight,
1024  DenseMatrix &A) const
1025 {
1026  MFEM_ABORT("Metric not implemented yet.");
1027 }
1028 
1029 double TMOP_Metric_315::EvalW(const DenseMatrix &Jpt) const
1030 {
1031  // mu_315 = mu_15_3D = (det(J) - 1)^2
1032  ie.SetJacobian(Jpt.GetData());
1033  const double c1 = ie.Get_I3b() - 1.0;
1034  return c1*c1;
1035 }
1036 
1038 {
1039  // mu_315 = (I3b - 1)^2
1040  // P = 2*(I3b - 1)*dI3b
1041  ie.SetJacobian(Jpt.GetData());
1042  P.Set(2*(ie.Get_I3b() - 1.0), ie.Get_dI3b());
1043 }
1044 
1046  const DenseMatrix &DS,
1047  const double weight,
1048  DenseMatrix &A) const
1049 {
1050  // P = 2*(I3b - 1)*dI3b
1051  // dP = 2*(dI3b x dI3b) + 2*(I3b - 1)*ddI3b
1052  ie.SetJacobian(Jpt.GetData());
1053  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
1054  ie.Assemble_TProd(2*weight, ie.Get_dI3b(), A.GetData());
1055  ie.Assemble_ddI3b(2*weight*(ie.Get_I3b() - 1.0), A.GetData());
1056 }
1057 
1059 {
1060  // mu_316 = 0.5 (det(J) + 1/det(J)) - 1.
1061  return 0.5 * (Jpt.Det() + 1.0 / Jpt.Det()) - 1.0;
1062 }
1063 
1064 double TMOP_Metric_316::EvalW(const DenseMatrix &Jpt) const
1065 {
1066  // mu_316 = mu_16_3D = 0.5*(I3b + 1/I3b) - 1
1067  ie.SetJacobian(Jpt.GetData());
1068  const double I3b = ie.Get_I3b();
1069  return 0.5*(I3b + 1.0/I3b) - 1.0;
1070 }
1071 
1073 {
1074  // mu_316 = mu_16_3D = 0.5*(I3b + 1/I3b) - 1
1075  // P = 0.5*(1 - 1/I3b^2)*dI3b = (0.5 - 0.5/I3)*dI3b
1076  ie.SetJacobian(Jpt.GetData());
1077  P.Set(0.5 - 0.5/ie.Get_I3(), ie.Get_dI3b());
1078 }
1079 
1081  const DenseMatrix &DS,
1082  const double weight,
1083  DenseMatrix &A) const
1084 {
1085  // P = 0.5*(1 - 1/I3b^2)*dI3b = (0.5 - 0.5/I3)*dI3b
1086  // dP = (1/I3b^3)*(dI3b x dI3b) + (0.5 - 0.5/I3)*ddI3b
1087  ie.SetJacobian(Jpt.GetData());
1088  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
1089  ie.Assemble_TProd(weight/(ie.Get_I3()*ie.Get_I3b()),
1090  ie.Get_dI3b(), A.GetData());
1091  ie.Assemble_ddI3b(weight*(0.5 - 0.5/ie.Get_I3()), A.GetData());
1092 }
1093 
1095 {
1096  // mu_321 = |J - J^-t|^2.
1097  ie.SetJacobian(Jpt.GetData());
1098  DenseMatrix invt(3);
1099  CalcInverseTranspose(Jpt, invt);
1100  invt.Add(-1.0, Jpt);
1101  return invt.FNorm2();
1102 }
1103 
1104 double TMOP_Metric_321::EvalW(const DenseMatrix &Jpt) const
1105 {
1106  // mu_321 = mu_21_3D = |J - J^{-t}|^2
1107  // = |J|^2 + |J^{-1}|^2 - 6
1108  // = |J|^2 + (l1^{-2} + l2^{-2} + l3^{-2}) - 6
1109  // = |J|^2 + (l2^2*l3^2 + l1^2*l3^2 + l1^2*l2^2)/det(J)^2 - 6
1110  // = I1 + I2/I3b^2 - 6 = I1 + I2/I3 - 6
1111  ie.SetJacobian(Jpt.GetData());
1112  return ie.Get_I1() + ie.Get_I2()/ie.Get_I3() - 6.0;
1113 }
1114 
1116 {
1117  // mu_321 = I1 + I2/I3b^2 - 6 = I1 + I2/I3 - 6
1118  // P = dI1 + (1/I3)*dI2 - (2*I2/I3b^3)*dI3b
1119  ie.SetJacobian(Jpt.GetData());
1120  const double I3 = ie.Get_I3();
1121  Add(1.0/I3, ie.Get_dI2(),
1122  -2*ie.Get_I2()/(I3*ie.Get_I3b()), ie.Get_dI3b(), P);
1123  P += ie.Get_dI1();
1124 }
1125 
1127  const DenseMatrix &DS,
1128  const double weight,
1129  DenseMatrix &A) const
1130 {
1131  // P = dI1 + (1/I3)*dI2 - (2*I2/I3b^3)*dI3b
1132  // dP = ddI1 + (-2/I3b^3)*(dI2 x dI3b) + (1/I3)*ddI2 + (dI3b x dz) + z*ddI3b
1133  //
1134  // z = -2*I2/I3b^3
1135  // dz = (-2/I3b^3)*dI2 + (2*I2)*(3/I3b^4)*dI3b
1136  //
1137  // dP = ddI1 + (-2/I3b^3)*(dI2 x dI3b + dI3b x dI2) + (1/I3)*ddI2
1138  // + (6*I2/I3b^4)*(dI3b x dI3b) + (-2*I2/I3b^3)*ddI3b
1139  ie.SetJacobian(Jpt.GetData());
1140  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
1141  const double c0 = 1.0/ie.Get_I3b();
1142  const double c1 = weight*c0*c0;
1143  const double c2 = -2*c0*c1;
1144  const double c3 = c2*ie.Get_I2();
1145  ie.Assemble_ddI1(weight, A.GetData());
1146  ie.Assemble_ddI2(c1, A.GetData());
1147  ie.Assemble_ddI3b(c3, A.GetData());
1148  ie.Assemble_TProd(c2, ie.Get_dI2(), ie.Get_dI3b(), A.GetData());
1149  ie.Assemble_TProd(-3*c0*c3, ie.Get_dI3b(), A.GetData());
1150 }
1151 
1153 {
1154  // mu_322 = 1 / (6 det(J)) |J - adj(J)^t|^2
1155  DenseMatrix adj_J_t(3);
1156  CalcAdjugateTranspose(Jpt, adj_J_t);
1157  adj_J_t *= -1.0;
1158  adj_J_t.Add(1.0, Jpt);
1159  return 1.0 / 6.0 / Jpt.Det() * adj_J_t.FNorm2();
1160 }
1161 
1162 double TMOP_Metric_322::EvalW(const DenseMatrix &Jpt) const
1163 {
1164  // mu_322 = 1 / (6 det(J)) |J - adj(J)^t|^2
1165  // = 1 / (6 det(J)) |J|^2 + 1/6 det(J) |J^{-1}|^2 - 1
1166  // = I1b / (I3b^-1/3) / 6 + I2b (I3b^1/3) / 6 - 1
1167  ie.SetJacobian(Jpt.GetData());
1168 
1169  return ie.Get_I1b() / pow(ie.Get_I3b(), 1.0/3.0) / 6.0 +
1170  ie.Get_I2b() * pow(ie.Get_I3b(), 1.0/3.0) / 6.0 - 1.0;
1171 }
1172 
1174 {
1175  // mu_322 = I1b (I3b^-1/3) / 6 + I2b (I3b^1/3) / 6 - 1
1176  // P = 1/6 (I3b^-1/3) dI1b - 1/18 I1b (I3b^-4/3) dI3b
1177  // + 1/6 (I3b^1/3) dI2b + 1/18 I2b (I3b^-2/3) dI3b
1178  ie.SetJacobian(Jpt.GetData());
1179  P.Set(1.0/6.0 * pow(ie.Get_I3b(), -1.0/3.0),
1180  ie.Get_dI1b());
1181  P.Add(-1.0/18.0 * ie.Get_I1b() * pow(ie.Get_I3b(), -4.0/3.0),
1182  ie.Get_dI3b());
1183  P.Add(1.0/6.0 * pow(ie.Get_I3b(), 1.0/3.0),
1184  ie.Get_dI2b());
1185  P.Add(1.0/18.0 * ie.Get_I2b() * pow(ie.Get_I3b(), -2.0/3.0),
1186  ie.Get_dI3b());
1187 }
1188 
1190  const double weight, DenseMatrix &A) const
1191 {
1192  // P = 1/6 (I3b^-1/3) dI1b - 1/18 I1b (I3b^-4/3) dI3b
1193  // + 1/6 (I3b^1/3) dI2b + 1/18 I2b (I3b^-2/3) dI3b
1194  // dP = 1/6 (I3b^-1/3) ddI1b - 1/18 (I3b^-4/3) (dI1b x dI3b)
1195  // - 1/18 I1b (I3b^-4/3) ddI3b
1196  // - 1/18 (I3b^-4/3) (dI3b x dI1b)
1197  // + 2/27 I1b (I3b^-7/3) (dI3b x dI3b)
1198  // + 1/6 (I3b^1/3) ddI2b + 1/18 (I3b^-2/3) (dI2b x dI3b)
1199  // + 1/18 I2b (I3b^-2/3) ddI3b
1200  // + 1/18 (I3b^-2/3) (dI3b x dI2b)
1201  // - 1/27 I2b (I3b^-5/3) (dI3b x dI3b)
1202  ie.SetJacobian(Jpt.GetData());
1203  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
1204  const double p13 = weight * pow(ie.Get_I3b(), 1.0/3.0),
1205  m13 = weight * pow(ie.Get_I3b(), -1.0/3.0),
1206  m23 = weight * pow(ie.Get_I3b(), -2.0/3.0),
1207  m43 = weight * pow(ie.Get_I3b(), -4.0/3.0),
1208  m53 = weight * pow(ie.Get_I3b(), -5.0/3.0),
1209  m73 = weight * pow(ie.Get_I3b(), -7.0/3.0);
1210  ie.Assemble_ddI1b(1.0/6.0 * m13, A.GetData());
1211  // Combines - 1/18 (I3b^-4/3) (dI1b x dI3b) - 1/18 (I3b^-4/3) (dI3b x dI1b).
1212  ie.Assemble_TProd(-1.0/18.0 * m43,
1213  ie.Get_dI1b(), ie.Get_dI3b(), A.GetData());
1214  ie.Assemble_ddI3b(-1.0/18.0 * ie.Get_I1b() * m43, A.GetData());
1215  ie.Assemble_TProd(2.0/27.0 * ie.Get_I1b() * m73,
1216  ie.Get_dI3b(), A.GetData());
1217  ie.Assemble_ddI2b(1.0/6.0 * p13, A.GetData());
1218  // Combines + 1/18 (I3b^-2/3) (dI2b x dI3b) + 1/18 (I3b^-2/3) (dI3b x dI2b).
1219  ie.Assemble_TProd(1.0/18.0 * m23,
1220  ie.Get_dI2b(), ie.Get_dI3b(), A.GetData());
1221  ie.Assemble_ddI3b(1.0/18.0 * ie.Get_I2b() * m23, A.GetData());
1222  ie.Assemble_TProd(-1.0/27.0 * ie.Get_I2b() * m53,
1223  ie.Get_dI3b(), A.GetData());
1224 }
1225 
1227 {
1228  // mu_323 = |J|^3 - 3 sqrt(3) ln(det(J)) - 3 sqrt(3).
1229  double fnorm = Jpt.FNorm();
1230  return fnorm * fnorm * fnorm - 3.0 * sqrt(3.0) * (log(Jpt.Det()) + 1.0);
1231 }
1232 
1233 double TMOP_Metric_323::EvalW(const DenseMatrix &Jpt) const
1234 {
1235  // mu_323 = I1^3/2 - 3 sqrt(3) ln(I3b) - 3 sqrt(3).
1236  ie.SetJacobian(Jpt.GetData());
1237  return pow(ie.Get_I1(), 1.5) - 3.0 * sqrt(3.0) * (log(ie.Get_I3b()) + 1.0);
1238 }
1239 
1241 {
1242  // mu_323 = I1^3/2 - 3 sqrt(3) ln(I3b) - 3 sqrt(3).
1243  // P = 3/2 (I1^1/2) dI1 - 3 sqrt(3) (I3b^-1) dI3b.
1244  ie.SetJacobian(Jpt.GetData());
1245  P.Set(1.5 * sqrt(ie.Get_I1()), ie.Get_dI1());
1246  P.Add(- 3.0 * sqrt(3.0) / ie.Get_I3b(), ie.Get_dI3b());
1247 }
1248 
1250  const double weight, DenseMatrix &A) const
1251 {
1252  // P = 3/2 (I1^1/2) dI1 - 3 sqrt(3) (I3b^-1) dI3b
1253  // dP = 3/2 (I1^1/2) ddI1 + 3/4 (I1^-1/2) (dI1 x dI1)
1254  // - 3 sqrt(3) (I3b^-1) ddI3b + 3 sqrt(3) (I3b^-2) (dI3b x dI3b)
1255  ie.SetJacobian(Jpt.GetData());
1256  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
1257  ie.Assemble_ddI1(weight * 1.5 * sqrt(ie.Get_I1()), A.GetData());
1258  ie.Assemble_TProd(weight * 0.75 / sqrt(ie.Get_I1()),
1259  ie.Get_dI1(), A.GetData());
1260  ie.Assemble_ddI3b(- weight * 3.0 * sqrt(3.0) / ie.Get_I3b(), A.GetData());
1261  ie.Assemble_TProd(weight * 3.0 * sqrt(3.0) / ie.Get_I3b() / ie.Get_I3b(),
1262  ie.Get_dI3b(), A.GetData());
1263 }
1264 
1265 double TMOP_Metric_352::EvalW(const DenseMatrix &Jpt) const
1266 {
1267  // mu_352 = 0.5*(det(J) - 1)^2 / (det(J) - tau0)
1268  ie.SetJacobian(Jpt.GetData());
1269  const double I3b = ie.Get_I3b();
1270  return 0.5*(I3b - 1.0)*(I3b - 1.0)/(I3b - tau0);
1271 }
1272 
1274 {
1275  // mu_352 = 0.5*(det(J) - 1)^2 / (det(J) - tau0)
1276  // P = (I3b - 1)/(I3b - tau0)*dI3b + 0.5*(I3b - 1)^2*(-1/(I3b - tau0)^2)*dI3b
1277  // = [ (I3b - 1)/(I3b - tau0) - 0.5*(I3b - 1)^2/(I3b - tau0)^2 ] * dI3b
1278  // = (c - 0.5*c*c) * dI3b
1279  ie.SetJacobian(Jpt.GetData());
1280  const double I3b = ie.Get_I3b();
1281  const double c = (I3b - 1.0)/(I3b - tau0);
1282  P.Set(c - 0.5*c*c, ie.Get_dI3b());
1283 }
1284 
1286  const DenseMatrix &DS,
1287  const double weight,
1288  DenseMatrix &A) const
1289 {
1290  // c = (I3b - 1)/(I3b - tau0)
1291  //
1292  // P = (c - 0.5*c*c) * dI3b
1293  // dP = (1 - c)*(dI3b x dc) + (c - 0.5*c*c)*ddI3b
1294  //
1295  // dc = 1/(I3b - tau0)*dI3b - (I3b - 1)/(I3b - tau)^2*dI3b =
1296  // = (1 - c)/(I3b - tau0)*dI3b
1297  //
1298  // dP = (1 - c)^2/(I3b - tau0)*(dI3b x dI3b) + (c - 0.5*c*c)*ddI3b
1299  ie.SetJacobian(Jpt.GetData());
1300  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
1301  const double I3b = ie.Get_I3b();
1302  const double c0 = 1.0/(I3b - tau0);
1303  const double c = c0*(I3b - 1.0);
1304  ie.Assemble_TProd(weight*c0*(1.0 - c)*(1.0 - c), ie.Get_dI3b(), A.GetData());
1305  ie.Assemble_ddI3b(weight*(c - 0.5*c*c), A.GetData());
1306 }
1307 
1308 
1309 
1310 
1312 {
1313  // mu_360 = |J|^3 / 3^(3/2) - det(J)
1314  const double fnorm = Jpt.FNorm();
1315  return fnorm * fnorm * fnorm / pow(3.0, 1.5) - Jpt.Det();
1316 }
1317 
1318 double TMOP_Metric_360::EvalW(const DenseMatrix &Jpt) const
1319 {
1320  // mu_360 = (I1/3)^(3/2) - I3b.
1321  ie.SetJacobian(Jpt.GetData());
1322  return pow(ie.Get_I1()/3.0, 1.5) - ie.Get_I3b();
1323 }
1324 
1326 {
1327  // mu_360 = (I1/3)^(3/2) - I3b.
1328  // P = 3/2 * (I1/3)^1/2 * dI1 / 3 - dI3b
1329  // = 1/2 * (I1/3)^1/2 * dI1 - dI3b.
1330  ie.SetJacobian(Jpt.GetData());
1331  Add(0.5 * sqrt(ie.Get_I1()/3.0), ie.Get_dI1(), -1.0, ie.Get_dI3b(), P);
1332 }
1333 
1335  const double weight, DenseMatrix &A) const
1336 {
1337  // P = 1/2 * (I1/3)^1/2 * dI1 - dI3b.
1338  // dP = 1/12 * (I1/3)^(-1/2) * (dI1 x dI1) + 1/2 * (I1/3)^1/2 * ddI1 - ddI3b
1339  ie.SetJacobian(Jpt.GetData());
1340  ie.SetDerivativeMatrix(DS.Height(), DS.GetData());
1341  ie.Assemble_TProd(weight / 12.0 / sqrt(ie.Get_I1()/3.0),
1342  ie.Get_dI1(), A.GetData());
1343  ie.Assemble_ddI1(weight / 2.0 * sqrt(ie.Get_I1()/3.0), A.GetData());
1344  ie.Assemble_ddI3b(-weight, A.GetData());
1345 }
1346 
1347 double TMOP_AMetric_011::EvalW(const DenseMatrix &Jpt) const
1348 {
1349  MFEM_VERIFY(Jtr != NULL,
1350  "Requires a target Jacobian, use SetTargetJacobian().");
1351 
1352  int dim = Jpt.Size();
1353 
1354  DenseMatrix Jpr(dim, dim);
1355  Mult(Jpt, *Jtr, Jpr);
1356 
1357  double alpha = Jpr.Det(),
1358  omega = Jtr->Det();
1359 
1360  DenseMatrix AdjAt(dim), WtW(dim), WRK(dim), Jtrt(dim);
1361  CalcAdjugateTranspose(Jpr, AdjAt);
1362  Jtrt.Transpose(*Jtr);
1363  MultAAt(Jtrt, WtW);
1364  WtW *= 1./omega;
1365  Mult(AdjAt, WtW, WRK);
1366 
1367  WRK -= Jpr;
1368  WRK *= -1.;
1369 
1370  return (0.25/alpha)*WRK.FNorm2();
1371 }
1372 
1373 double TMOP_AMetric_014a::EvalW(const DenseMatrix &Jpt) const
1374 {
1375  MFEM_VERIFY(Jtr != NULL,
1376  "Requires a target Jacobian, use SetTargetJacobian().");
1377 
1378  int dim = Jpt.Size();
1379 
1380  DenseMatrix Jpr(dim, dim);
1381  Mult(Jpt, *Jtr, Jpr);
1382 
1383  double sqalpha = pow(Jpr.Det(), 0.5),
1384  sqomega = pow(Jtr->Det(), 0.5);
1385 
1386  return 0.5*pow(sqalpha/sqomega - sqomega/sqalpha, 2.);
1387 }
1388 
1389 double TMOP_AMetric_036::EvalW(const DenseMatrix &Jpt) const
1390 {
1391  MFEM_VERIFY(Jtr != NULL,
1392  "Requires a target Jacobian, use SetTargetJacobian().");
1393 
1394  int dim = Jpt.Size();
1395 
1396  DenseMatrix Jpr(dim, dim);
1397  Mult(Jpt, *Jtr, Jpr); // T*W = A
1398 
1399  double alpha = Jpr.Det(); // det(A)
1400  Jpr -= *Jtr; // A-W
1401 
1402  return (1./alpha)*(Jpr.FNorm2()); //(1/alpha)*(|A-W|^2)
1403 }
1404 
1405 double TMOP_AMetric_107a::EvalW(const DenseMatrix &Jpt) const
1406 {
1407  MFEM_VERIFY(Jtr != NULL,
1408  "Requires a target Jacobian, use SetTargetJacobian().");
1409 
1410  int dim = Jpt.Size();
1411 
1412  DenseMatrix Jpr(dim, dim);
1413  Mult(Jpt, *Jtr, Jpr);
1414 
1415  double alpha = Jpr.Det(),
1416  aw = Jpr.FNorm()/Jtr->FNorm();
1417 
1418  DenseMatrix W = *Jtr;
1419  W *= aw;
1420  Jpr -= W;
1421 
1422  return (0.5/alpha)*Jpr.FNorm2();
1423 }
1424 
1425 
1427 {
1428  MFEM_VERIFY(nodes, "Nodes are not given!");
1429  MFEM_ASSERT(avg_volume == 0.0, "The average volume is already computed!");
1430 
1431  Mesh *mesh = nodes->FESpace()->GetMesh();
1432  const int NE = mesh->GetNE();
1434  double volume = 0.0;
1435 
1436  for (int i = 0; i < NE; i++)
1437  {
1438  mesh->GetElementTransformation(i, *nodes, &Tr);
1439  const IntegrationRule &ir =
1440  IntRules.Get(mesh->GetElementBaseGeometry(i), Tr.OrderJ());
1441  for (int j = 0; j < ir.GetNPoints(); j++)
1442  {
1443  const IntegrationPoint &ip = ir.IntPoint(j);
1444  Tr.SetIntPoint(&ip);
1445  volume += ip.weight * Tr.Weight();
1446  }
1447  }
1448 
1449  NCMesh *ncmesh = mesh->ncmesh;
1450  if (Parallel() == false)
1451  {
1452  avg_volume = (ncmesh == NULL) ?
1453  volume / NE : volume / ncmesh->GetNumRootElements();
1454 
1455  }
1456 #ifdef MFEM_USE_MPI
1457  else
1458  {
1459  double area_NE[4];
1460  area_NE[0] = volume; area_NE[1] = NE;
1461  MPI_Allreduce(area_NE, area_NE + 2, 2, MPI_DOUBLE, MPI_SUM, comm);
1462  avg_volume = (ncmesh == NULL) ?
1463  area_NE[2] / area_NE[3] : area_NE[2] / ncmesh->GetNumRootElements();
1464  }
1465 #endif
1466 }
1467 
1469  const FiniteElementSpace &fes,
1470  const IntegrationRule &ir,
1471  const Vector &xe,
1472  DenseTensor &Jtr) const
1473 {
1474  // Fallback to the 1-element method, ComputeElementTargets()
1475 
1476  // When UsesPhysicalCoordinates() == true, we assume 'xe' uses
1477  // ElementDofOrdering::LEXICOGRAPHIC iff 'fe' is a TensorFiniteElement.
1478 
1479  const Mesh *mesh = fes.GetMesh();
1480  const int NE = mesh->GetNE();
1481  // Quick return for empty processors:
1482  if (NE == 0) { return; }
1483  const int dim = mesh->Dimension();
1484  MFEM_VERIFY(mesh->GetNumGeometries(dim) <= 1,
1485  "mixed meshes are not supported");
1486  MFEM_VERIFY(!fes.IsVariableOrder(), "variable orders are not supported");
1487  const FiniteElement &fe = *fes.GetFE(0);
1488  const int sdim = fes.GetVDim();
1489  const int nvdofs = sdim*fe.GetDof();
1490  MFEM_VERIFY(!UsesPhysicalCoordinates() ||
1491  xe.Size() == NE*nvdofs, "invalid input Vector 'xe'!");
1492  const int NQ = ir.GetNPoints();
1493  const Array<int> *dof_map = nullptr;
1495  {
1496  const TensorBasisElement *tfe =
1497  dynamic_cast<const TensorBasisElement *>(&fe);
1498  if (tfe)
1499  {
1500  dof_map = &tfe->GetDofMap();
1501  if (dof_map->Size() == 0) { dof_map = nullptr; }
1502  }
1503  }
1504 
1505  Vector elfun_lex, elfun_nat;
1506  DenseTensor J;
1507  xe.HostRead();
1508  Jtr.HostWrite();
1509  if (UsesPhysicalCoordinates() && dof_map != nullptr)
1510  {
1511  elfun_nat.SetSize(nvdofs);
1512  }
1513  for (int e = 0; e < NE; e++)
1514  {
1516  {
1517  if (!dof_map)
1518  {
1519  elfun_nat.SetDataAndSize(xe.GetData()+e*nvdofs, nvdofs);
1520  }
1521  else
1522  {
1523  elfun_lex.SetDataAndSize(xe.GetData()+e*nvdofs, nvdofs);
1524  const int ndofs = fe.GetDof();
1525  for (int d = 0; d < sdim; d++)
1526  {
1527  for (int i_lex = 0; i_lex < ndofs; i_lex++)
1528  {
1529  elfun_nat[(*dof_map)[i_lex]+d*ndofs] =
1530  elfun_lex[i_lex+d*ndofs];
1531  }
1532  }
1533  }
1534  }
1535  J.UseExternalData(Jtr(e*NQ).Data(), sdim, dim, NQ);
1536  ComputeElementTargets(e, fe, ir, elfun_nat, J);
1537  }
1538 }
1539 
1541 {
1542  switch (target_type)
1543  {
1544  case IDEAL_SHAPE_UNIT_SIZE: return false;
1547  case GIVEN_SHAPE_AND_SIZE:
1548  case GIVEN_FULL: return true;
1549  default: MFEM_ABORT("TargetType not added to ContainsVolumeInfo.");
1550  }
1551  return false;
1552 }
1553 
1555  const IntegrationRule &ir,
1556  const Vector &elfun,
1557  DenseTensor &Jtr) const
1558 {
1559  MFEM_CONTRACT_VAR(elfun);
1560  MFEM_ASSERT(target_type == IDEAL_SHAPE_UNIT_SIZE || nodes != NULL, "");
1561 
1562  const FiniteElement *nfe = (target_type != IDEAL_SHAPE_UNIT_SIZE) ?
1563  nodes->FESpace()->GetFE(e_id) : NULL;
1564  const DenseMatrix &Wideal =
1566  MFEM_ASSERT(Wideal.Height() == Jtr.SizeI(), "");
1567  MFEM_ASSERT(Wideal.Width() == Jtr.SizeJ(), "");
1568 
1569  switch (target_type)
1570  {
1571  case IDEAL_SHAPE_UNIT_SIZE:
1572  {
1573  for (int i = 0; i < ir.GetNPoints(); i++) { Jtr(i) = Wideal; }
1574  break;
1575  }
1577  {
1578  if (avg_volume == 0.0) { ComputeAvgVolume(); }
1579  DenseMatrix W(Wideal.Height());
1580 
1581  NCMesh *ncmesh = nodes->FESpace()->GetMesh()->ncmesh;
1582  double el_volume = avg_volume;
1583  if (ncmesh)
1584  {
1585  el_volume = avg_volume / ncmesh->GetElementSizeReduction(e_id);
1586  }
1587 
1588  W.Set(std::pow(volume_scale * el_volume / Wideal.Det(),
1589  1./W.Height()), Wideal);
1590  for (int i = 0; i < ir.GetNPoints(); i++) { Jtr(i) = W; }
1591  break;
1592  }
1594  case GIVEN_SHAPE_AND_SIZE:
1595  {
1596  const int dim = nfe->GetDim(), dof = nfe->GetDof();
1597  MFEM_ASSERT(dim == nodes->FESpace()->GetVDim(), "");
1598  DenseMatrix dshape(dof, dim), pos(dof, dim);
1599  Array<int> xdofs(dof * dim);
1600  Vector posV(pos.Data(), dof * dim);
1601  double detW;
1602 
1603  // always initialize detW to suppress a warning:
1604  detW = (target_type == IDEAL_SHAPE_GIVEN_SIZE) ? Wideal.Det() : 0.0;
1605  nodes->FESpace()->GetElementVDofs(e_id, xdofs);
1606  nodes->GetSubVector(xdofs, posV);
1607  for (int i = 0; i < ir.GetNPoints(); i++)
1608  {
1609  nfe->CalcDShape(ir.IntPoint(i), dshape);
1610  MultAtB(pos, dshape, Jtr(i));
1612  {
1613  const double det = Jtr(i).Det();
1614  MFEM_VERIFY(det > 0.0, "The given mesh is inverted!");
1615  Jtr(i).Set(std::pow(det / detW, 1./dim), Wideal);
1616  }
1617  }
1618  break;
1619  }
1620  default:
1621  MFEM_ABORT("invalid target type!");
1622  }
1623 }
1624 
1626  const IntegrationRule &ir,
1627  const Vector &elfun,
1629  DenseTensor &dJtr) const
1630 {
1631  MFEM_CONTRACT_VAR(elfun);
1632  MFEM_ASSERT(target_type == IDEAL_SHAPE_UNIT_SIZE || nodes != NULL, "");
1633 
1634  // TODO: Compute derivative for targets with GIVEN_SHAPE or/and GIVEN_SIZE
1635  for (int i = 0; i < Tpr.GetFE()->GetDim()*ir.GetNPoints(); i++)
1636  { dJtr(i) = 0.; }
1637 }
1638 
1640  VectorCoefficient *vspec,
1641  TMOPMatrixCoefficient *mspec)
1642 {
1643  scalar_tspec = sspec;
1644  vector_tspec = vspec;
1645  matrix_tspec = mspec;
1646 }
1647 
1649  const IntegrationRule &ir,
1650  const Vector &elfun,
1651  DenseTensor &Jtr) const
1652 {
1653  DenseMatrix point_mat;
1654  point_mat.UseExternalData(elfun.GetData(), fe.GetDof(), fe.GetDim());
1655 
1656  switch (target_type)
1657  {
1658  case GIVEN_FULL:
1659  {
1660  MFEM_VERIFY(matrix_tspec != NULL,
1661  "Target type GIVEN_FULL requires a MatrixCoefficient.");
1662 
1664  Tpr.SetFE(&fe);
1665  Tpr.ElementNo = e_id;
1667  Tpr.GetPointMat().Transpose(point_mat);
1668 
1669  for (int i = 0; i < ir.GetNPoints(); i++)
1670  {
1671  const IntegrationPoint &ip = ir.IntPoint(i);
1672  Tpr.SetIntPoint(&ip);
1673  matrix_tspec->Eval(Jtr(i), Tpr, ip);
1674  }
1675  break;
1676  }
1677  default:
1678  MFEM_ABORT("Incompatible target type for analytic adaptation!");
1679  }
1680 }
1681 
1683  const Vector &elfun,
1685  DenseTensor &dJtr) const
1686 {
1687  const FiniteElement *fe = Tpr.GetFE();
1688  DenseMatrix point_mat;
1689  point_mat.UseExternalData(elfun.GetData(), fe->GetDof(), fe->GetDim());
1690 
1691  switch (target_type)
1692  {
1693  case GIVEN_FULL:
1694  {
1695  MFEM_VERIFY(matrix_tspec != NULL,
1696  "Target type GIVEN_FULL requires a TMOPMatrixCoefficient.");
1697 
1698  for (int d = 0; d < fe->GetDim(); d++)
1699  {
1700  for (int i = 0; i < ir.GetNPoints(); i++)
1701  {
1702  const IntegrationPoint &ip = ir.IntPoint(i);
1703  Tpr.SetIntPoint(&ip);
1704  DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
1705  matrix_tspec->EvalGrad(dJtr_i, Tpr, ip, d);
1706  }
1707  }
1708  break;
1709  }
1710  default:
1711  MFEM_ABORT("Incompatible target type for analytic adaptation!");
1712  }
1713 }
1714 
1715 namespace internal
1716 {
1717 
1718 // MFEM_FORALL-based copy kernel -- used by protected methods below.
1719 // Needed as a workaround for the nvcc restriction that methods with MFEM_FORALL
1720 // in them must to be public.
1721 static inline void device_copy(double *d_dest, const double *d_src, int size)
1722 {
1723  MFEM_FORALL(i, size, d_dest[i] = d_src[i];);
1724 }
1725 
1726 } // namespace internal
1727 
1728 #ifdef MFEM_USE_MPI
1730 {
1731  MFEM_VERIFY(adapt_eval, "SetAdaptivityEvaluator() has not been called!")
1732  MFEM_VERIFY(ncomp > 0, "No target specifications have been set!");
1733 
1734  ParFiniteElementSpace *ptspec_fes = t.ParFESpace();
1735 
1736  tspec_sav = tspec;
1737 
1738  delete tspec_fesv;
1739  tspec_fesv = new FiniteElementSpace(ptspec_fes->GetMesh(),
1740  ptspec_fes->FEColl(), ncomp);
1741 
1742  delete ptspec_fesv;
1743  ptspec_fesv = new ParFiniteElementSpace(ptspec_fes->GetParMesh(),
1744  ptspec_fes->FEColl(), ncomp);
1745 
1746  delete tspec_pgf;
1748  tspec_gf = tspec_pgf;
1749 
1750  adapt_eval->SetParMetaInfo(*ptspec_fes->GetParMesh(), *ptspec_fesv);
1751  adapt_eval->SetInitialField(*ptspec_fes->GetMesh()->GetNodes(), tspec);
1752 }
1753 
1755 {
1756  ptspec_fesv->Update();
1757  if (tspec_fesv)
1758  {
1759  delete tspec_fesv;
1761  ptspec_fesv->FEColl(), ncomp);
1762  }
1763  tspec_pgf->Update();
1764  tspec_gf = tspec_pgf;
1766  tspec_sav = tspec;
1767 
1770 }
1771 
1773 {
1774  const int vdim = tspec_.FESpace()->GetVDim(),
1775  ndof = tspec_.FESpace()->GetNDofs();
1776  MFEM_VERIFY(ndof == tspec.Size()/ncomp, "Inconsistency in SetTspecAtIndex.");
1777 
1778  const auto tspec__d = tspec_.Read();
1779  auto tspec_d = tspec.ReadWrite();
1780  const int offset = idx*ndof;
1781  internal::device_copy(tspec_d + offset, tspec__d, ndof*vdim);
1783 }
1784 
1786 {
1787  MFEM_VERIFY(tspec_.FESpace()->GetOrdering() == Ordering::byNODES,
1788  "Discrete target size should be ordered byNodes.");
1789  if (sizeidx > -1) { SetTspecAtIndex(sizeidx, tspec_); return; }
1790  sizeidx = ncomp;
1791  SetDiscreteTargetBase(tspec_);
1793 }
1794 
1796 {
1797  MFEM_VERIFY(tspec_.FESpace()->GetOrdering() == Ordering::byNODES,
1798  "Discrete target skewness should be ordered byNodes.");
1799  if (skewidx > -1) { SetTspecAtIndex(skewidx, tspec_); return; }
1800  skewidx = ncomp;
1801  SetDiscreteTargetBase(tspec_);
1803 }
1804 
1806 {
1807  MFEM_VERIFY(ar.FESpace()->GetOrdering() == Ordering::byNODES,
1808  "Discrete target aspect ratio should be ordered byNodes.");
1809  if (aspectratioidx > -1) { SetTspecAtIndex(aspectratioidx, ar); return; }
1813 }
1814 
1816 {
1817  MFEM_VERIFY(o.FESpace()->GetOrdering() == Ordering::byNODES,
1818  "Discrete target orientation should be ordered byNodes.");
1819  if (orientationidx > -1) { SetTspecAtIndex(orientationidx, o); return; }
1823 }
1824 
1826 {
1827  SetParDiscreteTargetSize(tspec_);
1828 }
1829 #endif // MFEM_USE_MPI
1830 
1832 {
1833  const int vdim = tspec_.FESpace()->GetVDim(),
1834  ndof = tspec_.FESpace()->GetNDofs();
1835 
1836  ncomp += vdim;
1837 
1838  // need to append data to tspec
1839  // make a copy of tspec->tspec_temp, increase its size, and
1840  // copy data from tspec_temp -> tspec, then add new entries
1841  Vector tspec_temp = tspec;
1842  tspec.UseDevice(true);
1843  tspec_sav.UseDevice(true);
1844  tspec.SetSize(ncomp*ndof);
1845 
1846  const auto tspec_temp_d = tspec_temp.Read();
1847  auto tspec_d = tspec.ReadWrite();
1848  internal::device_copy(tspec_d, tspec_temp_d, tspec_temp.Size());
1849 
1850  const auto tspec__d = tspec_.Read();
1851  const int offset = (ncomp-vdim)*ndof;
1852  internal::device_copy(tspec_d + offset, tspec__d, ndof*vdim);
1853 }
1854 
1856 {
1857  const int vdim = tspec_.FESpace()->GetVDim(),
1858  ndof = tspec_.FESpace()->GetNDofs();
1859  MFEM_VERIFY(ndof == tspec.Size()/ncomp, "Inconsistency in SetTargetSpec.");
1860 
1861  const auto tspec__d = tspec_.Read();
1862  auto tspec_d = tspec.ReadWrite();
1863  const int offset = idx*ndof;
1864  internal::device_copy(tspec_d + offset, tspec__d, ndof*vdim);
1866 }
1867 
1869 {
1870  MFEM_VERIFY(tspec_.FESpace()->GetOrdering() == Ordering::byNODES,
1871  "Discrete target size should be ordered byNodes.");
1872  if (sizeidx > -1) { SetTspecAtIndex(sizeidx, tspec_); return; }
1873  sizeidx = ncomp;
1874  SetDiscreteTargetBase(tspec_);
1876 }
1877 
1879 {
1880  MFEM_VERIFY(tspec_.FESpace()->GetOrdering() == Ordering::byNODES,
1881  "Discrete target skewness should be ordered byNodes.");
1882  if (skewidx > -1) { SetTspecAtIndex(skewidx, tspec_); return; }
1883  skewidx = ncomp;
1884  SetDiscreteTargetBase(tspec_);
1886 }
1887 
1889 {
1890  MFEM_VERIFY(ar.FESpace()->GetOrdering() == Ordering::byNODES,
1891  "Discrete target aspect ratio should be ordered byNodes.");
1892  if (aspectratioidx > -1) { SetTspecAtIndex(aspectratioidx, ar); return; }
1896 }
1897 
1899 {
1900  MFEM_VERIFY(o.FESpace()->GetOrdering() == Ordering::byNODES,
1901  "Discrete target orientation should be ordered byNodes.");
1902  if (orientationidx > -1) { SetTspecAtIndex(orientationidx, o); return; }
1906 }
1907 
1909 {
1910  MFEM_VERIFY(adapt_eval, "SetAdaptivityEvaluator() has not been called!")
1911  MFEM_VERIFY(ncomp > 0, "No target specifications have been set!");
1912 
1913  const FiniteElementSpace *tspec_fes = t.FESpace();
1914 
1915  tspec_sav = tspec;
1916 
1917  delete tspec_fesv;
1918  tspec_fesv = new FiniteElementSpace(tspec_fes->GetMesh(),
1919  tspec_fes->FEColl(), ncomp,
1921 
1922  delete tspec_gf;
1924 
1925  adapt_eval->SetSerialMetaInfo(*tspec_fes->GetMesh(), *tspec_fesv);
1926  adapt_eval->SetInitialField(*tspec_fes->GetMesh()->GetNodes(), tspec);
1927 }
1928 
1930 {
1931  if (idx < 0) { return; }
1932  const int ndof = tspec_.FESpace()->GetNDofs(),
1933  vdim = tspec_.FESpace()->GetVDim();
1934  MFEM_VERIFY(ndof == tspec.Size()/ncomp,
1935  "Inconsistency in GetSerialDiscreteTargetSpec.");
1936 
1937  for (int i = 0; i < ndof*vdim; i++)
1938  {
1939  tspec_(i) = tspec(i + idx*ndof);
1940  }
1941 }
1942 
1944 {
1945  tspec_fesv->Update();
1946  tspec_gf->Update();
1948  tspec_sav = tspec;
1949 
1952 }
1953 
1955 {
1957 }
1958 
1959 
1961  bool use_flag,
1962  int new_x_ordering)
1963 {
1964  if (use_flag && good_tspec) { return; }
1965 
1966  MFEM_VERIFY(tspec.Size() > 0, "Target specification is not set!");
1967  adapt_eval->ComputeAtNewPosition(new_x, tspec, new_x_ordering);
1968  tspec_sav = tspec;
1969 
1970  good_tspec = use_flag;
1971 }
1972 
1974  Vector &IntData,
1975  int new_x_ordering)
1976 {
1977  adapt_eval->ComputeAtNewPosition(new_x, IntData, new_x_ordering);
1978 }
1979 
1982  int dofidx, int dir,
1983  const Vector &IntData)
1984 {
1985  MFEM_VERIFY(tspec.Size() > 0, "Target specification is not set!");
1986 
1987  Array<int> dofs;
1988  tspec_fesv->GetElementDofs(T.ElementNo, dofs);
1989  const int cnt = tspec.Size()/ncomp; // dofs per scalar-field
1990 
1991  for (int i = 0; i < ncomp; i++)
1992  {
1993  tspec(dofs[dofidx]+i*cnt) = IntData(dofs[dofidx] + i*cnt + dir*cnt*ncomp);
1994  }
1995 }
1996 
1998  int dofidx)
1999 {
2000  MFEM_VERIFY(tspec.Size() > 0, "Target specification is not set!");
2001 
2002  Array<int> dofs;
2003  tspec_fesv->GetElementDofs(T.ElementNo, dofs);
2004  const int cnt = tspec.Size()/ncomp;
2005  for (int i = 0; i < ncomp; i++)
2006  {
2007  tspec(dofs[dofidx] + i*cnt) = tspec_sav(dofs[dofidx] + i*cnt);
2008  }
2009 }
2010 
2012  const IntegrationRule &intrule)
2013 {
2014  switch (target_type)
2015  {
2017  case GIVEN_SHAPE_AND_SIZE:
2018  {
2019  const int ndofs = tspec_fesv->GetFE(e_id)->GetDof(),
2020  ntspec_dofs = ndofs*ncomp;
2021 
2022  Vector tspec_vals(ntspec_dofs);
2023 
2024  Array<int> dofs;
2025  tspec_fesv->GetElementVDofs(e_id, dofs);
2026  tspec.GetSubVector(dofs, tspec_vals);
2027  DenseMatrix tr;
2028  tspec_gf->GetVectorValues(e_id, intrule, tspec_refine, tr);
2030  break;
2031  }
2032  default:
2033  MFEM_ABORT("Incompatible target type for discrete adaptation!");
2034  }
2035 }
2036 
2038 {
2039  coarse_tspec_fesv = fes;
2040  const Operator *c_op = fes->GetUpdateOperator();
2041  tspec_derefine.SetSize(c_op->Height());
2042  c_op->Mult(tspec, tspec_derefine);
2043 }
2044 
2046  const IntegrationRule &ir,
2047  const Vector &elfun,
2048  DenseTensor &Jtr) const
2049 {
2050  MFEM_VERIFY(tspec_fesv, "No target specifications have been set.");
2051  const int dim = fe.GetDim(),
2052  nqp = ir.GetNPoints();
2053  Jtrcomp.SetSize(dim, dim, 4*nqp);
2054 
2055  FiniteElementSpace *src_fes = tspec_fesv;
2056 
2057  switch (target_type)
2058  {
2060  case GIVEN_SHAPE_AND_SIZE:
2061  {
2062  const DenseMatrix &Wideal =
2064  const int ndofs = tspec_fesv->GetFE(e_id)->GetDof(),
2065  ntspec_dofs = ndofs*ncomp;
2066 
2067  Vector shape(ndofs), tspec_vals(ntspec_dofs), par_vals,
2068  par_vals_c1, par_vals_c2, par_vals_c3;
2069 
2070  Array<int> dofs;
2071  DenseMatrix D_rho(dim), Q_phi(dim), R_theta(dim);
2072  tspec_fesv->GetElementVDofs(e_id, dofs);
2073  tspec.UseDevice(true);
2074  tspec.GetSubVector(dofs, tspec_vals);
2075  if (tspec_refine.NumCols() > 0) // Refinement
2076  {
2077  MFEM_VERIFY(amr_el >= 0, " Target being constructed for an AMR element.");
2078  for (int i = 0; i < ncomp; i++)
2079  {
2080  for (int j = 0; j < ndofs; j++)
2081  {
2082  tspec_vals(j + i*ndofs) = tspec_refine(j + amr_el*ndofs, i);
2083  }
2084  }
2085  }
2086  else if (tspec_derefine.Size() > 0) // Derefinement
2087  {
2088  dofs.SetSize(0);
2089  coarse_tspec_fesv->GetElementVDofs(e_id, dofs);
2090  tspec_derefine.GetSubVector(dofs, tspec_vals);
2091  src_fes = coarse_tspec_fesv;
2092  }
2093 
2094  for (int q = 0; q < nqp; q++)
2095  {
2096  const IntegrationPoint &ip = ir.IntPoint(q);
2097  src_fes->GetFE(e_id)->CalcShape(ip, shape);
2098  Jtr(q) = Wideal; // Initialize to identity
2099  for (int d = 0; d < 4; d++)
2100  {
2101  DenseMatrix Jtrcomp_q(Jtrcomp.GetData(d + 4*q), dim, dim);
2102  Jtrcomp_q = Wideal; // Initialize to identity
2103  }
2104 
2105  if (sizeidx != -1) // Set size
2106  {
2107  par_vals.SetDataAndSize(tspec_vals.GetData()+sizeidx*ndofs, ndofs);
2108  double min_size = par_vals.Min();//0.001; //
2109  if (lim_min_size > 0.)
2110  {
2111  min_size = lim_min_size;
2112  }
2113  else
2114  {
2115  MFEM_VERIFY(min_size > 0.0,
2116  "Non-positive size propagated in the target definition.");
2117  }
2118  const double size = std::max(shape * par_vals, min_size);
2119  Jtr(q).Set(std::pow(size, 1.0/dim), Jtr(q));
2120  DenseMatrix Jtrcomp_q(Jtrcomp.GetData(0 + 4*q), dim, dim);
2121  Jtrcomp_q = Jtr(q);
2122  } // Done size
2123 
2124  if (target_type == IDEAL_SHAPE_GIVEN_SIZE) { continue; }
2125 
2126  if (aspectratioidx != -1) // Set aspect ratio
2127  {
2128  if (dim == 2)
2129  {
2130  par_vals.SetDataAndSize(tspec_vals.GetData()+
2131  aspectratioidx*ndofs, ndofs);
2132  const double min_size = par_vals.Min();
2133  MFEM_VERIFY(min_size > 0.0,
2134  "Non-positive aspect-ratio propagated in the target definition.");
2135 
2136  const double aspectratio = shape * par_vals;
2137  D_rho = 0.;
2138  D_rho(0,0) = 1./pow(aspectratio,0.5);
2139  D_rho(1,1) = pow(aspectratio,0.5);
2140  }
2141  else
2142  {
2143  par_vals.SetDataAndSize(tspec_vals.GetData()+
2144  aspectratioidx*ndofs, ndofs*3);
2145  par_vals_c1.SetDataAndSize(par_vals.GetData(), ndofs);
2146  par_vals_c2.SetDataAndSize(par_vals.GetData()+ndofs, ndofs);
2147  par_vals_c3.SetDataAndSize(par_vals.GetData()+2*ndofs, ndofs);
2148 
2149  const double rho1 = shape * par_vals_c1;
2150  const double rho2 = shape * par_vals_c2;
2151  const double rho3 = shape * par_vals_c3;
2152  D_rho = 0.;
2153  D_rho(0,0) = pow(rho1,2./3.);
2154  D_rho(1,1) = pow(rho2,2./3.);
2155  D_rho(2,2) = pow(rho3,2./3.);
2156  }
2157  DenseMatrix Jtrcomp_q(Jtrcomp.GetData(1 + 4*q), dim, dim);
2158  Jtrcomp_q = D_rho;
2159  DenseMatrix Temp = Jtr(q);
2160  Mult(D_rho, Temp, Jtr(q));
2161  } // Done aspect ratio
2162 
2163  if (skewidx != -1) // Set skew
2164  {
2165  if (dim == 2)
2166  {
2167  par_vals.SetDataAndSize(tspec_vals.GetData()+
2168  skewidx*ndofs, ndofs);
2169 
2170  const double skew = shape * par_vals;
2171 
2172  Q_phi = 0.;
2173  Q_phi(0,0) = 1.;
2174  Q_phi(0,1) = cos(skew);
2175  Q_phi(1,1) = sin(skew);
2176  }
2177  else
2178  {
2179  par_vals.SetDataAndSize(tspec_vals.GetData()+
2180  skewidx*ndofs, ndofs*3);
2181  par_vals_c1.SetDataAndSize(par_vals.GetData(), ndofs);
2182  par_vals_c2.SetDataAndSize(par_vals.GetData()+ndofs, ndofs);
2183  par_vals_c3.SetDataAndSize(par_vals.GetData()+2*ndofs, ndofs);
2184 
2185  const double phi12 = shape * par_vals_c1;
2186  const double phi13 = shape * par_vals_c2;
2187  const double chi = shape * par_vals_c3;
2188 
2189  Q_phi = 0.;
2190  Q_phi(0,0) = 1.;
2191  Q_phi(0,1) = cos(phi12);
2192  Q_phi(0,2) = cos(phi13);
2193 
2194  Q_phi(1,1) = sin(phi12);
2195  Q_phi(1,2) = sin(phi13)*cos(chi);
2196 
2197  Q_phi(2,2) = sin(phi13)*sin(chi);
2198  }
2199  DenseMatrix Jtrcomp_q(Jtrcomp.GetData(2 + 4*q), dim, dim);
2200  Jtrcomp_q = Q_phi;
2201  DenseMatrix Temp = Jtr(q);
2202  Mult(Q_phi, Temp, Jtr(q));
2203  } // Done skew
2204 
2205  if (orientationidx != -1) // Set orientation
2206  {
2207  if (dim == 2)
2208  {
2209  par_vals.SetDataAndSize(tspec_vals.GetData()+
2210  orientationidx*ndofs, ndofs);
2211 
2212  const double theta = shape * par_vals;
2213  R_theta(0,0) = cos(theta);
2214  R_theta(0,1) = -sin(theta);
2215  R_theta(1,0) = sin(theta);
2216  R_theta(1,1) = cos(theta);
2217  }
2218  else
2219  {
2220  par_vals.SetDataAndSize(tspec_vals.GetData()+
2221  orientationidx*ndofs, ndofs*3);
2222  par_vals_c1.SetDataAndSize(par_vals.GetData(), ndofs);
2223  par_vals_c2.SetDataAndSize(par_vals.GetData()+ndofs, ndofs);
2224  par_vals_c3.SetDataAndSize(par_vals.GetData()+2*ndofs, ndofs);
2225 
2226  const double theta = shape * par_vals_c1;
2227  const double psi = shape * par_vals_c2;
2228  const double beta = shape * par_vals_c3;
2229 
2230  double ct = cos(theta), st = sin(theta),
2231  cp = cos(psi), sp = sin(psi),
2232  cb = cos(beta), sb = sin(beta);
2233 
2234  R_theta = 0.;
2235  R_theta(0,0) = ct*sp;
2236  R_theta(1,0) = st*sp;
2237  R_theta(2,0) = cp;
2238 
2239  R_theta(0,1) = -st*cb + ct*cp*sb;
2240  R_theta(1,1) = ct*cb + st*cp*sb;
2241  R_theta(2,1) = -sp*sb;
2242 
2243  R_theta(0,0) = -st*sb - ct*cp*cb;
2244  R_theta(1,0) = ct*sb - st*cp*cb;
2245  R_theta(2,0) = sp*cb;
2246  }
2247  DenseMatrix Jtrcomp_q(Jtrcomp.GetData(3 + 4*q), dim, dim);
2248  Jtrcomp_q = R_theta;
2249  DenseMatrix Temp = Jtr(q);
2250  Mult(R_theta, Temp, Jtr(q));
2251  } // Done orientation
2252  }
2253  break;
2254  }
2255  default:
2256  MFEM_ABORT("Incompatible target type for discrete adaptation!");
2257  }
2258 }
2259 
2261  const Vector &elfun,
2263  DenseTensor &dJtr) const
2264 {
2265  MFEM_ASSERT(target_type == IDEAL_SHAPE_UNIT_SIZE || nodes != NULL, "");
2266 
2267  MFEM_VERIFY(tspec_fesv, "No target specifications have been set.");
2268 
2269  dJtr = 0.;
2270  const int e_id = Tpr.ElementNo;
2271  const FiniteElement *fe = Tpr.GetFE();
2272 
2273  switch (target_type)
2274  {
2276  case GIVEN_SHAPE_AND_SIZE:
2277  {
2278  const DenseMatrix &Wideal =
2280  const int dim = Wideal.Height(),
2281  ndofs = fe->GetDof(),
2282  ntspec_dofs = ndofs*ncomp;
2283 
2284  Vector shape(ndofs), tspec_vals(ntspec_dofs), par_vals,
2285  par_vals_c1(ndofs), par_vals_c2(ndofs), par_vals_c3(ndofs);
2286 
2287  Array<int> dofs;
2288  DenseMatrix dD_rho(dim), dQ_phi(dim), dR_theta(dim);
2289  DenseMatrix dQ_phi13(dim), dQ_phichi(dim); // dQ_phi is used for dQ/dphi12 in 3D
2290  DenseMatrix dR_psi(dim), dR_beta(dim);
2291  tspec_fesv->GetElementVDofs(e_id, dofs);
2292  tspec.GetSubVector(dofs, tspec_vals);
2293 
2294  DenseMatrix grad_e_c1(ndofs, dim),
2295  grad_e_c2(ndofs, dim),
2296  grad_e_c3(ndofs, dim);
2297  Vector grad_ptr_c1(grad_e_c1.GetData(), ndofs*dim),
2298  grad_ptr_c2(grad_e_c2.GetData(), ndofs*dim),
2299  grad_ptr_c3(grad_e_c3.GetData(), ndofs*dim);
2300 
2301  DenseMatrix grad_phys; // This will be (dof x dim, dof).
2302  fe->ProjectGrad(*fe, Tpr, grad_phys);
2303 
2304  for (int i = 0; i < ir.GetNPoints(); i++)
2305  {
2306  const IntegrationPoint &ip = ir.IntPoint(i);
2307  DenseMatrix Jtrcomp_s(Jtrcomp.GetData(0 + 4*i), dim, dim); // size
2308  DenseMatrix Jtrcomp_d(Jtrcomp.GetData(1 + 4*i), dim, dim); // aspect-ratio
2309  DenseMatrix Jtrcomp_q(Jtrcomp.GetData(2 + 4*i), dim, dim); // skew
2310  DenseMatrix Jtrcomp_r(Jtrcomp.GetData(3 + 4*i), dim, dim); // orientation
2311  DenseMatrix work1(dim), work2(dim), work3(dim);
2312 
2313  if (sizeidx != -1) // Set size
2314  {
2315  par_vals.SetDataAndSize(tspec_vals.GetData()+sizeidx*ndofs, ndofs);
2316 
2317  grad_phys.Mult(par_vals, grad_ptr_c1);
2318  Vector grad_q(dim);
2319  tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
2320  grad_e_c1.MultTranspose(shape, grad_q);
2321 
2322  const double min_size = par_vals.Min();
2323  MFEM_VERIFY(min_size > 0.0,
2324  "Non-positive size propagated in the target definition.");
2325  const double size = std::max(shape * par_vals, min_size);
2326  double dz_dsize = (1./dim)*pow(size, 1./dim - 1.);
2327 
2328  Mult(Jtrcomp_q, Jtrcomp_d, work1); // Q*D
2329  Mult(Jtrcomp_r, work1, work2); // R*Q*D
2330 
2331  for (int d = 0; d < dim; d++)
2332  {
2333  DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
2334  work1 = Wideal;
2335  work1.Set(dz_dsize, work1); // dz/dsize
2336  work1 *= grad_q(d); // dz/dsize*dsize/dx
2337  AddMult(work1, work2, dJtr_i); // dz/dx*R*Q*D
2338  }
2339  } // Done size
2340 
2341  if (target_type == IDEAL_SHAPE_GIVEN_SIZE) { continue; }
2342 
2343  if (aspectratioidx != -1) // Set aspect ratio
2344  {
2345  if (dim == 2)
2346  {
2347  par_vals.SetDataAndSize(tspec_vals.GetData()+
2348  aspectratioidx*ndofs, ndofs);
2349 
2350  grad_phys.Mult(par_vals, grad_ptr_c1);
2351  Vector grad_q(dim);
2352  tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
2353  grad_e_c1.MultTranspose(shape, grad_q);
2354 
2355  const double aspectratio = shape * par_vals;
2356  dD_rho = 0.;
2357  dD_rho(0,0) = -0.5*pow(aspectratio,-1.5);
2358  dD_rho(1,1) = 0.5*pow(aspectratio,-0.5);
2359 
2360  Mult(Jtrcomp_s, Jtrcomp_r, work1); // z*R
2361  Mult(work1, Jtrcomp_q, work2); // z*R*Q
2362 
2363  for (int d = 0; d < dim; d++)
2364  {
2365  DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
2366  work1 = dD_rho;
2367  work1 *= grad_q(d); // work1 = dD/drho*drho/dx
2368  AddMult(work2, work1, dJtr_i); // z*R*Q*dD/dx
2369  }
2370  }
2371  else // 3D
2372  {
2373  par_vals.SetDataAndSize(tspec_vals.GetData()+
2374  aspectratioidx*ndofs, ndofs*3);
2375  par_vals_c1.SetData(par_vals.GetData());
2376  par_vals_c2.SetData(par_vals.GetData()+ndofs);
2377  par_vals_c3.SetData(par_vals.GetData()+2*ndofs);
2378 
2379  grad_phys.Mult(par_vals_c1, grad_ptr_c1);
2380  grad_phys.Mult(par_vals_c2, grad_ptr_c2);
2381  grad_phys.Mult(par_vals_c3, grad_ptr_c3);
2382  Vector grad_q1(dim), grad_q2(dim), grad_q3(dim);
2383  tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
2384  grad_e_c1.MultTranspose(shape, grad_q1);
2385  grad_e_c2.MultTranspose(shape, grad_q2);
2386  grad_e_c3.MultTranspose(shape, grad_q3);
2387 
2388  const double rho1 = shape * par_vals_c1;
2389  const double rho2 = shape * par_vals_c2;
2390  const double rho3 = shape * par_vals_c3;
2391  dD_rho = 0.;
2392  dD_rho(0,0) = (2./3.)*pow(rho1,-1./3.);
2393  dD_rho(1,1) = (2./3.)*pow(rho2,-1./3.);
2394  dD_rho(2,2) = (2./3.)*pow(rho3,-1./3.);
2395 
2396  Mult(Jtrcomp_s, Jtrcomp_r, work1); // z*R
2397  Mult(work1, Jtrcomp_q, work2); // z*R*Q
2398 
2399 
2400  for (int d = 0; d < dim; d++)
2401  {
2402  DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
2403  work1 = dD_rho;
2404  work1(0,0) *= grad_q1(d);
2405  work1(1,2) *= grad_q2(d);
2406  work1(2,2) *= grad_q3(d);
2407  // work1 = dD/dx = dD/drho1*drho1/dx + dD/drho2*drho2/dx
2408  AddMult(work2, work1, dJtr_i); // z*R*Q*dD/dx
2409  }
2410  }
2411  } // Done aspect ratio
2412 
2413  if (skewidx != -1) // Set skew
2414  {
2415  if (dim == 2)
2416  {
2417  par_vals.SetDataAndSize(tspec_vals.GetData()+
2418  skewidx*ndofs, ndofs);
2419 
2420  grad_phys.Mult(par_vals, grad_ptr_c1);
2421  Vector grad_q(dim);
2422  tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
2423  grad_e_c1.MultTranspose(shape, grad_q);
2424 
2425  const double skew = shape * par_vals;
2426 
2427  dQ_phi = 0.;
2428  dQ_phi(0,0) = 1.;
2429  dQ_phi(0,1) = -sin(skew);
2430  dQ_phi(1,1) = cos(skew);
2431 
2432  Mult(Jtrcomp_s, Jtrcomp_r, work2); // z*R
2433 
2434  for (int d = 0; d < dim; d++)
2435  {
2436  DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
2437  work1 = dQ_phi;
2438  work1 *= grad_q(d); // work1 = dQ/dphi*dphi/dx
2439  Mult(work1, Jtrcomp_d, work3); // dQ/dx*D
2440  AddMult(work2, work3, dJtr_i); // z*R*dQ/dx*D
2441  }
2442  }
2443  else
2444  {
2445  par_vals.SetDataAndSize(tspec_vals.GetData()+
2446  skewidx*ndofs, ndofs*3);
2447  par_vals_c1.SetData(par_vals.GetData());
2448  par_vals_c2.SetData(par_vals.GetData()+ndofs);
2449  par_vals_c3.SetData(par_vals.GetData()+2*ndofs);
2450 
2451  grad_phys.Mult(par_vals_c1, grad_ptr_c1);
2452  grad_phys.Mult(par_vals_c2, grad_ptr_c2);
2453  grad_phys.Mult(par_vals_c3, grad_ptr_c3);
2454  Vector grad_q1(dim), grad_q2(dim), grad_q3(dim);
2455  tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
2456  grad_e_c1.MultTranspose(shape, grad_q1);
2457  grad_e_c2.MultTranspose(shape, grad_q2);
2458  grad_e_c3.MultTranspose(shape, grad_q3);
2459 
2460  const double phi12 = shape * par_vals_c1;
2461  const double phi13 = shape * par_vals_c2;
2462  const double chi = shape * par_vals_c3;
2463 
2464  dQ_phi = 0.;
2465  dQ_phi(0,0) = 1.;
2466  dQ_phi(0,1) = -sin(phi12);
2467  dQ_phi(1,1) = cos(phi12);
2468 
2469  dQ_phi13 = 0.;
2470  dQ_phi13(0,2) = -sin(phi13);
2471  dQ_phi13(1,2) = cos(phi13)*cos(chi);
2472  dQ_phi13(2,2) = cos(phi13)*sin(chi);
2473 
2474  dQ_phichi = 0.;
2475  dQ_phichi(1,2) = -sin(phi13)*sin(chi);
2476  dQ_phichi(2,2) = sin(phi13)*cos(chi);
2477 
2478  Mult(Jtrcomp_s, Jtrcomp_r, work2); // z*R
2479 
2480  for (int d = 0; d < dim; d++)
2481  {
2482  DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
2483  work1 = dQ_phi;
2484  work1 *= grad_q1(d); // work1 = dQ/dphi12*dphi12/dx
2485  work1.Add(grad_q2(d), dQ_phi13); // + dQ/dphi13*dphi13/dx
2486  work1.Add(grad_q3(d), dQ_phichi); // + dQ/dchi*dchi/dx
2487  Mult(work1, Jtrcomp_d, work3); // dQ/dx*D
2488  AddMult(work2, work3, dJtr_i); // z*R*dQ/dx*D
2489  }
2490  }
2491  } // Done skew
2492 
2493  if (orientationidx != -1) // Set orientation
2494  {
2495  if (dim == 2)
2496  {
2497  par_vals.SetDataAndSize(tspec_vals.GetData()+
2498  orientationidx*ndofs, ndofs);
2499 
2500  grad_phys.Mult(par_vals, grad_ptr_c1);
2501  Vector grad_q(dim);
2502  tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
2503  grad_e_c1.MultTranspose(shape, grad_q);
2504 
2505  const double theta = shape * par_vals;
2506  dR_theta(0,0) = -sin(theta);
2507  dR_theta(0,1) = -cos(theta);
2508  dR_theta(1,0) = cos(theta);
2509  dR_theta(1,1) = -sin(theta);
2510 
2511  Mult(Jtrcomp_q, Jtrcomp_d, work1); // Q*D
2512  Mult(Jtrcomp_s, work1, work2); // z*Q*D
2513  for (int d = 0; d < dim; d++)
2514  {
2515  DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
2516  work1 = dR_theta;
2517  work1 *= grad_q(d); // work1 = dR/dtheta*dtheta/dx
2518  AddMult(work1, work2, dJtr_i); // z*dR/dx*Q*D
2519  }
2520  }
2521  else
2522  {
2523  par_vals.SetDataAndSize(tspec_vals.GetData()+
2524  orientationidx*ndofs, ndofs*3);
2525  par_vals_c1.SetData(par_vals.GetData());
2526  par_vals_c2.SetData(par_vals.GetData()+ndofs);
2527  par_vals_c3.SetData(par_vals.GetData()+2*ndofs);
2528 
2529  grad_phys.Mult(par_vals_c1, grad_ptr_c1);
2530  grad_phys.Mult(par_vals_c2, grad_ptr_c2);
2531  grad_phys.Mult(par_vals_c3, grad_ptr_c3);
2532  Vector grad_q1(dim), grad_q2(dim), grad_q3(dim);
2533  tspec_fesv->GetFE(e_id)->CalcShape(ip, shape);
2534  grad_e_c1.MultTranspose(shape, grad_q1);
2535  grad_e_c2.MultTranspose(shape, grad_q2);
2536  grad_e_c3.MultTranspose(shape, grad_q3);
2537 
2538  const double theta = shape * par_vals_c1;
2539  const double psi = shape * par_vals_c2;
2540  const double beta = shape * par_vals_c3;
2541 
2542  const double ct = cos(theta), st = sin(theta),
2543  cp = cos(psi), sp = sin(psi),
2544  cb = cos(beta), sb = sin(beta);
2545 
2546  dR_theta = 0.;
2547  dR_theta(0,0) = -st*sp;
2548  dR_theta(1,0) = ct*sp;
2549  dR_theta(2,0) = 0;
2550 
2551  dR_theta(0,1) = -ct*cb - st*cp*sb;
2552  dR_theta(1,1) = -st*cb + ct*cp*sb;
2553  dR_theta(2,1) = 0.;
2554 
2555  dR_theta(0,0) = -ct*sb + st*cp*cb;
2556  dR_theta(1,0) = -st*sb - ct*cp*cb;
2557  dR_theta(2,0) = 0.;
2558 
2559  dR_beta = 0.;
2560  dR_beta(0,0) = 0.;
2561  dR_beta(1,0) = 0.;
2562  dR_beta(2,0) = 0.;
2563 
2564  dR_beta(0,1) = st*sb + ct*cp*cb;
2565  dR_beta(1,1) = -ct*sb + st*cp*cb;
2566  dR_beta(2,1) = -sp*cb;
2567 
2568  dR_beta(0,0) = -st*cb + ct*cp*sb;
2569  dR_beta(1,0) = ct*cb + st*cp*sb;
2570  dR_beta(2,0) = 0.;
2571 
2572  dR_psi = 0.;
2573  dR_psi(0,0) = ct*cp;
2574  dR_psi(1,0) = st*cp;
2575  dR_psi(2,0) = -sp;
2576 
2577  dR_psi(0,1) = 0. - ct*sp*sb;
2578  dR_psi(1,1) = 0. + st*sp*sb;
2579  dR_psi(2,1) = -cp*sb;
2580 
2581  dR_psi(0,0) = 0. + ct*sp*cb;
2582  dR_psi(1,0) = 0. + st*sp*cb;
2583  dR_psi(2,0) = cp*cb;
2584 
2585  Mult(Jtrcomp_q, Jtrcomp_d, work1); // Q*D
2586  Mult(Jtrcomp_s, work1, work2); // z*Q*D
2587  for (int d = 0; d < dim; d++)
2588  {
2589  DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
2590  work1 = dR_theta;
2591  work1 *= grad_q1(d); // work1 = dR/dtheta*dtheta/dx
2592  work1.Add(grad_q2(d), dR_psi); // +dR/dpsi*dpsi/dx
2593  work1.Add(grad_q3(d), dR_beta); // +dR/dbeta*dbeta/dx
2594  AddMult(work1, work2, dJtr_i); // z*dR/dx*Q*D
2595  }
2596  }
2597  } // Done orientation
2598  }
2599  break;
2600  }
2601  default:
2602  MFEM_ABORT("Incompatible target type for discrete adaptation!");
2603  }
2604  Jtrcomp.Clear();
2605 }
2606 
2608  const double dx,
2609  bool use_flag,
2610  int x_ordering)
2611 {
2612  if (use_flag && good_tspec_grad) { return; }
2613 
2614  const int dim = tspec_fesv->GetFE(0)->GetDim(),
2615  cnt = x.Size()/dim;
2616 
2618 
2619  Vector TSpecTemp;
2620  Vector xtemp = x;
2621  for (int j = 0; j < dim; j++)
2622  {
2623  for (int i = 0; i < cnt; i++)
2624  {
2625  int idx = x_ordering == Ordering::byNODES ? j*cnt + i : i*dim + j;
2626  xtemp(idx) += dx;
2627  }
2628 
2629  TSpecTemp.NewDataAndSize(tspec_pert1h.GetData() + j*cnt*ncomp, cnt*ncomp);
2630  UpdateTargetSpecification(xtemp, TSpecTemp, x_ordering);
2631 
2632  for (int i = 0; i < cnt; i++)
2633  {
2634  int idx = x_ordering == Ordering::byNODES ? j*cnt + i : i*dim + j;
2635  xtemp(idx) -= dx;
2636  }
2637  }
2638 
2639  good_tspec_grad = use_flag;
2640 }
2641 
2643  double dx, bool use_flag,
2644  int x_ordering)
2645 {
2646 
2647  if (use_flag && good_tspec_hess) { return; }
2648 
2649  const int dim = tspec_fesv->GetFE(0)->GetDim(),
2650  cnt = x.Size()/dim,
2651  totmix = 1+2*(dim-2);
2652 
2654  tspec_pertmix.SetSize(cnt*totmix*ncomp);
2655 
2656  Vector TSpecTemp;
2657  Vector xtemp = x;
2658 
2659  // T(x+2h)
2660  for (int j = 0; j < dim; j++)
2661  {
2662  for (int i = 0; i < cnt; i++)
2663  {
2664  int idx = x_ordering == Ordering::byNODES ? j*cnt + i : i*dim + j;
2665  xtemp(idx) += 2*dx;
2666  }
2667 
2668  TSpecTemp.NewDataAndSize(tspec_pert2h.GetData() + j*cnt*ncomp, cnt*ncomp);
2669  UpdateTargetSpecification(xtemp, TSpecTemp, x_ordering);
2670 
2671  for (int i = 0; i < cnt; i++)
2672  {
2673  int idx = x_ordering == Ordering::byNODES ? j*cnt + i : i*dim + j;
2674  xtemp(idx) -= 2*dx;
2675  }
2676  }
2677 
2678  // T(x+h,y+h)
2679  int j = 0;
2680  for (int k1 = 0; k1 < dim; k1++)
2681  {
2682  for (int k2 = 0; (k1 != k2) && (k2 < dim); k2++)
2683  {
2684  for (int i = 0; i < cnt; i++)
2685  {
2686  int idx1 = x_ordering == Ordering::byNODES ? k1*cnt+i : i*dim + k1;
2687  int idx2 = x_ordering == Ordering::byNODES ? k2*cnt+i : i*dim + k2;
2688  xtemp(idx1) += dx;
2689  xtemp(idx2) += dx;
2690  }
2691 
2692  TSpecTemp.NewDataAndSize(tspec_pertmix.GetData() + j*cnt*ncomp, cnt*ncomp);
2693  UpdateTargetSpecification(xtemp, TSpecTemp, x_ordering);
2694 
2695  for (int i = 0; i < cnt; i++)
2696  {
2697  int idx1 = x_ordering == Ordering::byNODES ? k1*cnt+i : i*dim + k1;
2698  int idx2 = x_ordering == Ordering::byNODES ? k2*cnt+i : i*dim + k2;
2699  xtemp(idx1) -= dx;
2700  xtemp(idx2) -= dx;
2701  }
2702  j++;
2703  }
2704  }
2705 
2706  good_tspec_hess = use_flag;
2707 }
2708 
2710 {
2711  delete tspec_gf;
2712  delete adapt_eval;
2713  delete tspec_fesv;
2714 #ifdef MFEM_USE_MPI
2715  delete ptspec_fesv;
2716 #endif
2717 }
2718 
2720  const FiniteElementSpace &f)
2721 {
2722  delete fes;
2723  delete mesh;
2724  mesh = new Mesh(m, true);
2725  fes = new FiniteElementSpace(mesh, f.FEColl(),
2726  f.GetVDim(), f.GetOrdering());
2727 }
2728 
2729 #ifdef MFEM_USE_MPI
2731  const ParFiniteElementSpace &f)
2732 {
2733  delete pfes;
2734  delete pmesh;
2735  pmesh = new ParMesh(m, true);
2736  pfes = new ParFiniteElementSpace(pmesh, f.FEColl(),
2737  f.GetVDim(), f.GetOrdering());
2738 }
2739 #endif
2740 
2742 {
2743 #ifdef MFEM_USE_MPI
2744  if (pmesh) { pmesh->DeleteGeometricFactors(); }
2745 #else
2746  if (mesh) { mesh->DeleteGeometricFactors(); }
2747 #endif
2748 }
2749 
2751 {
2752  delete fes;
2753  delete mesh;
2754 #ifdef MFEM_USE_MPI
2755  delete pfes;
2756  delete pmesh;
2757 #endif
2758 }
2759 
2761 {
2762  if (PA.enabled)
2763  {
2764  PA.H.GetMemory().DeleteDevice(copy_to_host);
2765  PA.H0.GetMemory().DeleteDevice(copy_to_host);
2766  if (!copy_to_host && !PA.Jtr.GetMemory().HostIsValid())
2767  {
2768  PA.Jtr_needs_update = true;
2769  }
2770  PA.Jtr.GetMemory().DeleteDevice(copy_to_host);
2771  }
2772 }
2773 
2775 {
2776  delete lim_func;
2777  delete adapt_lim_gf;
2778  delete surf_fit_gf;
2779  for (int i = 0; i < ElemDer.Size(); i++)
2780  {
2781  delete ElemDer[i];
2782  delete ElemPertEnergy[i];
2783  }
2784 }
2785 
2787  const GridFunction &dist, Coefficient &w0,
2788  TMOP_LimiterFunction *lfunc)
2789 {
2790  lim_nodes0 = &n0;
2791  lim_coeff = &w0;
2792  lim_dist = &dist;
2793  MFEM_VERIFY(lim_dist->FESpace()->GetVDim() == 1,
2794  "'dist' must be a scalar GridFunction!");
2795 
2796  delete lim_func;
2797  lim_func = (lfunc) ? lfunc : new TMOP_QuadraticLimiter;
2798 }
2799 
2801  TMOP_LimiterFunction *lfunc)
2802 {
2803  lim_nodes0 = &n0;
2804  lim_coeff = &w0;
2805  lim_dist = NULL;
2806 
2807  delete lim_func;
2808  lim_func = (lfunc) ? lfunc : new TMOP_QuadraticLimiter;
2809 }
2810 
2812  Coefficient &coeff,
2813  AdaptivityEvaluator &ae)
2814 {
2815  adapt_lim_gf0 = &z0;
2816  delete adapt_lim_gf;
2817  adapt_lim_gf = new GridFunction(z0);
2818  adapt_lim_coeff = &coeff;
2819  adapt_lim_eval = &ae;
2820 
2822  *z0.FESpace());
2825 }
2826 
2827 #ifdef MFEM_USE_MPI
2829  Coefficient &coeff,
2830  AdaptivityEvaluator &ae)
2831 {
2832  adapt_lim_gf0 = &z0;
2833  adapt_lim_pgf0 = &z0;
2834  delete adapt_lim_gf;
2835  adapt_lim_gf = new GridFunction(z0);
2836  adapt_lim_coeff = &coeff;
2837  adapt_lim_eval = &ae;
2838 
2840  *z0.ParFESpace());
2843 }
2844 #endif
2845 
2847  const Array<bool> &smarker,
2848  Coefficient &coeff,
2849  AdaptivityEvaluator &ae)
2850 {
2851  delete surf_fit_gf;
2852  surf_fit_gf = new GridFunction(s0);
2853  surf_fit_marker = &smarker;
2854  surf_fit_coeff = &coeff;
2855  surf_fit_eval = &ae;
2856 
2858  *s0.FESpace());
2861 }
2862 
2863 #ifdef MFEM_USE_MPI
2865  const Array<bool> &smarker,
2866  Coefficient &coeff,
2867  AdaptivityEvaluator &ae)
2868 {
2869  delete surf_fit_gf;
2870  surf_fit_gf = new GridFunction(s0);
2871  surf_fit_marker = &smarker;
2872  surf_fit_coeff = &coeff;
2873  surf_fit_eval = &ae;
2874 
2876  *s0.ParFESpace());
2879 }
2880 #endif
2881 
2882 void TMOP_Integrator::GetSurfaceFittingErrors(double &err_avg, double &err_max)
2883 {
2884  MFEM_VERIFY(surf_fit_gf, "Surface fitting has not been enabled.");
2885 
2886  int loc_cnt = 0;
2887  double loc_max = 0.0, loc_sum = 0.0;
2888  for (int i = 0; i < surf_fit_marker->Size(); i++)
2889  {
2890  if ((*surf_fit_marker)[i] == true)
2891  {
2892  loc_cnt++;
2893  loc_max = std::max(loc_max, std::abs((*surf_fit_gf)(i)));
2894  loc_sum += std::abs((*surf_fit_gf)(i));
2895  }
2896  }
2897 
2898 #ifdef MFEM_USE_MPI
2899  if (targetC->Parallel() == false) { return; }
2900  int glob_cnt;
2901  MPI_Comm comm = targetC->GetComm();
2902  MPI_Allreduce(&loc_max, &err_max, 1, MPI_DOUBLE, MPI_MAX, comm);
2903  MPI_Allreduce(&loc_cnt, &glob_cnt, 1, MPI_INT, MPI_SUM, comm);
2904  MPI_Allreduce(&loc_sum, &err_avg, 1, MPI_DOUBLE, MPI_SUM, comm);
2905  err_avg = err_avg / glob_cnt;
2906 #else
2907  err_avg = loc_sum / loc_cnt;
2908  err_max = loc_max;
2909 #endif
2910 }
2911 
2913 {
2914  if (adapt_lim_gf)
2915  {
2916  adapt_lim_gf->Update();
2918  *adapt_lim_gf->FESpace());
2921  }
2922 }
2923 
2924 #ifdef MFEM_USE_MPI
2926 {
2927  if (adapt_lim_gf)
2928  {
2929  adapt_lim_gf->Update();
2934  }
2935 }
2936 #endif
2937 
2940  const Vector &elfun)
2941 {
2942  const int dof = el.GetDof(), dim = el.GetDim();
2943  const int el_id = T.ElementNo;
2944  double energy;
2945 
2946  // No adaptive limiting / surface fitting terms if the function is called
2947  // as part of a FD derivative computation (because we include the exact
2948  // derivatives of these terms in FD computations).
2949  const bool adaptive_limiting = (adapt_lim_gf && fd_call_flag == false);
2950  const bool surface_fit = (surf_fit_gf && fd_call_flag == false);
2951 
2952  DSh.SetSize(dof, dim);
2953  Jrt.SetSize(dim);
2954  Jpr.SetSize(dim);
2955  Jpt.SetSize(dim);
2956  PMatI.UseExternalData(elfun.GetData(), dof, dim);
2957 
2959 
2960  energy = 0.0;
2962  targetC->ComputeElementTargets(el_id, el, ir, elfun, Jtr);
2963 
2964  // Limited case.
2965  Vector shape, p, p0, d_vals;
2966  DenseMatrix pos0;
2967  if (lim_coeff)
2968  {
2969  shape.SetSize(dof);
2970  p.SetSize(dim);
2971  p0.SetSize(dim);
2972  pos0.SetSize(dof, dim);
2973  Vector pos0V(pos0.Data(), dof * dim);
2974  Array<int> pos_dofs;
2975  lim_nodes0->FESpace()->GetElementVDofs(el_id, pos_dofs);
2976  lim_nodes0->GetSubVector(pos_dofs, pos0V);
2977  if (lim_dist)
2978  {
2979  lim_dist->GetValues(el_id, ir, d_vals);
2980  }
2981  else
2982  {
2983  d_vals.SetSize(ir.GetNPoints()); d_vals = 1.0;
2984  }
2985  }
2986 
2987  // Define ref->physical transformation, when a Coefficient is specified.
2988  IsoparametricTransformation *Tpr = NULL;
2989  if (metric_coeff || lim_coeff || adaptive_limiting || surface_fit)
2990  {
2991  Tpr = new IsoparametricTransformation;
2992  Tpr->SetFE(&el);
2993  Tpr->ElementNo = el_id;
2995  Tpr->Attribute = T.Attribute;
2996  Tpr->mesh = T.mesh;
2997  Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
2998  }
2999  // TODO: computing the coefficients 'metric_coeff' and 'lim_coeff' in physical
3000  // coordinates means that, generally, the gradient and Hessian of the
3001  // TMOP_Integrator will depend on the derivatives of the coefficients.
3002  //
3003  // In some cases the coefficients are independent of any movement of
3004  // the physical coordinates (i.e. changes in 'elfun'), e.g. when the
3005  // coefficient is a ConstantCoefficient or a GridFunctionCoefficient.
3006 
3007  Vector adapt_lim_gf_q, adapt_lim_gf0_q;
3008  if (adaptive_limiting)
3009  {
3010  adapt_lim_gf->GetValues(el_id, ir, adapt_lim_gf_q);
3011  adapt_lim_gf0->GetValues(el_id, ir, adapt_lim_gf0_q);
3012  }
3013 
3014  for (int i = 0; i < ir.GetNPoints(); i++)
3015  {
3016  const IntegrationPoint &ip = ir.IntPoint(i);
3017 
3018  const DenseMatrix &Jtr_i = Jtr(i);
3019  metric->SetTargetJacobian(Jtr_i);
3020  CalcInverse(Jtr_i, Jrt);
3021  const double weight = ip.weight * Jtr_i.Det();
3022 
3023  el.CalcDShape(ip, DSh);
3024  MultAtB(PMatI, DSh, Jpr);
3025  Mult(Jpr, Jrt, Jpt);
3026 
3027  double val = metric_normal * metric->EvalW(Jpt);
3028  if (metric_coeff) { val *= metric_coeff->Eval(*Tpr, ip); }
3029 
3030  if (lim_coeff)
3031  {
3032  el.CalcShape(ip, shape);
3033  PMatI.MultTranspose(shape, p);
3034  pos0.MultTranspose(shape, p0);
3035  val += lim_normal *
3036  lim_func->Eval(p, p0, d_vals(i)) *
3037  lim_coeff->Eval(*Tpr, ip);
3038  }
3039 
3040  // Contribution from the adaptive limiting term.
3041  if (adaptive_limiting)
3042  {
3043  const double diff = adapt_lim_gf_q(i) - adapt_lim_gf0_q(i);
3044  val += adapt_lim_coeff->Eval(*Tpr, ip) * lim_normal * diff * diff;
3045  }
3046 
3047  energy += weight * val;
3048  }
3049 
3050  // Contribution from the surface fitting term.
3051  if (surface_fit)
3052  {
3053  const IntegrationRule &ir_s =
3054  surf_fit_gf->FESpace()->GetFE(el_id)->GetNodes();
3055  Array<int> dofs;
3056  Vector sigma_e;
3057  surf_fit_gf->FESpace()->GetElementDofs(el_id, dofs);
3058  surf_fit_gf->GetSubVector(dofs, sigma_e);
3059  for (int s = 0; s < dofs.Size(); s++)
3060  {
3061  if ((*surf_fit_marker)[dofs[s]] == true)
3062  {
3063  const IntegrationPoint &ip_s = ir_s.IntPoint(s);
3064  Tpr->SetIntPoint(&ip_s);
3065  energy += surf_fit_coeff->Eval(*Tpr, ip_s) * surf_fit_normal *
3066  sigma_e(s) * sigma_e(s);
3067  }
3068  }
3069  }
3070 
3071  delete Tpr;
3072  return energy;
3073 }
3074 
3077  const Vector &elfun,
3078  const IntegrationRule &irule)
3079 {
3080  int dof = el.GetDof(), dim = el.GetDim(),
3081  NEsplit = elfun.Size() / (dof*dim), el_id = T.ElementNo;
3082  double energy = 0.;
3083 
3084  TargetConstructor *tc = const_cast<TargetConstructor *>(targetC);
3085  DiscreteAdaptTC *dtc = dynamic_cast<DiscreteAdaptTC *>(tc);
3086  // For DiscreteAdaptTC the GridFunctions used to set the targets must be
3087  // mapped onto the fine elements.
3088  if (dtc) { dtc->SetTspecFromIntRule(el_id, irule); }
3089 
3090  for (int e = 0; e < NEsplit; e++)
3091  {
3092  DSh.SetSize(dof, dim);
3093  Jrt.SetSize(dim);
3094  Jpr.SetSize(dim);
3095  Jpt.SetSize(dim);
3096  Vector elfun_child(dof*dim);
3097  for (int i = 0; i < dof; i++)
3098  {
3099  for (int d = 0; d < dim; d++)
3100  {
3101  // elfun is (xe1,xe2,...xen,ye1,ye2...yen) and has nodal coordinates
3102  // for all the children element of the parent element being considered.
3103  // So we must index and get (xek, yek) i.e. nodal coordinates for
3104  // the fine element being considered.
3105  elfun_child(i + d*dof) = elfun(i + e*dof + d*dof*NEsplit);
3106  }
3107  }
3108  PMatI.UseExternalData(elfun_child.GetData(), dof, dim);
3109 
3111 
3112  double el_energy = 0;
3114  if (dtc)
3115  {
3116  // This is used to index into the tspec vector inside DiscreteAdaptTC.
3117  dtc->SetRefinementSubElement(e);
3118  }
3119  targetC->ComputeElementTargets(el_id, el, ir, elfun_child, Jtr);
3120 
3121  // Define ref->physical transformation, wn a Coefficient is specified.
3122  IsoparametricTransformation *Tpr = NULL;
3123  if (metric_coeff || lim_coeff)
3124  {
3125  Tpr = new IsoparametricTransformation;
3126  Tpr->SetFE(&el);
3127  Tpr->ElementNo = T.ElementNo;
3129  Tpr->Attribute = T.Attribute;
3130  Tpr->mesh = T.mesh;
3131  Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
3132  }
3133 
3134  for (int i = 0; i < ir.GetNPoints(); i++)
3135  {
3136  const IntegrationPoint &ip = ir.IntPoint(i);
3137  const DenseMatrix &Jtr_i = Jtr(i);
3138  h_metric->SetTargetJacobian(Jtr_i);
3139  CalcInverse(Jtr_i, Jrt);
3140  const double weight = ip.weight * Jtr_i.Det();
3141 
3142  el.CalcDShape(ip, DSh);
3143  MultAtB(PMatI, DSh, Jpr);
3144  Mult(Jpr, Jrt, Jpt);
3145 
3146  double val = metric_normal * h_metric->EvalW(Jpt);
3147  if (metric_coeff) { val *= metric_coeff->Eval(*Tpr, ip); }
3148 
3149  el_energy += weight * val;
3150  delete Tpr;
3151  }
3152  energy += el_energy;
3153  }
3154  energy /= NEsplit;
3155 
3156  if (dtc) { dtc->ResetRefinementTspecData(); }
3157 
3158  return energy;
3159 }
3160 
3163  const Vector &elfun)
3164 {
3165  int dof = el.GetDof(), dim = el.GetDim();
3166  double energy = 0.;
3167 
3168  DSh.SetSize(dof, dim);
3169  Jrt.SetSize(dim);
3170  Jpr.SetSize(dim);
3171  Jpt.SetSize(dim);
3172  PMatI.UseExternalData(elfun.GetData(), dof, dim);
3173 
3175 
3176  energy = 0.0;
3178  targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
3179 
3180  // Define ref->physical transformation, wn a Coefficient is specified.
3181  IsoparametricTransformation *Tpr = NULL;
3182  if (metric_coeff)
3183  {
3184  Tpr = new IsoparametricTransformation;
3185  Tpr->SetFE(&el);
3186  Tpr->ElementNo = T.ElementNo;
3188  Tpr->Attribute = T.Attribute;
3189  Tpr->mesh = T.mesh;
3190  Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
3191  }
3192 
3193  for (int i = 0; i < ir.GetNPoints(); i++)
3194  {
3195  const IntegrationPoint &ip = ir.IntPoint(i);
3196  const DenseMatrix &Jtr_i = Jtr(i);
3197  h_metric->SetTargetJacobian(Jtr_i);
3198  CalcInverse(Jtr_i, Jrt);
3199  const double weight = ip.weight * Jtr_i.Det();
3200 
3201  el.CalcDShape(ip, DSh);
3202  MultAtB(PMatI, DSh, Jpr);
3203  Mult(Jpr, Jrt, Jpt);
3204 
3205  double val = metric_normal * h_metric->EvalW(Jpt);
3206  if (metric_coeff) { val *= metric_coeff->Eval(*Tpr, ip); }
3207 
3208  energy += weight * val;
3209  }
3210 
3211  delete Tpr;
3212  return energy;
3213 }
3214 
3217  const Vector &elfun, Vector &elvect)
3218 {
3219  if (!fdflag)
3220  {
3221  AssembleElementVectorExact(el, T, elfun, elvect);
3222  }
3223  else
3224  {
3225  AssembleElementVectorFD(el, T, elfun, elvect);
3226  }
3227 }
3228 
3231  const Vector &elfun,
3232  DenseMatrix &elmat)
3233 {
3234  if (!fdflag)
3235  {
3236  AssembleElementGradExact(el, T, elfun, elmat);
3237  }
3238  else
3239  {
3240  AssembleElementGradFD(el, T, elfun, elmat);
3241  }
3242 }
3243 
3246  const Vector &elfun,
3247  Vector &elvect)
3248 {
3249  const int dof = el.GetDof(), dim = el.GetDim();
3250 
3251  DenseMatrix Amat(dim), work1(dim), work2(dim);
3252  DSh.SetSize(dof, dim);
3253  DS.SetSize(dof, dim);
3254  Jrt.SetSize(dim);
3255  Jpt.SetSize(dim);
3256  P.SetSize(dim);
3257  PMatI.UseExternalData(elfun.GetData(), dof, dim);
3258  elvect.SetSize(dof*dim);
3259  PMatO.UseExternalData(elvect.GetData(), dof, dim);
3260 
3262  const int nqp = ir.GetNPoints();
3263 
3264  elvect = 0.0;
3265  Vector weights(nqp);
3266  DenseTensor Jtr(dim, dim, nqp);
3267  DenseTensor dJtr(dim, dim, dim*nqp);
3268  targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
3269 
3270  // Limited case.
3271  DenseMatrix pos0;
3272  Vector shape, p, p0, d_vals, grad;
3273  shape.SetSize(dof);
3274  if (lim_coeff)
3275  {
3276  p.SetSize(dim);
3277  p0.SetSize(dim);
3278  pos0.SetSize(dof, dim);
3279  Vector pos0V(pos0.Data(), dof * dim);
3280  Array<int> pos_dofs;
3281  lim_nodes0->FESpace()->GetElementVDofs(T.ElementNo, pos_dofs);
3282  lim_nodes0->GetSubVector(pos_dofs, pos0V);
3283  if (lim_dist)
3284  {
3285  lim_dist->GetValues(T.ElementNo, ir, d_vals);
3286  }
3287  else
3288  {
3289  d_vals.SetSize(nqp); d_vals = 1.0;
3290  }
3291  }
3292 
3293  // Define ref->physical transformation, when a Coefficient is specified.
3294  IsoparametricTransformation *Tpr = NULL;
3296  {
3297  Tpr = new IsoparametricTransformation;
3298  Tpr->SetFE(&el);
3299  Tpr->ElementNo = T.ElementNo;
3301  Tpr->Attribute = T.Attribute;
3302  Tpr->mesh = T.mesh;
3303  Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
3304  if (exact_action)
3305  {
3306  targetC->ComputeElementTargetsGradient(ir, elfun, *Tpr, dJtr);
3307  }
3308  }
3309 
3310  Vector d_detW_dx(dim);
3311  Vector d_Winv_dx(dim);
3312 
3313  for (int q = 0; q < nqp; q++)
3314  {
3315  const IntegrationPoint &ip = ir.IntPoint(q);
3316  const DenseMatrix &Jtr_q = Jtr(q);
3317  metric->SetTargetJacobian(Jtr_q);
3318  CalcInverse(Jtr_q, Jrt);
3319  weights(q) = ip.weight * Jtr_q.Det();
3320  double weight_m = weights(q) * metric_normal;
3321 
3322  el.CalcDShape(ip, DSh);
3323  Mult(DSh, Jrt, DS);
3324  MultAtB(PMatI, DS, Jpt);
3325 
3326  metric->EvalP(Jpt, P);
3327 
3328  if (metric_coeff) { weight_m *= metric_coeff->Eval(*Tpr, ip); }
3329 
3330  P *= weight_m;
3331  AddMultABt(DS, P, PMatO); // w_q det(W) dmu/dx : dA/dx Winv
3332 
3333  if (exact_action)
3334  {
3335  el.CalcShape(ip, shape);
3336  // Derivatives of adaptivity-based targets.
3337  // First term: w_q d*(Det W)/dx * mu(T)
3338  // d(Det W)/dx = det(W)*Tr[Winv*dW/dx]
3339  DenseMatrix dwdx(dim);
3340  for (int d = 0; d < dim; d++)
3341  {
3342  const DenseMatrix &dJtr_q = dJtr(q + d * nqp);
3343  Mult(Jrt, dJtr_q, dwdx );
3344  d_detW_dx(d) = dwdx.Trace();
3345  }
3346  d_detW_dx *= weight_m*metric->EvalW(Jpt); // *[w_q*det(W)]*mu(T)
3347 
3348  // Second term: w_q det(W) dmu/dx : AdWinv/dx
3349  // dWinv/dx = -Winv*dW/dx*Winv
3350  MultAtB(PMatI, DSh, Amat);
3351  for (int d = 0; d < dim; d++)
3352  {
3353  const DenseMatrix &dJtr_q = dJtr(q + d*nqp);
3354  Mult(Jrt, dJtr_q, work1); // Winv*dw/dx
3355  Mult(work1, Jrt, work2); // Winv*dw/dx*Winv
3356  Mult(Amat, work2, work1); // A*Winv*dw/dx*Winv
3357  MultAtB(P, work1, work2); // dmu/dT^T*A*Winv*dw/dx*Winv
3358  d_Winv_dx(d) = work2.Trace(); // Tr[dmu/dT : AWinv*dw/dx*Winv]
3359  }
3360  d_Winv_dx *= -weight_m; // Include (-) factor as well
3361 
3362  d_detW_dx += d_Winv_dx;
3363  AddMultVWt(shape, d_detW_dx, PMatO);
3364  }
3365 
3366  if (lim_coeff)
3367  {
3368  if (!exact_action) { el.CalcShape(ip, shape); }
3369  PMatI.MultTranspose(shape, p);
3370  pos0.MultTranspose(shape, p0);
3371  lim_func->Eval_d1(p, p0, d_vals(q), grad);
3372  grad *= weights(q) * lim_normal * lim_coeff->Eval(*Tpr, ip);
3373  AddMultVWt(shape, grad, PMatO);
3374  }
3375  }
3376 
3377  if (adapt_lim_gf) { AssembleElemVecAdaptLim(el, *Tpr, ir, weights, PMatO); }
3378  if (surf_fit_gf) { AssembleElemVecSurfFit(el, *Tpr, PMatO); }
3379 
3380  delete Tpr;
3381 }
3382 
3385  const Vector &elfun,
3386  DenseMatrix &elmat)
3387 {
3388  const int dof = el.GetDof(), dim = el.GetDim();
3389 
3390  DSh.SetSize(dof, dim);
3391  DS.SetSize(dof, dim);
3392  Jrt.SetSize(dim);
3393  Jpt.SetSize(dim);
3394  PMatI.UseExternalData(elfun.GetData(), dof, dim);
3395  elmat.SetSize(dof*dim);
3396 
3398  const int nqp = ir.GetNPoints();
3399 
3400  elmat = 0.0;
3401  Vector weights(nqp);
3402  DenseTensor Jtr(dim, dim, nqp);
3403  targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
3404 
3405  // Limited case.
3406  DenseMatrix pos0, hess;
3407  Vector shape, p, p0, d_vals;
3408  if (lim_coeff)
3409  {
3410  shape.SetSize(dof);
3411  p.SetSize(dim);
3412  p0.SetSize(dim);
3413  pos0.SetSize(dof, dim);
3414  Vector pos0V(pos0.Data(), dof * dim);
3415  Array<int> pos_dofs;
3416  lim_nodes0->FESpace()->GetElementVDofs(T.ElementNo, pos_dofs);
3417  lim_nodes0->GetSubVector(pos_dofs, pos0V);
3418  if (lim_dist)
3419  {
3420  lim_dist->GetValues(T.ElementNo, ir, d_vals);
3421  }
3422  else
3423  {
3424  d_vals.SetSize(nqp); d_vals = 1.0;
3425  }
3426  }
3427 
3428  // Define ref->physical transformation, when a Coefficient is specified.
3429  IsoparametricTransformation *Tpr = NULL;
3431  {
3432  Tpr = new IsoparametricTransformation;
3433  Tpr->SetFE(&el);
3434  Tpr->ElementNo = T.ElementNo;
3436  Tpr->Attribute = T.Attribute;
3437  Tpr->mesh = T.mesh;
3438  Tpr->GetPointMat().Transpose(PMatI);
3439  }
3440 
3441  for (int q = 0; q < nqp; q++)
3442  {
3443  const IntegrationPoint &ip = ir.IntPoint(q);
3444  const DenseMatrix &Jtr_q = Jtr(q);
3445  metric->SetTargetJacobian(Jtr_q);
3446  CalcInverse(Jtr_q, Jrt);
3447  weights(q) = ip.weight * Jtr_q.Det();
3448  double weight_m = weights(q) * metric_normal;
3449 
3450  el.CalcDShape(ip, DSh);
3451  Mult(DSh, Jrt, DS);
3452  MultAtB(PMatI, DS, Jpt);
3453 
3454  if (metric_coeff) { weight_m *= metric_coeff->Eval(*Tpr, ip); }
3455 
3456  metric->AssembleH(Jpt, DS, weight_m, elmat);
3457 
3458  // TODO: derivatives of adaptivity-based targets.
3459 
3460  if (lim_coeff)
3461  {
3462  el.CalcShape(ip, shape);
3463  PMatI.MultTranspose(shape, p);
3464  pos0.MultTranspose(shape, p0);
3465  weight_m = weights(q) * lim_normal * lim_coeff->Eval(*Tpr, ip);
3466  lim_func->Eval_d2(p, p0, d_vals(q), hess);
3467  for (int i = 0; i < dof; i++)
3468  {
3469  const double w_shape_i = weight_m * shape(i);
3470  for (int j = 0; j < dof; j++)
3471  {
3472  const double w = w_shape_i * shape(j);
3473  for (int d1 = 0; d1 < dim; d1++)
3474  {
3475  for (int d2 = 0; d2 < dim; d2++)
3476  {
3477  elmat(d1*dof + i, d2*dof + j) += w * hess(d1, d2);
3478  }
3479  }
3480  }
3481  }
3482  }
3483  }
3484 
3485  if (adapt_lim_gf) { AssembleElemGradAdaptLim(el, *Tpr, ir, weights, elmat); }
3486  if (surf_fit_gf) { AssembleElemGradSurfFit(el, *Tpr, elmat); }
3487 
3488  delete Tpr;
3489 }
3490 
3493  const IntegrationRule &ir,
3494  const Vector &weights,
3495  DenseMatrix &mat)
3496 {
3497  const int dof = el.GetDof(), dim = el.GetDim(), nqp = weights.Size();
3498  Vector shape(dof), adapt_lim_gf_e, adapt_lim_gf_q, adapt_lim_gf0_q(nqp);
3499 
3500  Array<int> dofs;
3502  adapt_lim_gf->GetSubVector(dofs, adapt_lim_gf_e);
3503  adapt_lim_gf->GetValues(Tpr.ElementNo, ir, adapt_lim_gf_q);
3504  adapt_lim_gf0->GetValues(Tpr.ElementNo, ir, adapt_lim_gf0_q);
3505 
3506  // Project the gradient of adapt_lim_gf in the same space.
3507  // The FE coefficients of the gradient go in adapt_lim_gf_grad_e.
3508  DenseMatrix adapt_lim_gf_grad_e(dof, dim);
3509  DenseMatrix grad_phys; // This will be (dof x dim, dof).
3510  el.ProjectGrad(el, Tpr, grad_phys);
3511  Vector grad_ptr(adapt_lim_gf_grad_e.GetData(), dof*dim);
3512  grad_phys.Mult(adapt_lim_gf_e, grad_ptr);
3513 
3514  Vector adapt_lim_gf_grad_q(dim);
3515 
3516  for (int q = 0; q < nqp; q++)
3517  {
3518  const IntegrationPoint &ip = ir.IntPoint(q);
3519  el.CalcShape(ip, shape);
3520  adapt_lim_gf_grad_e.MultTranspose(shape, adapt_lim_gf_grad_q);
3521  adapt_lim_gf_grad_q *= 2.0 * (adapt_lim_gf_q(q) - adapt_lim_gf0_q(q));
3522  adapt_lim_gf_grad_q *= weights(q) * lim_normal * adapt_lim_coeff->Eval(Tpr, ip);
3523  AddMultVWt(shape, adapt_lim_gf_grad_q, mat);
3524  }
3525 }
3526 
3529  const IntegrationRule &ir,
3530  const Vector &weights,
3531  DenseMatrix &mat)
3532 {
3533  const int dof = el.GetDof(), dim = el.GetDim(), nqp = weights.Size();
3534  Vector shape(dof), adapt_lim_gf_e, adapt_lim_gf_q, adapt_lim_gf0_q(nqp);
3535 
3536  Array<int> dofs;
3538  adapt_lim_gf->GetSubVector(dofs, adapt_lim_gf_e);
3539  adapt_lim_gf->GetValues(Tpr.ElementNo, ir, adapt_lim_gf_q);
3540  adapt_lim_gf0->GetValues(Tpr.ElementNo, ir, adapt_lim_gf0_q);
3541 
3542  // Project the gradient of adapt_lim_gf in the same space.
3543  // The FE coefficients of the gradient go in adapt_lim_gf_grad_e.
3544  DenseMatrix adapt_lim_gf_grad_e(dof, dim);
3545  DenseMatrix grad_phys; // This will be (dof x dim, dof).
3546  el.ProjectGrad(el, Tpr, grad_phys);
3547  Vector grad_ptr(adapt_lim_gf_grad_e.GetData(), dof*dim);
3548  grad_phys.Mult(adapt_lim_gf_e, grad_ptr);
3549 
3550  // Project the gradient of each gradient of adapt_lim_gf in the same space.
3551  // The FE coefficients of the second derivatives go in adapt_lim_gf_hess_e.
3552  DenseMatrix adapt_lim_gf_hess_e(dof*dim, dim);
3553  Mult(grad_phys, adapt_lim_gf_grad_e, adapt_lim_gf_hess_e);
3554  // Reshape to be more convenient later (no change in the data).
3555  adapt_lim_gf_hess_e.SetSize(dof, dim*dim);
3556 
3557  Vector adapt_lim_gf_grad_q(dim);
3558  DenseMatrix adapt_lim_gf_hess_q(dim, dim);
3559 
3560  for (int q = 0; q < nqp; q++)
3561  {
3562  const IntegrationPoint &ip = ir.IntPoint(q);
3563  el.CalcShape(ip, shape);
3564 
3565  adapt_lim_gf_grad_e.MultTranspose(shape, adapt_lim_gf_grad_q);
3566  Vector gg_ptr(adapt_lim_gf_hess_q.GetData(), dim*dim);
3567  adapt_lim_gf_hess_e.MultTranspose(shape, gg_ptr);
3568 
3569  const double w = weights(q) * lim_normal * adapt_lim_coeff->Eval(Tpr, ip);
3570  for (int i = 0; i < dof * dim; i++)
3571  {
3572  const int idof = i % dof, idim = i / dof;
3573  for (int j = 0; j <= i; j++)
3574  {
3575  const int jdof = j % dof, jdim = j / dof;
3576  const double entry =
3577  w * ( 2.0 * adapt_lim_gf_grad_q(idim) * shape(idof) *
3578  /* */ adapt_lim_gf_grad_q(jdim) * shape(jdof) +
3579  2.0 * (adapt_lim_gf_q(q) - adapt_lim_gf0_q(q)) *
3580  adapt_lim_gf_hess_q(idim, jdim) * shape(idof) * shape(jdof));
3581  mat(i, j) += entry;
3582  if (i != j) { mat(j, i) += entry; }
3583  }
3584  }
3585  }
3586 }
3587 
3590  DenseMatrix &mat)
3591 {
3592  const int el_id = Tpr.ElementNo;
3593  // Check if the element has any DOFs marked for surface fitting.
3594  Array<int> dofs;
3595  surf_fit_gf->FESpace()->GetElementDofs(el_id, dofs);
3596  int count = 0;
3597  for (int s = 0; s < dofs.Size(); s++)
3598  {
3599  count += ((*surf_fit_marker)[dofs[s]]) ? 1 : 0;
3600  }
3601  if (count == 0) { return; }
3602 
3603  const FiniteElement &el_s = *surf_fit_gf->FESpace()->GetFE(el_id);
3604 
3605  const int dof_x = el_x.GetDof(), dim = el_x.GetDim(),
3606  dof_s = el_s.GetDof();
3607 
3608  Vector sigma_e;
3609  surf_fit_gf->GetSubVector(dofs, sigma_e);
3610 
3611  // Project the gradient of sigma in the same space.
3612  // The FE coefficients of the gradient go in surf_fit_grad_e.
3613  DenseMatrix surf_fit_grad_e(dof_s, dim);
3614  Vector grad_ptr(surf_fit_grad_e.GetData(), dof_s * dim);
3615  DenseMatrix grad_phys; // This will be (dof x dim, dof).
3616  el_s.ProjectGrad(el_s, Tpr, grad_phys);
3617  grad_phys.Mult(sigma_e, grad_ptr);
3618 
3619  Vector shape_x(dof_x), shape_s(dof_s);
3620  const IntegrationRule &ir = el_s.GetNodes();
3621  Vector surf_fit_grad_s(dim);
3622  surf_fit_grad_s = 0.0;
3623 
3624  for (int s = 0; s < dof_s; s++)
3625  {
3626  if ((*surf_fit_marker)[dofs[s]] == false) { continue; }
3627 
3628  const IntegrationPoint &ip = ir.IntPoint(s);
3629  Tpr.SetIntPoint(&ip);
3630  el_x.CalcShape(ip, shape_x);
3631  el_s.CalcShape(ip, shape_s);
3632 
3633  // Note that this gradient is already in physical space.
3634  surf_fit_grad_e.MultTranspose(shape_s, surf_fit_grad_s);
3635  surf_fit_grad_s *= 2.0 * surf_fit_normal *
3636  surf_fit_coeff->Eval(Tpr, ip) * sigma_e(s);
3637 
3638  AddMultVWt(shape_x, surf_fit_grad_s, mat);
3639  }
3640 }
3641 
3644  DenseMatrix &mat)
3645 {
3646  const int el_id = Tpr.ElementNo;
3647  // Check if the element has any DOFs marked for surface fitting.
3648  Array<int> dofs;
3649  surf_fit_gf->FESpace()->GetElementDofs(el_id, dofs);
3650  int count = 0;
3651  for (int s = 0; s < dofs.Size(); s++)
3652  {
3653  count += ((*surf_fit_marker)[dofs[s]]) ? 1 : 0;
3654  }
3655  if (count == 0) { return; }
3656 
3657  const FiniteElement &el_s = *surf_fit_gf->FESpace()->GetFE(el_id);
3658 
3659  const int dof_x = el_x.GetDof(), dim = el_x.GetDim(),
3660  dof_s = el_s.GetDof();
3661 
3662  Vector sigma_e;
3663  surf_fit_gf->GetSubVector(dofs, sigma_e);
3664 
3665  DenseMatrix surf_fit_grad_e(dof_s, dim);
3666  Vector grad_ptr(surf_fit_grad_e.GetData(), dof_s * dim);
3667  DenseMatrix grad_phys;
3668  el_s.ProjectGrad(el_s, Tpr, grad_phys);
3669  grad_phys.Mult(sigma_e, grad_ptr);
3670 
3671  DenseMatrix surf_fit_hess_e(dof_s, dim*dim);
3672  Vector hess_ptr(surf_fit_hess_e.GetData(), dof_s*dim*dim);
3673  surf_fit_hess_e.SetSize(dof_s*dim, dim);
3674  Mult(grad_phys, surf_fit_grad_e, surf_fit_hess_e);
3675  surf_fit_hess_e.SetSize(dof_s, dim * dim);
3676 
3677  const IntegrationRule &ir = el_s.GetNodes();
3678  Vector shape_x(dof_x), shape_s(dof_s);
3679 
3680  Vector surf_fit_grad_s(dim);
3681  DenseMatrix surf_fit_hess_s(dim, dim);
3682 
3683 
3684  for (int s = 0; s < dof_s; s++)
3685  {
3686  if ((*surf_fit_marker)[dofs[s]] == false) { continue; }
3687 
3688  const IntegrationPoint &ip = ir.IntPoint(s);
3689  Tpr.SetIntPoint(&ip);
3690  el_x.CalcShape(ip, shape_x);
3691  el_s.CalcShape(ip, shape_s);
3692 
3693  // These are the sums over k at the dof s (looking at the notes).
3694  surf_fit_grad_e.MultTranspose(shape_s, surf_fit_grad_s);
3695  Vector gg_ptr(surf_fit_hess_s.GetData(), dim * dim);
3696  surf_fit_hess_e.MultTranspose(shape_s, gg_ptr);
3697 
3698  // Loops over the local matrix.
3699  const double w = surf_fit_normal * surf_fit_coeff->Eval(Tpr, ip);
3700  for (int i = 0; i < dof_x * dim; i++)
3701  {
3702  const int idof = i % dof_x, idim = i / dof_x;
3703  for (int j = 0; j <= i; j++)
3704  {
3705  const int jdof = j % dof_x, jdim = j / dof_x;
3706  const double entry =
3707  w * ( 2.0 * surf_fit_grad_s(idim) * shape_x(idof) *
3708  /* */ surf_fit_grad_s(jdim) * shape_x(jdof) +
3709  2.0 * sigma_e(s) * surf_fit_hess_s(idim, jdim) *
3710  /* */ shape_x(idof) * shape_x(jdof));
3711  mat(i, j) += entry;
3712  if (i != j) { mat(j, i) += entry; }
3713  }
3714  }
3715  }
3716 }
3717 
3720  Vector &elfun, const int dofidx,
3721  const int dir, const double e_fx,
3722  bool update_stored)
3723 {
3724  int dof = el.GetDof();
3725  int idx = dir*dof+dofidx;
3726  elfun[idx] += dx;
3727  double e_fxph = GetElementEnergy(el, T, elfun);
3728  elfun[idx] -= dx;
3729  double dfdx = (e_fxph-e_fx)/dx;
3730 
3731  if (update_stored)
3732  {
3733  (*(ElemPertEnergy[T.ElementNo]))(idx) = e_fxph;
3734  (*(ElemDer[T.ElementNo]))(idx) = dfdx;
3735  }
3736 
3737  return dfdx;
3738 }
3739 
3742  const Vector &elfun,
3743  Vector &elvect)
3744 {
3745  const int dof = el.GetDof(), dim = el.GetDim(), elnum = T.ElementNo;
3746  if (elnum>=ElemDer.Size())
3747  {
3748  ElemDer.Append(new Vector);
3749  ElemPertEnergy.Append(new Vector);
3750  ElemDer[elnum]->SetSize(dof*dim);
3751  ElemPertEnergy[elnum]->SetSize(dof*dim);
3752  }
3753 
3754  elvect.SetSize(dof*dim);
3755  Vector elfunmod(elfun);
3756 
3757  // In GetElementEnergy(), skip terms that have exact derivative calculations.
3758  fd_call_flag = true;
3759 
3760  // Energy for unperturbed configuration.
3761  const double e_fx = GetElementEnergy(el, T, elfun);
3762 
3763  for (int j = 0; j < dim; j++)
3764  {
3765  for (int i = 0; i < dof; i++)
3766  {
3767  if (discr_tc)
3768  {
3770  el, T, i, j, discr_tc->GetTspecPert1H());
3771  }
3772  elvect(j*dof+i) = GetFDDerivative(el, T, elfunmod, i, j, e_fx, true);
3774  }
3775  }
3776  fd_call_flag = false;
3777 
3778  // Contributions from adaptive limiting, surface fitting (exact derivatives).
3779  if (adapt_lim_gf || surf_fit_gf)
3780  {
3782  const int nqp = ir.GetNPoints();
3783  DenseTensor Jtr(dim, dim, nqp);
3784  targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
3785 
3787  Tpr.SetFE(&el);
3788  Tpr.ElementNo = T.ElementNo;
3789  Tpr.Attribute = T.Attribute;
3790  Tpr.mesh = T.mesh;
3791  PMatI.UseExternalData(elfun.GetData(), dof, dim);
3792  Tpr.GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
3793 
3794  Vector weights(nqp);
3795  for (int q = 0; q < nqp; q++)
3796  {
3797  weights(q) = ir.IntPoint(q).weight * Jtr(q).Det();
3798  }
3799 
3800  PMatO.UseExternalData(elvect.GetData(), dof, dim);
3801  if (adapt_lim_gf) { AssembleElemVecAdaptLim(el, Tpr, ir, weights, PMatO); }
3802  if (surf_fit_gf) { AssembleElemVecSurfFit(el, Tpr, PMatO); }
3803  }
3804 }
3805 
3808  const Vector &elfun,
3809  DenseMatrix &elmat)
3810 {
3811  const int dof = el.GetDof(), dim = el.GetDim();
3812 
3813  elmat.SetSize(dof*dim);
3814  Vector elfunmod(elfun);
3815 
3816  const Vector &ElemDerLoc = *(ElemDer[T.ElementNo]);
3817  const Vector &ElemPertLoc = *(ElemPertEnergy[T.ElementNo]);
3818 
3819  // In GetElementEnergy(), skip terms that have exact derivative calculations.
3820  fd_call_flag = true;
3821  for (int i = 0; i < dof; i++)
3822  {
3823  for (int j = 0; j < i+1; j++)
3824  {
3825  for (int k1 = 0; k1 < dim; k1++)
3826  {
3827  for (int k2 = 0; k2 < dim; k2++)
3828  {
3829  elfunmod(k2*dof+j) += dx;
3830 
3831  if (discr_tc)
3832  {
3834  el, T, j, k2, discr_tc->GetTspecPert1H());
3835  if (j != i)
3836  {
3838  el, T, i, k1, discr_tc->GetTspecPert1H());
3839  }
3840  else // j==i
3841  {
3842  if (k1 != k2)
3843  {
3844  int idx = k1+k2-1;
3846  el, T, i, idx, discr_tc->GetTspecPertMixH());
3847  }
3848  else // j==i && k1==k2
3849  {
3851  el, T, i, k1, discr_tc->GetTspecPert2H());
3852  }
3853  }
3854  }
3855 
3856  double e_fx = ElemPertLoc(k2*dof+j);
3857  double e_fpxph = GetFDDerivative(el, T, elfunmod, i, k1, e_fx,
3858  false);
3859  elfunmod(k2*dof+j) -= dx;
3860  double e_fpx = ElemDerLoc(k1*dof+i);
3861 
3862  elmat(k1*dof+i, k2*dof+j) = (e_fpxph - e_fpx) / dx;
3863  elmat(k2*dof+j, k1*dof+i) = (e_fpxph - e_fpx) / dx;
3864 
3865  if (discr_tc)
3866  {
3869  }
3870  }
3871  }
3872  }
3873  }
3874  fd_call_flag = false;
3875 
3876  // Contributions from adaptive limiting.
3877  if (adapt_lim_gf || surf_fit_gf)
3878  {
3880  const int nqp = ir.GetNPoints();
3881  DenseTensor Jtr(dim, dim, nqp);
3882  targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
3883 
3885  Tpr.SetFE(&el);
3886  Tpr.ElementNo = T.ElementNo;
3887  Tpr.Attribute = T.Attribute;
3888  Tpr.mesh = T.mesh;
3889  PMatI.UseExternalData(elfun.GetData(), dof, dim);
3890  Tpr.GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
3891 
3892  Vector weights(nqp);
3893  for (int q = 0; q < nqp; q++)
3894  {
3895  weights(q) = ir.IntPoint(q).weight * Jtr(q).Det();
3896  }
3897 
3898  if (adapt_lim_gf) { AssembleElemGradAdaptLim(el, Tpr, ir, weights, elmat); }
3899  if (surf_fit_gf) { AssembleElemGradSurfFit(el, Tpr, elmat); }
3900  }
3901 }
3902 
3904 {
3905  if (!surf_fit_coeff) { return; }
3906 
3907  if (surf_fit_coeff)
3908  {
3909  auto cf = dynamic_cast<ConstantCoefficient *>(surf_fit_coeff);
3910  MFEM_VERIFY(cf, "Dynamic weight works only with a ConstantCoefficient.");
3911  cf->constant *= factor;
3912  }
3913 }
3914 
3916 {
3917  if (surf_fit_coeff)
3918  {
3919  auto cf = dynamic_cast<ConstantCoefficient *>(surf_fit_coeff);
3920  MFEM_VERIFY(cf, "Dynamic weight works only with a ConstantCoefficient.");
3921  return cf->constant;
3922  }
3923  return 0.0;
3924 }
3925 
3927 {
3929  metric_normal = 1.0 / metric_normal;
3930  lim_normal = 1.0 / lim_normal;
3931  //if (surf_fit_gf) { surf_fit_normal = 1.0 / surf_fit_normal; }
3933 }
3934 
3935 #ifdef MFEM_USE_MPI
3937 {
3938  double loc[3];
3939  ComputeNormalizationEnergies(x, loc[0], loc[1], loc[2]);
3940  double rdc[3];
3941  MPI_Allreduce(loc, rdc, 3, MPI_DOUBLE, MPI_SUM, x.ParFESpace()->GetComm());
3942  metric_normal = 1.0 / rdc[0];
3943  lim_normal = 1.0 / rdc[1];
3944  // if (surf_fit_gf) { surf_fit_normal = 1.0 / rdc[2]; }
3946 }
3947 #endif
3948 
3950  double &metric_energy,
3951  double &lim_energy,
3952  double &surf_fit_gf_energy)
3953 {
3954  Array<int> vdofs;
3955  Vector x_vals;
3956  const FiniteElementSpace* const fes = x.FESpace();
3957 
3958  const int dim = fes->GetMesh()->Dimension();
3959  Jrt.SetSize(dim);
3960  Jpr.SetSize(dim);
3961  Jpt.SetSize(dim);
3962 
3963  metric_energy = 0.0;
3964  lim_energy = 0.0;
3965  surf_fit_gf_energy = 0.0;
3966  for (int i = 0; i < fes->GetNE(); i++)
3967  {
3968  const FiniteElement *fe = fes->GetFE(i);
3970  const int nqp = ir.GetNPoints();
3971  DenseTensor Jtr(dim, dim, nqp);
3972  const int dof = fe->GetDof();
3973  DSh.SetSize(dof, dim);
3974 
3975  fes->GetElementVDofs(i, vdofs);
3976  x.GetSubVector(vdofs, x_vals);
3977  PMatI.UseExternalData(x_vals.GetData(), dof, dim);
3978 
3979  targetC->ComputeElementTargets(i, *fe, ir, x_vals, Jtr);
3980 
3981  for (int q = 0; q < nqp; q++)
3982  {
3983  const IntegrationPoint &ip = ir.IntPoint(q);
3985  CalcInverse(Jtr(q), Jrt);
3986  const double weight = ip.weight * Jtr(q).Det();
3987 
3988  fe->CalcDShape(ip, DSh);
3989  MultAtB(PMatI, DSh, Jpr);
3990  Mult(Jpr, Jrt, Jpt);
3991 
3992  metric_energy += weight * metric->EvalW(Jpt);
3993  lim_energy += weight;
3994  }
3995 
3996  // Normalization of the surface fitting term.
3997  if (surf_fit_gf)
3998  {
3999  Array<int> dofs;
4000  Vector sigma_e;
4001  surf_fit_gf->FESpace()->GetElementDofs(i, dofs);
4002  surf_fit_gf->GetSubVector(dofs, sigma_e);
4003  for (int s = 0; s < dofs.Size(); s++)
4004  {
4005  if ((*surf_fit_marker)[dofs[s]] == true)
4006  {
4007  surf_fit_gf_energy += sigma_e(s) * sigma_e(s);
4008  }
4009  }
4010  }
4011  }
4012 
4013  if (targetC->ContainsVolumeInfo() == false)
4014  {
4015  // Special case when the targets don't contain volumetric information.
4016  lim_energy = fes->GetNE();
4017  }
4018 }
4019 
4021  const FiniteElementSpace &fes)
4022 {
4023  const FiniteElement *fe = fes.GetFE(0);
4025  const int NE = fes.GetMesh()->GetNE(), dim = fe->GetDim(),
4026  dof = fe->GetDof(), nsp = ir.GetNPoints();
4027 
4028  Array<int> xdofs(dof * dim);
4029  DenseMatrix dshape(dof, dim), pos(dof, dim);
4030  Vector posV(pos.Data(), dof * dim);
4031  Jpr.SetSize(dim);
4032 
4033  dx = std::numeric_limits<float>::max();
4034 
4035  double detv_sum;
4036  double detv_avg_min = std::numeric_limits<float>::max();
4037  for (int i = 0; i < NE; i++)
4038  {
4039  fes.GetElementVDofs(i, xdofs);
4040  x.GetSubVector(xdofs, posV);
4041  detv_sum = 0.;
4042  for (int j = 0; j < nsp; j++)
4043  {
4044  fes.GetFE(i)->CalcDShape(ir.IntPoint(j), dshape);
4045  MultAtB(pos, dshape, Jpr);
4046  detv_sum += std::fabs(Jpr.Det());
4047  }
4048  double detv_avg = pow(detv_sum/nsp, 1./dim);
4049  detv_avg_min = std::min(detv_avg, detv_avg_min);
4050  }
4051  dx = detv_avg_min / dxscale;
4052 }
4053 
4055  int new_x_ordering)
4056 {
4057  if (discr_tc)
4058  {
4059  PA.Jtr_needs_update = true;
4060  }
4061  // Update adapt_lim_gf if adaptive limiting is enabled.
4062  if (adapt_lim_gf)
4063  {
4064  adapt_lim_eval->ComputeAtNewPosition(new_x, *adapt_lim_gf, new_x_ordering);
4065  }
4066 
4067  // Update surf_fit_gf if surface fitting is enabled.
4068  if (surf_fit_gf)
4069  {
4070  surf_fit_eval->ComputeAtNewPosition(new_x, *surf_fit_gf, new_x_ordering);
4071  }
4072 }
4073 
4075 {
4076  if (!fdflag) { return; }
4077  ComputeMinJac(x, fes);
4078 #ifdef MFEM_USE_MPI
4079  const ParFiniteElementSpace *pfes =
4080  dynamic_cast<const ParFiniteElementSpace *>(&fes);
4081  if (pfes)
4082  {
4083  double min_jac_all;
4084  MPI_Allreduce(&dx, &min_jac_all, 1, MPI_DOUBLE, MPI_MIN, pfes->GetComm());
4085  dx = min_jac_all;
4086  }
4087 #endif
4088 }
4089 
4091 {
4092  fdflag = true;
4093  const FiniteElementSpace *fes = x.FESpace();
4094  ComputeFDh(x,*fes);
4095  if (discr_tc)
4096  {
4097 #ifdef MFEM_USE_GSLIB
4099  if (dynamic_cast<const InterpolatorFP *>(ae))
4100  {
4101  MFEM_ABORT("Using GSLIB-based interpolation with finite differences"
4102  "requires careful consideration. Contact TMOP team.");
4103  }
4104 #endif
4108  }
4109 }
4110 
4111 #ifdef MFEM_USE_MPI
4113 {
4114  fdflag = true;
4115  const ParFiniteElementSpace *pfes = x.ParFESpace();
4116  ComputeFDh(x,*pfes);
4117  if (discr_tc)
4118  {
4119 #ifdef MFEM_USE_GSLIB
4121  if (dynamic_cast<const InterpolatorFP *>(ae))
4122  {
4123  MFEM_ABORT("Using GSLIB-based interpolation with finite differences"
4124  "requires careful consideration. Contact TMOP team.");
4125  }
4126 #endif
4127  discr_tc->UpdateTargetSpecification(x, false, pfes->GetOrdering());
4130  }
4131 }
4132 #endif
4133 
4135  const FiniteElementSpace &fes)
4136 {
4137  double min_detT = std::numeric_limits<double>::infinity();
4138  const int NE = fes.GetMesh()->GetNE();
4139  const int dim = fes.GetMesh()->Dimension();
4140  Array<int> xdofs;
4141  Jpr.SetSize(dim);
4142  Jpt.SetSize(dim);
4143  Jrt.SetSize(dim);
4144 
4145  for (int i = 0; i < NE; i++)
4146  {
4147  const FiniteElement *fe = fes.GetFE(i);
4149  const int dof = fe->GetDof(), nsp = ir.GetNPoints();
4150 
4151  DSh.SetSize(dof, dim);
4152  Vector posV(dof * dim);
4153  PMatI.UseExternalData(posV.GetData(), dof, dim);
4154 
4155  fes.GetElementVDofs(i, xdofs);
4156  x.GetSubVector(xdofs, posV);
4157 
4159  targetC->ComputeElementTargets(i, *fe, ir, posV, Jtr);
4160 
4161  for (int q = 0; q < nsp; q++)
4162  {
4163  const IntegrationPoint &ip = ir.IntPoint(q);
4164  const DenseMatrix &Jtr_q = Jtr(q);
4165  CalcInverse(Jtr_q, Jrt);
4166  fe->CalcDShape(ip, DSh);
4167  MultAtB(PMatI, DSh, Jpr);
4168  Mult(Jpr, Jrt, Jpt);
4169  double detT = Jpt.Det();
4170  min_detT = std::min(min_detT, detT);
4171  }
4172  }
4173  return min_detT;
4174 }
4175 
4177  const FiniteElementSpace &fes)
4178 {
4179  double max_muT = -std::numeric_limits<double>::infinity();
4180  const int NE = fes.GetMesh()->GetNE();
4181  const int dim = fes.GetMesh()->Dimension();
4182  Array<int> xdofs;
4183  Jpr.SetSize(dim);
4184  Jpt.SetSize(dim);
4185  Jrt.SetSize(dim);
4186 
4189 
4190  if (!wcuo || wcuo->GetWorstCaseType() !=
4192  {
4193  return 0.0;
4194  }
4195 
4196  for (int i = 0; i < NE; i++)
4197  {
4198  const FiniteElement *fe = fes.GetFE(i);
4200  const int dof = fe->GetDof(), nsp = ir.GetNPoints();
4201  Jpr.SetSize(dim);
4202  Jrt.SetSize(dim);
4203  Jpt.SetSize(dim);
4204 
4205  DSh.SetSize(dof, dim);
4206  Vector posV(dof * dim);
4207  PMatI.UseExternalData(posV.GetData(), dof, dim);
4208 
4209  fes.GetElementVDofs(i, xdofs);
4210  x.GetSubVector(xdofs, posV);
4211 
4213  targetC->ComputeElementTargets(i, *fe, ir, posV, Jtr);
4214 
4215  for (int q = 0; q < nsp; q++)
4216  {
4217  const IntegrationPoint &ip = ir.IntPoint(q);
4218  const DenseMatrix &Jtr_q = Jtr(q);
4219  CalcInverse(Jtr_q, Jrt);
4220 
4221  fe->CalcDShape(ip, DSh);
4222  MultAtB(PMatI, DSh, Jpr);
4223  Mult(Jpr, Jrt, Jpt);
4224 
4225  double metric_val = 0.0;
4226  if (wcuo)
4227  {
4228  wcuo->SetTargetJacobian(Jtr_q);
4229  metric_val = wcuo->EvalWBarrier(Jpt);
4230  }
4231 
4232  max_muT = std::max(max_muT, metric_val);
4233  }
4234  }
4235  return max_muT;
4236 }
4237 
4239  const FiniteElementSpace &fes)
4240 {
4243 
4244  if (!wcuo) { return; }
4245 
4246 #ifdef MFEM_USE_MPI
4247  const ParFiniteElementSpace *pfes =
4248  dynamic_cast<const ParFiniteElementSpace *>(&fes);
4249 #endif
4250 
4251  if (wcuo && wcuo->GetBarrierType() ==
4253  {
4254  double min_detT = ComputeMinDetT(x, fes);
4255  double min_detT_all = min_detT;
4256 #ifdef MFEM_USE_MPI
4257  if (pfes)
4258  {
4259  MPI_Allreduce(&min_detT, &min_detT_all, 1, MPI_DOUBLE, MPI_MIN,
4260  pfes->GetComm());
4261  }
4262 #endif
4263  if (wcuo) { wcuo->SetMinDetT(min_detT_all); }
4264  }
4265 
4266  double max_muT = ComputeUntanglerMaxMuBarrier(x, fes);
4267  double max_muT_all = max_muT;
4268 #ifdef MFEM_USE_MPI
4269  if (pfes)
4270  {
4271  MPI_Allreduce(&max_muT, &max_muT_all, 1, MPI_DOUBLE, MPI_MAX,
4272  pfes->GetComm());
4273  }
4274 #endif
4275  wcuo->SetMaxMuT(max_muT_all);
4276 }
4277 
4279  const GridFunction &dist,
4280  Coefficient &w0,
4281  TMOP_LimiterFunction *lfunc)
4282 {
4283  MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
4284 
4285  tmopi[0]->EnableLimiting(n0, dist, w0, lfunc);
4286  for (int i = 1; i < tmopi.Size(); i++) { tmopi[i]->DisableLimiting(); }
4287 }
4288 
4290  Coefficient &w0,
4291  TMOP_LimiterFunction *lfunc)
4292 {
4293  MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
4294 
4295  tmopi[0]->EnableLimiting(n0, w0, lfunc);
4296  for (int i = 1; i < tmopi.Size(); i++) { tmopi[i]->DisableLimiting(); }
4297 }
4298 
4300 {
4301  MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
4302 
4303  tmopi[0]->SetLimitingNodes(n0);
4304  for (int i = 1; i < tmopi.Size(); i++) { tmopi[i]->DisableLimiting(); }
4305 }
4306 
4309  const Vector &elfun)
4310 {
4311  double energy= 0.0;
4312  for (int i = 0; i < tmopi.Size(); i++)
4313  {
4314  energy += tmopi[i]->GetElementEnergy(el, T, elfun);
4315  }
4316  return energy;
4317 }
4318 
4321  const Vector &elfun,
4322  Vector &elvect)
4323 {
4324  MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
4325 
4326  tmopi[0]->AssembleElementVector(el, T, elfun, elvect);
4327  for (int i = 1; i < tmopi.Size(); i++)
4328  {
4329  Vector elvect_i;
4330  tmopi[i]->AssembleElementVector(el, T, elfun, elvect_i);
4331  elvect += elvect_i;
4332  }
4333 }
4334 
4337  const Vector &elfun,
4338  DenseMatrix &elmat)
4339 {
4340  MFEM_VERIFY(tmopi.Size() > 0, "No TMOP_Integrators were added.");
4341 
4342  tmopi[0]->AssembleElementGrad(el, T, elfun, elmat);
4343  for (int i = 1; i < tmopi.Size(); i++)
4344  {
4345  DenseMatrix elmat_i;
4346  tmopi[i]->AssembleElementGrad(el, T, elfun, elmat_i);
4347  elmat += elmat_i;
4348  }
4349 }
4350 
4353  const Vector &elfun,
4354  const IntegrationRule &irule)
4355 {
4356  double energy= 0.0;
4357  for (int i = 0; i < tmopi.Size(); i++)
4358  {
4359  energy += tmopi[i]->GetRefinementElementEnergy(el, T, elfun, irule);
4360  }
4361  return energy;
4362 }
4363 
4365  const FiniteElement &el,
4367  const Vector &elfun)
4368 {
4369  double energy= 0.0;
4370  for (int i = 0; i < tmopi.Size(); i++)
4371  {
4372  energy += tmopi[i]->GetDerefinementElementEnergy(el, T, elfun);
4373  }
4374  return energy;
4375 }
4376 
4378 {
4379  const int cnt = tmopi.Size();
4380  double total_integral = 0.0;
4381  for (int i = 0; i < cnt; i++)
4382  {
4383  tmopi[i]->EnableNormalization(x);
4384  total_integral += 1.0 / tmopi[i]->metric_normal;
4385  }
4386  for (int i = 0; i < cnt; i++)
4387  {
4388  tmopi[i]->metric_normal = 1.0 / total_integral;
4389  }
4390 }
4391 
4392 #ifdef MFEM_USE_MPI
4394 {
4395  const int cnt = tmopi.Size();
4396  double total_integral = 0.0;
4397  for (int i = 0; i < cnt; i++)
4398  {
4399  tmopi[i]->ParEnableNormalization(x);
4400  total_integral += 1.0 / tmopi[i]->metric_normal;
4401  }
4402  for (int i = 0; i < cnt; i++)
4403  {
4404  tmopi[i]->metric_normal = 1.0 / total_integral;
4405  }
4406 }
4407 #endif
4408 
4410 {
4411  for (int i = 0; i < tmopi.Size(); i++)
4412  {
4413  tmopi[i]->AssemblePA(fes);
4414  }
4415 }
4416 
4418  const FiniteElementSpace &fes)
4419 {
4420  for (int i = 0; i < tmopi.Size(); i++)
4421  {
4422  tmopi[i]->AssembleGradPA(xe,fes);
4423  }
4424 }
4425 
4427 {
4428  for (int i = 0; i < tmopi.Size(); i++)
4429  {
4430  tmopi[i]->AssembleGradDiagonalPA(de);
4431  }
4432 }
4433 
4435 {
4436  for (int i = 0; i < tmopi.Size(); i++)
4437  {
4438  tmopi[i]->AddMultPA(xe, ye);
4439  }
4440 }
4441 
4443 {
4444  for (int i = 0; i < tmopi.Size(); i++)
4445  {
4446  tmopi[i]->AddMultGradPA(re, ce);
4447  }
4448 }
4449 
4451 {
4452  double energy = 0.0;
4453  for (int i = 0; i < tmopi.Size(); i++)
4454  {
4455  energy += tmopi[i]->GetLocalStateEnergyPA(xe);
4456  }
4457  return energy;
4458 }
4459 
4461  const TargetConstructor &tc,
4462  const Mesh &mesh, GridFunction &metric_gf)
4463 {
4464  const int NE = mesh.GetNE();
4465  const GridFunction &nodes = *mesh.GetNodes();
4466  const int dim = mesh.Dimension();
4467  DenseMatrix Winv(dim), T(dim), A(dim), dshape, pos;
4468  Array<int> pos_dofs, gf_dofs;
4469  DenseTensor W;
4470  Vector posV;
4471 
4472  for (int i = 0; i < NE; i++)
4473  {
4474  const FiniteElement &fe_pos = *nodes.FESpace()->GetFE(i);
4475  const IntegrationRule &ir = metric_gf.FESpace()->GetFE(i)->GetNodes();
4476  const int nsp = ir.GetNPoints(), dof = fe_pos.GetDof();
4477 
4478  dshape.SetSize(dof, dim);
4479  pos.SetSize(dof, dim);
4480  posV.SetDataAndSize(pos.Data(), dof * dim);
4481 
4482  metric_gf.FESpace()->GetElementDofs(i, gf_dofs);
4483  nodes.FESpace()->GetElementVDofs(i, pos_dofs);
4484  nodes.GetSubVector(pos_dofs, posV);
4485 
4486  W.SetSize(dim, dim, nsp);
4487  tc.ComputeElementTargets(i, fe_pos, ir, posV, W);
4488 
4489  for (int j = 0; j < nsp; j++)
4490  {
4491  const DenseMatrix &Wj = W(j);
4492  metric.SetTargetJacobian(Wj);
4493  CalcInverse(Wj, Winv);
4494 
4495  const IntegrationPoint &ip = ir.IntPoint(j);
4496  fe_pos.CalcDShape(ip, dshape);
4497  MultAtB(pos, dshape, A);
4498  Mult(A, Winv, T);
4499 
4500  metric_gf(gf_dofs[j]) = metric.EvalW(T);
4501  }
4502  }
4503 }
4504 
4505 } // namespace mfem
Abstract class for all finite elements.
Definition: fe_base.hpp:232
void ComputeUntangleMetricQuantiles(const Vector &x, const FiniteElementSpace &fes)
Definition: tmop.cpp:4238
InvariantsEvaluator2D< double > ie
Definition: tmop.hpp:505
virtual void ComputeElementTargets(int e_id, const FiniteElement &fe, const IntegrationRule &ir, const Vector &elfun, DenseTensor &Jtr) const
Given an element and quadrature rule, computes ref->target transformation Jacobians for each quadratu...
Definition: tmop.cpp:1648
virtual double GetDerefinementElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun)
Definition: tmop.cpp:3161
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:466
virtual double EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition: tmop.cpp:930
virtual void SetParDiscreteTargetSize(const ParGridFunction &tspec_)
Definition: tmop.cpp:1785
virtual void ComputeElementTargets(int e_id, const FiniteElement &fe, const IntegrationRule &ir, const Vector &elfun, DenseTensor &Jtr) const
Given an element and quadrature rule, computes ref->target transformation Jacobians for each quadratu...
Definition: tmop.cpp:2045
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:670
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:747
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:964
InvariantsEvaluator3D< double > ie
Definition: tmop.hpp:698
virtual void SetInitialField(const Vector &init_nodes, const Vector &init_field)=0
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition: intrules.hpp:247
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:407
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const =0
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
void AddMultVWt(const Vector &v, const Vector &w, DenseMatrix &VWt)
VWt += v w^t.
Definition: densemat.cpp:3166
InvariantsEvaluator3D< double > ie
Definition: tmop.hpp:795
void AssembleElemVecSurfFit(const FiniteElement &el_x, IsoparametricTransformation &Tpr, DenseMatrix &mat)
Definition: tmop.cpp:3588
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:222
Class for an integration rule - an Array of IntegrationPoint.
Definition: intrules.hpp:90
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:910
VectorCoefficient * vector_tspec
Definition: tmop.hpp:1379
bool IsVariableOrder() const
Returns true if the space contains elements of varying polynomial orders.
Definition: fespace.hpp:463
void EnableFiniteDifferences(const GridFunction &x)
Enables FD-based approximation and computes dx.
Definition: tmop.cpp:4090
void NewDataAndSize(double *d, int s)
Set the Vector data and size, deleting the old data, if owned.
Definition: vector.hpp:162
const TargetType target_type
Definition: tmop.hpp:1261
Class for grid function - Vector with associated FE space.
Definition: gridfunc.hpp:30
DenseMatrix PMatO
Definition: tmop.hpp:1711
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:1080
DenseTensor Jtr
Definition: tmop.hpp:1741
void ComputeAvgMetrics(const GridFunction &nodes, const TargetConstructor &tc, Vector &averages) const
Definition: tmop.cpp:99
void UseExternalData(double *ext_data, int i, int j, int k)
Definition: densemat.hpp:1039
double & min_detT
Definition: tmop.hpp:390
virtual void Update(bool want_transform=true)
Reflect changes in the mesh: update number of DOFs, etc. Also, calculate GridFunction transformation ...
Definition: fespace.cpp:3336
InvariantsEvaluator3D< double > ie
Definition: tmop.hpp:717
const DenseMatrix * Jtr
Definition: tmop.hpp:26
InvariantsEvaluator3D< double > ie
Definition: tmop.hpp:774
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:1273
void Assemble_ddI2b(scalar_t w, scalar_t *A)
Definition: invariants.hpp:384
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
Definition: intrules.cpp:923
double GetSurfaceFittingWeight()
Get the surface fitting weight.
Definition: tmop.cpp:3915
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:539
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:579
Base class for vector Coefficients that optionally depend on time and space.
A coefficient that is constant across space and time.
Definition: coefficient.hpp:84
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:346
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:981
void Assemble_ddI2b(scalar_t w, scalar_t *A)
void ComputeBalancedWeights(const GridFunction &nodes, const TargetConstructor &tc, Vector &weights) const
Definition: tmop.cpp:70
DenseMatrix Jrt
Definition: tmop.hpp:1711
Geometry::Type GetElementBaseGeometry(int i) const
Definition: mesh.hpp:1108
void SetDerivativeMatrix(int height, const scalar_t *Deriv)
The Deriv matrix is dof x 2, using column-major storage.
Definition: invariants.hpp:184
const GridFunction * lim_dist
Definition: tmop.hpp:1663
virtual void SetSerialDiscreteTargetOrientation(const GridFunction &tspec_)
Definition: tmop.cpp:1898
virtual double GetElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun)
Compute the local energy.
Definition: tmop.cpp:4307
bool UsesPhysicalCoordinates() const
Return true if the methods ComputeElementTargets(), ComputeAllElementTargets(), and ComputeElementTar...
Definition: tmop.hpp:1327
struct mfem::TMOP_Integrator::@23 PA
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:1389
virtual void ComputeAtNewPosition(const Vector &new_nodes, Vector &new_field, int new_nodes_ordering=Ordering::byNODES)=0
int Dimension() const
Definition: mesh.hpp:1047
virtual void EvalGrad(DenseMatrix &K, ElementTransformation &T, const IntegrationPoint &ip, int comp)=0
Evaluate the derivative of the matrix coefficient with respect to comp in the element described by T ...
InvariantsEvaluator2D< double > ie
Definition: tmop.hpp:427
const double eps
Definition: tmop.hpp:697
void EnableNormalization(const GridFunction &x)
Computes the normalization factors of the metric and limiting integrals using the mesh position given...
Definition: tmop.cpp:3926
const scalar_t * Get_dI3b()
Definition: invariants.hpp:783
const IntegrationRule & GradientIntegrationRule(const FiniteElement &el) const
Definition: tmop.hpp:1824
void SetSize(int s)
Resize the vector to size s.
Definition: vector.hpp:512
void InterpolateTMOP_QualityMetric(TMOP_QualityMetric &metric, const TargetConstructor &tc, const Mesh &mesh, GridFunction &metric_gf)
Interpolates the metric&#39;s values at the nodes of metric_gf.
Definition: tmop.cpp:4460
TMOP_QualityMetric * metric
Definition: tmop.hpp:1645
InvariantsEvaluator2D< double > ie
Definition: tmop.hpp:445
Base class for limiting functions to be used in class TMOP_Integrator.
Definition: tmop.hpp:1072
virtual const double * HostRead() const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
Definition: vector.hpp:452
virtual void ComputeElementTargetsGradient(const IntegrationRule &ir, const Vector &elfun, IsoparametricTransformation &Tpr, DenseTensor &dJtr) const
Definition: tmop.cpp:2260
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:512
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:374
virtual double EvalW(const DenseMatrix &Jpt) const =0
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Definition: vector.hpp:117
virtual void Eval_d2(const Vector &x, const Vector &x0, double dist, DenseMatrix &d2) const =0
Returns the Hessian of the limiting function f(x, x0, d) with respect to x.
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:1373
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Definition: table.cpp:475
virtual void Update(bool want_transform=true)
Definition: pfespace.cpp:3290
void ParUpdateAfterMeshTopologyChange()
Definition: tmop.cpp:1754
DenseMatrix Jpr
Definition: tmop.hpp:1711
virtual void Eval(DenseMatrix &K, ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the matrix coefficient in the element described by T at the point ip, storing the result in ...
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition: operator.hpp:72
void SetIntPoint(const IntegrationPoint *ip)
Set the integration point ip that weights and Jacobians will be evaluated at.
Definition: eltrans.hpp:93
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const =0
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
double Det() const
Definition: densemat.cpp:488
InvariantsEvaluator2D< double > ie
Definition: tmop.hpp:222
int Size() const
Returns the size of the vector.
Definition: vector.hpp:199
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:55
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:1233
ParFiniteElementSpace * pfes
Definition: tmop.hpp:1190
Data type dense matrix using column-major storage.
Definition: densemat.hpp:23
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:1318
void GetSurfaceFittingErrors(double &err_avg, double &err_max)
Definition: tmop.cpp:2882
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:944
double * Data() const
Returns the matrix data array.
Definition: densemat.hpp:111
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:763
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:1265
struct ::_p_Mat * Mat
Definition: petsc.hpp:70
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:717
int GetNDofs() const
Returns number of degrees of freedom.
Definition: fespace.hpp:584
void EnableAdaptiveLimiting(const GridFunction &z0, Coefficient &coeff, AdaptivityEvaluator &ae)
Restriction of the node positions to certain regions.
Definition: tmop.cpp:2811
virtual const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
Definition: vector.hpp:448
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:616
int SizeJ() const
Definition: densemat.hpp:1025
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:1334
void EnableNormalization(const GridFunction &x)
Normalization factor that considers all integrators in the combination.
Definition: tmop.cpp:4377
virtual double EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition: tmop.cpp:853
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:200
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:802
double & min_detT
Definition: tmop.hpp:716
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
const AdaptivityEvaluator * GetAdaptivityEvaluator() const
Definition: tmop.hpp:1569
Abstract parallel finite element space.
Definition: pfespace.hpp:28
virtual void AssemblePA(const FiniteElementSpace &)
Method defining partial assembly.
Definition: tmop.cpp:4409
InvariantsEvaluator2D< double > ie
Definition: tmop.hpp:359
void SetSerialMetaInfo(const Mesh &m, const FiniteElementSpace &f)
Definition: tmop.cpp:2719
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:399
void UpdateGradientTargetSpecification(const Vector &x, double dx, bool use_flag=false, int x_ordering=Ordering::byNODES)
Definition: tmop.cpp:2607
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:1325
const IntegrationRule * ir
Definition: tmop.hpp:1749
InvariantsEvaluator2D< double > ie
Definition: tmop.hpp:463
void AssembleElementVectorFD(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, Vector &elvect)
Definition: tmop.cpp:3740
const GridFunction * nodes
Definition: tmop.hpp:1258
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:880
virtual void SetSerialDiscreteTargetSkew(const GridFunction &tspec_)
Definition: tmop.cpp:1878
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
Definition: vector.cpp:548
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:733
void UpdateSurfaceFittingWeight(double factor)
Update the surface fitting weight as surf_fit_coeff *= factor;.
Definition: tmop.cpp:3903
void SetRefinementSubElement(int amr_el_)
Definition: tmop.hpp:1626
void Assemble_TProd(scalar_t w, const scalar_t *X, const scalar_t *Y, scalar_t *A)
Definition: invariants.hpp:432
void Assemble_ddI1(scalar_t w, scalar_t *A)
Definition: invariants.hpp:226
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:686
Default limiter function in TMOP_Integrator.
Definition: tmop.hpp:1093
virtual double GetLocalStateEnergyPA(const Vector &) const
Compute the local (to the MPI rank) energy with partial assembly.
Definition: tmop.cpp:4450
void Set(double alpha, const double *A)
Set the matrix to alpha * A, assuming that A has the same dimensions as the matrix and uses column-ma...
Definition: densemat.cpp:572
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:206
void AssembleElementGradExact(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, DenseMatrix &elmat)
Definition: tmop.cpp:3383
virtual void AddMultGradPA(const Vector &, Vector &) const
Method for partially assembled gradient action.
Definition: tmop.cpp:4442
Array< Vector * > ElemDer
Definition: tmop.hpp:1698
double Trace() const
Trace of a square matrix.
Definition: densemat.cpp:464
const Vector & GetTspecPertMixH()
Definition: tmop.hpp:1576
Geometry Geometries
Definition: fe.cpp:49
void EnableLimiting(const GridFunction &n0, const GridFunction &dist, Coefficient &w0, TMOP_LimiterFunction *lfunc=NULL)
Adds the limiting term to the first integrator. Disables it for the rest.
Definition: tmop.cpp:4278
void Assemble_ddI2(scalar_t w, scalar_t *A)
Definition: invariants.hpp:335
Coefficient * scalar_tspec
Definition: tmop.hpp:1378
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i&#39;th element in t...
Definition: fespace.cpp:2783
virtual void SetSerialDiscreteTargetAspectRatio(const GridFunction &tspec_)
Definition: tmop.cpp:1888
int GetNumGeometries(int dim) const
Return the number of geometries of the given dimension present in the mesh.
Definition: mesh.cpp:5921
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:677
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:571
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Definition: intrules.hpp:379
const Array< int > & GetDofMap() const
Get an Array<int> that maps lexicographically ordered indices to the indices of the respective nodes/...
Definition: fe_base.hpp:1188
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:809
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:872
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:641
const IntegrationRule & EnergyIntegrationRule(const FiniteElement &el) const
Definition: tmop.hpp:1810
double ComputeUntanglerMaxMuBarrier(const Vector &x, const FiniteElementSpace &fes)
Definition: tmop.cpp:4176
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
Definition: fe_base.hpp:319
void Add(const DenseMatrix &A, const DenseMatrix &B, double alpha, DenseMatrix &C)
C = A + alpha*B.
Definition: densemat.cpp:2321
Abstract class for local mesh quality metrics in the target-matrix optimization paradigm (TMOP) by P...
Definition: tmop.hpp:23
virtual double EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition: tmop.cpp:1152
void FinalizeSerialDiscreteTargetSpec(const GridFunction &tspec_)
Definition: tmop.cpp:1908
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:432
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition: intrules.hpp:250
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:212
Coefficient * adapt_lim_coeff
Definition: tmop.hpp:1675
virtual ~AdaptivityEvaluator()
Definition: tmop.cpp:2750
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:1405
void SetJacobian(const scalar_t *Jac)
The Jacobian should use column-major storage.
Definition: invariants.hpp:181
void CalcAdjugateTranspose(const DenseMatrix &a, DenseMatrix &adjat)
Calculate the transposed adjugate of a matrix (for NxN matrices, N=1,2,3)
Definition: densemat.cpp:2551
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:246
void Assemble_ddI3b(scalar_t w, scalar_t *A)
InvariantsEvaluator3D< double > ie
Definition: tmop.hpp:737
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:352
void SetLimitingNodes(const GridFunction &n0)
Update the original/reference nodes used for limiting.
Definition: tmop.cpp:4299
void SetDiscreteTargetBase(const GridFunction &tspec_)
Definition: tmop.cpp:1831
AdaptivityEvaluator * adapt_lim_eval
Definition: tmop.hpp:1676
void GetValues(int i, const IntegrationRule &ir, Vector &vals, int vdim=1) const
Definition: gridfunc.cpp:524
double f(const Vector &xvec)
Definition: lor_mms.hpp:32
double * GetData() const
Returns the matrix data array.
Definition: densemat.hpp:115
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:587
virtual double EvalWBarrier(const DenseMatrix &Jpt) const
Definition: tmop.cpp:184
void AddMult(const DenseMatrix &b, const DenseMatrix &c, DenseMatrix &a)
Matrix matrix multiplication. A += B * C.
Definition: densemat.cpp:2447
DiscreteAdaptTC * discr_tc
Definition: tmop.hpp:1685
void EnableLimiting(const GridFunction &n0, const GridFunction &dist, Coefficient &w0, TMOP_LimiterFunction *lfunc=NULL)
Limiting of the mesh displacements (general version).
Definition: tmop.cpp:2786
virtual double EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition: tmop.cpp:23
virtual WorstCaseType GetWorstCaseType()
Definition: tmop.hpp:215
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:608
void UpdateTargetSpecificationAtNode(const FiniteElement &el, ElementTransformation &T, int nodenum, int idir, const Vector &IntData)
Definition: tmop.cpp:1980
int Size() const
For backward compatibility define Size to be synonym of Width()
Definition: densemat.hpp:102
void SetTspecFromIntRule(int e_id, const IntegrationRule &intrule)
Definition: tmop.cpp:2011
virtual int Id() const
Return the metric ID.
Definition: tmop.hpp:78
virtual void Update()
Transform by the Space UpdateMatrix (e.g., on Mesh change).
Definition: pgridfunc.cpp:81
const FiniteElementCollection * FEColl() const
Definition: fespace.hpp:601
void UpdateAfterMeshPositionChange(const Vector &new_x, int new_x_ordering=Ordering::byNODES)
Definition: tmop.cpp:4054
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:482
void Add(const double c, const DenseMatrix &A)
Adds the matrix A multiplied by the number c to the matrix.
Definition: densemat.cpp:581
void MultTranspose(const double *x, double *y) const
Multiply a vector with the transpose matrix.
Definition: densemat.cpp:215
void ResetRefinementTspecData()
Definition: tmop.hpp:1611
InvariantsEvaluator2D< double > ie
Definition: tmop.hpp:577
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:306
virtual double EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition: tmop.cpp:1226
void AssembleElementVectorExact(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, Vector &elvect)
Definition: tmop.cpp:3244
const TargetConstructor * targetC
Definition: tmop.hpp:1646
ParMesh * GetParMesh() const
Definition: pfespace.hpp:277
Array< Vector * > ElemPertEnergy
Definition: tmop.hpp:1699
const GridFunction * lim_nodes0
Definition: tmop.hpp:1660
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const =0
Evaluate the values of all shape functions of a scalar finite element in reference space at the given...
const ParGridFunction * adapt_lim_pgf0
Definition: tmop.hpp:1672
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:1016
double Sum() const
Return the sum of the vector entries.
Definition: vector.cpp:912
const scalar_t * Get_dI2b()
Definition: invariants.hpp:216
InvariantsEvaluator2D< double > ie
Definition: tmop.hpp:391
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:862
void SetDerivativeMatrix(int height, const scalar_t *Deriv)
The Deriv matrix is dof x 3, using column-major storage.
Definition: invariants.hpp:740
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:1173
virtual void AssembleGradPA(const Vector &, const FiniteElementSpace &)
Prepare the integrator for partial assembly (PA) gradient evaluations on the given FE space fes at th...
Definition: tmop.cpp:4417
InvariantsEvaluator3D< double > ie
Definition: tmop.hpp:816
virtual void SetParDiscreteTargetAspectRatio(const ParGridFunction &tspec_)
Definition: tmop.cpp:1805
double * GetData(int k)
Definition: densemat.hpp:1083
double Weight()
Return the weight of the Jacobian matrix of the transformation at the currently set IntegrationPoint...
Definition: eltrans.hpp:131
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:380
virtual void ComputeElementTargetsGradient(const IntegrationRule &ir, const Vector &elfun, IsoparametricTransformation &Tpr, DenseTensor &dJtr) const
Definition: tmop.cpp:1625
void GetColumn(int c, Vector &col) const
Definition: densemat.cpp:1331
void SetSize(int i, int j, int k, MemoryType mt_=MemoryType::PRESERVE)
Definition: densemat.hpp:1030
void ParEnableNormalization(const ParGridFunction &x)
Definition: tmop.cpp:4393
InvariantsEvaluator2D< double > ie
Definition: tmop.hpp:596
virtual void ProjectGrad(const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &grad) const
Compute the discrete gradient matrix from the given FiniteElement onto &#39;this&#39; FiniteElement. The ElementTransformation is included to support cases when the matrix depends on it.
Definition: fe_base.cpp:160
int GetNumRootElements()
Return the number of root elements.
Definition: ncmesh.hpp:366
double FNorm2() const
Compute the square of the Frobenius norm of the matrix.
Definition: densemat.hpp:269
virtual void AssembleElementVector(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, Vector &elvect)
Perform the local action of the NonlinearFormIntegrator.
Definition: tmop.cpp:3215
InvariantsEvaluator2D< double > ie
Definition: tmop.hpp:323
FiniteElementSpace * tspec_fesv
Definition: tmop.hpp:1443
A class for non-conforming AMR. The class is not used directly by the user, rather it is an extension...
Definition: ncmesh.hpp:121
Coefficient * metric_coeff
Definition: tmop.hpp:1653
void AssembleElemGradSurfFit(const FiniteElement &el_x, IsoparametricTransformation &Tpr, DenseMatrix &mat)
Definition: tmop.cpp:3642
void SetData(double *d)
Definition: vector.hpp:149
FiniteElementSpace * FESpace()
Definition: gridfunc.hpp:683
TMOP_QualityMetric * h_metric
Definition: tmop.hpp:1644
Array< TMOP_QualityMetric * > tmop_q_arr
Definition: tmop.hpp:88
void Mult(const double *x, double *y) const
Matrix vector multiplication.
Definition: densemat.cpp:173
int GetNE() const
Returns number of elements in the mesh.
Definition: fespace.hpp:614
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:1115
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:368
virtual BarrierType GetBarrierType()
Definition: tmop.hpp:213
void Assemble_ddI1b(scalar_t w, scalar_t *A)
Definition: invariants.hpp:257
void RestoreTargetSpecificationAtNode(ElementTransformation &T, int nodenum)
Definition: tmop.cpp:1997
bool Parallel() const
Definition: tmop.hpp:1303
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:1037
void SetTspecAtIndex(int idx, const GridFunction &tspec_)
Definition: tmop.cpp:1855
virtual double GetRefinementElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, const IntegrationRule &irule)
Computes the mean of the energies of the given element&#39;s children.
Definition: tmop.cpp:3075
double * GetData() const
Return a pointer to the beginning of the Vector data.
Definition: vector.hpp:208
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:43
void CalcInverse(const DenseMatrix &a, DenseMatrix &inva)
Definition: densemat.cpp:2587
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:358
int GetVDim() const
Returns vector dimension.
Definition: fespace.hpp:581
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indexes of degrees of freedom in array dofs for i&#39;th element.
Definition: fespace.cpp:281
double omega
Definition: ex25.cpp:141
Coefficient * lim_coeff
Definition: tmop.hpp:1661
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:502
AdaptivityEvaluator * surf_fit_eval
Definition: tmop.hpp:1682
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:449
Mesh * GetMesh() const
Returns the mesh.
Definition: fespace.hpp:441
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:649
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:952
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:1045
virtual void SetTargetJacobian(const DenseMatrix &Jtr_)
Specify the reference-element -> target-element Jacobian matrix for the point of interest.
Definition: tmop.hpp:43
void Transpose()
(*this) = (*this)^t
Definition: densemat.cpp:1420
int GetDim() const
Returns the reference space dimension for the finite element.
Definition: fe_base.hpp:310
ComplexDenseMatrix * MultAtB(const ComplexDenseMatrix &A, const ComplexDenseMatrix &B)
Multiply the complex conjugate transpose of a matrix A with a matrix B. A^H*B.
void AssembleElemGradAdaptLim(const FiniteElement &el, IsoparametricTransformation &Tpr, const IntegrationRule &ir, const Vector &weights, DenseMatrix &m)
Definition: tmop.cpp:3527
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:286
void AddMultABt(const DenseMatrix &A, const DenseMatrix &B, DenseMatrix &ABt)
ABt += A * B^t.
Definition: densemat.cpp:2886
virtual void AssembleElementGrad(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, DenseMatrix &elmat)
Assemble the local gradient matrix.
Definition: tmop.cpp:3229
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:1029
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:1126
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:96
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:1249
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:1162
void Assemble_ddI2(scalar_t w, scalar_t *A)
Definition: invariants.hpp:951
const double eps
Definition: tmop.hpp:576
DenseMatrix tspec_refine
Definition: tmop.hpp:1432
const scalar_t * Get_dI1()
Definition: invariants.hpp:763
virtual double EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition: tmop.cpp:1094
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
Definition: coefficient.hpp:41
InvariantsEvaluator3D< double > ie
Definition: tmop.hpp:941
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:33
TMOPMatrixCoefficient * matrix_tspec
Definition: tmop.hpp:1380
virtual double EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition: tmop.cpp:341
double Min() const
Returns the minimal element of the vector.
Definition: vector.cpp:1194
ParFiniteElementSpace * ParFESpace() const
Definition: pgridfunc.hpp:113
const scalar_t * Get_dI1()
Definition: invariants.hpp:204
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition: array.hpp:684
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:1189
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:996
virtual bool ContainsVolumeInfo() const
Checks if the target matrices contain non-trivial size specification.
Definition: tmop.cpp:1540
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:600
InvariantsEvaluator2D< double > ie
Definition: tmop.hpp:410
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:1104
void MultAAt(const DenseMatrix &a, DenseMatrix &aat)
Calculate the matrix A.At.
Definition: densemat.cpp:2719
void ReleasePADeviceMemory(bool copy_to_host=true)
Definition: tmop.cpp:2760
double * HostWrite()
Shortcut for mfem::Write(GetMemory(), TotalSize(), false).
Definition: densemat.hpp:1124
virtual void AssembleElementGrad(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, DenseMatrix &elmat)
Assemble the local gradient matrix.
Definition: tmop.cpp:4335
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition: fe_base.hpp:322
void CalcInverseTranspose(const DenseMatrix &a, DenseMatrix &inva)
Calculate the inverse transpose of a matrix (for NxN matrices, N=1,2,3)
Definition: densemat.cpp:2654
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition: operator.hpp:66
const scalar_t * Get_dI1b()
Definition: invariants.hpp:208
DenseTensor Jtrcomp
Definition: tmop.hpp:1439
int NumCols() const
Get the number of columns (size of input) of the Operator. Synonym with Width().
Definition: operator.hpp:75
void SetDataAndSize(double *d, int s)
Set the Vector data and size.
Definition: vector.hpp:156
void SetParMetaInfo(const ParMesh &m, const ParFiniteElementSpace &f)
Parallel version of SetSerialMetaInfo.
Definition: tmop.cpp:2730
virtual DofTransformation * GetElementDofs(int elem, Array< int > &dofs) const
Returns indices of degrees of freedom of element &#39;elem&#39;.
Definition: fespace.cpp:2680
virtual void Update()
Transform by the Space UpdateMatrix (e.g., on Mesh change).
Definition: gridfunc.cpp:165
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:699
GridFunction * tspec_gf
Definition: tmop.hpp:1445
const scalar_t * Get_dI1b()
Definition: invariants.hpp:767
virtual double EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition: tmop.cpp:630
void UpdateAfterMeshTopologyChange()
Definition: tmop.cpp:2912
virtual void SetMaxMuT(double max_muT_)
Definition: tmop.hpp:211
DenseMatrix PMatI
Definition: tmop.hpp:1711
virtual void SetMinDetT(double min_detT_)
Definition: tmop.hpp:209
InvariantsEvaluator3D< double > ie
Definition: tmop.hpp:755
int GetNE() const
Returns number of elements.
Definition: mesh.hpp:936
virtual void ComputeElementTargets(int e_id, const FiniteElement &fe, const IntegrationRule &ir, const Vector &elfun, DenseTensor &Jtr) const
Given an element and quadrature rule, computes ref->target transformation Jacobians for each quadratu...
Definition: tmop.cpp:1554
double a
Definition: lissajous.cpp:41
void ComputeFDh(const Vector &x, const FiniteElementSpace &fes)
Determines the perturbation, h, for FD-based approximation.
Definition: tmop.cpp:4074
const scalar_t * Get_dI2b()
Definition: invariants.hpp:775
virtual double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
Definition: vector.hpp:464
virtual double EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition: tmop.cpp:1311
void ComputeNormalizationEnergies(const GridFunction &x, double &metric_energy, double &lim_energy, double &surf_fit_gf_energy)
Definition: tmop.cpp:3949
virtual double Eval(const Vector &x, const Vector &x0, double d) const =0
Returns the limiting function, f(x, x0, d).
Coefficient * surf_fit_coeff
Definition: tmop.hpp:1681
Class for integration point with weight.
Definition: intrules.hpp:25
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:550
void UpdateHessianTargetSpecification(const Vector &x, double dx, bool use_flag=false, int x_ordering=Ordering::byNODES)
Definition: tmop.cpp:2642
AdaptivityEvaluator * adapt_eval
Definition: tmop.hpp:1462
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:775
ParFiniteElementSpace * ptspec_fesv
Definition: tmop.hpp:1448
InvariantsEvaluator3D< double > ie
Definition: tmop.hpp:615
void Assemble_TProd(scalar_t w, const scalar_t *X, const scalar_t *Y, scalar_t *A)
const FiniteElementSpace * fes
Definition: tmop.hpp:1748
Array< TMOP_Integrator * > tmopi
Definition: tmop.hpp:2070
A standard isoparametric element transformation.
Definition: eltrans.hpp:361
const scalar_t * Get_dI2()
Definition: invariants.hpp:771
void ComputeMinJac(const Vector &x, const FiniteElementSpace &fes)
Definition: tmop.cpp:4020
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
Definition: mesh.cpp:348
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:1347
const IntegrationRule & ActionIntegrationRule(const FiniteElement &el) const
Definition: tmop.hpp:1819
MPI_Comm GetComm() const
Definition: tmop.hpp:1304
Ordering::Type GetOrdering() const
Return the ordering method.
Definition: fespace.hpp:599
double GetFDDerivative(const FiniteElement &el, ElementTransformation &T, Vector &elfun, const int nodenum, const int idir, const double baseenergy, bool update_stored)
Definition: tmop.cpp:3718
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:918
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:973
double surf_fit_normal
Definition: tmop.hpp:1683
int dim
Definition: ex24.cpp:53
virtual double GetElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun)
Computes the integral of W(Jacobian(Trt)) over a target zone.
Definition: tmop.cpp:2938
void AssembleElemVecAdaptLim(const FiniteElement &el, IsoparametricTransformation &Tpr, const IntegrationRule &ir, const Vector &weights, DenseMatrix &mat)
Definition: tmop.cpp:3491
void SetFE(const FiniteElement *FE)
Set the element that will be used to compute the transformations.
Definition: eltrans.hpp:381
void ParUpdateAfterMeshTopologyChange()
Definition: tmop.cpp:2925
virtual double GetDerefinementElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun)
Definition: tmop.cpp:4364
void ComputeAvgVolume() const
Definition: tmop.cpp:1426
void Assemble_ddI1(scalar_t w, scalar_t *A)
Definition: invariants.hpp:793
virtual void Eval_d1(const Vector &x, const Vector &x0, double dist, Vector &d1) const =0
Returns the gradient of the limiting function f(x, x0, d) with respect to x.
const Operator * GetUpdateOperator()
Get the GridFunction update operator.
Definition: fespace.hpp:897
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:742
const Vector & GetTspecPert2H()
Definition: tmop.hpp:1575
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:657
const Vector & GetTspecPert1H()
Definition: tmop.hpp:1574
int SizeI() const
Definition: densemat.hpp:1024
void AssembleElementGradFD(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, DenseMatrix &elmat)
Definition: tmop.cpp:3806
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:440
InvariantsEvaluator2D< double > ie
Definition: tmop.hpp:301
double infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
Definition: vector.hpp:46
const DenseMatrix & GetGeomToPerfGeomJac(int GeomType) const
Definition: geom.hpp:98
virtual void SetParDiscreteTargetSpec(const ParGridFunction &tspec_)
Definition: tmop.cpp:1825
InvariantsEvaluator2D< double > ie
Definition: tmop.hpp:341
double Norml2() const
Returns the l2 norm of the vector.
Definition: vector.cpp:804
NCMesh * ncmesh
Optional nonconforming mesh extension.
Definition: mesh.hpp:278
void GetVectorValues(int i, const IntegrationRule &ir, DenseMatrix &vals, DenseMatrix &tr) const
Definition: gridfunc.cpp:717
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:1240
int Size() const
Return the logical size of the array.
Definition: array.hpp:141
RefCoord t[3]
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the coefficient in the element described by T at the point ip.
GridFunction * adapt_lim_gf
Definition: tmop.hpp:1674
const scalar_t * Get_dI2()
Definition: invariants.hpp:212
MPI_Comm GetComm() const
Definition: pfespace.hpp:273
GridFunction * surf_fit_gf
Definition: tmop.hpp:1679
const double alpha
Definition: ex15.cpp:369
void FinalizeParDiscreteTargetSpec(const ParGridFunction &tspec_)
Definition: tmop.cpp:1729
virtual int OrderJ() const
Return the order of the elements of the Jacobian of the transformation.
Definition: eltrans.cpp:443
ParGridFunction * tspec_pgf
Definition: tmop.hpp:1450
Vector data type.
Definition: vector.hpp:60
void GetDiscreteTargetSpec(GridFunction &tspec_, int idx)
Get one of the discrete fields from tspec.
Definition: tmop.cpp:1929
DenseMatrix DSh
Definition: tmop.hpp:1711
const Array< bool > * surf_fit_marker
Definition: tmop.hpp:1680
virtual double EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition: tmop.cpp:793
const DenseMatrix & GetPointMat() const
Return the stored point matrix.
Definition: eltrans.hpp:404
DenseMatrix DS
Definition: tmop.hpp:1711
InvariantsEvaluator3D< double > ie
Definition: tmop.hpp:655
virtual void AssembleGradDiagonalPA(Vector &) const
Method for computing the diagonal of the gradient with partial assembly.
Definition: tmop.cpp:4426
void SetTspecDataForDerefinement(FiniteElementSpace *fes)
Computes target specification data with respect to the coarse FE space.
Definition: tmop.cpp:2037
void UpdateTargetSpecification(const Vector &new_x, bool use_flag=false, int new_x_ordering=Ordering::byNODES)
Definition: tmop.cpp:1960
void GetNodes(Vector &node_coord) const
Definition: mesh.cpp:7949
void EnableSurfaceFitting(const GridFunction &s0, const Array< bool > &smarker, Coefficient &coeff, AdaptivityEvaluator &ae)
Fitting of certain DOFs to the zero level set of a function.
Definition: tmop.cpp:2846
void DeleteGeometricFactors()
Destroy all GeometricFactors stored by the Mesh.
Definition: mesh.cpp:882
InvariantsEvaluator3D< double > ie
Definition: tmop.hpp:959
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:755
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:167
RefCoord s[3]
virtual void SetSerialDiscreteTargetSpec(const GridFunction &tspec_)
Definition: tmop.cpp:1954
virtual void SetParDiscreteTargetSkew(const ParGridFunction &tspec_)
Definition: tmop.cpp:1795
virtual double EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition: tmop.cpp:896
virtual void ComputeElementTargetsGradient(const IntegrationRule &ir, const Vector &elfun, IsoparametricTransformation &Tpr, DenseTensor &dJtr) const
Definition: tmop.cpp:1682
virtual double GetRefinementElementEnergy(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, const IntegrationRule &irule)
Definition: tmop.cpp:4351
virtual void SetParDiscreteTargetOrientation(const ParGridFunction &tspec_)
Definition: tmop.cpp:1815
void UseExternalData(double *d, int h, int w)
Change the data array and the size of the DenseMatrix.
Definition: densemat.hpp:80
Class for parallel grid function.
Definition: pgridfunc.hpp:32
void Assemble_ddI1b(scalar_t w, scalar_t *A)
Definition: invariants.hpp:827
Base class representing target-matrix construction algorithms for mesh optimization via the target-ma...
Definition: tmop.hpp:1234
const FiniteElement * GetFE() const
Get the current element used to compute the transformations.
Definition: eltrans.hpp:389
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Definition: densemat.hpp:105
virtual ~DiscreteAdaptTC()
Definition: tmop.cpp:2709
Abstract operator.
Definition: operator.hpp:24
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Definition: fe_base.hpp:388
virtual void CalcDShape(const IntegrationPoint &ip, DenseMatrix &dshape) const =0
Evaluate the gradients of all shape functions of a scalar finite element in reference space at the gi...
virtual void SetAnalyticTargetSpec(Coefficient *sspec, VectorCoefficient *vspec, TMOPMatrixCoefficient *mspec)
Definition: tmop.cpp:1639
Rank 3 tensor (array of matrices)
Definition: densemat.hpp:978
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:392
virtual double EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition: tmop.cpp:1058
Class for parallel meshes.
Definition: pmesh.hpp:32
virtual void SetSerialDiscreteTargetSize(const GridFunction &tspec_)
Definition: tmop.cpp:1868
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:1285
TMOP_LimiterFunction * lim_func
Definition: tmop.hpp:1665
InvariantsEvaluator3D< double > ie
Definition: tmop.hpp:634
const GridFunction * adapt_lim_gf0
Definition: tmop.hpp:1670
virtual void AssembleElementVector(const FiniteElement &el, ElementTransformation &T, const Vector &elfun, Vector &elvect)
Perform the local action of the NonlinearFormIntegrator.
Definition: tmop.cpp:4319
double ComputeMinDetT(const Vector &x, const FiniteElementSpace &fes)
Definition: tmop.cpp:4134
virtual void AddMultPA(const Vector &, Vector &) const
Method for partially assembled action.
Definition: tmop.cpp:4434
DenseMatrix Jpt
Definition: tmop.hpp:1711
int GetOrder() const
Returns the order of the finite element. In the case of anisotropic orders, returns the maximum order...
Definition: fe_base.hpp:326
Array< double > wt_arr
Definition: tmop.hpp:89
void ParEnableNormalization(const ParGridFunction &x)
Definition: tmop.cpp:3936
void ComputeAllElementTargets_Fallback(const FiniteElementSpace &fes, const IntegrationRule &ir, const Vector &xe, DenseTensor &Jtr) const
Definition: tmop.cpp:1468
DenseMatrix P
Definition: tmop.hpp:1711
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:1064
class Mesh * mesh
The Mesh object containing the element.
Definition: eltrans.hpp:84
void UpdateAfterMeshTopologyChange()
Update all discrete fields based on tspec and update for AMR.
Definition: tmop.cpp:1943
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:903
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:558
virtual double EvalW(const DenseMatrix &Jpt) const
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants...
Definition: tmop.cpp:937
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:818
virtual void EvalP(const DenseMatrix &Jpt, DenseMatrix &P) const
Evaluate the 1st Piola-Kirchhoff stress tensor, P = P(Jpt).
Definition: tmop.cpp:1072
FiniteElementSpace * fes
Definition: tmop.hpp:1185
InvariantsEvaluator3D< double > ie
Definition: tmop.hpp:676
virtual void AssembleH(const DenseMatrix &Jpt, const DenseMatrix &DS, const double weight, DenseMatrix &A) const
Evaluate the derivative of the 1st Piola-Kirchhoff stress tensor and assemble its contribution to the...
Definition: tmop.cpp:1021
FiniteElementSpace * coarse_tspec_fesv
Definition: tmop.hpp:1444
void SetJacobian(const scalar_t *Jac)
The Jacobian should use column-major storage.
Definition: invariants.hpp:737