Previous | ToC | Up | Next |
Alice: In order to adapt your code mkplummer2.rb
to standard units, we have to change scales, both in position space
and in velocity space. Let us start with positions. In our old
system, we had a structural length
Let us call this quantity our scale factor.
In standard units, the virial radius
Bob: And this means that all distances have to be scaled this way,
since that is the definition of a scale factor after all. I'll copy
the previous code in a file called mkplummer3.rb, and add this
scaling. That will take only two lines. Here, right at the top of the
mkplummer method, I'm adding this line:
Then at the place where we initialize the positions for each body, we
have to divide by that scale factor, just as we had to divide the virial
radius by that factor:
Alice: That must be right. Now the velocity scaling is a bit more tricky.
How shall we approach that?
Bob: Velocities come into the kinetic energy. Since the masses of the
particles are not affected, the velocities must scale like the square root
of the energy.
Alice: Good point! The total mass of a cluster with
Bob: In other words, we have for the potential energy of the cluster
as a whole:
and
Since they must remain proportional to each other, with the virial factor
of two between them, we know that
Alice: That is an extremely sloppy notation, using
Bob: This means that I can add the following conversion factor to the
code, at the point where the velocities are calculated:
Alice: That must be correct, but let's make sure that we get the right
energy and the right quartiles again -- and this time in standard units.
Bob: Let's start with the quartiles:
Bob: Now let's see whether the energies come out standardized as well.
That should be easy to verify: in the standard units, the total energy
should be -1/4. Let's check:
Bob: There are a couple other features I'd like to add to the code:
a quiet start, and center-of-mass adjustment. Let's start with the
first one.
In my original code, each star is given a position in the star cluster
independently of all other stars. If you make a small star cluster,
it is possible that you wind up with a significant excess of stars, in
the core, say, or equally likely a significant lack of stars, there
or somewhere else.
I have found it helpful in some of my simulations to start in a more
quiet way, in which the stars are initially layered, each occupying a
position somewhere in their proper mass shell. In other words, you
divide the N-body system as an onion into N different concentric
shells, centered on the center of the cluster, and each having the
same amount of mass. You then sprinkle one star into each different
shell.
Alice: I'm not sure whether that really helps. After you let the
system evolve for a while, you will soon develop fluctuations that
obey Poissonian statistics. You won't keep your neat layering for
long. As a matter of fact, within a small fraction of the crossing
time, your particles will visit shells other than the ones they were
born in.
Bob: That is true, but even so, I like to start with a more orderly
bunch of stars. For one thing, the quartiles will come out better initially.
Alice: I'm still not convinced that it will help, but it won't hurt either.
Go right ahead!
Bob: I'll copy the previous version in a new file mkplummer4.rb
Now I have to be careful. Given me a minute. . . . . Ah, this should
do it. Here is the new version of the mkplummer method:
Alice: Can you point out what you changed?
Bob: There are only two places where I added something. Before entering
the nb.body.each loop, I define the inner mass shell -- in fact,
an inner mass sphere; the central layer is a sphere, and all the subsequent
ones are shells -- as follows:
Then, at the beginning of the loop, I pick a random value for the
cumulative mass within the constraint that the value for the
cumulative mass has to lie within the range present within the current
mass shell:
As soon as I have done that, I shift the boundaries of the mass shell up
by one shell, to make them ready for the next traversal of the loop:
The last difference is that the radius is now determined from the value
for the cumulative mass that I had just found, rather than from using the
random number generator here directly:
Alice: How about testing the new version?
Bob: The total energy should remain unchanged, still -1/4. Here it is:
Bob: I hope so! Let's try:
10. Two More Code Versions
10.1. Standard Units
. In that system,
the virial radius was:
.
This means that we have to divide the virial radius by the scale factor,
when we switch from the old units to standard units.
scalefactor = 16.0 / (3.0 * PI)
b.pos = spherical(radius) / scalefactor
stars
is unity, and each star therefore has a mass of
in
both systems, or old system of units, and the standard system of
units. It is only a change in the magnitude of their velocities that
can make up for a change in kinetic energy -- or in total or potential
energies, for that matter, since all these quantities are related.
And we know that the potential energy can only scale with the
distances, since
in both the old system and the new
one.
and
as arbitrary lengths and velocities, but I see what you
mean, and yes, obviously the square of the velocities transform inversely
proportional to the distances.
b.vel = spherical(velocity) * sqrt(scalefactor)
10.2. Checking Quartiles
|gravity> kali mkplummer3.rb -n 10000 | kali quartiles.rb
==> Plummer's Model Builder <==
Number of particles : N = 10000
pseudorandom number seed given : 0
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 : 259442867243987632366378221437785255631
The values of the three quartiles for r(M) are:
r(1/4) = 0.478
r(1/2) = 0.762
r(3/4) = 1.28
|gravity> kali mkplummer3.rb -n 10000 | kali quartiles.rb
==> Plummer's Model Builder <==
Number of particles : N = 10000
pseudorandom number seed given : 0
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 : 106794077952737035657087400769366713948
The values of the three quartiles for r(M) are:
r(1/4) = 0.4805
r(1/2) = 0.7715
r(3/4) = 1.266
|gravity> kali mkplummer3.rb -n 10000 | kali quartiles.rb
==> Plummer's Model Builder <==
Number of particles : N = 10000
pseudorandom number seed given : 0
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 : 96818168461728251751749907043384566601
The values of the three quartiles for r(M) are:
r(1/4) = 0.4772
r(1/2) = 0.7701
r(3/4) = 1.29
Alice: These are indeed what we had derived a bit earlier, in
eqs. (126) and (127):
10.3. Checking Energy
|gravity> kali mkplummer3.rb -n 1000 | kali energy.rb
==> Plummer's Model Builder <==
Number of particles : N = 1000
pseudorandom number seed given : 0
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 : 79118596476922924266900277323025514556
E_kin = 0.248 , E_pot = -0.488 , E_tot = -0.24
|gravity> kali mkplummer3.rb -n 1000 | kali energy.rb
==> Plummer's Model Builder <==
Number of particles : N = 1000
pseudorandom number seed given : 0
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 : 18939911909289684081959561570789443691
E_kin = 0.246 , E_pot = -0.492 , E_tot = -0.246
|gravity> kali mkplummer3.rb -n 1000 | kali energy.rb
==> Plummer's Model Builder <==
Number of particles : N = 1000
pseudorandom number seed given : 0
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 : 257729252563068529020018340246685814098
E_kin = 0.253 , E_pot = -0.482 , E_tot = -0.228
Alice: Just as it should be, within the expected statistical errors of a
few percent. Great! Now we can generate a truly
standard realization of Plummer's model.
10.4. Quiet Start
10.5. Quiet Indeed
cumulative_mass_min = 0
cumulative_mass_max = 1.0/n
cumulative_mass = frand(cumulative_mass_min, cumulative_mass_max)
cumulative_mass_min = cumulative_mass_max
cumulative_mass_max += 1.0/n
radius = 1.0 / sqrt( cumulative_mass ** (-2.0/3.0) - 1.0)
|gravity> kali mkplummer4.rb -n 1000 | kali energy.rb
==> Plummer's Model Builder <==
Number of particles : N = 1000
pseudorandom number seed given : 0
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 : 65204294661663778940336406294820512989
E_kin = 0.252 , E_pot = -0.499 , E_tot = -0.246
Alice: Fair enough. And your quartiles should come out wonderfully
accurate, even for, say, 100 particles, by construction.
|gravity> kali mkplummer4.rb -n 100 | kali quartiles.rb
==> Plummer's Model Builder <==
Number of particles : N = 100
pseudorandom number seed given : 0
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 : 290538234552319837019298862196807084315
The values of the three quartiles for r(M) are:
r(1/4) = 0.4762
r(1/2) = 0.7566
r(3/4) = 1.268
|gravity> kali mkplummer4.rb -n 100 | kali quartiles.rb
==> Plummer's Model Builder <==
Number of particles : N = 100
pseudorandom number seed given : 0
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 : 144809416188173600253986381061280801268
The values of the three quartiles for r(M) are:
r(1/4) = 0.4712
r(1/2) = 0.7675
r(3/4) = 1.258
|gravity> kali mkplummer4.rb -n 100 | kali quartiles.rb
==> Plummer's Model Builder <==
Number of particles : N = 100
pseudorandom number seed given : 0
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 : 46461356975499902229965866264015114536
The values of the three quartiles for r(M) are:
r(1/4) = 0.4722
r(1/2) = 0.7668
r(3/4) = 1.273
Indeed, as expected. And of course it will be even more accurate
for 10,000 particles:
|gravity> kali mkplummer4.rb -n 10000 | kali quartiles.rb
==> Plummer's Model Builder <==
Number of particles : N = 10000
pseudorandom number seed given : 0
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 : 206965737790539113565393631360305885539
The values of the three quartiles for r(M) are:
r(1/4) = 0.4777
r(1/2) = 0.7685
r(3/4) = 1.281
Alice: Quiet indeed. You have managed to shove the statistical noise
under the rug.
Previous | ToC | Up | Next |