MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
ex18.cpp
Go to the documentation of this file.
1// MFEM Example 18
2//
3// Compile with: make ex18
4//
5// Sample runs:
6//
7// ex18 -p 1 -r 2 -o 1 -s 3
8// ex18 -p 1 -r 1 -o 3 -s 4
9// ex18 -p 1 -r 0 -o 5 -s 6
10// ex18 -p 2 -r 1 -o 1 -s 3 -mf
11// ex18 -p 2 -r 0 -o 3 -s 3 -mf
12//
13// Description: This example code solves the compressible Euler system of
14// equations, a model nonlinear hyperbolic PDE, with a
15// discontinuous Galerkin (DG) formulation.
16//
17// (u_t, v)_T - (F(u), ∇ v)_T + <F̂(u,n), [[v]]>_F = 0
18//
19// where (⋅,⋅)_T is volume integration, and <⋅,⋅>_F is face
20// integration, F is the Euler flux function, and F̂ is the
21// numerical flux.
22//
23// Specifically, it solves for an exact solution of the equations
24// whereby a vortex is transported by a uniform flow. Since all
25// boundaries are periodic here, the method's accuracy can be
26// assessed by measuring the difference between the solution and
27// the initial condition at a later time when the vortex returns
28// to its initial location.
29//
30// Note that as the order of the spatial discretization increases,
31// the timestep must become smaller. This example currently uses a
32// simple estimate derived by Cockburn and Shu for the 1D RKDG
33// method. An additional factor can be tuned by passing the --cfl
34// (or -c shorter) flag.
35//
36// The example demonstrates usage of DGHyperbolicConservationLaws
37// that wraps NonlinearFormIntegrators containing element and face
38// integration schemes. In this case the system also involves an
39// external approximate Riemann solver for the DG interface flux.
40// By default, weak-divergence is pre-assembled in element-wise
41// manner, which corresponds to (I_h(F(u_h)), ∇ v). This yields
42// better performance and similar accuracy for the included test
43// problems. This can be turned off and use nonlinear assembly
44// similar to matrix-free assembly when -mf flag is provided.
45// It also demonstrates how to use GLVis for in-situ visualization
46// of vector grid function and how to set top-view.
47//
48// We recommend viewing examples 9, 14 and 17 before viewing this
49// example.
50
51#include "mfem.hpp"
52#include <fstream>
53#include <iostream>
54#include <sstream>
55#include "ex18.hpp"
56
57using namespace std;
58using namespace mfem;
59
60int main(int argc, char *argv[])
61{
62 // 1. Parse command-line options.
63 int problem = 1;
64 const real_t specific_heat_ratio = 1.4;
65 const real_t gas_constant = 1.0;
66
67 string mesh_file = "";
68 int IntOrderOffset = 1;
69 int ref_levels = 1;
70 int order = 3;
71 int ode_solver_type = 4;
72 real_t t_final = 2.0;
73 real_t dt = -0.01;
74 real_t cfl = 0.3;
75 bool visualization = true;
76 bool preassembleWeakDiv = true;
77 int vis_steps = 50;
78
79 int precision = 8;
80 cout.precision(precision);
81
82 OptionsParser args(argc, argv);
83 args.AddOption(&mesh_file, "-m", "--mesh",
84 "Mesh file to use. If not provided, then a periodic square"
85 " mesh will be used.");
86 args.AddOption(&problem, "-p", "--problem",
87 "Problem setup to use. See EulerInitialCondition().");
88 args.AddOption(&ref_levels, "-r", "--refine",
89 "Number of times to refine the mesh uniformly.");
90 args.AddOption(&order, "-o", "--order",
91 "Order (degree) of the finite elements.");
92 args.AddOption(&ode_solver_type, "-s", "--ode-solver",
94 args.AddOption(&t_final, "-tf", "--t-final", "Final time; start time is 0.");
95 args.AddOption(&dt, "-dt", "--time-step",
96 "Time step. Positive number skips CFL timestep calculation.");
97 args.AddOption(&cfl, "-c", "--cfl-number",
98 "CFL number for timestep calculation.");
99 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
100 "--no-visualization",
101 "Enable or disable GLVis visualization.");
102 args.AddOption(&preassembleWeakDiv, "-ea", "--element-assembly-divergence",
103 "-mf", "--matrix-free-divergence",
104 "Weak divergence assembly level\n"
105 " ea - Element assembly with interpolated F\n"
106 " mf - Nonlinear assembly in matrix-free manner");
107 args.AddOption(&vis_steps, "-vs", "--visualization-steps",
108 "Visualize every n-th timestep.");
109 args.ParseCheck();
110
111 // 2. Read the mesh from the given mesh file. When the user does not provide
112 // mesh file, use the default mesh file for the problem.
113 Mesh mesh = mesh_file.empty() ? EulerMesh(problem) : Mesh(mesh_file);
114 const int dim = mesh.Dimension();
115 const int num_equations = dim + 2;
116
117 // Refine the mesh to increase the resolution. In this example we do
118 // 'ref_levels' of uniform refinement, where 'ref_levels' is a command-line
119 // parameter.
120 for (int lev = 0; lev < ref_levels; lev++)
121 {
122 mesh.UniformRefinement();
123 }
124
125 // 3. Define the ODE solver used for time integration. Several explicit
126 // Runge-Kutta methods are available.
127 unique_ptr<ODESolver> ode_solver = ODESolver::SelectExplicit(ode_solver_type);
128
129 // 4. Define the discontinuous DG finite element space of the given
130 // polynomial order on the refined mesh.
131 DG_FECollection fec(order, dim);
132 // Finite element space for a scalar (thermodynamic quantity)
133 FiniteElementSpace fes(&mesh, &fec);
134 // Finite element space for a mesh-dim vector quantity (momentum)
135 FiniteElementSpace dfes(&mesh, &fec, dim, Ordering::byNODES);
136 // Finite element space for all variables together (total thermodynamic state)
137 FiniteElementSpace vfes(&mesh, &fec, num_equations, Ordering::byNODES);
138
139 // This example depends on this ordering of the space.
140 MFEM_ASSERT(fes.GetOrdering() == Ordering::byNODES, "");
141
142 cout << "Number of unknowns: " << vfes.GetVSize() << endl;
143
144 // 5. Define the initial conditions, save the corresponding mesh and grid
145 // functions to files. These can be opened with GLVis using:
146 // "glvis -m euler-mesh.mesh -g euler-1-init.gf" (for x-momentum).
147
148 // Initialize the state.
150 specific_heat_ratio,
151 gas_constant);
152 GridFunction sol(&vfes);
153 sol.ProjectCoefficient(u0);
154 GridFunction mom(&dfes, sol.GetData() + fes.GetNDofs());
155 // Output the initial solution.
156 {
157 ostringstream mesh_name;
158 mesh_name << "euler-mesh.mesh";
159 ofstream mesh_ofs(mesh_name.str().c_str());
160 mesh_ofs.precision(precision);
161 mesh_ofs << mesh;
162
163 for (int k = 0; k < num_equations; k++)
164 {
165 GridFunction uk(&fes, sol.GetData() + k * fes.GetNDofs());
166 ostringstream sol_name;
167 sol_name << "euler-" << k << "-init.gf";
168 ofstream sol_ofs(sol_name.str().c_str());
169 sol_ofs.precision(precision);
170 sol_ofs << uk;
171 }
172 }
173
174 // 6. Set up the nonlinear form with euler flux and numerical flux
175 EulerFlux flux(dim, specific_heat_ratio);
176 RusanovFlux numericalFlux(flux);
178 vfes, std::unique_ptr<HyperbolicFormIntegrator>(
179 new HyperbolicFormIntegrator(numericalFlux, IntOrderOffset)),
180 preassembleWeakDiv);
181
182 // 7. Visualize momentum with its magnitude
183 socketstream sout;
184 if (visualization)
185 {
186 char vishost[] = "localhost";
187 int visport = 19916;
188
189 sout.open(vishost, visport);
190 if (!sout)
191 {
192 visualization = false;
193 cout << "Unable to connect to GLVis server at " << vishost << ':'
194 << visport << endl;
195 cout << "GLVis visualization disabled.\n";
196 }
197 else
198 {
199 sout.precision(precision);
200 // Plot magnitude of vector-valued momentum
201 sout << "solution\n" << mesh << mom;
202 sout << "window_title 'momentum, t = 0'\n";
203 sout << "view 0 0\n"; // view from top
204 sout << "keys jlm\n"; // turn off perspective and light, show mesh
205 sout << "pause\n";
206 sout << flush;
207 cout << "GLVis visualization paused."
208 << " Press space (in the GLVis window) to resume it.\n";
209 }
210 }
211
212 // 8. Time integration
213
214 // When dt is not specified, use CFL condition.
215 // Compute h_min and initial maximum characteristic speed
216 real_t hmin = infinity();
217 if (cfl > 0)
218 {
219 for (int i = 0; i < mesh.GetNE(); i++)
220 {
221 hmin = min(mesh.GetElementSize(i, 1), hmin);
222 }
223 // Find a safe dt, using a temporary vector. Calling Mult() computes the
224 // maximum char speed at all quadrature points on all faces (and all
225 // elements with -mf).
226 Vector z(sol.Size());
227 euler.Mult(sol, z);
228
229 real_t max_char_speed = euler.GetMaxCharSpeed();
230 dt = cfl * hmin / max_char_speed / (2 * order + 1);
231 }
232
233 // Start the timer.
234 tic_toc.Clear();
235 tic_toc.Start();
236
237 // Init time integration
238 real_t t = 0.0;
239 euler.SetTime(t);
240 ode_solver->Init(euler);
241
242 // Integrate in time.
243 bool done = false;
244 for (int ti = 0; !done;)
245 {
246 real_t dt_real = min(dt, t_final - t);
247
248 ode_solver->Step(sol, t, dt_real);
249 if (cfl > 0) // update time step size with CFL
250 {
251 real_t max_char_speed = euler.GetMaxCharSpeed();
252 dt = cfl * hmin / max_char_speed / (2 * order + 1);
253 }
254 ti++;
255
256 done = (t >= t_final - 1e-8 * dt);
257 if (done || ti % vis_steps == 0)
258 {
259 cout << "time step: " << ti << ", time: " << t << endl;
260 if (visualization)
261 {
262 sout << "window_title 'momentum, t = " << t << "'\n";
263 sout << "solution\n" << mesh << mom << flush;
264 }
265 }
266 }
267
268 tic_toc.Stop();
269 cout << " done, " << tic_toc.RealTime() << "s." << endl;
270
271 // 9. Save the final solution. This output can be viewed later using GLVis:
272 // "glvis -m euler-mesh-final.mesh -g euler-1-final.gf" (for x-momentum).
273 {
274 ostringstream mesh_name;
275 mesh_name << "euler-mesh-final.mesh";
276 ofstream mesh_ofs(mesh_name.str().c_str());
277 mesh_ofs.precision(precision);
278 mesh_ofs << mesh;
279
280 for (int k = 0; k < num_equations; k++)
281 {
282 GridFunction uk(&fes, sol.GetData() + k * fes.GetNDofs());
283 ostringstream sol_name;
284 sol_name << "euler-" << k << "-final.gf";
285 ofstream sol_ofs(sol_name.str().c_str());
286 sol_ofs.precision(precision);
287 sol_ofs << uk;
288 }
289 }
290
291 // 10. Compute the L2 solution error summed for all components.
292 const real_t error = sol.ComputeLpError(2, u0);
293 cout << "Solution error: " << error << endl;
294
295 return 0;
296}
Time dependent DG operator for hyperbolic conservation laws.
Definition ex18.hpp:32
void Mult(const Vector &x, Vector &y) const override
Apply nonlinear form to obtain M⁻¹(DIVF + JUMP HAT(F))
Definition ex18.hpp:168
Euler flux.
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:244
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
Definition fespace.hpp:845
Ordering::Type GetOrdering() const
Return the ordering method.
Definition fespace.hpp:876
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition fespace.hpp:848
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:31
virtual real_t ComputeLpError(const real_t p, Coefficient &exsol, Coefficient *weight=NULL, const IntegrationRule *irs[]=NULL, const Array< int > *elems=NULL) const
Returns ||u_ex - u_h||_Lp for H1 or L2 elements.
virtual void ProjectCoefficient(Coefficient &coeff)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
Abstract hyperbolic form integrator, assembling (F(u, x), ∇v) and <F̂(u⁻,u⁺,x) n, [v]> terms for scal...
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:346
Mesh data type.
Definition mesh.hpp:64
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1282
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1216
real_t GetElementSize(int i, int type=0)
Get the size of the i-th element relative to the perfect reference element.
Definition mesh.cpp:107
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:11295
static MFEM_EXPORT std::string ExplicitTypes
Definition ode.hpp:185
static MFEM_EXPORT std::unique_ptr< ODESolver > SelectExplicit(const int ode_solver_type)
Definition ode.cpp:46
void ParseCheck(std::ostream &out=mfem::out)
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
Rusanov flux, also known as local Lax-Friedrichs, F̂ n = ½(F(u⁺,x)n + F(u⁻,x)n) - ½λ(u⁺ - u⁻) where λ...
double RealTime()
Return the number of real seconds elapsed since the stopwatch was started.
Definition tic_toc.cpp:432
void Start()
Start the stopwatch. The elapsed time is not cleared.
Definition tic_toc.cpp:411
void Stop()
Stop the stopwatch.
Definition tic_toc.cpp:422
void Clear()
Clear the elapsed time on the stopwatch and restart it if it's running.
Definition tic_toc.cpp:406
virtual void SetTime(const real_t t_)
Set the current time.
Definition operator.hpp:394
A general vector function coefficient.
Vector data type.
Definition vector.hpp:82
int Size() const
Returns the size of the vector.
Definition vector.hpp:226
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition vector.hpp:235
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
int problem
Definition ex15.cpp:62
int dim
Definition ex24.cpp:53
int main()
real_t infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
Definition vector.hpp:47
Mesh EulerMesh(const int problem)
Definition ex18.hpp:299
VectorFunctionCoefficient EulerInitialCondition(const int problem, const real_t specific_heat_ratio, const real_t gas_constant)
Definition ex18.hpp:317
StopWatch tic_toc
Definition tic_toc.cpp:450
float real_t
Definition config.hpp:43
const char vishost[]