完善MECMAS21参数配置与分组交互
This commit is contained in:
1 parent
32f21f08ff
commit
be54070855
28 files changed
+3418
-202
No files matched your search
@@ -72,7 +72,125 @@ class AmesimMechanicalPublicComponentTests(unittest.TestCase):
|
||||
self.assertAlmostEqual(mass.port_1.x, 0.1)
|
||||
self.assertAlmostEqual(mass.port_2.v, 0.2)
|
||||
|
||||
def test_mecmas21_uses_amesim_one_two_friction_encoding(self) -> None:
|
||||
disabled = AmesimMecmas21(
|
||||
"mass_disabled",
|
||||
self.medium,
|
||||
useFriction=1.0,
|
||||
fcoul=5.0,
|
||||
v0=2.0,
|
||||
)
|
||||
enabled = AmesimMecmas21(
|
||||
"mass_enabled",
|
||||
self.medium,
|
||||
useFriction=2.0,
|
||||
fcoul=5.0,
|
||||
v0=2.0,
|
||||
)
|
||||
|
||||
self.assertFalse(disabled.use_friction)
|
||||
self.assertEqual(disabled._dry_friction_force(), 0.0)
|
||||
self.assertTrue(enabled.use_friction)
|
||||
self.assertEqual(enabled._dry_friction_force(), -5.0)
|
||||
|
||||
def test_mecmas21_choice_metadata_preserves_amesim_codes(self) -> None:
|
||||
definitions = {
|
||||
definition.name: definition
|
||||
for definition in AmesimMecmas21.PARAMETERS
|
||||
}
|
||||
expected_options = {
|
||||
"useFriction": ((1.0, "否"), (2.0, "是")),
|
||||
"stoptype": (
|
||||
(1.0, "理想限位"),
|
||||
(2.0, "弹性限位"),
|
||||
(3.0, "恢复碰撞"),
|
||||
(4.0, "无限位"),
|
||||
),
|
||||
"discContactOption": (
|
||||
(1.0, "允许负接触力"),
|
||||
(2.0, "不允许负接触力"),
|
||||
),
|
||||
"strib": ((1.0, "否"), (2.0, "是")),
|
||||
"frictionType": ((1.0, "简单"), (2.0, "高级")),
|
||||
}
|
||||
|
||||
for name, options in expected_options.items():
|
||||
with self.subTest(name=name):
|
||||
definition = definitions[name]
|
||||
self.assertEqual(definition.editor, "choice")
|
||||
self.assertEqual(
|
||||
tuple((option.value, option.label) for option in definition.options),
|
||||
options,
|
||||
)
|
||||
self.assertIn("尚未实现", definitions["frictionType"].description)
|
||||
self.assertIn("尚未实现", definitions["strib"].description)
|
||||
self.assertEqual(definitions["theta"].label, "倾角(度)")
|
||||
self.assertIn("+90°", definitions["theta"].description)
|
||||
self.assertIn("-90°", definitions["theta"].description)
|
||||
self.assertIn("重力分量", definitions["theta"].description)
|
||||
self.assertEqual(AmesimMecmas21.MODEL_VERSION, "0.2.0")
|
||||
|
||||
def test_mecmas21_visibility_matches_amesim_parameter_dependencies(self) -> None:
|
||||
definitions = {
|
||||
definition.name: definition
|
||||
for definition in AmesimMecmas21.PARAMETERS
|
||||
}
|
||||
expected_visibility = {
|
||||
"fstick": (
|
||||
("stoptype", (1.0, 2.0, 4.0)),
|
||||
("useFriction", (2.0,)),
|
||||
),
|
||||
"fcoul": (
|
||||
("stoptype", (1.0, 2.0, 4.0)),
|
||||
("useFriction", (2.0,)),
|
||||
),
|
||||
"rvisc": (("useFriction", (2.0,)),),
|
||||
"wind": (("useFriction", (2.0,)),),
|
||||
"dvel": (
|
||||
("stoptype", (1.0, 2.0, 4.0)),
|
||||
("useFriction", (2.0,)),
|
||||
("frictionType", (2.0,)),
|
||||
),
|
||||
"restdvel": (("stoptype", (3.0,)),),
|
||||
"restcoeff": (("stoptype", (3.0,)),),
|
||||
"astrib": (
|
||||
("stoptype", (1.0, 2.0, 4.0)),
|
||||
("useFriction", (2.0,)),
|
||||
("frictionType", (2.0,)),
|
||||
("strib", (2.0,)),
|
||||
),
|
||||
"xmin": (("stoptype", (1.0, 2.0, 3.0)),),
|
||||
"Kbmin": (("stoptype", (2.0,)),),
|
||||
"Dbmin": (("stoptype", (2.0,)),),
|
||||
"Pdmin": (("stoptype", (2.0,)),),
|
||||
"xmax": (("stoptype", (1.0, 2.0, 3.0)),),
|
||||
"Kbmax": (("stoptype", (2.0,)),),
|
||||
"Dbmax": (("stoptype", (2.0,)),),
|
||||
"Pdmax": (("stoptype", (2.0,)),),
|
||||
"discContactOption": (("stoptype", (2.0,)),),
|
||||
"strib": (
|
||||
("stoptype", (1.0, 2.0, 4.0)),
|
||||
("useFriction", (2.0,)),
|
||||
("frictionType", (2.0,)),
|
||||
),
|
||||
"frictionType": (
|
||||
("stoptype", (1.0, 2.0, 4.0)),
|
||||
("useFriction", (2.0,)),
|
||||
),
|
||||
}
|
||||
|
||||
for name, expected in expected_visibility.items():
|
||||
with self.subTest(name=name):
|
||||
self.assertEqual(
|
||||
tuple(
|
||||
(condition.parameter, condition.values)
|
||||
for condition in definitions[name].visible_when
|
||||
),
|
||||
expected,
|
||||
)
|
||||
for name in ("mass", "theta", "useFriction", "stoptype", "v0", "x0"):
|
||||
with self.subTest(always_visible=name):
|
||||
self.assertEqual(definitions[name].visible_when, ())
|
||||
|
||||
def test_lmechn1_ties_active_port_kinematics_and_balances_force(self) -> None:
|
||||
node = AmesimLmechn1("node_1", self.medium, v1=2.0, sum=1.0)
|
||||
@@ -136,14 +254,32 @@ class AmesimMechanicalPublicComponentTests(unittest.TestCase):
|
||||
self.assertAlmostEqual(contact.gap, 0.0005)
|
||||
self.assertAlmostEqual(contact.contact_force, 0.0)
|
||||
|
||||
def test_mecmas21_registry_rejects_fractional_integer_options(self) -> None:
|
||||
with self.assertRaisesRegex(ValueError, "useFriction must be an integer"):
|
||||
def test_mecmas21_registry_rejects_fractional_choice_value(self) -> None:
|
||||
with self.assertRaisesRegex(ValueError, "must be one of"):
|
||||
COMPONENT_MODEL_REGISTRY["amesim_mecmas21"].create(
|
||||
"mass_1",
|
||||
self.medium,
|
||||
{"useFriction": 0.5},
|
||||
)
|
||||
|
||||
def test_mecmas21_registry_rejects_unknown_integer_options(self) -> None:
|
||||
invalid_options = {
|
||||
"useFriction": 0.0,
|
||||
"stoptype": 0.0,
|
||||
"discContactOption": 3.0,
|
||||
"strib": 0.0,
|
||||
"frictionType": 3.0,
|
||||
}
|
||||
|
||||
for name, value in invalid_options.items():
|
||||
with self.subTest(name=name):
|
||||
with self.assertRaisesRegex(ValueError, "must be one of"):
|
||||
COMPONENT_MODEL_REGISTRY["amesim_mecmas21"].create(
|
||||
"mass_1",
|
||||
self.medium,
|
||||
{name: value},
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user