完善AMESim组件界面与仿真求解稳定性
This commit is contained in:
1 parent
e7177ab03e
commit
410ef535e8
34 files changed
+3340
-251
No files matched your search
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from math import isfinite
|
||||
from typing import Protocol
|
||||
|
||||
from app.simulation.systems.network import Endpoint, SimulationNetwork
|
||||
@@ -13,6 +14,21 @@ class SignalOutputComponent(Protocol):
|
||||
...
|
||||
|
||||
|
||||
class SignalEventSource(Protocol):
|
||||
"""Optional contract for signal sources with known time discontinuities."""
|
||||
|
||||
name: str
|
||||
|
||||
def signal_event_times(
|
||||
self,
|
||||
start_time: float,
|
||||
stop_time: float,
|
||||
) -> tuple[float, ...]:
|
||||
"""Return event times strictly inside ``(start_time, stop_time)``."""
|
||||
|
||||
...
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SignalSolveDiagnostics:
|
||||
propagated: int
|
||||
@@ -51,6 +67,37 @@ class SignalResolver:
|
||||
self.last_diagnostics = diagnostics
|
||||
return diagnostics
|
||||
|
||||
def event_times(self, start_time: float, stop_time: float) -> tuple[float, ...]:
|
||||
"""Collect optional source events that can be used as integration splits.
|
||||
|
||||
Event discovery is deliberately duck typed so existing signal-output
|
||||
components remain valid without implementing ``signal_event_times``.
|
||||
"""
|
||||
|
||||
start = float(start_time)
|
||||
stop = float(stop_time)
|
||||
if not isfinite(start) or not isfinite(stop):
|
||||
raise ValueError("Signal event interval must be finite.")
|
||||
if stop < start:
|
||||
raise ValueError("Signal event interval stop must not precede start.")
|
||||
if stop == start:
|
||||
return ()
|
||||
|
||||
events: set[float] = set()
|
||||
for component in self.network.components.values():
|
||||
source_event_times = getattr(component, "signal_event_times", None)
|
||||
if source_event_times is None:
|
||||
continue
|
||||
for raw_time in source_event_times(start, stop):
|
||||
event_time = float(raw_time)
|
||||
if not isfinite(event_time):
|
||||
raise ValueError(
|
||||
f"Signal event time from component '{component.name}' must be finite."
|
||||
)
|
||||
if start < event_time < stop:
|
||||
events.add(event_time)
|
||||
return tuple(sorted(events))
|
||||
|
||||
def _source_target(self, endpoints: tuple[Endpoint, Endpoint]) -> tuple[Endpoint, Endpoint]:
|
||||
first, second = endpoints
|
||||
first_port = self.network.components[first.component].get_port(first.port)
|
||||
|
||||
Reference in new issue
Block a user