完善AMESim组件界面与仿真求解稳定性

This commit is contained in:
ljz committed 2026-08-02 00:57:48 +08:00
1 parent e7177ab03e
commit 410ef535e8
34 files changed
+3340 -251

No files matched your search

@@ -1,6 +1,7 @@
from __future__ import annotations
from collections.abc import Mapping
from math import floor
from app.simulation.core.base import AlgebraicComponent
from app.simulation.core.catalog import ComponentDisplaySpec, PortDisplaySpec
@@ -27,7 +28,7 @@ class AmesimStep0(AlgebraicComponent):
label="STEP0 阶跃信号",
library_id="amesim",
category_id="signals",
symbol="signal",
symbol="amesim_step0",
ports=(PortDisplaySpec("out", "right", order=10),),
order=10,
)
@@ -71,6 +72,15 @@ class AmesimStep0(AlgebraicComponent):
def signal_output_values(self, time: float) -> dict[str, float]:
return {"out": self.output_at(time)}
def signal_event_times(
self,
start_time: float,
stop_time: float,
) -> tuple[float, ...]:
"""Expose the exact STEP0 switch time as an integration split point."""
return (self.time,) if start_time < self.time < stop_time else ()
def component_result_values(self) -> Mapping[str, float]:
return {"y": self.out.signal}
@@ -117,7 +127,7 @@ class AmesimUd00(AlgebraicComponent):
label="UD00 分段线性信号",
library_id="amesim",
category_id="signals",
symbol="signal",
symbol="amesim_ud00",
ports=(PortDisplaySpec("out", "right", order=10),),
order=20,
)
@@ -200,5 +210,58 @@ class AmesimUd00(AlgebraicComponent):
def signal_output_values(self, time: float) -> dict[str, float]:
return {"out": self.output_at(time)}
def signal_event_times(
self,
start_time: float,
stop_time: float,
) -> tuple[float, ...]:
"""Return UD00 start, stage, and repeated cycle boundaries.
The final non-cyclic stage is intentionally not given an end event:
``output_at`` continues that stage's slope after its configured duration.
"""
if stop_time <= start_time:
return ()
active_durations = self.durations[: self.nstages]
stage_offsets = [0.0]
elapsed = 0.0
for duration in active_durations[:-1]:
elapsed += duration
stage_offsets.append(elapsed)
if not self.iscyclic:
return tuple(
sorted(
{
event_time
for offset in stage_offsets
if start_time
< (event_time := self.tstart + offset)
< stop_time
}
)
)
cycle_duration = sum(active_durations)
if cycle_duration <= 0.0:
return ()
events: set[float] = set()
for offset in stage_offsets:
first_boundary = self.tstart + offset
cycle_index = max(
0,
floor((start_time - first_boundary) / cycle_duration) + 1,
)
event_time = first_boundary + cycle_index * cycle_duration
while event_time < stop_time:
if event_time > start_time:
events.add(event_time)
cycle_index += 1
event_time = first_boundary + cycle_index * cycle_duration
return tuple(sorted(events))
def component_result_values(self) -> Mapping[str, float]:
return {"y": self.out.signal}