Source code for andes.routines.adaptive

"""
Shared helpers for adaptive integration methods.
"""

import numpy as np


[docs]def weighted_rms_error(err_vec, x_prev, x_new, abstol, reltol, err_wt): """ Compute weighted RMS norm of an error vector. Parameters ---------- err_vec : np.ndarray Error estimate vector. x_prev : np.ndarray Previous accepted state. x_new : np.ndarray Candidate new state. abstol : float Absolute tolerance. reltol : float Relative tolerance. err_wt : np.ndarray Pre-allocated work array. """ np.maximum(np.abs(x_prev), np.abs(x_new), out=err_wt) err_wt *= reltol err_wt += abstol np.divide(err_vec, err_wt, out=err_wt) return np.sqrt(np.dot(err_wt, err_wt) / len(err_wt))
[docs]def propose_step_factor(err_est, order, safety=0.9, min_factor=0.2, max_factor=5.0): """ Propose a multiplicative step-size factor from a normalized error estimate. """ if err_est <= 0: return max_factor factor = safety * err_est ** (-1.0 / (order + 1)) if factor < min_factor: return min_factor if factor > max_factor: return max_factor return factor
[docs]def candidate_h(err_est, h, order, safety=0.9, min_factor=0.2, max_factor=5.0): """ Propose a candidate next step size from normalized error. """ return h * propose_step_factor(err_est, order, safety=safety, min_factor=min_factor, max_factor=max_factor)
[docs]def check_adaptive_bust(tds): """ Shared bust-check for adaptive methods (TrapezoidAdaptive, QNDF). Called after ``step()`` has written ``tds.deltat``. If the step was rejected and deltat has fallen to the adaptive minimum, marks simulation as busted. """ if not tds.converged and tds.deltat <= tds.deltatmin_adapt: rejected_h = tds.deltat tds.deltat = 0 tds.busted = True tds.err_msg = ( "Step size below adaptive minimum after rejection " f"(deltat={rejected_h:.4g}, dtmin_adapt={tds.deltatmin_adapt:.4g})." )
[docs]def accept_reject(err_est, h, deltatmax, order, fail_count=0, accept_threshold=1.0, accept_safety=0.9, accept_min_factor=0.2, accept_max_factor=2.0, reject_safety=0.9, reject_min_factor=0.2, reject_max_factor=0.9, repeat_reject_after=1, repeat_reject_factor=0.5): """ Shared accept/reject controller for adaptive methods. Returns ------- tuple[bool, float, int] ``(accepted, h_next, fail_count_next)``. """ if err_est <= accept_threshold: h_next = candidate_h(err_est, h, order, safety=accept_safety, min_factor=accept_min_factor, max_factor=accept_max_factor) return True, min(h_next, deltatmax), 0 fail_count_next = fail_count + 1 h_next = candidate_h(err_est, h, order, safety=reject_safety, min_factor=reject_min_factor, max_factor=reject_max_factor) if fail_count_next > repeat_reject_after: h_next = min(h_next, h * repeat_reject_factor) return False, min(h_next, deltatmax), fail_count_next