Commit Graph

1235 Commits

Author SHA1 Message Date
Don Cross
2bdb25227e C EclipticGeoMoon: use true equinox of date.
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.
2022-12-05 13:55:36 -05:00
Don Cross
576eea2245 Unrolled loops from remaining nutation functions. 2022-12-04 21:30:22 -05:00
Don Cross
b9738d9661 C: Unrolled the truncated IAU2000B formula. 2022-12-04 20:56:15 -05:00
Don Cross
b8c0a1f0cc Python: hand-optmized nutation.
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.
2022-12-04 20:27:44 -05:00
Don Cross
d3f36b942d Verify nutation angles are consistent across languages. 2022-12-04 14:20:44 -05:00
Don Cross
8a153315cf Simplified and optimized nutation formula.
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.
2022-12-04 10:31:15 -05:00
Don Cross
84621b4d33 Enable truncation of the IAU2000B nutation model.
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.
2022-12-03 21:29:59 -05:00
Don Cross
db24ae9332 C: Added comments. Error checking in SphereFromVector.
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.
2022-12-03 16:30:55 -05:00
Don Cross
119dfed824 C: define J2000 mean obliquity constants in one place. 2022-11-29 14:57:36 -05:00
Don Cross
53b735a941 Fixed misspelled "ecliptic" in documentation. 2022-11-28 11:57:36 -05:00
Don Cross
5087e4df28 More documentation fixes for rise/set, altitude. 2022-11-27 13:56:51 -05:00
Don Cross
e12d2e88c6 Updated docs: SearchRiseSet, SearchAltitude.
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.
2022-11-27 12:42:48 -05:00
Don Cross
1725c77c9f Fixed doc typos. JS HelioState user-defined stars.
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.
2022-11-23 12:01:34 -05:00
Don Cross
098eb3ac7a Optimized HelioDistance for user-defined stars.
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.
2022-11-23 11:16:56 -05:00
Don Cross
79f6eac8eb HelioState functions support user-defined stars. 2022-11-23 09:21:56 -05:00
Don Cross
7b7a306baf Python: Find rise/set/culm of user-defined stars.
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.
2022-11-22 21:42:02 -05:00
Don Cross
fe625c5956 Kotlin: added support for user-defined stars. 2022-11-22 19:29:15 -05:00
Don Cross
a6ddf1880a C#: implemented user-defined stars. 2022-11-22 15:06:04 -05:00
Don Cross
f6ad8b5b26 C: Find rise/set/culm of user-defined stars.
SearchRiseSet and SearchHourAngle now work with user-defined stars.

Fixed a bug in InternalSearchAltitude where I failed to return an error
code when its call to MaxAltitudeSlope failed.
2022-11-22 05:46:50 -05:00
Don Cross
6b4c6c67e2 C: Added Astronomy_DefineStar.
Beginning to add support in C for user-defined stars.
2022-11-21 22:16:30 -05:00
Don Cross
696efe8649 JS: Find rise/set/culm of user-defined stars.
DefineStar now requires passing in the heliocentric
distance of the star expressed in light-years.
That way, I can directly support returning vectors
to a star from HelioVector, GeoVector, etc.

SearchRiseSet and SearchHourAngle now work with user-defined stars.
2022-11-21 20:55:27 -05:00
Don Cross
84d6aff35a JS: Added function DefineStar.
I'm starting to implement the ability to define
up to 8 distinct points in the sky as "stars"
that will be allowed as a `body` parameter to
some Astronomy Engine functions, to be determined.
2022-11-21 12:53:45 -05:00
Don Cross
8fa81d0fbc Fixed botched commit: didn't update Kotlin docs. 2022-11-14 13:40:10 -05:00
Don Cross
351e997a2f Merge branch 'riseset_poles'
Fixed issues with finding rise/set events near the
Earth's poles. Avoid assumptions that rise/set is
tied to hour angles.
2022-11-14 12:05:20 -05:00
Don Cross
d9d955a651 Altitude search: better parameter checking.
Made sure all the altitude search functions
verify that the geographic latitude and target altitude
are valid numbers in the range [-90, +90].

Reworked the C version of the code to be clearer:
eliminated goofy ALTDIFF macro, split out max
altitude derivative into its own function MaxAltitudeSlope,
just like the other language implementations do.

