Skip to content

Commit 25e1a2b

Browse files
Output all CVODE steps
refs #1330
1 parent c2e1bfd commit 25e1a2b

2 files changed

Lines changed: 54 additions & 28 deletions

File tree

src/OMSimulatorLib/SystemSC.cpp

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -534,23 +534,23 @@ oms_status_enu_t oms::SystemSC::doStep()
534534
switch(solverMethod)
535535
{
536536
case oms_solver_sc_explicit_euler:
537-
return doStepEuler();
537+
return doStepEuler(time + maximumStepSize);
538538

539539
case oms_solver_sc_cvode:
540-
return doStepCVODE();
540+
return doStepCVODE(time + maximumStepSize);
541541

542542
default:
543543
return logError_InternalError;
544544
}
545545
}
546546

547-
oms_status_enu_t oms::SystemSC::doStepEuler()
547+
oms_status_enu_t oms::SystemSC::doStepEuler(double stopTime)
548548
{
549549
fmi2Status fmistatus;
550550
oms_status_enu_t status;
551551

552552
// Step 1: Initialize state variables and time
553-
const fmi2Real end_time = std::min(time + maximumStepSize, getModel().getStopTime());
553+
const fmi2Real end_time = std::min(time + maximumStepSize, stopTime);
554554
const fmi2Real event_time_tolerance = 1e-4;
555555

556556
logDebug("doStepEuler: " + std::to_string(time) + " -> " + std::to_string(end_time));
@@ -766,13 +766,14 @@ oms_status_enu_t oms::SystemSC::doStepEuler()
766766
return oms_status_ok;
767767
}
768768

769-
oms_status_enu_t oms::SystemSC::doStepCVODE()
769+
oms_status_enu_t oms::SystemSC::doStepCVODE(double stopTime)
770770
{
771771
fmi2Status fmistatus;
772772
oms_status_enu_t status;
773-
int flag;
773+
int flag = 0;
774+
bool tnext_is_event = false;
774775

775-
const fmi2Real end_time = std::min(time + maximumStepSize, getModel().getStopTime());
776+
const fmi2Real end_time = stopTime;
776777

777778
// find next time event
778779
fmi2Real tnext = end_time+1.0;
@@ -788,16 +789,35 @@ oms_status_enu_t oms::SystemSC::doStepCVODE()
788789
time = end_time;
789790
}
790791
}
792+
793+
tnext_is_event = tnext <= end_time;
794+
tnext = std::min(tnext, end_time);
795+
791796
logDebug("tnext: " + std::to_string(tnext));
792797

793-
while (time < end_time)
794-
{
798+
//while (time < end_time)
799+
//{
795800
logDebug("CVode: " + std::to_string(time) + " -> " + std::to_string(end_time));
796801
for (size_t j=0, k=0; j < fmus.size(); ++j)
797802
for (size_t i=0; i < nStates[j]; ++i, ++k)
798803
NV_Ith_S(solverData.cvode.y, k) = states[j][i];
799804

800-
flag = CVode(solverData.cvode.mem, std::min(tnext, end_time), solverData.cvode.y, &time, CV_NORMAL);
805+
double cvode_time = tnext;
806+
CVodeGetCurrentTime(solverData.cvode.mem, &cvode_time);
807+
if (cvode_time < tnext) {
808+
flag = CVode(solverData.cvode.mem, tnext, solverData.cvode.y, &cvode_time, CV_ONE_STEP);
809+
if (flag < 0)
810+
return logError("SUNDIALS_ERROR: CVode() failed with flag = " + std::to_string(flag));
811+
}
812+
813+
if (cvode_time > tnext) {
814+
// interpolate result to tnext (this shouldn't take any further steps)
815+
flag = CVode(solverData.cvode.mem, tnext, solverData.cvode.y, &cvode_time, CV_NORMAL);
816+
if (flag < 0)
817+
return logError("SUNDIALS_ERROR: CVode() failed with flag = " + std::to_string(flag));
818+
}
819+
820+
time = cvode_time;
801821

802822
for (size_t i = 0, j=0; i < fmus.size(); ++i)
803823
{
@@ -809,7 +829,7 @@ oms_status_enu_t oms::SystemSC::doStepCVODE()
809829
if (oms_status_ok != status) return status;
810830
}
811831

812-
if (flag == CV_ROOT_RETURN || time == tnext)
832+
if (flag == CV_ROOT_RETURN || tnext_is_event && time == tnext)
813833
{
814834
logDebug("event found!!! " + std::to_string(time));
815835

@@ -839,15 +859,6 @@ oms_status_enu_t oms::SystemSC::doStepCVODE()
839859
if (fmi2OK != fmistatus) logError_FMUCall("fmi2_enterContinuousTimeMode", fmus[i]);
840860
}
841861

842-
for (size_t i = 0; i < fmus.size(); ++i)
843-
{
844-
if (0 == nStates[i])
845-
continue;
846-
847-
status = fmus[i]->getContinuousStates(states[i]);
848-
if (oms_status_ok != status) return status;
849-
}
850-
851862
// find next time event
852863
tnext = end_time+1.0;
853864
for (size_t i = 0; i < fmus.size(); ++i)
@@ -862,6 +873,10 @@ oms_status_enu_t oms::SystemSC::doStepCVODE()
862873
time = end_time;
863874
}
864875
}
876+
877+
tnext_is_event = tnext <= end_time;
878+
tnext = std::min(tnext, end_time);
879+
865880
logDebug("tnext: " + std::to_string(tnext));
866881

