MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
tmop-check-metric.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, 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 tmop-check-metric
20//
21// Sample runs: tmop-check-metric -mid 360
22
23#include "mfem.hpp"
24#include <iostream>
25
26using namespace mfem;
27using namespace std;
28
29int main(int argc, char *argv[])
30{
31 int metric_id = 2;
32 bool a_metric_version = false;
33 int convergence_iter = 10;
34 bool verbose = false;
35
36 // Choose metric.
37 OptionsParser args(argc, argv);
38 args.AddOption(&metric_id, "-mid", "--metric-id", "Metric id");
39 args.AddOption(&a_metric_version, "-A", "-Ametric", "-no-A", "--no-Ametric",
40 "Use the A-version of the metric, if available.");
41 args.AddOption(&verbose, "-v", "-verbose", "-no-v", "--no-verbose",
42 "Enable extra screen output.");
43 args.AddOption(&convergence_iter, "-i", "--iterations",
44 "Number of iterations to check convergence of derivatives.");
45
46 args.Parse();
47 if (!args.Good())
48 {
49 args.PrintUsage(cout);
50 return 1;
51 }
52 args.PrintOptions(cout);
53
54 // Setup metric.
55 real_t tauval = -0.1;
56 TMOP_QualityMetric *metric = NULL;
57 switch (metric_id)
58 {
59 // T-metrics
60 case 1: metric = new TMOP_Metric_001; break;
61 case 2: metric = new TMOP_Metric_002; break;
62 case 7: metric = new TMOP_Metric_007; break;
63 case 9: metric = new TMOP_Metric_009; break;
64 case 14:
65 if (a_metric_version) { metric = new TMOP_Metric_014; }
66 else { metric = new TMOP_AMetric_014; } break;
67 case 22: metric = new TMOP_Metric_022(tauval); break;
68 case 50:
69 if (a_metric_version) { metric = new TMOP_Metric_050; }
70 else { metric = new TMOP_AMetric_050; } break;
71 case 55: metric = new TMOP_Metric_055; break;
72 case 56: metric = new TMOP_Metric_056; break;
73 case 58: metric = new TMOP_Metric_058; break;
74 case 77: metric = new TMOP_Metric_077; break;
75 case 80: metric = new TMOP_Metric_080(0.5); break;
76 case 85: metric = new TMOP_Metric_085; break;
77 case 90: metric = new TMOP_Metric_090; break;
78 case 94: metric = new TMOP_Metric_094; break;
79 case 98: metric = new TMOP_Metric_098; break;
80 // case 211: metric = new TMOP_Metric_211; break;
81 // case 252: metric = new TMOP_Metric_252(tauval); break;
82 case 301: metric = new TMOP_Metric_301; break;
83 case 302: metric = new TMOP_Metric_302; break;
84 case 303: metric = new TMOP_Metric_303; break;
85 case 304: metric = new TMOP_Metric_304; break;
86 // case 311: metric = new TMOP_Metric_311; break;
87 case 313: metric = new TMOP_Metric_313(tauval); break;
88 case 315: metric = new TMOP_Metric_315; break;
89 case 316: metric = new TMOP_Metric_316; break;
90 case 318: metric = new TMOP_Metric_318; break;
91 case 321: metric = new TMOP_Metric_321; break;
92 case 322: metric = new TMOP_Metric_322; break;
93 case 323: metric = new TMOP_Metric_323; break;
94 case 328: metric = new TMOP_Metric_328; break;
95 case 332: metric = new TMOP_Metric_332(0.5); break;
96 case 333: metric = new TMOP_Metric_333(0.5); break;
97 case 334: metric = new TMOP_Metric_334(0.5); break;
98 case 338: metric = new TMOP_Metric_338; break;
99 case 342: metric = new TMOP_Metric_342; break;
100 case 347: metric = new TMOP_Metric_347(0.5); break;
101 // case 352: metric = new TMOP_Metric_352(tauval); break;
102 case 360: metric = new TMOP_Metric_360; break;
103 // A-metrics
104 case 11: metric = new TMOP_AMetric_011; break;
105 case 36: metric = new TMOP_AMetric_036; break;
106 case 51: metric = new TMOP_AMetric_051; break;
107 case 107: metric = new TMOP_AMetric_107; break;
108 case 126: metric = new TMOP_AMetric_126(0.9); break;
109 default: cout << "Unknown metric_id: " << metric_id << endl; return 3;
110 }
111
112 const int dim = (metric_id < 300) ? 2 : 3;
113 Mesh *mesh;
114 if (dim == 2)
115 {
117 }
118 else
119 {
120 mesh = new Mesh(Mesh::MakeCartesian3D(1, 1, 1, Element::HEXAHEDRON));
121 }
122 H1_FECollection fec(2, dim);
123 FiniteElementSpace fespace(mesh, &fec, dim);
124
125 DenseMatrix T(dim);
126 Vector T_vec(T.GetData(), dim * dim);
127
128 // Test evaluation.
129 int valid_cnt = 0, bad_cnt = 0;
130 for (int i = 0; i < 1000; i++)
131 {
132 T_vec.Randomize(i);
133 // Increase probability of det(T) > 0.
134 T(0, 0) += T_vec.Max();
135 if (T.Det() <= 0.0) { continue; }
136
137 auto W = Geometries.GetGeomToPerfGeomJac(fespace.GetFE(0)->GetGeomType());
138 metric->SetTargetJacobian(W);
139
140 const real_t i_form = metric->EvalW(T),
141 m_form = metric->EvalWMatrixForm(T);
142 const real_t diff = std::abs(i_form - m_form) / std::abs(m_form);
143 if (diff > 1e-8)
144 {
145 bad_cnt++;
146 if (verbose)
147 {
148 cout << "Wrong metric computation: "
149 << i_form << " (invariant), " << m_form << " (matrix form) "
150 << diff << " (normalized difference) " << endl;
151 }
152 }
153 valid_cnt++;
154 }
155 cout << "--- EvalW: " << bad_cnt << " errors out of "
156 << valid_cnt << " comparisons with det(T) > 0.\n";
157
158 NonlinearForm a(&fespace);
159 mesh->SetNodalFESpace(&fespace);
160 GridFunction x(&fespace);
161 mesh->SetNodalGridFunction(&x);
162 x(0) = 0.25;
163
165 tc.SetNodes(x);
166 auto integ = new TMOP_Integrator(metric, &tc, NULL);
167 a.AddDomainIntegrator(integ);
168
170 const FiniteElement &fe = *fespace.GetFE(0);
171 Array<int> vdofs;
172 fespace.GetElementVDofs(0, vdofs);
173 Vector x_loc(x.Size());
174 x.GetSubVector(vdofs, x_loc);
175
176 // Test 1st derivative (assuming EvalW is correct). Should be 2nd order.
177 Vector dF_0;
178 const real_t F_0 = integ->GetElementEnergy(fe, Tr, x_loc);
179 integ->AssembleElementVector(fe, Tr, x_loc, dF_0);
180 if (verbose) { cout << "***\ndF = \n"; dF_0.Print(); cout << "***\n"; }
181 real_t dx = 0.1;
182 real_t rate_dF_sum = 0.0, err_old = 1.0;
183 for (int k = 0; k < convergence_iter; k++)
184 {
185 real_t err_k = 0.0;
186 for (int i = 0; i < x_loc.Size(); i++)
187 {
188 x_loc(i) += dx;
189 err_k = std::max(err_k, std::abs(F_0 + dF_0(i) * dx -
190 integ->GetElementEnergy(fe, Tr, x_loc)));
191 x_loc(i) -= dx;
192 }
193 dx *= 0.5;
194
195 if (verbose && k == 0)
196 {
197 std::cout << "dF error " << k << ": " << err_k << endl;
198 }
199 if (k > 0)
200 {
201 real_t r = log2(err_old / err_k);
202 rate_dF_sum += r;
203 if (verbose)
204 {
205 std::cout << "dF error " << k << ": " << err_k << " " << r << endl;
206 }
207 }
208 err_old = err_k;
209 }
210 std::cout << "--- EvalP: avg rate of convergence (should be 2): "
211 << rate_dF_sum / (convergence_iter - 1) << endl;
212
213 // Test 2nd derivative (assuming EvalP is correct).
214 real_t min_avg_rate = 7.0;
215 DenseMatrix ddF_0;
216 integ->AssembleElementGrad(fe, Tr, x_loc, ddF_0);
217 if (verbose) { cout << "***\nddF = \n"; ddF_0.Print(); cout << "***\n"; }
218 for (int i = 0; i < x_loc.Size(); i++)
219 {
220 real_t rate_sum = 0.0;
221 dx = 0.1;
222 for (int k = 0; k < convergence_iter; k++)
223 {
224 real_t err_k = 0.0;
225
226 for (int j = 0; j < x_loc.Size(); j++)
227 {
228 x_loc(j) += dx;
229 Vector dF_dx;
230 integ->AssembleElementVector(fe, Tr, x_loc, dF_dx);
231 err_k = std::max(err_k, std::abs(dF_0(i) + ddF_0(i, j) * dx - dF_dx(i)));
232 x_loc(j) -= dx;
233 }
234 dx *= 0.5;
235
236 if (verbose && k == 0)
237 {
238 cout << "ddF error for dof " << i << ", " << k << ": "
239 << err_k << endl;
240 }
241 if (k > 0)
242 {
243 real_t r = log2(err_old / err_k);
244 // Error is zero (2nd derivative is exact) -> put rate 2 (optimal).
245 if (err_k < 1e-14) { r = 2.0; }
246 rate_sum += r;
247 if (verbose)
248 {
249 cout << "ddF error for dof " << i << ", " << k << ": " << err_k
250 << " " << r << endl;
251 }
252
253 }
254 err_old = err_k;
255 }
256 min_avg_rate = std::min(min_avg_rate, rate_sum / (convergence_iter - 1));
257 }
258 std::cout << "--- AssembleH: avg rate of convergence (should be 2): "
259 << min_avg_rate << endl;
260
261 delete metric;
262 delete mesh;
263 return 0;
264}
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
real_t * GetData() const
Returns the matrix data array.
Definition densemat.hpp:118
void Print(std::ostream &out=mfem::out, int width_=4) const override
Prints matrix to stream out.
real_t Det() const
Definition densemat.cpp:516
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:244
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for the i'th element. The returned indices are offsets into an ...
Definition fespace.cpp:332
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
Definition fespace.cpp:3835
Abstract class for all finite elements.
Definition fe_base.hpp:244
Geometry::Type GetGeomType() const
Returns the Geometry::Type of the reference element.
Definition fe_base.hpp:331
const DenseMatrix & GetGeomToPerfGeomJac(int GeomType) const
Definition geom.hpp:102
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:31
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:275
Mesh data type.
Definition mesh.hpp:64
void GetElementTransformation(int i, IsoparametricTransformation *ElTr) const
Builds the transformation defining the i-th element in ElTr. ElTr must be allocated in advance and wi...
Definition mesh.cpp:357
static Mesh MakeCartesian3D(int nx, int ny, int nz, Element::Type type, real_t sx=1.0, real_t sy=1.0, real_t sz=1.0, bool sfc_ordering=true)
Creates a mesh for the parallelepiped [0,sx]x[0,sy]x[0,sz], divided into nx*ny*nz hexahedra if type =...
Definition mesh.cpp:4481
void SetNodalGridFunction(GridFunction *nodes, bool make_owner=false)
Definition mesh.cpp:6473
virtual void SetNodalFESpace(FiniteElementSpace *nfes)
Definition mesh.cpp:6426
static Mesh MakeCartesian2D(int nx, int ny, Element::Type type, bool generate_edges=false, real_t sx=1.0, real_t sy=1.0, bool sfc_ordering=true)
Creates mesh for the rectangle [0,sx]x[0,sy], divided into nx*ny quadrilaterals if type = QUADRILATER...
Definition mesh.cpp:4471
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
void PrintUsage(std::ostream &out) const
Print the usage message.
void PrintOptions(std::ostream &out) const
Print the options.
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 'var' to receive the value. Enable/disable tags are used to set the bool...
Definition optparser.hpp:82
bool Good() const
Return true if the command line options were parsed successfully.
2D barrier Size (V) metric (polyconvex).
Definition tmop.hpp:1149
2D barrier Shape+Size+Orientation (VOS) metric (polyconvex).
Definition tmop.hpp:1169
2D barrier Skew (Q) metric.
Definition tmop.hpp:1189
2D barrier Size+Skew (VQ) metric.
Definition tmop.hpp:1209
2D barrier Shape+Orientation (OS) metric (polyconvex).
Definition tmop.hpp:1231
2D barrier Shape+Size (VS) metric (polyconvex).
Definition tmop.hpp:1251
A TMOP integrator class based on any given TMOP_QualityMetric and TargetConstructor.
Definition tmop.hpp:1885
2D non-barrier metric without a type.
Definition tmop.hpp:249
2D barrier Shape+Size (VS) metric (not polyconvex).
Definition tmop.hpp:374
2D barrier Shape+Size (VS) metric (not polyconvex).
Definition tmop.hpp:392
2D non-barrier Shape+Size+Orientation (VOS) metric (polyconvex).
Definition tmop.hpp:408
2D Shifted barrier form of shape metric (mu_2).
Definition tmop.hpp:427
2D barrier shape (S) metric (not polyconvex).
Definition tmop.hpp:504
2D barrier Shape+Orientation (OS) metric (polyconvex).
Definition tmop.hpp:590
2D compound barrier Shape+Size (VS) metric (balanced).
Definition tmop.hpp:605
2D compound barrier Shape+Size (VS) metric (balanced).
Definition tmop.hpp:626
2D barrier Shape+Size+Orientation (VOS) metric (polyconvex).
Definition tmop.hpp:647
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition tmop.hpp:701
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition tmop.hpp:720
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition tmop.hpp:741
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition tmop.hpp:762
3D Shape (S) metric, untangling version of 303.
Definition tmop.hpp:802
3D Size (V) metric.
Definition tmop.hpp:823
3D Size (V) metric.
Definition tmop.hpp:841
3D Size (V) metric.
Definition tmop.hpp:860
3D barrier Shape+Size (VS) metric, well-posed (invex).
Definition tmop.hpp:881
3D barrier Shape+Size (VS) metric, well-posed (invex).
Definition tmop.hpp:902
3D barrier Shape+Size (VS) metric, well-posed (invex).
Definition tmop.hpp:923
3D compound barrier Shape+Size (VS) metric (polyconvex, balanced).
Definition tmop.hpp:944
3D compound barrier Shape+Size (VS) metric (polyconvex).
Definition tmop.hpp:965
3D barrier Shape+Size (VS) metric, well-posed (polyconvex).
Definition tmop.hpp:986
3D barrier Shape+Size (VS) metric, well-posed (polyconvex).
Definition tmop.hpp:1005
3D compound barrier Shape+Size (VS) metric (polyconvex, balanced).
Definition tmop.hpp:1027
3D barrier Shape+Size+Orientation (VOS) metric (polyconvex).
Definition tmop.hpp:1048
3D barrier Shape+Size (VS) metric, well-posed (polyconvex).
Definition tmop.hpp:1066
3D non-barrier Shape (S) metric.
Definition tmop.hpp:1107
Abstract class for local mesh quality metrics in the target-matrix optimization paradigm (TMOP) by P....
Definition tmop.hpp:24
virtual real_t EvalWMatrixForm(const DenseMatrix &Jpt) const
Evaluates the metric in matrix form (opposed to invariant form). Used for validating the invariant ev...
Definition tmop.hpp:53
virtual void SetTargetJacobian(const DenseMatrix &Jtr_)
Specify the reference-element -> target-element Jacobian matrix for the point of interest.
Definition tmop.hpp:49
virtual real_t EvalW(const DenseMatrix &Jpt) const =0
Evaluate the strain energy density function, W = W(Jpt), by using the 2D or 3D matrix invariants,...
Base class representing target-matrix construction algorithms for mesh optimization via the target-ma...
Definition tmop.hpp:1481
void SetNodes(const GridFunction &n)
Set the nodes to be used in the target-matrix construction.
Definition tmop.hpp:1560
Vector data type.
Definition vector.hpp:82
void Randomize(int seed=0)
Set random values in the vector.
Definition vector.cpp:915
void Print(std::ostream &out=mfem::out, int width=8) const
Prints vector to stream out.
Definition vector.cpp:830
real_t Max() const
Returns the maximal element of the vector.
Definition vector.cpp:1164
int Size() const
Returns the size of the vector.
Definition vector.hpp:226
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
Definition vector.cpp:653
int dim
Definition ex24.cpp:53
int main()
real_t a
Definition lissajous.cpp:41
Geometry Geometries
Definition fe.cpp:49
float real_t
Definition config.hpp:43