myokit 1.36.0__py3-none-any.whl → 1.36.1__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.
- myokit/_myokit_version.py +1 -1
- myokit/_sim/cvodessim.c +221 -149
- myokit/_sim/mcl.h +54 -0
- myokit/lib/hh.py +3 -0
- myokit/tests/test_lib_hh.py +36 -0
- {myokit-1.36.0.dist-info → myokit-1.36.1.dist-info}/METADATA +1 -1
- {myokit-1.36.0.dist-info → myokit-1.36.1.dist-info}/RECORD +11 -11
- {myokit-1.36.0.dist-info → myokit-1.36.1.dist-info}/LICENSE.txt +0 -0
- {myokit-1.36.0.dist-info → myokit-1.36.1.dist-info}/WHEEL +0 -0
- {myokit-1.36.0.dist-info → myokit-1.36.1.dist-info}/entry_points.txt +0 -0
- {myokit-1.36.0.dist-info → myokit-1.36.1.dist-info}/top_level.txt +0 -0
myokit/_myokit_version.py
CHANGED
|
@@ -14,7 +14,7 @@ __release__ = True
|
|
|
14
14
|
# incompatibility
|
|
15
15
|
# - Changes to revision indicate bugfixes, tiny new features
|
|
16
16
|
# - There is no significance to odd/even numbers
|
|
17
|
-
__version_tuple__ = 1, 36,
|
|
17
|
+
__version_tuple__ = 1, 36, 1
|
|
18
18
|
|
|
19
19
|
# String version of the version number
|
|
20
20
|
__version__ = '.'.join([str(x) for x in __version_tuple__])
|
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
|
-
*
|
|
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
|
-
|
|
229
|
+
check_sundials_error(SUNErrCode code, const char *funcname)
|
|
89
230
|
{
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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 >=
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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(
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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 (
|
|
1756
|
+
if (check_cvode_related_flag(flag_cvode, "CVodeSensReInit")) return sim_clean();
|
|
1685
1757
|
}
|
|
1686
1758
|
flag_reinit = 0;
|
|
1687
1759
|
}
|
myokit/_sim/mcl.h
CHANGED
|
@@ -651,6 +651,9 @@ PyObject* mcl_info_device_dict(cl_device_id device_id, size_t bufsize, char* buf
|
|
|
651
651
|
}
|
|
652
652
|
|
|
653
653
|
// Name
|
|
654
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
655
|
+
printf(" Querying name\n");
|
|
656
|
+
#endif
|
|
654
657
|
flag = clGetDeviceInfo(device_id, CL_DEVICE_NAME, bufsize, buffer, NULL);
|
|
655
658
|
if(mcl_flag(flag)) { Py_DECREF(device); return NULL; }
|
|
656
659
|
val = PyUnicode_FromString(buffer);
|
|
@@ -658,6 +661,9 @@ PyObject* mcl_info_device_dict(cl_device_id device_id, size_t bufsize, char* buf
|
|
|
658
661
|
Py_CLEAR(val);
|
|
659
662
|
|
|
660
663
|
// Vendor
|
|
664
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
665
|
+
printf(" Querying vendor\n");
|
|
666
|
+
#endif
|
|
661
667
|
flag = clGetDeviceInfo(device_id, CL_DEVICE_VENDOR, bufsize, buffer, NULL);
|
|
662
668
|
if(mcl_flag(flag)) { Py_DECREF(device); return NULL; }
|
|
663
669
|
val = PyUnicode_FromString(buffer);
|
|
@@ -665,6 +671,9 @@ PyObject* mcl_info_device_dict(cl_device_id device_id, size_t bufsize, char* buf
|
|
|
665
671
|
Py_CLEAR(val);
|
|
666
672
|
|
|
667
673
|
// Device version
|
|
674
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
675
|
+
printf(" Querying device version\n");
|
|
676
|
+
#endif
|
|
668
677
|
flag = clGetDeviceInfo(device_id, CL_DEVICE_VERSION, bufsize, buffer, NULL);
|
|
669
678
|
if(mcl_flag(flag)) { Py_DECREF(device); return NULL; }
|
|
670
679
|
val = PyUnicode_FromString(buffer);
|
|
@@ -672,6 +681,9 @@ PyObject* mcl_info_device_dict(cl_device_id device_id, size_t bufsize, char* buf
|
|
|
672
681
|
Py_CLEAR(val);
|
|
673
682
|
|
|
674
683
|
// Driver version
|
|
684
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
685
|
+
printf(" Querying driver version\n");
|
|
686
|
+
#endif
|
|
675
687
|
flag = clGetDeviceInfo(device_id, CL_DRIVER_VERSION, bufsize, buffer, NULL);
|
|
676
688
|
if(mcl_flag(flag)) { Py_DECREF(device); return NULL; }
|
|
677
689
|
val = PyUnicode_FromString(buffer);
|
|
@@ -679,6 +691,9 @@ PyObject* mcl_info_device_dict(cl_device_id device_id, size_t bufsize, char* buf
|
|
|
679
691
|
Py_CLEAR(val);
|
|
680
692
|
|
|
681
693
|
// Clock speed (MHz)
|
|
694
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
695
|
+
printf(" Querying clock speed\n");
|
|
696
|
+
#endif
|
|
682
697
|
flag = clGetDeviceInfo(device_id, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(buf_uint), &buf_uint, NULL);
|
|
683
698
|
if(mcl_flag(flag)) { Py_DECREF(device); return NULL; }
|
|
684
699
|
val = PyLong_FromUnsignedLong(buf_uint);
|
|
@@ -686,6 +701,9 @@ PyObject* mcl_info_device_dict(cl_device_id device_id, size_t bufsize, char* buf
|
|
|
686
701
|
Py_CLEAR(val);
|
|
687
702
|
|
|
688
703
|
// Global memory (bytes)
|
|
704
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
705
|
+
printf(" Querying global memory size\n");
|
|
706
|
+
#endif
|
|
689
707
|
flag = clGetDeviceInfo(device_id, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(buf_ulong), &buf_ulong, NULL);
|
|
690
708
|
if(mcl_flag(flag)) { Py_DECREF(device); return NULL; }
|
|
691
709
|
val = PyLong_FromUnsignedLongLong(buf_ulong);
|
|
@@ -693,6 +711,9 @@ PyObject* mcl_info_device_dict(cl_device_id device_id, size_t bufsize, char* buf
|
|
|
693
711
|
Py_CLEAR(val);
|
|
694
712
|
|
|
695
713
|
// Local memory (bytes)
|
|
714
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
715
|
+
printf(" Querying local memory size\n");
|
|
716
|
+
#endif
|
|
696
717
|
flag = clGetDeviceInfo(device_id, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(buf_ulong), &buf_ulong, NULL);
|
|
697
718
|
if(mcl_flag(flag)) { Py_DECREF(device); return NULL; }
|
|
698
719
|
val = PyLong_FromUnsignedLongLong(buf_ulong);
|
|
@@ -700,6 +721,9 @@ PyObject* mcl_info_device_dict(cl_device_id device_id, size_t bufsize, char* buf
|
|
|
700
721
|
Py_CLEAR(val);
|
|
701
722
|
|
|
702
723
|
// Const memory (bytes)
|
|
724
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
725
|
+
printf(" Querying max buffer size\n");
|
|
726
|
+
#endif
|
|
703
727
|
flag = clGetDeviceInfo(device_id, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(buf_ulong), &buf_ulong, NULL);
|
|
704
728
|
if(mcl_flag(flag)) { Py_DECREF(device); return NULL; }
|
|
705
729
|
val = PyLong_FromUnsignedLongLong(buf_ulong);
|
|
@@ -707,6 +731,9 @@ PyObject* mcl_info_device_dict(cl_device_id device_id, size_t bufsize, char* buf
|
|
|
707
731
|
Py_CLEAR(val);
|
|
708
732
|
|
|
709
733
|
// Computing units
|
|
734
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
735
|
+
printf(" Querying max computing units\n");
|
|
736
|
+
#endif
|
|
710
737
|
flag = clGetDeviceInfo(device_id, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(buf_uint), &buf_uint, NULL);
|
|
711
738
|
if(mcl_flag(flag)) { Py_DECREF(device); return NULL; }
|
|
712
739
|
val = PyLong_FromUnsignedLong(buf_uint);
|
|
@@ -714,6 +741,9 @@ PyObject* mcl_info_device_dict(cl_device_id device_id, size_t bufsize, char* buf
|
|
|
714
741
|
Py_CLEAR(val);
|
|
715
742
|
|
|
716
743
|
// Max workgroup size
|
|
744
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
745
|
+
printf(" Querying max work group size\n");
|
|
746
|
+
#endif
|
|
717
747
|
flag = clGetDeviceInfo(device_id, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(buf_size_t), &buf_size_t, NULL);
|
|
718
748
|
if(mcl_flag(flag)) { Py_DECREF(device); return NULL; }
|
|
719
749
|
val = PyLong_FromSize_t(buf_size_t);
|
|
@@ -721,6 +751,9 @@ PyObject* mcl_info_device_dict(cl_device_id device_id, size_t bufsize, char* buf
|
|
|
721
751
|
Py_CLEAR(val);
|
|
722
752
|
|
|
723
753
|
// Max workitem sizes
|
|
754
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
755
|
+
printf(" Querying max work item sizes\n");
|
|
756
|
+
#endif
|
|
724
757
|
flag = clGetDeviceInfo(device_id, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(buf_uint), &buf_uint, NULL);
|
|
725
758
|
if(mcl_flag(flag)) { Py_DECREF(device); return NULL; }
|
|
726
759
|
val = PyLong_FromUnsignedLong(buf_uint);
|
|
@@ -739,6 +772,9 @@ PyObject* mcl_info_device_dict(cl_device_id device_id, size_t bufsize, char* buf
|
|
|
739
772
|
Py_CLEAR(items_sizes_tuple);
|
|
740
773
|
|
|
741
774
|
// Maximum size of a kernel parameter
|
|
775
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
776
|
+
printf(" Querying maximum kernel parameter size\n");
|
|
777
|
+
#endif
|
|
742
778
|
flag = clGetDeviceInfo(device_id, CL_DEVICE_MAX_PARAMETER_SIZE, sizeof(buf_size_t), &buf_size_t, NULL);
|
|
743
779
|
if(mcl_flag(flag)) { Py_DECREF(device); return NULL; }
|
|
744
780
|
val = PyLong_FromSize_t(buf_size_t);
|
|
@@ -834,29 +870,47 @@ mcl_info(void)
|
|
|
834
870
|
|
|
835
871
|
// Check all platforms
|
|
836
872
|
for (i=0; i<n_platforms; i++) {
|
|
873
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
874
|
+
printf("Checking platform %u\n", (unsigned int)i);
|
|
875
|
+
#endif
|
|
837
876
|
|
|
838
877
|
// Create platform dict
|
|
839
878
|
platform = mcl_info_platform_dict(platform_ids[i], sizeof(buffer), buffer);
|
|
840
879
|
if (platform == NULL) { Py_DECREF(platforms); return NULL; }
|
|
880
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
881
|
+
printf(" Obtained platform info dict.\n");
|
|
882
|
+
#endif
|
|
841
883
|
|
|
842
884
|
// Count devices
|
|
843
885
|
flag = clGetDeviceIDs(platform_ids[i], CL_DEVICE_TYPE_ALL, MCL_MAX_DEVICES, device_ids, &n_devices);
|
|
844
886
|
if (flag == CL_DEVICE_NOT_FOUND) {
|
|
845
887
|
n_devices = 0;
|
|
888
|
+
} else if (flag == CL_INVALID_VALUE) {
|
|
889
|
+
// This seems to happen on Mac OS 14.4.1
|
|
890
|
+
n_devices = 0;
|
|
846
891
|
} else if (mcl_flag(flag)) {
|
|
847
892
|
Py_DECREF(platforms);
|
|
848
893
|
return NULL;
|
|
849
894
|
}
|
|
895
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
896
|
+
printf(" Found %u devices.\n", (unsigned int)n_devices);
|
|
897
|
+
#endif
|
|
850
898
|
|
|
851
899
|
// Create devices tuple, must decref on exception
|
|
852
900
|
devices = PyTuple_New((size_t)n_devices);
|
|
853
901
|
|
|
854
902
|
// Add devices
|
|
855
903
|
for (j=0; j<n_devices; j++) {
|
|
904
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
905
|
+
printf(" Checking device %u\n", (unsigned int)j);
|
|
906
|
+
#endif
|
|
856
907
|
|
|
857
908
|
// Create device dict, must decref on exception
|
|
858
909
|
device = mcl_info_device_dict(device_ids[j], sizeof(buffer), buffer);
|
|
859
910
|
if (device == NULL) { Py_DECREF(platforms); Py_DECREF(devices); return NULL; }
|
|
911
|
+
#ifdef MYOKIT_DEBUG_MESSAGES
|
|
912
|
+
printf(" Obtained device info dict.\n");
|
|
913
|
+
#endif
|
|
860
914
|
|
|
861
915
|
// Add device to devices tuple (steals reference)
|
|
862
916
|
PyTuple_SetItem(devices, j, device);
|
myokit/lib/hh.py
CHANGED
|
@@ -298,6 +298,9 @@ class HHModel:
|
|
|
298
298
|
'_y[' + k + '] = ' + state.uname() + ' = '
|
|
299
299
|
+ inf + ' + (_y0[' + k + '] - ' + inf
|
|
300
300
|
+ ') * numpy.exp(-_t / ' + tau + ')')
|
|
301
|
+
f.append(
|
|
302
|
+
'_y[' + k + '][_t == 0] = ' + state.uname() + '[_t == 0] = '
|
|
303
|
+
+ '_y0[' + k + ']')
|
|
301
304
|
|
|
302
305
|
# Add current calculation
|
|
303
306
|
if self._current is not None:
|
myokit/tests/test_lib_hh.py
CHANGED
|
@@ -15,6 +15,8 @@ import myokit.lib.hh as hh
|
|
|
15
15
|
|
|
16
16
|
from myokit.tests import DIR_DATA
|
|
17
17
|
|
|
18
|
+
from myokit.tests import WarningCollector
|
|
19
|
+
|
|
18
20
|
|
|
19
21
|
MODEL = """
|
|
20
22
|
[[model]]
|
|
@@ -914,6 +916,40 @@ class AnalyticalSimulationTest(unittest.TestCase):
|
|
|
914
916
|
e = np.abs(d1['binding.I'] - d2['binding.I'])
|
|
915
917
|
self.assertLess(np.max(e), 2e-4)
|
|
916
918
|
|
|
919
|
+
def test_tau_overflow(self):
|
|
920
|
+
# Overflows leading to tau=0 should still report current
|
|
921
|
+
# https://github.com/myokit/myokit/issues/1059
|
|
922
|
+
|
|
923
|
+
# Load model and convert to inf-tau form
|
|
924
|
+
fname = os.path.join(DIR_DATA, 'lr-1991-fitting.mmt')
|
|
925
|
+
model = hh.convert_hh_states_to_inf_tau_form(myokit.load_model(fname))
|
|
926
|
+
|
|
927
|
+
# Get initial state and set steady state
|
|
928
|
+
initial_state = model.get('ina.m').initial_value(as_float=True)
|
|
929
|
+
steady_state = 0.75
|
|
930
|
+
model.get('ina.m.inf').set_rhs(steady_state)
|
|
931
|
+
|
|
932
|
+
# Create an analytical simulation
|
|
933
|
+
model = hh.HHModel(model, states=['ina.m', 'ina.h', 'ina.j'],
|
|
934
|
+
parameters=['ina.p5'], current='ina.INa')
|
|
935
|
+
p = myokit.pacing.steptrain_linear(20, 40, 10, -80, 10, 10)
|
|
936
|
+
s = hh.AnalyticalSimulation(model, protocol=p)
|
|
937
|
+
|
|
938
|
+
# Setting p5=0.001 will trigger an overflow in ina.m.beta
|
|
939
|
+
s.set_parameters([0.001])
|
|
940
|
+
with WarningCollector() as wc:
|
|
941
|
+
# Log times chosen so that s._function varies length of _t
|
|
942
|
+
log = s.run(41, log_times=np.array([0, 1, 2, 10, 11, 12, 20, 40]))
|
|
943
|
+
self.assertIn('overflow', wc.text())
|
|
944
|
+
|
|
945
|
+
# Should be no NaNs in log
|
|
946
|
+
self.assertFalse(np.any(np.isnan(log['ina.INa'])))
|
|
947
|
+
self.assertFalse(np.any(np.isnan(log['ina.m'])))
|
|
948
|
+
|
|
949
|
+
# Should immediately jump from initial state to steady state
|
|
950
|
+
self.assertTrue(log['ina.m'][0] == initial_state)
|
|
951
|
+
self.assertTrue(np.all(log['ina.m'][1:] == steady_state))
|
|
952
|
+
|
|
917
953
|
|
|
918
954
|
if __name__ == '__main__':
|
|
919
955
|
unittest.main()
|
|
@@ -8,7 +8,7 @@ myokit/_err.py,sha256=PZJFrb3KGqW8XiT466UDtSTsW83M2J02T96Vm2CaCto,11060
|
|
|
8
8
|
myokit/_expressions.py,sha256=7We9a830pV7bvQziZcjwab-96p0LXg4AfawZhvvdR8U,103902
|
|
9
9
|
myokit/_io.py,sha256=2ll5Yb-sbP4tvc3pPmzhNuv_PaRMPJlNRWb1TzXfELg,8948
|
|
10
10
|
myokit/_model_api.py,sha256=I93WLjstvikqpkqQ5KC4PjNVlSz3nrxms_aKDgSEZ2c,194214
|
|
11
|
-
myokit/_myokit_version.py,sha256=
|
|
11
|
+
myokit/_myokit_version.py,sha256=Tj0x0hW2n9taFBS4CUqW6b_QI-kKolONZiG692DKLek,726
|
|
12
12
|
myokit/_parsing.py,sha256=GTVUwJvqjkQ3rc6BiwMFnzanLivbSUzW796gHCTJrNg,74065
|
|
13
13
|
myokit/_progress.py,sha256=Mi2QU6Vqj4qudhXc76amXM31iID2Mo8Gljw5OH2COZ4,4410
|
|
14
14
|
myokit/_protocol.py,sha256=_N16LGHppIv4yCSPjy0q2f-Oed0yG1wMk0ipTtXnMck,30756
|
|
@@ -85,14 +85,14 @@ myokit/_sim/cmodel.h,sha256=PlXRNDWV5JDsl28G-k3UlzwFCF5_crkAeWpRgPO8a0s,38795
|
|
|
85
85
|
myokit/_sim/cmodel.py,sha256=9amSihccWepI1SGI98b5tvvSq2cmAMLX-ecgHoXnc0Y,15775
|
|
86
86
|
myokit/_sim/compiler.c,sha256=yahdqeQhEU4Uduy3xP2NS21k8h2rQXEQTWYpsE6NEFk,4047
|
|
87
87
|
myokit/_sim/compiler.py,sha256=80Qwk7_LOjbu0jt9_aeMLQMEvYj3H4xIoE525zUUEK8,2664
|
|
88
|
-
myokit/_sim/cvodessim.c,sha256=
|
|
88
|
+
myokit/_sim/cvodessim.c,sha256=iWXHVSNTN2VqGGu24N8QFRWwpUUxDo17fTIP0Fv0Ikg,78062
|
|
89
89
|
myokit/_sim/cvodessim.py,sha256=EtFixQFg84qQy134TWOAgFd__cUrWs1LdXiJ_YJ-e_Y,46122
|
|
90
90
|
myokit/_sim/differential.hpp,sha256=LiaFNQks_4RkWeNEnUc48XjbdYyGSsxfWo35leygM68,15446
|
|
91
91
|
myokit/_sim/fiber_tissue.c,sha256=mKtNy3Qs2Tg917hgCryaftwJGHqFn7WZAOuJWG3VVpY,47444
|
|
92
92
|
myokit/_sim/fiber_tissue.py,sha256=A3zyGPGHNjFdGgbIzCiKYN8o4L2nq7W_ZjO996jF9Kc,50780
|
|
93
93
|
myokit/_sim/jacobian.cpp,sha256=mvuxHnxiyg4GW-ik1qOgOGbaj-sb-DbtidsRDXfRIjc,8012
|
|
94
94
|
myokit/_sim/jacobian.py,sha256=5Gmli0knQUozhYyarOrMBFnvytKnrufOh3HrGiycUMM,12957
|
|
95
|
-
myokit/_sim/mcl.h,sha256=
|
|
95
|
+
myokit/_sim/mcl.h,sha256=B8k6eur1VsvnYO2bV94Zm2-B66sCZMgPmzCUQnfelqA,34114
|
|
96
96
|
myokit/_sim/opencl.c,sha256=jQ3eJNldvX-sOnbIrexUSnOmIfEFSL9ceHNYkW18y80,5037
|
|
97
97
|
myokit/_sim/opencl.py,sha256=cHJ4CeqAmDLEik0WSuZ46UJYKmpaq2i0wuEZu_ZC7ng,16446
|
|
98
98
|
myokit/_sim/openclsim.c,sha256=St0P93K0mcYt2oabR7-XRsVFRsrL6kGW-b_kA-P6TsE,46541
|
|
@@ -197,7 +197,7 @@ myokit/gui/vargrapher.py,sha256=GALPOZjQ0ShOBu_qd_RwVRRQla0t2ctgQ25Jb8NmuJ8,6072
|
|
|
197
197
|
myokit/lib/__init__.py,sha256=GWvBrLDJHdbobXjt9WMFAd1td2Ml7dnvtzsDmYfuVFM,216
|
|
198
198
|
myokit/lib/deps.py,sha256=gB-W7LFZK6gAzf00mXvu6ws44Yua06Gd9HsKMe0lpXM,23859
|
|
199
199
|
myokit/lib/guess.py,sha256=BW_wOeStFKpjdZWRZpaO5PLEj8KGSdy_1kc3FM36zfk,28056
|
|
200
|
-
myokit/lib/hh.py,sha256=
|
|
200
|
+
myokit/lib/hh.py,sha256=8wMRnjrjZ8gNeErKz0KYQSqUeljJPPC2G339jPjNFXw,46813
|
|
201
201
|
myokit/lib/markov.py,sha256=VNXvrRdnATILxvuXm-VPw7S_L1Jtd9rRJPtOHKYtxZQ,67940
|
|
202
202
|
myokit/lib/multi.py,sha256=WDYvoAaVsMqnshk1NoVnH1zyVeVZ0GtsdHplZlkG86A,4408
|
|
203
203
|
myokit/lib/plots.py,sha256=tRyM4DhcZzlPLBs-VxdsZ7MJXvqLlDWmC12WhL7pP44,13875
|
|
@@ -245,7 +245,7 @@ myokit/tests/test_jacobian_calculator.py,sha256=_nBJdNI0L6tspWX7RgZcM-WW9CJ8oxZp
|
|
|
245
245
|
myokit/tests/test_jacobian_tracer.py,sha256=SoT6pOXKtzsDHPY2krHVCTtu7BDBtYobhFqejj77q4M,1767
|
|
246
246
|
myokit/tests/test_lib_deps.py,sha256=0Hgw_ncakKuKOe8awVezmTdxIIoVMZz4JjTEFsIOakc,7476
|
|
247
247
|
myokit/tests/test_lib_guess.py,sha256=IqbElIMWQN_FxiGj4tohZq9JZLpSAFzn4d9lo0-WKOE,42333
|
|
248
|
-
myokit/tests/test_lib_hh.py,sha256=
|
|
248
|
+
myokit/tests/test_lib_hh.py,sha256=f6QUvPpsJlRQ5gnULlQQUO9yh4sRSYr7rsqQCURNi3o,32591
|
|
249
249
|
myokit/tests/test_lib_markov.py,sha256=Rg_jqgSiKtlpaE6pLiCcmYlCTqyVkPkQ5SIGfyPRv2I,39983
|
|
250
250
|
myokit/tests/test_lib_multi.py,sha256=XL2qxtgNeO2aRaaM1VEzYBo1H3FTBY7-cftqsKwoNHo,5145
|
|
251
251
|
myokit/tests/test_lib_plots.py,sha256=_t1QucHdCoy6fALOZDY9DL0cMRJYB0nflk68LFSwU7U,5754
|
|
@@ -391,9 +391,9 @@ myokit/tests/data/multi/beeler-no-name.mmt,sha256=tBeWcTVag1gAQAvxWlUqH6GQhF1D4D
|
|
|
391
391
|
myokit/tests/data/multi/lr-1991.mmt,sha256=9jzHRAy1nLiBOPioiEpXmsRvIqwEezRY_ve2eHMDbTQ,6013
|
|
392
392
|
myokit/tests/data/multi/not-a-model.csv,sha256=7ek3pQXr2fpjNjFTs-B-T_kEehx8IQ-evdcg24dtMEs,109
|
|
393
393
|
myokit/tests/data/multi/subdir/beeler-no-name.mmt,sha256=tBeWcTVag1gAQAvxWlUqH6GQhF1D4DMnlmuePQn1vBY,3008
|
|
394
|
-
myokit-1.36.
|
|
395
|
-
myokit-1.36.
|
|
396
|
-
myokit-1.36.
|
|
397
|
-
myokit-1.36.
|
|
398
|
-
myokit-1.36.
|
|
399
|
-
myokit-1.36.
|
|
394
|
+
myokit-1.36.1.dist-info/LICENSE.txt,sha256=19_GtuJ-mvPSB1zH9rF_uKVK-bs5bEXFc7PISIRF1KI,1833
|
|
395
|
+
myokit-1.36.1.dist-info/METADATA,sha256=bCxAeMCjxz2LrlwPK6TPNKOUBXlZhfr_Jtqfn_GMBOA,6279
|
|
396
|
+
myokit-1.36.1.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
|
397
|
+
myokit-1.36.1.dist-info/entry_points.txt,sha256=yP9wy3w0YAAYUD5PYGliYKhnKvEp5l6p4S_XvXsqreM,48
|
|
398
|
+
myokit-1.36.1.dist-info/top_level.txt,sha256=vopnhGEticqud7tKy6L6dvi_n_AMXoiYBEiboRTnsWY,7
|
|
399
|
+
myokit-1.36.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|