验收四路模型并优化拓扑求解性能

This commit is contained in:
huojiarong committed 2026-08-12 11:57:42 +00:00
1 parent caca32a513
commit 456c29b3b6
20 files changed
+1085 -137

No files matched your search

+43 -1
View File
@@ -39,7 +39,7 @@ class SolveIVPConfig:
t_stop: float = 20.0
method: str = "BDF"
rtol: float = 1e-6
atol: float = 1e-8
atol: float | Sequence[float] = 1e-8
max_step: float = 1e-3
first_step: float | None = None
@@ -88,6 +88,34 @@ def _append_or_replace_solution_sample(
return
_append_solution_sample(times, states, time, state)
def _project_nearby_pre_transition_sample(
times: list[float],
states: list[list[float]],
transition: StateTransition,
config: SolveIVPConfig,
) -> None:
"""Resolve a sample/event ordering that is below solver time precision.
An adaptive dense interpolant can place a discontinuous impact a few
nanoseconds after its analytically coincident output sample. Keep the
located event and restart time unchanged, but report that ambiguous sample
on the reset side of the discontinuity.
"""
if not times or not math.isfinite(config.max_step):
return
time_gap = float(transition.time) - times[-1]
tolerance = max(
64.0 * math.ulp(max(abs(float(transition.time)), 1.0)),
min(
abs(float(config.max_step) * float(config.rtol)),
1.0e-8,
),
)
if not 0.0 < time_gap <= tolerance:
return
for index, value in enumerate(transition.state):
states[index][-1] = float(value)
def _normalize_state_transition(
transition: StateTransition,
@@ -534,6 +562,7 @@ def _integrate_scipy_stepwise(
accepted_step_callback: AcceptedStepCallback | None,
breakpoints: Sequence[float] = (),
state_transition_handler: StateTransitionHandler | None = None,
jac_sparsity=None,
) -> ODESolution:
"""Initial stepwise integration path for breakpoints and state resets.
@@ -625,6 +654,8 @@ def _integrate_scipy_stepwise(
"atol": config.atol,
"max_step": segment_max_step,
}
if jac_sparsity is not None and config.method in {"BDF", "Radau"}:
solver_options["jac_sparsity"] = jac_sparsity
requested_first_step = (
0.1 * segment_max_step
if last_recoverable_error is not None
@@ -666,6 +697,7 @@ def _integrate_scipy_stepwise(
error = exc
break
restart_at_transition = False
restart_after_recoverable = False
while solver.status == "running":
@@ -806,6 +838,12 @@ def _integrate_scipy_stepwise(
)
sample_index += 1
_project_nearby_pre_transition_sample(
times,
states,
transition,
config,
)
last_accepted_time = transition.time
last_accepted_state = list(transition.state)
last_transition = transition
@@ -923,6 +961,7 @@ def integrate_ode(
accepted_step_callback: AcceptedStepCallback | None = None,
breakpoints: Sequence[float] | None = None,
state_transition_handler: StateTransitionHandler | None = None,
jac_sparsity=None,
):
"""Integrate an ODE, optionally restarting at equation discontinuities.
@@ -992,6 +1031,7 @@ def integrate_ode(
accepted_step_callback,
normalized_breakpoints,
state_transition_handler,
jac_sparsity,
)
solve_options = {
@@ -1006,4 +1046,6 @@ def integrate_ode(
}
if config.first_step is not None:
solve_options["first_step"] = config.first_step
if jac_sparsity is not None and config.method in {"BDF", "Radau"}:
solve_options["jac_sparsity"] = jac_sparsity
return solve_ivp(**solve_options)