Конвертировать общий блок в модуль

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

Я дам немного фона, прежде чем показывать код. Я имею дело с большим количеством данных, которые потребуют 64-битной компиляции и больше, чем 2 ГБ памяти. Первое, что я заметил в коде, это то, что многие переменные были записаны как "настоящие", но в своем исследовании я обнаружил, что "двойная точность" допускает гораздо большие переменные и будет более гибким выбором, поэтому я изменил все "реальные" переменные для "двойной точности" переменных.

Он также находится в файле, который включен в компиляцию файла сборки fortran "dist.f" и называется "geocoord.inc". Я обнаружил, что переменные сохраняются в общий блок, но еще раз, мне нужно что-то, что может содержать больший объем данных. Как я уже говорил, модуль будет лучше использовать. Мне нужно несколько советов по преобразованию этого включаемого файла для правильной работы с модульной программой, которые я перечислю ниже.

Dist.f:

c Convert latitude and longitude to kilometers relative
c to center of coordinates by short distance conversion.

subroutine dist(xlat, xlon, xkm, ykm)

implicit none

c   Parameters:
double precision    xlat, xlon  ! (input)
double precision        xkm, ykm    ! (output)

c   Local variables:
double precision lat1, lat2, lat3
double precision    q
double precision    xx
double precision    yp

include "geocoord.inc"

c Set up short distance conversion by subr. SETORG
  q=60*xlat-olat
  yp=q+olat
  lat1=datan(rlatc*dtan(RAD*yp/60.0))
  lat2=datan(rlatc*dtan(RAD*OLAT/60.0))
  LAT3=(LAT2+LAT1)/2.
  xx=60*xlon-olon  !  - wegen LON E
  q=q*aa
  xx = xx*bb*dcos(LAT3)
  IF(rotate.ne.0.) then
c** rotate coordinate system anticlockwise
    yp=cost*q+sint*xx
    xx=cost*xx-sint*q
    q=yp
  ENDIF

  xkm=xx
  ykm=q

  return
  end

Geocoord.inc:

double precision rearth
double precision ellip
double precision rlatc
double precision rad
double precision olat, olon
double precision aa, bb, bc
double precision sint, cost
double precision rotate
integer icoordsystem

common /GEO_COORSYSTEM/ rearth, ellip, rlatc, rad,
&    olat, olon, aa, bb, bc, sint, cost, rotate,
&    icoordsystem

Я ценю любые советы, которые вы можете дать и извиниться за мое относительное невежество во всем, что касается Фортрана!

2 ответа

Решение

Модернизация старого кода часто является непростой задачей. По крайней мере, для начинающего. Переезд из real в double precision не в духе современного Фортрана, но пока вы не введете модули, все в порядке. Когда у вас есть модули, лучше сделать:

module precisions
  integer, parameter :: rp = kind(1.d0) !if you insist on double, otherwise use selected_real_kind()
end module

и везде используйте новую константу вида, которая обозначает вашу реальную точность:

  use precisions

      real(rp) :: variables

С общими блоками показанный вами будет:

module geo_coordsystem
  use precisions

  implicit none

  real(rp) :: rearth
  real(rp) ::  ellip
  real(rp) ::  rlatc
  real(rp) ::  rad
  real(rp) ::  olat, olon
  real(rp) ::  aa, bb, bc
  real(rp) ::  sint, cost
  real(rp) ::  rotate
  integer icoordsystem

end module

Тогда вы используете это:

subroutine dist(xlat, xlon, xkm, ykm)
  use precisions
  use geo_coordsystem

  implicit none

Вы также можете постоянно перемещать свои подпрограммы в модули. Делайте это небольшими шагами и всегда проверяйте, чтобы не было ошибок.

Несколько компиляторов Фортрана имеют возможность повысить действительные переменные до двойной точности. В gfortran опция -fdefault-real-8, как описано на http://gcc.gnu.org/onlinedocs/gfortran/Fortran-Dialect-Options.html. В конечном счете, лучше использовать виды, как предложил Владимир Ф.

Другие вопросы по тегам