研发Fortran 调用 [英] R & Fortran call

查看:11
本文介绍了研发Fortran 调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我没有使用 Fortran 的经验,但我试图通过 .Fortran() 函数从 R 调用它来运行该语言的一个非常简单的循环.每当我运行粘贴在下面的 R 代码的最后一行时,R gui 崩溃并且我没有得到任何结果.我有兴趣将实值 x 的向量从 Fortran 带回 R 以进行进一步分析.g 为 0 到 1 之间的数值,n 为整数,均由 R 中的用户提供.

I don't have experience with Fortran, but I am trying to run a very simple loop in that language by calling it from R via the .Fortran() function. Whenever I run the last line of the R code that is pasted below, the R gui crashes and I get no result. I am interest in bringing back the vector of real values x from Fortran into R for further analysis. g is a numeric value between 0 and 1, and n an integer, and they are both supplied by the user in R.

任何帮助将不胜感激!最好的,

Any help would be much appreciated! Best,

文森特

在 bar.f 中保存的 Fortran 代码:

Fortran code saved in bar.f:

    subroutine bar(n, g, x)

      integer n
      double precision g
      double precision x(n)
      integer i
      x(1)=1
      do 100 i = 2, n
          x(i) = x(i-1) * g + 1
  100 continue

      end

在 Cygwin 中使用 gfortran 编译 DLL:

Compiling the DLL in Cygwin with gfortran:

gfortran -shared -obar.dll bar.f

R 代码:

dyn.load("d:/bar.dll")
is.loaded("bar")
.Fortran("bar", n=as.integer(15), g=as.double(5), x=as.double(rnorm(5)))

推荐答案

当我编译你的代码时,我可以执行一次对 .Fortran 的调用.当我第二次运行它时,它崩溃了.但是,我注意到,如果我使传递给 x 的向量与传递给 n 的整数的长度相同,建议它应该是,即:

When I compile your code, I can execute the call to .Fortran once. When I run it a second time, it crashes. However, I noticed that if I make the vector passed for x the same length as the integer passed for n suggests it should be, i.e:

.Fortran('bar', n = as.integer(15), g = as.double (5), x = as.double(rnorm(15)) )

我可以根据需要多次运行该函数.所以问题可能是你告诉 Fortran 例程它有一个长度为 15 的向量可以使用,但只发送一个长度为 5 的向量.这可能导致 Fortran 例程访问它不应该访问的内存可以解释崩溃.

I can run the function as many times as I want. So the problem may be that you are telling the Fortran routine it has a vector of length 15 to work with, but are only sending in a vector of length 5. This could be causing the Fortran routine to access memory it is not supposed to which would explain a crash.

由于看起来您无论如何都在例程中生成 x 的所有值,因此您可以跳过生成随机数并使用 R 的 double(n) 函数,其中 n 是要生成的空向量的长度:

Since it looks like you are generating all values of x in the routine anyway, you could skip generating random numbers and just send in an empty vector using R's double(n) function, where n is the length of the empty vector you want to generate:

.Fortran('bar', n = as.integer(15), g = as.double(5), x = double(15))

integercharacter 是有用的函数,它们返回像 double 这样的向量.

integer and character are useful functions that return vectors like double.

还有一些关于 Fortran 风格的友好建议,因为您提到您刚刚开始使用该语言:

Also some friendly suggestions concerning Fortran style since you mention you are just getting started with the language:

  • 使用 .f90 扩展名命名文件可能是明智的——大多数编译器假定以 .f 结尾的文件遵循旧的固定格式"格式,它是一种 PITA,因为它被设计用于打孔卡.

  • It might be wise to name your files with a .f90 extension---files ending in .f are assumed by most compilers to adhere to the old "fixed-form" format which is a PITA as it was designed to be used on punch cards.

Do 100 ... 100 continue 语句是 Fortran 77 中结束循环的一种风格.现代的等价物是 Do .. 结束做.

The Do 100 ... 100 continue statements are an style of ending loops in Fortran 77. The modern equivalent is Do .. end do.

对于 Fortran 函数和子例程,明智的做法是声明传入和传出例程的变量的意图".可用的意图声明是:

With Fortran functions and subroutines, it is wise to declare the "intent" of variables passing in and out of the routine. The available intent declarations are:

  • intent(in):表示仅作为输入进入例程的变量.一旦进入例程,它们应该被视为参数,如果尝试更改它们,编译器将引发错误.

  • intent(in): Signifies variables that are entering the routine only as inputs. Once inside the routine, they should be treated as parameters and the compiler will raise an error if any attempt is made to change them.

intent(out):表示其值应在例程内生成的变量作为输出.如果在例程中未分配意图输出变量,编译器将发出警告.

intent(out): Signifies variables whose values should be generated inside the routine as outputs. The compiler will issue a warning if an intent out variable is not assigned within the routine.

intent(inout):表示可以携带一组值进入例程并以不同值离开例程的变量.

intent(inout): Signifies variables that may enter the routine carrying a certain set of values and leave the routine with different values.

在变量上设置意图将帮助编译器生成警告和错误,从而为您节省一些寻找错误的时间.

Setting intents on variables will help the compiler generate warnings and errors that may save you some bug hunting.

Fortran 有一个默认行为,即任何未在例程头中声明的变量,如果其名称以 i-n 开头,则为整数,否则为实数.这可能会导致拼写错误的变量名称神奇地"成为变量,而编译器不会注意到或告诉您.在您的例程顶部设置 implicit none 会禁用此行为,并允许编译器通知您可能很难追踪的错误.

Fortran has a default behavior where any variable not declared in the header of the routine will be an integer if its name starts with i-n and real otherwise. This can cause misspelled variable names to "magically" become variables without the compiler batting an eye or telling you. Setting implicit none at the top of your routines disables this behavior and allows the compiler to notify you of mistakes that can be very hard to track down otherwise.

将这些建议考虑在内的子例程版本如下所示:

A version of your subroutine that takes these suggestions into account would look like the following:

subroutine bar(n, g, x)
  implicit none

  integer, intent(in):: n
  double precision, intent(in):: g
  double precision, intent(inout):: x(n)

  integer:: i

  x(1) = 1
  do i = 2, n
    x(i) = x(i - 1) * g + 1
  end do

end subroutine bar

此外,让 R 使用 R CMDSHLIB 子命令来编译库也很有用:

Also, it is useful to let R compile your libraries using the SHLIB subcommand of R CMD:

R CMD SHLIB -o bar.dll bar.f90

这将针对包含有用功能的 R 库编译您的程序,例如 BLAS 例程、统计例程和可以将信息打印到 R 控制台的方法.请参阅编写 R 扩展,第 6 节了解更多信息.

This will compile your programs against the R libraries which contain useful functions---such as BLAS routines, stats routines and methods that can print information to the R console. See Writing R Extensions, Section 6 for more info.

希望这会有所帮助!

这篇关于研发Fortran 调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