MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
tmop-check-metric.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11//
12// ------------------------------------------------------
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 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 real_t 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 real_t i_form = metric->EvalW(T),
117 m_form = metric->EvalWMatrixForm(T);
118 const real_t diff = std::abs(i_form - m_form) / std::abs(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 real_t 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 real_t dx = 0.1;
169 real_t rate_dF_sum = 0.0, err_old = 1.0;
170 for (int k = 0; k < convergence_iter; k++)
171 {
172 real_t err_k = 0.0;
173 for (int i = 0; i < x_loc.Size(); i++)
174 {
175 x_loc(i) += dx;
176 err_k = std::max(err_k, std::abs(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 real_t 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 real_t 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 real_t rate_sum = 0.0;
208 dx = 0.1;
209 for (int k = 0; k < convergence_iter; k++)
210 {
211 real_t 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 = std::max(err_k, std::abs(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 real_t 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 = std::min(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}
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
real_t * GetData() const
Returns the matrix data array.
Definition densemat.hpp:115
virtual void Print(std::ostream &out=mfem::out, int width_=4) const
Prints matrix to stream out.
real_t Det() const
Definition densemat.cpp:535
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:220
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:287
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:3168
Abstract class for all finite elements.
Definition fe_base.hpp:239
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:31
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:260
Mesh data type.
Definition mesh.hpp:56
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:4253
void SetNodalGridFunction(GridFunction *nodes, bool make_owner=false)
Definition mesh.cpp:6200
virtual void SetNodalFESpace(FiniteElementSpace *nfes)
Definition mesh.cpp:6153
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:4243
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 Shape+Size+Orientation (VOS) metric (polyconvex).
Definition tmop.hpp:1114
2D barrier Shape+Orientation (OS) metric (polyconvex).
Definition tmop.hpp:1132
2D barrier Shape+Size (VS) metric (polyconvex).
Definition tmop.hpp:1150
A TMOP integrator class based on any given TMOP_QualityMetric and TargetConstructor.
Definition tmop.hpp:1738
2D non-barrier metric without a type.
Definition tmop.hpp:222
2D barrier Shape+Size (VS) metric (not polyconvex).
Definition tmop.hpp:341
2D barrier Shape+Size (VS) metric (not polyconvex).
Definition tmop.hpp:359
2D non-barrier Shape+Size+Orientation (VOS) metric (polyconvex).
Definition tmop.hpp:375
2D Shifted barrier form of shape metric (mu_2).
Definition tmop.hpp:394
2D barrier shape (S) metric (not polyconvex).
Definition tmop.hpp:471
2D barrier Shape+Orientation (OS) metric (polyconvex).
Definition tmop.hpp:557
2D compound barrier Shape+Size (VS) metric (balanced).
Definition tmop.hpp:572
2D compound barrier Shape+Size (VS) metric (balanced).
Definition tmop.hpp:593
2D barrier Shape+Size+Orientation (VOS) metric (polyconvex).
Definition tmop.hpp:614
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition tmop.hpp:668
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition tmop.hpp:687
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition tmop.hpp:708
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition tmop.hpp:729
3D Shape (S) metric, untangling version of 303.
Definition tmop.hpp:769
3D Size (V) metric.
Definition tmop.hpp:790
3D Size (V) metric.
Definition tmop.hpp:808
3D Size (V) metric.
Definition tmop.hpp:827
3D barrier Shape+Size (VS) metric, well-posed (invex).
Definition tmop.hpp:848
3D barrier Shape+Size (VS) metric, well-posed (invex).
Definition tmop.hpp:869
3D barrier Shape+Size (VS) metric, well-posed (invex).
Definition tmop.hpp:890
3D compound barrier Shape+Size (VS) metric (polyconvex, balanced).
Definition tmop.hpp:911
3D compound barrier Shape+Size (VS) metric (polyconvex).
Definition tmop.hpp:932
3D barrier Shape+Size (VS) metric, well-posed (polyconvex).
Definition tmop.hpp:953
3D barrier Shape+Size (VS) metric, well-posed (polyconvex).
Definition tmop.hpp:972
3D compound barrier Shape+Size (VS) metric (polyconvex, balanced).
Definition tmop.hpp:994
3D barrier Shape+Size (VS) metric, well-posed (polyconvex).
Definition tmop.hpp:1015
3D non-barrier Shape (S) metric.
Definition tmop.hpp:1056
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:47
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:1334
void SetNodes(const GridFunction &n)
Set the nodes to be used in the target-matrix construction.
Definition tmop.hpp:1413
Vector data type.
Definition vector.hpp:80
void Randomize(int seed=0)
Set random values in the vector.
Definition vector.cpp:816
void Print(std::ostream &out=mfem::out, int width=8) const
Prints vector to stream out.
Definition vector.cpp:755
real_t Max() const
Returns the maximal element of the vector.
Definition vector.cpp:922
int Size() const
Returns the size of the vector.
Definition vector.hpp:218
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
Definition vector.cpp:578
int dim
Definition ex24.cpp:53
int main()
real_t a
Definition lissajous.cpp:41
float real_t
Definition config.hpp:43