Конвертировать общий блок в модуль
Я исследователь, работающий с программой, написанной на Фортране. У меня есть базовые навыки кодирования, поэтому мне нужно немного помочь, чтобы получить некоторый код для правильной компиляции.
Я дам немного фона, прежде чем показывать код. Я имею дело с большим количеством данных, которые потребуют 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. В конечном счете, лучше использовать виды, как предложил Владимир Ф.