// MFEM Example 20 // // Compile with: make ex20 // // Sample runs: ex20 // // Description: This example demonstrates the use of the variable // order, symplectic ODE integration algorithm. // Symplectic integration algorithms are designed to // conserve energy when integrating, in time, systems of // ODEs which are derived from Hamiltonain systems. // // Hamiltonian systems define the energy of a system as a // function of time (t), a set of generalized coordinates // (q), and their corresponding generalized momenta (p). // H(q,p,t) = T(p) + V(q,t) // Hamilton's equations then specify how q and p evolve // in time: // dq/dt = dH/dp // dp/dt = -dH/dq // To use the symplectic integration classes we need to // define an mfem::Operator P which evaluates the action // of dH/dp, and an mfem::TimeDependentOperator F which // computes -dH/dq. // // This example offers five simple 1D Hamiltonians: // 0) Simple Harmonic Oscillator (mass on a spring) // H = ( p^2 / m + q^2 / k ) / 2 // 1) Pendulum // H = ( p^2 / m - k ( 1 - cos(q) ) ) / 2 // 2) Gaussian Potential Well // H = ( p^2 / m ) / 2 - k exp(-q^2 / 2) // 3) Quartic Potential // H = ( p^2 / m + k ( 1 + q^2 ) q^2 ) / 2 // 4) Negative Quartic Potential // H = ( p^2 / m + k ( 1 - q^2 /8 ) q^2 ) / 2 // In all cases these Hamiltonians are shifted by constant // values so that the energy will remain positive. The mean // and standard deviation of the computed energies at each // time step are displayed upon completion. // // We then use GLVis to visualize the results in a // non-standard way by defining the axes to be q, p, and // t rather than x, y, and z. In this space we build a // ribbon-like mesh with nodes at (0,0,t) and (q,p,t). // Finally we plot the energy as a function of time as a // scalar field on this ribbon-like mesh. // // For a more traditional plot of the results, including // q, p, and H, can be obtained by selecting the "-gp" // option. This creates a data file and input deck for // the GnuPlot application (not included with MFEM). To // visualize these results on most linux systems type the // command "gnuplot gnuplot_ex20.inp". The data file, // named "ex20.dat", should be simple enough to display // with other plotting programs as well. // #include "mfem.hpp" #include #include using namespace std; using namespace mfem; static int prob_ = 0; static double m_ = 1.0; static double k_ = 1.0; double hamiltonian(double q, double p, double t); class GradT : public Operator { public: GradT() : Operator(1) {} void Mult(const Vector &x, Vector &y) const { y.Set(1.0/m_, x); } private: }; class NegGradV : public TimeDependentOperator { public: NegGradV() : TimeDependentOperator(1) {} void Mult(const Vector &x, Vector &y) const; private: }; int main(int argc, char *argv[]) { // Parse command-line options. int order = 1; int nsteps = 100; double dt = 0.1; bool visualization = true; bool gnuplot = false; OptionsParser args(argc, argv); args.AddOption(&order, "-o", "--order", "Time integration order."); args.AddOption(&prob_, "-p", "--problem-type", "Problem Type:\n" "\t 0 - Simple Harmonic Oscillator\n" "\t 1 - Pendulum\n" "\t 2 - Gaussian Potential Well\n" "\t 3 - Quartic Potential\n" "\t 4 - Negative Quartic Potential"); args.AddOption(&nsteps, "-n", "--number-of-steps", "Number of time steps."); args.AddOption(&dt, "-dt", "--time-step", "Time step size."); args.AddOption(&m_, "-m", "--mass", "Mass."); args.AddOption(&k_, "-k", "--spring-const", "Spring Constant."); args.AddOption(&visualization, "-vis", "--visualization", "-no-vis", "--no-visualization", "Enable or disable GLVis visualization."); args.AddOption(&gnuplot, "-gp", "--gnuplot", "-no-gp", "--no-gnuplot", "Enable or disable GnuPlot visualization."); args.Parse(); if (!args.Good()) { args.PrintUsage(cout); return 1; } args.PrintOptions(cout); SIAVSolver siaSolver(order); GradT P; NegGradV F; siaSolver.Init(P,F); double t = 0.0; Vector q(1), p(1); q(0) = 0.0; p(0) = 1.0; ofstream ofs; if ( gnuplot ) { ofs.open("ex20.dat"); ofs << t << "\t" << q(0) << "\t" << p(0) << endl; } Vector e(nsteps+1); int nverts = (visualization)?2*(nsteps+1):0; int nelems = (visualization)?nsteps:0; Mesh mesh(2, nverts, nelems, 0, 3); int v[4]; Vector x0(3); x0 = 0.0; //x0(0) = M_PI; Vector x1(3); x1 = 0.0; double e_mean = 0.0; for (int i=0; i