Skip to content

Latest commit

 

History

History
198 lines (159 loc) · 6.83 KB

File metadata and controls

198 lines (159 loc) · 6.83 KB

Previous: Limb darkening · Documentation home · Next: Coordinates and conventions

Accuracy control

VBMicrolensing correspondence: AccuracyControl.md. The s=0.8, q=0.1, source-position, source-radius, and tolerance examples are retained.

Use the same lens and source values while changing only the requested absolute accuracy:

import lcbinint

s, q, y1, y2, rho = 0.8, 0.1, 0.01, 0.01, 0.01

mag_1e3 = lcbinint.binary_ray_shooting(
    y1, y2, s=s, q=q, rho=rho,
    options=lcbinint.Options(tol=1e-3),
)
print("Magnification (accuracy at 1.e-3) =", mag_1e3)

mag_1e4 = lcbinint.binary_ray_shooting(
    y1, y2, s=s, q=q, rho=rho,
    options=lcbinint.Options(tol=1e-4),
)
print("Magnification (accuracy at 1.e-4) =", mag_1e4)

Precision control

mag_rel_1e1 = lcbinint.binary_ray_shooting(
    y1, y2, s=s, q=q, rho=rho,
    options=lcbinint.Options(reltol=1e-1),
)
print("Magnification (relative precision at 1.e-1) =", mag_rel_1e1)

How the tolerance is applied

lcbinint uses one budget at each epoch:

tol + reltol * max(abs(magnification), 1)

tol is the absolute term and reltol is the relative term. If either term is set explicitly, the other term is zero unless it is also supplied. If both are left at zero, the calibrated default is equivalent to 1e-4 + 1e-3 * max(abs(magnification), 1).

The returned value is not made accurate merely by requesting a tolerance. Inspect finite_source_converged and finite_source_error_estimates when the result matters scientifically.

Evaluation modes

A finite-source light curve can move between several methods from epoch to epoch:

Reported method Meaning
point_source Source size is safely negligible at this position.
hexadecapole A fourth-order finite-source expansion is locally safe.
source_plane_quadrature The source disk is integrated in the source plane.
inverse_ray_cartesian A Cartesian inverse-ray grid resolves the finite images.
inverse_ray_polar A polar inverse-ray grid is selected for suitable high-magnification geometry.

inverse_ray_grid controls the full inverse-ray backend; it does not disable the safe point-source or hexadecapole fast paths.

automatic = lcbinint.Options(
    nbin="auto",
    inverse_ray_grid="auto",
    tol=1e-4,
    reltol=1e-3,
)

fixed_cartesian = lcbinint.Options(
    nbin=800,
    inverse_ray_grid="cartesian",
    tol=1e-4,
    reltol=1e-3,
)

fixed_polar = lcbinint.Options(
    nbin=800,
    polar_nbin=800,
    inverse_ray_grid="polar",
    tol=1e-4,
    reltol=1e-3,
)

nbin="auto" predicts one resolution for each binary-lens epoch from the calibrated law, rounds upward, and evaluates it once. Its embedded error indicator is diagnostic and does not trigger a larger grid. A fixed integer is useful for reproducibility experiments and is also one-shot.

Option summary

Option Purpose Normal choice
tol, reltol Absolute and relative finite-source error budget. Set both for a scientific accuracy target.
nbin Automatic or fixed source-grid resolution. "auto"
max_source_bins Ceiling applied to the automatic resolution prediction. Leave at the calibrated default unless diagnostics require more.
inverse_ray_grid "auto", "cartesian", or "polar". "auto"
polar_nbin Optional independent polar resolution. None
caustic_bins Sampling used only for caustic/critical-curve visualization. Increase for denser scatter plots.
hex_tol Fourth-order self-consistency threshold. Leave at the default unless validating method selection.
point_source_threshold Geometric point-source safety margin. Advanced validation only.

Inspect the selected method

import numpy as np
import matplotlib.pyplot as plt

params = {
    "s": 0.9, "q": 0.1, "u0": 0.0, "alpha": 1.0,
    "rho": 0.01, "tE": 30.0, "t0": 7500,
}
t = np.linspace(7470, 7530, 300)
curve = lcbinint.LightCurve(options=automatic)
info = curve.info(t, params)

method_names = list(dict.fromkeys(info.finite_source_method_names))
method_index = {name: index for index, name in enumerate(method_names, start=1)}
selected = [method_index[name] for name in info.finite_source_method_names]
# Fixed, colorblind-friendly palette; reserve vermilion for caustics below.
method_colors = ["#0173B2", "#DE8F05", "#029E73", "#CC78BC", "#56B4E9"]

fig, (mag_ax, method_ax) = plt.subplots(2, 1, sharex=True, figsize=(4.8, 3.8))
mag_ax.plot(t, info.magnifications)
mag_ax.set_ylabel("Magnification")
for color_index, name in enumerate(method_names):
    mask = np.asarray(info.finite_source_method_names) == name
    method_ax.scatter(
        t[mask], np.asarray(selected)[mask], s=10,
        color=method_colors[color_index],
    )
method_ax.set_yticks(range(1, len(method_names) + 1))
method_ax.set(xlabel="Time", ylabel="Method")
fig.tight_layout()
plt.show()

Automatic method selection

Use the same colors to show where each method is selected along the source trajectory. Each uninterrupted run is drawn as one line segment; caustics are red.

methods = np.asarray(info.finite_source_method_names)
trajectory = curve.source_trajectory(t, params)
caustics = curve.caustics(params)

plt.figure(figsize=(2.8, 2.8))
for x, y in zip(caustics.x, caustics.y):
    plt.plot(x, y, color="#6C6C6C", lw=1.1)

display_x = np.asarray(trajectory.x)
display_y = np.asarray(trajectory.y)
for color_index, name in enumerate(method_names):
    indices = np.flatnonzero(methods == name)
    breaks = np.where(np.diff(indices) != 1)[0] + 1
    for run in np.split(indices, breaks):
        if len(run) > 1:
            plt.plot(
                display_x[run], display_y[run],
                color=method_colors[color_index], lw=1.2,
            )
        elif len(run) == 1:
            plt.plot(
                display_x[run], display_y[run], color=method_colors[color_index],
                marker="o", markersize=2.5,
            )
plt.xlabel("X")
plt.ylabel("Y")
plt.axis("equal")
plt.show()

Method selection along the source trajectory

The method numbers in the lower panel are:

  1. point_source — point-source approximation.
  2. hexadecapole — fourth-order finite-source approximation.
  3. inverse_ray_cartesian — Cartesian inverse ray shooting.
  4. source_plane_quadrature — direct source-plane integration.
  5. inverse_ray_polar — polar inverse ray shooting.

For the calibration evidence and the exact retry rules, continue to Numerical methods.

Previous: Limb darkening · Documentation home · Next: Coordinates and conventions