完善AMESim可配置参数交互

补充气动孔口、动态管路、UD00 与弹性接触组件的离散选项、条件显示和折叠分组。

增加目录协议、非法选项和前端参数表交互回归测试,不修改现有求解公式。
This commit is contained in:
ljz committed 2026-08-04 01:27:17 +08:00
1 parent be54070855
commit df1d676131
12 files changed
+1262 -69

No files matched your search

+111 -10
View File
@@ -8,16 +8,44 @@ from app.simulation.components.amesim.gases import (
normalize_amesim_gas_index,
)
from app.simulation.core.base import AlgebraicComponent
from app.simulation.core.catalog import ComponentDisplaySpec, PortDisplaySpec
from app.simulation.core.catalog import (
ComponentDisplaySpec,
ParameterGroupDisplaySpec,
PortDisplaySpec,
)
from app.simulation.core.equations import EquationResidual
from app.simulation.core.metadata import (
ParameterCondition,
ParameterDefinition,
ParameterOption,
ResultVariableDefinition,
)
from app.simulation.core.medium import GasMedium
from app.simulation.core.ports import PortDefinition
_FLOW_COEFFICIENT_OPTIONS = (
ParameterOption(1.0, "Cq"),
ParameterOption(2.0, "Cv"),
ParameterOption(3.0, "Kv"),
)
_FLOWSET_USES_CQ = (ParameterCondition("flowset", (1.0,)),)
_FLOWSET_USES_CV = (ParameterCondition("flowset", (2.0,)),)
_FLOWSET_USES_KV = (ParameterCondition("flowset", (3.0,)),)
_PNOR001_FLOW_COEFFICIENT_GROUP = ParameterGroupDisplaySpec(
id="flow_coefficient",
label="流量系数",
parameters=("cq", "area", "Cv", "Kv"),
order=10,
)
_PNVO001_FLOW_COEFFICIENT_GROUP = ParameterGroupDisplaySpec(
id="flow_coefficient",
label="流量系数",
parameters=("cq", "area0", "Cv", "Kv"),
order=10,
)
class AmesimPnor001(AlgebraicComponent):
"""AMESim PNOR001 constant-flow-coefficient pneumatic orifice.
@@ -27,7 +55,7 @@ class AmesimPnor001(AlgebraicComponent):
"""
MODEL_TYPE = "amesim_pnor001"
MODEL_VERSION = "0.1.0"
MODEL_VERSION = "0.2.0"
PORTS = (
PortDefinition.pneumatic("port_1", nominal_role="bidirectional"),
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
@@ -43,6 +71,7 @@ class AmesimPnor001(AlgebraicComponent):
minimum=1.0e-10,
maximum=1.0,
description="孔口实际质量流量相对于理想可压缩流量的无量纲修正系数。",
visible_when=_FLOWSET_USES_CQ,
),
ParameterDefinition(
"area",
@@ -53,6 +82,7 @@ class AmesimPnor001(AlgebraicComponent):
minimum=0.0,
maximum=1.0,
description="选择 Cq/面积方式时用于流量计算的有效孔口面积。",
visible_when=_FLOWSET_USES_CQ,
),
ParameterDefinition(
"Cv",
@@ -62,6 +92,7 @@ class AmesimPnor001(AlgebraicComponent):
unit="",
minimum=0.0,
description="选择 Cv 方式时使用的英制流量系数。",
visible_when=_FLOWSET_USES_CV,
),
ParameterDefinition(
"Kv",
@@ -71,6 +102,7 @@ class AmesimPnor001(AlgebraicComponent):
unit="",
minimum=0.0,
description="选择 Kv 方式时使用的公制流量系数。",
visible_when=_FLOWSET_USES_KV,
),
ParameterDefinition(
"flowset",
@@ -80,6 +112,8 @@ class AmesimPnor001(AlgebraicComponent):
unit="",
minimum=1.0,
maximum=3.0,
editor="choice",
options=_FLOW_COEFFICIENT_OPTIONS,
description="流量参数方式:1 使用 Cq 和面积,2 使用 Cv,3 使用 Kv。",
),
)
@@ -111,6 +145,7 @@ class AmesimPnor001(AlgebraicComponent):
PortDisplaySpec("port_2", "right", order=20),
),
order=10,
parameter_groups=(_PNOR001_FLOW_COEFFICIENT_GROUP,),
)
def __init__(
@@ -320,7 +355,7 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
"""
MODEL_TYPE = "amesim_pnvo001_fixed"
MODEL_VERSION = "0.1.0"
MODEL_VERSION = "0.2.0"
PORTS = (
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
PortDefinition.pneumatic("port_3", nominal_role="bidirectional"),
@@ -336,6 +371,7 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
minimum=1.0e-10,
maximum=1.0,
description="孔口实际质量流量相对于理想可压缩流量的无量纲修正系数。",
visible_when=_FLOWSET_USES_CQ,
),
ParameterDefinition(
"area0",
@@ -346,6 +382,7 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
minimum=0.0,
maximum=1.0,
description="阀门完全开启时的最大有效孔口面积。",
visible_when=_FLOWSET_USES_CQ,
),
ParameterDefinition(
"Cv",
@@ -355,6 +392,7 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
unit="",
minimum=0.0,
description="选择 Cv 方式时使用的最大英制流量系数。",
visible_when=_FLOWSET_USES_CV,
),
ParameterDefinition(
"Kv",
@@ -364,6 +402,7 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
unit="",
minimum=0.0,
description="选择 Kv 方式时使用的最大公制流量系数。",
visible_when=_FLOWSET_USES_KV,
),
ParameterDefinition(
"flowset",
@@ -373,6 +412,8 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
unit="",
minimum=1.0,
maximum=3.0,
editor="choice",
options=_FLOW_COEFFICIENT_OPTIONS,
description="流量参数方式:1 使用 Cq 和面积,2 使用 Cv,3 使用 Kv。",
),
ParameterDefinition(
@@ -422,6 +463,7 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
PortDisplaySpec("port_3", "right", order=20),
),
order=30,
parameter_groups=(_PNVO001_FLOW_COEFFICIENT_GROUP,),
)
def __init__(
@@ -685,7 +727,7 @@ class AmesimPnvo001SignalOpening(AmesimPnvo001FixedOpening):
"""AMESim PNVO001 signal-controlled pneumatic orifice."""
MODEL_TYPE = "amesim_pnvo001"
MODEL_VERSION = "0.1.0"
MODEL_VERSION = "0.2.0"
PORTS = (
PortDefinition.signal("res", nominal_role="input"),
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
@@ -693,12 +735,70 @@ class AmesimPnvo001SignalOpening(AmesimPnvo001FixedOpening):
)
PARAMETERS = (
AMESIM_GAS_INDEX_PARAMETER,
ParameterDefinition("cq", 0.72, label="流量系数 Cq", quantity="dimensionless", unit="", minimum=1.0e-10, maximum=1.0),
ParameterDefinition("area0", 5.0e-6, label="最大孔口面积", quantity="area", unit="m2", minimum=0.0, maximum=1.0),
ParameterDefinition("Cv", 0.5, label="最大流量系数 Cv", quantity="dimensionless", unit="", minimum=0.0),
ParameterDefinition("Kv", 0.4, label="最大流量系数 Kv", quantity="dimensionless", unit="", minimum=0.0),
ParameterDefinition("flowset", 1.0, label="流量系数设置", quantity="dimensionless", unit="", minimum=1.0, maximum=3.0),
ParameterDefinition("opening0", 1.0, label="初始开度", quantity="dimensionless", unit="", minimum=0.0, maximum=1.0),
ParameterDefinition(
"cq",
0.72,
label="流量系数 Cq",
quantity="dimensionless",
unit="",
minimum=1.0e-10,
maximum=1.0,
description="孔口实际质量流量相对于理想可压缩流量的无量纲修正系数。",
visible_when=_FLOWSET_USES_CQ,
),
ParameterDefinition(
"area0",
5.0e-6,
label="最大孔口面积",
quantity="area",
unit="m2",
minimum=0.0,
maximum=1.0,
description="阀门完全开启时的最大有效孔口面积。",
visible_when=_FLOWSET_USES_CQ,
),
ParameterDefinition(
"Cv",
0.5,
label="最大流量系数 Cv",
quantity="dimensionless",
unit="",
minimum=0.0,
description="选择 Cv 方式时使用的最大英制流量系数。",
visible_when=_FLOWSET_USES_CV,
),
ParameterDefinition(
"Kv",
0.4,
label="最大流量系数 Kv",
quantity="dimensionless",
unit="",
minimum=0.0,
description="选择 Kv 方式时使用的最大公制流量系数。",
visible_when=_FLOWSET_USES_KV,
),
ParameterDefinition(
"flowset",
1.0,
label="流量系数设置",
quantity="dimensionless",
unit="",
minimum=1.0,
maximum=3.0,
editor="choice",
options=_FLOW_COEFFICIENT_OPTIONS,
description="流量参数方式:1 使用 Cq 和面积,2 使用 Cv,3 使用 Kv。",
),
ParameterDefinition(
"opening0",
1.0,
label="初始开度",
quantity="dimensionless",
unit="",
minimum=0.0,
maximum=1.0,
description="信号尚未传播时使用的归一化初始开度;0 表示关闭,1 表示完全开启。",
),
)
RESULT_VARIABLES = AmesimPnvo001FixedOpening.RESULT_VARIABLES
DISPLAY = ComponentDisplaySpec(
@@ -712,6 +812,7 @@ class AmesimPnvo001SignalOpening(AmesimPnvo001FixedOpening):
PortDisplaySpec("port_3", "right", order=20),
),
order=35,
parameter_groups=(_PNVO001_FLOW_COEFFICIENT_GROUP,),
)
def __init__(
+48 -9
View File
@@ -8,10 +8,16 @@ from app.simulation.components.amesim.gases import (
normalize_amesim_gas_index,
)
from app.simulation.core.base import AlgebraicComponent, DynamicComponent, ThermodynamicVolumeComponent
from app.simulation.core.catalog import ComponentDisplaySpec, PortDisplaySpec
from app.simulation.core.catalog import (
ComponentDisplaySpec,
ParameterGroupDisplaySpec,
PortDisplaySpec,
)
from app.simulation.core.equations import EquationResidual
from app.simulation.core.metadata import (
ParameterCondition,
ParameterDefinition,
ParameterOption,
ResultVariableDefinition,
THERMODYNAMIC_VOLUME_RESULT_VARIABLES,
)
@@ -20,6 +26,18 @@ from app.simulation.core.ports import PortDefinition
from app.simulation.core.state import VolumeState
_DYNAMIC_PIPE_POLYTROPIC_MODE = ParameterCondition("mode", (1.0,))
_DYNAMIC_PIPE_HEAT_EXCHANGE_MODE = ParameterCondition("mode", (2.0,))
_DYNAMIC_PIPE_PARAMETER_GROUPS = (
ParameterGroupDisplaySpec(
id="thermodynamics",
label="热力学",
parameters=("k", "kth", "extemp"),
order=10,
),
)
class AmesimPnl00r(AlgebraicComponent):
"""AMESim PNL00R pneumatic pipe friction resistance.
@@ -308,7 +326,7 @@ class AmesimPnl0001(ThermodynamicVolumeComponent):
"""AMESim PNL0001 C-R pneumatic pipe with compressibility and friction."""
MODEL_TYPE = "amesim_pnl0001"
MODEL_VERSION = "0.1.0"
MODEL_VERSION = "0.2.0"
PORTS = (
PortDefinition.pneumatic("port_1", nominal_role="bidirectional"),
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
@@ -354,7 +372,11 @@ class AmesimPnl0001(ThermodynamicVolumeComponent):
minimum=0.0,
minimum_exclusive=True,
maximum=2.0,
description="AMESim 管路热力学配置使用的多方指数。",
description=(
"mode=1 多方过程使用的指数;当前公开求解器保留该 AMESim "
"配置,尚未实现多方指数对状态方程的修正。"
),
visible_when=(_DYNAMIC_PIPE_POLYTROPIC_MODE,),
),
ParameterDefinition(
"kth",
@@ -363,7 +385,8 @@ class AmesimPnl0001(ThermodynamicVolumeComponent):
quantity="heat_transfer_coefficient",
unit="W/(m2*K)",
minimum=0.0,
description="管内气体与外部环境之间的对流换热系数。",
description="mode=2 带换热过程使用的气体与外部环境对流换热系数。",
visible_when=(_DYNAMIC_PIPE_HEAT_EXCHANGE_MODE,),
),
ParameterDefinition(
"extemp",
@@ -373,7 +396,8 @@ class AmesimPnl0001(ThermodynamicVolumeComponent):
unit="K",
minimum=0.0,
minimum_exclusive=True,
description="管路外部环境的绝对温度,用于计算换热功率。",
description="mode=2 带换热过程使用的外部环境绝对温度。",
visible_when=(_DYNAMIC_PIPE_HEAT_EXCHANGE_MODE,),
),
ParameterDefinition(
"mode",
@@ -383,7 +407,16 @@ class AmesimPnl0001(ThermodynamicVolumeComponent):
unit="",
minimum=1.0,
maximum=2.0,
description="热模型选择:1 为绝热,2 为按换热系数计算环境换热。",
editor="choice",
options=(
ParameterOption(1.0, "多方过程"),
ParameterOption(2.0, "带换热"),
),
description=(
"AMESim 原始编码:1 为多方过程,2 为带换热。当前公开求解器在"
"多方模式下关闭环境换热,在带换热模式下按换热系数和外部温度"
"计算环境换热。"
),
),
ParameterDefinition(
"p0",
@@ -450,6 +483,7 @@ class AmesimPnl0001(ThermodynamicVolumeComponent):
PortDisplaySpec("port_2", "right", order=20),
),
order=30,
parameter_groups=_DYNAMIC_PIPE_PARAMETER_GROUPS,
)
def __init__(
@@ -513,7 +547,10 @@ class AmesimPnl0001(ThermodynamicVolumeComponent):
rounded = round(value)
if not isclose(value, rounded, rel_tol=0.0, abs_tol=1.0e-12):
raise ValueError(f"PNL0001 parameter {name} must be an integer value.")
return int(rounded)
integer = int(rounded)
if name == "mode" and integer not in {1, 2}:
raise ValueError("PNL0001 parameter mode must be one of 1, 2.")
return integer
@classmethod
def create(
@@ -713,7 +750,7 @@ class AmesimPnl0002(AmesimPnl0001):
"""AMESim PNL0002 R-C-R pneumatic pipe with one center compliance."""
MODEL_TYPE = "amesim_pnl0002"
MODEL_VERSION = "0.1.0"
MODEL_VERSION = "0.2.0"
PORTS = (
PortDefinition.pneumatic("port_1", nominal_role="bidirectional"),
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
@@ -730,6 +767,7 @@ class AmesimPnl0002(AmesimPnl0001):
PortDisplaySpec("port_2", "right", order=20),
),
order=40,
parameter_groups=_DYNAMIC_PIPE_PARAMETER_GROUPS,
)
@classmethod
@@ -856,7 +894,7 @@ class AmesimPnl0003(DynamicComponent):
state_size = 4
MODEL_TYPE = "amesim_pnl0003"
MODEL_VERSION = "0.1.0"
MODEL_VERSION = "0.2.0"
PORTS = (
PortDefinition.pneumatic("port_1", nominal_role="bidirectional"),
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
@@ -930,6 +968,7 @@ class AmesimPnl0003(DynamicComponent):
PortDisplaySpec("port_2", "right", order=20),
),
order=50,
parameter_groups=_DYNAMIC_PIPE_PARAMETER_GROUPS,
)
def __init__(
@@ -27,6 +27,8 @@ _MECMAS21_ELASTIC_STOP = ParameterCondition("stoptype", (2.0,))
_MECMAS21_RESTITUTION_STOP = ParameterCondition("stoptype", (3.0,))
_MECMAS21_ADVANCED_FRICTION = ParameterCondition("frictionType", (2.0,))
_MECMAS21_STRIBECK_ENABLED = ParameterCondition("strib", (2.0,))
_LSTP00A_NUMERICAL_STIFFNESS = ParameterCondition("stiffmode", (1.0,))
_LSTP00A_GEOMETRICAL_STIFFNESS = ParameterCondition("stiffmode", (2.0,))
class AmesimF000(AlgebraicComponent):
@@ -713,22 +715,126 @@ class AmesimLstp00a(AlgebraicComponent):
"""AMESim LSTP00A first public elastic contact component."""
MODEL_TYPE = "amesim_lstp00a"
MODEL_VERSION = "0.1.0"
MODEL_VERSION = "0.2.0"
PORTS = (
PortDefinition.mechanical_translational("port_1"),
PortDefinition.mechanical_translational("port_2"),
)
PARAMETERS = (
ParameterDefinition("na", 10.0, label="有效圈数", quantity="dimensionless", unit="", minimum=0.0, minimum_exclusive=True),
ParameterDefinition("gap0", 0.0, label="初始间隙", quantity="length", unit="m"),
ParameterDefinition("kcont", 1.0e6, label="接触刚度", quantity="translational_stiffness", unit="N/m", minimum=0.0),
ParameterDefinition("G", 8.57e10, label="剪切模量", quantity="pressure", unit="Pa", minimum=0.0),
ParameterDefinition("sdiam", 0.02, label="弹簧直径", quantity="length", unit="m", minimum=0.0),
ParameterDefinition("wdiam", 0.002, label="线径", quantity="length", unit="m", minimum=0.0),
ParameterDefinition("rcont", 0.0, label="接触阻尼", quantity="translational_damping", unit="N/(m/s)", minimum=0.0),
ParameterDefinition("Pdis", 1.0e-7, label="满阻尼穿透", quantity="length", unit="m", minimum=0.0),
ParameterDefinition("stiffmode", 1.0, label="刚度模式", quantity="dimensionless", unit="", minimum=0.0),
ParameterDefinition("discContactOption", 1.0, label="接触选项", quantity="dimensionless", unit="", minimum=0.0),
ParameterDefinition(
"na",
10.0,
label="有效圈数",
quantity="dimensionless",
unit="",
minimum=0.0,
minimum_exclusive=True,
description="几何刚度模式下使用的弹簧有效圈数。",
visible_when=(_LSTP00A_GEOMETRICAL_STIFFNESS,),
),
ParameterDefinition(
"gap0",
0.0,
label="初始间隙",
quantity="length",
unit="m",
description="两个机械端口开始产生接触力前的初始间隙。",
),
ParameterDefinition(
"kcont",
1.0e6,
label="接触刚度",
quantity="translational_stiffness",
unit="N/m",
minimum=0.0,
description="数值刚度模式下直接指定的接触刚度。",
visible_when=(_LSTP00A_NUMERICAL_STIFFNESS,),
),
ParameterDefinition(
"G",
8.57e10,
label="剪切模量",
quantity="pressure",
unit="Pa",
minimum=0.0,
description="几何刚度模式下的材料剪切模量。",
visible_when=(_LSTP00A_GEOMETRICAL_STIFFNESS,),
),
ParameterDefinition(
"sdiam",
0.02,
label="弹簧直径",
quantity="length",
unit="m",
minimum=0.0,
description="几何刚度模式下的弹簧平均直径。",
visible_when=(_LSTP00A_GEOMETRICAL_STIFFNESS,),
),
ParameterDefinition(
"wdiam",
0.002,
label="线径",
quantity="length",
unit="m",
minimum=0.0,
description="几何刚度模式下的弹簧线径。",
visible_when=(_LSTP00A_GEOMETRICAL_STIFFNESS,),
),
ParameterDefinition(
"rcont",
0.0,
label="接触阻尼",
quantity="translational_damping",
unit="N/(m/s)",
minimum=0.0,
description="接触穿透过程中使用的最大阻尼系数。",
),
ParameterDefinition(
"Pdis",
1.0e-7,
label="满阻尼穿透",
quantity="length",
unit="m",
minimum=0.0,
description="接触阻尼由零增至全值所需的穿透量。",
),
ParameterDefinition(
"stiffmode",
1.0,
label="刚度模式",
quantity="dimensionless",
unit="",
minimum=1.0,
maximum=2.0,
editor="choice",
options=(
ParameterOption(1.0, "数值刚度"),
ParameterOption(2.0, "几何参数"),
),
description=(
"AMESim 原始编码:1 直接使用接触刚度,2 使用弹簧几何参数。"
"当前公开求解器尚未实现由几何参数换算刚度,几何模式仍沿用"
"已保存的接触刚度值。"
),
),
ParameterDefinition(
"discContactOption",
1.0,
label="允许负接触力",
quantity="dimensionless",
unit="",
minimum=1.0,
maximum=2.0,
editor="choice",
options=(
ParameterOption(1.0, "允许负接触力"),
ParameterOption(2.0, "不允许负接触力"),
),
description=(
"AMESim 原始编码:1 保留阻尼项可能产生的负接触力,"
"2 将接触力限制为非负。"
),
),
)
RESULT_VARIABLES = (
ResultVariableDefinition("gap", "间隙", "length", "m", "derived", 10),
@@ -745,6 +851,20 @@ class AmesimLstp00a(AlgebraicComponent):
PortDisplaySpec("port_2", "right", order=20),
),
order=40,
parameter_groups=(
ParameterGroupDisplaySpec(
id="stiffness",
label="刚度",
parameters=("kcont", "G", "sdiam", "wdiam", "na"),
order=10,
),
ParameterGroupDisplaySpec(
id="contact",
label="接触",
parameters=("gap0", "rcont", "Pdis"),
order=20,
),
),
)
def __init__(self, name: str, medium: IdealGasMedium, **parameters: float) -> None:
@@ -773,9 +893,14 @@ class AmesimLstp00a(AlgebraicComponent):
medium: IdealGasMedium,
parameters: Mapping[str, float],
) -> "AmesimLstp00a":
definitions = {definition.name: definition for definition in cls.PARAMETERS}
for integer_name in ("stiffmode", "discContactOption"):
if not float(parameters[integer_name]).is_integer():
value = float(parameters[integer_name])
if not value.is_integer():
raise ValueError(f"LSTP00A {integer_name} must be an integer.")
message = definitions[integer_name].validation_message(value)
if message is not None:
raise ValueError(f"LSTP00A {integer_name} {message}.")
return cls(name=name, medium=medium, **dict(parameters))
@property
@@ -4,12 +4,71 @@ from collections.abc import Mapping
from math import floor
from app.simulation.core.base import AlgebraicComponent
from app.simulation.core.catalog import ComponentDisplaySpec, PortDisplaySpec
from app.simulation.core.metadata import ParameterDefinition, ResultVariableDefinition
from app.simulation.core.catalog import (
ComponentDisplaySpec,
ParameterGroupDisplaySpec,
PortDisplaySpec,
)
from app.simulation.core.metadata import (
ParameterCondition,
ParameterDefinition,
ParameterOption,
ResultVariableDefinition,
)
from app.simulation.core.medium import IdealGasMedium
from app.simulation.core.ports import PortDefinition
def _ud00_stage_parameters(index: int) -> tuple[ParameterDefinition, ...]:
visible_when = (
()
if index == 1
else (
ParameterCondition(
"nstages",
tuple(float(stage_count) for stage_count in range(index, 9)),
),
)
)
return (
ParameterDefinition(
f"start{index}",
0.0 if index == 1 else 1.0,
label=f"第 {index} 段起点",
quantity="dimensionless",
unit="",
description=f"第 {index} 段开始时的输出值。",
visible_when=visible_when,
),
ParameterDefinition(
f"end{index}",
1.0,
label=f"第 {index} 段终点",
quantity="dimensionless",
unit="",
description=f"第 {index} 段结束时的输出值。",
visible_when=visible_when,
),
ParameterDefinition(
f"t{index}",
1.0 if index == 1 else 0.0,
label=f"第 {index} 段时长",
quantity="time",
unit="s",
minimum=0.0,
description=f"第 {index} 段的持续时间。",
visible_when=visible_when,
),
)
_UD00_STAGE_PARAMETERS = tuple(
parameter
for stage_index in range(1, 9)
for parameter in _ud00_stage_parameters(stage_index)
)
class AmesimStep0(AlgebraicComponent):
"""AMESim STEP0 scalar step signal source."""
@@ -89,36 +148,48 @@ class AmesimUd00(AlgebraicComponent):
"""AMESim UD00 piecewise-linear scalar signal source."""
MODEL_TYPE = "amesim_ud00"
MODEL_VERSION = "0.1.0"
MODEL_VERSION = "0.2.0"
PORTS = (PortDefinition.signal("out", nominal_role="output"),)
PARAMETERS = (
ParameterDefinition("tstart", 0.0, label="启动时间", quantity="time", unit="s"),
ParameterDefinition("start1", 0.0, label="第 1 段起点", quantity="dimensionless", unit=""),
ParameterDefinition("end1", 1.0, label="第 1 段终点", quantity="dimensionless", unit=""),
ParameterDefinition("t1", 1.0, label="第 1 段时长", quantity="time", unit="s", minimum=0.0),
ParameterDefinition("start2", 1.0, label="第 2 段起点", quantity="dimensionless", unit=""),
ParameterDefinition("end2", 1.0, label="第 2 段终点", quantity="dimensionless", unit=""),
ParameterDefinition("t2", 0.0, label="第 2 段时长", quantity="time", unit="s", minimum=0.0),
ParameterDefinition("start3", 1.0, label="第 3 段起点", quantity="dimensionless", unit=""),
ParameterDefinition("end3", 1.0, label="第 3 段终点", quantity="dimensionless", unit=""),
ParameterDefinition("t3", 0.0, label="第 3 段时长", quantity="time", unit="s", minimum=0.0),
ParameterDefinition("start4", 1.0, label="第 4 段起点", quantity="dimensionless", unit=""),
ParameterDefinition("end4", 1.0, label="第 4 段终点", quantity="dimensionless", unit=""),
ParameterDefinition("t4", 0.0, label="第 4 段时长", quantity="time", unit="s", minimum=0.0),
ParameterDefinition("start5", 1.0, label="第 5 段起点", quantity="dimensionless", unit=""),
ParameterDefinition("end5", 1.0, label="第 5 段终点", quantity="dimensionless", unit=""),
ParameterDefinition("t5", 0.0, label="第 5 段时长", quantity="time", unit="s", minimum=0.0),
ParameterDefinition("start6", 1.0, label="第 6 段起点", quantity="dimensionless", unit=""),
ParameterDefinition("end6", 1.0, label="第 6 段终点", quantity="dimensionless", unit=""),
ParameterDefinition("t6", 0.0, label="第 6 段时长", quantity="time", unit="s", minimum=0.0),
ParameterDefinition("start7", 1.0, label="第 7 段起点", quantity="dimensionless", unit=""),
ParameterDefinition("end7", 1.0, label="第 7 段终点", quantity="dimensionless", unit=""),
ParameterDefinition("t7", 0.0, label="第 7 段时长", quantity="time", unit="s", minimum=0.0),
ParameterDefinition("start8", 1.0, label="第 8 段起点", quantity="dimensionless", unit=""),
ParameterDefinition("end8", 1.0, label="第 8 段终点", quantity="dimensionless", unit=""),
ParameterDefinition("t8", 0.0, label="第 8 段时长", quantity="time", unit="s", minimum=0.0),
ParameterDefinition("nstages", 1.0, label="段数", quantity="dimensionless", unit="", minimum=1.0, maximum=8.0),
ParameterDefinition("iscyclic", 0.0, label="循环", quantity="dimensionless", unit="", minimum=0.0, maximum=1.0),
ParameterDefinition(
"tstart",
0.0,
label="启动时间",
quantity="time",
unit="s",
description="分段信号开始输出第一段之前的等待时间。",
),
*_UD00_STAGE_PARAMETERS,
ParameterDefinition(
"nstages",
1.0,
label="段数",
quantity="dimensionless",
unit="",
minimum=1.0,
maximum=8.0,
editor="choice",
options=tuple(
ParameterOption(float(stage_count), str(stage_count))
for stage_count in range(1, 9)
),
description="参与输出计算的有效线性分段数量。",
),
ParameterDefinition(
"iscyclic",
0.0,
label="循环",
quantity="dimensionless",
unit="",
minimum=0.0,
maximum=1.0,
editor="choice",
options=(
ParameterOption(0.0, "否"),
ParameterOption(1.0, "是"),
),
description="当前公共协议编码:0 表示单次输出,1 表示循环输出。",
),
)
RESULT_VARIABLES = (
ResultVariableDefinition("y", "输出", "dimensionless", "", "signal", 10),
@@ -130,6 +201,16 @@ class AmesimUd00(AlgebraicComponent):
symbol="amesim_ud00",
ports=(PortDisplaySpec("out", "right", order=10),),
order=20,
parameter_groups=(
ParameterGroupDisplaySpec(
id="stages",
label="分段参数",
parameters=tuple(
parameter.name for parameter in _UD00_STAGE_PARAMETERS
),
order=10,
),
),
)
def __init__(
@@ -174,10 +255,17 @@ class AmesimUd00(AlgebraicComponent):
) -> "AmesimUd00":
nstages = parameters["nstages"]
iscyclic = parameters["iscyclic"]
if not float(nstages).is_integer():
raise ValueError("UD00 nstages must be an integer.")
if not float(iscyclic).is_integer():
raise ValueError("UD00 iscyclic must be 0 or 1.")
definitions = {definition.name: definition for definition in cls.PARAMETERS}
for parameter_name, value in (
("nstages", nstages),
("iscyclic", iscyclic),
):
numeric_value = float(value)
if not numeric_value.is_integer():
raise ValueError(f"UD00 {parameter_name} must be an integer.")
message = definitions[parameter_name].validation_message(numeric_value)
if message is not None:
raise ValueError(f"UD00 {parameter_name} {message}.")
return cls(
name=name,
medium=medium,