[英]How to handle error in integration in GSL
我正在编写需要真正快速地计算大量积分的python代码,因此,不是使用c
函数使用scipy.integrate
,而是使用ctypes
计算c
所有积分。
我使用以下代码导入c函数:
ctypes.CDLL('/usr/lib/i386-linux-gnu/libgslcblas.so', mode=ctypes.RTLD_GLOBAL)
ctypes.CDLL('/usr/lib/i386-linux-gnu/libgsl.so', mode=ctypes.RTLD_GLOBAL)
lib = ctypes.CDLL('/home/aurelien/Desktop/Project/within_opt_model_1/integral_test.so')
在c中,我使用以下公式计算积分:
gsl_integration_workspace *w = gsl_integration_workspace_alloc(200);
double result, err;
gsl_function F;
F.function = &integral;
F.params = ¶ms;
gsl_integration_qags(&F, z, 1, 1e-6, 1e-6, 200, w, &result, &err);
gsl_integration_workspace_free(w);
问题是,有时(〜5%的时间),由于我的积分正在缓慢收敛,它将杀死我的程序并打印:
gsl: qags.c:563: ERROR: interval is divergent, or slowly convergent
Default GSL error handler invoked
Aborted (core dumped)
如果我使用1e-10
而不是1e-6
,则不会发生此问题,但会使积分计算变慢得多。
我想要一种方法来try, catch
以便在大多数情况下使用1e-6
并快速进行,而在失败时使用1e-10
。
我试着做:
int status = gsl_integration_qags(&F, z, 1, 1e-6, 1e-6, 200, w, &result, &err);
printf("%i\n", status);
但这只会显示0,因为错误会在返回任何值之前中止。
我的猜测是我需要创建自己的错误处理程序方法,但是我不知道该怎么做。
非常感谢你! (如果有帮助,我可以向您展示更多代码,我试图使所有内容保持简洁)。
您需要做的就是通过设置自己的错误处理程序
https://www.gnu.org/software/gsl/doc/html/err.html#c.gsl_set_error_handler
参见例如带有ctypes的回调(如何从C调用python函数)如何声明适当的回调并将其传递。
默认处理程序中止(如上面的文档链接中所述),但是当然不这样做是您的特权:)
来自GCC GSL:
错误处理程序
GSL错误处理程序的默认行为是打印一条短消息并调用abort()。 使用此默认值时,每当库例程报告错误时,程序都将通过core-dump停止。 对于不检查库例程的返回状态的程序,这是作为故障安全默认值(我们不鼓励您以这种方式编写程序)。
您可以调用gsl_set_error_handler_off()
禁用默认错误处理程序(此函数通过定义不执行任何操作的错误处理程序来关闭错误处理程序)。
我认为以下将完成工作
gsl_set_error_handler_off()
gsl_integration_workspace *w = gsl_integration_workspace_alloc(200);
double result, err;
gsl_function F;
F.function = &integral;
F.params = ¶ms;
int status = gsl_integration_qags(&F, z, 1, 1e-6, 1e-6, 200, w, &result, &err);
if(status == GSL_EDIVERGE){
status = gsl_integration_qags(&F, z, 1, 1e-10, 1e-10, 200, w, &result, &err);
/*handle other errors here...*/
}
gsl_integration_workspace_free(w);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.