I am a researcher working with a program written in Fortran. I have very basic coding skills, so I need a bit of help getting some code to compile properly.
I will give a bit of background before showing the code. I am dealing with a large number of data, which will require 64-bit compiling and greater than 2 gb of memory. The first thing I noticed in the code is that many of the variables were written as "real", but in my research I found that "double precision" allows for much larger variables, and would be a more flexible choice, so I changed all "real" variables to "double precision" variables.
There is also in a file that is included in the compilation of the fortran build file "dist.f", called "geocoord.inc". I found that the variables are saved to a common block, but once again, I need something that can hold a larger amount of data. As I have been led to believe, a module would be a better program to use. I need some advice in converting this include file to work properly with the module program, which I will list below.
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
I appreciate any advice that you can provide and apologize for my relative ignorance in all things Fortran!
Modernizing an old code is often not an easy task. At least for a beginner. The move from real
to double precision
is not in the spirit of modern Fortran, but until you introduce modules it is OK. When you have modules it is better to do:
module precisions
integer, parameter :: rp = kind(1.d0) !if you insist on double, otherwise use selected_real_kind()
end module
and everywhere use the new kind constant that denotes your real precision:
use precisions
real(rp) :: variables
With the common blocks, the one you showed would be:
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
Then you use it:
subroutine dist(xlat, xlon, xkm, ykm)
use precisions
use geo_coordsystem
implicit none
You can also continually move you subroutines to modules. Do that in small steps and always check that you didn't introduce some bug.