suncalc icon indicating copy to clipboard operation
suncalc copied to clipboard

Coarse getMoonTimes

Open andersborgabiro opened this issue 4 years ago • 2 comments

It seems very coarse to check for cross-overs each 2 hours. Could this be made a function argument?

Stargazing calls for something like 10 minutes resolution to be on the safe side, provided the calculation is otherwise correct.

Thanks in advance.

andersborgabiro avatar Mar 05 '21 12:03 andersborgabiro

The idea to check each 2 hours is sound, but the lack of further narrowing down is... obviously not. A proper root-finding algorithm should be used to narrow it down, something along the lines of:

let hx = (x) =>
  SunCalc.getMoonPosition(hoursLater(t, x), lat, lng).altitude - hc;

for (var i = 1; i <= 24; i += 2) {
  h2 = h(i+1);
  if (h0 * h2 <= 0) {
    // crosses zero, good to solve
    // assume a JS port of https://docs.rs/kurbo/0.8.1/kurbo/common/fn.solve_itp.html
    let root = solve_itp(
      // function and bounds
      hx, i - 1, i + 1,
      // 0.01h max error -- that's tiny!
      0.01,
      // irrelevant hyperparameters
      1, 0.2 / 2,
      // initial values
      h0, h2
    );
    if (h0 < 0) rise = root;
    else set = root;
  }
  h0 = h2;
}

(The step-size can actually be made much larger in this case, since ITP will handle the narrow-down. The tricky thing is that I haven't figured out what to do when the moon actually goes up-then-down in a two-hour window -- the quadratic thing will catch it with a middle point, while here it won't even try to solve! I guess making it two subintervals according to a quadratic guess might be the way to go:)

for (var i = 1; i <= 24; i += 2) {
  h2 = h(i+1);
  if (h0 * h2 <= 0) {
    // crosses zero, good to solve
    // assume a JS port of https://docs.rs/kurbo/0.8.1/kurbo/common/fn.solve_itp.html
    let root = solve_itp(
      // function and bounds
      hx, i - 1, i + 1,
      // 0.01h max error -- that's tiny!
      0.01,
      // irrelevant hyperparameters
      1, 0.2 / 2,
      // initial values
      h0, h2
    );
    if (h0 < 0) rise = root;
    else set = root;
  } else {
    h1 = h(i);
    // Look at h1, do two separate intervals for itp, splitting at the quadratic "xe"
  }
  h0 = h2;
}

But do note that getMoonPosition itself might be a bit wrong (#102), and without that fixed any root-finding algorithm will be bad.

Artoria2e5 avatar Aug 23 '21 12:08 Artoria2e5

Thanks. I'll try this. Amateur astronomers are picky about when the moon is up (or rather not up).

andersborgabiro avatar Aug 24 '21 08:08 andersborgabiro