867882
// emit the right limit of the event
@@ -885,10 +900,10 @@ oms_status_enu_t oms::SystemSC::doStepCVODE()
885900
flag = CVodeReInit(solverData.cvode.mem, time, solverData.cvode.y);
886901
if (flag < 0) return logError("SUNDIALS_ERROR: CVodeReInit() failed with flag = " + std::to_string(flag));
887902

888-
continue;
903+
return oms_status_ok;
889904
}
890905

891-
if (flag == CV_SUCCESS)
906+
if (flag >= 0) // Some kind of success
892907
{
893908
logDebug("CVode completed successfully at t = " + std::to_string(time));
894909

@@ -914,7 +929,7 @@ oms_status_enu_t oms::SystemSC::doStepCVODE()
914929
}
915930
else
916931
return logError("CVode failed with flag = " + std::to_string(flag));
917-
}
932+
//}
918933

919934
return oms_status_ok;
920935

@@ -930,14 +945,25 @@ oms_status_enu_t oms::SystemSC::stepUntil(double stopTime)
930945

931946
// main simulation loop
932947
oms_status_enu_t status = oms_status_ok;
933-
while (time < std::min(stopTime, getModel().getStopTime()) && oms_status_ok == status)
948+
double endTime = std::min(stopTime, getModel().getStopTime());
949+
double lastTime = time;
950+
while (time < endTime && oms_status_ok == status)
934951
{
935-
status = doStep();
952+
if (solverMethod == oms_solver_sc_explicit_euler)
953+
status = doStepEuler(endTime);
954+
else if (solverMethod == oms_solver_sc_cvode)
955+
status = doStepCVODE(endTime);
956+
else
957+
return logError_InternalError;
958+
936959
if (status != oms_status_ok)
937960
logWarning("Bad return code at time " + std::to_string(time));
938961

939-
if (isTopLevelSystem() && Flags::ProgressBar())
962+
if (isTopLevelSystem() && Flags::ProgressBar() && time > lastTime + maximumStepSize)
963+
{
940964
Log::ProgressBar(startTime, stopTime, time);
965+
lastTime = time;
966+
}
941967
}
942968

943969
if (isTopLevelSystem() && Flags::ProgressBar())

src/OMSimulatorLib/SystemSC.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ namespace oms
7171
oms_status_enu_t setSolver(oms_solver_enu_t solver) {if (solver > oms_solver_sc_min && solver < oms_solver_sc_max) {solverMethod=solver; return oms_status_ok;} return oms_status_error;}
7272

7373
private:
74-
oms_status_enu_t doStepEuler();
75-
oms_status_enu_t doStepCVODE();
74+
oms_status_enu_t doStepEuler(double stopTime);
75+
oms_status_enu_t doStepCVODE(double stopTime);
7676

7777
protected:
7878
SystemSC(const ComRef& cref, Model* parentModel, System* parentSystem);

0 commit comments

Comments
 (0)