整合求解器活动监控与步长回归证据
同步远端 PNL0003 诊断和大采样网格能力,语义合并活动感知的 60 秒真停滞判定与旧后端 15 分钟兼容兜底。 纳管热路径优化、15 单元运行证据、浏览器与 API 报告,并补充北京时间更新日志和遗留问题。
This commit is contained in:
1 parent
c19cf77aee
commit
e18399c022
46 files changed
+181589
-170
No files matched your search
@@ -31,6 +31,7 @@ from app.simulation.solvers.solver import (
|
||||
IntegrationCancelled,
|
||||
ODESolution,
|
||||
SolveIVPConfig,
|
||||
SolverActivityTracker,
|
||||
integrate_ode,
|
||||
)
|
||||
from app.simulation.solvers.signal import SignalResolver
|
||||
@@ -453,6 +454,7 @@ class GenericFluidSystem:
|
||||
self.pneumatic_volume_propagation_count = 0
|
||||
self._jacobian_sparsity = None
|
||||
self._ode_tangent_provider: ThreePistonTangentProvider | None = None
|
||||
self._activity_tracker: SolverActivityTracker | None = None
|
||||
|
||||
def _request_causal_residual_audit(self) -> None:
|
||||
"""Make topology or mode boundaries verify the next causal closure."""
|
||||
@@ -957,6 +959,8 @@ class GenericFluidSystem:
|
||||
*,
|
||||
record_rhs_outcome: bool = False,
|
||||
) -> dict[str, dict[str, float]]:
|
||||
if self._activity_tracker is not None:
|
||||
self._activity_tracker.record_thermofluid_closure(time)
|
||||
transaction = self._thermofluid_transaction_plan.capture()
|
||||
last_algebraic_diagnostics = self._last_algebraic_diagnostics
|
||||
last_algebraic_scope = self._last_algebraic_scope
|
||||
@@ -1156,6 +1160,8 @@ class GenericFluidSystem:
|
||||
self,
|
||||
connected_h: dict[str, dict[str, float]],
|
||||
) -> list[float]:
|
||||
if self._activity_tracker is not None:
|
||||
self._activity_tracker.record_phase("state_derivatives")
|
||||
return self.pneumatic_storage_reducer.coupled_derivatives(
|
||||
self.mechanical_state_reducer.state_derivatives(connected_h)
|
||||
)
|
||||
@@ -1194,7 +1200,32 @@ class GenericFluidSystem:
|
||||
sample_step: float,
|
||||
progress_callback: SimulationProgressCallback | None = None,
|
||||
cancel_check: SimulationCancellationCheck | None = None,
|
||||
activity_tracker: SolverActivityTracker | None = None,
|
||||
) -> GenericSimulationResult:
|
||||
previous_activity_tracker = self._activity_tracker
|
||||
self._activity_tracker = activity_tracker
|
||||
try:
|
||||
return self._simulate(
|
||||
config,
|
||||
sample_step=sample_step,
|
||||
progress_callback=progress_callback,
|
||||
cancel_check=cancel_check,
|
||||
activity_tracker=activity_tracker,
|
||||
)
|
||||
finally:
|
||||
self._activity_tracker = previous_activity_tracker
|
||||
|
||||
def _simulate(
|
||||
self,
|
||||
config: SolveIVPConfig,
|
||||
*,
|
||||
sample_step: float,
|
||||
progress_callback: SimulationProgressCallback | None = None,
|
||||
cancel_check: SimulationCancellationCheck | None = None,
|
||||
activity_tracker: SolverActivityTracker | None = None,
|
||||
) -> GenericSimulationResult:
|
||||
if activity_tracker is not None:
|
||||
activity_tracker.record_phase("initializing", config.t_start)
|
||||
last_reported_progress = -1.0
|
||||
last_reported_phase = ""
|
||||
|
||||
@@ -1223,12 +1254,21 @@ class GenericFluidSystem:
|
||||
report_progress(0.0, "initializing", force=True)
|
||||
with performance_span("simulation.sample_initialization"):
|
||||
integration_config = config
|
||||
mechanical_tolerance_plan = None
|
||||
if isinstance(config.atol, (int, float)):
|
||||
mechanical_tolerance_plan = (
|
||||
self.mechanical_state_reducer.absolute_tolerance_plan(
|
||||
float(config.atol),
|
||||
mode=(
|
||||
None
|
||||
if config.method == "BDF"
|
||||
else "legacy"
|
||||
),
|
||||
)
|
||||
)
|
||||
integration_config = replace(
|
||||
config,
|
||||
atol=self.mechanical_state_reducer.absolute_tolerances(
|
||||
float(config.atol)
|
||||
),
|
||||
atol=list(mechanical_tolerance_plan.values),
|
||||
)
|
||||
t_eval = simulation_sample_times(config, sample_step)
|
||||
signal_event_times = self.signal_resolver.event_times(
|
||||
@@ -1321,6 +1361,8 @@ class GenericFluidSystem:
|
||||
def evaluate_jacobian_rhs(time, state):
|
||||
if cancel_check is not None and cancel_check():
|
||||
raise IntegrationCancelled
|
||||
if activity_tracker is not None:
|
||||
activity_tracker.record_rhs(float(time))
|
||||
return monitored_rhs(
|
||||
time,
|
||||
[float(value) for value in state],
|
||||
@@ -1372,6 +1414,7 @@ class GenericFluidSystem:
|
||||
jac_sparsity=jac_sparsity,
|
||||
jac=jacobian,
|
||||
recoverable_trial_retries=True,
|
||||
activity_tracker=activity_tracker,
|
||||
)
|
||||
finally:
|
||||
self._ode_tangent_provider = None
|
||||
@@ -1388,6 +1431,11 @@ class GenericFluidSystem:
|
||||
else max(0.0, last_reported_progress)
|
||||
)
|
||||
report_progress(postprocess_progress, "postprocessing", force=True)
|
||||
if activity_tracker is not None:
|
||||
activity_tracker.record_phase(
|
||||
"postprocessing",
|
||||
furthest_solver_time,
|
||||
)
|
||||
times = [float(value) for value in solution.t]
|
||||
if isinstance(solution, ODESolution):
|
||||
solver_segment_diagnostics = [
|
||||
@@ -1601,6 +1649,11 @@ class GenericFluidSystem:
|
||||
self._close_current_state(times[time_index])
|
||||
self._append_current_state(series)
|
||||
series["time"].append(times[time_index])
|
||||
if activity_tracker is not None:
|
||||
activity_tracker.record_phase(
|
||||
"postprocessing",
|
||||
times[time_index],
|
||||
)
|
||||
except Exception as exc:
|
||||
run_status = "failed"
|
||||
result_message = str(exc)
|
||||
@@ -1621,6 +1674,14 @@ class GenericFluidSystem:
|
||||
diagnostics = {
|
||||
"integration": {
|
||||
"method": integration_config.method,
|
||||
"mechanicalAbsoluteTolerance": (
|
||||
mechanical_tolerance_plan.as_dict()
|
||||
if mechanical_tolerance_plan is not None
|
||||
else {
|
||||
"mode": "callerVector",
|
||||
"stateCount": len(initial_state),
|
||||
}
|
||||
),
|
||||
"jacobianSparsity": jacobian_diagnostics,
|
||||
"jacobian": runtime_jacobian_diagnostics,
|
||||
"segmentCount": len(solver_segment_diagnostics),
|
||||
@@ -1730,6 +1791,19 @@ class GenericFluidSystem:
|
||||
for variable in self.network.result_variable_metadata()
|
||||
if variable.key in series
|
||||
)
|
||||
final_simulated_time = (
|
||||
float(series["time"][-1])
|
||||
if series["time"]
|
||||
else float(config.t_start)
|
||||
)
|
||||
if activity_tracker is not None:
|
||||
activity_tracker.record_phase(
|
||||
"complete" if run_status == "completed" else run_status,
|
||||
final_simulated_time,
|
||||
)
|
||||
diagnostics["activity"] = (
|
||||
activity_tracker.snapshot().as_dict()
|
||||
)
|
||||
report_progress(
|
||||
1.0 if run_status == "completed" else max(0.0, last_reported_progress),
|
||||
"complete" if run_status == "completed" else run_status,
|
||||
@@ -1740,9 +1814,7 @@ class GenericFluidSystem:
|
||||
status=run_status,
|
||||
message=result_message,
|
||||
simulated_until=(
|
||||
float(series["time"][-1])
|
||||
if series["time"]
|
||||
else float(config.t_start)
|
||||
final_simulated_time
|
||||
),
|
||||
requested_stop_time=float(config.t_stop),
|
||||
variables=variables,
|
||||
|
||||
Reference in new issue
Block a user