I was using a UT calculation where I should have used TT.
All of the JPL Horizons state vector input files are
expressed in TT. I found I was a few microseconds off,
which has no measurable effect, but I thought I would
do the time calculations the absolutely correct way.
I have decided the ability to select different
collections of gravitating bodies causes far
more complexity in the code than it is worth.
So now the gravity simulator always calculates
the Sun and all planets except Pluto.
This greatly simplifies the core code, gets
a good balance between efficiency and accuracy,
and makes the test matrix much simpler.
The GravSimOriginState function was doing too
much work for bodies that weren't already calculated
and cached. Instead of always calling Astronomy_BaryState,
it is possible to do a lot less work for most bodies
by recycling the SSB calculation that has already
been done.
Other minor code cleanup -- mostly stuff that makes
the code easier to read and understand.
Now testing all 4 major asteroids:
Ceres, Pallas, Vesta, Juno.
Test all 3 simulation options.
Interestingly, it doesn't seem to matter much
whether I include the 4 inner planets or not.
I guess they are too small and too far away
from the asteroid belt.
Asteroids are probably difficult to calculate accurately
over long time spans, so I generated replacement
test data from JPL Horizons. Instead of trying to
cover the years 1800..2200, I cover the much smaller
range 2020..2040.
C GravSimFile(0 : barystate/Ceres.txt ): PASS (max_rdiff = 4.347e-04, max_vdiff = 1.733e-06)
C GravSimFile(0 : barystate/Pallas.txt): PASS (max_rdiff = 2.826e-04, max_vdiff = 1.263e-06)
C GravSimFile(0 : barystate/Vesta.txt ): PASS (max_rdiff = 5.201e-04, max_vdiff = 2.703e-06)
C GravSimFile(0 : barystate/Juno.txt ): PASS (max_rdiff = 2.162e-04, max_vdiff = 1.063e-06)
C GravSimFile(1 : barystate/Ceres.txt ): PASS (max_rdiff = 4.347e-04, max_vdiff = 1.733e-06)
C GravSimFile(1 : barystate/Pallas.txt): PASS (max_rdiff = 2.826e-04, max_vdiff = 1.263e-06)
C GravSimFile(1 : barystate/Vesta.txt ): PASS (max_rdiff = 5.201e-04, max_vdiff = 2.703e-06)
C GravSimFile(1 : barystate/Juno.txt ): PASS (max_rdiff = 2.162e-04, max_vdiff = 1.063e-06)
C GravSimFile(2 : barystate/Ceres.txt ): PASS (max_rdiff = 4.347e-04, max_vdiff = 1.733e-06)
C GravSimFile(2 : barystate/Pallas.txt): PASS (max_rdiff = 2.826e-04, max_vdiff = 1.263e-06)
C GravSimFile(2 : barystate/Vesta.txt ): PASS (max_rdiff = 5.201e-04, max_vdiff = 2.703e-06)
C GravSimFile(2 : barystate/Juno.txt ): PASS (max_rdiff = 2.162e-04, max_vdiff = 1.063e-06)
C GravitySimulatorTest: PASS
Starting implementation of a generalized gravity simulator.
Already calculating the movement of Ceres, but with less
accuracy than I had hoped. I don't know if the lack of modeling
pull of the other asteroids has a larger effect than I expected,
or there is just something wrong with the implementation.
I'm preparing to create a generalized gravity simulator
for small bodies moving through the Solar System
under the influence of the Sun and planets.
Adding JPL Horizons data for 1 comet and 5 asteroids:
Comet 1P/Halley
Ceres
Juno
Pallas
Vesta
101955 Bennu
Halley was chosen as an object with a highly eccentric orbit.
Bennu was chosen as a member of the inner solar system, where
Earth and Mars are likely to have strong effects.
The remaining 4 major asteroids were chosen as typical members
of the asteroid belt between Mars and Jupiter.
Added the following iterator functions that wrap
search/next pairs of functions:
GlobalSolarEclipsesAfter
LocalSolarEclipsesAfter
LunarApsidesAfter
LunarEclipsesAfter
MoonNodesAfter
MoonQuartersAfter
PlanetApsidesAfter
TransitsAfter
I updated the following C# demos:
moonphase.cs ==> MoonQuartersAfter
lunar_eclipse.cs ==> LunarEclipsesAfter
Fixed an issue in the C# Markdown generator
so that it can now handle generic types like
`IEnumerable<MoonQuarterInfo>`.
Added the following iterator functions that wrap
search/next pairs of functions:
globalSolarEclipsesAfter
localSolarEclipsesAfter
lunarApsidesAfter
lunarEclipsesAfter
moonNodesAfter
moonQuartersAfter
planetApsidesAfter
transitsAfter
I updated the following Kotlin demos:
MoonPhase.kt ==> moonQuartersAfter
LunarEclipse.kt ==> lunarEclipsesAfter
However, I have not yet figured out how to use these
functions in the corresponding Java demos.
It makes more sense to report Jupiter's moons with
individually named structure fields rather than an array.
It reduces the overall code and documentation size,
and outside of unit testing, there are few cases
where iterating over an array of moons is more
lucid than using the names of the moons.
This is a breaking change, but hopefully very few
developers are using this function yet.
Fixing the breakage is very simple.
It makes more sense to report Jupiter's moons with
individually named structure fields rather than an array.
It reduces the overall code and documentation size,
and outside of unit testing, there are few cases
where iterating over an array of moons is more
lucid than using the names of the moons.
This is a breaking change, but hopefully very few
developers are using this function yet.
Fixing the breakage is very simple.
Also added operator overloads for adding and
subtracting StateVector, just like we already had
for Vector.
It makes more sense to report Jupiter's moons with
individually named structure fields rather than an array.
It reduces the overall code and documentation size,
and outside of unit testing, there are few cases
where iterating over an array of moons is more
lucid than using the names of the moons.
This is a breaking change, but hopefully very few
developers are using this function yet.
Fixing the breakage is very simple.
It makes more sense to report Jupiter's moons with
individually named structure fields rather than an array.
It reduces the overall code and documentation size,
and outside of unit testing, there are few cases
where iterating over an array of moons is more
lucid than using the names of the moons.
This is a breaking change, but hopefully very few
developers are using this function yet.
Fixing the breakage is very simple.
It makes more sense to report Jupiter's moons with
individually named structure fields rather than an array.
It reduces the overall code and documentation size,
and outside of unit testing, there are few cases
where iterating over an array of moons is more
lucid than using the names of the moons.
This is a breaking change, but hopefully very few
developers are using this function yet.
Fixing the breakage is very simple.
Added Kotlin and Java demos for calculating Jupiter's moons.
Illustrates correcting for light travel time.
I added named getters for the 4 moons in `JupiterMoonsInfo`,
because in Java it was really ugly to write
`jm.getMoon()[0]`, etc.
I had to add a new method `Vector.withTime` to work around
the error checking that throws an exception if vectors
from different times are added.
Also made Kotlin constants public:
MINUTES_PER_DAY
SECONDS_PER_DAY
MILLISECONDS_PER_DAY
Deleted the do-nothing placeholders for installing
the Kotlin Native compiler. We are not going to support
Kotlin Native for now.
Removed redundant installation of pylint from the
Windows commit_hook.bat.
Other batch file cleanup, now that I know "||" works in Windows.
I refactored the unit tests for all the demo programs
to follow a different pattern that makes it simpler
to add more demo tests in the future.
The main thing is that correct output and generated
output are now in separate directories `correct` and `test`.
I have moved the test scripts from `test/test` to `./demotest`
in all the langauge demo directories.
This makes it simpler to clean up any stale generated
files before each test run by `rm -f test/*.txt`.
I stumbled across this while making the Java demo tests,
and it was a better solution, so now all the other languages
are consistent with the Java demo tests.
In the C demo tests, I also decided to compile all the
binary executables into a subdirectory `bin` that can
be cleaned out before each run, to make sure there are
no stale executables from an earlier run.
Direct use of arrayOf can be a bit more efficient than calling map and toTypedArray.
It could be faster if JupiterMoonsInfo was holding a list but better to use direct
typed array initializer for more efficiency.
Used IntelliJ IDEA's linter to perform code cleanup.
There were unused variables, `var` that could be replaced with `val`,
and other minor code style issues.
While doing this, I also discovered that a lot of documentation
links were broken. The fix is to stop intenting the text after
a `@param`.
When documentation refers to a Body value, e.g. Body.Earth,
link to its information page. I'm not sure this is super helpful,
but it is an attempt to provide better linking.
Added more explanatory text about the SSB and EMB values.
I found that a blank line splits the extra text onto the
dedicated pages for SSB and EMB, while leaving the "brief"
description on the list of all Body enum values. That is nice.
I found that there were a bunch of lingering 'jvm'
tags in the generated markdown documentation.
Got rid of them with another change to format_kotlin_doc.py.
I missed a couple of places where I want to remove
private constructor calls from enum members.
Also, discard [name] and [ordinal] links while preserving
other properties that are intentionally exposed.
I reported an issue to Dokka about enum members
being listed backwards in the generated markdown:
https://github.com/Kotlin/dokka/issues/2466
In the meantime, this is a workaround where I reverse the order
of the enum members in my own script format_kotlin_doc.py.
This is a workaround for a Dokka GFM issue I reported:
https://github.com/Kotlin/dokka/issues/2468
I updated the format_kotlin_doc.py script to
remove the internal constructor calls for members of the Body enum.
The dokkaGfm tool has a few oddities I don't like.
I updated my format_kotlin_doc.py script to work around
a couple of them:
1. Strip out all the noisy [jvm] tags it puts everywhere.
2. Remove the unhelpful and incorrect `Properties` sections
it adds to all my enum classes and enum members.
I will come back and address other issues later.
The sha256sum and md5sum utilities are available by
default on Linux, but not Windows or Mac OS.
I created the script `checksum.py` that can perform
sha256 and md5 checksum verification on all 3 systems.
Got rid of the ugly checksum.bat I was using on Windows.
Deleted the md5 checksum files, since I only need sha256
for now.
Before this change, I was always skipping verification
of downloads on Mac systems.
Added functions:
searchPlanetApsis
nextPlanetApsis
I discovered that I had an unnecessary special relaxation
of apsis error tolerance for Pluto. It turns out that currently
0.1 degrees of orbital rotation is enough for all the planets.
Search for times when the Moon ascends or descends
through the ecliptic plane. These are called
ascending and descending nodes. Added the functions:
searchMoonNode
nextMoonNode
Also corrected comments in the unit tests that
incorrectly stated nodes occur when the ecliptic
longitude is zero. They should have said the
ecliptic latitude is zero.
The existing lunar libration functions in the
other languages (C, C#, Python, JavaScript) were
calculating the Moon's ecliptic latitude and longitude
in radians, not degrees as intended. They have been fixed.
Implemented the libration function for Kotlin.
Calculate the position and velocity of any
of the five Lagrange points for a pair of
Solar System bodies. Added the functions:
lagrangePoint
lagrangePointFast