完善AMESim可配置参数交互
补充气动孔口、动态管路、UD00 与弹性接触组件的离散选项、条件显示和折叠分组。 增加目录协议、非法选项和前端参数表交互回归测试,不修改现有求解公式。
This commit is contained in:
1 parent
be54070855
commit
df1d676131
12 files changed
+1262
-69
No files matched your search
@@ -8,16 +8,44 @@ from app.simulation.components.amesim.gases import (
|
|||||||
normalize_amesim_gas_index,
|
normalize_amesim_gas_index,
|
||||||
)
|
)
|
||||||
from app.simulation.core.base import AlgebraicComponent
|
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.equations import EquationResidual
|
||||||
from app.simulation.core.metadata import (
|
from app.simulation.core.metadata import (
|
||||||
|
ParameterCondition,
|
||||||
ParameterDefinition,
|
ParameterDefinition,
|
||||||
|
ParameterOption,
|
||||||
ResultVariableDefinition,
|
ResultVariableDefinition,
|
||||||
)
|
)
|
||||||
from app.simulation.core.medium import GasMedium
|
from app.simulation.core.medium import GasMedium
|
||||||
from app.simulation.core.ports import PortDefinition
|
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):
|
class AmesimPnor001(AlgebraicComponent):
|
||||||
"""AMESim PNOR001 constant-flow-coefficient pneumatic orifice.
|
"""AMESim PNOR001 constant-flow-coefficient pneumatic orifice.
|
||||||
|
|
||||||
@@ -27,7 +55,7 @@ class AmesimPnor001(AlgebraicComponent):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
MODEL_TYPE = "amesim_pnor001"
|
MODEL_TYPE = "amesim_pnor001"
|
||||||
MODEL_VERSION = "0.1.0"
|
MODEL_VERSION = "0.2.0"
|
||||||
PORTS = (
|
PORTS = (
|
||||||
PortDefinition.pneumatic("port_1", nominal_role="bidirectional"),
|
PortDefinition.pneumatic("port_1", nominal_role="bidirectional"),
|
||||||
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
|
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
|
||||||
@@ -43,6 +71,7 @@ class AmesimPnor001(AlgebraicComponent):
|
|||||||
minimum=1.0e-10,
|
minimum=1.0e-10,
|
||||||
maximum=1.0,
|
maximum=1.0,
|
||||||
description="孔口实际质量流量相对于理想可压缩流量的无量纲修正系数。",
|
description="孔口实际质量流量相对于理想可压缩流量的无量纲修正系数。",
|
||||||
|
visible_when=_FLOWSET_USES_CQ,
|
||||||
),
|
),
|
||||||
ParameterDefinition(
|
ParameterDefinition(
|
||||||
"area",
|
"area",
|
||||||
@@ -53,6 +82,7 @@ class AmesimPnor001(AlgebraicComponent):
|
|||||||
minimum=0.0,
|
minimum=0.0,
|
||||||
maximum=1.0,
|
maximum=1.0,
|
||||||
description="选择 Cq/面积方式时用于流量计算的有效孔口面积。",
|
description="选择 Cq/面积方式时用于流量计算的有效孔口面积。",
|
||||||
|
visible_when=_FLOWSET_USES_CQ,
|
||||||
),
|
),
|
||||||
ParameterDefinition(
|
ParameterDefinition(
|
||||||
"Cv",
|
"Cv",
|
||||||
@@ -62,6 +92,7 @@ class AmesimPnor001(AlgebraicComponent):
|
|||||||
unit="",
|
unit="",
|
||||||
minimum=0.0,
|
minimum=0.0,
|
||||||
description="选择 Cv 方式时使用的英制流量系数。",
|
description="选择 Cv 方式时使用的英制流量系数。",
|
||||||
|
visible_when=_FLOWSET_USES_CV,
|
||||||
),
|
),
|
||||||
ParameterDefinition(
|
ParameterDefinition(
|
||||||
"Kv",
|
"Kv",
|
||||||
@@ -71,6 +102,7 @@ class AmesimPnor001(AlgebraicComponent):
|
|||||||
unit="",
|
unit="",
|
||||||
minimum=0.0,
|
minimum=0.0,
|
||||||
description="选择 Kv 方式时使用的公制流量系数。",
|
description="选择 Kv 方式时使用的公制流量系数。",
|
||||||
|
visible_when=_FLOWSET_USES_KV,
|
||||||
),
|
),
|
||||||
ParameterDefinition(
|
ParameterDefinition(
|
||||||
"flowset",
|
"flowset",
|
||||||
@@ -80,6 +112,8 @@ class AmesimPnor001(AlgebraicComponent):
|
|||||||
unit="",
|
unit="",
|
||||||
minimum=1.0,
|
minimum=1.0,
|
||||||
maximum=3.0,
|
maximum=3.0,
|
||||||
|
editor="choice",
|
||||||
|
options=_FLOW_COEFFICIENT_OPTIONS,
|
||||||
description="流量参数方式:1 使用 Cq 和面积,2 使用 Cv,3 使用 Kv。",
|
description="流量参数方式:1 使用 Cq 和面积,2 使用 Cv,3 使用 Kv。",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -111,6 +145,7 @@ class AmesimPnor001(AlgebraicComponent):
|
|||||||
PortDisplaySpec("port_2", "right", order=20),
|
PortDisplaySpec("port_2", "right", order=20),
|
||||||
),
|
),
|
||||||
order=10,
|
order=10,
|
||||||
|
parameter_groups=(_PNOR001_FLOW_COEFFICIENT_GROUP,),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -320,7 +355,7 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
MODEL_TYPE = "amesim_pnvo001_fixed"
|
MODEL_TYPE = "amesim_pnvo001_fixed"
|
||||||
MODEL_VERSION = "0.1.0"
|
MODEL_VERSION = "0.2.0"
|
||||||
PORTS = (
|
PORTS = (
|
||||||
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
|
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
|
||||||
PortDefinition.pneumatic("port_3", nominal_role="bidirectional"),
|
PortDefinition.pneumatic("port_3", nominal_role="bidirectional"),
|
||||||
@@ -336,6 +371,7 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
|
|||||||
minimum=1.0e-10,
|
minimum=1.0e-10,
|
||||||
maximum=1.0,
|
maximum=1.0,
|
||||||
description="孔口实际质量流量相对于理想可压缩流量的无量纲修正系数。",
|
description="孔口实际质量流量相对于理想可压缩流量的无量纲修正系数。",
|
||||||
|
visible_when=_FLOWSET_USES_CQ,
|
||||||
),
|
),
|
||||||
ParameterDefinition(
|
ParameterDefinition(
|
||||||
"area0",
|
"area0",
|
||||||
@@ -346,6 +382,7 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
|
|||||||
minimum=0.0,
|
minimum=0.0,
|
||||||
maximum=1.0,
|
maximum=1.0,
|
||||||
description="阀门完全开启时的最大有效孔口面积。",
|
description="阀门完全开启时的最大有效孔口面积。",
|
||||||
|
visible_when=_FLOWSET_USES_CQ,
|
||||||
),
|
),
|
||||||
ParameterDefinition(
|
ParameterDefinition(
|
||||||
"Cv",
|
"Cv",
|
||||||
@@ -355,6 +392,7 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
|
|||||||
unit="",
|
unit="",
|
||||||
minimum=0.0,
|
minimum=0.0,
|
||||||
description="选择 Cv 方式时使用的最大英制流量系数。",
|
description="选择 Cv 方式时使用的最大英制流量系数。",
|
||||||
|
visible_when=_FLOWSET_USES_CV,
|
||||||
),
|
),
|
||||||
ParameterDefinition(
|
ParameterDefinition(
|
||||||
"Kv",
|
"Kv",
|
||||||
@@ -364,6 +402,7 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
|
|||||||
unit="",
|
unit="",
|
||||||
minimum=0.0,
|
minimum=0.0,
|
||||||
description="选择 Kv 方式时使用的最大公制流量系数。",
|
description="选择 Kv 方式时使用的最大公制流量系数。",
|
||||||
|
visible_when=_FLOWSET_USES_KV,
|
||||||
),
|
),
|
||||||
ParameterDefinition(
|
ParameterDefinition(
|
||||||
"flowset",
|
"flowset",
|
||||||
@@ -373,6 +412,8 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
|
|||||||
unit="",
|
unit="",
|
||||||
minimum=1.0,
|
minimum=1.0,
|
||||||
maximum=3.0,
|
maximum=3.0,
|
||||||
|
editor="choice",
|
||||||
|
options=_FLOW_COEFFICIENT_OPTIONS,
|
||||||
description="流量参数方式:1 使用 Cq 和面积,2 使用 Cv,3 使用 Kv。",
|
description="流量参数方式:1 使用 Cq 和面积,2 使用 Cv,3 使用 Kv。",
|
||||||
),
|
),
|
||||||
ParameterDefinition(
|
ParameterDefinition(
|
||||||
@@ -422,6 +463,7 @@ class AmesimPnvo001FixedOpening(AlgebraicComponent):
|
|||||||
PortDisplaySpec("port_3", "right", order=20),
|
PortDisplaySpec("port_3", "right", order=20),
|
||||||
),
|
),
|
||||||
order=30,
|
order=30,
|
||||||
|
parameter_groups=(_PNVO001_FLOW_COEFFICIENT_GROUP,),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -685,7 +727,7 @@ class AmesimPnvo001SignalOpening(AmesimPnvo001FixedOpening):
|
|||||||
"""AMESim PNVO001 signal-controlled pneumatic orifice."""
|
"""AMESim PNVO001 signal-controlled pneumatic orifice."""
|
||||||
|
|
||||||
MODEL_TYPE = "amesim_pnvo001"
|
MODEL_TYPE = "amesim_pnvo001"
|
||||||
MODEL_VERSION = "0.1.0"
|
MODEL_VERSION = "0.2.0"
|
||||||
PORTS = (
|
PORTS = (
|
||||||
PortDefinition.signal("res", nominal_role="input"),
|
PortDefinition.signal("res", nominal_role="input"),
|
||||||
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
|
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
|
||||||
@@ -693,12 +735,70 @@ class AmesimPnvo001SignalOpening(AmesimPnvo001FixedOpening):
|
|||||||
)
|
)
|
||||||
PARAMETERS = (
|
PARAMETERS = (
|
||||||
AMESIM_GAS_INDEX_PARAMETER,
|
AMESIM_GAS_INDEX_PARAMETER,
|
||||||
ParameterDefinition("cq", 0.72, label="流量系数 Cq", quantity="dimensionless", unit="", minimum=1.0e-10, maximum=1.0),
|
ParameterDefinition(
|
||||||
ParameterDefinition("area0", 5.0e-6, label="最大孔口面积", quantity="area", unit="m2", minimum=0.0, maximum=1.0),
|
"cq",
|
||||||
ParameterDefinition("Cv", 0.5, label="最大流量系数 Cv", quantity="dimensionless", unit="", minimum=0.0),
|
0.72,
|
||||||
ParameterDefinition("Kv", 0.4, label="最大流量系数 Kv", quantity="dimensionless", unit="", minimum=0.0),
|
label="流量系数 Cq",
|
||||||
ParameterDefinition("flowset", 1.0, label="流量系数设置", quantity="dimensionless", unit="", minimum=1.0, maximum=3.0),
|
quantity="dimensionless",
|
||||||
ParameterDefinition("opening0", 1.0, label="初始开度", quantity="dimensionless", unit="", minimum=0.0, maximum=1.0),
|
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
|
RESULT_VARIABLES = AmesimPnvo001FixedOpening.RESULT_VARIABLES
|
||||||
DISPLAY = ComponentDisplaySpec(
|
DISPLAY = ComponentDisplaySpec(
|
||||||
@@ -712,6 +812,7 @@ class AmesimPnvo001SignalOpening(AmesimPnvo001FixedOpening):
|
|||||||
PortDisplaySpec("port_3", "right", order=20),
|
PortDisplaySpec("port_3", "right", order=20),
|
||||||
),
|
),
|
||||||
order=35,
|
order=35,
|
||||||
|
parameter_groups=(_PNVO001_FLOW_COEFFICIENT_GROUP,),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
|||||||
@@ -8,10 +8,16 @@ from app.simulation.components.amesim.gases import (
|
|||||||
normalize_amesim_gas_index,
|
normalize_amesim_gas_index,
|
||||||
)
|
)
|
||||||
from app.simulation.core.base import AlgebraicComponent, DynamicComponent, ThermodynamicVolumeComponent
|
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.equations import EquationResidual
|
||||||
from app.simulation.core.metadata import (
|
from app.simulation.core.metadata import (
|
||||||
|
ParameterCondition,
|
||||||
ParameterDefinition,
|
ParameterDefinition,
|
||||||
|
ParameterOption,
|
||||||
ResultVariableDefinition,
|
ResultVariableDefinition,
|
||||||
THERMODYNAMIC_VOLUME_RESULT_VARIABLES,
|
THERMODYNAMIC_VOLUME_RESULT_VARIABLES,
|
||||||
)
|
)
|
||||||
@@ -20,6 +26,18 @@ from app.simulation.core.ports import PortDefinition
|
|||||||
from app.simulation.core.state import VolumeState
|
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):
|
class AmesimPnl00r(AlgebraicComponent):
|
||||||
"""AMESim PNL00R pneumatic pipe friction resistance.
|
"""AMESim PNL00R pneumatic pipe friction resistance.
|
||||||
|
|
||||||
@@ -308,7 +326,7 @@ class AmesimPnl0001(ThermodynamicVolumeComponent):
|
|||||||
"""AMESim PNL0001 C-R pneumatic pipe with compressibility and friction."""
|
"""AMESim PNL0001 C-R pneumatic pipe with compressibility and friction."""
|
||||||
|
|
||||||
MODEL_TYPE = "amesim_pnl0001"
|
MODEL_TYPE = "amesim_pnl0001"
|
||||||
MODEL_VERSION = "0.1.0"
|
MODEL_VERSION = "0.2.0"
|
||||||
PORTS = (
|
PORTS = (
|
||||||
PortDefinition.pneumatic("port_1", nominal_role="bidirectional"),
|
PortDefinition.pneumatic("port_1", nominal_role="bidirectional"),
|
||||||
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
|
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
|
||||||
@@ -354,7 +372,11 @@ class AmesimPnl0001(ThermodynamicVolumeComponent):
|
|||||||
minimum=0.0,
|
minimum=0.0,
|
||||||
minimum_exclusive=True,
|
minimum_exclusive=True,
|
||||||
maximum=2.0,
|
maximum=2.0,
|
||||||
description="AMESim 管路热力学配置使用的多方指数。",
|
description=(
|
||||||
|
"mode=1 多方过程使用的指数;当前公开求解器保留该 AMESim "
|
||||||
|
"配置,尚未实现多方指数对状态方程的修正。"
|
||||||
|
),
|
||||||
|
visible_when=(_DYNAMIC_PIPE_POLYTROPIC_MODE,),
|
||||||
),
|
),
|
||||||
ParameterDefinition(
|
ParameterDefinition(
|
||||||
"kth",
|
"kth",
|
||||||
@@ -363,7 +385,8 @@ class AmesimPnl0001(ThermodynamicVolumeComponent):
|
|||||||
quantity="heat_transfer_coefficient",
|
quantity="heat_transfer_coefficient",
|
||||||
unit="W/(m2*K)",
|
unit="W/(m2*K)",
|
||||||
minimum=0.0,
|
minimum=0.0,
|
||||||
description="管内气体与外部环境之间的对流换热系数。",
|
description="mode=2 带换热过程使用的气体与外部环境对流换热系数。",
|
||||||
|
visible_when=(_DYNAMIC_PIPE_HEAT_EXCHANGE_MODE,),
|
||||||
),
|
),
|
||||||
ParameterDefinition(
|
ParameterDefinition(
|
||||||
"extemp",
|
"extemp",
|
||||||
@@ -373,7 +396,8 @@ class AmesimPnl0001(ThermodynamicVolumeComponent):
|
|||||||
unit="K",
|
unit="K",
|
||||||
minimum=0.0,
|
minimum=0.0,
|
||||||
minimum_exclusive=True,
|
minimum_exclusive=True,
|
||||||
description="管路外部环境的绝对温度,用于计算换热功率。",
|
description="mode=2 带换热过程使用的外部环境绝对温度。",
|
||||||
|
visible_when=(_DYNAMIC_PIPE_HEAT_EXCHANGE_MODE,),
|
||||||
),
|
),
|
||||||
ParameterDefinition(
|
ParameterDefinition(
|
||||||
"mode",
|
"mode",
|
||||||
@@ -383,7 +407,16 @@ class AmesimPnl0001(ThermodynamicVolumeComponent):
|
|||||||
unit="",
|
unit="",
|
||||||
minimum=1.0,
|
minimum=1.0,
|
||||||
maximum=2.0,
|
maximum=2.0,
|
||||||
description="热模型选择:1 为绝热,2 为按换热系数计算环境换热。",
|
editor="choice",
|
||||||
|
options=(
|
||||||
|
ParameterOption(1.0, "多方过程"),
|
||||||
|
ParameterOption(2.0, "带换热"),
|
||||||
|
),
|
||||||
|
description=(
|
||||||
|
"AMESim 原始编码:1 为多方过程,2 为带换热。当前公开求解器在"
|
||||||
|
"多方模式下关闭环境换热,在带换热模式下按换热系数和外部温度"
|
||||||
|
"计算环境换热。"
|
||||||
|
),
|
||||||
),
|
),
|
||||||
ParameterDefinition(
|
ParameterDefinition(
|
||||||
"p0",
|
"p0",
|
||||||
@@ -450,6 +483,7 @@ class AmesimPnl0001(ThermodynamicVolumeComponent):
|
|||||||
PortDisplaySpec("port_2", "right", order=20),
|
PortDisplaySpec("port_2", "right", order=20),
|
||||||
),
|
),
|
||||||
order=30,
|
order=30,
|
||||||
|
parameter_groups=_DYNAMIC_PIPE_PARAMETER_GROUPS,
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -513,7 +547,10 @@ class AmesimPnl0001(ThermodynamicVolumeComponent):
|
|||||||
rounded = round(value)
|
rounded = round(value)
|
||||||
if not isclose(value, rounded, rel_tol=0.0, abs_tol=1.0e-12):
|
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.")
|
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
|
@classmethod
|
||||||
def create(
|
def create(
|
||||||
@@ -713,7 +750,7 @@ class AmesimPnl0002(AmesimPnl0001):
|
|||||||
"""AMESim PNL0002 R-C-R pneumatic pipe with one center compliance."""
|
"""AMESim PNL0002 R-C-R pneumatic pipe with one center compliance."""
|
||||||
|
|
||||||
MODEL_TYPE = "amesim_pnl0002"
|
MODEL_TYPE = "amesim_pnl0002"
|
||||||
MODEL_VERSION = "0.1.0"
|
MODEL_VERSION = "0.2.0"
|
||||||
PORTS = (
|
PORTS = (
|
||||||
PortDefinition.pneumatic("port_1", nominal_role="bidirectional"),
|
PortDefinition.pneumatic("port_1", nominal_role="bidirectional"),
|
||||||
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
|
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
|
||||||
@@ -730,6 +767,7 @@ class AmesimPnl0002(AmesimPnl0001):
|
|||||||
PortDisplaySpec("port_2", "right", order=20),
|
PortDisplaySpec("port_2", "right", order=20),
|
||||||
),
|
),
|
||||||
order=40,
|
order=40,
|
||||||
|
parameter_groups=_DYNAMIC_PIPE_PARAMETER_GROUPS,
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -856,7 +894,7 @@ class AmesimPnl0003(DynamicComponent):
|
|||||||
|
|
||||||
state_size = 4
|
state_size = 4
|
||||||
MODEL_TYPE = "amesim_pnl0003"
|
MODEL_TYPE = "amesim_pnl0003"
|
||||||
MODEL_VERSION = "0.1.0"
|
MODEL_VERSION = "0.2.0"
|
||||||
PORTS = (
|
PORTS = (
|
||||||
PortDefinition.pneumatic("port_1", nominal_role="bidirectional"),
|
PortDefinition.pneumatic("port_1", nominal_role="bidirectional"),
|
||||||
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
|
PortDefinition.pneumatic("port_2", nominal_role="bidirectional"),
|
||||||
@@ -930,6 +968,7 @@ class AmesimPnl0003(DynamicComponent):
|
|||||||
PortDisplaySpec("port_2", "right", order=20),
|
PortDisplaySpec("port_2", "right", order=20),
|
||||||
),
|
),
|
||||||
order=50,
|
order=50,
|
||||||
|
parameter_groups=_DYNAMIC_PIPE_PARAMETER_GROUPS,
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ _MECMAS21_ELASTIC_STOP = ParameterCondition("stoptype", (2.0,))
|
|||||||
_MECMAS21_RESTITUTION_STOP = ParameterCondition("stoptype", (3.0,))
|
_MECMAS21_RESTITUTION_STOP = ParameterCondition("stoptype", (3.0,))
|
||||||
_MECMAS21_ADVANCED_FRICTION = ParameterCondition("frictionType", (2.0,))
|
_MECMAS21_ADVANCED_FRICTION = ParameterCondition("frictionType", (2.0,))
|
||||||
_MECMAS21_STRIBECK_ENABLED = ParameterCondition("strib", (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):
|
class AmesimF000(AlgebraicComponent):
|
||||||
@@ -713,22 +715,126 @@ class AmesimLstp00a(AlgebraicComponent):
|
|||||||
"""AMESim LSTP00A first public elastic contact component."""
|
"""AMESim LSTP00A first public elastic contact component."""
|
||||||
|
|
||||||
MODEL_TYPE = "amesim_lstp00a"
|
MODEL_TYPE = "amesim_lstp00a"
|
||||||
MODEL_VERSION = "0.1.0"
|
MODEL_VERSION = "0.2.0"
|
||||||
PORTS = (
|
PORTS = (
|
||||||
PortDefinition.mechanical_translational("port_1"),
|
PortDefinition.mechanical_translational("port_1"),
|
||||||
PortDefinition.mechanical_translational("port_2"),
|
PortDefinition.mechanical_translational("port_2"),
|
||||||
)
|
)
|
||||||
PARAMETERS = (
|
PARAMETERS = (
|
||||||
ParameterDefinition("na", 10.0, label="有效圈数", quantity="dimensionless", unit="", minimum=0.0, minimum_exclusive=True),
|
ParameterDefinition(
|
||||||
ParameterDefinition("gap0", 0.0, label="初始间隙", quantity="length", unit="m"),
|
"na",
|
||||||
ParameterDefinition("kcont", 1.0e6, label="接触刚度", quantity="translational_stiffness", unit="N/m", minimum=0.0),
|
10.0,
|
||||||
ParameterDefinition("G", 8.57e10, label="剪切模量", quantity="pressure", unit="Pa", minimum=0.0),
|
label="有效圈数",
|
||||||
ParameterDefinition("sdiam", 0.02, label="弹簧直径", quantity="length", unit="m", minimum=0.0),
|
quantity="dimensionless",
|
||||||
ParameterDefinition("wdiam", 0.002, label="线径", quantity="length", unit="m", minimum=0.0),
|
unit="",
|
||||||
ParameterDefinition("rcont", 0.0, label="接触阻尼", quantity="translational_damping", unit="N/(m/s)", minimum=0.0),
|
minimum=0.0,
|
||||||
ParameterDefinition("Pdis", 1.0e-7, label="满阻尼穿透", quantity="length", unit="m", minimum=0.0),
|
minimum_exclusive=True,
|
||||||
ParameterDefinition("stiffmode", 1.0, label="刚度模式", quantity="dimensionless", unit="", minimum=0.0),
|
description="几何刚度模式下使用的弹簧有效圈数。",
|
||||||
ParameterDefinition("discContactOption", 1.0, label="接触选项", quantity="dimensionless", unit="", minimum=0.0),
|
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 = (
|
RESULT_VARIABLES = (
|
||||||
ResultVariableDefinition("gap", "间隙", "length", "m", "derived", 10),
|
ResultVariableDefinition("gap", "间隙", "length", "m", "derived", 10),
|
||||||
@@ -745,6 +851,20 @@ class AmesimLstp00a(AlgebraicComponent):
|
|||||||
PortDisplaySpec("port_2", "right", order=20),
|
PortDisplaySpec("port_2", "right", order=20),
|
||||||
),
|
),
|
||||||
order=40,
|
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:
|
def __init__(self, name: str, medium: IdealGasMedium, **parameters: float) -> None:
|
||||||
@@ -773,9 +893,14 @@ class AmesimLstp00a(AlgebraicComponent):
|
|||||||
medium: IdealGasMedium,
|
medium: IdealGasMedium,
|
||||||
parameters: Mapping[str, float],
|
parameters: Mapping[str, float],
|
||||||
) -> "AmesimLstp00a":
|
) -> "AmesimLstp00a":
|
||||||
|
definitions = {definition.name: definition for definition in cls.PARAMETERS}
|
||||||
for integer_name in ("stiffmode", "discContactOption"):
|
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.")
|
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))
|
return cls(name=name, medium=medium, **dict(parameters))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
@@ -4,12 +4,71 @@ from collections.abc import Mapping
|
|||||||
from math import floor
|
from math import floor
|
||||||
|
|
||||||
from app.simulation.core.base import AlgebraicComponent
|
from app.simulation.core.base import AlgebraicComponent
|
||||||
from app.simulation.core.catalog import ComponentDisplaySpec, PortDisplaySpec
|
from app.simulation.core.catalog import (
|
||||||
from app.simulation.core.metadata import ParameterDefinition, ResultVariableDefinition
|
ComponentDisplaySpec,
|
||||||
|
ParameterGroupDisplaySpec,
|
||||||
|
PortDisplaySpec,
|
||||||
|
)
|
||||||
|
from app.simulation.core.metadata import (
|
||||||
|
ParameterCondition,
|
||||||
|
ParameterDefinition,
|
||||||
|
ParameterOption,
|
||||||
|
ResultVariableDefinition,
|
||||||
|
)
|
||||||
from app.simulation.core.medium import IdealGasMedium
|
from app.simulation.core.medium import IdealGasMedium
|
||||||
from app.simulation.core.ports import PortDefinition
|
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):
|
class AmesimStep0(AlgebraicComponent):
|
||||||
"""AMESim STEP0 scalar step signal source."""
|
"""AMESim STEP0 scalar step signal source."""
|
||||||
|
|
||||||
@@ -89,36 +148,48 @@ class AmesimUd00(AlgebraicComponent):
|
|||||||
"""AMESim UD00 piecewise-linear scalar signal source."""
|
"""AMESim UD00 piecewise-linear scalar signal source."""
|
||||||
|
|
||||||
MODEL_TYPE = "amesim_ud00"
|
MODEL_TYPE = "amesim_ud00"
|
||||||
MODEL_VERSION = "0.1.0"
|
MODEL_VERSION = "0.2.0"
|
||||||
PORTS = (PortDefinition.signal("out", nominal_role="output"),)
|
PORTS = (PortDefinition.signal("out", nominal_role="output"),)
|
||||||
PARAMETERS = (
|
PARAMETERS = (
|
||||||
ParameterDefinition("tstart", 0.0, label="启动时间", quantity="time", unit="s"),
|
ParameterDefinition(
|
||||||
ParameterDefinition("start1", 0.0, label="第 1 段起点", quantity="dimensionless", unit=""),
|
"tstart",
|
||||||
ParameterDefinition("end1", 1.0, label="第 1 段终点", quantity="dimensionless", unit=""),
|
0.0,
|
||||||
ParameterDefinition("t1", 1.0, label="第 1 段时长", quantity="time", unit="s", minimum=0.0),
|
label="启动时间",
|
||||||
ParameterDefinition("start2", 1.0, label="第 2 段起点", quantity="dimensionless", unit=""),
|
quantity="time",
|
||||||
ParameterDefinition("end2", 1.0, label="第 2 段终点", quantity="dimensionless", unit=""),
|
unit="s",
|
||||||
ParameterDefinition("t2", 0.0, label="第 2 段时长", quantity="time", unit="s", minimum=0.0),
|
description="分段信号开始输出第一段之前的等待时间。",
|
||||||
ParameterDefinition("start3", 1.0, label="第 3 段起点", quantity="dimensionless", unit=""),
|
),
|
||||||
ParameterDefinition("end3", 1.0, label="第 3 段终点", quantity="dimensionless", unit=""),
|
*_UD00_STAGE_PARAMETERS,
|
||||||
ParameterDefinition("t3", 0.0, label="第 3 段时长", quantity="time", unit="s", minimum=0.0),
|
ParameterDefinition(
|
||||||
ParameterDefinition("start4", 1.0, label="第 4 段起点", quantity="dimensionless", unit=""),
|
"nstages",
|
||||||
ParameterDefinition("end4", 1.0, label="第 4 段终点", quantity="dimensionless", unit=""),
|
1.0,
|
||||||
ParameterDefinition("t4", 0.0, label="第 4 段时长", quantity="time", unit="s", minimum=0.0),
|
label="段数",
|
||||||
ParameterDefinition("start5", 1.0, label="第 5 段起点", quantity="dimensionless", unit=""),
|
quantity="dimensionless",
|
||||||
ParameterDefinition("end5", 1.0, label="第 5 段终点", quantity="dimensionless", unit=""),
|
unit="",
|
||||||
ParameterDefinition("t5", 0.0, label="第 5 段时长", quantity="time", unit="s", minimum=0.0),
|
minimum=1.0,
|
||||||
ParameterDefinition("start6", 1.0, label="第 6 段起点", quantity="dimensionless", unit=""),
|
maximum=8.0,
|
||||||
ParameterDefinition("end6", 1.0, label="第 6 段终点", quantity="dimensionless", unit=""),
|
editor="choice",
|
||||||
ParameterDefinition("t6", 0.0, label="第 6 段时长", quantity="time", unit="s", minimum=0.0),
|
options=tuple(
|
||||||
ParameterDefinition("start7", 1.0, label="第 7 段起点", quantity="dimensionless", unit=""),
|
ParameterOption(float(stage_count), str(stage_count))
|
||||||
ParameterDefinition("end7", 1.0, label="第 7 段终点", quantity="dimensionless", unit=""),
|
for stage_count in range(1, 9)
|
||||||
ParameterDefinition("t7", 0.0, label="第 7 段时长", quantity="time", unit="s", minimum=0.0),
|
),
|
||||||
ParameterDefinition("start8", 1.0, label="第 8 段起点", quantity="dimensionless", unit=""),
|
description="参与输出计算的有效线性分段数量。",
|
||||||
ParameterDefinition("end8", 1.0, label="第 8 段终点", quantity="dimensionless", unit=""),
|
),
|
||||||
ParameterDefinition("t8", 0.0, label="第 8 段时长", quantity="time", unit="s", minimum=0.0),
|
ParameterDefinition(
|
||||||
ParameterDefinition("nstages", 1.0, label="段数", quantity="dimensionless", unit="", minimum=1.0, maximum=8.0),
|
"iscyclic",
|
||||||
ParameterDefinition("iscyclic", 0.0, label="循环", quantity="dimensionless", unit="", minimum=0.0, maximum=1.0),
|
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 = (
|
RESULT_VARIABLES = (
|
||||||
ResultVariableDefinition("y", "输出", "dimensionless", "", "signal", 10),
|
ResultVariableDefinition("y", "输出", "dimensionless", "", "signal", 10),
|
||||||
@@ -130,6 +201,16 @@ class AmesimUd00(AlgebraicComponent):
|
|||||||
symbol="amesim_ud00",
|
symbol="amesim_ud00",
|
||||||
ports=(PortDisplaySpec("out", "right", order=10),),
|
ports=(PortDisplaySpec("out", "right", order=10),),
|
||||||
order=20,
|
order=20,
|
||||||
|
parameter_groups=(
|
||||||
|
ParameterGroupDisplaySpec(
|
||||||
|
id="stages",
|
||||||
|
label="分段参数",
|
||||||
|
parameters=tuple(
|
||||||
|
parameter.name for parameter in _UD00_STAGE_PARAMETERS
|
||||||
|
),
|
||||||
|
order=10,
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -174,10 +255,17 @@ class AmesimUd00(AlgebraicComponent):
|
|||||||
) -> "AmesimUd00":
|
) -> "AmesimUd00":
|
||||||
nstages = parameters["nstages"]
|
nstages = parameters["nstages"]
|
||||||
iscyclic = parameters["iscyclic"]
|
iscyclic = parameters["iscyclic"]
|
||||||
if not float(nstages).is_integer():
|
definitions = {definition.name: definition for definition in cls.PARAMETERS}
|
||||||
raise ValueError("UD00 nstages must be an integer.")
|
for parameter_name, value in (
|
||||||
if not float(iscyclic).is_integer():
|
("nstages", nstages),
|
||||||
raise ValueError("UD00 iscyclic must be 0 or 1.")
|
("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(
|
return cls(
|
||||||
name=name,
|
name=name,
|
||||||
medium=medium,
|
medium=medium,
|
||||||
|
|||||||
@@ -14,6 +14,62 @@ const physicalPort = (
|
|||||||
order: side === "left" ? 0 : 1,
|
order: side === "left" ? 0 : 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const ud00StageParameters = Array.from({ length: 8 }, (_, offset) => offset + 1)
|
||||||
|
.flatMap((stage) => {
|
||||||
|
const visibleWhen =
|
||||||
|
stage === 1
|
||||||
|
? {}
|
||||||
|
: {
|
||||||
|
visibleWhen: [
|
||||||
|
{
|
||||||
|
parameter: "nstages",
|
||||||
|
values: Array.from(
|
||||||
|
{ length: 9 - stage },
|
||||||
|
(_, offset) => stage + offset,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: `start${stage}`,
|
||||||
|
label: `第 ${stage} 段起点`,
|
||||||
|
quantity: "dimensionless",
|
||||||
|
unit: "",
|
||||||
|
default: stage === 1 ? 0 : 1,
|
||||||
|
minimumExclusive: false,
|
||||||
|
description: `第 ${stage} 段开始时的输出值。`,
|
||||||
|
...visibleWhen,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `end${stage}`,
|
||||||
|
label: `第 ${stage} 段终点`,
|
||||||
|
quantity: "dimensionless",
|
||||||
|
unit: "",
|
||||||
|
default: 1,
|
||||||
|
minimumExclusive: false,
|
||||||
|
description: `第 ${stage} 段结束时的输出值。`,
|
||||||
|
...visibleWhen,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `t${stage}`,
|
||||||
|
label: `第 ${stage} 段时长`,
|
||||||
|
quantity: "time",
|
||||||
|
unit: "s",
|
||||||
|
default: stage === 1 ? 1 : 0,
|
||||||
|
minimum: 0,
|
||||||
|
minimumExclusive: false,
|
||||||
|
description: `第 ${stage} 段的持续时间。`,
|
||||||
|
...visibleWhen,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
const ud00StageParameterNames = Array.from(
|
||||||
|
{ length: 8 },
|
||||||
|
(_, offset) => offset + 1,
|
||||||
|
).flatMap((stage) => [`start${stage}`, `end${stage}`, `t${stage}`]);
|
||||||
|
|
||||||
export const componentCatalog = {
|
export const componentCatalog = {
|
||||||
schemaVersion: 1,
|
schemaVersion: 1,
|
||||||
libraries: [
|
libraries: [
|
||||||
@@ -419,6 +475,380 @@ export const componentCatalog = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: "amesim_pnor001",
|
||||||
|
label: "PNOR001 常系数气动孔口",
|
||||||
|
modelType: "amesim_pnor001",
|
||||||
|
modelVersion: "0.2.0",
|
||||||
|
symbol: "symbol-not-registered",
|
||||||
|
order: 7,
|
||||||
|
category: {
|
||||||
|
id: "generic",
|
||||||
|
label: "通用组件",
|
||||||
|
order: 1,
|
||||||
|
},
|
||||||
|
ports: [],
|
||||||
|
parameterGroups: [
|
||||||
|
{
|
||||||
|
id: "flow_coefficient",
|
||||||
|
label: "流量系数",
|
||||||
|
order: 10,
|
||||||
|
parameters: ["cq", "area", "Cv", "Kv"],
|
||||||
|
defaultExpanded: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: "cq",
|
||||||
|
label: "流量系数 Cq",
|
||||||
|
quantity: "dimensionless",
|
||||||
|
unit: "",
|
||||||
|
default: 0.72,
|
||||||
|
minimum: 1e-10,
|
||||||
|
maximum: 1,
|
||||||
|
minimumExclusive: false,
|
||||||
|
description: "孔口实际质量流量相对于理想可压缩流量的无量纲修正系数。",
|
||||||
|
visibleWhen: [{ parameter: "flowset", values: [1] }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "area",
|
||||||
|
label: "孔口面积",
|
||||||
|
quantity: "area",
|
||||||
|
unit: "m2",
|
||||||
|
default: 5e-6,
|
||||||
|
minimum: 0,
|
||||||
|
maximum: 1,
|
||||||
|
minimumExclusive: false,
|
||||||
|
description: "选择 Cq/面积方式时用于流量计算的有效孔口面积。",
|
||||||
|
visibleWhen: [{ parameter: "flowset", values: [1] }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Cv",
|
||||||
|
label: "流量系数 Cv",
|
||||||
|
quantity: "dimensionless",
|
||||||
|
unit: "",
|
||||||
|
default: 0.5,
|
||||||
|
minimum: 0,
|
||||||
|
minimumExclusive: false,
|
||||||
|
description: "选择 Cv 方式时使用的英制流量系数。",
|
||||||
|
visibleWhen: [{ parameter: "flowset", values: [2] }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Kv",
|
||||||
|
label: "流量系数 Kv",
|
||||||
|
quantity: "dimensionless",
|
||||||
|
unit: "",
|
||||||
|
default: 0.4,
|
||||||
|
minimum: 0,
|
||||||
|
minimumExclusive: false,
|
||||||
|
description: "选择 Kv 方式时使用的公制流量系数。",
|
||||||
|
visibleWhen: [{ parameter: "flowset", values: [3] }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "flowset",
|
||||||
|
label: "流量系数设置",
|
||||||
|
quantity: "dimensionless",
|
||||||
|
unit: "",
|
||||||
|
default: 1,
|
||||||
|
minimum: 1,
|
||||||
|
maximum: 3,
|
||||||
|
minimumExclusive: false,
|
||||||
|
editor: "choice",
|
||||||
|
options: [
|
||||||
|
{ value: 1, label: "Cq" },
|
||||||
|
{ value: 2, label: "Cv" },
|
||||||
|
{ value: 3, label: "Kv" },
|
||||||
|
],
|
||||||
|
description: "流量参数方式:1 使用 Cq 和面积,2 使用 Cv,3 使用 Kv。",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "amesim_pnl0001",
|
||||||
|
label: "PNL0001 C-R 动态管路",
|
||||||
|
modelType: "amesim_pnl0001",
|
||||||
|
modelVersion: "0.2.0",
|
||||||
|
symbol: "symbol-not-registered",
|
||||||
|
order: 8,
|
||||||
|
category: {
|
||||||
|
id: "generic",
|
||||||
|
label: "通用组件",
|
||||||
|
order: 1,
|
||||||
|
},
|
||||||
|
ports: [],
|
||||||
|
parameterGroups: [
|
||||||
|
{
|
||||||
|
id: "thermodynamics",
|
||||||
|
label: "热力学",
|
||||||
|
order: 10,
|
||||||
|
parameters: ["k", "kth", "extemp"],
|
||||||
|
defaultExpanded: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: "diam",
|
||||||
|
label: "管径",
|
||||||
|
quantity: "length",
|
||||||
|
unit: "m",
|
||||||
|
default: 0.01,
|
||||||
|
minimum: 0,
|
||||||
|
minimumExclusive: true,
|
||||||
|
description: "管路的有效内径,用于计算流通面积、储气容积和摩擦压降。",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "k",
|
||||||
|
label: "多方指数",
|
||||||
|
quantity: "dimensionless",
|
||||||
|
unit: "",
|
||||||
|
default: 1.35,
|
||||||
|
minimum: 0,
|
||||||
|
maximum: 2,
|
||||||
|
minimumExclusive: true,
|
||||||
|
visibleWhen: [{ parameter: "mode", values: [1] }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "kth",
|
||||||
|
label: "换热系数",
|
||||||
|
quantity: "heat_transfer_coefficient",
|
||||||
|
unit: "W/(m2*K)",
|
||||||
|
default: 0,
|
||||||
|
minimum: 0,
|
||||||
|
minimumExclusive: false,
|
||||||
|
visibleWhen: [{ parameter: "mode", values: [2] }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "extemp",
|
||||||
|
label: "外部温度",
|
||||||
|
quantity: "temperature",
|
||||||
|
unit: "K",
|
||||||
|
default: 293.15,
|
||||||
|
minimum: 0,
|
||||||
|
minimumExclusive: true,
|
||||||
|
visibleWhen: [{ parameter: "mode", values: [2] }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mode",
|
||||||
|
label: "热模型",
|
||||||
|
quantity: "dimensionless",
|
||||||
|
unit: "",
|
||||||
|
default: 2,
|
||||||
|
minimum: 1,
|
||||||
|
maximum: 2,
|
||||||
|
minimumExclusive: false,
|
||||||
|
editor: "choice",
|
||||||
|
options: [
|
||||||
|
{ value: 1, label: "多方过程" },
|
||||||
|
{ value: 2, label: "带换热" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "amesim_ud00",
|
||||||
|
label: "UD00 分段线性信号",
|
||||||
|
modelType: "amesim_ud00",
|
||||||
|
modelVersion: "0.2.0",
|
||||||
|
symbol: "symbol-not-registered",
|
||||||
|
order: 9,
|
||||||
|
category: {
|
||||||
|
id: "generic",
|
||||||
|
label: "通用组件",
|
||||||
|
order: 1,
|
||||||
|
},
|
||||||
|
ports: [],
|
||||||
|
parameterGroups: [
|
||||||
|
{
|
||||||
|
id: "stages",
|
||||||
|
label: "分段参数",
|
||||||
|
order: 10,
|
||||||
|
parameters: ud00StageParameterNames,
|
||||||
|
defaultExpanded: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: "tstart",
|
||||||
|
label: "启动时间",
|
||||||
|
quantity: "time",
|
||||||
|
unit: "s",
|
||||||
|
default: 0,
|
||||||
|
minimumExclusive: false,
|
||||||
|
description: "分段信号开始输出第一段之前的等待时间。",
|
||||||
|
},
|
||||||
|
...ud00StageParameters,
|
||||||
|
{
|
||||||
|
name: "nstages",
|
||||||
|
label: "段数",
|
||||||
|
quantity: "dimensionless",
|
||||||
|
unit: "",
|
||||||
|
default: 1,
|
||||||
|
minimum: 1,
|
||||||
|
maximum: 8,
|
||||||
|
minimumExclusive: false,
|
||||||
|
editor: "choice",
|
||||||
|
options: Array.from({ length: 8 }, (_, offset) => ({
|
||||||
|
value: offset + 1,
|
||||||
|
label: String(offset + 1),
|
||||||
|
})),
|
||||||
|
description: "参与输出计算的有效线性分段数量。",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "iscyclic",
|
||||||
|
label: "循环",
|
||||||
|
quantity: "dimensionless",
|
||||||
|
unit: "",
|
||||||
|
default: 0,
|
||||||
|
minimum: 0,
|
||||||
|
maximum: 1,
|
||||||
|
minimumExclusive: false,
|
||||||
|
editor: "choice",
|
||||||
|
options: [
|
||||||
|
{ value: 0, label: "否" },
|
||||||
|
{ value: 1, label: "是" },
|
||||||
|
],
|
||||||
|
description: "当前公共协议编码:0 表示单次输出,1 表示循环输出。",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "amesim_lstp00a",
|
||||||
|
label: "LSTP00A 弹性接触",
|
||||||
|
modelType: "amesim_lstp00a",
|
||||||
|
modelVersion: "0.2.0",
|
||||||
|
symbol: "symbol-not-registered",
|
||||||
|
order: 10,
|
||||||
|
category: {
|
||||||
|
id: "generic",
|
||||||
|
label: "通用组件",
|
||||||
|
order: 1,
|
||||||
|
},
|
||||||
|
ports: [],
|
||||||
|
parameterGroups: [
|
||||||
|
{
|
||||||
|
id: "stiffness",
|
||||||
|
label: "刚度",
|
||||||
|
order: 10,
|
||||||
|
parameters: ["kcont", "G", "sdiam", "wdiam", "na"],
|
||||||
|
defaultExpanded: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "contact",
|
||||||
|
label: "接触",
|
||||||
|
order: 20,
|
||||||
|
parameters: ["gap0", "rcont", "Pdis"],
|
||||||
|
defaultExpanded: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
parameters: [
|
||||||
|
{
|
||||||
|
name: "na",
|
||||||
|
label: "有效圈数",
|
||||||
|
quantity: "dimensionless",
|
||||||
|
unit: "",
|
||||||
|
default: 10,
|
||||||
|
minimum: 0,
|
||||||
|
minimumExclusive: true,
|
||||||
|
visibleWhen: [{ parameter: "stiffmode", values: [2] }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "gap0",
|
||||||
|
label: "初始间隙",
|
||||||
|
quantity: "length",
|
||||||
|
unit: "m",
|
||||||
|
default: 0,
|
||||||
|
minimumExclusive: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "kcont",
|
||||||
|
label: "接触刚度",
|
||||||
|
quantity: "translational_stiffness",
|
||||||
|
unit: "N/m",
|
||||||
|
default: 1e6,
|
||||||
|
minimum: 0,
|
||||||
|
minimumExclusive: false,
|
||||||
|
visibleWhen: [{ parameter: "stiffmode", values: [1] }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "G",
|
||||||
|
label: "剪切模量",
|
||||||
|
quantity: "pressure",
|
||||||
|
unit: "Pa",
|
||||||
|
default: 8.57e10,
|
||||||
|
minimum: 0,
|
||||||
|
minimumExclusive: false,
|
||||||
|
visibleWhen: [{ parameter: "stiffmode", values: [2] }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "sdiam",
|
||||||
|
label: "弹簧直径",
|
||||||
|
quantity: "length",
|
||||||
|
unit: "m",
|
||||||
|
default: 0.02,
|
||||||
|
minimum: 0,
|
||||||
|
minimumExclusive: false,
|
||||||
|
visibleWhen: [{ parameter: "stiffmode", values: [2] }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "wdiam",
|
||||||
|
label: "线径",
|
||||||
|
quantity: "length",
|
||||||
|
unit: "m",
|
||||||
|
default: 0.002,
|
||||||
|
minimum: 0,
|
||||||
|
minimumExclusive: false,
|
||||||
|
visibleWhen: [{ parameter: "stiffmode", values: [2] }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "rcont",
|
||||||
|
label: "接触阻尼",
|
||||||
|
quantity: "translational_damping",
|
||||||
|
unit: "N/(m/s)",
|
||||||
|
default: 0,
|
||||||
|
minimum: 0,
|
||||||
|
minimumExclusive: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Pdis",
|
||||||
|
label: "满阻尼穿透",
|
||||||
|
quantity: "length",
|
||||||
|
unit: "m",
|
||||||
|
default: 1e-7,
|
||||||
|
minimum: 0,
|
||||||
|
minimumExclusive: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "stiffmode",
|
||||||
|
label: "刚度模式",
|
||||||
|
quantity: "dimensionless",
|
||||||
|
unit: "",
|
||||||
|
default: 1,
|
||||||
|
minimum: 1,
|
||||||
|
maximum: 2,
|
||||||
|
minimumExclusive: false,
|
||||||
|
editor: "choice",
|
||||||
|
options: [
|
||||||
|
{ value: 1, label: "数值刚度" },
|
||||||
|
{ value: 2, label: "几何参数" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "discContactOption",
|
||||||
|
label: "允许负接触力",
|
||||||
|
quantity: "dimensionless",
|
||||||
|
unit: "",
|
||||||
|
default: 1,
|
||||||
|
minimum: 1,
|
||||||
|
maximum: 2,
|
||||||
|
minimumExclusive: false,
|
||||||
|
editor: "choice",
|
||||||
|
options: [
|
||||||
|
{ value: 1, label: "允许负接触力" },
|
||||||
|
{ value: 2, label: "不允许负接触力" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -50,6 +50,22 @@ async function addMecmasEncodingTestComponent(page: Page) {
|
|||||||
await node.click();
|
await node.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function addParameterMetadataTestComponent(
|
||||||
|
page: Page,
|
||||||
|
label: string,
|
||||||
|
type: string,
|
||||||
|
) {
|
||||||
|
const canvas = page.locator(".flow-canvas .react-flow__pane");
|
||||||
|
await page
|
||||||
|
.getByRole("button", { name: label, exact: true })
|
||||||
|
.dragTo(canvas, { targetPosition: { x: 620, y: 330 } });
|
||||||
|
const node = page.locator(
|
||||||
|
`.flow-canvas .react-flow__node[data-id="${type}_1"]`,
|
||||||
|
);
|
||||||
|
await expect(node).toBeVisible();
|
||||||
|
await node.click();
|
||||||
|
}
|
||||||
|
|
||||||
test("组件参数和仿真设置使用共享的三列表格", async ({ page }) => {
|
test("组件参数和仿真设置使用共享的三列表格", async ({ page }) => {
|
||||||
await page.goto("/");
|
await page.goto("/");
|
||||||
await addPneumaticTestComponent(page);
|
await addPneumaticTestComponent(page);
|
||||||
@@ -310,6 +326,194 @@ test("通用离散选项按多条件控制参数行且保留隐藏值和未知
|
|||||||
await expect(page.getByLabel("高级参数", { exact: true })).toHaveValue("42");
|
await expect(page.getByLabel("高级参数", { exact: true })).toHaveValue("42");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("PNOR001 和 PNL0001 控制项前置并切换折叠组中的条件参数", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
await page.goto("/");
|
||||||
|
await addParameterMetadataTestComponent(
|
||||||
|
page,
|
||||||
|
"PNOR001 常系数气动孔口",
|
||||||
|
"amesim_pnor001",
|
||||||
|
);
|
||||||
|
|
||||||
|
const componentTable = page.getByRole("table", { name: "组件参数" });
|
||||||
|
const flowset = page.getByLabel("流量系数设置", { exact: true });
|
||||||
|
const flowGroup = componentTable.getByRole("button", { name: /流量系数/ });
|
||||||
|
await expect(flowset.locator("option")).toHaveText(["Cq", "Cv", "Kv"]);
|
||||||
|
await expect(flowset).toHaveValue("1");
|
||||||
|
await expect(flowGroup).toHaveAttribute("aria-expanded", "false");
|
||||||
|
await expect(page.getByLabel("流量系数 Cq", { exact: true })).toBeHidden();
|
||||||
|
await expect(page.getByLabel("孔口面积", { exact: true })).toBeHidden();
|
||||||
|
await expect(parameterRow(componentTable, "流量系数 Cv")).toHaveCount(0);
|
||||||
|
const flowsetBox = await parameterRow(
|
||||||
|
componentTable,
|
||||||
|
"流量系数设置",
|
||||||
|
).boundingBox();
|
||||||
|
const flowGroupBox = await flowGroup.boundingBox();
|
||||||
|
expect(flowsetBox).not.toBeNull();
|
||||||
|
expect(flowGroupBox).not.toBeNull();
|
||||||
|
expect(flowsetBox!.y).toBeLessThan(flowGroupBox!.y);
|
||||||
|
|
||||||
|
await flowGroup.click();
|
||||||
|
const area = page.getByLabel("孔口面积", { exact: true });
|
||||||
|
await expect(page.getByLabel("流量系数 Cq", { exact: true })).toBeVisible();
|
||||||
|
await expect(area).toBeVisible();
|
||||||
|
await area.fill("7.5e-6");
|
||||||
|
await area.press("Enter");
|
||||||
|
await expect(area).toHaveValue("7.5e-6");
|
||||||
|
|
||||||
|
await flowset.selectOption("2");
|
||||||
|
await expect(parameterRow(componentTable, "流量系数 Cq")).toHaveCount(0);
|
||||||
|
await expect(parameterRow(componentTable, "孔口面积")).toHaveCount(0);
|
||||||
|
await expect(page.getByLabel("流量系数 Cv", { exact: true })).toBeVisible();
|
||||||
|
await expect(parameterRow(componentTable, "流量系数 Kv")).toHaveCount(0);
|
||||||
|
await flowset.selectOption("1");
|
||||||
|
await expect(area).toHaveValue("7.5e-6");
|
||||||
|
|
||||||
|
await addParameterMetadataTestComponent(
|
||||||
|
page,
|
||||||
|
"PNL0001 C-R 动态管路",
|
||||||
|
"amesim_pnl0001",
|
||||||
|
);
|
||||||
|
const mode = page.getByLabel("热模型", { exact: true });
|
||||||
|
const thermalGroup = componentTable.getByRole("button", { name: /热力学/ });
|
||||||
|
await expect(mode.locator("option")).toHaveText(["多方过程", "带换热"]);
|
||||||
|
await expect(mode).toHaveValue("2");
|
||||||
|
const pnlParameterOrder = (
|
||||||
|
await componentTable.getByRole("rowheader").allTextContents()
|
||||||
|
).map((text) => text.trim());
|
||||||
|
expect(pnlParameterOrder.indexOf("热模型")).toBeLessThan(
|
||||||
|
pnlParameterOrder.indexOf("管径"),
|
||||||
|
);
|
||||||
|
await expect(thermalGroup).toHaveAttribute("aria-expanded", "false");
|
||||||
|
await thermalGroup.click();
|
||||||
|
await expect(parameterRow(componentTable, "多方指数")).toHaveCount(0);
|
||||||
|
await expect(page.getByLabel("换热系数", { exact: true })).toBeVisible();
|
||||||
|
await expect(page.getByLabel("外部温度", { exact: true })).toBeVisible();
|
||||||
|
|
||||||
|
await mode.selectOption("1");
|
||||||
|
await expect(page.getByLabel("多方指数", { exact: true })).toBeVisible();
|
||||||
|
await expect(parameterRow(componentTable, "换热系数")).toHaveCount(0);
|
||||||
|
await expect(parameterRow(componentTable, "外部温度")).toHaveCount(0);
|
||||||
|
await expect(thermalGroup).toHaveAttribute("aria-expanded", "true");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("UD00 段数前置并逐段显示第 2 至第 4 段参数", async ({ page }) => {
|
||||||
|
await page.goto("/");
|
||||||
|
await addParameterMetadataTestComponent(
|
||||||
|
page,
|
||||||
|
"UD00 分段线性信号",
|
||||||
|
"amesim_ud00",
|
||||||
|
);
|
||||||
|
|
||||||
|
const componentTable = page.getByRole("table", { name: "组件参数" });
|
||||||
|
const stageCount = page.getByLabel("段数", { exact: true });
|
||||||
|
const cyclic = page.getByLabel("循环", { exact: true });
|
||||||
|
const stageGroup = componentTable.getByRole("button", { name: /分段参数/ });
|
||||||
|
await expect(stageCount.locator("option")).toHaveText([
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
"5",
|
||||||
|
"6",
|
||||||
|
"7",
|
||||||
|
"8",
|
||||||
|
]);
|
||||||
|
await expect(cyclic.locator("option")).toHaveText(["否", "是"]);
|
||||||
|
const parameterOrder = (
|
||||||
|
await componentTable.getByRole("rowheader").allTextContents()
|
||||||
|
).map((text) => text.trim());
|
||||||
|
expect(parameterOrder.indexOf("段数")).toBeLessThan(
|
||||||
|
parameterOrder.indexOf("启动时间"),
|
||||||
|
);
|
||||||
|
expect(parameterOrder.indexOf("循环")).toBeLessThan(
|
||||||
|
parameterOrder.indexOf("启动时间"),
|
||||||
|
);
|
||||||
|
await expect(stageGroup).toHaveAttribute("aria-expanded", "false");
|
||||||
|
await expect(page.getByLabel("第 1 段起点", { exact: true })).toBeHidden();
|
||||||
|
await stageGroup.click();
|
||||||
|
await expect(page.getByLabel("第 1 段起点", { exact: true })).toBeVisible();
|
||||||
|
|
||||||
|
const expectStageVisibility = async (stage: number, visible: boolean) => {
|
||||||
|
for (const suffix of ["起点", "终点", "时长"]) {
|
||||||
|
const row = parameterRow(componentTable, `第 ${stage} 段${suffix}`);
|
||||||
|
if (visible) {
|
||||||
|
await expect(row).toBeVisible();
|
||||||
|
} else {
|
||||||
|
await expect(row).toHaveCount(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await expectStageVisibility(2, false);
|
||||||
|
await expectStageVisibility(3, false);
|
||||||
|
await expectStageVisibility(4, false);
|
||||||
|
await stageCount.selectOption("2");
|
||||||
|
await expectStageVisibility(2, true);
|
||||||
|
await expectStageVisibility(3, false);
|
||||||
|
await expectStageVisibility(4, false);
|
||||||
|
await stageCount.selectOption("3");
|
||||||
|
await expectStageVisibility(2, true);
|
||||||
|
await expectStageVisibility(3, true);
|
||||||
|
await expectStageVisibility(4, false);
|
||||||
|
await stageCount.selectOption("4");
|
||||||
|
await expectStageVisibility(2, true);
|
||||||
|
await expectStageVisibility(3, true);
|
||||||
|
await expectStageVisibility(4, true);
|
||||||
|
await expect(stageGroup).toHaveAttribute("aria-expanded", "true");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("LSTP00A 刚度模式前置并切换数值与几何刚度参数", async ({ page }) => {
|
||||||
|
await page.goto("/");
|
||||||
|
await addParameterMetadataTestComponent(
|
||||||
|
page,
|
||||||
|
"LSTP00A 弹性接触",
|
||||||
|
"amesim_lstp00a",
|
||||||
|
);
|
||||||
|
|
||||||
|
const componentTable = page.getByRole("table", { name: "组件参数" });
|
||||||
|
const stiffnessMode = page.getByLabel("刚度模式", { exact: true });
|
||||||
|
const contactOption = page.getByLabel("允许负接触力", { exact: true });
|
||||||
|
const stiffnessGroup = componentTable.getByRole("button", { name: /刚度/ });
|
||||||
|
const contactGroup = componentTable.getByRole("button", { name: /接触/ });
|
||||||
|
await expect(stiffnessMode.locator("option")).toHaveText([
|
||||||
|
"数值刚度",
|
||||||
|
"几何参数",
|
||||||
|
]);
|
||||||
|
await expect(contactOption.locator("option")).toHaveText([
|
||||||
|
"允许负接触力",
|
||||||
|
"不允许负接触力",
|
||||||
|
]);
|
||||||
|
await expect(stiffnessGroup).toHaveAttribute("aria-expanded", "false");
|
||||||
|
await expect(contactGroup).toHaveAttribute("aria-expanded", "false");
|
||||||
|
const stiffnessModeBox = await parameterRow(
|
||||||
|
componentTable,
|
||||||
|
"刚度模式",
|
||||||
|
).boundingBox();
|
||||||
|
const stiffnessGroupBox = await stiffnessGroup.boundingBox();
|
||||||
|
expect(stiffnessModeBox).not.toBeNull();
|
||||||
|
expect(stiffnessGroupBox).not.toBeNull();
|
||||||
|
expect(stiffnessModeBox!.y).toBeLessThan(stiffnessGroupBox!.y);
|
||||||
|
|
||||||
|
await stiffnessGroup.click();
|
||||||
|
await expect(page.getByLabel("接触刚度", { exact: true })).toBeVisible();
|
||||||
|
for (const label of ["有效圈数", "剪切模量", "弹簧直径", "线径"]) {
|
||||||
|
await expect(parameterRow(componentTable, label)).toHaveCount(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
await stiffnessMode.selectOption("2");
|
||||||
|
await expect(parameterRow(componentTable, "接触刚度")).toHaveCount(0);
|
||||||
|
for (const label of ["有效圈数", "剪切模量", "弹簧直径", "线径"]) {
|
||||||
|
await expect(page.getByLabel(label, { exact: true })).toBeVisible();
|
||||||
|
}
|
||||||
|
await expect(stiffnessGroup).toHaveAttribute("aria-expanded", "true");
|
||||||
|
|
||||||
|
await stiffnessMode.selectOption("1");
|
||||||
|
await expect(page.getByLabel("接触刚度", { exact: true })).toBeVisible();
|
||||||
|
await expect(parameterRow(componentTable, "剪切模量")).toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
test("MECMAS21 可配置参数前置并按条件显示可折叠参数组", async ({
|
test("MECMAS21 可配置参数前置并按条件显示可折叠参数组", async ({
|
||||||
page,
|
page,
|
||||||
}) => {
|
}) => {
|
||||||
|
|||||||
@@ -280,6 +280,25 @@ class AmesimMechanicalPublicComponentTests(unittest.TestCase):
|
|||||||
{name: value},
|
{name: value},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_lstp00a_registry_rejects_invalid_choice_values(self) -> None:
|
||||||
|
invalid_options = {
|
||||||
|
"stiffmode": (0.0, 1.5, 3.0),
|
||||||
|
"discContactOption": (0.0, 1.5, 3.0),
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, values in invalid_options.items():
|
||||||
|
for value in values:
|
||||||
|
with self.subTest(name=name, value=value):
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
ValueError,
|
||||||
|
"must be (?:one of|at least|at most)",
|
||||||
|
):
|
||||||
|
COMPONENT_MODEL_REGISTRY["amesim_lstp00a"].create(
|
||||||
|
"contact_1",
|
||||||
|
self.medium,
|
||||||
|
{name: value},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
@@ -45,7 +45,7 @@ class AmesimPnl0001ComponentTests(unittest.TestCase):
|
|||||||
self.medium,
|
self.medium,
|
||||||
{"gi": 1.5},
|
{"gi": 1.5},
|
||||||
)
|
)
|
||||||
with self.assertRaisesRegex(ValueError, "mode must be an integer"):
|
with self.assertRaisesRegex(ValueError, "must be one of"):
|
||||||
COMPONENT_MODEL_REGISTRY["amesim_pnl0001"].create(
|
COMPONENT_MODEL_REGISTRY["amesim_pnl0001"].create(
|
||||||
"pnl_1",
|
"pnl_1",
|
||||||
self.medium,
|
self.medium,
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class AmesimPnor001ComponentTests(unittest.TestCase):
|
|||||||
self.assertEqual(orifice.flowset, 1)
|
self.assertEqual(orifice.flowset, 1)
|
||||||
|
|
||||||
def test_rejects_fractional_integer_parameters(self) -> None:
|
def test_rejects_fractional_integer_parameters(self) -> None:
|
||||||
with self.assertRaisesRegex(ValueError, "flowset must be an integer"):
|
with self.assertRaisesRegex(ValueError, "must be one of"):
|
||||||
COMPONENT_MODEL_REGISTRY["amesim_pnor001"].create(
|
COMPONENT_MODEL_REGISTRY["amesim_pnor001"].create(
|
||||||
"pnor_1",
|
"pnor_1",
|
||||||
self.medium,
|
self.medium,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class AmesimPnvo001FixedOpeningComponentTests(unittest.TestCase):
|
|||||||
self.assertEqual(valve.opening, 1.0)
|
self.assertEqual(valve.opening, 1.0)
|
||||||
|
|
||||||
def test_rejects_fractional_flowset(self) -> None:
|
def test_rejects_fractional_flowset(self) -> None:
|
||||||
with self.assertRaisesRegex(ValueError, "flowset must be an integer"):
|
with self.assertRaisesRegex(ValueError, "must be one of"):
|
||||||
COMPONENT_MODEL_REGISTRY["amesim_pnvo001_fixed"].create(
|
COMPONENT_MODEL_REGISTRY["amesim_pnvo001_fixed"].create(
|
||||||
"valve_1",
|
"valve_1",
|
||||||
self.medium,
|
self.medium,
|
||||||
|
|||||||
@@ -59,12 +59,31 @@ class AmesimSignalComponentTests(unittest.TestCase):
|
|||||||
self.assertEqual(signal.signal_event_times(0.0, 5.0), (1.0, 2.0, 3.0, 4.0))
|
self.assertEqual(signal.signal_event_times(0.0, 5.0), (1.0, 2.0, 3.0, 4.0))
|
||||||
|
|
||||||
def test_ud00_registry_rejects_fractional_stage_controls(self) -> None:
|
def test_ud00_registry_rejects_fractional_stage_controls(self) -> None:
|
||||||
with self.assertRaisesRegex(ValueError, "nstages must be an integer"):
|
with self.assertRaisesRegex(ValueError, "must be one of"):
|
||||||
COMPONENT_MODEL_REGISTRY["amesim_ud00"].create(
|
COMPONENT_MODEL_REGISTRY["amesim_ud00"].create(
|
||||||
"piecewise_1",
|
"piecewise_1",
|
||||||
self.medium,
|
self.medium,
|
||||||
{"nstages": 1.5},
|
{"nstages": 1.5},
|
||||||
)
|
)
|
||||||
|
for name, value in (("nstages", 9.0), ("iscyclic", 2.0)):
|
||||||
|
with self.subTest(name=name):
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
ValueError,
|
||||||
|
"must be (?:one of|at most)",
|
||||||
|
):
|
||||||
|
COMPONENT_MODEL_REGISTRY["amesim_ud00"].create(
|
||||||
|
"piecewise_1",
|
||||||
|
self.medium,
|
||||||
|
{name: value},
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_pnvo001_registry_rejects_invalid_flowset_choice(self) -> None:
|
||||||
|
with self.assertRaisesRegex(ValueError, "must be one of"):
|
||||||
|
COMPONENT_MODEL_REGISTRY["amesim_pnvo001"].create(
|
||||||
|
"valve_1",
|
||||||
|
self.medium,
|
||||||
|
{"flowset": 1.5},
|
||||||
|
)
|
||||||
|
|
||||||
def test_pnvo001_signal_opening_reads_res_port(self) -> None:
|
def test_pnvo001_signal_opening_reads_res_port(self) -> None:
|
||||||
valve = COMPONENT_MODEL_REGISTRY["amesim_pnvo001"].create(
|
valve = COMPONENT_MODEL_REGISTRY["amesim_pnvo001"].create(
|
||||||
|
|||||||
@@ -401,6 +401,174 @@ class ComponentCatalogTests(unittest.TestCase):
|
|||||||
self.assertEqual(pnl0003_parameters["p1_0"]["unit"], "Pa")
|
self.assertEqual(pnl0003_parameters["p1_0"]["unit"], "Pa")
|
||||||
self.assertEqual(pnl0003_parameters["T2_0"]["quantity"], "temperature")
|
self.assertEqual(pnl0003_parameters["T2_0"]["quantity"], "temperature")
|
||||||
|
|
||||||
|
def test_amesim_configurable_parameters_expose_choices_and_groups(self) -> None:
|
||||||
|
def parameters(model_type: str) -> dict[str, dict[str, object]]:
|
||||||
|
return {
|
||||||
|
parameter["name"]: parameter
|
||||||
|
for parameter in self.components[model_type]["parameters"]
|
||||||
|
}
|
||||||
|
|
||||||
|
flow_options = [
|
||||||
|
{"value": 1.0, "label": "Cq"},
|
||||||
|
{"value": 2.0, "label": "Cv"},
|
||||||
|
{"value": 3.0, "label": "Kv"},
|
||||||
|
]
|
||||||
|
for model_type, area_name in (
|
||||||
|
("amesim_pnor001", "area"),
|
||||||
|
("amesim_pnvo001_fixed", "area0"),
|
||||||
|
("amesim_pnvo001", "area0"),
|
||||||
|
):
|
||||||
|
with self.subTest(model_type=model_type):
|
||||||
|
component = self.components[model_type]
|
||||||
|
model_parameters = parameters(model_type)
|
||||||
|
self.assertEqual(component["modelVersion"], "0.2.0")
|
||||||
|
self.assertEqual(model_parameters["flowset"]["editor"], "choice")
|
||||||
|
self.assertEqual(model_parameters["flowset"]["options"], flow_options)
|
||||||
|
self.assertEqual(
|
||||||
|
model_parameters["cq"]["visibleWhen"],
|
||||||
|
[{"parameter": "flowset", "values": [1.0]}],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
model_parameters[area_name]["visibleWhen"],
|
||||||
|
[{"parameter": "flowset", "values": [1.0]}],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
model_parameters["Cv"]["visibleWhen"],
|
||||||
|
[{"parameter": "flowset", "values": [2.0]}],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
model_parameters["Kv"]["visibleWhen"],
|
||||||
|
[{"parameter": "flowset", "values": [3.0]}],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
component["parameterGroups"],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "flow_coefficient",
|
||||||
|
"label": "流量系数",
|
||||||
|
"parameters": ["cq", area_name, "Cv", "Kv"],
|
||||||
|
"order": 10,
|
||||||
|
"defaultExpanded": False,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
thermal_options = [
|
||||||
|
{"value": 1.0, "label": "多方过程"},
|
||||||
|
{"value": 2.0, "label": "带换热"},
|
||||||
|
]
|
||||||
|
for model_type in ("amesim_pnl0001", "amesim_pnl0002", "amesim_pnl0003"):
|
||||||
|
with self.subTest(model_type=model_type):
|
||||||
|
component = self.components[model_type]
|
||||||
|
model_parameters = parameters(model_type)
|
||||||
|
self.assertEqual(component["modelVersion"], "0.2.0")
|
||||||
|
self.assertEqual(model_parameters["mode"]["editor"], "choice")
|
||||||
|
self.assertEqual(model_parameters["mode"]["options"], thermal_options)
|
||||||
|
self.assertEqual(
|
||||||
|
model_parameters["k"]["visibleWhen"],
|
||||||
|
[{"parameter": "mode", "values": [1.0]}],
|
||||||
|
)
|
||||||
|
for name in ("kth", "extemp"):
|
||||||
|
self.assertEqual(
|
||||||
|
model_parameters[name]["visibleWhen"],
|
||||||
|
[{"parameter": "mode", "values": [2.0]}],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
component["parameterGroups"],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "thermodynamics",
|
||||||
|
"label": "热力学",
|
||||||
|
"parameters": ["k", "kth", "extemp"],
|
||||||
|
"order": 10,
|
||||||
|
"defaultExpanded": False,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
ud00 = self.components["amesim_ud00"]
|
||||||
|
ud00_parameters = parameters("amesim_ud00")
|
||||||
|
self.assertEqual(ud00["modelVersion"], "0.2.0")
|
||||||
|
self.assertEqual(ud00_parameters["nstages"]["editor"], "choice")
|
||||||
|
self.assertEqual(
|
||||||
|
ud00_parameters["nstages"]["options"],
|
||||||
|
[
|
||||||
|
{"value": float(stage_count), "label": str(stage_count)}
|
||||||
|
for stage_count in range(1, 9)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
ud00_parameters["iscyclic"]["options"],
|
||||||
|
[{"value": 0.0, "label": "否"}, {"value": 1.0, "label": "是"}],
|
||||||
|
)
|
||||||
|
self.assertNotIn("visibleWhen", ud00_parameters["start1"])
|
||||||
|
self.assertEqual(
|
||||||
|
ud00_parameters["start2"]["visibleWhen"],
|
||||||
|
[{"parameter": "nstages", "values": [2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]}],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
ud00_parameters["t8"]["visibleWhen"],
|
||||||
|
[{"parameter": "nstages", "values": [8.0]}],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
ud00["parameterGroups"][0]["parameters"],
|
||||||
|
[
|
||||||
|
name
|
||||||
|
for stage_index in range(1, 9)
|
||||||
|
for name in (
|
||||||
|
f"start{stage_index}",
|
||||||
|
f"end{stage_index}",
|
||||||
|
f"t{stage_index}",
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
lstp = self.components["amesim_lstp00a"]
|
||||||
|
lstp_parameters = parameters("amesim_lstp00a")
|
||||||
|
self.assertEqual(lstp["modelVersion"], "0.2.0")
|
||||||
|
self.assertEqual(
|
||||||
|
lstp_parameters["stiffmode"]["options"],
|
||||||
|
[
|
||||||
|
{"value": 1.0, "label": "数值刚度"},
|
||||||
|
{"value": 2.0, "label": "几何参数"},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
lstp_parameters["discContactOption"]["options"],
|
||||||
|
[
|
||||||
|
{"value": 1.0, "label": "允许负接触力"},
|
||||||
|
{"value": 2.0, "label": "不允许负接触力"},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
lstp_parameters["kcont"]["visibleWhen"],
|
||||||
|
[{"parameter": "stiffmode", "values": [1.0]}],
|
||||||
|
)
|
||||||
|
for name in ("na", "G", "sdiam", "wdiam"):
|
||||||
|
self.assertEqual(
|
||||||
|
lstp_parameters[name]["visibleWhen"],
|
||||||
|
[{"parameter": "stiffmode", "values": [2.0]}],
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
lstp["parameterGroups"],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "stiffness",
|
||||||
|
"label": "刚度",
|
||||||
|
"parameters": ["kcont", "G", "sdiam", "wdiam", "na"],
|
||||||
|
"order": 10,
|
||||||
|
"defaultExpanded": False,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "contact",
|
||||||
|
"label": "接触",
|
||||||
|
"parameters": ["gap0", "rcont", "Pdis"],
|
||||||
|
"order": 20,
|
||||||
|
"defaultExpanded": False,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
def test_every_registered_component_is_in_the_catalog(self) -> None:
|
def test_every_registered_component_is_in_the_catalog(self) -> None:
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
set(self.components),
|
set(self.components),
|
||||||
|
|||||||
Reference in new issue
Block a user