验收四路模型并优化拓扑求解性能
This commit is contained in:
1 parent
caca32a513
commit
456c29b3b6
20 files changed
+1085
-137
No files matched your search
@@ -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)
|
||||
Reference in new issue
Block a user