问题描述
我希望我的代码将代码写入另一个文档中,读取它,然后像使用代码编写代码一样使用它。假设我们有以下内容:
$ b $ pre $ MODULE samplemod
CONTAINS
FUNCTION sillysum(boudary,function)RESULT(计数器)
IMPLICIT NONE
REAL(KIND = 8):: boundary,counter
REAL(KIND = 8),DIMENSION(:) :: function
INTEGER :: m
计数器= 0.d0
DO m = 1,my_mesh%me
计数器=函数(m)+外部函数
END DO
END FUNCTION sillysum
END MODULE samplemod
程序sampleprogram
USE samplemod
REAL(KIND = 8),DIMENSION(:) :: function1
ALLOCATE(function1(100))
DO m = 1,100
函数1(i)= i
END DO
WRITE(*,*)sillysum(100,function1)
结束程序sampleprogram
在某些外部文件(例如'externfunct.txt')中写入 m ** 2
。 Fortran代码如何读取外部函数 m ** 2
, SIN(m)
,甚至 0
并替换 externalfunction
。这里有一个简单的例子:
REAL(KIND = 8):: x = 2
CHARACTER(LEN = *) :: strng =external
WRITE(*,*)Hello world,2 +,strng,=,2 + external
在我写的txt文件中,我写了 SIN(x)
。
我认为这有两种不同的方法(*实际上,似乎还有一种第三种方法,请参阅EDIT)。一个是使用共享库,另一个是使用数学表达式的解析器。第一种方法在Rossetastone页面()和SO页面(例如,)。对于第二种方法,您可以通过使用数学解析器或Fortran数学解析器等进行搜索来查找第三方库。在此,我尝试了因为它看起来非常简单(只有一个模块,没有安装)。如果我们编写一个简单的测试程序,像这样:
程序测试
$ p $ (* 1)
只使用解释器:init,evaluate,dp = > realkind
隐式无
整型,参数:: mxvars = 10! (10):: symbols(mxvars)
real(dp):: values(mxvars),回答
字符(1000):: funcstr !!用户定义的数学表达式
character(5):: stat
!>定义变量名称。
符号(1)=x
符号(2)=a
符号(3)=b
符号(4)=c
符号(5)=foo
!>获取数学表达式。
print *,请输入一个数学表达式:
read(*,(a))funcstr !!例如a * x + b
!>初始化评估者。
调用init(funcstr,symbols,stat)
if(stat / =ok)stopstat / = ok
!>设置变量的值。
值(:)= 0
值(1)= 2.0_dp! x
值(2)= 10.0_dp!
值(3)= 7.0_dp! b
!>评估。
answer = evaluate(values)
print *,function value =,answer
end program
$ gfortran -ffree- line-length-none interpreter.f90 mytest.f90
我们可以按如下方式测试各种表达式: p>
$ ./a.out
请输入数学表达式:
a * x + b
函数值= 27.000000000000000
$ ./a.out
请输入数学表达式:
sin(a * x)+ cos(b)+ foo
函数值= 1.6668475050709324
其他库的用法也非常相似。由于每个库的性能可能会有所不同,因此尝试使用几个不同的库进行比较可能会很有用。
( * 1)模块有一些行
sind
,cosd
和tand
,但它们不被gfortran支持。所以,为了编译,我已经将它们注释掉了,并用stop
替换它们,即
stopsind not supported ...
! pdata(st)= sind(pdata(st))
sind(x)意味着
sin(x * pi / 180)
,所以可以这样定义它。)
第三种方法可能是调用通过
system()
来内置eval()
函数,如Python或Julia等解释型语言,例如。虽然这也有很多弱点(并且可能直接使用这些语言更容易),但是从Fortran调用eval()
可能对于某些特定用途很有用。I'd like to have my code take code written in another document, read it, and then use it as though it was written in the code. Say we have the following:
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
Where in some external file (say 'externfunct.txt') one has written
m**2
. How can the Fortran code read the external functionm**2
,SIN(m)
, or even0
and have that replaceexternalfunction
. Here's a simpler example:REAL(KIND=8) :: x = 2 CHARACTER(LEN=*) :: strng = "external" WRITE(*,*) "Hello world, 2 + ", strng, " = ", 2 + external
Where in a txt file I have written I have written
SIN(x)
.解决方案I think there are two different approaches for this (* in fact, there seems a "third" approach also, see EDIT); one is to use a shared library, and the other is to use a parser for math expressions. The first approach is described in a Rossetastone page (Call a function in a shared library) and an SO page (Fortran dynamic libraries, load at runtime?), for example. For the second approach, you can find 3rd-party libraries by searching with "math parser" or "Fortran math parser" etc. Here, I have tried this one because it seems pretty simple (only one module and no installation). If we write a simple test program like this
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
and compile it as (*1)
$ gfortran -ffree-line-length-none interpreter.f90 mytest.f90
we can test various expressions as follows:
$ ./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
The usage of other libraries also seems very similar. Because the performance of each library may be rather different, it may be useful to try several different libraries for comparison.
(*1) The module has some lines with
sind
,cosd
, andtand
, but they are not supported by gfortran. So, to compile, I have commented them out and replaced them bystop
, i.e.,stop "sind not supported..." ! pdata(st) = sind(pdata(st))
(I guess
sind(x)
meanssin( x * pi / 180 )
, so it may be OK to define it as such.)[EDIT]
A "third" approach may be to call the built-in
eval()
function in interpreted languages like Python or Julia viasystem()
, e.g., this SO page. Although this also has a lot of weak points (and it is probably much easier to use such languages directly), callingeval()
from Fortran might be useful for some specific purposes.这篇关于如何从外部文件插入fortran代码到单独的代码中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!