merge/model-development-into-main #2
No files matched your search
@@ -3841,6 +3841,7 @@ class TestMqlSimulationResult:
|
||||
class TestMqlFullStateSnapshot:
|
||||
pneumatic: object
|
||||
mechanical: object
|
||||
mechanical_node_total_force_by_alias: dict[str, float]
|
||||
|
||||
@property
|
||||
def state_count(self) -> int:
|
||||
@@ -3906,9 +3907,17 @@ class TestMqlFullStateClosure:
|
||||
def snapshot(self, state_vector: list[float] | None = None) -> TestMqlFullStateSnapshot:
|
||||
values = self.initial_state_vector() if state_vector is None else list(state_vector)
|
||||
pneumatic_state, mechanical_state = self._split_state(values)
|
||||
pneumatic_snapshot = self.pneumatic_closure.snapshot(pneumatic_state)
|
||||
mechanical_snapshot = self.mechanical_closure.snapshot(mechanical_state)
|
||||
return TestMqlFullStateSnapshot(
|
||||
pneumatic=self.pneumatic_closure.snapshot(pneumatic_state),
|
||||
mechanical=self.mechanical_closure.snapshot(mechanical_state),
|
||||
pneumatic=pneumatic_snapshot,
|
||||
mechanical=mechanical_snapshot,
|
||||
mechanical_node_total_force_by_alias=(
|
||||
self._mechanical_node_total_force_by_alias(
|
||||
pneumatic_snapshot,
|
||||
mechanical_snapshot,
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
def rhs(self, state_vector: list[float]) -> list[float]:
|
||||
@@ -3931,6 +3940,31 @@ class TestMqlFullStateClosure:
|
||||
pneumatic_snapshot: object,
|
||||
mechanical_snapshot: object,
|
||||
) -> dict[str, float]:
|
||||
force_by_mass_alias = self._piston_force_by_mass_alias(pneumatic_snapshot)
|
||||
elastic_force_by_mass_alias = self._elastic_endstop_force_by_mass_alias(
|
||||
mechanical_snapshot
|
||||
)
|
||||
for mass_alias, contact_force in elastic_force_by_mass_alias.items():
|
||||
force_by_mass_alias[mass_alias] = (
|
||||
force_by_mass_alias.get(mass_alias, 0.0) - contact_force
|
||||
)
|
||||
return force_by_mass_alias
|
||||
|
||||
def _mechanical_node_total_force_by_alias(
|
||||
self,
|
||||
pneumatic_snapshot: object,
|
||||
mechanical_snapshot: object,
|
||||
) -> dict[str, float]:
|
||||
return {
|
||||
"dynamic_mechanical_node_alternative_2": sum(
|
||||
self._elastic_endstop_force_by_mass_alias(mechanical_snapshot).values()
|
||||
),
|
||||
"dynamic_mechanical_node_alternative_3": sum(
|
||||
self._piston_force_by_mass_alias(pneumatic_snapshot).values()
|
||||
),
|
||||
}
|
||||
|
||||
def _piston_force_by_mass_alias(self, pneumatic_snapshot: object) -> dict[str, float]:
|
||||
from PythonModels.systems.test_mql_pneumatic import pressure_to_amesim_gauge_pa
|
||||
|
||||
force_by_mass_alias: dict[str, float] = {}
|
||||
@@ -3940,8 +3974,14 @@ class TestMqlFullStateClosure:
|
||||
force_by_mass_alias[mass_alias] = (
|
||||
pressure_to_amesim_gauge_pa(chamber.p) * piston.annulus_area_m2
|
||||
)
|
||||
return force_by_mass_alias
|
||||
|
||||
def _elastic_endstop_force_by_mass_alias(
|
||||
self,
|
||||
mechanical_snapshot: object,
|
||||
) -> dict[str, float]:
|
||||
state_by_alias = {state.alias: state for state in mechanical_snapshot.states}
|
||||
force_by_mass_alias: dict[str, float] = {}
|
||||
for mass_alias, support_mass_alias, endstop_alias in _ELASTIC_ENDSTOP_FORCE_BINDINGS:
|
||||
mass_state = state_by_alias[mass_alias]
|
||||
support_state = state_by_alias[support_mass_alias]
|
||||
@@ -3952,9 +3992,9 @@ class TestMqlFullStateClosure:
|
||||
penetration_velocity_m_s = (
|
||||
mass_state.velocity_m_s - support_state.velocity_m_s
|
||||
)
|
||||
force_by_mass_alias[mass_alias] = (
|
||||
force_by_mass_alias.get(mass_alias, 0.0)
|
||||
- endstop.contact_force(gap_mm, penetration_velocity_m_s)
|
||||
force_by_mass_alias[mass_alias] = endstop.contact_force(
|
||||
gap_mm,
|
||||
penetration_velocity_m_s,
|
||||
)
|
||||
return force_by_mass_alias
|
||||
|
||||
|
||||
@@ -552,6 +552,18 @@ class TestMqlPn3P4NodeChamberSegmentTests(unittest.TestCase):
|
||||
snapshot.mechanical.states[0].alias,
|
||||
"mass_friction_endstops_10",
|
||||
)
|
||||
self.assertAlmostEqual(
|
||||
snapshot.mechanical_node_total_force_by_alias[
|
||||
"dynamic_mechanical_node_alternative_2"
|
||||
],
|
||||
0.0,
|
||||
)
|
||||
self.assertAlmostEqual(
|
||||
snapshot.mechanical_node_total_force_by_alias[
|
||||
"dynamic_mechanical_node_alternative_3"
|
||||
],
|
||||
-326.7174678324367,
|
||||
)
|
||||
self.assertAlmostEqual(rhs[112], -0.8167936695810917)
|
||||
|
||||
def test_full_state_closure_applies_elastic_endstop_force_to_small_masses(self) -> None:
|
||||
@@ -563,6 +575,7 @@ class TestMqlPn3P4NodeChamberSegmentTests(unittest.TestCase):
|
||||
state = closure.initial_state_vector()
|
||||
state[113] = 1.0e-3
|
||||
|
||||
snapshot = closure.snapshot(state)
|
||||
rhs = closure.rhs(state)
|
||||
initial_rhs = closure.rhs(closure.initial_state_vector())
|
||||
endstop = closure.mechanical_closure.assembly.elastic_endstops[
|
||||
@@ -577,6 +590,12 @@ class TestMqlPn3P4NodeChamberSegmentTests(unittest.TestCase):
|
||||
rhs[112],
|
||||
initial_rhs[112] - expected_contact_force / mass,
|
||||
)
|
||||
self.assertAlmostEqual(
|
||||
snapshot.mechanical_node_total_force_by_alias[
|
||||
"dynamic_mechanical_node_alternative_2"
|
||||
],
|
||||
expected_contact_force,
|
||||
)
|
||||
|
||||
def test_simulates_full_132_state_closure(self) -> None:
|
||||
solution = self.system.simulate_full_state_from_spec(
|
||||
|
||||
Reference in new issue
Block a user