Files
SystemSimulationApp/tests/test_amesim_mechanical_public_components.py
T

136 lines
4.6 KiB
Python

from __future__ import annotations
import unittest
from app.simulation.components.amesim.mechanical.translational import (
AmesimF000,
AmesimForc,
AmesimMecmas21,
AmesimLstp00a,
AmesimLmechn1,
)
from app.simulation.core.medium import IdealGasMedium
from app.simulation.registry import COMPONENT_MODEL_REGISTRY
class AmesimMechanicalPublicComponentTests(unittest.TestCase):
def setUp(self) -> None:
self.medium = IdealGasMedium()
def test_f000_constrains_mechanical_port_force_to_zero(self) -> None:
source = AmesimF000("zero_1")
source.port_1.f = 12.5
residuals = source.pressure_flow_equation_residuals()
self.assertEqual(len(residuals), 1)
self.assertEqual(residuals[0].variables, ("zero_1.port_1.f",))
self.assertAlmostEqual(residuals[0].value, 12.5)
def test_forc_converts_signal_to_opposing_source_port_force(self) -> None:
converter = AmesimForc("force_1")
converter.res.signal = 20.0
converter.port_2.f = -20.0
residuals = converter.pressure_flow_equation_residuals()
self.assertAlmostEqual(converter.output_force, 20.0)
self.assertAlmostEqual(residuals[0].value, 0.0)
self.assertEqual(converter.component_result_values(), {"force": 20.0})
def test_mecmas21_acceleration_uses_connected_port_forces(self) -> None:
mass = AmesimMecmas21(
"mass_1",
self.medium,
mass=2.0,
fcoul=0.0,
rvisc=0.0,
wind=0.0,
x0=0.1,
v0=0.2,
)
mass.port_1.f = 10.0
mass.port_2.f = -2.0
self.assertEqual(mass.get_state_vector(), [0.2, 0.1])
self.assertAlmostEqual(mass.acceleration(), 4.0)
self.assertEqual(mass.state_derivative_from_ports({}), [4.0, 0.2])
self.assertAlmostEqual(mass.port_1.x, 0.1)
self.assertAlmostEqual(mass.port_2.v, 0.2)
def test_lmechn1_ties_active_port_kinematics_and_balances_force(self) -> None:
node = AmesimLmechn1("node_1", self.medium, v1=2.0, sum=1.0)
node.port_1.x = 0.2
node.port_1.v = 0.3
node.port_1.f = 4.0
node.port_2.x = 0.2
node.port_2.v = 0.3
node.port_2.f = 6.0
node.port_9.x = 0.2
node.port_9.v = 0.3
node.port_9.f = -10.0
residuals = node.pressure_flow_equation_residuals()
self.assertEqual(node.active_ports, ("port_1", "port_2", "port_9"))
self.assertAlmostEqual(node.total_force, 0.0)
self.assertEqual(len(residuals), 5)
self.assertTrue(all(abs(residual.value) <= 1.0e-12 for residual in residuals))
self.assertEqual(node.component_result_values(), {"tforce": 0.0})
def test_lmechn1_registry_rejects_fractional_integer_options(self) -> None:
with self.assertRaisesRegex(ValueError, "v1 must be an integer"):
COMPONENT_MODEL_REGISTRY["amesim_lmechn1"].create(
"node_1",
self.medium,
{"v1": 2.5},
)
def test_lstp00a_generates_opposing_contact_forces(self) -> None:
contact = AmesimLstp00a(
"contact_1",
self.medium,
gap0=0.0,
kcont=1000.0,
rcont=10.0,
)
contact.port_1.x = 0.0
contact.port_2.x = 0.002
contact.port_1.v = 0.0
contact.port_2.v = 0.1
contact.port_1.f = -3.0
contact.port_2.f = 3.0
self.assertAlmostEqual(contact.gap, -0.002)
self.assertAlmostEqual(contact.penetration, 0.002)
self.assertAlmostEqual(contact.contact_force, 3.0)
self.assertEqual(
contact.component_result_values(),
{"gap": -0.002, "penetration": 0.002, "force": 3.0},
)
residuals = contact.pressure_flow_equation_residuals()
self.assertAlmostEqual(residuals[0].value, 0.0)
self.assertAlmostEqual(residuals[1].value, 0.0)
def test_lstp00a_returns_zero_before_contact(self) -> None:
contact = AmesimLstp00a("contact_1", self.medium, gap0=0.001, kcont=1000.0)
contact.port_1.x = 0.0
contact.port_2.x = 0.0005
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"):
COMPONENT_MODEL_REGISTRY["amesim_mecmas21"].create(
"mass_1",
self.medium,
{"useFriction": 0.5},
)
if __name__ == "__main__":
unittest.main()