Minor rewording of comments in MaxAltitudeSlope functions.

Python InvalidBodyError now includes the invalid body
in the diagnostic message.
2022-11-14 11:04:46 -05:00
Don Cross
5e074d05aa Bumped version number to 2.1.10.
Not ready to tag yet, because I need to merge into
master branch first, to pick up the npm package
configuration change.
2022-11-14 08:15:23 -05:00
Don Cross
1b52e91394 Python: overhauled altitude search 2022-11-13 22:17:06 -05:00
Don Cross
e85863acf5 JS: reworked rise/set to work in polar regions 2022-11-13 20:45:00 -05:00
Don Cross
e31be80497 Kotlin: reworked rise/set to work in polar regions 2022-11-13 19:25:44 -05:00
Don Cross
480e0c3ab5 C#: Overhauled altitude search for polar regions.
The C# version of the altitude searches now work correctly
near the Earth's poles. This is a port of the C version.
Cleaned up a little code in the C version.
2022-11-13 12:25:10 -05:00
Don Cross
a5995e2ee0 C RiseSet: improved efficiency.
Do not recurse deeper when any solution would
have a rise+set or a set+rise consecutively
within one second. This would risk confusing the
search, which has a 0.1 second tolerance for convergence.
For practical reasons, such events are dubious anyway,
being swamped by unpredictable atmospheric refraction.
Plus it's just faster to not have to recurse so deeply.

Add a safety valve that fails the search if recursion
gets deeper than the above tolerance would ever allow
to happen in the first place.

This change improves performance significantly:

C RiseSet: passed 5909 lines: time errors in minutes: rms=0.2904, max=1.1541, recur=15, altcount=156881

Added helper function AscentError for cleaner code in error cases.
2022-11-13 10:32:47 -05:00
Don Cross
8498d23c73 C RiseSet: print performance stats.
Track the maximum recursion depth in FindAscent.
Count the number of times the altitude_diff function is called.
These are important performance statistics that I want to
measure, so I can try a few optimization ideas.

Current results:

don@spearmint:~/github/astronomy/generate $ ./generate source && ./ctbuild && ./ctest -v riseset
./ctbuild: C compiler = gcc
./ctbuild: Built 'ctest' program.
C RiseSet: Moon    lat=-61.0 lon=103.0
C RiseSet: Moon    lat=-45.0 lon=150.0
C RiseSet: Moon    lat=29.0 lon=-81.0
C RiseSet: Moon    lat=80.0 lon=130.0
C RiseSet: Moon    lat=83.0 lon=105.0
C RiseSet: Moon    lat=84.0 lon=125.0
C RiseSet: Moon    lat=85.0 lon=135.0
C RiseSet: Moon    lat=85.0 lon=140.0
C RiseSet: Sun     lat=-90.0 lon=0.0
C RiseSet: Sun     lat=-88.0 lon=45.0
C RiseSet: Sun     lat=-60.0 lon=-150.0
C RiseSet: Sun     lat=15.0 lon=75.0
C RiseSet: Sun     lat=29.0 lon=-81.0
C RiseSet: Sun     lat=60.0 lon=0.0
C RiseSet: Sun     lat=89.0 lon=30.0
C RiseSet: Sun     lat=90.0 lon=0.0
C RiseSet: passed 5909 lines: time errors in minutes: rms=0.2904, max=1.1541, recur=19, altcount=171438
2022-11-13 09:36:48 -05:00
Don Cross
bfc7c80309 C: Cleanup of new function FindAscent(). 2022-11-12 21:52:38 -05:00
Don Cross
4602f619d3 C: Rise/set that works near the poles!
This is a whole new algorithm that efficiently finds
all rise/set events, even near the poles.
It uses a recursive bisection search that limits
recursion depth by knowing the maximum possible
|da/dt| = change in altitude with respect to time.
2022-11-12 21:40:20 -05:00
Don Cross
eede908314 Arcsine of (radius/dist) for more accuracy.
Finding apparent angular radius by dividing body radius
by distance is not quite as accurate as taking the
arcsine of the same ratio. Changed this for a slightly
more accurate answer.
2022-11-10 15:20:04 -05:00
Don Cross
bf20fb1c44 C: InternalSearchAltitude owns func + context.
Refactored so there is a single altitude function/context pair
instead of separate ones for SearchAltitude and SearchRiseSet.
This allows InternalSearchAltitude to fully understand the
problem to be solved, and also makes the code smaller.
InternalSearchAltitude will need to perform min/max altitude
calculations, which means it needs to know all the parameters
of the altitude search directly. They are no longer hidden
inside an opaque function pointer and context.

