我正在嘗試從Fortran中調用GSL rountine CQUAD。我的想法是編寫一個調用gsl rountine的.c子例程,並依賴於函數和邊界。兩個問題:我對c和fortrans的iso_c_binding知之甚少。我嘗試如下:從Fortran調用GSL例程CQUAD
一個簡單的調用程序(在No output from a Fortran program using the Gnu Scientific Library via a c wrapper類似MSB的職位):
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(http://www.lrz.de/services/software/mathematik/gsl/fortran/)。它是完整的(包括cquad),並且效果很好。 – 2014-11-03 00:50:44
@ViniciusMiranda它解決了,但是當一個簡單的接口塊就足夠了,我去爲它而不是安裝完整的軟件包。同樣,我使用我自己的非常簡單的接口'pthread_create'和'pthread_join',而不是使用現有的Fortran POSIX包,研究其安裝並將其保存在需要我的代碼編譯的所有計算機上。 – 2014-11-03 09:08:43
@ViniciusMiranda謝謝,這肯定是首先想到的。但是,在編譯fgsl時,所有例程的make check都失敗了。到目前爲止,筆者沒有回答我的問題。正如Vladimir F所說,對於一個例行公事,我不認爲需要安裝一個完整的軟件包。除此之外,我喜歡有更多的控制權,特別是如果標準軟件包有bug的話。 – PeMa 2014-11-03 13:02:13