Numerical model of the Solar System
A Solar System Numerical Model
A Law of Motion for Entities in a Solar System Numerical Model
The solar system may be modeled numerically using both Newton's Law of Gravitation and Newton's Second Law of Motion.
Newton's Universal Law of Gravitation states that if a test mass m resides at a coordinate vector , then the gravitational force acting on the test mass, due to another mass that is present is:
is the gravitation constant.
is the mass of an entity i. For purposes of modeling a solar system, it is assumed to be a mass that is large enough to make a difference in the motion of test mass m. It could be a star, a planet, a moon, a large asteroid, or maybe even a large comet. A small rock or a spacecraft would not be massive enough.
is the coordinate vector of entity i.
is the gravitational force acting on mass m.
In a solar system, there will be many entities i. Therefore, the total gravitational force acting on test mass m will be the sum of the forces for each i, over all n forces that are present:
Here we have changed the definition of to mean the total gravitational force due to all entities i.
is the total gravitational force acting on mass m.
Newton's Second Law of Motion states that if a net force of acts on a test mass m, that the test mass will undergo an acceleration such that all three quantities are related by:
These two laws have the common left-hand-side . They may therefore be combined. When this is done and when the resulting equation is divided through by the common factor m, an equation of motion for test mass m results:
At this point the concept of a test mass m is dispensed with. In order to model a solar system, each of the entities j of mass , in turn, take the place of the test mass. The coordinate vector of the test mass therefore becomes the coordinate vector of entity j, and the summation is done over all other entities i except for the case where i equals j itself.
where obviously both i and j run from 1 to n.
The above equation is written in vector form. In order to have a set of formulas that is useful, the vector equation must be split into its three vector component equations.
where
At this point we have an equation of motion for all entities j in the solar system to be modeled.
Reduced Units
The mks system of units consists of three basic units for the three basic mechanical scalars. Length is in meters [m], mass is in kilograms [kg], and time is in seconds [s].
This would be a terribly awkward system of units for modeling a solar system. A far more convenient system of units would be: length in astronomical units [ AU ], mass in Terran masses [mTerran], and time in days [d].
An astronomical unit [AU] is the mean distance from the center of the Earth to the center of the Sun, over the course of any given recent year. In this system of units, the Earth could be given an initial coordinate of, say, (x = 1.0, y = 0.0). A planet that is toward the outer edge of the solar system, such as Pluto, could be given an initial coordinate of, say, (x = 40.0, y = 0.0). The magnitude of the distances that occur in a solar system model is quite manageable in this system of units.
A Terran mass [mTerran] is simply the mass of the Earth. In this system of units, the Earth would have a mass of (m = 1.0). A large planet, (the gas giant Jupiter being an example of such), could have a mass of, say (m = 300.0). A star, (our Sun being an example of such), could have a mass of, say, (m = 300,000.0) The magnitude of masses that occur in a solar system model is quite intuitive in this system of units. It is fairly easy to picture that another planet could have, say 10 times, or 1000 times the mass of the Earth, and that a star could have, say 1 million times the mass of the Earth.
A mean solar day of Earth [d] is a familiar unit that is easy to picture. It takes our Earth a year made up of 364.24 means solar days to orbit 360 degrees around our Sun. If a planet at the outer edge of the solar system took, say, 200.0 years to orbit around the Sun, then this would be an interval of time that could be easily pictured, and easily converted to days. The magnitude of the time intervals that occur in a solar system model is both manageable and intuitive in this system of units.
For reference, the conversion between the MKS system, and our AU-mTerran-d system, is given below:
1.0 AU = 149.5985 x 10^9 m 1.0 mTerran = 5.977 x 10^24 kg 1.0 d = 60. * 60. * 24. s = 86,400.0 s
The Universal Constant of Gravitation, G is, in MKS units:
G = 6.673 x 10^-11 m^3 kg^-1 s^-2
If we are going to go ahead and use our AU-mTerran-d system of units, then we must convert this constant to that system of units and use the converted constant in our numerical model of the solar system. Let us call this converted constant 'g'.
g = 6.673 x 10^-11 (m^3 kg^-1 s^-2) (149.5985 x 10^9 m/AU)^-3 (5.977 x 10^24 kg/mTerran)^+1 (86,400.0 s/d)^+2
= (6.673 x 10^-11) (149.5985 x 10^9)^-3 (5.977 x 10^24)^+1 (86,400.0)^-2 AU^3 mTerran^-1 d^-2
= 1.595 861 x 10^-29 AU^3 mTerran^-1 d^-2
It is this converted constant g that will be used in the code. The converted constant g may appear to be a less convenient number than the original constant G. However, the more convenient value for G appears in one of the input files, and the awkward conversion to g is done automatically in the code.
The initial velocities of the solar system entities are given in units of [km/s]. However, users who have become used to our AU-mTerran-d system may wish to assign velocities in units of [AU/d]. The conversion factors are:
1.0 AU / d = 1731.464 120 km / s 1.0 km / s = 0.000 577 459 AU / d
The code expects the initial velocities to be in units of [km/s]. The code was written this way for the reason that users may wish to generalize it so that the trajectories of spacecraft through the solar system may be calculated. Spacecraft using conventional chemical rocket fuels function by applying an engine burn in order to attain a change in velocity (a delta-v) in any given direction. The distance over which the spacecraft travels while a given engine burn is applied, is negligible compared to the distance scale of the solar system through which it will travel. Therefore a given delta-v may be considered to occur instantaneously. A delta-v is typically in units of [km/s]. Therefore while distances are often given in [AU], and time intervals in [d], velocities are often given in [km/s].
Now that we have both a set of equations of motion and a convenient system of units, we next need an algorithm for computing the coordinates of the solar system entities, as time passes.
A Time-Stepping Algorithm
The next step is to come up with an algorithm in which the coordinates may be calculated as time passes.
We start with the definitions for velocity and acceleration:
If instead of an infinitesimal time step we consider a finite time step , then we obtain definitions for the average velocity and acceleration over the time interval
or
Splitting these vector equations into the vector component equations:
or:
Next we need an algorithm for stepping the coordinates (x, y, z)_j through time. Let us consider just coordinate x for just one entity, and let us consider the following algorithm:
input t_f, (delta)t (We need input values for the time step size (delta)t and the final time t_f) t = 0. (We start the time at zero) x = x_0 (We set the coordinate x to its initial value) v = v_0 (We set the velocity v to its initial value) a = f(x) (The acceleration is a function of x and we calculate it here) (3.) output t, x loop until (t = t_f) | t = t + (delta)t (We advance the time) | x = x + v * (delta)t (We advance the coordinate) (1.) | v = v + a * (delta)t (We advance the velocity) (2.) | a = f(x) (We calculate the new acceleration as a function of x) (3.) | output t, x
This algorithm is called the Euler Algorithm. It is the most basic time stepping algorithm that can be used to solve a point particle classical mechanics problem. The Euler Algorithm, however, has problems. The formulas (1.) and (2.) are based on the definitions given earlier of average velocity and average acceleration over a finite time interval, and yet it uses velocitites and accelerations that occur at the beginning of the time interval.
A better algorithm is to use velocities and accelerations that occur in the middle of the time intervals. This is quite simply accomplished. We start by advancing the velocity by only a half step rather than a full step. From that point on, we advance the coordinate and the velocity by a full step, except that in this algorithm, the velocity that is used to advance the coordinate, occurs in the middle of the coordinate time step, and the acceleration that is used to advance the velocity, occurs in the middle of the velocity time step.
input t_f, (delta)t (We need input values for the time step size (delta)t and the final time t_f) t = 0. (We start the time at zero) x = x_0 (We set the coordinate x to its initial value) a = f(x) (The acceleration is a function of x and we calculate it here) (3.) v = v_0 (We set the velocity v to its initial value) output t, x v = v + a * (delta)t/2. (We advance the velocity by half a time step) loop until (t = t_f) | t = t + (delta)t (We advance the time) | x = x + v * (delta)t (We advance the coordinate by a full time step) (1.) | a = f(x) (We calculate the new acceleration as a function of x) (3.) | v = v + a * (delta)t (We advance the velocity by a full time step) (2.) | output t, x
This algorithm is called the Feynman Algorithm, or the Verlet Algorithm.
We now have all the tools we need to construct a numerical model of the solar system. We have an equation of motion for all the solar system entities j, which provides us with the acceleration of all the solar system entities j at any given instant. We also have a time stepping algorithm which uses this acceleration information for a given entity to step its coordinates and velocity through time.
A Working Code
The following code constitutes such a numerical model. The code is written in fortran 77. It reads an input file]] containing start-up information for a solar system, and writes an output file that contains the coordinates of each solar system entity, at each time step in the simulation, from an initial time of zero, up until the final time.
program solarV2f implicit none c call readConsts() call readSystem() call moveSystem() c stop end c subroutine readConsts() implicit none c double precision rAu, mTerran, g, deltaT, tF double precision tDay common /fundConsts/ rAu, mTerran, g, deltaT, tF, tDay c integer nin, nout, nlog parameter(nin=1, nout=2, nlog=3) c open(nin, file='const.dat', status='old') read(nin, *) rAu read(nin, *) mTerran read(nin, *) g read(nin, *) deltaT read(nin, *) tF close(nin) c tDay = 60. * 60. * 24. g = g * mTerran * tDay * tDay / (rAu * rAu * rAu) c return end c subroutine readSystem() implicit none c double precision PI parameter(PI=3.141592) c double precision rAu, mTerran, g, deltaT, tF double precision tDay common /fundConsts/ rAu, mTerran, g, deltaT, tF, tDay c integer nMax, n parameter(nMax = 20) character*20 name(nMax) double precision mass(nMax) double precision rx(nMax), ry(nMax), rz(nMax) double precision vOldx(nMax), vOldy(nMax), vOldz(nMax) double precision vAvex(nMax), vAvey(nMax), vAvez(nMax) common /size/ n common /system/ name, mass, rx, ry, rz, & vOldx, vOldy, vOldz, vAvex, vAvey, vAvez c double precision r, theta, phi double precision vr, vtheta, vphi double precision vx(nMax), vy(nMax), vz(nMax) integer i c integer nin, nout, nlog parameter(nin=1, nout=2, nlog=3) c open(nin, file='solar.dat', status='old') read(nin, *) n do i = 1, n read(nin, 10) name(i) read(nin, *) mass(i) read(nin, *) r, theta, phi theta = theta * (PI/180.) phi = phi * (PI/180.) rx(i) = r * sin(theta) * cos(phi) ry(i) = r * sin(theta) * sin(phi) rz(i) = r * cos(theta) c read(nin, *) vr, vtheta, vphi vx(i) = vr * sin(theta) * cos(phi) & + vtheta * cos(theta) * cos(phi) & - vphi * sin(phi) vy(i) = vr * sin(theta) * sin(phi) & + vtheta * cos(theta) * sin(phi) & + vphi * cos(phi) vz(i) = vr * cos(theta) & - vtheta * sin(theta) c vx(i) = (tDay * 1000. / rAu) * vx(i) vy(i) = (tDay * 1000. / rAu) * vy(i) vz(i) = (tDay * 1000. / rAu) * vz(i) c vOldx(i) = vx(i) vOldy(i) = vy(i) vOldz(i) = vz(i) c vAvex(i) = vx(i) vAvey(i) = vy(i) vAvez(i) = vz(i) c enddo close(nin) return 10 format(a20) end c subroutine moveSystem implicit none c double precision rAu, mTerran, g, deltaT, tF double precision tDay common /fundConsts/ rAu, mTerran, g, deltaT, tF, tDay c integer nMax, n parameter(nMax = 20) character*20 name(nMax) double precision mass(nMax) double precision rx(nMax), ry(nMax), rz(nMax) double precision vOldx(nMax), vOldy(nMax), vOldz(nMax) double precision vAvex(nMax), vAvey(nMax), vAvez(nMax) common /size/ n common /system/ name, mass, rx, ry, rz, & vOldx, vOldy, vOldz, vAvex, vAvey, vAvez c integer i double precision t double precision vNewx, vNewy, vNewz double precision ax, ay, az c integer nin, nout, nlog parameter(nin=1, nout=2, nlog=3) c open(nout, file='coords.dat', status='unknown') c c Start at time zero c t = 0. call writeSystem(t) c c Perform initial half-step c do i = 1, n call accelMass(i, g, ax, ay, az) vOldx(i) = vOldx(i) + (deltaT * ax) / 2. vOldy(i) = vOldy(i) + (deltaT * ay) / 2. vOldz(i) = vOldz(i) + (deltaT * az) / 2. enddo c c Perform time steps c do while (t < tF) t = t + deltaT do i = 1, n rx(i) = rx(i) + (deltaT * vOldx(i)) ry(i) = ry(i) + (deltaT * vOldy(i)) rz(i) = rz(i) + (deltaT * vOldz(i)) enddo do i = 1, n call accelMass(i, g, ax, ay, az) vNewx = vOldx(i) + (deltaT * ax) vNewy = vOldy(i) + (deltaT * ay) vNewz = vOldz(i) + (deltaT * az) vAvex(i) = (vOldx(i) + vNewx) / 2. vAvey(i) = (vOldy(i) + vNewy) / 2. vAvez(i) = (vOldz(i) + vNewz) / 2. vOldx(i) = vNewx vOldy(i) = vNewy vOldz(i) = vNewz enddo call writeSystem(t) enddo c c Calculations are done c close(nout) return end c subroutine accelMass(i, g, ax, ay, az) implicit none c integer i double precision g double precision ax, ay, az c integer nMax, n parameter(nMax = 20) character*20 name(nMax) double precision mass(nMax) double precision rx(nMax), ry(nMax), rz(nMax) double precision vOldx(nMax), vOldy(nMax), vOldz(nMax) double precision vAvex(nMax), vAvey(nMax), vAvez(nMax) common /size/ n common /system/ name, mass, rx, ry, rz, & vOldx, vOldy, vOldz, vAvex, vAvey, vAvez c integer j double precision rsx, rsy, rsz double precision rox, roy, roz double precision rosx, rosy, rosz double precision ms double precision r2, r, r3 c c Initialize the acceleration c ax = 0. ay = 0. az = 0. c c Set the coordinates of the observer mass c rox = rx(i) roy = ry(i) roz = rz(i) c c Loop over all other masses c do j = 1, n if (j .ne. i) then ms = mass(j) c rsx = rx(j) rsy = ry(j) rsz = rz(j) c rosx = rsx - rox rosy = rsy - roy rosz = rsz - roz c r2 = rosx*rosx + rosy*rosy + rosz*rosz r = dsqrt(r2) r3 = r * r * r c ax = ax + g * ms * rosx / r3 ay = ay + g * ms * rosy / r3 az = az + g * ms * rosz / r3 endif enddo c return end c subroutine writeSystem(t) implicit none c double precision t c integer nMax, n parameter(nMax = 20) character*20 name(nMax) double precision mass(nMax) double precision rx(nMax), ry(nMax), rz(nMax) double precision vOldx(nMax), vOldy(nMax), vOldz(nMax) double precision vAvex(nMax), vAvey(nMax), vAvez(nMax) common /size/ n common /system/ name, mass, rx, ry, rz, & vOldx, vOldy, vOldz, vAvex, vAvey, vAvez c integer i c integer nin, nout, nlog parameter(nin=1, nout=2, nlog=3) c c Write the time c write(nout,200) t c c Write the number of masses in this time frame c write(nout,100) n c c Loop over all the masses and write the coordinates of each one c do i = 1, n write(nout,300) rx(i), ry(i), rz(i) enddo c return 100 format(I4) 200 format(F12.6) 300 format(F12.6,4X,F12.6,4X,F12.6) end c
The following file contains the physical constants that the numerical model requires, as well as the time information.
149.5985e09 5.977e24 6.673e-11 1. 1000.
The file is in the form of:
[1.0 AU, in m] [1.0 mTerran, in kg] [G, in m^3 kg^-1 s^-2] [Time step, in d] [Total time interval of simulation, in d]
The next file contains contains the information for a simplified solar system.
3 Sun 332943 0.031254 90. 180. 0. 0. 0.079 Jupiter 2000 5.203 88.694 0. 0. 0. 13.07 Earth 1. 1. 90. 0. 0. 0. 29.78
The file is in the form of:
[Number of solar system entities] [Name of solar system entity 1] [Mass in mTerran] [Initial Radius from center, in AU] [Initial Theta, in degrees] [Initial Phi, in degrees] [Initial Radius-direction velocity, in km/s] [Initial Theta-direction velocity, in km/s] [Initial Phi-direction velocity, in km/s]
The time info in the first file, and the solar system info in the second file, may be modified.
This article is intended to explain the physical theory that is required to numerically simulate solar system dynamics using Newton's Law of Gravitation, and Newton's Second Law of Motion, and to provide a simple code that serves as an example of how the theory may be coded. No attempt has been made here to graphically display or animate the motion of the solar system entities.
Users may wish to develop more elaborate codes that will do this. They may wish to use the code provided here as the 'physics engine' in such a code.
Readers may note that the code performs some complicated coordinate system conversion calculations, particularly in the calculation of the initial velocity components. These calculations are described in a separate article, on a transformation from spherical coordinates to rectangular coordinates.