/* callback to pass to DODRC; calls the Python function in the global structure |odr_global| */ void fcn_callback(int *n, int *m, int *np, int *nq, int *ldn, int *ldm, int *ldnp, double *beta, double *xplusd, int *ifixb, int *ifixx, int *ldfix, int *ideval, double *f, double *fjacb, double *fjacd, int *istop) { PyObject *arg01, *arglist; PyObject *result; PyArrayObject *result_array = NULL; PyArrayObject *pyXplusD; arg01 = PyTuple_New(2); if (*m != 1) { npy_intp dim2[2]; dim2[0] = *m; dim2[1] = *n; pyXplusD = (PyArrayObject *) PyArray_SimpleNew(2, dim2, NPY_DOUBLE); memcpy(pyXplusD->data, (void *)xplusd, (*m) * (*n) * sizeof(double)); } else { npy_intp dim1[1]; dim1[0] = *n; pyXplusD = (PyArrayObject *) PyArray_SimpleNew(1, dim1, NPY_DOUBLE); memcpy(pyXplusD->data, (void *)xplusd, (*n) * sizeof(double)); } PyTuple_SetItem(arg01, 0, odr_global.pyBeta); Py_INCREF(odr_global.pyBeta); PyTuple_SetItem(arg01, 1, (PyObject *) pyXplusD); Py_INCREF((PyObject *) pyXplusD); if (odr_global.extra_args != NULL) { arglist = PySequence_Concat(arg01, odr_global.extra_args); } else { arglist = PySequence_Tuple(arg01); /* make a copy */ } Py_DECREF(arg01); *istop = 0; memcpy(((PyArrayObject *) (odr_global.pyBeta))->data, (void *)beta, (*np) * sizeof(double)); if ((*ideval % 10) >= 1) { /* compute f with odr_global.fcn */ if (odr_global.fcn == NULL) { /* we don't have a function to call */ PYERR2(odr_error, "Function has not been initialized"); } if ((result = PyEval_CallObject(odr_global.fcn, arglist)) == NULL) { PyObject *tmpobj, *str1; if (PyErr_ExceptionMatches(odr_stop)) { /* stop, don't fail */ *istop = 1; Py_DECREF(arglist); return; } PyErr_Print(); tmpobj = PyObject_GetAttrString(odr_global.fcn, "func_name"); if (tmpobj == NULL) goto fail; str1 = PyString_FromString ("Error occurred while calling the Python function named "); if (str1 == NULL) { Py_DECREF(tmpobj); goto fail; } PyString_ConcatAndDel(&str1, tmpobj); PyErr_SetString(odr_error, PyString_AsString(str1)); Py_DECREF(str1); goto fail; } if ((result_array = (PyArrayObject *) PyArray_ContiguousFromObject(result, NPY_DOUBLE, 0, 2)) == NULL) { PYERR2(odr_error, "Result from function call is not a proper array of floats."); } memcpy((void *)f, result_array->data, (*n) * (*nq) * sizeof(double)); Py_DECREF(result_array); } if (((*ideval) / 10) % 10 >= 1) { /* compute fjacb with odr_global.fjacb */ if (odr_global.fjacb == NULL) { /* we don't have a function to call */ PYERR2(odr_error, "Function has not been initialized"); } if ((result = PyEval_CallObject(odr_global.fjacb, arglist)) == NULL) { PyObject *tmpobj, *str1; if (PyErr_ExceptionMatches(odr_stop)) { /* stop, don't fail */ *istop = 1; Py_DECREF(arglist); return; } PyErr_Print(); tmpobj = PyObject_GetAttrString(odr_global.fjacb, "func_name"); if (tmpobj == NULL) goto fail; str1 = PyString_FromString ("Error occurred while calling the Python function named "); if (str1 == NULL) { Py_DECREF(tmpobj); goto fail; } PyString_ConcatAndDel(&str1, tmpobj); PyErr_SetString(odr_error, PyString_AsString(str1)); Py_DECREF(str1); goto fail; } if ((result_array = (PyArrayObject *) PyArray_ContiguousFromObject(result, NPY_DOUBLE, 0, 2)) == NULL) { PYERR2(odr_error, "Result from function call is not a proper array of floats."); } if (*nq != 1 && *np != 1) { /* result_array should be rank-3 */ if (result_array->nd != 3) { Py_DECREF(result_array); PYERR2(odr_error, "Beta Jacobian is not rank-3"); } } else if (*nq == 1) { /* result_array should be rank-2 */ if (result_array->nd != 2) { Py_DECREF(result_array); PYERR2(odr_error, "Beta Jacobian is not rank-2"); } } memcpy((void *)fjacb, result_array->data, (*n) * (*nq) * (*np) * sizeof(double)); Py_DECREF(result_array); } if (((*ideval) / 100) % 10 >= 1) { /* compute fjacd with odr_global.fjacd */ if (odr_global.fjacd == NULL) { /* we don't have a function to call */ PYERR2(odr_error, "fjcad has not been initialized"); } if ((result = PyEval_CallObject(odr_global.fjacd, arglist)) == NULL) { PyObject *tmpobj, *str1; if (PyErr_ExceptionMatches(odr_stop)) { /* stop, don't fail */ *istop = 1; Py_DECREF(arglist); return; } PyErr_Print(); tmpobj = PyObject_GetAttrString(odr_global.fjacd, "func_name"); if (tmpobj == NULL) goto fail; str1 = PyString_FromString ("Error occurred while calling the Python function named "); if (str1 == NULL) { Py_DECREF(tmpobj); goto fail; } PyString_ConcatAndDel(&str1, tmpobj); PyErr_SetString(odr_error, PyString_AsString(str1)); Py_DECREF(str1); goto fail; } if ((result_array = (PyArrayObject *) PyArray_ContiguousFromObject(result, NPY_DOUBLE, 0, 2)) == NULL) { PYERR2(odr_error, "Result from function call is not a proper array of floats."); } if (*nq != 1 && *m != 1) { /* result_array should be rank-3 */ if (result_array->nd != 3) { Py_DECREF(result_array); PYERR2(odr_error, "xplusd Jacobian is not rank-3"); } } else if (*nq == 1 && *m != 1) { /* result_array should be rank-2 */ if (result_array->nd != 2) { Py_DECREF(result_array); PYERR2(odr_error, "xplusd Jacobian is not rank-2"); } } else if (*nq == 1 && *m == 1) { /* result_array should be rank-1 */ if (result_array->nd != 1) { Py_DECREF(result_array); PYERR2(odr_error, "xplusd Jacobian is not rank-1"); } } memcpy((void *)fjacd, result_array->data, (*n) * (*nq) * (*m) * sizeof(double)); Py_DECREF(result_array); } Py_DECREF(result); Py_DECREF(arglist); Py_DECREF(pyXplusD); return; fail: Py_XDECREF(result); Py_XDECREF(arglist); Py_XDECREF(pyXplusD); *istop = -1; return; }
int setup_extra_inputs(PyArrayObject **ap_rtol, PyObject *o_rtol, PyArrayObject **ap_atol, PyObject *o_atol, PyArrayObject **ap_tcrit, PyObject *o_tcrit, int *numcrit, int neq) { int itol = 0; double tol = 1.49012e-8; npy_intp one = 1; /* Setup tolerances */ if (o_rtol == NULL) { *ap_rtol = (PyArrayObject *) PyArray_SimpleNew(1, &one, NPY_DOUBLE); if (*ap_rtol == NULL) { PYERR2(odepack_error,"Error constructing relative tolerance."); } *(double *) PyArray_DATA(*ap_rtol) = tol; /* Default */ } else { *ap_rtol = (PyArrayObject *) PyArray_ContiguousFromObject(o_rtol, NPY_DOUBLE, 0, 1); if (*ap_rtol == NULL) { PYERR2(odepack_error,"Error converting relative tolerance."); } /* XXX Fix the following. */ if (PyArray_NDIM(*ap_rtol) == 0); /* rtol is scalar */ else if (PyArray_DIMS(*ap_rtol)[0] == neq) { itol |= 2; /* Set rtol array flag */ } else { PYERR(odepack_error, "Tolerances must be an array of the same length as the\n number of equations or a scalar."); } } if (o_atol == NULL) { *ap_atol = (PyArrayObject *) PyArray_SimpleNew(1, &one, NPY_DOUBLE); if (*ap_atol == NULL) { PYERR2(odepack_error,"Error constructing absolute tolerance"); } *(double *)PyArray_DATA(*ap_atol) = tol; } else { *ap_atol = (PyArrayObject *) PyArray_ContiguousFromObject(o_atol, NPY_DOUBLE, 0, 1); if (*ap_atol == NULL) { PYERR2(odepack_error,"Error converting absolute tolerance."); } /* XXX Fix the following. */ if (PyArray_NDIM(*ap_atol) == 0); /* atol is scalar */ else if (PyArray_DIMS(*ap_atol)[0] == neq) { itol |= 1; /* Set atol array flag */ } else { PYERR(odepack_error,"Tolerances must be an array of the same length as the\n number of equations or a scalar."); } } itol++; /* increment to get correct value */ /* Setup t-critical */ if (o_tcrit != NULL) { *ap_tcrit = (PyArrayObject *) PyArray_ContiguousFromObject(o_tcrit, NPY_DOUBLE, 0, 1); if (*ap_tcrit == NULL) { PYERR2(odepack_error,"Error constructing critical times."); } *numcrit = PyArray_Size((PyObject *) (*ap_tcrit)); } return itol; fail: /* Needed for use of PYERR */ return -1; }