myokit 1.36.0__py3-none-any.whl → 1.37.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. myokit/__init__.py +6 -19
  2. myokit/_datablock.py +45 -55
  3. myokit/_datalog.py +2 -2
  4. myokit/_err.py +26 -3
  5. myokit/_expressions.py +241 -127
  6. myokit/_model_api.py +19 -13
  7. myokit/_myokit_version.py +1 -1
  8. myokit/_sim/cvodessim.c +221 -149
  9. myokit/_sim/jacobian.py +3 -3
  10. myokit/_sim/mcl.h +54 -0
  11. myokit/_sim/openclsim.py +5 -5
  12. myokit/_sim/rhs.py +1 -1
  13. myokit/formats/__init__.py +4 -9
  14. myokit/formats/ansic/_ewriter.py +4 -20
  15. myokit/formats/heka/_patchmaster.py +16 -10
  16. myokit/formats/opencl/_ewriter.py +3 -42
  17. myokit/formats/opencl/template/minilog.py +1 -1
  18. myokit/formats/sympy/_ereader.py +2 -1
  19. myokit/formats/wcp/_wcp.py +3 -3
  20. myokit/gui/datalog_viewer.py +12 -7
  21. myokit/lib/hh.py +3 -0
  22. myokit/lib/markov.py +2 -2
  23. myokit/lib/plots.py +4 -4
  24. myokit/tests/data/formats/wcp-file-empty.wcp +0 -0
  25. myokit/tests/test_datablock.py +10 -10
  26. myokit/tests/test_datalog.py +4 -1
  27. myokit/tests/test_expressions.py +532 -251
  28. myokit/tests/test_formats_ansic.py +6 -18
  29. myokit/tests/test_formats_cpp.py +0 -5
  30. myokit/tests/test_formats_cuda.py +7 -15
  31. myokit/tests/test_formats_easyml.py +4 -9
  32. myokit/tests/test_formats_latex.py +10 -11
  33. myokit/tests/test_formats_matlab.py +0 -8
  34. myokit/tests/test_formats_opencl.py +0 -29
  35. myokit/tests/test_formats_python.py +2 -19
  36. myokit/tests/test_formats_stan.py +0 -13
  37. myokit/tests/test_formats_sympy.py +3 -3
  38. myokit/tests/test_formats_wcp.py +15 -0
  39. myokit/tests/test_lib_hh.py +36 -0
  40. myokit/tests/test_model.py +20 -20
  41. myokit/tests/test_parsing.py +19 -0
  42. {myokit-1.36.0.dist-info → myokit-1.37.0.dist-info}/METADATA +1 -1
  43. {myokit-1.36.0.dist-info → myokit-1.37.0.dist-info}/RECORD +47 -46
  44. {myokit-1.36.0.dist-info → myokit-1.37.0.dist-info}/LICENSE.txt +0 -0
  45. {myokit-1.36.0.dist-info → myokit-1.37.0.dist-info}/WHEEL +0 -0
  46. {myokit-1.36.0.dist-info → myokit-1.37.0.dist-info}/entry_points.txt +0 -0
  47. {myokit-1.36.0.dist-info → myokit-1.37.0.dist-info}/top_level.txt +0 -0
myokit/_sim/cvodessim.c CHANGED
@@ -25,20 +25,26 @@ import myokit
25
25
  #include <Python.h>
26
26
  #include <stdio.h>
27
27
 
28
- #include <cvodes/cvodes.h>
29
- #include <nvector/nvector_serial.h>
30
- #include <sundials/sundials_types.h>
31
28
  #include <sundials/sundials_config.h>
32
29
  #ifndef SUNDIALS_VERSION_MAJOR
33
30
  #define SUNDIALS_VERSION_MAJOR 2
34
31
  #endif
32
+ #include <sundials/sundials_types.h>
33
+ #if SUNDIALS_VERSION_MAJOR >= 7
34
+ #define realtype sunrealtype
35
+ #define RCONST SUN_RCONST
36
+ #endif
37
+ #include <nvector/nvector_serial.h>
38
+ #include <cvodes/cvodes.h>
35
39
  #if SUNDIALS_VERSION_MAJOR >= 3
36
40
  #include <sunmatrix/sunmatrix_dense.h>
37
41
  #include <sunlinsol/sunlinsol_dense.h>
38
- #include <cvodes/cvodes_direct.h>
39
42
  #else
40
43
  #include <cvodes/cvodes_dense.h>
41
44
  #endif
45
+ #if SUNDIALS_VERSION_MAJOR < 6
46
+ #include <cvodes/cvodes_direct.h>
47
+ #endif
42
48
 
43
49
  <?
44
50
  if myokit.DEBUG_SM:
@@ -75,107 +81,180 @@ typedef struct {
75
81
  realtype *p;
76
82
  } *UserData;
77
83
 
