优化压力流量求解并达到四路性能门槛
This commit is contained in:
1 parent
6572defaa4
commit
6a064892e2
20 files changed
+711
-175
No files matched your search
@@ -44,6 +44,36 @@ class SolveIVPConfig:
|
||||
first_step: float | None = None
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SolverSegmentDiagnostics:
|
||||
"""Work performed by implicit solver instances inside one event segment."""
|
||||
|
||||
start_time: float
|
||||
requested_stop_time: float
|
||||
simulated_until: float
|
||||
nfev: int = 0
|
||||
njev: int = 0
|
||||
nlu: int = 0
|
||||
accepted_step_count: int = 0
|
||||
solver_start_count: int = 0
|
||||
state_transition_count: int = 0
|
||||
recoverable_retry_count: int = 0
|
||||
|
||||
def as_dict(self) -> dict[str, float | int]:
|
||||
return {
|
||||
"startTime": self.start_time,
|
||||
"requestedStopTime": self.requested_stop_time,
|
||||
"simulatedUntil": self.simulated_until,
|
||||
"nfev": self.nfev,
|
||||
"njev": self.njev,
|
||||
"nlu": self.nlu,
|
||||
"acceptedStepCount": self.accepted_step_count,
|
||||
"solverStartCount": self.solver_start_count,
|
||||
"stateTransitionCount": self.state_transition_count,
|
||||
"recoverableRetryCount": self.recoverable_retry_count,
|
||||
}
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ODESolution:
|
||||
t: list[float]
|
||||
@@ -52,6 +82,7 @@ class ODESolution:
|
||||
message: str
|
||||
status: IntegrationStatus = "completed"
|
||||
error: Exception | None = None
|
||||
solver_segments: tuple[SolverSegmentDiagnostics, ...] = ()
|
||||
|
||||
|
||||
def _vector_add(a: list[float], b: list[float], scale: float = 1.0) -> list[float]:
|
||||
@@ -610,6 +641,7 @@ def _integrate_scipy_stepwise(
|
||||
same_time_transition_count = 0
|
||||
integration_progressed = False
|
||||
last_reported_step: float | None = None
|
||||
solver_segments: list[SolverSegmentDiagnostics] = []
|
||||
|
||||
def cancellation_message() -> str:
|
||||
return (
|
||||
@@ -639,9 +671,17 @@ def _integrate_scipy_stepwise(
|
||||
math.nextafter(segment_end, -math.inf) if is_breakpoint else segment_end
|
||||
)
|
||||
has_integration_interval = integration_end > last_accepted_time
|
||||
segment_start_time = last_accepted_time
|
||||
segment_max_step = float(config.max_step)
|
||||
recoverable_retry_count = 0
|
||||
last_recoverable_error: RecoverableTrialStateError | None = None
|
||||
segment_nfev = 0
|
||||
segment_njev = 0
|
||||
segment_nlu = 0
|
||||
segment_accepted_steps = 0
|
||||
segment_solver_starts = 0
|
||||
segment_state_transitions = 0
|
||||
segment_recoverable_retries = 0
|
||||
|
||||
while has_integration_interval and last_accepted_time < integration_end:
|
||||
if cancel_check():
|
||||
@@ -681,6 +721,7 @@ def _integrate_scipy_stepwise(
|
||||
break
|
||||
except RecoverableTrialStateError as exc:
|
||||
recoverable_retry_count += 1
|
||||
segment_recoverable_retries += 1
|
||||
last_recoverable_error = exc
|
||||
next_step = 0.5 * segment_max_step
|
||||
minimum_step = 64.0 * math.ulp(max(abs(last_accepted_time), 1.0))
|
||||
@@ -697,6 +738,7 @@ def _integrate_scipy_stepwise(
|
||||
error = exc
|
||||
break
|
||||
|
||||
segment_solver_starts += 1
|
||||
|
||||
restart_at_transition = False
|
||||
restart_after_recoverable = False
|
||||
@@ -720,6 +762,7 @@ def _integrate_scipy_stepwise(
|
||||
break
|
||||
except RecoverableTrialStateError as exc:
|
||||
recoverable_retry_count += 1
|
||||
segment_recoverable_retries += 1
|
||||
last_recoverable_error = exc
|
||||
attempted_step = segment_max_step
|
||||
next_step = 0.5 * attempted_step
|
||||
@@ -744,6 +787,7 @@ def _integrate_scipy_stepwise(
|
||||
if solver.status == "failed":
|
||||
if last_recoverable_error is not None:
|
||||
recoverable_retry_count += 1
|
||||
segment_recoverable_retries += 1
|
||||
next_step = 0.5 * segment_max_step
|
||||
minimum_step = 64.0 * math.ulp(
|
||||
max(abs(last_accepted_time), 1.0)
|
||||
@@ -759,6 +803,7 @@ def _integrate_scipy_stepwise(
|
||||
message = str(step_message or "Integration step failed.")
|
||||
break
|
||||
|
||||
segment_accepted_steps += 1
|
||||
step_end_time = float(solver.t)
|
||||
step_end_state = [float(value) for value in solver.y]
|
||||
dense_output = (
|
||||
@@ -807,6 +852,7 @@ def _integrate_scipy_stepwise(
|
||||
break
|
||||
|
||||
if transition is not None:
|
||||
segment_state_transitions += 1
|
||||
try:
|
||||
same_time_transition_count = (
|
||||
_next_same_time_transition_count(
|
||||
@@ -896,6 +942,9 @@ def _integrate_scipy_stepwise(
|
||||
)
|
||||
report_step(reported_time)
|
||||
|
||||
segment_nfev += int(getattr(solver, "nfev", 0))
|
||||
segment_njev += int(getattr(solver, "njev", 0))
|
||||
segment_nlu += int(getattr(solver, "nlu", 0))
|
||||
if status != "completed":
|
||||
break
|
||||
if restart_after_recoverable:
|
||||
@@ -903,6 +952,22 @@ def _integrate_scipy_stepwise(
|
||||
if not restart_at_transition:
|
||||
break
|
||||
|
||||
solver_segments.append(
|
||||
SolverSegmentDiagnostics(
|
||||
start_time=float(segment_start_time),
|
||||
requested_stop_time=float(segment_end),
|
||||
simulated_until=float(
|
||||
segment_end if status == "completed" else last_accepted_time
|
||||
),
|
||||
nfev=segment_nfev,
|
||||
njev=segment_njev,
|
||||
nlu=segment_nlu,
|
||||
accepted_step_count=segment_accepted_steps,
|
||||
solver_start_count=segment_solver_starts,
|
||||
state_transition_count=segment_state_transitions,
|
||||
recoverable_retry_count=segment_recoverable_retries,
|
||||
)
|
||||
)
|
||||
if status != "completed":
|
||||
break
|
||||
|
||||
@@ -949,6 +1014,7 @@ def _integrate_scipy_stepwise(
|
||||
message=message,
|
||||
status=status,
|
||||
error=error,
|
||||
solver_segments=tuple(solver_segments),
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user