190 lines
9.6 KiB
Python
190 lines
9.6 KiB
Python
from __future__ import annotations
|
|
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
from PythonModels.reporting.amesim_results import load_test_mql_amesim_results
|
|
from PythonModels.reporting.test_mql_mechanical_observations import (
|
|
build_test_mql_mechanical_observation_catalog,
|
|
)
|
|
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
TEST_MQL_AME = REPO_ROOT / "AmesimModels" / "test_mql.ame"
|
|
|
|
|
|
class TestMqlMechanicalObservationCatalogTests(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls) -> None:
|
|
cls.amesim_results = load_test_mql_amesim_results(TEST_MQL_AME)
|
|
cls.catalog = build_test_mql_mechanical_observation_catalog(cls.amesim_results)
|
|
|
|
def test_builds_expected_mechanical_observation_counts(self) -> None:
|
|
self.assertEqual(len(self.catalog.pistons), 8)
|
|
self.assertEqual(len(self.catalog.masses), 10)
|
|
self.assertEqual(len(self.catalog.elastic_endstops), 8)
|
|
self.assertEqual(len(self.catalog.zero_force_sources), 16)
|
|
self.assertEqual(len(self.catalog.force_connectors), 2)
|
|
self.assertEqual(len(self.catalog.mechanical_nodes), 2)
|
|
self.assertEqual(self.catalog.binding_count, 46)
|
|
|
|
def test_piston_binding_exposes_amesim_data_paths(self) -> None:
|
|
binding = self.catalog.pistons["pn_brp2_8"]
|
|
|
|
self.assertEqual(binding.volume_path, "vol1@pn_brp2_8")
|
|
self.assertEqual(binding.volume_rate_path, "vvol1@pn_brp2_8")
|
|
self.assertEqual(binding.length_path, "length@pn_brp2_8")
|
|
self.assertEqual(binding.force_port_2_path, "f2@pn_brp2_8")
|
|
self.assertEqual(binding.force_port_3_path, "f3@pn_brp2_8")
|
|
self.assertEqual(binding.displacement_port_2_path, "x5@pn_brp2_8")
|
|
self.assertEqual(binding.velocity_port_2_path, "v5@pn_brp2_8")
|
|
self.assertEqual(binding.displacement_port_3_path, "x4@pn_brp2_8")
|
|
self.assertEqual(binding.velocity_port_3_path, "v4@pn_brp2_8")
|
|
|
|
def test_piston_observation_matches_amesim_final_sample(self) -> None:
|
|
observation = self.catalog.pistons["pn_brp2_8"].observation_at(
|
|
self.amesim_results,
|
|
-1,
|
|
)
|
|
|
|
self.assertAlmostEqual(observation.time, self.amesim_results.times[-1])
|
|
self.assertAlmostEqual(observation.chamber_volume_cm3, 34242.54636512914)
|
|
self.assertAlmostEqual(observation.chamber_volume_rate_l_min, 8.360141002531034e-07)
|
|
self.assertAlmostEqual(observation.chamber_length_mm, 1090.0013536465842)
|
|
self.assertAlmostEqual(observation.displacement_port_2_m, 0.3700013536465843)
|
|
self.assertAlmostEqual(observation.velocity_port_2_m_s, 4.435303434246023e-10)
|
|
self.assertAlmostEqual(observation.displacement_port_3_m, -0.72)
|
|
self.assertAlmostEqual(observation.velocity_port_3_m_s, 0.0)
|
|
|
|
def test_mass_binding_exposes_primary_and_reversed_duplicate_paths(self) -> None:
|
|
binding = self.catalog.masses["mass_friction_endstops_10"]
|
|
|
|
self.assertEqual(binding.displacement_path, "x1@mass_friction_endstops_10")
|
|
self.assertEqual(binding.velocity_path, "v1@mass_friction_endstops_10")
|
|
self.assertEqual(binding.acceleration_path, "acc1@mass_friction_endstops_10")
|
|
self.assertEqual(binding.displacement_duplicate_path, "x1dup@mass_friction_endstops_10")
|
|
self.assertEqual(binding.velocity_duplicate_path, "v1dup@mass_friction_endstops_10")
|
|
self.assertEqual(binding.acceleration_duplicate_path, "acc1dup@mass_friction_endstops_10")
|
|
self.assertEqual(binding.lower_contact_force_path, "Fmin@mass_friction_endstops_10")
|
|
self.assertEqual(binding.upper_contact_force_path, "Fmax@mass_friction_endstops_10")
|
|
self.assertEqual(binding.viscous_friction_force_path, "Fvisc@mass_friction_endstops_10")
|
|
self.assertEqual(binding.dry_friction_force_path, "Ffric@mass_friction_endstops_10")
|
|
self.assertEqual(binding.stick_flag_path, "stick@mass_friction_endstops_10")
|
|
|
|
def test_mass_observation_matches_amesim_final_sample(self) -> None:
|
|
observation = self.catalog.masses["mass_friction_endstops_10"].observation_at(
|
|
self.amesim_results,
|
|
-1,
|
|
)
|
|
|
|
self.assertAlmostEqual(observation.displacement_m, 0.3700013536465843)
|
|
self.assertAlmostEqual(observation.velocity_m_s, 4.435303434246023e-10)
|
|
self.assertAlmostEqual(observation.acceleration_m_s2, -3.5662378650158644e-07)
|
|
self.assertAlmostEqual(observation.lower_contact_force_n, 0.0)
|
|
self.assertAlmostEqual(observation.upper_contact_force_n, 0.0)
|
|
self.assertAlmostEqual(observation.viscous_friction_force_n, 0.0)
|
|
self.assertAlmostEqual(observation.dry_friction_force_n, 0.0)
|
|
self.assertAlmostEqual(observation.stick_flag, 0.0)
|
|
|
|
def test_mass_duplicate_series_are_sign_reversed(self) -> None:
|
|
for binding in self.catalog.masses.values():
|
|
with self.subTest(alias=binding.alias):
|
|
for primary_path, duplicate_path in (
|
|
(binding.displacement_path, binding.displacement_duplicate_path),
|
|
(binding.velocity_path, binding.velocity_duplicate_path),
|
|
(binding.acceleration_path, binding.acceleration_duplicate_path),
|
|
):
|
|
primary = self.amesim_results.series(primary_path)
|
|
duplicate = self.amesim_results.series(duplicate_path)
|
|
self.assertLess(
|
|
max(abs(a + b) for a, b in zip(primary, duplicate)),
|
|
1.0e-12,
|
|
)
|
|
|
|
def test_elastic_endstop_observation_matches_amesim_final_sample(self) -> None:
|
|
observation = self.catalog.elastic_endstops["elasticendstop_8"].observation_at(
|
|
self.amesim_results,
|
|
-1,
|
|
)
|
|
|
|
self.assertAlmostEqual(observation.force_n, 135409.0113969468)
|
|
self.assertAlmostEqual(observation.duplicate_force_n, 135409.0113969468)
|
|
self.assertAlmostEqual(observation.gap_mm, -0.0013536465842123313)
|
|
self.assertAlmostEqual(observation.stiffness_n_m, 100000000000.0)
|
|
|
|
def test_elastic_endstop_duplicate_force_matches_primary_series(self) -> None:
|
|
for binding in self.catalog.elastic_endstops.values():
|
|
force = self.amesim_results.series(binding.force_path)
|
|
duplicate = self.amesim_results.series(binding.duplicate_force_path)
|
|
with self.subTest(alias=binding.alias):
|
|
self.assertLess(
|
|
max(abs(a - b) for a, b in zip(force, duplicate)),
|
|
1.0e-9,
|
|
)
|
|
|
|
def test_zero_force_source_observations_are_zero(self) -> None:
|
|
for binding in self.catalog.zero_force_sources.values():
|
|
force = self.amesim_results.series(binding.force_path)
|
|
with self.subTest(alias=binding.alias):
|
|
self.assertEqual(binding.force_path, f"fzero@{binding.alias}")
|
|
self.assertEqual(min(force), 0.0)
|
|
self.assertEqual(max(force), 0.0)
|
|
self.assertEqual(binding.observation_at(self.amesim_results, -1).force_n, 0.0)
|
|
|
|
def test_force_connector_observations_match_amesim_samples(self) -> None:
|
|
force_1 = self.catalog.force_connectors["forcecon_1"].observation_at(
|
|
self.amesim_results,
|
|
-1,
|
|
)
|
|
force_2 = self.catalog.force_connectors["forcecon_2"].observation_at(
|
|
self.amesim_results,
|
|
-1,
|
|
)
|
|
|
|
self.assertEqual(self.catalog.force_connectors["forcecon_1"].force_path, "force@forcecon_1")
|
|
self.assertEqual(self.catalog.force_connectors["forcecon_2"].force_path, "force@forcecon_2")
|
|
self.assertAlmostEqual(force_1.force_n, 49000.0)
|
|
self.assertAlmostEqual(force_2.force_n, 0.0)
|
|
self.assertAlmostEqual(
|
|
self.amesim_results.series("force@forcecon_1")[0],
|
|
1.0e17,
|
|
)
|
|
self.assertAlmostEqual(
|
|
self.amesim_results.series("force@forcecon_2")[0],
|
|
1.0e12,
|
|
)
|
|
|
|
def test_mechanical_node_bindings_expose_all_ports(self) -> None:
|
|
node = self.catalog.mechanical_nodes["dynamic_mechanical_node_alternative_2"]
|
|
|
|
self.assertEqual(sorted(node.velocity_paths_by_port), list(range(1, 9)))
|
|
self.assertEqual(sorted(node.displacement_paths_by_port), list(range(1, 9)))
|
|
self.assertEqual(node.velocity_paths_by_port[1], "p1__vt@dynamic_mechanical_node_alternative_2")
|
|
self.assertEqual(node.displacement_paths_by_port[8], "p8__xt@dynamic_mechanical_node_alternative_2")
|
|
self.assertEqual(node.total_force_path, "tforce@dynamic_mechanical_node_alternative_2")
|
|
|
|
def test_mechanical_node_observations_match_amesim_final_samples(self) -> None:
|
|
front = self.catalog.mechanical_nodes["dynamic_mechanical_node_alternative_2"].observation_at(
|
|
self.amesim_results,
|
|
-1,
|
|
)
|
|
rear = self.catalog.mechanical_nodes["dynamic_mechanical_node_alternative_3"].observation_at(
|
|
self.amesim_results,
|
|
-1,
|
|
)
|
|
|
|
self.assertEqual(set(front.velocities_m_s), set(range(1, 9)))
|
|
self.assertEqual(set(front.displacements_m), set(range(1, 9)))
|
|
self.assertAlmostEqual(front.velocities_m_s[1], -0.0)
|
|
self.assertAlmostEqual(front.displacements_m[1], -0.3700000000000001)
|
|
self.assertAlmostEqual(front.displacements_m[8], -0.3700000000000001)
|
|
self.assertAlmostEqual(front.total_force_n, 1083272.2763054767)
|
|
self.assertAlmostEqual(rear.velocities_m_s[1], 0.0)
|
|
self.assertAlmostEqual(rear.displacements_m[1], -0.72)
|
|
self.assertAlmostEqual(rear.displacements_m[8], -0.72)
|
|
self.assertAlmostEqual(rear.total_force_n, 1083272.2762592242)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|