Skip to content

Example: oscillation equations ​

Migrated from the wiki

This page replaces the Oscillation equations page of the old GitHub wiki. The wiki described an integrand written for a former FOODIE API (type, extends(integrand), with an update_previous_steps method and integrator-specific init calls) that no longer exists. The current integrand is integrand_oscillation of src/tests/tester/foodie_test_integrand_oscillation.f90, integrated by the CLI tester.

Mathematical model ​

The inertial oscillation equations are a system of two ODEs [1]:

Ut=R(U),U=[v1v2],R(U)=[−fv2fv1]

with constant frequency f, by default f=10−4. The exact solution is a rotation in the v1-v2 plane:

v1(t)=v1(0)cos⁡(ft)−v2(0)sin⁡(ft),v2(t)=v1(0)sin⁡(ft)+v2(0)cos⁡(ft)

The path of the solution must be a circle, its amplitude constant: the eigenvalues of the system, ±if, are purely imaginary, so the problem tests the behaviour of the schemes on the imaginary axis. A scheme whose stability region does not contain a segment of the imaginary axis, such as the forward Euler scheme, amplifies the solution at every step whatever the step size; the leapfrog scheme, unstable on dissipative problems, is neutrally stable here.

The FOODIE integrand ​

The state is an array of two reals; the residual function is, verbatim from the source:

fortran
pure function dU_dt(self, t) result(dState_dt)
!< Time derivative of integrand_oscillation field.
class(integrand_oscillation), intent(in)           :: self         !< Integrand.
real(R_P),                    intent(in), optional :: t            !< Time.
real(R_P), allocatable                             :: dState_dt(:) !< Integrand time derivative.

dState_dt = [-self%f * self%U(2), &
              self%f * self%U(1)]
endfunction dU_dt

The operators and the assignments follow the pattern of the quick start, acting on the two components of the state.

Integration ​

Build the CLI tester and integrate the problem with three time steps up to t=106 (about 16 periods), from the default initial state (v1,v2)=(0,1):

bash
fobis build --mode tester-gnu
./build/tester/foodie_tester test -s runge_kutta_ssp_stages_5_order_4 -Dt 1000 500 250 -ft 1e6 oscillation

The tester prints the error of v1 and v2 at the final time and the observed orders. The errors for some schemes:

SchemeΔt=1000Δt=500Δt=250Observed order
euler_explicit109.46.491.32(unstable)
leapfrog1.50e-13.64e-29.01e-32.01
leapfrog_raw1.52e-13.70e-29.27e-32.00
adams_bashforth_32.18e-22.58e-33.10e-43.06
adams_moulton_22.25e-32.72e-43.35e-53.02
runge_kutta_ssp_stages_3_order_32.38e-32.81e-43.41e-53.05
runge_kutta_ssp_stages_5_order_43.19e-52.04e-61.29e-73.99

(error of v1; observed order on the two finest steps; default options: 1 fixed point iteration for Adams-Moulton.)

  • The forward Euler solution spirals outwards: with fΔt=0.1 its amplitude grows by 1+(fΔt)2 per step, the error (109 for an amplitude 1) is not a truncation error but an instability.
  • The leapfrog family is neutrally stable on this problem. At these step sizes leapfrog_raw shows an observed order of about 2: its 1st order error term is proportional to the filter coefficient ν=0.01, and dominates only for smaller steps. Its formal order is 1, see Notes on the orders.
  • The multistep schemes are started up with the exact solution by the tester.

Add -r (--save_results) to save the solutions as Tecplot ASCII files and plot the path in the v1-v2 plane.

Bibliography ​

[1] Numerical Methods for Fluid Dynamics With Applications to Geophysics, D. R. Durran, Springer, 2010.

Released under the GPL v3, BSD 2-Clause, BSD 3-Clause and MIT licenses.