Confirmed that Mercury is taking 19 iterations/call on average,
and Mars is taking about 10 iterations/call.
The other planets average 6 iterations/call.
Compiler does not understand that there is no need for
a switch default because the enclosing switch statement
has already guarded against that. Changed to ternary
operator to make compiler warning go away.
Still need to verify that there is a consistent interval between
consecutive events.
Mercury is taking way too long to converge.
Mars is kind of slow too.
Need to improve the efficiency of SearchRelativeLongitude!
Using relative heliocentric ecliptic longitude of the Earth
and the other planet. Home in on when both planets have the
same longitude (the difference is 0).
For some reason, all my calculations are about 8 minutes earlier
than predictions from the test data. I suspect this is because
of light travel time from the Sun (equivalently, aberration).
Added new function Astronomy.SunPosition().
It is supposed to return ecliptic coordinates of date for the Sun
as seen from the center of the Earth.
The values look reasonable but I need to test them.
Will use the Sun's longitude in the return value from SunPosition()
to determine solstices and equinoxes.
All callers of sidereal_time ended up needing it for apparent time,
not mean time. So I simplified the code so it no longer has extra
stuff for calculating GMST.
Astronomy.GeoVector no longer iterates to try to correct light
travel time for the apparent position of the Sun. The Sun's
heliocentric coordinates are always (0,0,0), so there is no need
to do that.
Search limit can be adjusted in options passed into Search().
After 20 iterations, we should have divided the search
region by a factor of more than a million. If quadratic
interpolation can't finish the job at that point, something
is really wrong.
Allow caller to pass in pre-evaluated endpoints to begin the search.
This eliminates 2 function calls per search, reducing the
average from 8 calls/search down to 6 calls/search.
I think this is about as good of performance as I'm going to get.
The smaller the slope magnitude |df/dt| is, the larger
the uncertainty in dt. That means we are better off using
an estimated value for the slope each time than underestimating
the time error like we were doing.
This also simplifies the code, and does not make it very
much slower.
I learned by debugging the code that the Chebyshev approximation
does not exactly reproduce the endpoints like I thought. It does so
for the x values indicated by Alpha[1][...].
Now pass in max slope of function to be searched, expressed
in units/day. By seeing how far the function is from zero,
we can deduce whether we are within the specified time tolerance
of finding the event.
Use a simplified refraction model in the rise/set search so that
the function is better fit by parabolas. Assume constant refraction
instead of variable refraction, because it only matters near the horizon
anyway. Use a canned value of +34 minutes, which creates close fit with
test data.
I am interested in optimizing the Search function.
Right now it is a very simple binary search that keeps breaking
an interval in half to narrow in on the time of where the supplied
function ascends through zero. I know this can be made much better,
and this is important because the function calls are very expensive
in some cases.
So this commit adds the beginning of some simple metrics tracking
where unit test code can retrieve the number of times Search
sampled the function it is trying to find the ascending root for.
Latitudes within the arctic/antarctic circles cause too much
hassle because of horizon-grazing that makes it hard for
two different programs to agree on when (or even whether)
a rise or set took place.
The refraction formula went nuts near altitude angle -5.11 degrees.
We were taking the tangent of a value that zoomed toward infinity
near that value, causing essentially random numbers without any
upper bound to their size. Just like JPL Horizons, truncate any
angle more than 1 degree below the horizon, only I have a linear
taper down to 0 refraction as the altitude angle approaches -90.
I did not want any chance of creating an altitude less than -90.
Removed unit tests for the Sun at latitude -80 degrees.
It is too easy for my code to behave differently from another
calculator, because tiny changes in atmospheric modeling can
cause disagreement about whether there even is a sunset/sunrise.
This is because for observers so close to the pole, the Sun
sometimes barely dips below the horizon and then comes back
up for less than an hour.
This is the first time it has passed the unit test,
although the unit test is just exercising whether the predictions
occur in the right order. I will need to add check for how accurate
the predictions are.
I will rework the rise/set algorithm to use min/max altitude events.
The result will be much more efficient, and will handle special
cases near the poles better.
Git seems to return different exit codes on every system I try.
So now I'm just looking at whether 'git status --porcelain'
emits any text or not, without paying any attention to its exit code.
Very simply, use git command to confirm there were no unexpected
modifications. In particular, if the checked in generated source
doesn't match what got written by the generate program, this will
fail the Travis CI build.