Astronomy software predicts the location of the Sun by taking JPL predictions of where the Earth and Sun will be, which the JPL expresses as a series of polynomials that cover specific ranges of dates. Asking “when will the sun be at azimuth z?” is asking when three different polynomials, that are each varying at a different rate (the polynomial for the Sun, for the Earth-Moon barycenter revolving around the Sun, and the Earth revolving around the barycenter), will happen to bring the difference between the two positions to precisely a certain angle.
And, it turns out, that problem falls into the class of “gross” math problems — or, as professionals say, “non-closed-form-solution problems.” But I like your word “gross” because it catches very well how most of us feel when we discover that much of the world has to be tackled by trial-and-error instead of just giving us an answer.
Fortunately, a vast enough swatch of science is “gross” in this sense that there are standard ways of asking “when will this big complicated function reach exactly value z?” If you are able to install and try out SciPy, the increasingly popular science library for Python, you will find that it has a whole collection of routines that sneak up on solutions, each using a different tactic. The other answerer has already identified one such tactic — halving the search space with each trial — but that is generally the slowest (though in some extreme cases, the safest) approach; here are some others:
http://docs.scipy.org/doc/scipy/reference/optimize.html
Create a little function that returns “how far off” the Sun's azimuth is a time t
from the azimuth you want, where the function will finally return zero when the azimuth is exactly right, like:
def f(t):
...
return desired_az - sun.az
Then try out one of the “root finding scalar functions” from that SciPy page. The bisect()
function will, just like the other answerer suggests, keep cutting the search space in half to narrow things down. But my guess is that you'll find a Newton's method to be far less “gross” and far faster — try newton()
or brentq()
, and see what happens!