| File: | /tmp/pyrefcon/scipy/scipy/integrate/_odepackmodule.c |
| Warning: | line 830, column 9 PyObject ownership leak with reference count of 1 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | ||||
| 2 | /* MULTIPACK module by Travis Oliphant | |||
| 3 | ||||
| 4 | Copyright (c) 2002 Travis Oliphant all rights reserved | |||
| 5 | oliphant.travis@ieee.org | |||
| 6 | Permission to use, modify, and distribute this software is given under the | |||
| 7 | terms of the SciPy (BSD style) license. See LICENSE.txt that came with | |||
| 8 | this distribution for specifics. | |||
| 9 | ||||
| 10 | NO WARRANTY IS EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. | |||
| 11 | */ | |||
| 12 | ||||
| 13 | ||||
| 14 | /* This extension module is a collection of wrapper functions around | |||
| 15 | common FORTRAN code in the package ODEPACK. | |||
| 16 | ||||
| 17 | The wrappers are meant to be nearly direct translations between the | |||
| 18 | FORTRAN code and Python. Some parameters like sizes do not need to be | |||
| 19 | passed since they are available from the objects. | |||
| 20 | ||||
| 21 | It is anticipated that a pure Python module be written to call these lower | |||
| 22 | level routines and make a simpler user interface. All of the routines define | |||
| 23 | default values for little-used parameters so that even the raw routines are | |||
| 24 | quite useful without a separate wrapper. | |||
| 25 | ||||
| 26 | FORTRAN Outputs that are not either an error indicator or the sought-after | |||
| 27 | results are placed in a dictionary and returned as an optional member of | |||
| 28 | the result tuple when the full_output argument is non-zero. | |||
| 29 | */ | |||
| 30 | ||||
| 31 | #include "Python.h" | |||
| 32 | ||||
| 33 | #include "numpy/arrayobject.h" | |||
| 34 | ||||
| 35 | #ifdef HAVE_BLAS_ILP64 | |||
| 36 | #define F_INTint npy_int64 | |||
| 37 | #define F_INT_NPYNPY_INT NPY_INT64NPY_LONG | |||
| 38 | #else | |||
| 39 | #define F_INTint int | |||
| 40 | #define F_INT_NPYNPY_INT NPY_INT | |||
| 41 | #endif | |||
| 42 | ||||
| 43 | ||||
| 44 | #define PYERR(errobj,message){ PyErr_SetString(errobj,message); goto fail; } {\ | |||
| 45 | PyErr_SetString(errobj,message); \ | |||
| 46 | goto fail; \ | |||
| 47 | } | |||
| 48 | #define PYERR2(errobj,message){ PyErr_Print(); PyErr_SetString(errobj, message); goto fail; } { \ | |||
| 49 | PyErr_Print(); \ | |||
| 50 | PyErr_SetString(errobj, message); \ | |||
| 51 | goto fail; \ | |||
| 52 | } | |||
| 53 | ||||
| 54 | typedef struct _odepack_globals { | |||
| 55 | PyObject *python_function; | |||
| 56 | PyObject *python_jacobian; | |||
| 57 | PyObject *extra_arguments; /* a tuple */ | |||
| 58 | int jac_transpose; | |||
| 59 | int jac_type; | |||
| 60 | int tfirst; | |||
| 61 | } odepack_params; | |||
| 62 | ||||
| 63 | static odepack_params global_params = {NULL((void*)0), NULL((void*)0), NULL((void*)0), 0, 0, 0}; | |||
| 64 | ||||
| 65 | static | |||
| 66 | PyObject *call_odeint_user_function(PyObject *func, npy_intp n, double *x, | |||
| 67 | double t, int tfirst, | |||
| 68 | PyObject *args, PyObject *error_obj) | |||
| 69 | { | |||
| 70 | /* | |||
| 71 | This function is the C wrapper of the user's Python functions that | |||
| 72 | define the differential equations (and also the Jacobian function). | |||
| 73 | The Fortran code calls ode_function() and ode_jacobian_function(), | |||
| 74 | and those functions call this function to call the Python functions | |||
| 75 | provided to odeint by the user. | |||
| 76 | ||||
| 77 | If an error occurs, NULL is returned. Otherwise, a NumPy array | |||
| 78 | is returned. | |||
| 79 | */ | |||
| 80 | ||||
| 81 | PyArrayObject *sequence = NULL((void*)0); | |||
| 82 | PyObject *tfloat = NULL((void*)0); | |||
| 83 | PyObject *firstargs = NULL((void*)0); | |||
| 84 | PyObject *arglist = NULL((void*)0); | |||
| 85 | PyObject *result = NULL((void*)0); | |||
| 86 | PyArrayObject *result_array = NULL((void*)0); | |||
| 87 | ||||
| 88 | /* Build sequence argument from inputs */ | |||
| 89 | sequence = (PyArrayObject *) PyArray_SimpleNewFromData(1, &n, NPY_DOUBLE,(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) PyArray_API [93])(&(*(PyTypeObject *)PyArray_API[2]), 1, &n, NPY_DOUBLE , ((void*)0), (char *) x, 0, (0x0001 | (0x0100 | 0x0400)), (( void*)0)) | |||
| 90 | (char *) x)(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) PyArray_API [93])(&(*(PyTypeObject *)PyArray_API[2]), 1, &n, NPY_DOUBLE , ((void*)0), (char *) x, 0, (0x0001 | (0x0100 | 0x0400)), (( void*)0)); | |||
| 91 | if (sequence == NULL((void*)0)) { | |||
| 92 | goto fail; | |||
| 93 | } | |||
| 94 | ||||
| 95 | tfloat = PyFloat_FromDouble(t); | |||
| 96 | if (tfloat == NULL((void*)0)) { | |||
| 97 | goto fail; | |||
| 98 | } | |||
| 99 | ||||
| 100 | /* firstargs is a tuple that will hold the first two arguments. */ | |||
| 101 | firstargs = PyTuple_New(2); | |||
| 102 | if (firstargs == NULL((void*)0)) { | |||
| 103 | goto fail; | |||
| 104 | } | |||
| 105 | ||||
| 106 | if (tfirst == 0) { | |||
| 107 | PyTuple_SET_ITEM(firstargs, 0, (PyObject *) sequence)PyTuple_SetItem(firstargs, 0, (PyObject *) sequence); | |||
| 108 | PyTuple_SET_ITEM(firstargs, 1, tfloat)PyTuple_SetItem(firstargs, 1, tfloat); | |||
| 109 | } else { | |||
| 110 | PyTuple_SET_ITEM(firstargs, 0, tfloat)PyTuple_SetItem(firstargs, 0, tfloat); | |||
| 111 | PyTuple_SET_ITEM(firstargs, 1, (PyObject *) sequence)PyTuple_SetItem(firstargs, 1, (PyObject *) sequence); | |||
| 112 | } | |||
| 113 | /* firstargs now owns the sequence and tfloat references. */ | |||
| 114 | sequence = NULL((void*)0); | |||
| 115 | tfloat = NULL((void*)0); | |||
| 116 | ||||
| 117 | arglist = PySequence_Concat(firstargs, args); | |||
| 118 | if (arglist == NULL((void*)0)) { | |||
| 119 | goto fail; | |||
| 120 | } | |||
| 121 | ||||
| 122 | /* Call the Python function. */ | |||
| 123 | result = PyObject_CallObject(func, arglist); | |||
| 124 | if (result == NULL((void*)0)) { | |||
| 125 | goto fail; | |||
| 126 | } | |||
| 127 | ||||
| 128 | result_array = (PyArrayObject *) | |||
| 129 | PyArray_ContiguousFromObject(result, NPY_DOUBLE, 0, 0)(*(PyObject * (*)(PyObject *, PyArray_Descr *, int, int, int, PyObject *)) PyArray_API[69])(result, (*(PyArray_Descr * (*) (int)) PyArray_API[45])(NPY_DOUBLE), 0, 0, ((0x0001 | (0x0100 | 0x0400))) | 0x0040, ((void*)0)); | |||
| 130 | ||||
| 131 | fail: | |||
| 132 | Py_XDECREF(sequence)_Py_XDECREF(((PyObject*)(sequence))); | |||
| 133 | Py_XDECREF(tfloat)_Py_XDECREF(((PyObject*)(tfloat))); | |||
| 134 | Py_XDECREF(firstargs)_Py_XDECREF(((PyObject*)(firstargs))); | |||
| 135 | Py_XDECREF(arglist)_Py_XDECREF(((PyObject*)(arglist))); | |||
| 136 | Py_XDECREF(result)_Py_XDECREF(((PyObject*)(result))); | |||
| 137 | return (PyObject *) result_array; | |||
| 138 | } | |||
| 139 | ||||
| 140 | ||||
| 141 | static PyObject *odepack_error; | |||
| 142 | ||||
| 143 | #if defined(UPPERCASE_FORTRAN) | |||
| 144 | #if defined(NO_APPEND_FORTRAN) | |||
| 145 | /* nothing to do here */ | |||
| 146 | #else | |||
| 147 | #define LSODAlsoda_ LSODA_ | |||
| 148 | #endif | |||
| 149 | #else | |||
| 150 | #if defined(NO_APPEND_FORTRAN) | |||
| 151 | #define LSODAlsoda_ lsoda | |||
| 152 | #else | |||
| 153 | #define LSODAlsoda_ lsoda_ | |||
| 154 | #endif | |||
| 155 | #endif | |||
| 156 | ||||
| 157 | typedef void lsoda_f_t(F_INTint *n, double *t, double *y, double *ydot); | |||
| 158 | typedef int lsoda_jac_t(F_INTint *n, double *t, double *y, F_INTint *ml, F_INTint *mu, | |||
| 159 | double *pd, F_INTint *nrowpd); | |||
| 160 | ||||
| 161 | void LSODAlsoda_(lsoda_f_t *f, F_INTint *neq, double *y, double *t, double *tout, F_INTint *itol, | |||
| 162 | double *rtol, double *atol, F_INTint *itask, F_INTint *istate, F_INTint *iopt, | |||
| 163 | double *rwork, F_INTint *lrw, F_INTint *iwork, F_INTint *liw, lsoda_jac_t *jac, | |||
| 164 | F_INTint *jt); | |||
| 165 | ||||
| 166 | /* | |||
| 167 | void ode_function(int *n, double *t, double *y, double *ydot) | |||
| 168 | { | |||
| 169 | ydot[0] = -0.04*y[0] + 1e4*y[1]*y[2]; | |||
| 170 | ydot[2] = 3e7*y[1]*y[1]; | |||
| 171 | ydot[1] = -ydot[0] - ydot[2]; | |||
| 172 | return; | |||
| 173 | } | |||
| 174 | */ | |||
| 175 | ||||
| 176 | void | |||
| 177 | ode_function(F_INTint *n, double *t, double *y, double *ydot) | |||
| 178 | { | |||
| 179 | /* | |||
| 180 | This is the function called from the Fortran code. It should | |||
| 181 | -- use call_odeint_user_function to get a multiarrayobject result | |||
| 182 | -- check for errors and set *n to -1 if any | |||
| 183 | -- otherwise place result of calculation in ydot | |||
| 184 | */ | |||
| 185 | ||||
| 186 | PyArrayObject *result_array = NULL((void*)0); | |||
| 187 | ||||
| 188 | result_array = (PyArrayObject *) | |||
| 189 | call_odeint_user_function(global_params.python_function, | |||
| 190 | *n, y, *t, global_params.tfirst, | |||
| 191 | global_params.extra_arguments, | |||
| 192 | odepack_error); | |||
| 193 | if (result_array == NULL((void*)0)) { | |||
| 194 | *n = -1; | |||
| 195 | return; | |||
| 196 | } | |||
| 197 | ||||
| 198 | if (PyArray_NDIM(result_array) > 1) { | |||
| 199 | *n = -1; | |||
| 200 | PyErr_Format(PyExc_RuntimeError, | |||
| 201 | "The array return by func must be one-dimensional, but got ndim=%d.", | |||
| 202 | PyArray_NDIM(result_array)); | |||
| 203 | Py_DECREF(result_array)_Py_DECREF(((PyObject*)(result_array))); | |||
| 204 | return; | |||
| 205 | } | |||
| 206 | ||||
| 207 | if (PyArray_Size(*(npy_intp (*)(PyObject *)) PyArray_API[59])((PyObject *)result_array) != *n) { | |||
| 208 | PyErr_Format(PyExc_RuntimeError, | |||
| 209 | "The size of the array returned by func (%ld) does not match " | |||
| 210 | "the size of y0 (%d).", | |||
| 211 | PyArray_Size(*(npy_intp (*)(PyObject *)) PyArray_API[59])((PyObject *)result_array), *n); | |||
| 212 | *n = -1; | |||
| 213 | Py_DECREF(result_array)_Py_DECREF(((PyObject*)(result_array))); | |||
| 214 | return; | |||
| 215 | } | |||
| 216 | ||||
| 217 | memcpy(ydot, PyArray_DATA(result_array), (*n)*sizeof(double)); | |||
| 218 | Py_DECREF(result_array)_Py_DECREF(((PyObject*)(result_array))); | |||
| 219 | return; | |||
| 220 | } | |||
| 221 | ||||
| 222 | ||||
| 223 | /* | |||
| 224 | * Copy a contiguous matrix at `c` to a Fortran-ordered matrix at `f`. | |||
| 225 | * `ldf` is the leading dimension of the Fortran array at `f`. | |||
| 226 | * `nrows` and `ncols` are the number of rows and columns of the matrix, resp. | |||
| 227 | * If `transposed` is 0, c[i, j] is *(c + ncols*i + j). | |||
| 228 | * If `transposed` is nonzero, c[i, j] is *(c + i + nrows*j) (i.e. `c` is | |||
| 229 | * stored in F-contiguous order). | |||
| 230 | */ | |||
| 231 | ||||
| 232 | static void | |||
| 233 | copy_array_to_fortran(double *f, F_INTint ldf, F_INTint nrows, F_INTint ncols, | |||
| 234 | double *c, F_INTint transposed) | |||
| 235 | { | |||
| 236 | F_INTint i, j; | |||
| 237 | F_INTint row_stride, col_stride; | |||
| 238 | ||||
| 239 | /* The strides count multiples of sizeof(double), not bytes. */ | |||
| 240 | if (transposed) { | |||
| 241 | row_stride = 1; | |||
| 242 | col_stride = nrows; | |||
| 243 | } | |||
| 244 | else { | |||
| 245 | row_stride = ncols; | |||
| 246 | col_stride = 1; | |||
| 247 | } | |||
| 248 | for (i = 0; i < nrows; ++i) { | |||
| 249 | for (j = 0; j < ncols; ++j) { | |||
| 250 | double value; | |||
| 251 | /* value = c[i,j] */ | |||
| 252 | value = *(c + row_stride*i + col_stride*j); | |||
| 253 | /* f[i,j] = value */ | |||
| 254 | *(f + ldf*j + i) = value; | |||
| 255 | } | |||
| 256 | } | |||
| 257 | } | |||
| 258 | ||||
| 259 | ||||
| 260 | int | |||
| 261 | ode_jacobian_function(F_INTint *n, double *t, double *y, F_INTint *ml, F_INTint *mu, | |||
| 262 | double *pd, F_INTint *nrowpd) | |||
| 263 | { | |||
| 264 | /* | |||
| 265 | This is the function called from the Fortran code. It should | |||
| 266 | -- use call_odeint_user_function to get a multiarrayobject result | |||
| 267 | -- check for errors and return -1 if any (though this is ignored | |||
| 268 | by calling program). | |||
| 269 | -- otherwise place result of calculation in pd | |||
| 270 | */ | |||
| 271 | ||||
| 272 | PyArrayObject *result_array; | |||
| 273 | npy_intp ndim, nrows, ncols, dim_error; | |||
| 274 | npy_intp *dims; | |||
| 275 | ||||
| 276 | result_array = (PyArrayObject *) | |||
| 277 | call_odeint_user_function(global_params.python_jacobian, | |||
| 278 | *n, y, *t, global_params.tfirst, | |||
| 279 | global_params.extra_arguments, | |||
| 280 | odepack_error); | |||
| 281 | if (result_array == NULL((void*)0)) { | |||
| 282 | *n = -1; | |||
| 283 | return -1; | |||
| 284 | } | |||
| 285 | ||||
| 286 | ncols = *n; | |||
| 287 | if (global_params.jac_type == 4) { | |||
| 288 | nrows = *ml + *mu + 1; | |||
| 289 | } | |||
| 290 | else { | |||
| 291 | nrows = *n; | |||
| 292 | } | |||
| 293 | ||||
| 294 | if (!global_params.jac_transpose) { | |||
| 295 | npy_intp tmp; | |||
| 296 | tmp = nrows; | |||
| 297 | nrows = ncols; | |||
| 298 | ncols = tmp; | |||
| 299 | } | |||
| 300 | ||||
| 301 | ndim = PyArray_NDIM(result_array); | |||
| 302 | if (ndim > 2) { | |||
| 303 | PyErr_Format(PyExc_RuntimeError, | |||
| 304 | "The Jacobian array must be two dimensional, but got ndim=%d.", | |||
| 305 | ndim); | |||
| 306 | *n = -1; | |||
| 307 | Py_DECREF(result_array)_Py_DECREF(((PyObject*)(result_array))); | |||
| 308 | return -1; | |||
| 309 | } | |||
| 310 | ||||
| 311 | dims = PyArray_DIMS(result_array); | |||
| 312 | dim_error = 0; | |||
| 313 | if (ndim == 0) { | |||
| 314 | if ((nrows != 1) || (ncols != 1)) { | |||
| 315 | dim_error = 1; | |||
| 316 | } | |||
| 317 | } | |||
| 318 | if (ndim == 1) { | |||
| 319 | if ((nrows != 1) || (dims[0] != ncols)) { | |||
| 320 | dim_error = 1; | |||
| 321 | } | |||
| 322 | } | |||
| 323 | if (ndim == 2) { | |||
| 324 | if ((dims[0] != nrows) || (dims[1] != ncols)) { | |||
| 325 | dim_error = 1; | |||
| 326 | } | |||
| 327 | } | |||
| 328 | if (dim_error) { | |||
| 329 | char *b = ""; | |||
| 330 | if (global_params.jac_type == 4) { | |||
| 331 | b = "banded "; | |||
| 332 | } | |||
| 333 | PyErr_Format(PyExc_RuntimeError, | |||
| 334 | "Expected a %sJacobian array with shape (%d, %d)", | |||
| 335 | b, nrows, ncols); | |||
| 336 | *n = -1; | |||
| 337 | Py_DECREF(result_array)_Py_DECREF(((PyObject*)(result_array))); | |||
| 338 | return -1; | |||
| 339 | } | |||
| 340 | ||||
| 341 | /* | |||
| 342 | * global_params.jac_type is either 1 (full Jacobian) or 4 (banded Jacobian). | |||
| 343 | * global_params.jac_transpose is !col_deriv, so if global_params.jac_transpose | |||
| 344 | * is 0, the array created by the user is already in Fortran order, and | |||
| 345 | * a transpose is not needed when it is copied to pd. | |||
| 346 | */ | |||
| 347 | ||||
| 348 | if ((global_params.jac_type == 1) && !global_params.jac_transpose) { | |||
| 349 | /* Full Jacobian, no transpose needed, so we can use memcpy. */ | |||
| 350 | memcpy(pd, PyArray_DATA(result_array), (*n)*(*nrowpd)*sizeof(double)); | |||
| 351 | } | |||
| 352 | else { | |||
| 353 | /* | |||
| 354 | * global_params.jac_type == 4 (banded Jacobian), or | |||
| 355 | * global_params.jac_type == 1 and global_params.jac_transpose == 1. | |||
| 356 | * | |||
| 357 | * We can't use memcpy when global_params.jac_type is 4 because the leading | |||
| 358 | * dimension of pd doesn't necessarily equal the number of rows of the | |||
| 359 | * matrix. | |||
| 360 | */ | |||
| 361 | npy_intp m; /* Number of rows in the (full or packed banded) Jacobian. */ | |||
| 362 | if (global_params.jac_type == 4) { | |||
| 363 | m = *ml + *mu + 1; | |||
| 364 | } | |||
| 365 | else { | |||
| 366 | m = *n; | |||
| 367 | } | |||
| 368 | copy_array_to_fortran(pd, *nrowpd, m, *n, | |||
| 369 | (double *) PyArray_DATA(result_array), | |||
| 370 | !global_params.jac_transpose); | |||
| 371 | } | |||
| 372 | ||||
| 373 | Py_DECREF(result_array)_Py_DECREF(((PyObject*)(result_array))); | |||
| 374 | return 0; | |||
| 375 | } | |||
| 376 | ||||
| 377 | ||||
| 378 | int | |||
| 379 | setup_extra_inputs(PyArrayObject **ap_rtol, PyObject *o_rtol, | |||
| 380 | PyArrayObject **ap_atol, PyObject *o_atol, | |||
| 381 | PyArrayObject **ap_tcrit, PyObject *o_tcrit, | |||
| 382 | long *numcrit, int neq) | |||
| 383 | { | |||
| 384 | int itol = 0; | |||
| 385 | double tol = 1.49012e-8; | |||
| 386 | npy_intp one = 1; | |||
| 387 | ||||
| 388 | /* Setup tolerances */ | |||
| 389 | if (o_rtol == NULL((void*)0)) { | |||
| 390 | *ap_rtol = (PyArrayObject *) PyArray_SimpleNew(1, &one, NPY_DOUBLE)(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) PyArray_API [93])(&(*(PyTypeObject *)PyArray_API[2]), 1, &one, NPY_DOUBLE , ((void*)0), ((void*)0), 0, 0, ((void*)0)); | |||
| 391 | if (*ap_rtol == NULL((void*)0)) { | |||
| 392 | PYERR2(odepack_error,"Error constructing relative tolerance."){ PyErr_Print(); PyErr_SetString(odepack_error, "Error constructing relative tolerance." ); goto fail; }; | |||
| 393 | } | |||
| 394 | *(double *) PyArray_DATA(*ap_rtol) = tol; /* Default */ | |||
| 395 | } | |||
| 396 | else { | |||
| 397 | *ap_rtol = (PyArrayObject *) PyArray_ContiguousFromObject(o_rtol,(*(PyObject * (*)(PyObject *, PyArray_Descr *, int, int, int, PyObject *)) PyArray_API[69])(o_rtol, (*(PyArray_Descr * (*) (int)) PyArray_API[45])(NPY_DOUBLE), 0, 1, ((0x0001 | (0x0100 | 0x0400))) | 0x0040, ((void*)0)) | |||
| 398 | NPY_DOUBLE, 0, 1)(*(PyObject * (*)(PyObject *, PyArray_Descr *, int, int, int, PyObject *)) PyArray_API[69])(o_rtol, (*(PyArray_Descr * (*) (int)) PyArray_API[45])(NPY_DOUBLE), 0, 1, ((0x0001 | (0x0100 | 0x0400))) | 0x0040, ((void*)0)); | |||
| 399 | if (*ap_rtol == NULL((void*)0)) { | |||
| 400 | PYERR2(odepack_error,"Error converting relative tolerance."){ PyErr_Print(); PyErr_SetString(odepack_error, "Error converting relative tolerance." ); goto fail; }; | |||
| 401 | } | |||
| 402 | /* XXX Fix the following. */ | |||
| 403 | if (PyArray_NDIM(*ap_rtol) == 0); /* rtol is scalar */ | |||
| 404 | else if (PyArray_DIMS(*ap_rtol)[0] == neq) { | |||
| 405 | itol |= 2; /* Set rtol array flag */ | |||
| 406 | } | |||
| 407 | else { | |||
| 408 | PYERR(odepack_error, "Tolerances must be an array of the same length as the\n number of equations or a scalar."){ PyErr_SetString(odepack_error,"Tolerances must be an array of the same length as the\n number of equations or a scalar." ); goto fail; }; | |||
| 409 | } | |||
| 410 | } | |||
| 411 | ||||
| 412 | if (o_atol == NULL((void*)0)) { | |||
| 413 | *ap_atol = (PyArrayObject *) PyArray_SimpleNew(1, &one, NPY_DOUBLE)(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) PyArray_API [93])(&(*(PyTypeObject *)PyArray_API[2]), 1, &one, NPY_DOUBLE , ((void*)0), ((void*)0), 0, 0, ((void*)0)); | |||
| 414 | if (*ap_atol == NULL((void*)0)) { | |||
| 415 | PYERR2(odepack_error,"Error constructing absolute tolerance"){ PyErr_Print(); PyErr_SetString(odepack_error, "Error constructing absolute tolerance" ); goto fail; }; | |||
| 416 | } | |||
| 417 | *(double *)PyArray_DATA(*ap_atol) = tol; | |||
| 418 | } | |||
| 419 | else { | |||
| 420 | *ap_atol = (PyArrayObject *) PyArray_ContiguousFromObject(o_atol, NPY_DOUBLE, 0, 1)(*(PyObject * (*)(PyObject *, PyArray_Descr *, int, int, int, PyObject *)) PyArray_API[69])(o_atol, (*(PyArray_Descr * (*) (int)) PyArray_API[45])(NPY_DOUBLE), 0, 1, ((0x0001 | (0x0100 | 0x0400))) | 0x0040, ((void*)0)); | |||
| 421 | if (*ap_atol == NULL((void*)0)) { | |||
| 422 | PYERR2(odepack_error,"Error converting absolute tolerance."){ PyErr_Print(); PyErr_SetString(odepack_error, "Error converting absolute tolerance." ); goto fail; }; | |||
| 423 | } | |||
| 424 | /* XXX Fix the following. */ | |||
| 425 | if (PyArray_NDIM(*ap_atol) == 0); /* atol is scalar */ | |||
| 426 | else if (PyArray_DIMS(*ap_atol)[0] == neq) { | |||
| 427 | itol |= 1; /* Set atol array flag */ | |||
| 428 | } | |||
| 429 | else { | |||
| 430 | PYERR(odepack_error,"Tolerances must be an array of the same length as the\n number of equations or a scalar."){ PyErr_SetString(odepack_error,"Tolerances must be an array of the same length as the\n number of equations or a scalar." ); goto fail; }; | |||
| 431 | } | |||
| 432 | } | |||
| 433 | itol++; /* increment to get correct value */ | |||
| 434 | ||||
| 435 | /* Setup t-critical */ | |||
| 436 | if (o_tcrit != NULL((void*)0)) { | |||
| 437 | *ap_tcrit = (PyArrayObject *) PyArray_ContiguousFromObject(o_tcrit, NPY_DOUBLE, 0, 1)(*(PyObject * (*)(PyObject *, PyArray_Descr *, int, int, int, PyObject *)) PyArray_API[69])(o_tcrit, (*(PyArray_Descr * (* )(int)) PyArray_API[45])(NPY_DOUBLE), 0, 1, ((0x0001 | (0x0100 | 0x0400))) | 0x0040, ((void*)0)); | |||
| 438 | if (*ap_tcrit == NULL((void*)0)) { | |||
| 439 | PYERR2(odepack_error,"Error constructing critical times."){ PyErr_Print(); PyErr_SetString(odepack_error, "Error constructing critical times." ); goto fail; }; | |||
| 440 | } | |||
| 441 | *numcrit = PyArray_Size(*(npy_intp (*)(PyObject *)) PyArray_API[59])((PyObject *) (*ap_tcrit)); | |||
| 442 | } | |||
| 443 | return itol; | |||
| 444 | ||||
| 445 | fail: /* Needed for use of PYERR */ | |||
| 446 | return -1; | |||
| 447 | } | |||
| 448 | ||||
| 449 | ||||
| 450 | int | |||
| 451 | compute_lrw_liw(F_INTint *lrw, F_INTint *liw, F_INTint neq, F_INTint jt, F_INTint ml, F_INTint mu, | |||
| 452 | F_INTint mxordn, F_INTint mxords) | |||
| 453 | { | |||
| 454 | F_INTint lrn, lrs, nyh, lmat; | |||
| 455 | ||||
| 456 | if (jt == 1 || jt == 2) { | |||
| 457 | lmat = neq*neq + 2; | |||
| 458 | } | |||
| 459 | else if (jt == 4 || jt == 5) { | |||
| 460 | lmat = (2*ml + mu + 1)*neq + 2; | |||
| 461 | } | |||
| 462 | else { | |||
| 463 | PYERR(odepack_error,"Incorrect value for jt."){ PyErr_SetString(odepack_error,"Incorrect value for jt."); goto fail; }; | |||
| 464 | } | |||
| 465 | ||||
| 466 | if (mxordn < 0) { | |||
| 467 | PYERR(odepack_error,"Incorrect value for mxordn."){ PyErr_SetString(odepack_error,"Incorrect value for mxordn." ); goto fail; }; | |||
| 468 | } | |||
| 469 | if (mxords < 0) { | |||
| 470 | PYERR(odepack_error,"Incorrect value for mxords."){ PyErr_SetString(odepack_error,"Incorrect value for mxords." ); goto fail; }; | |||
| 471 | } | |||
| 472 | nyh = neq; | |||
| 473 | ||||
| 474 | lrn = 20 + nyh*(mxordn+1) + 3*neq; | |||
| 475 | lrs = 20 + nyh*(mxords+1) + 3*neq + lmat; | |||
| 476 | ||||
| 477 | *lrw = PyArray_MAX(lrn,lrs)(((lrn)>(lrs))?(lrn):(lrs)); | |||
| 478 | *liw = 20 + neq; | |||
| 479 | return 0; | |||
| 480 | ||||
| 481 | fail: | |||
| 482 | return -1; | |||
| 483 | } | |||
| 484 | ||||
| 485 | static char doc_odeint[] = | |||
| 486 | "[y,{infodict,}istate] = odeint(fun, y0, t, args=(), Dfun=None, " | |||
| 487 | "col_deriv=0, ml=, mu=, full_output=0, rtol=, atol=, tcrit=, h0=0.0, " | |||
| 488 | "hmax=0.0, hmin=0.0, ixpr=0.0, mxstep=0.0, mxhnil=0, mxordn=0, " | |||
| 489 | "mxords=0)\n yprime = fun(y,t,...)"; | |||
| 490 | ||||
| 491 | ||||
| 492 | static PyObject * | |||
| 493 | odepack_odeint(PyObject *dummy, PyObject *args, PyObject *kwdict) | |||
| 494 | { | |||
| 495 | PyObject *fcn, *y0, *p_tout, *o_rtol = NULL((void*)0), *o_atol = NULL((void*)0); | |||
| 496 | PyArrayObject *ap_y = NULL((void*)0), *ap_yout = NULL((void*)0); | |||
| 497 | PyArrayObject *ap_rtol = NULL((void*)0), *ap_atol = NULL((void*)0); | |||
| 498 | PyArrayObject *ap_tout = NULL((void*)0); | |||
| 499 | PyObject *extra_args = NULL((void*)0); | |||
| 500 | PyObject *Dfun = Py_None(&_Py_NoneStruct); | |||
| 501 | F_INTint neq, itol = 1, itask = 1, istate = 1, iopt = 0, lrw, *iwork, liw, jt = 4; | |||
| 502 | double *y, t, *tout, *rtol, *atol, *rwork; | |||
| 503 | double h0 = 0.0, hmax = 0.0, hmin = 0.0; | |||
| 504 | long ixpr = 0, mxstep = 0, mxhnil = 0, mxordn = 12, mxords = 5, ml = -1, mu = -1; | |||
| 505 | long tfirst; | |||
| 506 | PyObject *o_tcrit = NULL((void*)0); | |||
| 507 | PyArrayObject *ap_tcrit = NULL((void*)0); | |||
| 508 | PyArrayObject *ap_hu = NULL((void*)0), *ap_tcur = NULL((void*)0), *ap_tolsf = NULL((void*)0), *ap_tsw = NULL((void*)0); | |||
| 509 | PyArrayObject *ap_nst = NULL((void*)0), *ap_nfe = NULL((void*)0), *ap_nje = NULL((void*)0), *ap_nqu = NULL((void*)0); | |||
| 510 | PyArrayObject *ap_mused = NULL((void*)0); | |||
| 511 | long imxer = 0, lenrw = 0, leniw = 0, col_deriv = 0; | |||
| 512 | npy_intp out_sz = 0, dims[2]; | |||
| 513 | long k, ntimes, crit_ind = 0; | |||
| 514 | long allocated = 0, full_output = 0, numcrit = 0; | |||
| 515 | long t0count; | |||
| 516 | double *yout, *yout_ptr, *tout_ptr, *tcrit = NULL((void*)0); | |||
| 517 | double *wa; | |||
| 518 | static char *kwlist[] = {"fun", "y0", "t", "args", "Dfun", "col_deriv", | |||
| 519 | "ml", "mu", "full_output", "rtol", "atol", "tcrit", | |||
| 520 | "h0", "hmax", "hmin", "ixpr", "mxstep", "mxhnil", | |||
| 521 | "mxordn", "mxords", "tfirst", NULL((void*)0)}; | |||
| 522 | odepack_params save_params; | |||
| 523 | ||||
| 524 | if (!PyArg_ParseTupleAndKeywords(args, kwdict, "OOO|OOllllOOOdddllllll", kwlist, | |||
| 525 | &fcn, &y0, &p_tout, &extra_args, &Dfun, | |||
| 526 | &col_deriv, &ml, &mu, &full_output, &o_rtol, &o_atol, | |||
| 527 | &o_tcrit, &h0, &hmax, &hmin, &ixpr, &mxstep, &mxhnil, | |||
| 528 | &mxordn, &mxords, &tfirst)) { | |||
| 529 | return NULL((void*)0); | |||
| 530 | } | |||
| 531 | ||||
| 532 | if (o_tcrit == Py_None(&_Py_NoneStruct)) { | |||
| 533 | o_tcrit = NULL((void*)0); | |||
| 534 | } | |||
| 535 | if (o_rtol == Py_None(&_Py_NoneStruct)) { | |||
| 536 | o_rtol = NULL((void*)0); | |||
| 537 | } | |||
| 538 | if (o_atol == Py_None(&_Py_NoneStruct)) { | |||
| 539 | o_atol = NULL((void*)0); | |||
| 540 | } | |||
| 541 | ||||
| 542 | /* Set up jt, ml, and mu */ | |||
| 543 | if (Dfun == Py_None(&_Py_NoneStruct)) { | |||
| 544 | /* set jt for internally generated */ | |||
| 545 | jt++; | |||
| 546 | } | |||
| 547 | if (ml < 0 && mu < 0) { | |||
| 548 | /* neither ml nor mu given, mark jt for full jacobian */ | |||
| 549 | jt -= 3; | |||
| 550 | } | |||
| 551 | if (ml < 0) { | |||
| 552 | /* if one but not both are given */ | |||
| 553 | ml = 0; | |||
| 554 | } | |||
| 555 | if (mu < 0) { | |||
| 556 | mu = 0; | |||
| 557 | } | |||
| 558 | ||||
| 559 | /* Stash the current global_params in save_params. */ | |||
| 560 | memcpy(&save_params, &global_params, sizeof(save_params)); | |||
| 561 | ||||
| 562 | if (extra_args == NULL((void*)0)) { | |||
| 563 | if ((extra_args = PyTuple_New(0)) == NULL((void*)0)) { | |||
| 564 | goto fail; | |||
| 565 | } | |||
| 566 | } | |||
| 567 | else { | |||
| 568 | Py_INCREF(extra_args)_Py_INCREF(((PyObject*)(extra_args))); /* We decrement on exit. */ | |||
| 569 | } | |||
| 570 | if (!PyTuple_Check(extra_args)((((((PyObject*)(extra_args))->ob_type))->tp_flags & ((1UL << 26))) != 0)) { | |||
| 571 | PYERR(odepack_error, "Extra arguments must be in a tuple."){ PyErr_SetString(odepack_error,"Extra arguments must be in a tuple." ); goto fail; }; | |||
| 572 | } | |||
| 573 | if (!PyCallable_Check(fcn) || (Dfun != Py_None(&_Py_NoneStruct) && !PyCallable_Check(Dfun))) { | |||
| 574 | PYERR(odepack_error, "The function and its Jacobian must be callable functions."){ PyErr_SetString(odepack_error,"The function and its Jacobian must be callable functions." ); goto fail; }; | |||
| 575 | } | |||
| 576 | ||||
| 577 | /* Set global_params from the function arguments. */ | |||
| 578 | global_params.python_function = fcn; | |||
| 579 | global_params.extra_arguments = extra_args; | |||
| 580 | global_params.python_jacobian = Dfun; | |||
| 581 | global_params.jac_transpose = !(col_deriv); | |||
| 582 | global_params.jac_type = jt; | |||
| 583 | global_params.tfirst = tfirst; | |||
| 584 | ||||
| 585 | /* Initial input vector */ | |||
| 586 | ap_y = (PyArrayObject *) PyArray_ContiguousFromObject(y0, NPY_DOUBLE, 0, 0)(*(PyObject * (*)(PyObject *, PyArray_Descr *, int, int, int, PyObject *)) PyArray_API[69])(y0, (*(PyArray_Descr * (*)(int )) PyArray_API[45])(NPY_DOUBLE), 0, 0, ((0x0001 | (0x0100 | 0x0400 ))) | 0x0040, ((void*)0)); | |||
| 587 | if (ap_y == NULL((void*)0)) { | |||
| 588 | goto fail; | |||
| 589 | } | |||
| 590 | if (PyArray_NDIM(ap_y) > 1) { | |||
| 591 | PyErr_SetString(PyExc_ValueError, "Initial condition y0 must be one-dimensional."); | |||
| 592 | goto fail; | |||
| 593 | } | |||
| 594 | y = (double *) PyArray_DATA(ap_y); | |||
| 595 | neq = PyArray_Size(*(npy_intp (*)(PyObject *)) PyArray_API[59])((PyObject *) ap_y); | |||
| 596 | dims[1] = neq; | |||
| 597 | ||||
| 598 | /* Set of output times for integration */ | |||
| 599 | ap_tout = (PyArrayObject *) PyArray_ContiguousFromObject(p_tout, NPY_DOUBLE, 0, 0)(*(PyObject * (*)(PyObject *, PyArray_Descr *, int, int, int, PyObject *)) PyArray_API[69])(p_tout, (*(PyArray_Descr * (*) (int)) PyArray_API[45])(NPY_DOUBLE), 0, 0, ((0x0001 | (0x0100 | 0x0400))) | 0x0040, ((void*)0)); | |||
| 600 | if (ap_tout == NULL((void*)0)) { | |||
| 601 | goto fail; | |||
| 602 | } | |||
| 603 | if (PyArray_NDIM(ap_tout) > 1) { | |||
| 604 | PyErr_SetString(PyExc_ValueError, "Output times t must be one-dimensional."); | |||
| 605 | goto fail; | |||
| 606 | } | |||
| 607 | tout = (double *) PyArray_DATA(ap_tout); | |||
| 608 | ntimes = PyArray_Size(*(npy_intp (*)(PyObject *)) PyArray_API[59])((PyObject *)ap_tout); | |||
| 609 | dims[0] = ntimes; | |||
| 610 | ||||
| 611 | t0count = 0; | |||
| 612 | if (ntimes > 0) { | |||
| 613 | /* Copy tout[0] to t, and count how many times it occurs. */ | |||
| 614 | t = tout[0]; | |||
| 615 | t0count = 1; | |||
| 616 | while ((t0count < ntimes) && (tout[t0count] == t)) { | |||
| 617 | ++t0count; | |||
| 618 | } | |||
| 619 | } | |||
| 620 | ||||
| 621 | /* Set up array to hold the output evaluations*/ | |||
| 622 | ap_yout= (PyArrayObject *) PyArray_SimpleNew(2,dims,NPY_DOUBLE)(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) PyArray_API [93])(&(*(PyTypeObject *)PyArray_API[2]), 2, dims, NPY_DOUBLE , ((void*)0), ((void*)0), 0, 0, ((void*)0)); | |||
| 623 | if (ap_yout== NULL((void*)0)) { | |||
| 624 | goto fail; | |||
| 625 | } | |||
| 626 | yout = (double *) PyArray_DATA(ap_yout); | |||
| 627 | ||||
| 628 | /* Copy initial vector into first row(s) of output */ | |||
| 629 | yout_ptr = yout; | |||
| 630 | for (k = 0; k < t0count; ++k) { | |||
| 631 | memcpy(yout_ptr, y, neq*sizeof(double)); | |||
| 632 | yout_ptr += neq; | |||
| 633 | } | |||
| 634 | ||||
| 635 | itol = setup_extra_inputs(&ap_rtol, o_rtol, &ap_atol, o_atol, &ap_tcrit, | |||
| 636 | o_tcrit, &numcrit, neq); | |||
| 637 | if (itol < 0 ) { | |||
| 638 | goto fail; /* Something didn't work */ | |||
| 639 | } | |||
| 640 | rtol = (double *) PyArray_DATA(ap_rtol); | |||
| 641 | atol = (double *) PyArray_DATA(ap_atol); | |||
| 642 | ||||
| 643 | /* Find size of working arrays*/ | |||
| 644 | if (compute_lrw_liw(&lrw, &liw, neq, jt, ml, mu, mxordn, mxords) < 0) { | |||
| 645 | goto fail; | |||
| 646 | } | |||
| 647 | ||||
| 648 | if ((wa = (double *)malloc(lrw*sizeof(double) + liw*sizeof(F_INTint)))==NULL((void*)0)) { | |||
| 649 | PyErr_NoMemory(); | |||
| 650 | goto fail; | |||
| 651 | } | |||
| 652 | allocated = 1; | |||
| 653 | rwork = wa; | |||
| 654 | iwork = (F_INTint *)(wa + lrw); | |||
| 655 | ||||
| 656 | iwork[0] = ml; | |||
| 657 | iwork[1] = mu; | |||
| 658 | ||||
| 659 | if (h0 != 0.0 || hmax != 0.0 || hmin != 0.0 || ixpr != 0 || mxstep != 0 || | |||
| 660 | mxhnil != 0 || mxordn != 0 || mxords != 0) { | |||
| 661 | rwork[4] = h0; | |||
| 662 | rwork[5] = hmax; | |||
| 663 | rwork[6] = hmin; | |||
| 664 | iwork[4] = ixpr; | |||
| 665 | iwork[5] = mxstep; | |||
| 666 | iwork[6] = mxhnil; | |||
| 667 | iwork[7] = mxordn; | |||
| 668 | iwork[8] = mxords; | |||
| 669 | iopt = 1; | |||
| 670 | } | |||
| 671 | istate = 1; | |||
| 672 | k = t0count; | |||
| 673 | ||||
| 674 | /* If full output make some useful output arrays */ | |||
| 675 | if (full_output) { | |||
| 676 | out_sz = ntimes-1; | |||
| 677 | ap_hu = (PyArrayObject *) PyArray_SimpleNew(1, &out_sz, NPY_DOUBLE)(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) PyArray_API [93])(&(*(PyTypeObject *)PyArray_API[2]), 1, &out_sz, NPY_DOUBLE, ((void*)0), ((void*)0), 0, 0, ((void*)0)); | |||
| 678 | ap_tcur = (PyArrayObject *) PyArray_SimpleNew(1, &out_sz, NPY_DOUBLE)(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) PyArray_API [93])(&(*(PyTypeObject *)PyArray_API[2]), 1, &out_sz, NPY_DOUBLE, ((void*)0), ((void*)0), 0, 0, ((void*)0)); | |||
| 679 | ap_tolsf = (PyArrayObject *) PyArray_SimpleNew(1, &out_sz, NPY_DOUBLE)(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) PyArray_API [93])(&(*(PyTypeObject *)PyArray_API[2]), 1, &out_sz, NPY_DOUBLE, ((void*)0), ((void*)0), 0, 0, ((void*)0)); | |||
| 680 | ap_tsw = (PyArrayObject *) PyArray_SimpleNew(1, &out_sz, NPY_DOUBLE)(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) PyArray_API [93])(&(*(PyTypeObject *)PyArray_API[2]), 1, &out_sz, NPY_DOUBLE, ((void*)0), ((void*)0), 0, 0, ((void*)0)); | |||
| 681 | ap_nst = (PyArrayObject *) PyArray_SimpleNew(1, &out_sz, F_INT_NPY)(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) PyArray_API [93])(&(*(PyTypeObject *)PyArray_API[2]), 1, &out_sz, NPY_INT, ((void*)0), ((void*)0), 0, 0, ((void*)0)); | |||
| 682 | ap_nfe = (PyArrayObject *) PyArray_SimpleNew(1, &out_sz, F_INT_NPY)(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) PyArray_API [93])(&(*(PyTypeObject *)PyArray_API[2]), 1, &out_sz, NPY_INT, ((void*)0), ((void*)0), 0, 0, ((void*)0)); | |||
| 683 | ap_nje = (PyArrayObject *) PyArray_SimpleNew(1, &out_sz, F_INT_NPY)(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) PyArray_API [93])(&(*(PyTypeObject *)PyArray_API[2]), 1, &out_sz, NPY_INT, ((void*)0), ((void*)0), 0, 0, ((void*)0)); | |||
| 684 | ap_nqu = (PyArrayObject *) PyArray_SimpleNew(1, &out_sz, F_INT_NPY)(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) PyArray_API [93])(&(*(PyTypeObject *)PyArray_API[2]), 1, &out_sz, NPY_INT, ((void*)0), ((void*)0), 0, 0, ((void*)0)); | |||
| 685 | ap_mused = (PyArrayObject *) PyArray_SimpleNew(1, &out_sz, F_INT_NPY)(*(PyObject * (*)(PyTypeObject *, int, npy_intp const *, int, npy_intp const *, void *, int, int, PyObject *)) PyArray_API [93])(&(*(PyTypeObject *)PyArray_API[2]), 1, &out_sz, NPY_INT, ((void*)0), ((void*)0), 0, 0, ((void*)0)); | |||
| 686 | if (ap_hu == NULL((void*)0) || ap_tcur == NULL((void*)0) || ap_tolsf == NULL((void*)0) || | |||
| 687 | ap_tsw == NULL((void*)0) || ap_nst == NULL((void*)0) || ap_nfe == NULL((void*)0) || | |||
| 688 | ap_nje == NULL((void*)0) || ap_nqu == NULL((void*)0) || ap_mused == NULL((void*)0)) { | |||
| 689 | goto fail; | |||
| 690 | } | |||
| 691 | } | |||
| 692 | ||||
| 693 | if (o_tcrit != NULL((void*)0)) { | |||
| 694 | /* There are critical points */ | |||
| 695 | itask = 4; | |||
| 696 | tcrit = (double *)(PyArray_DATA(ap_tcrit)); | |||
| 697 | rwork[0] = *tcrit; | |||
| 698 | } | |||
| 699 | while (k < ntimes && istate > 0) { /* loop over desired times */ | |||
| 700 | ||||
| 701 | tout_ptr = tout + k; | |||
| 702 | /* Use tcrit if relevant */ | |||
| 703 | if (itask == 4) { | |||
| 704 | if (!tcrit) { | |||
| 705 | PYERR(odepack_error, "Internal error - tcrit must be defined!"){ PyErr_SetString(odepack_error,"Internal error - tcrit must be defined!" ); goto fail; }; | |||
| 706 | } | |||
| 707 | if (*tout_ptr > *(tcrit + crit_ind)) { | |||
| 708 | crit_ind++; | |||
| 709 | rwork[0] = *(tcrit+crit_ind); | |||
| 710 | } | |||
| 711 | } | |||
| 712 | if (crit_ind >= numcrit) { | |||
| 713 | itask = 1; /* No more critical values */ | |||
| 714 | } | |||
| 715 | ||||
| 716 | LSODAlsoda_(ode_function, &neq, y, &t, tout_ptr, &itol, rtol, atol, &itask, | |||
| 717 | &istate, &iopt, rwork, &lrw, iwork, &liw, | |||
| 718 | ode_jacobian_function, &jt); | |||
| 719 | if (full_output) { | |||
| 720 | *((double *)PyArray_DATA(ap_hu) + (k-1)) = rwork[10]; | |||
| 721 | *((double *)PyArray_DATA(ap_tcur) + (k-1)) = rwork[12]; | |||
| 722 | *((double *)PyArray_DATA(ap_tolsf) + (k-1)) = rwork[13]; | |||
| 723 | *((double *)PyArray_DATA(ap_tsw) + (k-1)) = rwork[14]; | |||
| 724 | *((F_INTint *)PyArray_DATA(ap_nst) + (k-1)) = iwork[10]; | |||
| 725 | *((F_INTint *)PyArray_DATA(ap_nfe) + (k-1)) = iwork[11]; | |||
| 726 | *((F_INTint *)PyArray_DATA(ap_nje) + (k-1)) = iwork[12]; | |||
| 727 | *((F_INTint *)PyArray_DATA(ap_nqu) + (k-1)) = iwork[13]; | |||
| 728 | if (istate == -5 || istate == -4) { | |||
| 729 | imxer = iwork[15]; | |||
| 730 | } | |||
| 731 | else { | |||
| 732 | imxer = -1; | |||
| 733 | } | |||
| 734 | lenrw = iwork[16]; | |||
| 735 | leniw = iwork[17]; | |||
| 736 | *((F_INTint *)PyArray_DATA(ap_mused) + (k-1)) = iwork[18]; | |||
| 737 | } | |||
| 738 | if (PyErr_Occurred()) { | |||
| 739 | goto fail; | |||
| 740 | } | |||
| 741 | memcpy(yout_ptr, y, neq*sizeof(double)); /* copy integration result to output*/ | |||
| 742 | yout_ptr += neq; | |||
| 743 | k++; | |||
| 744 | } | |||
| 745 | ||||
| 746 | /* Restore global_params from the previously stashed save_params. */ | |||
| 747 | memcpy(&global_params, &save_params, sizeof(save_params)); | |||
| 748 | ||||
| 749 | Py_DECREF(extra_args)_Py_DECREF(((PyObject*)(extra_args))); | |||
| 750 | Py_DECREF(ap_atol)_Py_DECREF(((PyObject*)(ap_atol))); | |||
| 751 | Py_DECREF(ap_rtol)_Py_DECREF(((PyObject*)(ap_rtol))); | |||
| 752 | Py_XDECREF(ap_tcrit)_Py_XDECREF(((PyObject*)(ap_tcrit))); | |||
| 753 | Py_DECREF(ap_y)_Py_DECREF(((PyObject*)(ap_y))); | |||
| 754 | Py_DECREF(ap_tout)_Py_DECREF(((PyObject*)(ap_tout))); | |||
| 755 | free(wa); | |||
| 756 | ||||
| 757 | /* Do Full output */ | |||
| 758 | if (full_output) { | |||
| 759 | return Py_BuildValue("N{s:N,s:N,s:N,s:N,s:N,s:N,s:N,s:N,s:l,s:l,s:l,s:N}l", | |||
| 760 | PyArray_Return(*(PyObject * (*)(PyArrayObject *)) PyArray_API[76])(ap_yout), | |||
| 761 | "hu", PyArray_Return(*(PyObject * (*)(PyArrayObject *)) PyArray_API[76])(ap_hu), | |||
| 762 | "tcur", PyArray_Return(*(PyObject * (*)(PyArrayObject *)) PyArray_API[76])(ap_tcur), | |||
| 763 | "tolsf", PyArray_Return(*(PyObject * (*)(PyArrayObject *)) PyArray_API[76])(ap_tolsf), | |||
| 764 | "tsw", PyArray_Return(*(PyObject * (*)(PyArrayObject *)) PyArray_API[76])(ap_tsw), | |||
| 765 | "nst", PyArray_Return(*(PyObject * (*)(PyArrayObject *)) PyArray_API[76])(ap_nst), | |||
| 766 | "nfe", PyArray_Return(*(PyObject * (*)(PyArrayObject *)) PyArray_API[76])(ap_nfe), | |||
| 767 | "nje", PyArray_Return(*(PyObject * (*)(PyArrayObject *)) PyArray_API[76])(ap_nje), | |||
| 768 | "nqu", PyArray_Return(*(PyObject * (*)(PyArrayObject *)) PyArray_API[76])(ap_nqu), | |||
| 769 | "imxer", imxer, | |||
| 770 | "lenrw", lenrw, | |||
| 771 | "leniw", leniw, | |||
| 772 | "mused", PyArray_Return(*(PyObject * (*)(PyArrayObject *)) PyArray_API[76])(ap_mused), | |||
| 773 | (long)istate); | |||
| 774 | } | |||
| 775 | else { | |||
| 776 | return Py_BuildValue("Nl", PyArray_Return(*(PyObject * (*)(PyArrayObject *)) PyArray_API[76])(ap_yout), (long)istate); | |||
| 777 | } | |||
| 778 | ||||
| 779 | fail: | |||
| 780 | /* Restore global_params from the previously stashed save_params. */ | |||
| 781 | memcpy(&global_params, &save_params, sizeof(save_params)); | |||
| 782 | ||||
| 783 | Py_XDECREF(extra_args)_Py_XDECREF(((PyObject*)(extra_args))); | |||
| 784 | Py_XDECREF(ap_y)_Py_XDECREF(((PyObject*)(ap_y))); | |||
| 785 | Py_XDECREF(ap_rtol)_Py_XDECREF(((PyObject*)(ap_rtol))); | |||
| 786 | Py_XDECREF(ap_atol)_Py_XDECREF(((PyObject*)(ap_atol))); | |||
| 787 | Py_XDECREF(ap_tcrit)_Py_XDECREF(((PyObject*)(ap_tcrit))); | |||
| 788 | Py_XDECREF(ap_tout)_Py_XDECREF(((PyObject*)(ap_tout))); | |||
| 789 | Py_XDECREF(ap_yout)_Py_XDECREF(((PyObject*)(ap_yout))); | |||
| 790 | if (allocated) { | |||
| 791 | free(wa); | |||
| 792 | } | |||
| 793 | if (full_output) { | |||
| 794 | Py_XDECREF(ap_hu)_Py_XDECREF(((PyObject*)(ap_hu))); | |||
| 795 | Py_XDECREF(ap_tcur)_Py_XDECREF(((PyObject*)(ap_tcur))); | |||
| 796 | Py_XDECREF(ap_tolsf)_Py_XDECREF(((PyObject*)(ap_tolsf))); | |||
| 797 | Py_XDECREF(ap_tsw)_Py_XDECREF(((PyObject*)(ap_tsw))); | |||
| 798 | Py_XDECREF(ap_nst)_Py_XDECREF(((PyObject*)(ap_nst))); | |||
| 799 | Py_XDECREF(ap_nfe)_Py_XDECREF(((PyObject*)(ap_nfe))); | |||
| 800 | Py_XDECREF(ap_nje)_Py_XDECREF(((PyObject*)(ap_nje))); | |||
| 801 | Py_XDECREF(ap_nqu)_Py_XDECREF(((PyObject*)(ap_nqu))); | |||
| 802 | Py_XDECREF(ap_mused)_Py_XDECREF(((PyObject*)(ap_mused))); | |||
| 803 | } | |||
| 804 | return NULL((void*)0); | |||
| 805 | } | |||
| 806 | ||||
| 807 | ||||
| 808 | static struct PyMethodDef odepack_module_methods[] = { | |||
| 809 | {"odeint", (PyCFunction) odepack_odeint, METH_VARARGS0x0001|METH_KEYWORDS0x0002, doc_odeint}, | |||
| 810 | {NULL((void*)0), NULL((void*)0), 0, NULL((void*)0)} | |||
| 811 | }; | |||
| 812 | ||||
| 813 | static struct PyModuleDef moduledef = { | |||
| 814 | PyModuleDef_HEAD_INIT{ { 1, ((void*)0) }, ((void*)0), 0, ((void*)0), }, | |||
| 815 | "_odepack", | |||
| 816 | NULL((void*)0), | |||
| 817 | -1, | |||
| 818 | odepack_module_methods, | |||
| 819 | NULL((void*)0), | |||
| 820 | NULL((void*)0), | |||
| 821 | NULL((void*)0), | |||
| 822 | NULL((void*)0) | |||
| 823 | }; | |||
| 824 | ||||
| 825 | PyObject * | |||
| 826 | PyInit__odepack(void) | |||
| 827 | { | |||
| 828 | PyObject *m, *d, *s; | |||
| 829 | ||||
| 830 | m = PyModule_Create(&moduledef)PyModule_Create2(&moduledef, 1013); | |||
| ||||
| ||||
| 831 | import_array(){if (_import_array() < 0) {PyErr_Print(); PyErr_SetString( PyExc_ImportError, "numpy.core.multiarray failed to import"); return ((void*)0); } }; | |||
| 832 | d = PyModule_GetDict(m); | |||
| 833 | ||||
| 834 | s = PyUnicode_FromString(" 1.9 "); | |||
| 835 | PyDict_SetItemString(d, "__version__", s); | |||
| 836 | odepack_error = PyErr_NewException ("odepack.error", NULL((void*)0), NULL((void*)0)); | |||
| 837 | Py_DECREF(s)_Py_DECREF(((PyObject*)(s))); | |||
| 838 | PyDict_SetItemString(d, "error", odepack_error); | |||
| 839 | if (PyErr_Occurred()) { | |||
| 840 | Py_FatalError("can't initialize module odepack"); | |||
| 841 | } | |||
| 842 | return m; | |||
| 843 | } |
| 1 | #ifndef PyModule_Create2 |
| 2 | struct _object; |
| 3 | typedef struct _object PyObject; |
| 4 | PyObject* clang_analyzer_PyObject_New_Reference(); |
| 5 | PyObject* PyModule_Create2(PyModuleDef *def, int module_api_version) { |
| 6 | return clang_analyzer_PyObject_New_Reference(); |
| 7 | } |
| 8 | #else |
| 9 | #warning "API PyModule_Create2 is defined as a macro." |
| 10 | #endif |