【发布时间】:2014-11-02 18:12:39
【问题描述】:
我正在尝试从 Fortran 调用 GSL 常规 CQUAD。我的想法是编写一个 .c 子例程,它调用 gsl 例程并依赖于函数和边界。两个问题:我对 c 和 fortrans iso_c_binding 知之甚少。我的尝试如下:
一个简单的调用程序(类似于MSB在No output from a Fortran program using the Gnu Scientific Library via a c wrapper的帖子):
program test
use iso_c_binding
interface
function my_cquad (f,a,b) bind(c)
import
real (kind=c_double) :: my_cquad
interface
function f(x) bind(c)
import
real(kind=c_double) :: f,x
end function
end interface
real (kind=c_double) :: a,b
end function my_cquad
end interface
real (kind=c_double) :: y,a,b
a=0. ; b=1.
y=my_cquad(g,a,b)
print*,y
stop
contains
function g(x) bind(C)
real(kind=c_double) :: g,x
g=sin(x)/x
return
end function g
end program test
.c子程序(基本上取自CQUAD作者在https://scicomp.stackexchange.com/questions/4730/numerical-integration-handling-nans-c-fortran中给出的例子):
#include <stdio.h>
#include <gsl/gsl_integration.h>
double my_cquad ( double my_f() , double a , double b )
{
gsl_function f;
gsl_integration_cquad_workspace *ws = NULL;
double res, abserr;
size_t neval;
/* Prepare the function. */
f.function = my_f;
f.params = NULL;
/* Initialize the workspace. */
if ( ( ws = gsl_integration_cquad_workspace_alloc( 200 ) ) == NULL ) {
printf( "call to gsl_integration_cquad_workspace_alloc failed.\n" );
abort();
}
/* Call the integrator. */
if ( gsl_integration_cquad( &f, a , b , 1.0e-10 , 1.0e-10 , ws , &res , &abserr , &neval ) != 0 ) {
printf( "call to gsl_integration_cquad failed.\n" );
abort();
}
/* Free the workspace. */
gsl_integration_cquad_workspace_free( ws );
/* Bye. */
return res;
}
单独的 .c 子例程似乎工作正常。这可以通过以下方式进行测试:
double g (double x)
{
return sin(x)/x;
}
int main () {
double y;
y=my_cquad(g,0.,1.);
printf("y: %2.18f\n", y);
return 0;
}
但是与 .f90 调用程序一起,在它编译的那一刻,但在运行时我得到了一个我不太明白的分段错误。
此外,拥有某种根据 fortran 类型函数创建 c 类型函数的包装器当然会很好。我正在考虑类似的事情:
function f_to_c(f) bind(c)
real(kind=c_double) :: f_to_c
real(kind=8) :: f
f_to_c=real(f,kind=c_double)
end function
但这并不涵盖虚拟变量。
提前感谢,非常抱歉代码量。
【问题讨论】:
-
不要重新发明轮子:使用 fgsl (lrz.de/services/software/mathematik/gsl/fortran)。它是完整的(包括 cquad)并且效果很好。
-
@ViniciusMiranda 它依赖,但是当一个简单的接口块就足够时,我会选择它而不是安装完整的包。同样的方式,我使用我自己的非常简单的接口
pthread_create和pthread_join,而不是使用现有的 Fortran POSIX 包,研究它的安装并在我需要我的代码编译的所有计算机上维护它。 -
@ViniciusMiranda 谢谢,这肯定是首先想到的。但是由于尚不清楚的原因
make check在编译 fgsl 时所有例程都失败了。到目前为止,作者还没有回答我的问题。正如 Vladimir F 所说,对于一个例程,我认为不需要安装完整的软件包。另外,我喜欢有更多的控制,特别是如果标准包有错误。 -
函数
my_f是一个函数指针,对吧?我对它的声明为double my_f()有点困惑。为什么会这样?