Performance Optimization
Numba JIT Compilation
GASFIR’s inner loops are JIT-compiled with Numba. The first call to any kernel function triggers compilation, which may take several seconds. Subsequent calls run at near-native speed. To warm up the cache before a long computation:
from gasfir import create_pulse, get_parameters, get_diabatic_ionization_probability
laser = create_pulse(800, 1e14, 0, 5) # short pulse just for warm-up
params = get_parameters("Hydrogen_SFA")
_ = get_diabatic_ionization_probability(pulse=laser, param_dict=params)
# From here on, compiled kernels are cached in memory.
Pulse Result Caching
Each Pulse instance caches field/potential evaluations keyed by
the grid hash. Reusing the same time grid avoids redundant computation:
t = laser.get_tgrid(dt=0.25)
E1 = laser.get_electric_field(t) # computed
E2 = laser.get_electric_field(t) # returned from cache
Batch Pre-Computation
When computing probabilities for many pulses, use
get_diabatic_ionization_probability_vec(). It calls
precompute_pulse_batch() once to strip the NumPy arrays out of
the pulse objects, then evaluates the kernel for every pulse across all CPU
cores:
from gasfir import get_diabatic_ionization_probability_vec, get_parameters
params = get_parameters("Hydrogen_SFA")
probs = get_diabatic_ionization_probability_vec(pulses, params)
During fitting, the grid pre-computation should happen once and be reused
across every parameter update. ret_gasfir_P_for_dataFrame()
(and gasfir.fitting.ret_residual_function()) do exactly this: they run
precompute_pulse_batch() at construction time and return a fast
closure that only re-evaluates the kernel:
from gasfir import ret_gasfir_P_for_dataFrame
P_func = ret_gasfir_P_for_dataFrame(df) # pre-computes once
probs = P_func(params) # cheap to call per parameter set
Choosing dt and dT
dT(fine grid) controls accuracy of the phase integral. Default 0.25 a.u. is safe for most conditions; increase to 0.5 for a ~2× speedup with mild accuracy loss.dt(coarse grid) controls the pulse envelope sampling. Default 2 a.u. is sufficient for pulses longer than ~5 optical cycles.