完善仿真交互、结果展示与模型元数据
This commit is contained in:
1 parent
f1256a121d
commit
f7f1078911
26 files changed
+9042
-575
No files matched your search
+28
-64
@@ -2,7 +2,6 @@ from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable, Mapping
|
||||
from dataclasses import dataclass
|
||||
from math import isfinite
|
||||
|
||||
from PythonModels.components.cylinder import Cylinder
|
||||
from PythonModels.components.orifice import Orifice
|
||||
@@ -10,29 +9,12 @@ from PythonModels.components.resistive_pipe import ResistivePipe
|
||||
from PythonModels.components.tank import Tank
|
||||
from PythonModels.components.tee import Tee
|
||||
from PythonModels.core.base import Component
|
||||
from PythonModels.core.metadata import ParameterDefinition
|
||||
from PythonModels.core.medium import IdealGasMedium
|
||||
from PythonModels.core.ports import PortDefinition
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ParameterSpec:
|
||||
name: str
|
||||
default: float
|
||||
minimum: float | None = None
|
||||
maximum: float | None = None
|
||||
minimum_exclusive: bool = False
|
||||
|
||||
def validation_message(self, value: float) -> str | None:
|
||||
if not isfinite(value):
|
||||
return "must be finite"
|
||||
if self.minimum is not None:
|
||||
if self.minimum_exclusive and value <= self.minimum:
|
||||
return f"must be greater than {self.minimum:g}"
|
||||
if not self.minimum_exclusive and value < self.minimum:
|
||||
return f"must be at least {self.minimum:g}"
|
||||
if self.maximum is not None and value > self.maximum:
|
||||
return f"must be at most {self.maximum:g}"
|
||||
return None
|
||||
ParameterSpec = ParameterDefinition
|
||||
|
||||
|
||||
ComponentFactory = Callable[
|
||||
@@ -45,11 +27,11 @@ ComponentFactory = Callable[
|
||||
class ComponentModelSpec:
|
||||
model_type: str
|
||||
ports: tuple[PortDefinition, ...]
|
||||
parameters: tuple[ParameterSpec, ...]
|
||||
parameters: tuple[ParameterDefinition, ...]
|
||||
factory: ComponentFactory
|
||||
|
||||
@property
|
||||
def parameter_by_name(self) -> dict[str, ParameterSpec]:
|
||||
def parameter_by_name(self) -> dict[str, ParameterDefinition]:
|
||||
return {parameter.name: parameter for parameter in self.parameters}
|
||||
|
||||
def create(
|
||||
@@ -77,6 +59,15 @@ class ComponentModelSpec:
|
||||
)
|
||||
component = self.factory(name, medium, resolved)
|
||||
component.model_type = self.model_type
|
||||
if component.port_definitions != self.ports:
|
||||
raise ValueError(
|
||||
f"Component implementation {self.model_type} does not match "
|
||||
"its declared ports."
|
||||
)
|
||||
if component.parameter_values != resolved:
|
||||
raise ValueError(
|
||||
f"Component implementation {self.model_type} did not preserve its parameters."
|
||||
)
|
||||
return component
|
||||
|
||||
|
||||
@@ -142,60 +133,33 @@ def _tee_factory(
|
||||
|
||||
COMPONENT_MODEL_REGISTRY: dict[str, ComponentModelSpec] = {
|
||||
"cylinder": ComponentModelSpec(
|
||||
model_type="cylinder",
|
||||
ports=(PortDefinition.pneumatic("port_b", nominal_role="outlet"),),
|
||||
parameters=(
|
||||
ParameterSpec("volume", 0.01, minimum=0.0, minimum_exclusive=True),
|
||||
ParameterSpec("p0", 35e6, minimum=0.0, minimum_exclusive=True),
|
||||
ParameterSpec("T0", 300.0, minimum=0.0, minimum_exclusive=True),
|
||||
),
|
||||
model_type=Cylinder.MODEL_TYPE,
|
||||
ports=Cylinder.PORTS,
|
||||
parameters=Cylinder.PARAMETERS,
|
||||
factory=_cylinder_factory,
|
||||
),
|
||||
"tank": ComponentModelSpec(
|
||||
model_type="tank",
|
||||
ports=(PortDefinition.pneumatic("port_a", nominal_role="inlet"),),
|
||||
parameters=(
|
||||
ParameterSpec("volume", 0.1, minimum=0.0, minimum_exclusive=True),
|
||||
ParameterSpec("p0", 1e5, minimum=0.0, minimum_exclusive=True),
|
||||
ParameterSpec("T0", 300.0, minimum=0.0, minimum_exclusive=True),
|
||||
),
|
||||
model_type=Tank.MODEL_TYPE,
|
||||
ports=Tank.PORTS,
|
||||
parameters=Tank.PARAMETERS,
|
||||
factory=_tank_factory,
|
||||
),
|
||||
"pipe": ComponentModelSpec(
|
||||
model_type="pipe",
|
||||
ports=(
|
||||
PortDefinition.pneumatic("port_a", nominal_role="inlet"),
|
||||
PortDefinition.pneumatic("port_b", nominal_role="outlet"),
|
||||
),
|
||||
parameters=(
|
||||
ParameterSpec("length", 5.0, minimum=0.0, minimum_exclusive=True),
|
||||
ParameterSpec("diameter", 0.02, minimum=0.0, minimum_exclusive=True),
|
||||
ParameterSpec("lambda_darcy", 0.02, minimum=0.0),
|
||||
ParameterSpec("p0", 1e5, minimum=0.0, minimum_exclusive=True),
|
||||
ParameterSpec("T0", 300.0, minimum=0.0, minimum_exclusive=True),
|
||||
),
|
||||
model_type=ResistivePipe.MODEL_TYPE,
|
||||
ports=ResistivePipe.PORTS,
|
||||
parameters=ResistivePipe.PARAMETERS,
|
||||
factory=_pipe_factory,
|
||||
),
|
||||
"orifice": ComponentModelSpec(
|
||||
model_type="orifice",
|
||||
ports=(
|
||||
PortDefinition.pneumatic("port_a", nominal_role="inlet"),
|
||||
PortDefinition.pneumatic("port_b", nominal_role="outlet"),
|
||||
),
|
||||
parameters=(
|
||||
ParameterSpec("K", 1e-5, minimum=0.0),
|
||||
ParameterSpec("opening", 1.0, minimum=0.0, maximum=1.0),
|
||||
),
|
||||
model_type=Orifice.MODEL_TYPE,
|
||||
ports=Orifice.PORTS,
|
||||
parameters=Orifice.PARAMETERS,
|
||||
factory=_orifice_factory,
|
||||
),
|
||||
"tee": ComponentModelSpec(
|
||||
model_type="tee",
|
||||
ports=(
|
||||
PortDefinition.pneumatic("port_in", nominal_role="bidirectional"),
|
||||
PortDefinition.pneumatic("port_out1", nominal_role="bidirectional"),
|
||||
PortDefinition.pneumatic("port_out2", nominal_role="bidirectional"),
|
||||
),
|
||||
parameters=(),
|
||||
model_type=Tee.MODEL_TYPE,
|
||||
ports=Tee.PORTS,
|
||||
parameters=Tee.PARAMETERS,
|
||||
factory=_tee_factory,
|
||||
),
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user