Skip to content

Commit 0dab0bc

Browse files
AnHeuermannclaude
andauthored
Don't call CVode with an interval it cannot integrate (#1621)
doStepCVODE accumulates end_time while the event times come from the FMU, so an event landing on the last ULP before end_time leaves time < end_time true with nothing integrable in between: time = 0.080000000000000001665 clock tick reported by the FMU end_time = 0.080000000000000015543 accumulated by the loop tout = min(tnext, end_time) = end_time gap = 1.39e-17 CVode rejects such an interval with CV_TOO_CLOSE, but only on the first call after a re-init - which is exactly the call following every event - so the whole simulation fails there. Skip the call and take end_time as reached, using CVode's own too-close test. Reproduced by simulation/clockedStepBoundary: a Modelica.Clocked FMU whose tick times are exact (k * period) against a communication step of 0.008, which fails at t = 0.08 without this change. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 77dcf25 commit 0dab0bc

9 files changed

Lines changed: 912 additions & 0 deletions

File tree

src/OMSimulatorLib/SystemSC.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,15 @@ oms_status_enu_t oms::SystemSC::doStepCVODE()
881881
{
882882
const fmi3Float64 tout = std::min(tnext, end_time);
883883

884+
// CVode rejects an interval it cannot tell apart from zero (CV_TOO_CLOSE)
885+
// There is nothing left to integrate in it; assume end_time is reached.
886+
if (tout - time < 2.0 * SUN_UNIT_ROUNDOFF * std::max(std::fabs(time), std::fabs(tout)))
887+
{
888+
logDebug("CVode: skipping degenerate interval " + std::to_string(time) + " -> " + std::to_string(tout));
889+
time = end_time;
890+
break;
891+
}
892+
884893
logDebug("CVode: " + std::to_string(time) + " -> " + std::to_string(tout));
885894
for (size_t j=0, k=0; j < fmus.size(); ++j)
886895
for (size_t i=0; i < nStates[j]; ++i, ++k)

testsuite/tests/resources/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ set(OM_OMS_TESTSUITE_RESOURCES_FMUS
1212
${CMAKE_CURRENT_SOURCE_DIR}/B
1313
${CMAKE_CURRENT_SOURCE_DIR}/BouncingBall
1414
${CMAKE_CURRENT_SOURCE_DIR}/BouncingBall3
15+
${CMAKE_CURRENT_SOURCE_DIR}/ClockedStepBoundary
1516
${CMAKE_CURRENT_SOURCE_DIR}/Dahlquist
1617
${CMAKE_CURRENT_SOURCE_DIR}/Dahlquist3
1718
${CMAKE_CURRENT_SOURCE_DIR}/DualMassOscillator.System1
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Regenerates testsuite/resources/ClockedStepBoundary.
2+
//
3+
// A clocked model: Modelica.Clocked drives it from periodic clocks whose tick
4+
// times are computed exactly (k * period), while a master stepping the FMU
5+
// accumulates its own communication points. The two disagree by an ULP once the
6+
// accumulated end of a communication step lands just past a tick, which is what
7+
// the clockedStepBoundary test exercises.
8+
9+
loadModel(Modelica, {"4.0.0"}); getErrorString();
10+
11+
buildModelFMU(Modelica.Clocked.Examples.CascadeControlledDrive.AbsoluteClocks, version="2.0", fmuType="me", fileNamePrefix="ClockedStepBoundary", platforms={"x86_64-linux-gnu docker run multiarch/crossbuild","x86_64-w64-mingw32 docker run multiarch/crossbuild"}); getErrorString();
12+
13+
system("zip -qd ClockedStepBoundary.fmu sources/* && unzip -o ClockedStepBoundary.fmu -d ClockedStepBoundary/");
Binary file not shown.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
<h1>Modelica.Clocked.Examples.CascadeControlledDrive.AbsoluteClocks</h1>
3+
<p> <i>Drive with clocked cascade controller where all partitions are defined with exact (integer) clock that need to be compatible to each other</i> </p>
4+
<h4> <u> Information </u> </h4><html>
5+
<p>
6+
Cascade control drive with discrete-time controller where two
7+
periodic clock with absolute periods are defined and
8+
are associated to
9+
the corresponding controller partitions.
10+
The super-sampling factor of block "super" is derived by
11+
clock inference.
12+
</p>
13+
</html>
14+
<h4> <u> Revisions </u> </h4>

0 commit comments

Comments
 (0)