MFEM  v4.4.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
ex30.cpp
Go to the documentation of this file.
1 // MFEM Example 30
2 //
3 // Compile with: make ex30
4 //
5 // Sample runs: ex30 -m ../data/square-disc.mesh -o 1
6 // ex30 -m ../data/square-disc.mesh -o 2
7 // ex30 -m ../data/square-disc.mesh -o 2 -me 1e+4
8 // ex30 -m ../data/square-disc-nurbs.mesh -o 2
9 // ex30 -m ../data/star.mesh -o 2 -eo 4
10 // ex30 -m ../data/fichera.mesh -o 2 -me 1e+5 -e 5e-2
11 // ex30 -m ../data/disc-nurbs.mesh -o 2
12 // ex30 -m ../data/ball-nurbs.mesh -o 2 -eo 3 -e 5e-2 -me 1e+5
13 // ex30 -m ../data/star-surf.mesh -o 2
14 // ex30 -m ../data/square-disc-surf.mesh -o 2
15 // ex30 -m ../data/amr-quad.mesh -l 2
16 //
17 // Description: This is an example of adaptive mesh refinement preprocessing
18 // which lowers the data oscillation [1] to a user-defined
19 // relative threshold. There is no PDE being solved.
20 //
21 // MFEM's capability to work with both conforming and
22 // nonconforming meshes is demonstrated in example 6. In some
23 // problems, the material data or loading data is not sufficiently
24 // resolved on the initial mesh. This missing fine scale data
25 // reduces the accuracy of the solution as well as the accuracy of
26 // some local error estimators. By preprocessing the mesh before
27 // solving the PDE, many issues can be avoided.
28 //
29 // [1] Morin, P., Nochetto, R. H., & Siebert, K. G. (2000). Data
30 // oscillation and convergence of adaptive FEM. SIAM Journal
31 // on Numerical Analysis, 38(2), 466-488.
32 //
33 // [2] Mitchell, W. F. (2013). A collection of 2D elliptic
34 // problems for testing adaptive grid refinement algorithms.
35 // Applied mathematics and computation, 220, 350-364.
36 
37 #include "mfem.hpp"
38 #include <fstream>
39 #include <iostream>
40 
41 using namespace std;
42 using namespace mfem;
43 
44 // Piecewise-affine function which is sometimes mesh-conforming
45 double affine_function(const Vector &p)
46 {
47  double x = p(0), y = p(1);
48  if (x < 0.0)
49  {
50  return 1.0 + x + y;
51  }
52  else
53  {
54  return 1.0;
55  }
56 }
57 
58 // Piecewise-constant function which is never mesh-conforming
59 double jump_function(const Vector &p)
60 {
61  if (p.Normlp(2.0) > 0.4 && p.Normlp(2.0) < 0.6)
62  {
63  return 1.0;
64  }
65  else
66  {
67  return 5.0;
68  }
69 }
70 
71 // Singular function derived from the Laplacian of the "steep wavefront" problem
72 // in [2].
73 double singular_function(const Vector &p)
74 {
75  double x = p(0), y = p(1);
76  double alpha = 1000.0;
77  double xc = 0.75, yc = 0.5;
78  double r0 = 0.7;
79  double r = sqrt(pow(x - xc,2.0) + pow(y - yc,2.0));
80  double num = - ( alpha - pow(alpha,3) * (pow(r,2) - pow(r0,2)) );
81  double denom = pow(r * ( pow(alpha,2) * pow(r0,2) + pow(alpha,2) * pow(r,2) \
82  - 2 * pow(alpha,2) * r0 * r + 1.0 ),2);
83  denom = max(denom,1e-8);
84  return num / denom;
85 }
86 
87 int main(int argc, char *argv[])
88 {
89  // 1. Parse command-line options.
90  const char *mesh_file = "../data/star.mesh";
91  int order = 1;
92  int nc_limit = 1;
93  int max_elems = 1e5;
94  double double_max_elems = double(max_elems);
95  bool visualization = true;
96  double osc_threshold = 1e-3;
97  int enriched_order = 5;
98 
99  OptionsParser args(argc, argv);
100  args.AddOption(&mesh_file, "-m", "--mesh",
101  "Mesh file to use.");
102  args.AddOption(&order, "-o", "--order",
103  "Finite element order (polynomial degree).");
104  args.AddOption(&nc_limit, "-l", "--nc-limit",
105  "Maximum level of hanging nodes.");
106  args.AddOption(&double_max_elems, "-me", "--max-elems",
107  "Stop after reaching this many elements.");
108  args.AddOption(&osc_threshold, "-e", "--error",
109  "relative data oscillation threshold.");
110  args.AddOption(&enriched_order, "-eo", "--enriched_order",
111  "Enriched quadrature order.");
112  args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
113  "--no-visualization",
114  "Enable or disable GLVis visualization.");
115  args.Parse();
116  if (!args.Good())
117  {
118  args.PrintUsage(cout);
119  return 1;
120  }
121  args.PrintOptions(cout);
122 
123  max_elems = int(double_max_elems);
124  Mesh mesh(mesh_file, 1, 1);
125 
126  // 2. Since a NURBS mesh can currently only be refined uniformly, we need to
127  // convert it to a piecewise-polynomial curved mesh. First we refine the
128  // NURBS mesh a bit and then project the curvature to quadratic Nodes.
129  if (mesh.NURBSext)
130  {
131  for (int i = 0; i < 2; i++)
132  {
133  mesh.UniformRefinement();
134  }
135  mesh.SetCurvature(2);
136  }
137 
138  // 3. Define functions and refiner.
139  FunctionCoefficient affine_coeff(affine_function);
141  FunctionCoefficient singular_coeff(singular_function);
142  CoefficientRefiner coeffrefiner(affine_coeff, order);
143 
144  // 4. Connect to GLVis.
145  char vishost[] = "localhost";
146  int visport = 19916;
147  socketstream sol_sock;
148  if (visualization)
149  {
150  sol_sock.open(vishost, visport);
151  }
152 
153  // 5. Define custom integration rule (optional).
154  const IntegrationRule *irs[Geometry::NumGeom];
155  int order_quad = 2*order + enriched_order;
156  for (int i = 0; i < Geometry::NumGeom; ++i)
157  {
158  irs[i] = &(IntRules.Get(i, order_quad));
159  }
160 
161  // 6. Apply custom refiner settings.
162  coeffrefiner.SetIntRule(irs);
163  coeffrefiner.SetMaxElements(max_elems);
164  coeffrefiner.SetThreshold(osc_threshold);
165  coeffrefiner.SetNCLimit(nc_limit);
166  coeffrefiner.PrintWarnings();
167 
168  // 7. Preprocess mesh to control osc (piecewise-affine function). This is
169  // mostly just a verification check. The oscillation should be zero if the
170  // function is mesh-conforming and order > 0.
171  coeffrefiner.PreprocessMesh(mesh);
172 
173  mfem::out << "\n";
174  mfem::out << "Function 0 (affine) \n";
175  mfem::out << "Number of Elements " << mesh.GetNE() << "\n";
176  mfem::out << "Osc error " << coeffrefiner.GetOsc() << "\n";
177 
178  // 8. Preprocess mesh to control osc (jump function).
179  coeffrefiner.ResetCoefficient(jump_coeff);
180  coeffrefiner.PreprocessMesh(mesh);
181 
182  mfem::out << "\n";
183  mfem::out << "Function 1 (discontinuous) \n";
184  mfem::out << "Number of Elements " << mesh.GetNE() << "\n";
185  mfem::out << "Osc error " << coeffrefiner.GetOsc() << "\n";
186 
187  // 9. Preprocess mesh to control osc (singular function).
188  coeffrefiner.ResetCoefficient(singular_coeff);
189  coeffrefiner.PreprocessMesh(mesh);
190 
191  mfem::out << "\n";
192  mfem::out << "Function 2 (singular) \n";
193  mfem::out << "Number of Elements " << mesh.GetNE() << "\n";
194  mfem::out << "Osc error " << coeffrefiner.GetOsc() << "\n";
195 
196  if (visualization)
197  {
198  sol_sock.precision(8);
199  sol_sock << "mesh\n" << mesh << flush;
200  }
201 
202  return 0;
203 }
Class for an integration rule - an Array of IntegrationPoint.
Definition: intrules.hpp:90
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
Definition: intrules.cpp:923
double jump_function(const Vector &p)
Definition: ex30.cpp:59
void ResetCoefficient(Coefficient &coeff_)
Reset the function f.
double singular_function(const Vector &p)
Definition: ex30.cpp:73
int GetNE() const
Returns number of elements.
Definition: mesh.hpp:928
void SetIntRule(const IntegrationRule *irs_[])
virtual int PreprocessMesh(Mesh &mesh, int max_it)
Apply the operator to the mesh max_it times or until tolerance achieved.
void SetMaxElements(long max_elements_)
Set the maximum number of elements stopping criterion: stop when the input mesh has num_elements &gt;= m...
double Normlp(double p) const
Returns the l_p norm of the vector.
Definition: vector.cpp:832
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
Definition: optparser.cpp:151
constexpr char vishost[]
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition: mesh.cpp:9737
constexpr int visport
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
Definition: mesh.cpp:5312
void SetNCLimit(int nc_limit_)
Set the maximum ratio of refinement levels of adjacent elements (0 = unlimited). The default value is...
void PrintUsage(std::ostream &out) const
Print the usage message.
Definition: optparser.cpp:454
FDualNumber< tbase > pow(const FDualNumber< tbase > &a, const FDualNumber< tbase > &b)
pow([dual number],[dual number])
Definition: fdual.hpp:543
Refinement operator to control data oscillation.
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
double affine_function(const Vector &p)
Definition: ex30.cpp:45
NURBSExtension * NURBSext
Optional NURBS mesh extension.
Definition: mesh.hpp:272
void SetThreshold(double threshold_)
Set the refinement threshold. The default value is 1.0e-2.
FDualNumber< tbase > sqrt(const FDualNumber< tbase > &f)
sqrt([dual number])
Definition: fdual.hpp:600
void PrintOptions(std::ostream &out) const
Print the options.
Definition: optparser.cpp:324
int open(const char hostname[], int port)
Open the socket stream on &#39;port&#39; at &#39;hostname&#39;.
const double alpha
Definition: ex15.cpp:369
A general function coefficient.
Vector data type.
Definition: vector.hpp:60
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition: globals.hpp:66
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Definition: intrules.hpp:379
int main()
bool Good() const
Return true if the command line options were parsed successfully.
Definition: optparser.hpp:150