Ascent#
A fast and flexible C++ simulation engine and differential equation solver.
Link |
|
|---|---|
Language |
C++ |
License |
Apache-2.0 license |
Lorenz equations#
We would like to solve the Lorenz equations, a classical chaotic system given by:
with parameter \(\sigma=10\), \(\rho = 28\) and \(\beta = \frac{8}{3}\), and the initial state \((x_0, y_0, z_0) = (1,1,1)\). We solve it with a classical Runge-Kutta method of order 4, given by asc::RK4 method.
To solve a problem with Ascent we first write our equation as a ODE of the form:
and the user provide the function \(f\) as (a lambda function for the example):
auto f = [](state_t const& u, state_t & du, double t);
where u the current state of the function, t the current time and output du \(f(t,u)\) by reference. By default, Ascent provide a asc::state_t type as a reference to std::vector<double> class.
13 auto lorenz = [&]( asc::state_t const& y, asc::state_t& dy, double t )
14 {
15 dy[0] = sigma * ( y[1] - y[0] );
16 dy[1] = y[0] * ( rho - y[2] ) - y[1];
17 dy[2] = y[0] * y[1] - beta * y[2];
18 };
If we need a more generic state type we need to use asc::RK4T<state_t> integrator in place of asc::RK4. Next we can call this integrator for one step with the time step dt by calling it as
integrator(f, un, tn, dt);
which takes current state un and time tn by references (also dt if this is an adaptive time step method), inside the time loop:
40 while ( tn < tf )
41 {
42 vec_observer( yn, tn );
43 integrator( lorenz, yn, tn, dt );
44 }
where vec_observer is an observer to save states in a std::vector.
For the complet example, see lorenz.cpp source file.
Transport equation#
In this example we would like to solve the following PDE:
with \(t>0\), on the torus \(x\in[0, 1)\), a velocity \(a=1\) and the initial condition given by a hat function:
We choose a first order up-wind scheme to estimate the \(x\) derivative and a forward Euler method for the time discretization given by asc::Euler method.
We define the up-wind scheme as:
46 auto upwind = [a, n_x, dx]( asc::state_t const& y, asc::state_t& dy, double t )
47 {
48 dy[0] = -( std::max( a, 0. ) * ( y[0] - y[n_x - 1] ) + std::min( a, 0. ) * ( y[1] - y[0] ) ) / dx;
49
50 for ( std::size_t i = 1; i < n_x - 1; ++i )
51 {
52 dy[i] = -( std::max( a, 0. ) * ( y[i] - y[i - 1] ) + std::min( a, 0. ) * ( y[i + 1] - y[i] ) ) / dx;
53 }
54
55 dy[n_x - 1] = -( std::max( a, 0. ) * ( y[n_x - 1] - y[n_x - 2] ) + std::min( a, 0. ) * ( y[0] - y[n_x - 1] ) ) / dx;
56 };
The time loop is the same as for Lorenz equation.
For the complet example, see transport.cpp source file.
Arenstorf orbit#
The Arenstorf orbit problem is a classical problem to test adaptive time step methods:
with initial condition \((x,\dot{x},y,\dot{y})=(0.994, 0, 0, -2.001585106)\), \(r_1\) and \(r_2\) given by
and with parameter \(\mu = 0.012277471\).
First of all, we need to rewrite this problem into a first order derivative equation in time
We define this system as:
11 auto arenstorf = [=]( asc::state_t const& y, asc::state_t& dy, double t )
12 {
13 double const y1 = y[0];
14 double const y2 = y[1];
15 double const y3 = y[2];
16 double const y4 = y[3];
17
18 double const r1 = sqrt( ( y1 + mu ) * ( y1 + mu ) + y2 * y2 );
19 double const r2 = sqrt( ( y1 - 1. + mu ) * ( y1 - 1. + mu ) + y2 * y2 );
20
21 dy[0] = y3;
22 dy[1] = y4;
23 dy[2] = y1 + 2. * y4 - ( 1. - mu ) * ( y1 + mu ) / ( r1 * r1 * r1 ) - mu * ( y1 - 1. + mu ) / ( r2 * r2 * r2 );
24 dy[3] = y2 - 2. * y3 - ( 1. - mu ) * y2 / ( r1 * r1 * r1 ) - mu * y2 / ( r2 * r2 * r2 );
25 };
We solve this example with given method asc::DOPRI45 which is the method RK5(4) 7M in [DP80] (mainly call DOPRI5). For this we need to set the integrator and settings for adaptive time step method
42 asc::DOPRI45 integrator;
43 asc::AdaptiveT<double> adaptive_settings( 1e-5, 1e-5, 0.9 );
then the time loop becomes
48 while ( tn < tf )
49 {
50 vec_observer( yn, tn, dt );
51 integrator( arenstorf, yn, tn, dt, adaptive_settings );
52 }
where we should pass the adaptive_setting object to integrator.
For the complet example, see arenstorf.cpp source file.