Функция FORTRAN77 возвращает массив

Извините, что задаю такие элементарные вопросы. Я работаю над некоторыми кодами FOTRAN77 и пытаюсь вызвать их из Python. Однако я обнаружил некоторые проблемы с возвратом двух или более значений из функции.

Ниже приведен код. Он имеет четыре входа (APPRAT, APPNUM, APSPAC, KOC), и я хочу вернуть три значения параметров (APPTOT, KD, TDEGF), которые хранятся в GENEEC3. Мой скомпилированный код хорошо работает, когда возвращается только один параметр, но не работает, когда я прошу его отправить обратно три параметра.

Поэтому, пожалуйста, дайте мне несколько предложений и спасибо всем за помощь!

      Function GENEEC3 (APPRAT,APPNUM,APSPAC,KOC)

      REAL GENEEC3(3)
      CHARACTER*1 METHOD,AGAIN,WETTED,ADSORP,AIRFLG,GRNFLG,ORCFLG,GRSIZE
Cf2py intent(in) APPRAT,APPNUM,APSPAC,KOC,METHAF,WETTED,METHOD,AIRFLG
Cf2py intent(in) YLOCEN,GRNFLG,ORCFLG,INCORP,SOL,METHAP,HYDHAP,FOTHAP      
Cf2py intent(out) GENEEC3(3)  
C    
      APPTOT=APPRAT*APPNUM
      TDEGF = APPNUM * APSPAC
      KD = 0.0116 * KOC
C
      GENEEC3(1)=APPTOT
      GENEEC3(2)=KD
      GENEEC3(3)=TDEGF
C      
      RETURN 
      END Function GENEEC3   

person TTT    schedule 04.04.2012    source источник
comment
Вы не можете использовать fortran 90 или более позднюю версию? я сомневаюсь, что Fortran 77 поддерживает массив как возвращаемое значение функции   -  person yosukesabai    schedule 04.04.2012
comment
@yosukesabai, мне жаль, что я не смог изменить его на fortran90...   -  person TTT    schedule 04.04.2012
comment
почему это...? f90 является надмножеством f77, поэтому почти весь код f77 является действительным кодом f90. и в наши дни есть бесплатные компиляторы f90, если деньги являются проблемой (например, gfortran)   -  person yosukesabai    schedule 04.04.2012
comment
Я думаю, что функция в FORTRAN возвращает одно значение, массив, вероятно, не подходит. Прошло около 30 лет с тех пор, как я в последний раз писал что-либо на FORTRAN, так что, возможно, с тех пор многое изменилось!   -  person NealB    schedule 04.04.2012
comment
и, если вы хотите вернуть массив, вы уже попадаете в f90, и вы использовали директиву намерения, которая введена в f90.   -  person yosukesabai    schedule 05.04.2012
comment
@yosukesabai, я использую gfortran в качестве моего компилятора. Значит ли это, что я могу писать вещи fortran95 в этом коде fortran77? спасибо   -  person TTT    schedule 05.04.2012
comment
@NealB, спасибо за подтверждение   -  person TTT    schedule 05.04.2012
comment
да, gfortran компилирует коды f90, f95. если вам нужно использовать фиксированный формат, этот старый код стиля f77, вы используете флаг -ffixed-form в gfortran. я попробовал ваш код, но gfortran выдал segfault, даже я скомпилировал для создания исполняемого файла fortran. я могу позволить коду работать с коммерческим компилятором. я буду тестировать немного больше   -  person yosukesabai    schedule 05.04.2012
comment
@yosukesabai, большое спасибо. У меня остались наивные вопросы. Нужно ли менять код .for на f95, чтобы активировать функцию возврата массива?   -  person TTT    schedule 05.04.2012
comment
см. в моем примере. оказалось, что проще написать подпрограмму на Фортране. f2py автоматически вернул его функции python. поскольку функция с массивом значений является относительно новой в fotran, я думаю, что есть много кода fotran, написанного как подпрограмма, которую имеет больше смысла рассматривать как функцию в python.   -  person yosukesabai    schedule 05.04.2012


Ответы (1)


Я попытался определить функцию fortran и позволить ей работать с f2py, но f2py, похоже, создает оболочку функции, в которой возвращаемое значение является скалярным. я не мог понять, как получить это прямо.

вместо этого я попытался определить подпрограмму. Затем f2py ловко догадался, что мне действительно нужна функция со значением массива! Ниже я подтвердил работу как с gfortran, так и с pgf90.

f2py --fcompiler=gnu95 -c -m geneec3 geneec3.f90

потом в питоне

>>> import geneec3
>>> geneec3.geneec3(1,1,1,1) 
>>> array([ 1.    ,  0.0116,  1.    ], dtype=float32)
>>>

генec3.f90

      subroutine GENEEC3 (APPRAT,APPNUM,APSPAC,KOC, results)

      implicit none
      REAL, dimension(3), intent(out) ::  results
      real, intent(in) :: apprat, appnum, apspac, koc
      real apptot, tdegf, kd


C    
      APPTOT=APPRAT*APPNUM
      TDEGF = APPNUM * APSPAC
      KD = 0.0116 * KOC
C
      results(1)=APPTOT
      results(2)=KD
      results(3)=TDEGF
      END subroutine GENEEC3
person yosukesabai    schedule 04.04.2012
comment
Большое вам спасибо за вашу помощь! Это действительно экономит мне много времени! - person TTT; 05.04.2012