We already had a function to search for the next time a body
reaches a certain hour angle. But we didn't have a function
to ask what the current hour angle of a body is.
This will resolve that problem, which will also answer
questions about true solar time: use the Sun as the body,
and add 12 to the hour angle, modulo 24.
Pylint discovered that I was raising Exception,
which was overly general. I didn't mean to do that;
it was supposed to be my custom exception type
astronomy.Error instead. So I fixed that case.
There were also some deprecated settings in the
pylint configuration file, so I fixed those too.
The documentation was missing a mention of
the `time` parameter in the following TypeScript
functions:
* `Rotation_ECT_EQD`
* `Rotation_EQD_ECT`
Likewise, the `time` parameter was not documented in
the corresponding Kotlin functions:
* `rotationEctEqd`
* `rotationEqdEct`
These mistakes have been corrected.
Now the C function Astronomy_Ecliptic returns ecliptic
coordinates in true equinox of date instead of the
J2000 mean equinox. I'm doing this because it is a
better fit for physical phenomena that ecliptic
coordinates are often used for. For example, lunar nodes,
eclipses, phase angles, and oppositions make more sense
with true latitude and longitude of date.
I will port these changes to the other languages also.
More work standardizing the nomenclature of the
orientation systems across all language documents.
Added C functions to calculate rotation matrices
for EQJ/ECT and ECT/EQJ.
I'm taking gcc 12.2 for a test drive today.
It reports a few warnings that slipped through earlier versions.
None of the warnings concern me for actual code safety,
but I went ahead and resolved them to keep the build clean.
Also provide a hook for a CPP environment variable to override
the C++ compiler to use, instead of forcing g++.
Somehow gcc didn't warn me that a `void` function
was trying to return a `void` value. It makes sense
from a functional language "unit type" perspective,
but it wasn't intentional, and it is weird. Fixed it.
Added EclipticGeoMoon as output to the temp/*_check.txt files as 'm' lines.
This ensures that all the languages calculate nearly identical values.
Optimized EclipticGeoMoon a little more by eliminating a redundant
call to mean_obliq.
Updated the C function Astronomy_EclipticGeoMoon to
correct ecliptic coordinates for nutation.
This means that the returned value is expressed in
true equinox of date instead of mean equinox of date.
This results in the moon_ecm test decreasing the max
longitude error from 24 arcseconds to 6 arcseconds.
EclipticGeoMoon is now about 40% slower, but it still
runs in about 0.4 microseconds per call.
I bootstrapped based on the pretty good optimizations that
codegen did for the Python version of the (now truncated)
IAU2000B nutation formula. I will do the same for the other
nutation formulas.
While trying to convert ecliptic coordinates from mean
equinox of date to true equinox of date, I ran into excessive
overhead from the IAU2000B nutation model. The fact that it
uses 77 trigonometric terms made the calculations a lot slower.
https://apps.dtic.mil/sti/pdfs/AD1112517.pdf
Page 4 in the above document mentions a shorter series
“NOD version 2” that has 13 terms instead of 77 as used in IAU2000B.
I had not noticed NOD2 before, because it appears only in
the FORTRAN version of NOVAS 3.x, not the C version.
After reading the FORTRAN code, I realized NOD2 is the same
as IAU2000B, only it keeps the first 13 of 77 terms.
The terms are already arranged in descending order of
significance, so it is easy to truncate the series.
Based on this discovery, I realized I could achieve all of
the required accuracy needed for Astronomy Engine by
keeping only the first 5 terms of the nutation series.
This tremendously speeds up nutation calculations while
sacrificing only a couple of arcseconds of accuracy.
It also makes the minified JavaScript code smaller:
Before: 119500 bytes.
After: 116653 bytes.
So that's what I did here. Most of the work was updating
unit tests for accepting slightly different calculation
results.
The nutation formula change did trigger detection of a
lurking bug in the inverse_terra functions, which convert
a geocentric vector into latitude, longitude, and elevation
(i.e. an Observer object). The Newton's Method loop in
this function was not always converging, resulting in
an infinite loop. I fixed that by increasing the
convergence threshold and throwing an exception
if the loop iterates more than 10 times.
I also fixed a couple of bugs in the `demotest` scripts.
Modified the code generator and source templates to allow
using fewer than 77 terms from the IAU2000B nutation model.
The number of terms causes calculations to be far slower than
I would like, plus most of these terms provide far less than
one arcsecond of difference in the output.
I want to experiment with truncated versions of the series.
https://apps.dtic.mil/sti/pdfs/AD1112517.pdf
Page 4 in the above document references a shorter series
"NOD version 2" that has only 13 terms instead of 77 as used in IAU2000B.
I found that code and confirmed the 13 terms are the first 13
consecutive terms from the original 77.
This commit does not change the number of terms calculated;
it only enables doing so by changing a single #define in
generate/codegen.c.
Once I change the nutation model, I'm sure there will be multiple
tweaks to unit tests to get everything working again.
Astronomy_SphereFromVector was not checking its vector
argument for having a bad status. Now it does.
Added comments that clarify exactly what nutation and precession
functions do.
The documentation for SearchRiseSet and SearchAltitude needed
clarification about refraction and the part of the body solved
for (center versus limb). The JavaScript version was especially
lacking compared to documentation for the other languages.
Also documented SearchAltitude's limitations; it does not
work at or near maximum/minimum altitude.
Mention that user-defined stars are allowed for
SearchRiseSet, SearchAltitude, and SearchHourAngle.
Fixed a couple places where the Kotlin documentation had
broken links to other functions.
I had a copy-n-paste typo in the `dec` parameters
for all of the DefineStar functions. Fixed it.
The TypeScript version of HelioState did not handle
user-defined stars. Added support there.
Because we instantly know the heliocentric
distance of a user-defined star, there is no
need to convert it into a vector and then take
the length of the vector.
All of the HelioDistance functions now return
the distance directly, as an optimization.
Also, I decided it didn't make sense to have a
default definition for user-defined stars.
If the caller doesn't define a star, it should
be treated as an invalid body.
Added Python support for user-defined stars.
Defined new StateVector methods: Position and Velocity.
Defined division operator: Vector / float.
Bumped version number to 2.1.12.