84
+ /*
85
+ * Check flags set by a generic sundials function, set python error.
86
+ * sundials_flag: The value to check
87
+ * funcname: The name of the function that returned the flag
88
+ */
89
+ int
90
+ check_sundials_flag(int flag, const char *funcname)
91
+ {
92
+ /* Check if flag < 0 */
93
+ if (flag < 0) {
94
+ PyErr_Format(PyExc_Exception, "Function %s failed with flag = %d", funcname, flag);
95
+ return 1;
96
+ }
97
+ return 0;
98
+ }
99
+
100
+ /*
101
+ * Check flags set by any cvode-related function except cvode(), set python error.
102
+ * sundials_flag: The value to check
103
+ * funcname: The name of the function that returned the flag
104
+ */
105
+ int
106
+ check_cvode_related_flag(int flag, const char *funcname)
107
+ {
108
+ /* Check if flag < 0 */
109
+ if (flag < 0) {
110
+ switch (flag) {
111
+ case CV_MEM_NULL:
112
+ PyErr_Format(PyExc_Exception, "Function %s failed with flag CV_MEM_NULL: The cvode memory block was not initialized.", funcname);
113
+ break;
114
+ case CV_MEM_FAIL:
115
+ PyErr_Format(PyExc_Exception, "Function %s failed with flag CV_MEM_FAIL: A memory allocation failed.", funcname);
116
+ break;
117
+ case CV_NO_MALLOC:
118
+ PyErr_Format(PyExc_Exception, "Function %s failed with flag CV_NO_MALLOC: A memory allocation function returned NULL.", funcname);
119
+ break;
120
+ case CV_ILL_INPUT:
121
+ PyErr_Format(PyExc_Exception, "Function %s failed with flag CV_ILL_INPUT: Invalid input arguments.", funcname);
122
+ break;
123
+ case CV_NO_SENS:
124
+ PyErr_Format(PyExc_Exception, "Function %s failed with flag CV_NO_SENS: Forward sensitivity analysis was not initialized.", funcname);
125
+ break;
126
+ case CV_BAD_K:
127
+ PyErr_Format(PyExc_Exception, "Function %s failed with flag CV_BAD_K: Argument k is not in range.", funcname);
128
+ break;
129
+ case CV_BAD_T:
130
+ PyErr_Format(PyExc_Exception, "Function %s failed with flag CV_BAD_T: Argument t is not in range.", funcname);
131
+ break;
132
+ case CV_BAD_DKY:
133
+ PyErr_Format(PyExc_Exception, "Function %s failed with flag CV_BAD_DKY: The argument DKY was NULL.", funcname);
134
+ break;
135
+ default:
136
+ PyErr_Format(PyExc_Exception, "Function %s failed with unhandled flag = %d", funcname, flag);
137
+ }
138
+ return 1;
139
+ }
140
+ return 0;
141
+ }
142
+
78
143
  /*
79
144
  * Check sundials flags, set python error.
80
- * flagvalue : The value to check
145
+ * flag: The value to check
146
+ * funcname: The name of the function that returned the flag
147
+ */
148
+ int
149
+ check_cvode_flag(int flag)
150
+ {
151
+ /* Check if flag < 0 */
152
+ if (flag < 0) {
153
+ switch (flag) {
154
+ case CV_TOO_MUCH_WORK:
155
+ PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag CV_TOO_MUCH_WORK: The solver took mxstep internal steps but could not reach tout.");
156
+ break;
157
+ case CV_TOO_MUCH_ACC:
158
+ PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag CV_TOO_MUCH_ACC: The solver could not satisfy the accuracy demanded by the user for some internal step.");
159
+ break;
160
+ case CV_ERR_FAILURE:
161
+ PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag CV_ERR_FAILURE: Error test failures occurred too many times during one internal time step or minimum step size was reached.");
162
+ break;
163
+ case CV_CONV_FAILURE:
164
+ PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag CV_CONV_FAILURE: Convergence test failures occurred too many times during one internal time step or minimum step size was reached.");
165
+ break;
166
+ case CV_LINIT_FAIL:
167
+ PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag CV_LINIT_FAIL: The linear solver's initialization function failed.");
168
+ break;
169
+ case -6:
170
+ PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -6 CV_LSETUP_FAIL: The linear solver's setup function failed in an unrecoverable manner.");
171
+ break;
172
+ case -7:
173
+ PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -7 CV_LSOLVE_FAIL: The linear solver's solve function failed in an unrecoverable manner.");
174
+ break;
175
+ case -8:
176
+ PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -8 CV_RHSFUNC_FAIL: The right-hand side function failed in an unrecoverable manner.");
177
+ break;
178
+ case -9:
179
+ PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -9 CV_FIRST_RHSFUNC_ERR: The right-hand side function failed at the first call.");
180
+ break;
181
+ case -10:
182
+ PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -10 CV_REPTD_RHSFUNC_ERR: The right-hand side function had repeated recoverable errors.");
183
+ break;
184
+ case -11:
185
+ PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -11 CV_UNREC_RHSFUNC_ERR: The right-hand side function had a recoverable error, but no recovery is possible.");
186
+ break;
187
+ case -12:
188
+ PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -12 CV_RTFUNC_FAIL: The root finding function failed in an unrecoverable manner.");
189
+ break;
190
+ case -20:
191
+ PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -20 CV_MEM_FAIL: A memory allocation failed.");
192
+ break;
193
+ case -21:
194
+ PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -21 CV_MEM_NULL: The cvode mem argument was NULL.");
195
+ break;
196
+ case -22:
197
+ PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -22 CV_ILL_INPUT: One of the function inputs is illegal.");
198
+ break;
199
+ case -23:
200
+ PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -23 CV_NO_MALLOC: The cvode memory block was not allocated by a call to CVodeMalloc.");
201
+ break;
202
+ case -24:
203
+ PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -24 CV_BAD_K: The derivative order k is larger than the order used.");
204
+ break;
205
+ case -25:
206
+ PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -25 CV_BAD_T: The time t is outside the last step taken.");
207
+ break;
208
+ case -26:
209
+ PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -26 CV_BAD_DKY: The output derivative vector is NULL.");
210
+ break;
211
+ case -27:
212
+ PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -27 CV_TOO_CLOSE: The output and initial times are too close to each other.");
213
+ break;
214
+ default:
215
+ PyErr_Format(PyExc_Exception, "Function CVode() failed with unhandled flag = %d", flag);
216
+ }
217
+ return 1;
218
+ }
219
+ return 0;
220
+ }
221
+
222
+ #if SUNDIALS_VERSION_MAJOR >= 7
223
+ /*
224
+ * Check sundials error code (Sundials 7 and above)
225
+ * sunerr : The SunErroCode to check
81
226
  * funcname : The name of the function that returned the flag
82
- * opt : Mode selector
83
- * 0 : Error if the flag is null
84
- * 1 : Error if the flag is < 0
85
- * 2 : Errir
86
227
  */
