|
24 | 24 | import numpy as np |
25 | 25 | import scipy.optimize as spopt |
26 | 26 |
|
27 | | -from pyfmi.fmi1 import FMUModelME1, FMUModelCS1, FMI_ERROR, FMI_DISCARD, FMI1_LAST_SUCCESSFUL_TIME # TODO |
| 27 | +from pyfmi.fmi1 import FMUModelME1, FMUModelCS1, FMI_OK, FMI_ERROR, FMI_DISCARD, FMI1_LAST_SUCCESSFUL_TIME # TODO |
28 | 28 | from pyfmi.fmi2 import FMUModelME2, FMUModelCS2, FMI2_INPUT, FMI2_LAST_SUCCESSFUL_TIME |
29 | 29 | from pyfmi.fmi3 import FMUModelME3, FMUModelCS3 |
30 | 30 | from pyfmi.fmi_coupled import CoupledFMUModelME2 |
@@ -1015,6 +1015,26 @@ def _set_solver_options(self): |
1015 | 1015 | """ |
1016 | 1016 | pass #No solver options |
1017 | 1017 |
|
| 1018 | + def _check_do_step_status_and_terminated(self, status) -> tuple[bool, float]: |
| 1019 | + """Return (true, <termination_time>) if terminated, (False, 0) else. |
| 1020 | + Raise exception in case of error returns.""" |
| 1021 | + if status != FMI_OK: |
| 1022 | + if status == FMI_DISCARD and isinstance(self.model, (FMUModelCS1, FMUModelCS2)): |
| 1023 | + try: |
| 1024 | + if isinstance(self.model, FMUModelCS1): |
| 1025 | + last_time = self.model.get_real_status(FMI1_LAST_SUCCESSFUL_TIME) |
| 1026 | + else: |
| 1027 | + last_time = self.model.get_real_status(FMI2_LAST_SUCCESSFUL_TIME) |
| 1028 | + return True, last_time |
| 1029 | + except FMUException: |
| 1030 | + pass |
| 1031 | + else: # status = error || fatal || (discard && FMI3) |
| 1032 | + raise FMUException("The simulation failed. See the log for more information. Return flag %d."%status) |
| 1033 | + elif isinstance(self.model, FMUModelCS3): |
| 1034 | + if self.model.do_step_terminated: |
| 1035 | + return True, self.model.time |
| 1036 | + return False, 0 |
| 1037 | + |
1018 | 1038 | def solve(self): |
1019 | 1039 | """ |
1020 | 1040 | Runs the simulation. |
@@ -1045,37 +1065,16 @@ def solve(self): |
1045 | 1065 | status = self.model.do_step(t,h) |
1046 | 1066 | self.status = status |
1047 | 1067 |
|
1048 | | - if isinstance(self.model, FMUModelCS3): |
1049 | | - if self.model.do_step_terminated: |
1050 | | - final_time = self.model.time |
| 1068 | + terminated, terminated_time = self._check_do_step_status_and_terminated(status) |
| 1069 | + if terminated: |
| 1070 | + if terminated_time > t: # only store additional point if time advanced |
| 1071 | + self.model.time = terminated_time |
| 1072 | + final_time = terminated_time |
1051 | 1073 |
|
1052 | 1074 | start_time_point = timer() |
1053 | 1075 | result_handler.integration_point() |
1054 | 1076 | self.timings["storing_result"] += timer() - start_time_point |
1055 | | - break |
1056 | | - |
1057 | | - if status != 0: |
1058 | | - |
1059 | | - if status == FMI_ERROR: |
1060 | | - raise FMUException("The simulation failed. See the log for more information. Return flag %d."%status) |
1061 | | - |
1062 | | - elif status == FMI_DISCARD and isinstance(self.model, (FMUModelCS1, FMUModelCS2)): |
1063 | | - |
1064 | | - try: |
1065 | | - if isinstance(self.model, FMUModelCS1): |
1066 | | - last_time = self.model.get_real_status(FMI1_LAST_SUCCESSFUL_TIME) |
1067 | | - else: |
1068 | | - last_time = self.model.get_real_status(FMI2_LAST_SUCCESSFUL_TIME) |
1069 | | - if last_time > t: #Solver succeeded in taken a step a little further than the last time |
1070 | | - self.model.time = last_time |
1071 | | - final_time = last_time |
1072 | | - |
1073 | | - start_time_point = timer() |
1074 | | - result_handler.integration_point() |
1075 | | - self.timings["storing_result"] += timer() - start_time_point |
1076 | | - except FMUException: |
1077 | | - pass |
1078 | | - break |
| 1077 | + break # stop integration loop |
1079 | 1078 |
|
1080 | 1079 | final_time = t+h |
1081 | 1080 |
|
|
0 commit comments