MFEM  v4.6.0
Finite element discretization library
check-tmop-metric.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 // ------------------------------------------------------
13 // Check Metric Miniapp: Check TMOP Metric Implementation
14 // ------------------------------------------------------
15 //
16 // This miniapp checks the evaluation, 1st, and 2nd derivatives of a TMOP
17 // metric. Works only in serial.
18 //
19 // Compile with: make check-tmop-metric
20 //
21 // Sample runs: check-tmop-metric -mid 360
22 
23 #include "mfem.hpp"
24 #include <iostream>
25 
26 using namespace mfem;
27 using namespace std;
28 
29 int main(int argc, char *argv[])
30 {
31  int metric_id = 2;
32  int convergence_iter = 10;
33  bool verbose = false;
34 
35  // Choose metric.
36  OptionsParser args(argc, argv);
37  args.AddOption(&metric_id, "-mid", "--metric-id", "Metric id");
38  args.AddOption(&verbose, "-v", "-verbose", "-no-v", "--no-verbose",
39  "Enable extra screen output.");
40  args.AddOption(&convergence_iter, "-i", "--iterations",
41  "Number of iterations to check convergence of derivatives.");
42 
43  args.Parse();
44  if (!args.Good())
45  {
46  args.PrintUsage(cout);
47  return 1;
48  }
49  args.PrintOptions(cout);
50 
51  // Setup metric.
52  double tauval = -0.1;
53  TMOP_QualityMetric *metric = NULL;
54  switch (metric_id)
55  {
56  // T-metrics
57  case 1: metric = new TMOP_Metric_001; break;
58  case 2: metric = new TMOP_Metric_002; break;
59  case 7: metric = new TMOP_Metric_007; break;
60  case 9: metric = new TMOP_Metric_009; break;
61  case 14: metric = new TMOP_Metric_014; break;
62  case 22: metric = new TMOP_Metric_022(tauval); break;
63  case 50: metric = new TMOP_Metric_050; break;
64  case 55: metric = new TMOP_Metric_055; break;
65  case 56: metric = new TMOP_Metric_056; break;
66  case 58: metric = new TMOP_Metric_058; break;
67  case 77: metric = new TMOP_Metric_077; break;
68  case 80: metric = new TMOP_Metric_080(0.5); break;
69  case 85: metric = new TMOP_Metric_085; break;
70  case 90: metric = new TMOP_Metric_090; break;
71  case 94: metric = new TMOP_Metric_094; break;
72  case 98: metric = new TMOP_Metric_098; break;
73  // case 211: metric = new TMOP_Metric_211; break;
74  // case 252: metric = new TMOP_Metric_252(tauval); break;
75  case 301: metric = new TMOP_Metric_301; break;
76  case 302: metric = new TMOP_Metric_302; break;
77  case 303: metric = new TMOP_Metric_303; break;
78  case 304: metric = new TMOP_Metric_304; break;
79  // case 311: metric = new TMOP_Metric_311; break;
80  case 313: metric = new TMOP_Metric_313(tauval); break;
81  case 315: metric = new TMOP_Metric_315; break;
82  case 316: metric = new TMOP_Metric_316; break;
83  case 318: metric = new TMOP_Metric_318; break;
84  case 321: metric = new TMOP_Metric_321; break;
85  case 322: metric = new TMOP_Metric_322; break;
86  case 323: metric = new TMOP_Metric_323; break;
87  case 328: metric = new TMOP_Metric_328; break;
88  case 332: metric = new TMOP_Metric_332(0.5); break;
89  case 333: metric = new TMOP_Metric_333(0.5); break;
90  case 334: metric = new TMOP_Metric_334(0.5); break;
91  case 338: metric = new TMOP_Metric_338; break;
92  case 347: metric = new TMOP_Metric_347(0.5); break;
93  // case 352: metric = new TMOP_Metric_352(tauval); break;
94  case 360: metric = new TMOP_Metric_360; break;
95  // A-metrics
96  case 11: metric = new TMOP_AMetric_011; break;
97  case 36: metric = new TMOP_AMetric_036; break;
98  case 107: metric = new TMOP_AMetric_107a; break;
99  case 126: metric = new TMOP_AMetric_126(0.9); break;
100  default: cout << "Unknown metric_id: " << metric_id << endl; return 3;
101  }
102 
103  const int dim = (metric_id < 300) ? 2 : 3;
104  DenseMatrix T(dim);
105  Vector T_vec(T.GetData(), dim * dim);
106 
107  // Test evaluation.
108  int valid_cnt = 0, bad_cnt = 0;
109  for (int i = 0; i < 1000; i++)
110  {
111  T_vec.Randomize(i);
112  // Increase probability of det(T) > 0.
113  T(0, 0) += T_vec.Max();
114  if (T.Det() <= 0.0) { continue; }
115 
116  const double i_form = metric->EvalW(T),
117  m_form = metric->EvalWMatrixForm(T);
118  const double diff = fabs(i_form - m_form) / fabs(m_form);
119  if (diff > 1e-8)
120  {
121  bad_cnt++;
122  if (verbose)
123  {
124  cout << "Wrong metric computation: "
125  << i_form << " (invariant), " << m_form << " (matrix form) "
126  << diff << " (normalized difference) " << endl;
127  }
128  }
129  valid_cnt++;
130  }
131  cout << "--- EvalW: " << bad_cnt << " errors out of "
132  << valid_cnt << " comparisons with det(T) > 0.\n";
133 
134  Mesh *mesh;
135  if (dim == 2)
136  {
138  }
139  else
140  {
141  mesh = new Mesh(Mesh::MakeCartesian3D(1, 1, 1, Element::HEXAHEDRON));
142  }
143  H1_FECollection fec(2, dim);
144  FiniteElementSpace fespace(mesh, &fec, dim);
145  NonlinearForm a(&fespace);
146  mesh->SetNodalFESpace(&fespace);
147  GridFunction x(&fespace);
148  mesh->SetNodalGridFunction(&x);
149  x(0) = 0.25;
150 
152  tc.SetNodes(x);
153  auto integ = new TMOP_Integrator(metric, &tc, NULL);
154  a.AddDomainIntegrator(integ);
155 
157  const FiniteElement &fe = *fespace.GetFE(0);
158  Array<int> vdofs;
159  fespace.GetElementVDofs(0, vdofs);
160  Vector x_loc(x.Size());
161  x.GetSubVector(vdofs, x_loc);
162 
163  // Test 1st derivative (assuming EvalW is correct). Should be 2nd order.
164  Vector dF_0;
165  const double F_0 = integ->GetElementEnergy(fe, Tr, x_loc);
166  integ->AssembleElementVector(fe, Tr, x_loc, dF_0);
167  if (verbose) { cout << "***\ndF = \n"; dF_0.Print(); cout << "***\n"; }
168  double dx = 0.1;
169  double rate_dF_sum = 0.0, err_old;
170  for (int k = 0; k < convergence_iter; k++)
171  {
172  double err_k = 0.0;
173  for (int i = 0; i < x_loc.Size(); i++)
174  {
175  x_loc(i) += dx;
176  err_k = fmax(err_k, fabs(F_0 + dF_0(i) * dx -
177  integ->GetElementEnergy(fe, Tr, x_loc)));
178  x_loc(i) -= dx;
179  }
180  dx *= 0.5;
181 
182  if (verbose && k == 0)
183  {
184  std::cout << "dF error " << k << ": " << err_k << endl;
185  }
186  if (k > 0)
187  {
188  double r = log2(err_old / err_k);
189  rate_dF_sum += r;
190  if (verbose)
191  {
192  std::cout << "dF error " << k << ": " << err_k << " " << r << endl;
193  }
194  }
195  err_old = err_k;
196  }
197  std::cout << "--- EvalP: avg rate of convergence (should be 2): "
198  << rate_dF_sum / (convergence_iter - 1) << endl;
199 
200  // Test 2nd derivative (assuming EvalP is correct).
201  double min_avg_rate = 7.0;
202  DenseMatrix ddF_0;
203  integ->AssembleElementGrad(fe, Tr, x_loc, ddF_0);
204  if (verbose) { cout << "***\nddF = \n"; ddF_0.Print(); cout << "***\n"; }
205  for (int i = 0; i < x_loc.Size(); i++)
206  {
207  double rate_sum = 0.0;
208  dx = 0.1;
209  for (int k = 0; k < convergence_iter; k++)
210  {
211  double err_k = 0.0;
212 
213  for (int j = 0; j < x_loc.Size(); j++)
214  {
215  x_loc(j) += dx;
216  Vector dF_dx;
217  integ->AssembleElementVector(fe, Tr, x_loc, dF_dx);
218  err_k = fmax(err_k, fabs(dF_0(i) + ddF_0(i, j) * dx - dF_dx(i)));
219  x_loc(j) -= dx;
220  }
221  dx *= 0.5;
222 
223  if (verbose && k == 0)
224  {
225  cout << "ddF error for dof " << i << ", " << k << ": "
226  << err_k << endl;
227  }
228  if (k > 0)
229  {
230  double r = log2(err_old / err_k);
231  // Error is zero (2nd derivative is exact) -> put rate 2 (optimal).
232  if (err_k < 1e-14) { r = 2.0; }
233  rate_sum += r;
234  if (verbose)
235  {
236  cout << "ddF error for dof " << i << ", " << k << ": " << err_k
237  << " " << r << endl;
238  }
239 
240  }
241  err_old = err_k;
242  }
243  min_avg_rate = fmin(min_avg_rate, rate_sum / (convergence_iter - 1));
244  }
245  std::cout << "--- AssembleH: avg rate of convergence (should be 2): "
246  << min_avg_rate << endl;
247 
248  delete metric;
249  delete mesh;
250  return 0;
251 }
Abstract class for all finite elements.
Definition: fe_base.hpp:233
3D non-barrier Shape (S) metric.
Definition: tmop.hpp:1051
Class for grid function - Vector with associated FE space.
Definition: gridfunc.hpp:30
3D barrier Shape+Size (VS) metric, well-posed (invex).
Definition: tmop.hpp:843
3D barrier Shape+Size (VS) metric, well-posed (polyconvex).
Definition: tmop.hpp:967
void PrintOptions(std::ostream &out) const
Print the options.
Definition: optparser.cpp:331
3D Size (V) metric.
Definition: tmop.hpp:822
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition: tmop.hpp:703
void PrintUsage(std::ostream &out) const
Print the usage message.
Definition: optparser.cpp:462
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...
static Mesh MakeCartesian3D(int nx, int ny, int nz, Element::Type type, double sx=1.0, double sy=1.0, double sz=1.0, bool sfc_ordering=true)
Definition: mesh.cpp:3783
void Print(std::ostream &out=mfem::out, int width=8) const
Prints vector to stream out.
Definition: vector.cpp:756
int Size() const
Returns the size of the vector.
Definition: vector.hpp:197
Data type dense matrix using column-major storage.
Definition: densemat.hpp:23
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition: tmop.hpp:682
3D Size (V) metric.
Definition: tmop.hpp:785
3D compound barrier Shape+Size (VS) metric (polyconvex, balanced).
Definition: tmop.hpp:989
2D barrier Shape+Size (VS) metric (polyconvex).
Definition: tmop.hpp:1145
3D barrier Shape+Size (VS) metric, well-posed (invex).
Definition: tmop.hpp:885
bool Good() const
Return true if the command line options were parsed successfully.
Definition: optparser.hpp:159
STL namespace.
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
Definition: vector.cpp:579
void Randomize(int seed=0)
Set random values in the vector.
Definition: vector.cpp:817
2D barrier Shape+Size (VS) metric (not polyconvex).
Definition: tmop.hpp:340
3D barrier Shape+Size (VS) metric, well-posed (invex).
Definition: tmop.hpp:864
2D Shifted barrier form of shape metric (mu_2).
Definition: tmop.hpp:389
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:2841
2D barrier shape (S) metric (not polyconvex).
Definition: tmop.hpp:466
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition: tmop.hpp:724
Abstract class for local mesh quality metrics in the target-matrix optimization paradigm (TMOP) by P...
Definition: tmop.hpp:23
2D compound barrier Shape+Size (VS) metric (balanced).
Definition: tmop.hpp:588
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
Definition: optparser.cpp:151
3D Size (V) metric.
Definition: tmop.hpp:803
void SetNodes(const GridFunction &n)
Set the nodes to be used in the target-matrix construction.
Definition: tmop.hpp:1409
virtual void Print(std::ostream &out=mfem::out, int width_=4) const
Prints matrix to stream out.
Definition: densemat.cpp:2221
3D barrier Shape+Size (VS) metric, well-posed (polyconvex).
Definition: tmop.hpp:1010
2D barrier Shape+Size+Orientation (VOS) metric (polyconvex).
Definition: tmop.hpp:609
virtual void SetNodalFESpace(FiniteElementSpace *nfes)
Definition: mesh.cpp:5577
2D barrier Shape+Orientation (OS) metric (polyconvex).
Definition: tmop.hpp:1127
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for the i&#39;th element. The returned indices are offsets into an ...
Definition: fespace.cpp:281
3D compound barrier Shape+Size (VS) metric (polyconvex, balanced).
Definition: tmop.hpp:906
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:219
void AddOption(bool *var, const char *enable_short_name, const char *enable_long_name, const char *disable_short_name, const char *disable_long_name, const char *description, bool required=false)
Add a boolean option and set &#39;var&#39; to receive the value. Enable/disable tags are used to set the bool...
Definition: optparser.hpp:82
static Mesh MakeCartesian2D(int nx, int ny, Element::Type type, bool generate_edges=false, double sx=1.0, double sy=1.0, bool sfc_ordering=true)
Definition: mesh.cpp:3773
2D barrier Shape+Size (VS) metric (not polyconvex).
Definition: tmop.hpp:358
double a
Definition: lissajous.cpp:41
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.hpp:47
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
Definition: mesh.cpp:355
2D barrier Shape+Size+Orientation (VOS) metric (polyconvex).
Definition: tmop.hpp:1109
3D Shape (S) metric, untangling version of 303.
Definition: tmop.hpp:764
int dim
Definition: ex24.cpp:53
2D compound barrier Shape+Size (VS) metric (balanced).
Definition: tmop.hpp:567
Vector data type.
Definition: vector.hpp:58
3D barrier Shape+Size (VS) metric, well-posed (polyconvex).
Definition: tmop.hpp:948
Arbitrary order H1-conforming (continuous) finite elements.
Definition: fe_coll.hpp:259
int main(int argc, char *argv[])
void SetNodalGridFunction(GridFunction *nodes, bool make_owner=false)
Definition: mesh.cpp:5624
Base class representing target-matrix construction algorithms for mesh optimization via the target-ma...
Definition: tmop.hpp:1329
3D compound barrier Shape+Size (VS) metric (polyconvex).
Definition: tmop.hpp:927
2D barrier Shape+Orientation (OS) metric (polyconvex).
Definition: tmop.hpp:552
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition: tmop.hpp:663
2D non-barrier metric without a type.
Definition: tmop.hpp:221
A TMOP integrator class based on any given TMOP_QualityMetric and TargetConstructor.
Definition: tmop.hpp:1733
2D non-barrier Shape+Size+Orientation (VOS) metric (polyconvex).
Definition: tmop.hpp:374