初版:实现 AMESim 机械因果化与事件求解

初步支持 MECMAS21 刚性质量状态归并、端止事件、恢复系数,以及 LSTP 接触和压力流量显式因果化。

已知问题:显式传播仍会重复扫描全网方程,长时刚性仿真性能待优化;自适应积分器遇到越出物理域的试探状态时,尚未实现恢复并缩步重试。
This commit is contained in:
ljz committed 2026-08-03 15:45:48 +08:00
1 parent de265cdde6
commit 971e8f2336
9 files changed
+2808 -169

No files matched your search

+18 -11
View File
@@ -8,6 +8,7 @@ from typing import Literal
from app.simulation.core.base import DynamicComponent
from app.simulation.core.metadata import ResultVariableMetadata
from app.simulation.solvers.algebraic import PressureFlowSolver
from app.simulation.solvers.mechanical import MechanicalStateReducer
from app.simulation.solvers.pneumatic_volume import PneumaticVolumeResolver
from app.simulation.solvers.solver import ODESolution, SolveIVPConfig, integrate_ode
from app.simulation.solvers.signal import SignalResolver
@@ -233,6 +234,10 @@ class GenericFluidSystem:
raise SimulationPreparationError(issues)
self.network = network
self.dynamic_components = network.dynamic_components()
self.mechanical_state_reducer = MechanicalStateReducer(
network,
self.dynamic_components,
)
self.pressure_flow_solver = PressureFlowSolver(network)
self.pneumatic_volume_resolver = PneumaticVolumeResolver(network)
self.signal_resolver = SignalResolver(network)
@@ -245,10 +250,10 @@ class GenericFluidSystem:
self.pneumatic_volume_propagation_count = 0
def initial_state_vector(self) -> list[float]:
return self.network.initial_state_vector()
return self.mechanical_state_reducer.initial_state_vector()
def apply_state_vector(self, values: list[float]) -> None:
self.network.apply_state_vector(values)
self.mechanical_state_reducer.apply_state_vector(values)
def _close_current_state(self, time: float) -> dict[str, dict[str, float]]:
signal = self.signal_resolver.solve(time)
@@ -263,6 +268,7 @@ class GenericFluidSystem:
component.refresh_thermodynamic_ports()
algebraic = self.pressure_flow_solver.solve()
stream, connected_h = self.stream_resolver.solve()
self.mechanical_state_reducer.update_constraint_accelerations()
self.algebraic_solve_count += 1 + int(bool(pneumatic_volume.propagated))
self.max_algebraic_residual = max(
self.max_algebraic_residual,
@@ -278,21 +284,16 @@ class GenericFluidSystem:
)
return connected_h
def consistent_initial_state_vector(self) -> list[float]:
def consistent_initial_state_vector(self, time: float = 0.0) -> list[float]:
state = self.initial_state_vector()
self.apply_state_vector(state)
self._close_current_state(0.0)
self._close_current_state(time)
return state
def rhs(self, _time: float, state_vector: list[float]) -> list[float]:
self.apply_state_vector(state_vector)
connected_h = self._close_current_state(_time)
derivatives: list[float] = []
for component in self.dynamic_components:
derivatives.extend(
component.state_derivative_from_ports(connected_h[component.name])
)
return derivatives
return self.mechanical_state_reducer.state_derivatives(connected_h)
def _append_current_state(self, series: dict[str, list[float]]) -> None:
for component in self.network.components.values():
@@ -340,7 +341,7 @@ class GenericFluidSystem:
config.t_start,
config.t_stop,
)
initial_state = self.consistent_initial_state_vector()
initial_state = self.consistent_initial_state_vector(config.t_start)
report_progress(0.0, "integrating", force=True)
duration = config.t_stop - config.t_start
furthest_solver_time = config.t_start
@@ -370,6 +371,11 @@ class GenericFluidSystem:
report_solver_time if cancel_check is not None else None
),
breakpoints=signal_event_times,
state_transition_handler=(
self.mechanical_state_reducer.state_transition
if self.mechanical_state_reducer.has_state_events
else None
),
)
if isinstance(solution, ODESolution):
run_status: SimulationRunStatus = solution.status
@@ -387,6 +393,7 @@ class GenericFluidSystem:
times = [float(value) for value in solution.t]
series: dict[str, list[float]] = {"time": []}
postprocessing_error: Exception | None = None
self.mechanical_state_reducer.reset_constraint_modes()
for time_index in range(len(times)):
if (
run_status == "completed"