公开更多 AMESim 组件并接入信号机械闭环
This commit is contained in:
1 parent
db4bdb4b70
commit
3f51a124d6
28 files changed
+3397
-58
No files matched your search
@@ -0,0 +1,62 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Protocol
|
||||
|
||||
from app.simulation.systems.network import Endpoint, SimulationNetwork
|
||||
|
||||
|
||||
class SignalOutputComponent(Protocol):
|
||||
name: str
|
||||
|
||||
def signal_output_values(self, time: float) -> dict[str, float]:
|
||||
...
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class SignalSolveDiagnostics:
|
||||
propagated: int
|
||||
|
||||
def as_dict(self) -> dict[str, object]:
|
||||
return {"propagated": self.propagated}
|
||||
|
||||
|
||||
class SignalResolver:
|
||||
"""Propagate scalar signal connections from output ports to input ports."""
|
||||
|
||||
def __init__(self, network: SimulationNetwork) -> None:
|
||||
self.network = network
|
||||
self._connections = [
|
||||
connection for connection in network.connections if connection.kind == "signal"
|
||||
]
|
||||
self.last_diagnostics: SignalSolveDiagnostics | None = None
|
||||
|
||||
def solve(self, time: float) -> SignalSolveDiagnostics:
|
||||
for component in self.network.components.values():
|
||||
signal_output_values = getattr(component, "signal_output_values", None)
|
||||
if signal_output_values is None:
|
||||
continue
|
||||
for port_name, value in signal_output_values(time).items():
|
||||
component.get_port(port_name).signal = float(value)
|
||||
|
||||
propagated = 0
|
||||
for connection in self._connections:
|
||||
source, target = self._source_target(connection.endpoints)
|
||||
source_port = self.network.components[source.component].get_port(source.port)
|
||||
target_port = self.network.components[target.component].get_port(target.port)
|
||||
target_port.signal = source_port.signal
|
||||
propagated += 1
|
||||
|
||||
diagnostics = SignalSolveDiagnostics(propagated=propagated)
|
||||
self.last_diagnostics = diagnostics
|
||||
return diagnostics
|
||||
|
||||
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)
|
||||
second_port = self.network.components[second.component].get_port(second.port)
|
||||
if first_port.definition is not None and first_port.definition.nominal_role == "output":
|
||||
return first, second
|
||||
if second_port.definition is not None and second_port.definition.nominal_role == "output":
|
||||
return second, first
|
||||
raise ValueError("Signal connection must contain one output endpoint.")
|
||||
Reference in new issue
Block a user