75 lines
3.7 KiB
Python
75 lines
3.7 KiB
Python
"""External Amesim encodings, separate from the saved public model contract.
|
||
|
||
Apply these mappings only when reading Amesim parameters. A browser JSON/XML
|
||
already uses public values: applying the mapping again changes its meaning.
|
||
Reviewed against the installed Amesim 2404 submodel parameter declarations.
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
|
||
AMESIM_CHOICE_VALUES = {
|
||
("amesim_ud00", "nstages"): {i: i for i in range(1, 9)},
|
||
("amesim_ud00", "iscyclic"): {1: 0, 2: 1},
|
||
("amesim_lstp00a", "stiffmode"): {1: 1, 2: 2},
|
||
("amesim_lstp00a", "discContactOption"): {1: 1, 2: 2},
|
||
("amesim_mecmas21", "useFriction"): {1: 1, 2: 2},
|
||
("amesim_mecmas21", "stoptype"): {1: 1, 2: 2, 3: 3, 4: 4},
|
||
("amesim_mecmas21", "discContactOption"): {1: 1, 2: 2},
|
||
("amesim_mecmas21", "strib"): {1: 1, 2: 2},
|
||
("amesim_mecmas21", "frictionType"): {1: 1, 2: 2},
|
||
("amesim_lmechn1", "sum"): {1: 1},
|
||
**{(model, "mode"): {1: 1, 2: 2} for model in
|
||
("amesim_pnl0001", "amesim_pnl0002", "amesim_pnl0003")},
|
||
**{(model, "flowset"): {1: 1, 2: 2, 3: 3} for model in
|
||
("amesim_pnor001", "amesim_pnvo001", "amesim_pnvo001_fixed")},
|
||
}
|
||
|
||
|
||
def amesim_choice_to_public(model_type: str, parameter: str, value: float) -> float:
|
||
mapping = AMESIM_CHOICE_VALUES.get((model_type, parameter))
|
||
if mapping is None:
|
||
return value
|
||
if value not in mapping:
|
||
raise ValueError(f"{model_type}.{parameter}: unknown Amesim encoding {value}; "
|
||
f"expected one of {tuple(mapping)}")
|
||
return float(mapping[value])
|
||
|
||
|
||
def contact_stiffness(component) -> float:
|
||
"""SI constant lowering; the contact force is evaluated in C."""
|
||
if int(component.stiffmode) == 1:
|
||
if component.kcont <= 0:
|
||
raise ValueError(f"{component.name}: LSTP00A 数值刚度模式要求 kcont > 0")
|
||
return component.kcont
|
||
if component.G < 0:
|
||
raise ValueError(f"{component.name}: LSTP00A 几何刚度模式要求 G >= 0")
|
||
for name in ("sdiam", "wdiam", "na"):
|
||
if getattr(component, name) <= 0:
|
||
raise ValueError(f"{component.name}: LSTP00A 几何刚度模式要求 {name} > 0")
|
||
return component.G * component.wdiam**4 / (8 * component.sdiam**3 * component.na)
|
||
|
||
|
||
def validate_numerical_semantics(component) -> None:
|
||
"""Reject requested behavior that cannot yet be faithfully executed.
|
||
|
||
Keep this at numerical compilation, so incomplete/future configurations
|
||
can still be edited and saved. Disabled friction settings have no effect.
|
||
"""
|
||
if component.model_type == "amesim_mecmas21" and component.use_friction and int(component.stoptype) != 3:
|
||
for name in ('dvel', 'astrib'):
|
||
if getattr(component, name) <= 0:
|
||
raise ValueError(f"{component.name}: MECMAS21 启用摩擦时 {name} 必须大于零(Amesim 参数约束)")
|
||
if component.fcoul > component.fstick:
|
||
raise ValueError(f"{component.name}: MECMAS21 库仑摩擦 fcoul 不能大于静摩擦 fstick(Amesim 参数约束)")
|
||
if component.model_type == 'amesim_mecmas21':
|
||
if int(component.stoptype) in (1, 2, 3) and component.xmin > component.xmax:
|
||
raise ValueError(f'{component.name}: MECMAS21 限位要求 xmin <= xmax')
|
||
if int(component.stoptype) == 2:
|
||
for name in ('Kbmin', 'Kbmax', 'Dbmin', 'Dbmax'):
|
||
if getattr(component, name) <= 0:
|
||
raise ValueError(f'{component.name}: MECMAS21 弹性限位要求 {name} > 0')
|
||
if component.model_type == 'amesim_mecmas21' and int(component.stoptype) == 3 and component.restdvel <= 0:
|
||
raise ValueError(f'{component.name}: MECMAS21 恢复碰撞模式要求 restdvel > 0(Amesim 参数约束)')
|
||
if component.model_type == "amesim_lstp00a":
|
||
contact_stiffness(component)
|