6.1. Asynchronicity
Alice: We have seen that constant time steps allow you to stop and
restart, and to get exactly the same results as you would have gotten,
had you done one single integration from being to end. But when we
tried to do the same thing with adaptive, shared time steps, we found
that we could not reproduce the same orbits.
Bob: And we knew why. In fact, we had predicted that we couldn't.
Alice: Yes. Now the question is: can we regain our reproducibility?
Bob: How?
Alice: What did not work was to force an output at exactly the right
time. That had the side effect of forcing the last step to be smaller
than it would have otherwise been.
However, there is an alternative. How about letting the system overshoot,
so that it can do an output a time it is happy with. When we then restart
the system, the integration should happen just like it would have otherwise.
Bob: I see what you mean. Well, let's test it!
Alice: Here is what we did before, but this time without the
--exact_time option:
|gravity> kali nbody_sh1.rb -t 1 < test.in > test01n.out
==> Shared Time Step Code <==
Integration method : method = hermite
Parameter to determine time step size: dt_param = 0.01
Interval between diagnostics output: dt_dia = 1.0
Time interval between snapshot output: dt_out = 1.0
Duration of the integration : t = 1.0
Screen Output Verbosity Level : verbosity = 1
ACS Output Verbosity Level : acs_verbosity = 1
Floating point precision : precision = 16
Incremental indentation : add_indent = 2
at time t = 0, after 0 steps :
E_kin = 0.25 , E_pot = -0.5 , E_tot = -0.25
E_tot - E_init = 0
(E_tot - E_init) / E_init = -0
at time t = 1.00035, after 1927 steps :
E_kin = 0.312 , E_pot = -0.562 , E_tot = -0.25
E_tot - E_init = -2.26e-10
(E_tot - E_init) / E_init = 9.03e-10
|gravity> kali nbody_sh1.rb -t 1 < test01n.out > test12n.out
==> Shared Time Step Code <==
Integration method : method = hermite
Parameter to determine time step size: dt_param = 0.01
Interval between diagnostics output: dt_dia = 1.0
Time interval between snapshot output: dt_out = 1.0
Duration of the integration : t = 1.0
Screen Output Verbosity Level : verbosity = 1
ACS Output Verbosity Level : acs_verbosity = 1
Floating point precision : precision = 16
Incremental indentation : add_indent = 2
at time t = 1.00035, after 0 steps :
E_kin = 0.312 , E_pot = -0.562 , E_tot = -0.25
E_tot - E_init = 0
(E_tot - E_init) / E_init = -0
at time t = 2.00117, after 1224 steps :
E_kin = 0.171 , E_pot = -0.421 , E_tot = -0.25
E_tot - E_init = 2.83e-10
(E_tot - E_init) / E_init = -1.13e-09
|gravity> kali nbody_sh1.rb -t 2 -o 2 < test.in > test02n.out
==> Shared Time Step Code <==
Integration method : method = hermite
Parameter to determine time step size: dt_param = 0.01
Interval between diagnostics output: dt_dia = 1.0
Time interval between snapshot output: dt_out = 2.0
Duration of the integration : t = 2.0
Screen Output Verbosity Level : verbosity = 1
ACS Output Verbosity Level : acs_verbosity = 1
Floating point precision : precision = 16
Incremental indentation : add_indent = 2
at time t = 0, after 0 steps :
E_kin = 0.25 , E_pot = -0.5 , E_tot = -0.25
E_tot - E_init = 0
(E_tot - E_init) / E_init = -0
at time t = 1.00035, after 1927 steps :
E_kin = 0.312 , E_pot = -0.562 , E_tot = -0.25
E_tot - E_init = -2.26e-10
(E_tot - E_init) / E_init = 9.03e-10
at time t = 2.00117, after 3151 steps :
E_kin = 0.171 , E_pot = -0.421 , E_tot = -0.25
E_tot - E_init = 5.76e-11
(E_tot - E_init) / E_init = -2.31e-10
Bob: So you think we'll get a smaller distance now?
Alice: As close to zero as we can!
Bob: Well, let's hope for the best:
|gravity> cat test12n.out test02n.out | kali nbody_diff.rb
==> 6N-dimensional phase space distance between two N-body systems <==
Screen Output Verbosity Level : verbosity = 1
ACS Output Verbosity Level : acs_verbosity = 1
Floating point precision : precision = 16
Incremental indentation : add_indent = 2
6N-dim. phase space dist. for two 4-body systems: 0.0000000000000000e+00
6.2. Overshooting
Alice: Hmmm, that's not good at all. What did we do to deserve that!
Bob: If we look at the diagnostics output, we see that we needed the same
number of steps to reach time 1, exactly 1263 in each case. Then in
the continued run, we took another 669 steps. This gives us a total
number of 1932 steps. Aha! That is not the number of steps that
the second run took.
Alice: Good catch! The second run stopped too early. And yes, of course,
we could have noticed that directly, had we looked at the final time: the
second run indeed shows an earlier ending time than the first one.
Bob: And that makes sense, too: we ask each run to go fro one or two time
units, or slightly more if they overshoot. Now asking a code to overshoot
twice in a row is likely to produce a larger overshoot than doing it
only once.
Alice: Again, you must be right. Going from time 0 to 1, with an
overshoot, and then adding one more time unit plus a new overshoot is
not the same as going from 0 to 2 immediately, with whatever overshoot
that gives.
Bob: Well, shall we try to let the long run proceed a little further,
to match up with the previous one?
Alice: You can certainly try. So this means adding the difference
of the two ending times to the desired duration; or in fact slightly
less, since we'll produce an overshoot anyway.
Bob: Okay, how about this:
|gravity> kali nbody_sh1.rb -t 2.0037 -o 2.0037 < test.in > test02n.out
==> Shared Time Step Code <==
Integration method : method = hermite
Parameter to determine time step size: dt_param = 0.01
Interval between diagnostics output: dt_dia = 1.0
Time interval between snapshot output: dt_out = 2.0037
Duration of the integration : t = 2.0037
Screen Output Verbosity Level : verbosity = 1
ACS Output Verbosity Level : acs_verbosity = 1
Floating point precision : precision = 16
Incremental indentation : add_indent = 2
at time t = 0, after 0 steps :
E_kin = 0.25 , E_pot = -0.5 , E_tot = -0.25
E_tot - E_init = 0
(E_tot - E_init) / E_init = -0
at time t = 1.00035, after 1927 steps :
E_kin = 0.312 , E_pot = -0.562 , E_tot = -0.25
E_tot - E_init = -2.26e-10
(E_tot - E_init) / E_init = 9.03e-10
at time t = 2.00117, after 3151 steps :
E_kin = 0.171 , E_pot = -0.421 , E_tot = -0.25
E_tot - E_init = 5.76e-11
(E_tot - E_init) / E_init = -2.31e-10
|gravity> cat test12n.out test02n.out | kali nbody_diff.rb
==> 6N-dimensional phase space distance between two N-body systems <==
Screen Output Verbosity Level : verbosity = 1
ACS Output Verbosity Level : acs_verbosity = 1
Floating point precision : precision = 16
Incremental indentation : add_indent = 2
6N-dim. phase space dist. for two 4-body systems: 9.2780296991970546e-03