【问题标题】:How does one insert fortran code from an external file into a separate code?如何将外部文件中的 fortran 代码插入到单独的代码中?
【发布时间】:2017-04-02 21:08:02
【问题描述】:

我想让我的代码获取在另一个文档中编写的代码,阅读它,然后像在代码中一样使用它。假设我们有以下内容:

MODULE samplemod
CONTAINS  
  FUNCTION sillysum(boudary,function) RESULT(counter)
    IMPLICIT NONE
    REAL(KIND=8) :: boundary, counter
    REAL(KIND=8), DIMENSION(:) :: function
    INTEGER :: m
    counter = 0.d0
    DO m = 1, my_mesh%me
      counter = function(m) + externalfunction
    END DO
  END FUNCTION sillysum
END MODULE samplemod

PROGRAM sampleprogram
  USE samplemod
  REAL(KIND=8), DIMENSION(:) :: function1
  ALLOCATE(function1(100))
  DO m=1, 100
     function1(i) = i
  END DO
  WRITE(*,*) sillysum(100,function1)    
END PROGRAM sampleprogram

在某个外部文件(比如“externfunct.txt”)中,有人写了m**2。 Fortran 代码如何读取外部函数m**2SIN(m) 甚至0 并替换externalfunction。这是一个更简单的例子:

REAL(KIND=8) :: x = 2
CHARACTER(LEN=*) :: strng = "external"
WRITE(*,*) "Hello world, 2 + ", strng, " = ", 2 + external

在我写的 txt 文件中我写了SIN(x)

【问题讨论】:

  • 你的意思是在编译时还是在运行时?这是两种截然不同的情况。
  • 你问题开头的代码块肯定是完全错误的。 kind=8 也非常丑陋且不便携。这并不意味着所有编译器都是 8 个字节。
  • this sort of thing,但这可能不是你的意思。
  • 我希望在运行时完成。这样我就不必每次想要更改函数时都筛选代码,也不必编译它。 “丑陋且不便携”是什么意思?你会推荐什么?
  • 我询问了语言选择,因为我认为解释性语言(例如 python)可能更适合这项任务。

标签: function include fortran external


【解决方案1】:

我认为对此有两种不同的方法(* 事实上,似乎还有“第三种”方法,请参阅编辑);一种是使用共享库,另一种是使用解析器进行数学表达式。例如,第一种方法在 Rossetastone 页面 (Call a function in a shared library) 和 SO 页面 (Fortran dynamic libraries, load at runtime?) 中进行了描述。对于第二种方法,您可以通过搜索“数学解析器”或“Fortran 数学解析器”等找到第三方库。在这里,我尝试了this one,因为它看起来很简单(只有一个模块,没有安装)。如果我们像这样写一个简单的测试程序

program test
    use interpreter, only: init, evaluate, dp => realkind
    implicit none
    integer, parameter :: mxvars = 10   !! consider 10 variables at most here
    character(10)      :: symbols( mxvars )
    real(dp)           :: values( mxvars ), answer
    character(1000)    :: funcstr  !! a user-defined math expression
    character(5)       :: stat

!> Define variable names.
    symbols( 1 ) = "x"
    symbols( 2 ) = "a"
    symbols( 3 ) = "b"
    symbols( 4 ) = "c"
    symbols( 5 ) = "foo"

!> Get a math expression.
    print *, "Please input a math expression:"
    read(*, "(a)") funcstr    !! e.g., a * x + b

!> Init the evaluator.
    call init( funcstr, symbols, stat )
    if ( stat /= "ok" ) stop "stat /= ok"

!> Set values for the variables.
    values( : ) = 0
    values( 1 ) = 2.0_dp   ! x
    values( 2 ) = 10.0_dp  ! a
    values( 3 ) = 7.0_dp   ! b

!> Evaluate.
    answer = evaluate( values )
    print *, "function value = ", answer

end program

编译成(*1)

$ gfortran -ffree-line-length-none interpreter.f90 mytest.f90

我们可以测试各种表达式如下:

$ ./a.out
 Please input a math expression:
a * x + b
 function value =    27.000000000000000
$ ./a.out
 Please input a math expression:
sin( a * x ) + cos( b ) + foo
 function value =    1.6668475050709324

其他库的用法似乎也很相似。因为每个库的性能可能会有很大差异,所以尝试几个不同的库进行比较可能会很有用。


(*1) 该模块有一些带有sindcosdtand 的行,但gfortran 不支持它们。因此,为了编译,我将它们注释掉并替换为stop,即,

stop "sind not supported..."
! pdata(st) = sind(pdata(st))

(我猜sind(x) 的意思是sin( x * pi / 180 ),所以可以这样定义。)


[编辑]

“第三种”方法可能是通过system(),例如this SO page,在Python 或Julia 等解释语言中调用内置eval() 函数。虽然这也有很多弱点(直接使用这些语言可能更容易),但从 Fortran 调用 eval() 可能对某些特定目的有用。

【讨论】:

  • 有没有办法解释字符串输入以在程序中使用?这需要一个字符串并提供一个数字。例如,假设我有一个时间推进模拟,该模拟演化了一个初始函数。我希望程序从外部读取一个初始函数,就像我在内部编写它一样,并使用它。
  • 它用于 PDE 评估,但它不仅仅用于初始条件。我希望代码具有我在外部定义的可调非线性函数 f(x,t)。这种非线性在时间推进算法中,所以我相信数值评估要么不兼容,要么在过程中选择不佳。
  • 如果是编译或者运行时的问题,重新编译就好了。我宁愿在两行 txt 文件中外部编写函数后重新编译,也不愿对代码进行排序,每次都写在那里(无论如何我都必须重新编译)。
  • 我编辑了这个问题。一般来说,如果可以让代码获取任何外部编写的代码(无论是 .f90 还是 .txt)并将其插入到代码中,那就太好了(所以不仅仅是数学语句,尽管这是主要目标)。跨度>
  • SIND 和其他人将在新版本的 gfortran 中。
猜你喜欢
  • 2011-04-29
  • 2018-06-04
  • 1970-01-01
  • 2014-03-24
  • 2018-08-03
  • 1970-01-01
  • 1970-01-01
  • 2013-09-11
  • 2023-03-27
相关资源
最近更新 更多