So now SearchAltitude and SearchRiseSet no longer create
contexts, nor pass in a function pointer. They just
pass the correct numeric parameters to the generic solver
InternalSearchAltitude, which packs the parameters into
the context for Search().

Unified the two context types into a single context type,
and the two callback functions into a single callback function.
2022-11-10 15:10:28 -05:00
Don Cross
3679966931 Version 2.1.9: attempt fix for Deno/Node type info.
Updated the version number so I can create a new
npm package to test the pull request from @matheo
that should allow TypeScript types to be exported correctly.
2022-11-08 20:59:17 -05:00
Mateo Tibaquira
40cd7e3b0e Fix #263 - Update the npm package metadata 2022-11-08 18:05:51 -05:00
Don Cross
5eca7d7760 CodeQL tweaks and fixes.
Updated CodeQL config to ignore source templates,
because they are not syntactically valid source code.
Ignore other stuff that is irrelevant to published
code quality.

Made various fixes based on helpful CodeQL analysis.
2022-11-07 15:31:05 -05:00
Don Cross
0674d69237 C RiseSet: starting algorithm without hour angles.
The rise/set search based on hour angles is complicated,
and doesn't handle oddities that happen close to the poles.
I'm starting to rework rise/set as a more brute force solution
that iterates through finite time steps.

I also added a series of Moon data for the arctic circle,
which includes some of the more painful special cases.
For example:

Moon  130  80 2034-05-16T13:21Z s
Moon  130  80 2034-05-16T13:51Z r

Here the Moon sets, then rises 30 minutes later.
So now I'm trying to figure out how to discover
arbitrarily brief intervals like this.
I want the time increments to scale intelligently
so that we don't waste time during long periods
of inactivity (body above or below the horizon continuously),
but without missing examples like the one above.
2022-11-05 20:58:04 -04:00
Don Cross
cd08fe5402 Eliminate doxygen warnings by pruning Doxyfile.
I use a variety of doxygen versions among the systems
that run the unit tests, including my personal development
systems and GitHub Actions.

Older versions of doxygen complain about options in Doxyfile
they don't know about.

Newer versions of doxygen complain about obsolete options in Doxyfile.

I'm trying to get rid of all these noisy warnings by pruning
all options in Doxyfile that are equivalent to their default
values. I only keep the options that I need to be different
from the default.

Hopefully this quiets down the warnings.
2022-11-02 12:02:31 -04:00
Don Cross
c8af73e1e7 Fixed #256 - added orbital period functions. 2022-11-01 19:40:30 -04:00
Don Cross
275e3a7c79 Kotlin: added function planetOrbitalPeriod. 2022-11-01 19:16:32 -04:00
Don Cross
23fd95a53f PY: Added PlanetOrbitalPeriod function. 2022-11-01 17:30:48 -04:00
Don Cross
fd49c25ae3 C#: exported function PlanetOrbitalPeriod. 2022-11-01 17:01:03 -04:00
Don Cross
bd115770e1 C: Added function Astronomy_PlanetOrbitalPeriod. 2022-11-01 16:38:57 -04:00
Don Cross
9e4fbecf55 JS: added OrbitalPeriod function. 2022-11-01 16:09:14 -04:00
Don Cross
6f25a3db85 Astronomy Engine v2.1.7: eclipse obscuration
This is my second attempt to release eclipse obscuration.
I discovered there was a missing unit test for obscuration
for lunar eclipses in the Kotlin library. It has been added.
2022-10-20 19:13:47 -04:00
Don Cross
232da2c319 Astronomy Engine 2.1.6: eclipse obscuration 2022-10-20 18:34:27 -04:00
Don Cross
06b62887d2 Kotlin: obscuration for solar, lunar eclipses. 2022-10-20 17:31:21 -04:00