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 function m**2
, SIN(m)
, or even 0
and have that replace externalfunction
. 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
and compile it as (*1)
we can test various expressions as follows:
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.,(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.