87
228
  int
88
- check_cvode_flag(void *flagvalue, char *funcname, int opt)
229
+ check_sundials_error(SUNErrCode code, const char *funcname)
89
230
  {
90
- if (opt == 0 && flagvalue == NULL) {
91
- /* Check if sundials function returned null pointer */
92
- PyErr_Format(PyExc_Exception, "%s() failed - returned NULL pointer", funcname);
231
+ const char* msg;
232
+ if (code) {
233
+ msg = SUNGetErrMsg(code);
234
+ PyErr_Format(PyExc_Exception, "%s() failed with message = %s", funcname, msg);
93
235
  return 1;
94
- } else if (opt == 1) {
95
- /* Check if flag < 0 */
96
- int flag = *((int*)flagvalue);
97
- if (flag < 0) {
98
- if (strcmp(funcname, "CVode") == 0) {
99
- switch (flag) {
100
- case -1:
101
- PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -1 CV_TOO_MUCH_WORK: The solver took mxstep internal steps but could not reach tout.");
102
- break;
103
- case -2:
104
- PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -2 CV_TOO_MUCH_ACC: The solver could not satisfy the accuracy demanded by the user for some internal step.");
105
- break;
106
- case -3:
107
- PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -3 CV_ERR_FAILURE: Error test failures occurred too many times during one internal time step or minimum step size was reached.");
108
- break;
109
- case -4:
110
- PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -4 CV_CONV_FAILURE: Convergence test failures occurred too many times during one internal time step or minimum step size was reached.");
111
- break;
112
- case -5:
113
- PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -5 CV_LINIT_FAIL: The linear solver's initialization function failed.");
114
- break;
115
- case -6:
116
- PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -6 CV_LSETUP_FAIL: The linear solver's setup function failed in an unrecoverable manner.");
117
- break;
118
- case -7:
119
- PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -7 CV_LSOLVE_FAIL: The linear solver's solve function failed in an unrecoverable manner.");
120
- break;
121
- case -8:
122
- PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -8 CV_RHSFUNC_FAIL: The right-hand side function failed in an unrecoverable manner.");
123
- break;
124
- case -9:
125
- PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -9 CV_FIRST_RHSFUNC_ERR: The right-hand side function failed at the first call.");
126
- break;
127
- case -10:
128
- PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -10 CV_REPTD_RHSFUNC_ERR: The right-hand side function had repeated recoverable errors.");
129
- break;
130
- case -11:
131
- PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -11 CV_UNREC_RHSFUNC_ERR: The right-hand side function had a recoverable error, but no recovery is possible.");
132
- break;
133
- case -12:
134
- PyErr_SetString(PyExc_ArithmeticError, "Function CVode() failed with flag -12 CV_RTFUNC_FAIL: The root finding function failed in an unrecoverable manner.");
135
- break;
136
- case -20:
137
- PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -20 CV_MEM_FAIL: A memory allocation failed.");
138
- break;
139
- case -21:
140
- PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -21 CV_MEM_NULL: The cvode mem argument was NULL.");
141
- break;
142
- case -22:
143
- PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -22 CV_ILL_INPUT: One of the function inputs is illegal.");
144
- break;
145
- case -23:
146
- PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -23 CV_NO_MALLOC: The cvode memory block was not allocated by a call to CVodeMalloc.");
147
- break;
148
- case -24:
149
- PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -24 CV_BAD_K: The derivative order k is larger than the order used.");
150
- break;
151
- case -25:
152
- PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -25 CV_BAD_T: The time t is outside the last step taken.");
153
- break;
154
- case -26:
155
- PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -26 CV_BAD_DKY: The output derivative vector is NULL.");
156
- break;
157
- case -27:
158
- PyErr_SetString(PyExc_Exception, "Function CVode() failed with flag -27 CV_TOO_CLOSE: The output and initial times are too close to each other.");
159
- break;
160
- default:
161
- PyErr_Format(PyExc_Exception, "Function CVode() failed with unknown flag = %d", flag);
162
- }
163
- } else {
164
- PyErr_Format(PyExc_Exception, "%s() failed with flag = %d", funcname, flag);
165
- }
166
- return 1;
167
- }
168
236
  }
169
237
  return 0;
170
238
  }
239
+ #endif
171
240
 
172
241
  /*
173
242
  * Error and warning message handler for CVODES.
174
- * Error messages are already set via check_cvode_flag, so this method
243
+ * Error messages are already set via check_cvode_flag & co, so this method
175
244
  * suppresses error messages.
176
245
  * Warnings are passed to Python's warning system, where they can be
177
246
  * caught or suppressed using the warnings module.
178
247
  */
248
+ #if SUNDIALS_VERSION_MAJOR >= 7
249
+ void
250
+ ErrorHandler(int line, const char* function, const char* file, const char* msg,
251
+ SUNErrCode error_code, void* err_user_data, SUNContext context)
252
+ {
253
+ if (error_code) {
254
+ PyErr_WarnFormat(PyExc_RuntimeWarning, 1, "CVODES: %s", msg);
255
+ }
256
+ }
257
+ #else
179
258
  void
180
259
  ErrorHandler(int error_code, const char *module, const char *function,
181
260
  char *msg, void *eh_data)
@@ -184,6 +263,7 @@ ErrorHandler(int error_code, const char *module, const char *function,
184
263
  PyErr_WarnFormat(PyExc_RuntimeWarning, 1, "CVODES: %s", msg);
185
264
  }
186
265
  }
