MFEM  v4.5.2
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 // Checks evaluation / 1st derivative / 2nd derivative for TMOP metrics. Serial.
13 // ./tmop-metric-magnitude -mid 2 -p 2.0
14 //
15 
16 #include "mfem.hpp"
17 #include "../common/mfem-common.hpp"
18 #include <iostream>
19 
20 using namespace mfem;
21 using namespace std;
22 
23 void Form2DJac(double perturb_v, double perturb_ar, double perturb_s,
24  DenseMatrix &J);
25 void Form3DJac(double perturb_v, double perturb_ar, double perturb_s,
26  DenseMatrix &J);
27 
28 int main(int argc, char *argv[])
29 {
30  int metric_id = 2;
31  double perturb_v = 1.0;
32  double perturb_ar = 1.0;
33  double perturb_s = 1.0;
34 
35  OptionsParser args(argc, argv);
36  args.AddOption(&metric_id, "-mid", "--metric-id", "Metric id");
37  args.AddOption(&perturb_v, "-pv", "--perturb-factor-volume",
38  "Volume perturbation factor w.r.t. the ideal element.");
39  args.AddOption(&perturb_ar, "-par", "--perturb-factor-aspect-ratio",
40  "Aspect ratio perturbation factor w.r.t. the ideal element.");
41  args.AddOption(&perturb_s, "-ps", "--perturb-factor-skew",
42  "Skew perturbation factor w.r.t. the ideal element.");
43  args.Parse();
44  if (!args.Good()) { args.PrintUsage(cout); return 1; }
45  args.PrintOptions(cout);
46 
47  // Setup metric.
48  TMOP_QualityMetric *metric = NULL;
49  switch (metric_id)
50  {
51  // T-metrics
52  case 1: metric = new TMOP_Metric_001; break;
53  case 2: metric = new TMOP_Metric_002; break;
54  case 7: metric = new TMOP_Metric_007; break;
55  case 9: metric = new TMOP_Metric_009; break;
56  case 14: metric = new TMOP_Metric_014; break;
57  case 50: metric = new TMOP_Metric_050; break;
58  case 55: metric = new TMOP_Metric_055; break;
59  case 56: metric = new TMOP_Metric_056; break;
60  case 58: metric = new TMOP_Metric_058; break;
61  case 77: metric = new TMOP_Metric_077; break;
62  case 85: metric = new TMOP_Metric_085; break;
63  case 98: metric = new TMOP_Metric_098; break;
64  // case 211: metric = new TMOP_Metric_211; break;
65  // case 252: metric = new TMOP_Metric_252(tauval); break;
66  case 301: metric = new TMOP_Metric_301; break;
67  case 302: metric = new TMOP_Metric_302; break;
68  case 303: metric = new TMOP_Metric_303; break;
69  case 304: metric = new TMOP_Metric_304; break;
70  // case 311: metric = new TMOP_Metric_311; break;
71  case 315: metric = new TMOP_Metric_315; break;
72  case 316: metric = new TMOP_Metric_316; break;
73  case 321: metric = new TMOP_Metric_321; break;
74  case 322: metric = new TMOP_Metric_322; break;
75  case 323: metric = new TMOP_Metric_323; break;
76  // case 352: metric = new TMOP_Metric_352(tauval); break;
77  case 360: metric = new TMOP_Metric_360; break;
78  // A-metrics
79  case 11: metric = new TMOP_AMetric_011; break;
80  case 36: metric = new TMOP_AMetric_036; break;
81  case 107: metric = new TMOP_AMetric_107a; break;
82  default: cout << "Unknown metric_id: " << metric_id << endl; return 3;
83  }
84 
85  const int dim = (metric_id < 300) ? 2 : 3;
86 
87  Mesh *mesh;
88  if (dim == 2)
89  {
91  }
92  else
93  {
94  mesh = new Mesh(Mesh::MakeCartesian3D(1, 1, 1, Element::HEXAHEDRON));
95  }
96  H1_FECollection fec(1, dim);
97  FiniteElementSpace fespace(mesh, &fec, dim);
98  mesh->SetNodalFESpace(&fespace);
99  GridFunction x(&fespace);
100  mesh->SetNodalGridFunction(&x);
101 
102  socketstream sock1;
103  common::VisualizeMesh(sock1, "localhost", 19916, *mesh, "ideal", 0, 0);
104 
105  DenseMatrix J;
106  (dim == 2) ? Form2DJac(perturb_v, perturb_ar, perturb_s, J)
107  /* */ : Form3DJac(perturb_v, perturb_ar, perturb_s, J);
108 
109  const int nodes_cnt = x.Size() / dim;
110  for (int i = 0; i < nodes_cnt; i++)
111  {
112  Vector X(dim);
113  for (int d = 0; d < dim; d++) { X(d) = x(i + d * nodes_cnt); }
114  Vector Jx(dim);
115  J.Mult(X, Jx);
116  for (int d = 0; d < dim; d++) { x(i + d * nodes_cnt) = Jx(d); }
117  }
118 
119  socketstream sock2;
120  common::VisualizeMesh(sock2, "localhost", 19916, *mesh, "perturbed", 400, 0);
121 
122  // Target is always identity -> Jpt = Jpr.
123  cout << "Magnitude of metric " << metric_id << ": " << metric->EvalW(J)
124  << "\n volume perturbation factor: " << perturb_v
125  << "\n aspect ratio pert factor: " << perturb_ar
126  << "\n skew perturbation factor: " << perturb_s << endl;
127 
128  delete metric;
129  delete mesh;
130  return 0;
131 }
132 
133 void Form2DJac(double perturb_v, double perturb_ar, double perturb_s,
134  DenseMatrix &J)
135 {
136  // Volume.
137  const double volume = 1.0 * perturb_v;
138 
139  // Aspect Ratio.
140  const double a_r = 1.0 * perturb_ar;
141  DenseMatrix M_ar(2); M_ar = 0.0;
142  M_ar(0, 0) = 1.0 / sqrt(a_r);
143  M_ar(1, 1) = sqrt(a_r);
144 
145  // Skew.
146  const double skew_angle = M_PI / 2.0 / perturb_s;
147  DenseMatrix M_skew(2);
148  M_skew(0, 0) = 1.0; M_skew(0, 1) = cos(skew_angle);
149  M_skew(1, 0) = 0.0; M_skew(1, 1) = sin(skew_angle);
150 
151  // Rotation.
152  const double rot_angle = 0.0; // not sure how to choose
153  DenseMatrix M_rot(2);
154  M_rot(0, 0) = cos(rot_angle); M_rot(0, 1) = -sin(rot_angle);
155  M_rot(1, 0) = sin(rot_angle); M_rot(1, 1) = cos(rot_angle);
156 
157  // Form J.
158  J.SetSize(2);
159  DenseMatrix TMP(2);
160  Mult(M_rot, M_skew, TMP);
161  Mult(TMP, M_ar, J);
162  J *= sqrt(volume / sin(skew_angle));
163 }
164 
165 void Form3DJac(double perturb_v, double perturb_ar, double perturb_s,
166  DenseMatrix &J)
167 {
168  MFEM_ABORT("The 3D case is still not complete.");
169 
170  // Volume.
171  const double volume = 1.0 * perturb_v;
172 
173  // Aspect Ratio - only in one direction, the others are uniform.
174  const double ar_1 = 1.0 * perturb_ar,
175  ar_2 = 1.0 * perturb_ar;
176 
177  // Skew - only in one direction, the others are pi/2.
178  const double skew_angle_12 = M_PI / 2.0 / perturb_s,
179  skew_angle_13 = M_PI / 2.0 / perturb_s,
180  skew_angle_23 = M_PI / 2.0 / perturb_s;
181  const double sin3 = sin(skew_angle_12)*sin(skew_angle_13)*sin(skew_angle_23);
182 
183  // Rotation - not done yet.
184 
185  J.SetSize(3);
186  //
187  J(0, 0) = ar_1;
188  J(0, 1) = ar_2 * cos(skew_angle_12);
189  J(0, 2) = cos(skew_angle_13) / (ar_1 * ar_2) *
190  sqrt(sin3 / volume);
191  //
192  J(1, 0) = 0.0;
193  J(1, 1) = ar_2 * sin(skew_angle_12);
194  J(1, 2) = sin(skew_angle_13) * cos(skew_angle_23) / (ar_1 * ar_2) *
195  sqrt(sin3 / volume);
196  //
197  J(2, 0) = 0.0;
198  J(2, 1) = 0.0;
199  J(2, 2) = sin(skew_angle_13) * sin(skew_angle_23) / (ar_1 * ar_2) *
200  sqrt(sin3/ volume);
201  //
202  J *= sqrt(volume / sin3);
203 }
204 
3D non-barrier Shape (S) metric.
Definition: tmop.hpp:956
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:771
void PrintOptions(std::ostream &out) const
Print the options.
Definition: optparser.cpp:324
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition: tmop.hpp:652
void PrintUsage(std::ostream &out) const
Print the usage message.
Definition: optparser.cpp:454
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:3736
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:199
Data type dense matrix using column-major storage.
Definition: densemat.hpp:23
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition: tmop.hpp:631
3D non-barrier metric without a type.
Definition: tmop.hpp:734
3D barrier Shape+Size (VS) metric, well-posed (invex).
Definition: tmop.hpp:813
bool Good() const
Return true if the command line options were parsed successfully.
Definition: optparser.hpp:150
STL namespace.
2D barrier Shape+Size (VS) metric (not polyconvex).
Definition: tmop.hpp:338
3D barrier Shape+Size (VS) metric, well-posed (invex).
Definition: tmop.hpp:792
void Form3DJac(double perturb_v, double perturb_ar, double perturb_s, DenseMatrix &J)
2D barrier shape (S) metric (not polyconvex).
Definition: tmop.hpp:460
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition: tmop.hpp:673
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 barrier metric without a type.
Definition: tmop.hpp:752
2D barrier Shape+Size+Orientation (VOS) metric (polyconvex).
Definition: tmop.hpp:558
virtual void SetNodalFESpace(FiniteElementSpace *nfes)
Definition: mesh.cpp:5298
void Mult(const double *x, double *y) const
Matrix vector multiplication.
Definition: densemat.cpp:173
2D barrier Shape+Orientation (OS) metric (polyconvex).
Definition: tmop.hpp:1032
int main(int argc, char *argv[])
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:96
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:3726
void Form2DJac(double perturb_v, double perturb_ar, double perturb_s, DenseMatrix &J)
2D barrier Shape+Size (VS) metric (not polyconvex).
Definition: tmop.hpp:356
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:1014
int dim
Definition: ex24.cpp:53
Vector data type.
Definition: vector.hpp:60
Arbitrary order H1-conforming (continuous) finite elements.
Definition: fe_coll.hpp:252
void SetNodalGridFunction(GridFunction *nodes, bool make_owner=false)
Definition: mesh.cpp:5345
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:543
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition: tmop.hpp:612
2D non-barrier metric without a type.
Definition: tmop.hpp:219
2D non-barrier Shape+Size+Orientation (VOS) metric (polyconvex).
Definition: tmop.hpp:372