componavt's picture
+ temp old streamlit
723b602
Raw
History Blame Contribute Delete
3.44 kB
import numpy as np
# Constants for shadowing analysis
SHADOWING_EPSILON_THRESHOLD = 1e-3
def compute_epsilon_t(distances):
"""
Compute epsilon(t) as the running maximum of distances.
Args:
distances: Array of distances between two trajectories at each time point
Returns:
Array representing epsilon(t) - the running maximum of distances
"""
return np.maximum.accumulate(distances)
def find_shadowing_breakdown_time(epsilon_t, t_eval, epsilon_threshold=SHADOWING_EPSILON_THRESHOLD):
"""
Find the shadowing breakdown time t* where epsilon(t) exceeds a threshold.
Args:
epsilon_t: Array of epsilon(t) values (running maximum of distances)
t_eval: Time points corresponding to epsilon(t) values
epsilon_threshold: Threshold above which shadowing is considered broken
Returns:
tuple: (shadowing_time, shadowing_length, shadowing_ratio)
shadowing_time: Time t* where epsilon(t) > epsilon_threshold (or None if never exceeded)
shadowing_length: Length of time where epsilon(t) <= epsilon_threshold
shadowing_ratio: Ratio of valid shadowing time to total time
"""
if len(epsilon_t) != len(t_eval):
raise ValueError("epsilon_t and t_eval must have the same length")
# Find the first time where epsilon(t) exceeds the threshold
exceed_indices = np.where(epsilon_t > epsilon_threshold)[0]
if len(exceed_indices) == 0:
# If threshold is never exceeded, shadowing holds for the entire duration
shadowing_time = None # Indicates no breakdown occurred
shadowing_length = t_eval[-1] - t_eval[0]
shadowing_ratio = 1.0
else:
# Take the first occurrence where threshold is exceeded
first_exceed_idx = exceed_indices[0]
shadowing_time = t_eval[first_exceed_idx]
shadowing_length = t_eval[first_exceed_idx] - t_eval[0]
shadowing_ratio = shadowing_length / (t_eval[-1] - t_eval[0])
return shadowing_time, shadowing_length, shadowing_ratio
def compute_shadowing_diagnostics(dop_solution, nn_solution, t_eval, epsilon_threshold=SHADOWING_EPSILON_THRESHOLD):
"""
Compute comprehensive shadowing diagnostics by comparing two solutions.
Args:
dop_solution: Dictionary with 'x' and 'y' arrays from DOP853 solver
nn_solution: Dictionary with 'x' and 'y' arrays from neural network solver
t_eval: Time points array
epsilon_threshold: Threshold for shadowing breakdown
Returns:
dict: Dictionary containing shadowing diagnostics
"""
# Calculate distance between DOP853 and NN solutions
dist = np.sqrt((dop_solution['x'] - nn_solution['x'])**2 + (dop_solution['y'] - nn_solution['y'])**2)
# Calculate epsilon(t) as the running maximum (sup norm)
epsilon_t = compute_epsilon_t(dist)
# Calculate shadowing breakdown diagnostics
shadowing_time, shadowing_length, shadowing_ratio = find_shadowing_breakdown_time(
epsilon_t, t_eval, epsilon_threshold
)
return {
'epsilon_t': epsilon_t,
'distances': dist,
'shadowing_time': shadowing_time,
'shadowing_length': shadowing_length,
'shadowing_ratio': shadowing_ratio,
'epsilon_threshold': epsilon_threshold,
'has_breakdown': shadowing_time is not None
}