266
+ #endif
187
267
 
188
268
  /*
189
269
  * Initialisation status.
@@ -569,6 +649,10 @@ sim_init(PyObject *self, PyObject *args)
569
649
  Model_Flag flag_model;
570
650
  ESys_Flag flag_epacing;
571
651
  TSys_Flag flag_fpacing;
652
+ /* Error handling in >=7 */
653
+ #if SUNDIALS_VERSION_MAJOR >= 7
654
+ SUNErrCode sunerr;
655
+ #endif
572
656
 
573
657
  /* Pacing systems */
574
658
  ESys epacing;
@@ -747,11 +831,12 @@ sim_init(PyObject *self, PyObject *args)
747
831
  /*
748
832
  * Create sundials context
749
833
  */
750
- #if SUNDIALS_VERSION_MAJOR >= 6
834
+ #if SUNDIALS_VERSION_MAJOR >= 7
835
+ sunerr = SUNContext_Create(SUN_COMM_NULL, &sundials_context);
836
+ if (check_sundials_error(sunerr, "SUNContext_Create")) return sim_clean();
837
+ #elif SUNDIALS_VERSION_MAJOR >= 6
751
838
  flag_cvode = SUNContext_Create(NULL, &sundials_context);
752
- if (check_cvode_flag(&flag_cvode, "SUNContext_Create", 1)) {
753
- return sim_cleanx(PyExc_Exception, "Failed to create Sundials context.");
754
- }
839
+ if (check_sundials_flag(flag_cvode, "SUNContext_Create")) return sim_clean();
755
840
  #ifdef MYOKIT_DEBUG_PROFILING
756
841
  benchmarker_print("CP Created sundials context.");
757
842
  #endif
@@ -767,9 +852,7 @@ sim_init(PyObject *self, PyObject *args)
767
852
  #else
768
853
  y = N_VNew_Serial(model->n_states);
769
854
  #endif
