2016-11-18 2 views
1

Я хотел бы, чтобы мой код взял код, написанный в другом документе, прочитал его, а затем использовал его, как если бы он был написан в коде. Скажем, мы имеем следующее:Как вставить fortran-код из внешнего файла в отдельный код?

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**2, SIN(m) или даже 0 и заменяет их externalfunction. Вот простой пример:

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

Где в текстовый файл я написал, написал SIN(x).

+0

Вы имеете в виду во время компиляции или во время выполнения? Это две разные ситуации. –

+1

Кодовый блок в начале вашего вопроса определенно совершенно неверен. Также 'kind = 8' очень уродливый и не переносимый. Это не означает 8 байтов во всех компиляторах. –

+0

Существует такая вещь (http://stackoverflow.com/q/7326828), но это, возможно, не совсем то, что вы имеете в виду. – francescalus

ответ

1

Я думаю, что для этого есть два разных подхода (* на самом деле, похоже, есть и «третий» подход, см. EDIT); один - использовать общую библиотеку, а другой - использовать синтаксический анализатор для математических выражений. Первый подход описан на странице 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) Модуль имеет несколько линий с sind, cosd и tand, но они не поддерживаются gfortran. Так, для компиляции, я заметил их и заменить их на stop, т.е.

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

(я предполагаю, что sind(x) означает sin(x * pi/180), так что может быть в порядке, чтобы определить его как таковой.)


[EDIT]

«третий» подход А может вызвать встроенный eval() функции в интерпретируемых языков, таких как Python или Джулии через system(), например, this SO page. Хотя это также имеет множество слабых мест (и, вероятно, гораздо проще использовать такие языки напрямую), вызов eval() из Fortran может быть полезен для определенных целей.

+0

Есть ли способ интерпретировать ввод строки для использования в программе? Это берет строку и предоставляет числовое значение. Скажем, например, у меня была симуляция во времени, которая развивает начальную функцию. Я хотел бы, чтобы программа читала исходную функцию извне, как будто я ее внутренне написал и работаю с ней. – Captain

+0

Это для оценки PDE, однако это больше, чем исходные условия. Я хочу, чтобы код имел регулируемую функцию нелинейности f (x, t), которую я определяю внешне. Эта нелинейность находится в алгоритме временного марширования, поэтому я считаю, что оценка численно либо несовместима, либо плохой вариант процесса. – Captain

+0

Если определение начальной функции связано с некоторыми кодами, имеющими несколько строк (и, возможно, зависит от разных параметров), хм, я думаю, что подход с разделяемой библиотекой может быть лучше и передать все переменные в качестве фиктивных аргументов. Поскольку Fortran не может оценивать коды во время выполнения, я думаю, что возможные подходы здесь довольно ограничены ... – roygvib

Смежные вопросы