3.6. Verification
Alice: Let's take all three codes we have now, for constant, shared,
and individual time steps. And let's give them a really good workout.
Shall we shoot for an accuracy of
? If we get too
close to machine accuracy, it may be more difficult to interpret our
results.
Bob: Fine with me. Let's start with the same initial conditions:
|gravity> kali mkplummer.rb -n 4 -s 1 | kali nbody_set_id.rb > test.in
==> Plummer's Model Builder <==
Number of particles : N = 4
pseudorandom number seed given : 1
Floating point precision : precision = 16
Incremental indentation : add_indent = 2
Screen Output Verbosity Level : verbosity = 1
ACS Output Verbosity Level : acs_verbosity = 1
Floating point precision : precision = 16
Incremental indentation : add_indent = 2
actual seed used : 1
==> Takes an N-body system, and gives each body a unique ID <==
value of @body_id for 1st body : n = 1
Floating point precision : precision = 16
Screen Output Verbosity Level : verbosity = 1
ACS Output Verbosity Level : acs_verbosity = 1
Floating point precision : precision = 16
Incremental indentation : add_indent = 2
We will have to try a few different time step accuracy parameters, to
get roughly the right relative energy conservation. This may take a few
repetitions. I'll start with constant time steps:
|gravity> kali nbody_cst1.rb -t 1 < test.in > tmpc.out
==> Constant Time Step Code <==
Integration method : method = hermite
Softening length : eps = 0.0
Time step size : dt = 0.001
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, after 1000 steps :
E_kin = 0.248 , E_pot = -0.613 , E_tot = -0.365
E_tot - E_init = -0.115
(E_tot - E_init) / E_init = 0.461
|gravity> kali nbody_cst1.rb -t 1 -c 0.0001 < test.in > tmpc.out
==> Constant Time Step Code <==
Integration method : method = hermite
Softening length : eps = 0.0
Time step size : dt = 0.0001
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, after 10000 steps :
E_kin = 0.313 , E_pot = -0.563 , E_tot = -0.25
E_tot - E_init = -6.62e-07
(E_tot - E_init) / E_init = 2.65e-06
A bit better than needed, but this will do. Now for shared time steps:
|gravity> kali nbody_sh1.rb -t 1 --exact_time < test.in > tmps.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
Force all outputs to occur at the exact times
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, after 1927 steps :
E_kin = 0.313 , E_pot = -0.563 , E_tot = -0.25
E_tot - E_init = -2.33e-10
(E_tot - E_init) / E_init = 9.32e-10
|gravity> kali nbody_sh1.rb -c 0.003 -t 1 --exact_time < test.in > tmps.out
==> Shared Time Step Code <==
Integration method : method = hermite
Parameter to determine time step size: dt_param = 0.003
Interval between diagnostics output: dt_dia = 1.0
Time interval between snapshot output: dt_out = 1.0
Duration of the integration : t = 1.0
Force all outputs to occur at the exact times
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, after 6424 steps :
E_kin = 0.313 , E_pot = -0.563 , E_tot = -0.25
E_tot - E_init = -6.12e-13
(E_tot - E_init) / E_init = 2.45e-12
|gravity> kali nbody_sh1.rb -c 0.002 -t 1 --exact_time < test.in > tmps.out
==> Shared Time Step Code <==
Integration method : method = hermite
Parameter to determine time step size: dt_param = 0.002
Interval between diagnostics output: dt_dia = 1.0
Time interval between snapshot output: dt_out = 1.0
Duration of the integration : t = 1.0
Force all outputs to occur at the exact times
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, after 9635 steps :
E_kin = 0.313 , E_pot = -0.563 , E_tot = -0.25
E_tot - E_init = -1.24e-13
(E_tot - E_init) / E_init = 4.96e-13
Okay, that one's below our
threshold too. Now
for individual time steps:
|gravity> kali nbody_ind1.rb -t 1 < test.in > tmpi.out
==> Individual Time Step Hermite Code <==
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, after 4257 steps :
E_kin = 0.313 , E_pot = -0.563 , E_tot = -0.25
E_tot - E_init = 7.24e-10
(E_tot - E_init) / E_init = -2.9e-09
|gravity> kali nbody_ind1.rb -c 0.002 -t 1 < test.in > tmpi.out
==> Individual Time Step Hermite Code <==
Parameter to determine time step size: dt_param = 0.002
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, after 21282 steps :
E_kin = 0.313 , E_pot = -0.563 , E_tot = -0.25
E_tot - E_init = -9.77e-13
(E_tot - E_init) / E_init = 3.91e-12
Perfect, just on the mark.
Alice: And now let's check whether the results are really similar:
|gravity> cat tmpc.out tmps.out | kali nbody_diff.rb
==> 6N-dimensional phase space distance between two N-body systems <==
Floating point precision : precision = 2
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: 6.8757897588114396e-06
|gravity> cat tmps.out tmpi.out | kali nbody_diff.rb
==> 6N-dimensional phase space distance between two N-body systems <==
Floating point precision : precision = 2
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: 3.5201108698382295e-11
Bob: There are larger than I would have expected. Especially the constant
time step run is off by an amount that is two orders of magnitude larger
than the relative energy conservation.
Alice: Yes, that is a bit much. The good news is that the shared time step
code and the individual time step code give results that correspond to about
. That may not be so bad; there is no guarantee that
the phase space distance should give the same result as the energy error.
Bob: Let me run the constant time step code with a two times smaller
time step size. That should increase the accuracy by more than an order
of magnitude, bringing all three codes more in line:
|gravity> kali nbody_cst1.rb -t 1 -c 0.00005 < test.in > tmpc.out
==> Constant Time Step Code <==
Integration method : method = hermite
Softening length : eps = 0.0
Time step size : dt = 5.0e-05
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, after 20000 steps :
E_kin = 0.313 , E_pot = -0.563 , E_tot = -0.25
E_tot - E_init = -1.35e-08
(E_tot - E_init) / E_init = 5.4e-08
And let's now compare all three pairs:
|gravity> cat tmpc.out tmps.out | kali nbody_diff.rb
==> 6N-dimensional phase space distance between two N-body systems <==
Floating point precision : precision = 2
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: 3.5758322798815124e-07
|gravity> cat tmpc.out tmpi.out | kali nbody_diff.rb
==> 6N-dimensional phase space distance between two N-body systems <==
Floating point precision : precision = 2
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: 3.5757721030515277e-07
|gravity> cat tmps.out tmpi.out | kali nbody_diff.rb
==> 6N-dimensional phase space distance between two N-body systems <==
Floating point precision : precision = 2
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: 3.5201108698382295e-11
Alice: Now they are indeed all comparable. Good! I am beginning to believe
that we may have done the right thing.