|
41 | 41 | #include <algorithm> |
42 | 42 | #include <cstring> |
43 | 43 | #include <sstream> |
| 44 | +#include <cmath> |
44 | 45 |
|
45 | 46 | int oms::cvode_rhs(realtype t, N_Vector y, N_Vector ydot, void* user_data) |
46 | 47 | { |
@@ -876,6 +877,15 @@ oms_status_enu_t oms::SystemSC::doStepCVODE(double stopTime) |
876 | 877 | { |
877 | 878 | logDebug("event found!!! " + std::to_string(time)); |
878 | 879 |
|
| 880 | + for (size_t i = 0; i < fmus.size(); ++i) |
| 881 | + { |
| 882 | + if (0 == nStates[i]) |
| 883 | + continue; |
| 884 | + |
| 885 | + status = fmus[i]->getDerivatives(states_der[i]); |
| 886 | + if (oms_status_ok != status) return status; |
| 887 | + } |
| 888 | + |
879 | 889 | // Enter event mode and handle discrete state updates for each FMU |
880 | 890 | for (size_t i = 0; i < fmus.size(); ++i) |
881 | 891 | { |
@@ -913,21 +923,38 @@ oms_status_enu_t oms::SystemSC::doStepCVODE(double stopTime) |
913 | 923 | if (isTopLevelSystem()) |
914 | 924 | getModel().emit(time, true); |
915 | 925 |
|
| 926 | + bool resetSolver = false; |
916 | 927 | for (size_t i = 0; i < fmus.size(); ++i) |
917 | 928 | { |
918 | 929 | if (0 == nStates[i]) |
919 | 930 | continue; |
920 | 931 |
|
921 | 932 | status = fmus[i]->getContinuousStates(states[i]); |
922 | 933 | if (oms_status_ok != status) return status; |
| 934 | + |
| 935 | + // Check whether dervative values have changed due to the event |
| 936 | + std::vector<double> prevDer; |
| 937 | + prevDer.reserve(nStates[i]); |
| 938 | + prevDer.assign(states_der[i], states_der[i] + nStates[i]); |
| 939 | + |
| 940 | + status = fmus[i]->getDerivatives(states_der[i]); |
| 941 | + if (oms_status_ok != status) return status; |
| 942 | + |
| 943 | + for (int k = 0; k < nStates[i]; k++) { |
| 944 | + double diff = states_der[i][k] - prevDer[k]; |
| 945 | + if (fabs(diff) > absoluteTolerance && fabs(diff) > relativeTolerance * fabs(prevDer[k])) |
| 946 | + resetSolver = true; |
| 947 | + } |
923 | 948 | } |
924 | 949 |
|
925 | 950 | for (size_t j=0, k=0; j < fmus.size(); ++j) |
926 | 951 | for (size_t i=0; i < nStates[j]; ++i, ++k) |
927 | 952 | NV_Ith_S(solverData.cvode.y, k) = states[j][i]; |
928 | 953 |
|
929 | | - flag = CVodeReInit(solverData.cvode.mem, time, solverData.cvode.y); |
930 | | - if (flag < 0) return logError("SUNDIALS_ERROR: CVodeReInit() failed with flag = " + std::to_string(flag)); |
| 954 | + if (resetSolver) { |
| 955 | + flag = CVodeReInit(solverData.cvode.mem, time, solverData.cvode.y); |
| 956 | + if (flag < 0) return logError("SUNDIALS_ERROR: CVodeReInit() failed with flag = " + std::to_string(flag)); |
| 957 | + } |
931 | 958 |
|
932 | 959 | return oms_status_ok; |
933 | 960 | } |
|
0 commit comments