MFEM  v4.6.0
Finite element discretization library
tmop-metric-magnitude.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 // Metric Magnitude Miniapp: track changes in TMOP metrics
14 // -------------------------------------------------------
15 //
16 // This miniapp can be used to track how TMPOP metrics change under geometric
17 // perturbations.
18 //
19 // Compile with: make tmop-metric-magnitude
20 //
21 // Sample runs: tmop-metric-magnitude -mid 7 -pv 2.0 -par 0.5 -ps 4.0
22 // tmop-metric-magnitude -mid 321 -pv 2.0 -par 0.5 -ps 4.0
23 
24 #include "mfem.hpp"
25 #include "../common/mfem-common.hpp"
26 #include <iostream>
27 
28 using namespace mfem;
29 using namespace std;
30 
31 void Form2DJac(double perturb_v, double perturb_ar, double perturb_s,
32  DenseMatrix &J);
33 void Form3DJac(double perturb_v, double perturb_ar, double perturb_s,
34  DenseMatrix &J);
35 
36 int main(int argc, char *argv[])
37 {
38  int metric_id = 2;
39  double perturb_v = 1.0;
40  double perturb_ar = 1.0;
41  double perturb_s = 1.0;
42 
43  OptionsParser args(argc, argv);
44  args.AddOption(&metric_id, "-mid", "--metric-id", "Metric id");
45  args.AddOption(&perturb_v, "-pv", "--perturb-factor-volume",
46  "Volume perturbation factor w.r.t. the ideal element.");
47  args.AddOption(&perturb_ar, "-par", "--perturb-factor-aspect-ratio",
48  "Aspect ratio perturbation factor w.r.t. the ideal element.");
49  args.AddOption(&perturb_s, "-ps", "--perturb-factor-skew",
50  "Skew perturbation factor w.r.t. the ideal element.");
51  args.Parse();
52  if (!args.Good()) { args.PrintUsage(cout); return 1; }
53  args.PrintOptions(cout);
54 
55  MFEM_VERIFY(perturb_v > 0.0 && perturb_ar > 0.0 && perturb_s >= 1.0,
56  "Invalid input");
57 
58  // Setup metric.
59  TMOP_QualityMetric *metric = NULL;
60  switch (metric_id)
61  {
62  // T-metrics
63  case 1: metric = new TMOP_Metric_001; break;
64  case 2: metric = new TMOP_Metric_002; break;
65  case 7: metric = new TMOP_Metric_007; break;
66  case 9: metric = new TMOP_Metric_009; break;
67  case 14: metric = new TMOP_Metric_014; break;
68  case 50: metric = new TMOP_Metric_050; break;
69  case 55: metric = new TMOP_Metric_055; break;
70  case 56: metric = new TMOP_Metric_056; break;
71  case 58: metric = new TMOP_Metric_058; break;
72  case 77: metric = new TMOP_Metric_077; break;
73  case 85: metric = new TMOP_Metric_085; break;
74  case 98: metric = new TMOP_Metric_098; break;
75  // case 211: metric = new TMOP_Metric_211; break;
76  // case 252: metric = new TMOP_Metric_252(tauval); break;
77  case 301: metric = new TMOP_Metric_301; break;
78  case 302: metric = new TMOP_Metric_302; break;
79  case 303: metric = new TMOP_Metric_303; break;
80  case 304: metric = new TMOP_Metric_304; break;
81  // case 311: metric = new TMOP_Metric_311; break;
82  case 315: metric = new TMOP_Metric_315; break;
83  case 316: metric = new TMOP_Metric_316; 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 352: metric = new TMOP_Metric_352(tauval); break;
88  case 360: metric = new TMOP_Metric_360; break;
89  // A-metrics
90  case 11: metric = new TMOP_AMetric_011; break;
91  case 36: metric = new TMOP_AMetric_036; break;
92  case 107: metric = new TMOP_AMetric_107a; break;
93  default: cout << "Unknown metric_id: " << metric_id << endl; return 3;
94  }
95 
96  const int dim = (metric_id < 300) ? 2 : 3;
97 
98  Mesh *mesh;
99  if (dim == 2)
100  {
102  }
103  else
104  {
105  mesh = new Mesh(Mesh::MakeCartesian3D(1, 1, 1, Element::HEXAHEDRON));
106  }
107  H1_FECollection fec(1, dim);
108  FiniteElementSpace fespace(mesh, &fec, dim);
109  mesh->SetNodalFESpace(&fespace);
110  GridFunction x(&fespace);
111  mesh->SetNodalGridFunction(&x);
112 
113  socketstream sock1;
114  common::VisualizeMesh(sock1, "localhost", 19916, *mesh, "ideal", 0, 0);
115 
116  DenseMatrix J;
117  (dim == 2) ? Form2DJac(perturb_v, perturb_ar, perturb_s, J)
118  /* */ : Form3DJac(perturb_v, perturb_ar, perturb_s, J);
119 
120  const int nodes_cnt = x.Size() / dim;
121  for (int i = 0; i < nodes_cnt; i++)
122  {
123  Vector X(dim);
124  for (int d = 0; d < dim; d++) { X(d) = x(i + d * nodes_cnt); }
125  Vector Jx(dim);
126  J.Mult(X, Jx);
127  for (int d = 0; d < dim; d++) { x(i + d * nodes_cnt) = Jx(d); }
128  }
129 
130  socketstream sock2;
131  common::VisualizeMesh(sock2, "localhost", 19916, *mesh, "perturbed", 400, 0);
132 
133  // Target is always identity -> Jpt = Jpr.
134  cout << "Magnitude of metric " << metric_id << ": " << metric->EvalW(J)
135  << "\n volume perturbation factor: " << perturb_v
136  << "\n aspect ratio pert factor: " << perturb_ar
137  << "\n skew perturbation factor: " << perturb_s << endl;
138 
139  delete metric;
140  delete mesh;
141  return 0;
142 }
143 
144 void Form2DJac(double perturb_v, double perturb_ar, double perturb_s,
145  DenseMatrix &J)
146 {
147  // Volume.
148  const double volume = 1.0 * perturb_v;
149 
150  // Aspect Ratio.
151  const double a_r = 1.0 * perturb_ar;
152  DenseMatrix M_ar(2); M_ar = 0.0;
153  M_ar(0, 0) = 1.0 / sqrt(a_r);
154  M_ar(1, 1) = sqrt(a_r);
155 
156  // Skew.
157  const double skew_angle = M_PI / 2.0 / perturb_s;
158  DenseMatrix M_skew(2);
159  M_skew(0, 0) = 1.0; M_skew(0, 1) = cos(skew_angle);
160  M_skew(1, 0) = 0.0; M_skew(1, 1) = sin(skew_angle);
161 
162  // Rotation.
163  const double rot_angle = 0.0; // not sure how to choose
164  DenseMatrix M_rot(2);
165  M_rot(0, 0) = cos(rot_angle); M_rot(0, 1) = -sin(rot_angle);
166  M_rot(1, 0) = sin(rot_angle); M_rot(1, 1) = cos(rot_angle);
167 
168  // Form J.
169  J.SetSize(2);
170  DenseMatrix TMP(2);
171  Mult(M_rot, M_skew, TMP);
172  Mult(TMP, M_ar, J);
173  J *= sqrt(volume / sin(skew_angle));
174 }
175 
176 void Form3DJac(double perturb_v, double perturb_ar, double perturb_s,
177  DenseMatrix &J)
178 {
179  // Volume.
180  const double volume = 1.0 * perturb_v;
181 
182  // Aspect Ratio - only in one direction, the others are uniform.
183  const double ar_1 = 1.0 * perturb_ar,
184  ar_2 = 1.0,
185  ar_3 = 1.0;
186 
187  // Skew - only in one direction, the others are pi/2.
188  const double skew_angle_12 = M_PI / 2.0 / perturb_s,
189  skew_angle_13 = M_PI / 2.0,
190  skew_angle_23 = M_PI / 2.0;
191 
192  // Rotation - not done yet.
193 
194  J.SetSize(3);
195  //
196  J(0, 0) = pow(ar_1, 1.0/3.0);
197  J(0, 1) = pow(ar_2, 1.0/3.0) * cos(skew_angle_12);
198  J(0, 2) = pow(ar_3, 1.0/3.0) * cos(skew_angle_13);
199  //
200  J(1, 0) = 0.0;
201  J(1, 1) = pow(ar_2, 1.0/3.0) * sin(skew_angle_12);
202  J(1, 2) = pow(ar_3, 1.0/3.0) * sin(skew_angle_13) * cos(skew_angle_23);
203  //
204  J(2, 0) = 0.0;
205  J(2, 1) = 0.0;
206  J(2, 2) = pow(ar_3, 1.0/3.0) * sin(skew_angle_13) * sin(skew_angle_23);
207  //
208 
209  double sin3 = sin(skew_angle_12)*sin(skew_angle_13)*sin(skew_angle_23),
210  ar3 = pow(ar_1, 1.0/3.0) * pow(ar_2, 1.0/3.0) * pow(ar_3, 1.0/3.0);
211  J *= pow(volume / (sin3 * ar3), 1.0/3.0);
212 }
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
void PrintOptions(std::ostream &out) const
Print the options.
Definition: optparser.cpp:331
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 Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
Definition: table.cpp:475
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 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.
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
void Form3DJac(double perturb_v, double perturb_ar, double perturb_s, DenseMatrix &J)
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
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
2D barrier Shape+Size+Orientation (VOS) metric (polyconvex).
Definition: tmop.hpp:609
virtual void SetNodalFESpace(FiniteElementSpace *nfes)
Definition: mesh.cpp:5577
void Mult(const double *x, double *y) const
Matrix vector multiplication.
Definition: densemat.cpp:172
2D barrier Shape+Orientation (OS) metric (polyconvex).
Definition: tmop.hpp:1127
int main(int argc, char *argv[])
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
void Form2DJac(double perturb_v, double perturb_ar, double perturb_s, DenseMatrix &J)
2D barrier Shape+Size (VS) metric (not polyconvex).
Definition: tmop.hpp:358
void VisualizeMesh(socketstream &sock, const char *vishost, int visport, Mesh &mesh, const char *title, int x, int y, int w, int h, const char *keys)
Definition: fem_extras.cpp:59
2D barrier Shape+Size+Orientation (VOS) metric (polyconvex).
Definition: tmop.hpp:1109
int dim
Definition: ex24.cpp:53
Vector data type.
Definition: vector.hpp:58
Arbitrary order H1-conforming (continuous) finite elements.
Definition: fe_coll.hpp:259
void SetNodalGridFunction(GridFunction *nodes, bool make_owner=false)
Definition: mesh.cpp:5624
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
Definition: densemat.hpp:105
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
2D non-barrier Shape+Size+Orientation (VOS) metric (polyconvex).
Definition: tmop.hpp:374