770
- if (check_cvode_flag((void*)y, "N_VNew_Serial", 0)) {
771
- return sim_cleanx(PyExc_Exception, "Failed to create state vector.");
772
- }
855
+ if (y == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate space for state vector.");
773
856
 
774
857
  /* Create state vector copy for error handling */
775
858
  #if SUNDIALS_VERSION_MAJOR >= 6
@@ -777,16 +860,12 @@ sim_init(PyObject *self, PyObject *args)
777
860
  #else
778
861
  ylast = N_VNew_Serial(model->n_states);
779
862
  #endif
780
- if (check_cvode_flag((void*)ylast, "N_VNew_Serial", 0)) {
781
- return sim_cleanx(PyExc_Exception, "Failed to create last-state vector.");
782
- }
863
+ if (ylast == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate space for last-state vector.");
783
864
 
784
865
  /* Create sensitivity vector array */
785
866
  if (model->has_sensitivities) {
786
867
  sy = N_VCloneVectorArray(model->ns_independents, y);
787
- if (check_cvode_flag((void*)sy, "N_VCloneVectorArray", 0)) {
788
- return sim_cleanx(PyExc_Exception, "Failed to allocate space to store sensitivities.");
789
- }
868
+ if (sy == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate space for sensitivity vector array.");
790
869
  }
791
870
 
792
871
  /*
@@ -809,14 +888,10 @@ sim_init(PyObject *self, PyObject *args)
809
888
  #else
810
889
  z = N_VNew_Serial(model->n_states);
811
890
  #endif
812
- if (check_cvode_flag((void*)z, "N_VNew_Serial", 0)) {
813
- return sim_cleanx(PyExc_Exception, "Failed to create state vector for logging.");
814
- }
891
+ if (z == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate space for state vector for logging.");
815
892
  if (model->has_sensitivities) {
816
893
  sz = N_VCloneVectorArray(model->ns_independents, y);
817
- if (check_cvode_flag((void*)sz, "N_VCloneVectorArray", 0)) {
818
- return sim_cleanx(PyExc_Exception, "Failed to create state sensitivity vector array for logging.");
819
- }
894
+ if (sz == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate space for sensitivity vector array for logging.");
820
895
  }
821
896
  }
822
897
 
@@ -964,9 +1039,7 @@ sim_init(PyObject *self, PyObject *args)
964
1039
  /* Create parameter scaling vector, for error control */
965
1040
  /* TODO: Get this from the Python code ? */
966
1041
  pbar = (realtype*)malloc((size_t)model->ns_independents * sizeof(realtype));
967
- if (pbar == NULL) {
968
- return sim_cleanx(PyExc_Exception, "Unable to allocate space to store parameter scales.");
969
- }
1042
+ if (pbar == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate space for parameter scale array.");
970
1043
  for (i=0; i<model->ns_independents; i++) {
971
1044
  pbar[i] = (udata->p[i] == 0.0 ? 1.0 : fabs(udata->p[i]));
972
1045
  }
@@ -990,17 +1063,11 @@ sim_init(PyObject *self, PyObject *args)
990
1063
  n_pace = (int)PyList_Size(protocols);
991
1064
  }
992
1065
  pacing_systems = (union PSys*)malloc((size_t)n_pace * sizeof(union PSys));
993
- if (pacing_systems == NULL) {
994
- return sim_cleanx(PyExc_Exception, "Unable to allocate space to store pacing systems.");
995
- }
1066
+ if (pacing_systems == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate space for pacing systems.");
996
1067
  pacing_types = (enum PSysType *)malloc((size_t)n_pace * sizeof(enum PSysType));
997
- if (pacing_types == NULL) {
998
- return sim_cleanx(PyExc_Exception, "Unable to allocate space to store pacing types.");
999
- }
1068
+ if (pacing_types == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate space for pacing types.");
1000
1069
  pacing = (realtype*)malloc((size_t)n_pace * sizeof(realtype));
1001
- if (pacing == NULL) {
1002
- return sim_cleanx(PyExc_Exception, "Unable to allocate space to store pacing values.");
1003
- }
1070
+ if (pacing == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate space for pacing values.");
1004
1071
  Model_SetupPacing(model, n_pace);
1005
1072
 
1006
1073
  /*
@@ -1081,68 +1148,73 @@ sim_init(PyObject *self, PyObject *args)
1081
1148
  #else
1082
1149
  cvode_mem = CVodeCreate(CV_BDF, CV_NEWTON);
1083
1150
  #endif
1084
- if (check_cvode_flag((void*)cvode_mem, "CVodeCreate", 0)) return sim_clean();
1151
+ if (cvode_mem == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate CVODE memory.");
1085
1152
 
1086
1153
  /* Set error and warning-message handler */
1154
+ #if SUNDIALS_VERSION_MAJOR >= 7
1155
+ sunerr = SUNContext_PushErrHandler(sundials_context, ErrorHandler, NULL);
1156
+ if (check_sundials_error(sunerr, "SUNContext_PushErrHandler")) return sim_clean();
1157
+ #else
1087
1158
  flag_cvode = CVodeSetErrHandlerFn(cvode_mem, ErrorHandler, NULL);
1088
- if (check_cvode_flag(&flag_cvode, "CVodeInit", 1)) return sim_clean();
1159
+ if (check_cvode_related_flag(flag_cvode, "CVodeSetErrHandlerFn")) return sim_clean();
1160
+ #endif
1089
1161
 
1090
1162
  /* Initialize solver memory, specify the rhs */
1091
1163
  flag_cvode = CVodeInit(cvode_mem, rhs, t, y);
1092
- if (check_cvode_flag(&flag_cvode, "CVodeInit", 1)) return sim_clean();
1164
+ if (check_cvode_related_flag(flag_cvode, "CVodeInit")) return sim_clean();
1093
1165
 
1094
1166
  /* Set absolute and relative tolerances */
1095
1167
  flag_cvode = CVodeSStolerances(cvode_mem, RCONST(rel_tol), RCONST(abs_tol));
1096
- if (check_cvode_flag(&flag_cvode, "CVodeSStolerances", 1)) return sim_clean();
1168
+ if (check_cvode_related_flag(flag_cvode, "CVodeSStolerances")) return sim_clean();
1097
1169
 
1098
1170
  /* Set a maximum step size (or 0.0 for none) */
1099
1171
  flag_cvode = CVodeSetMaxStep(cvode_mem, dt_max < 0 ? 0.0 : dt_max);
1100
- if (check_cvode_flag(&flag_cvode, "CVodeSetmaxStep", 1)) return sim_clean();
1172
+ if (check_cvode_related_flag(flag_cvode, "CVodeSetmaxStep")) return sim_clean();
1101
1173
 
1102
1174
  /* Set a minimum step size (or 0.0 for none) */
1103
1175
  flag_cvode = CVodeSetMinStep(cvode_mem, dt_min < 0 ? 0.0 : dt_min);
1104
- if (check_cvode_flag(&flag_cvode, "CVodeSetminStep", 1)) return sim_clean();
1176
+ if (check_cvode_related_flag(flag_cvode, "CVodeSetminStep")) return sim_clean();
1105
1177
 
1106
1178
  #if SUNDIALS_VERSION_MAJOR >= 6
1107
1179
  /* Create dense matrix for use in linear solves */
1108
1180
  sundense_matrix = SUNDenseMatrix(model->n_states, model->n_states, sundials_context);
1109
- if (check_cvode_flag((void *)sundense_matrix, "SUNDenseMatrix", 0)) return sim_clean();
1181
+ if (sundense_matrix == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate space for dense matrix.");
1110
1182
 
1111
1183
  /* Create dense linear solver object with matrix */
1112
1184
  sundense_solver = SUNLinSol_Dense(y, sundense_matrix, sundials_context);
1113
- if (check_cvode_flag((void *)sundense_solver, "SUNLinSol_Dense", 0)) return sim_clean();
1185
+ if (sundense_solver == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate space for dense solver.");
1114
1186
 
1115
1187
  /* Attach the matrix and solver to cvode */
1116
1188
  flag_cvode = CVodeSetLinearSolver(cvode_mem, sundense_solver, sundense_matrix);
1117
- if (check_cvode_flag(&flag_cvode, "CVodeSetLinearSolver", 1)) return sim_clean();
1189
+ if (check_sundials_flag(flag_cvode, "CVodeSetLinearSolver")) return sim_clean();
1118
1190
  #elif SUNDIALS_VERSION_MAJOR >= 4
1119
1191
  /* Create dense matrix for use in linear solves */
1120
1192
  sundense_matrix = SUNDenseMatrix(model->n_states, model->n_states);
1121
- if (check_cvode_flag((void *)sundense_matrix, "SUNDenseMatrix", 0)) return sim_clean();
1193
+ if (sundense_matrix == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate space for dense matrix.");
1122
1194
 
1123
1195
  /* Create dense linear solver object with matrix */
1124
1196
  sundense_solver = SUNLinSol_Dense(y, sundense_matrix);
1125
- if (check_cvode_flag((void *)sundense_solver, "SUNLinSol_Dense", 0)) return sim_clean();
1197
+ if (sundense_solver == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate space for dense solver.");
1126
1198
 
1127
1199
  /* Attach the matrix and solver to cvode */
1128
1200
  flag_cvode = CVodeSetLinearSolver(cvode_mem, sundense_solver, sundense_matrix);
1129
- if (check_cvode_flag(&flag_cvode, "CVodeSetLinearSolver", 1)) return sim_clean();
1201
+ if (check_sundials_flag(flag_cvode, "CVodeSetLinearSolver")) return sim_clean();
1130
1202
  #elif SUNDIALS_VERSION_MAJOR >= 3
1131
1203
  /* Create dense matrix for use in linear solves */
1132
1204
  sundense_matrix = SUNDenseMatrix(model->n_states, model->n_states);
1133
- if (check_cvode_flag((void *)sundense_matrix, "SUNDenseMatrix", 0)) return sim_clean();
1205
+ if (sundense_matrix == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate space for dense matrix.");
1134
1206
 
1135
1207
  /* Create dense linear solver object with matrix */
1136
1208
  sundense_solver = SUNDenseLinearSolver(y, sundense_matrix);
1137
- if (check_cvode_flag((void *)sundense_solver, "SUNDenseLinearSolver", 0)) return sim_clean();
1209
+ if (sundense_solver == NULL) return sim_cleanx(PyExc_Exception, "Unable to allocate space for dense solver.");
1138
1210
 
1139
1211
  /* Attach the matrix and solver to cvode */
1140
1212
  flag_cvode = CVDlsSetLinearSolver(cvode_mem, sundense_solver, sundense_matrix);
1141
- if (check_cvode_flag(&flag_cvode, "CVDlsSetLinearSolver", 1)) return sim_clean();
1213
+ if (check_sundials_flag(flag_cvode, "CVDlsSetLinearSolver")) return sim_clean();
1142
1214
  #else
1143
1215
  /* Create dense matrix for use in linear solves */
1144
1216
  flag_cvode = CVDense(cvode_mem, model->n_states);
1145
- if (check_cvode_flag(&flag_cvode, "CVDense", 1)) return sim_clean();
1217
+ if (check_sundials_flag(flag_cvode, "CVDense")) return sim_clean();
1146
1218
  #endif
1147
1219
 
1148
1220
  #ifdef MYOKIT_DEBUG_PROFILING
@@ -1155,19 +1227,19 @@ sim_init(PyObject *self, PyObject *args)
1155
1227
  RHS of the sensitivity ODE */
1156
1228
  /*flag_cvode = CVodeSensInit(cvode_mem, model->ns_independents, CV_SIMULTANEOUS, rhs1, sy);*/
1157
1229
  flag_cvode = CVodeSensInit(cvode_mem, model->ns_independents, CV_SIMULTANEOUS, NULL, sy);
1158
- if (check_cvode_flag(&flag_cvode, "CVodeSensInit", 1)) return sim_clean();
1230
+ if (check_cvode_related_flag(flag_cvode, "CVodeSensInit")) return sim_clean();
1159
1231
 
1160
1232
  /* Attach user data */
1161
1233
  flag_cvode = CVodeSetUserData(cvode_mem, udata);
1162
- if (check_cvode_flag(&flag_cvode, "CVodeSetUserData", 1)) return sim_clean();
1234
+ if (check_cvode_related_flag(flag_cvode, "CVodeSetUserData")) return sim_clean();
1163
1235
 
1164
1236
  /* Set parameter scales used in tolerances */
1165
1237
  flag_cvode = CVodeSetSensParams(cvode_mem, udata->p, pbar, NULL);
1166
- if (check_cvode_flag(&flag_cvode, "CVodeSetSensParams", 1)) return sim_clean();
1238
+ if (check_cvode_related_flag(flag_cvode, "CVodeSetSensParams")) return sim_clean();
1167
1239
 
1168
1240
  /* Set sensitivity tolerances calculating method (using pbar) */
1169
1241
  flag_cvode = CVodeSensEEtolerances(cvode_mem);
1170
- if (check_cvode_flag(&flag_cvode, "CVodeSensEEtolerances", 1)) return sim_clean();
1242
+ if (check_cvode_related_flag(flag_cvode, "CVodeSensEEtolerances")) return sim_clean();
1171
1243
 
1172
1244
  #ifdef MYOKIT_DEBUG_PROFILING
1173
1245
  benchmarker_print("CP CVODES sensitivity methods initialized.");
@@ -1184,7 +1256,7 @@ sim_init(PyObject *self, PyObject *args)
1184
1256
  if (model->is_ode && PyList_Check(rf_list)) {
1185
1257
  /* Initialize root function with 1 component */
1186
1258
  flag_cvode = CVodeRootInit(cvode_mem, 1, rf_function);
1187
- if (check_cvode_flag(&flag_cvode, "CVodeRootInit", 1)) return sim_clean();
1259
+ if (check_cvode_related_flag(flag_cvode, "CVodeRootInit")) return sim_clean();
1188
1260
 
1189
1261
  /* Direction of root crossings, one entry per root function, but we only use 1. */
1190
1262
  rf_direction = (int*)malloc(sizeof(int));
@@ -1416,7 +1488,7 @@ sim_step(PyObject *self, PyObject *args)
1416
1488
  #endif
1417
1489
 
1418
1490
  /* Check for errors */
1419
- if (check_cvode_flag(&flag_cvode, "CVode", 1)) {
1491
+ if (check_cvode_flag(flag_cvode)) {
1420
1492
  #ifdef MYOKIT_DEBUG_MESSAGES
1421
1493
  printf("\nCM CVODE flag %d. Setting error output and returning.\n", flag_cvode);
1422
1494
  #endif
@@ -1487,10 +1559,10 @@ sim_step(PyObject *self, PyObject *args)
1487
1559
 
1488
1560
  /* Go back to time=tnext */
1489
1561
  flag_cvode = CVodeGetDky(cvode_mem, tnext, 0, y);
1490
- if (check_cvode_flag(&flag_cvode, "CVodeGetDky", 1)) return sim_clean();
1562
+ if (check_cvode_related_flag(flag_cvode, "CVodeGetDky")) return sim_clean();
1491
1563
  if (model->has_sensitivities) {
1492
1564
  flag_cvode = CVodeGetSensDky(cvode_mem, tnext, 0, sy);
1493
- if (check_cvode_flag(&flag_cvode, "CVodeGetSensDky", 1)) return sim_clean();
1565
+ if (check_cvode_related_flag(flag_cvode, "CVodeGetSensDky")) return sim_clean();
1494
1566
  }
1495
1567
  t = tnext;
1496
1568
  /* Require reinit (after logging) */
@@ -1501,7 +1573,7 @@ sim_step(PyObject *self, PyObject *args)
1501
1573
  /* Get current sensitivity vector */
1502
1574
  if (model->has_sensitivities) {
1503
1575
  flag_cvode = CVodeGetSens(cvode_mem, &t, sy);
1504
- if (check_cvode_flag(&flag_cvode, "CVodeGetSens", 1)) return sim_clean();
1576
+ if (check_cvode_related_flag(flag_cvode, "CVodeGetSens")) return sim_clean();
1505
1577
  }
1506
1578
 
1507
1579
  /* Root found */
@@ -1509,7 +1581,7 @@ sim_step(PyObject *self, PyObject *args)
1509
1581
 
1510
1582
  /* Get directions of root crossings (1 per root function) */
1511
1583
  flag_root = CVodeGetRootInfo(cvode_mem, rf_direction);
1512
- if (check_cvode_flag(&flag_root, "CVodeGetRootInfo", 1)) return sim_clean();
1584
+ if (check_cvode_related_flag(flag_root, "CVodeGetRootInfo")) return sim_clean();
1513
1585
  /* We only have one root function, so we know that rf_direction[0] is non-zero at this point. */
1514
1586
 
1515
1587
  /* Store tuple (time, direction) for the found root */
@@ -1549,10 +1621,10 @@ sim_step(PyObject *self, PyObject *args)
1549
1621
  /* Get interpolated y(tlog) */
1550
1622
  if (model->is_ode) {
1551
1623
  flag_cvode = CVodeGetDky(cvode_mem, tlog, 0, z);
1552
- if (check_cvode_flag(&flag_cvode, "CVodeGetDky", 1)) return sim_clean();
1624
+ if (check_cvode_related_flag(flag_cvode, "CVodeGetDky")) return sim_clean();
1553
1625
  if (model->has_sensitivities) {
1554
1626
  flag_cvode = CVodeGetSensDky(cvode_mem, tlog, 0, sz);
1555
- if (check_cvode_flag(&flag_cvode, "CVodeGetSensDky", 1)) return sim_clean();
1627
+ if (check_cvode_related_flag(flag_cvode, "CVodeGetSensDky")) return sim_clean();
1556
1628
  }
1557
1629
  }
1558
1630
  /* If cvode-free mode, the states can't change so we don't
@@ -1678,10 +1750,10 @@ sim_step(PyObject *self, PyObject *args)
1678
1750
  */
1679
1751
  if (model->is_ode && flag_reinit) {
1680
1752
  flag_cvode = CVodeReInit(cvode_mem, t, y);
1681
- if (check_cvode_flag(&flag_cvode, "CVodeReInit", 1)) return sim_clean();
1753
+ if (check_cvode_related_flag(flag_cvode, "CVodeReInit")) return sim_clean();
1682
1754
  if (model->has_sensitivities) {
1683
1755
  flag_cvode = CVodeSensReInit(cvode_mem, CV_SIMULTANEOUS, sy);
1684
- if (check_cvode_flag(&flag_cvode, "CVodeSensReInit", 1)) return sim_clean();
1756
+ if (check_cvode_related_flag(flag_cvode, "CVodeSensReInit")) return sim_clean();
1685
1757
  }
1686
1758
  flag_reinit = 0;
1687
1759
  }
myokit/_sim/jacobian.py CHANGED
@@ -166,7 +166,7 @@ class JacobianTracer(myokit.CppModule):
166
166
  self._ext.calculate(state, bound, deriv, partial)
167
167
  # Discard derivatives
168
168
  # Convert partial derivatives to numpy array and store
169
- partial = np.array(partial, copy=False)
169
+ partial = np.asarray(partial)
170
170
  partial = partial.reshape((ns, ns))
171
171
  partials.append(partial)
172
172
  partials = np.array(partials)
@@ -282,8 +282,8 @@ class JacobianCalculator(myokit.CppModule):
282
282
  self._ext.calculate(state, inputs, deriv, partial)
283
283
 
284
284
  # Create numpy versions and return
285
- deriv = np.array(deriv, copy=False)
286
- partial = np.array(partial, copy=False).reshape((n, n))
285
+ deriv = np.asarray(deriv)
286
+ partial = np.asarray(partial).reshape((n, n))
287
287
  return deriv, partial
288
288
 
289
289
  def newton_root(self, x=None, accuracy=0, max_iter=50, damping=1):