"""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)