|
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 | { |
@@ -860,6 +861,15 @@ oms_status_enu_t oms::SystemSC::doStepCVODE(double stopTime) |
860 | 861 | { |
861 | 862 | logDebug("event found!!! " + std::to_string(time)); |
862 | 863 |
|
| 864 | + for (size_t i = 0; i < fmus.size(); ++i) |
| 865 | + { |
| 866 | + if (0 == nStates[i]) |
| 867 | + continue; |
| 868 | + |
| 869 | + status = fmus[i]->getDerivatives(states_der[i]); |
| 870 | + if (oms_status_ok != status) return status; |
| 871 | + } |
| 872 | + |
863 | 873 | // Enter event mode and handle discrete state updates for each FMU |
864 | 874 | for (size_t i = 0; i < fmus.size(); ++i) |
865 | 875 | { |
@@ -897,21 +907,38 @@ oms_status_enu_t oms::SystemSC::doStepCVODE(double stopTime) |
897 | 907 | if (isTopLevelSystem()) |
898 | 908 | getModel().emit(time, true); |
899 | 909 |
|
| 910 | + bool resetSolver = false; |
900 | 911 | for (size_t i = 0; i < fmus.size(); ++i) |
901 | 912 | { |
902 | 913 | if (0 == nStates[i]) |
903 | 914 | continue; |
904 | 915 |
|
905 | 916 | status = fmus[i]->getContinuousStates(states[i]); |
906 | 917 | if (oms_status_ok != status) return status; |
| 918 | + |
| 919 | + // Check whether dervative values have changed due to the event |
| 920 | + std::vector<double> prevDer; |
| 921 | + prevDer.reserve(nStates[i]); |
| 922 | + prevDer.assign(states_der[i], states_der[i] + nStates[i]); |
| 923 | + |
| 924 | + status = fmus[i]->getDerivatives(states_der[i]); |
| 925 | + if (oms_status_ok != status) return status; |
| 926 | + |
| 927 | + for (int k = 0; k < nStates[i]; k++) { |
| 928 | + double diff = states_der[i][k] - prevDer[k]; |
| 929 | + if (fabs(diff) > absoluteTolerance && fabs(diff) > relativeTolerance * fabs(prevDer[k])) |
| 930 | + resetSolver = true; |
| 931 | + } |
907 | 932 | } |
908 | 933 |
|
909 | 934 | for (size_t j=0, k=0; j < fmus.size(); ++j) |
910 | 935 | for (size_t i=0; i < nStates[j]; ++i, ++k) |
911 | 936 | NV_Ith_S(solverData.cvode.y, k) = states[j][i]; |
912 | 937 |
|
913 | | - flag = CVodeReInit(solverData.cvode.mem, time, solverData.cvode.y); |
914 | | - if (flag < 0) return logError("SUNDIALS_ERROR: CVodeReInit() failed with flag = " + std::to_string(flag)); |
| 938 | + if (resetSolver) { |
| 939 | + flag = CVodeReInit(solverData.cvode.mem, time, solverData.cvode.y); |
| 940 | + if (flag < 0) return logError("SUNDIALS_ERROR: CVodeReInit() failed with flag = " + std::to_string(flag)); |
| 941 | + } |
915 | 942 |
|
916 | 943 | return oms_status_ok; |
917 | 944 | } |
|
0 commit comments