from __future__ import annotations from collections.abc import Mapping from app.simulation.core.base import AlgebraicComponent from app.simulation.core.catalog import ComponentDisplaySpec, PortDisplaySpec from app.simulation.core.equations import EquationResidual from app.simulation.core.medium import IdealGasMedium from app.simulation.core.ports import PortDefinition class AmesimPnpl01(AlgebraicComponent): """AMESim PNPL01 zero pneumatic flow source. The component behaves as a sealed pneumatic boundary in the current acausal solver: it does not prescribe pressure, and only constrains its port mass flow to zero. """ MODEL_TYPE = "amesim_pnpl01" MODEL_VERSION = "0.1.0" PORTS = (PortDefinition.pneumatic("port_1", nominal_role="bidirectional"),) PARAMETERS = () RESULT_VARIABLES = () DISPLAY = ComponentDisplaySpec( label="PNPL01 零气动流边界", library_id="amesim", category_id="boundary", symbol="amesim_pnpl01", ports=(PortDisplaySpec("port_1", "left", order=10),), order=10, ) def __init__(self, name: str) -> None: super().__init__(name=name) self.set_parameter_values({}) self.port_1 = self.register_declared_port("port_1") @classmethod def create( cls, *, name: str, medium: IdealGasMedium, parameters: Mapping[str, float], ) -> AmesimPnpl01: return cls(name=name) def pressure_flow_equation_residuals(self) -> tuple[EquationResidual, ...]: return ( EquationResidual( id=f"{self.name}:zero_mass_flow", owner="component", owner_id=self.name, relation="constitutive", variables=(f"{self.name}.port_1.m_flow",), role="flow", value=self.port_1.m_flow, ), ) def update_stream_outflows(self, connected_h: Mapping[str, float]) -> None: if "port_1" in connected_h: self.port_1.h_outflow = connected_h["port_1"]