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