接入 AMESim 机械接触和节点组件

This commit is contained in:
huojiarong committed 2026-07-30 10:34:29 +00:00
1 parent 2ddaaeb56a
commit e87df789b2
8 files changed
+441 -9

No files matched your search

+134
View File
@@ -14,6 +14,20 @@ from tests.test_generic_system_xml_simulation import component_node, physical_ed
from tests.test_system_xml_protocol import physical_port
LSTP00A_DEFAULTS = {
"na": 10.0,
"gap0": 0.0,
"kcont": 1000.0,
"G": 8.57e10,
"sdiam": 0.02,
"wdiam": 0.002,
"rcont": 0.0,
"Pdis": 1.0e-7,
"stiffmode": 1.0,
"discContactOption": 1.0,
}
MECMAS21_DEFAULTS = {
"mass": 2.0,
"fstick": 0.0,
@@ -130,7 +144,127 @@ def signal_force_mass_project() -> ReactFlowProjectPayload:
)
def elastic_contact_project() -> ReactFlowProjectPayload:
left_parameters = dict(MECMAS21_DEFAULTS)
left_parameters["x0"] = 0.0
right_parameters = dict(MECMAS21_DEFAULTS)
right_parameters["x0"] = 0.001
return ReactFlowProjectPayload(
name="amesim-mechanical-elastic-contact-smoke",
nodes=[
component_node("zero_left", "amesim_f000", [mechanical_port("port_1", "right")]),
component_node(
"mass_left",
"amesim_mecmas21",
[mechanical_port("port_1", "left"), mechanical_port("port_2", "right")],
left_parameters,
),
component_node(
"contact_1",
"amesim_lstp00a",
[mechanical_port("port_1", "left"), mechanical_port("port_2", "right")],
LSTP00A_DEFAULTS,
),
component_node(
"mass_right",
"amesim_mecmas21",
[mechanical_port("port_1", "left"), mechanical_port("port_2", "right")],
right_parameters,
),
component_node("zero_right", "amesim_f000", [mechanical_port("port_1", "left")]),
],
edges=[
physical_edge("edge-1", "zero_left", "port_1", "mass_left", "port_1"),
physical_edge("edge-2", "mass_left", "port_2", "contact_1", "port_1"),
physical_edge("edge-3", "contact_1", "port_2", "mass_right", "port_1"),
physical_edge("edge-4", "mass_right", "port_2", "zero_right", "port_1"),
],
simulation={"t_start": 0.0, "t_stop": 0.02, "step": 0.01, "max_step": 0.005, "method": "BDF"},
)
def force_node_mass_project() -> ReactFlowProjectPayload:
node_ports = [mechanical_port(f"port_{index}", "left") for index in range(1, 9)]
node_ports.append(mechanical_port("port_9", "right"))
zero_nodes = [
component_node(f"zero_{index}", "amesim_f000", [mechanical_port("port_1", "right")])
for index in range(2, 9)
]
zero_edges = [
physical_edge(f"edge-zero-{index}", f"zero_{index}", "port_1", "node_1", f"port_{index}")
for index in range(2, 9)
]
return ReactFlowProjectPayload(
name="amesim-mechanical-node-smoke",
nodes=[
component_node(
"step_1",
"amesim_step0",
[signal_port("out", "output", "right")],
{"initial": 10.0, "final": 10.0, "time": 0.0},
),
component_node(
"force_1",
"amesim_forc",
[signal_port("res", "input", "left"), mechanical_port("port_2", "right")],
),
component_node("node_1", "amesim_lmechn1", node_ports, {"v1": 8.0, "sum": 1.0}),
*zero_nodes,
component_node(
"mass_1",
"amesim_mecmas21",
[mechanical_port("port_1", "left"), mechanical_port("port_2", "right")],
MECMAS21_DEFAULTS,
),
component_node("zero_right", "amesim_f000", [mechanical_port("port_1", "left")]),
],
edges=[
signal_edge("signal-1", "step_1", "out", "force_1", "res"),
physical_edge("edge-force", "force_1", "port_2", "node_1", "port_1"),
*zero_edges,
physical_edge("edge-mass", "node_1", "port_9", "mass_1", "port_1"),
physical_edge("edge-right", "mass_1", "port_2", "zero_right", "port_1"),
],
simulation={"t_start": 0.0, "t_stop": 0.02, "step": 0.01, "max_step": 0.005, "method": "BDF"},
)
class AmesimMechanicalXmlTests(unittest.TestCase):
def test_force_node_mass_project_compiles_and_simulates(self) -> None:
xml = build_reactflow_system_xml(force_node_mass_project())
report = validate_system_xml_document(xml)
self.assertTrue(report.valid, report.as_dict())
network = compile_reactflow_network(force_node_mass_project())
self.assertTrue(network.pressure_flow_structure_dict()["isSquare"])
result = run_system_xml_simulation(xml)
self.assertTrue(result["success"], result["message"])
self.assertEqual(result["series"]["step_1.out.signal"], [10.0, 10.0, 10.0])
self.assertEqual(result["series"]["force_1.res.signal"], [10.0, 10.0, 10.0])
self.assertAlmostEqual(result["series"]["mass_1.a"][0], 5.0)
self.assertGreater(result["series"]["mass_1.v"][-1], 0.0)
self.assertGreater(result["series"]["mass_1.x"][-1], 0.0)
def test_elastic_contact_project_compiles_and_simulates(self) -> None:
xml = build_reactflow_system_xml(elastic_contact_project())
report = validate_system_xml_document(xml)
self.assertTrue(report.valid, report.as_dict())
network = compile_reactflow_network(elastic_contact_project())
self.assertTrue(network.pressure_flow_structure_dict()["isSquare"])
result = run_system_xml_simulation(xml)
self.assertTrue(result["success"], result["message"])
self.assertEqual(result["series"]["time"], [0.0, 0.01, 0.02])
self.assertAlmostEqual(result["series"]["contact_1.force"][0], 1.0)
self.assertAlmostEqual(result["series"]["mass_left.a"][0], 0.5)
self.assertAlmostEqual(result["series"]["mass_right.a"][0], -0.5)
self.assertGreater(result["series"]["mass_left.x"][-1], 0.0)
self.assertLess(result["series"]["mass_right.x"][-1], 0.001)
def test_zero_force_mechanical_project_compiles_and_simulates(self) -> None:
xml = build_reactflow_system_xml(zero_force_mass_project())
report = validate_system_xml_document(xml)