[英]Fortran: How to conduct a job repeatedly using multiple files
Project description: 项目描述:
I have the coordinates of McDonalds in cities and the coordinates of city centers. 我有麦当劳在城市的坐标和市中心的坐标。 They are divided to text files by city.
它们按城市分为文本文件。 For example,
例如,
=== atlanta_mc.txt === === houston_mc.txt === ... (for 200 cities)
[latitude] [longitude] [latitude] [longitude] <-- The headers are not written in the files.
33.5431140 -84.5766910 29.8044570 -95.3990780
34.0489350 -84.0928960 30.0051170 -95.2834550
33.7853660 -84.1018980 29.7371140 -95.5352550
34.0903210 -84.2040180 29.7280160 -95.4188230
34.1606520 -84.1781010 29.7851700 -95.3609770
.... ....
My goal is to calculate the distance between the city center and each McDonald for each city. 我的目标是计算每个城市的市中心和每个麦当劳之间的距离。 The city center data file has [cityname],[latitude],[longitude] fiels.
市中心数据文件具有[cityname],[latitude],[longitude]字段。 It looks like:
看起来像:
== city_centers.txt ==
[city name] [latitude] [longitude] <-- The headers are not written in the file.
atlanta 33.79526 -84.326528
la 34.057453 -118.413842
ny 40.759347 -73.980202
houston 29.733215 -95.430824
....
(for 200 cities in the US.)
Fortran code: Fortran代码:
For one city (say, Atlanta), I can do the job as follows: 对于一个城市(例如亚特兰大),我可以执行以下操作:
program mcdonalds
implicit none
interface
function distkm(deglat1,deglon1,deglat2,deglon2)
real :: distkm
real, intent(in) :: deglat1,deglon1,deglat2,deglon2
end function distkm
end interface
integer, parameter :: maxnr = 200
integer :: nr, i, j, ios
character(len=1) :: junkfornr
real, dimension(:), allocatable :: lat, lon
! Obtain the total number of observations
nr=0
open(10, file='atlanta_mc.txt', status='old')
do i=1,maxnr
read(10,*,iostat=ios) junkfornr
if (ios/=0) exit
if (i == maxnr) then
stop
endif
nr = nr + 1
end do
allocate(lat(nr))
allocate(lon(nr))
rewind(10)
do i=1,nr
read(10,*) lat(i), lon(i)
end do
open(20,file='RESULT_atlanta_mc.txt')
do i=1,nr
write(20,100) "atlanta",lat(i),lon(i),distkm(lat(i),lon(i),33.79526,-84.326528)
100 format(A,3F12.6)
end do
end program mcdonalds
function distkm(deglat1,deglon1,deglat2,deglon2)
implicit none
real, intent(in) :: deglat1,deglon1,deglat2,deglon2
real :: pi,dlat,dlon,lat1,lat2,a,distkm
pi = 4*atan(1.0)
dlat = (deglat2-deglat1)*pi/180
dlon = (deglon2-deglon1)*pi/180
lat1 = deglat1*pi/180
lat2 = deglat2*pi/180
a = (sin(dlat/2))**2 + cos(lat1)*cos(lat2)*(sin(dlon/2))**2
distkm = 6372.8*2*atan2(sqrt(a),sqrt(1-a))
end function distkm
Problem: 问题:
I have to do this for the all cities. 我必须对所有城市都这样做。 So, I have to change (1) the McDonalds data file, (2) the city center coordinate;
因此,我必须更改(1)麦当劳数据文件,(2)市中心坐标; and (3) the result file for each city accordingly.
(3)每个城市的结果文件。 How do I have to write a program to iterate this process for the whole 200 cities?
我该如何编写程序来遍及整个200个城市? I use Intel Fortran ( ifort ) to compile it.
我使用Intel Fortran( ifort )进行编译。
EDIT (This code worked -- Friday, April 11, 2014): 编辑(此代码有效-2014年4月11日,星期五):
! calculate distances from the city center to each McDonald
! Try this for all the cities
program mcdonalds
implicit none
interface
function distkm(deglat1,deglon1,deglat2,deglon2)
real :: distkm
real, intent(in) :: deglat1,deglon1,deglat2,deglon2
end function distkm
end interface
integer, parameter :: maxnr = 200
integer :: nr, i, j, ios
character(len=1) :: junkfornr
character(len=25) :: fn
real, dimension(:), allocatable :: lat, lon
real, dimension(5) :: clat, clon
character(len=15), dimension(5) :: filename
character(len=6), dimension(5) :: code
character(len=7), dimension(5) :: cityname
! I have a text file that contains the list of data file names, city names and the (lat/lon)s of city centers.
! The name of that file: datafilelistcitycenter.txt
! === The content of the file looks like: ===
! atlanta_mc.txt 11111 atlanta 33.79526 -84.326528
! houston_mc.txt 22222 houston 29.733215 -95.430824
! la_mc.txt 33333 la 34.057453 -118.413842
! ny_mc.txt 44444 ny 40.759347 -73.980202
! philly_mc.txt 55555 philly 29.733215 -95.430824
! Let's assume we know the number of the cities.
! In this case, it is 5.
open(10, file='datafilelistcitycenter.txt', status='old')
rewind(10)
do i=1,5
read(10,*) filename(i), cityname(i), clat(i), clon(i)
end do
close(10)
! Obtain the total number of observations for each city
do j=1,5
open(j, file=filename(j), status='old')
nr=0
do i=1,maxnr
read(j,*,iostat=ios) junkfornr
if (ios/=0) exit
if (i == maxnr) then
write(*,*) "Error: Maximum number of records exceeded..."
write(*,*) "Exiting the program..."
stop
endif
nr = nr + 1
end do
allocate(lat(nr),lon(nr))
rewind(j)
do i=1,nr
read(j,*) lat(i), lon(i)
end do
close(j)
write(fn, '("RESULT_",A15)') filename(j)
open(j,file=fn)
do i=1,nr
write(j,100) code(j),cityname(j),lat(i),lon(i),distkm(lat(i),lon(i),clat(j),clon(j))
100 format(A6,A7,3F12.6)
end do
close(j)
deallocate(lat,lon)
end do
end program mcdonalds
function distkm(deglat1,deglon1,deglat2,deglon2)
implicit none
real, intent(in) :: deglat1,deglon1,deglat2,deglon2
real :: pi,dlat,dlon,lat1,lat2,a,distkm
pi = 4*atan(1.0)
dlat = (deglat2-deglat1)*pi/180
dlon = (deglon2-deglon1)*pi/180
lat1 = deglat1*pi/180
lat2 = deglat2*pi/180
a = (sin(dlat/2))**2 + cos(lat1)*cos(lat2)*(sin(dlon/2))**2
distkm = 6372.8*2*atan2(sqrt(a),sqrt(1-a))
end function distkm
No luck. 没运气。 I end up with very weird messages: severe <66>: output statement overflows record, unit -5, file Internal Fomatted Write.
我最终得到了很奇怪的消息:严重<66>:输出语句溢出记录,单位-5,文件内部格式写入。
EDIT: I think I got it right. 编辑:我想我做对了。 Thanks.
谢谢。
Instead of opening one specific city file such as atlanta_mc.tx, create a file that a list of the filenames of the city. 无需打开一个特定的城市文件(如atlanta_mc.tx),而是创建一个包含城市文件名列表的文件。 Open that file, add a new loop to your program and read a name of a city file, open and process it as you do now, then close the file.
打开该文件,在程序中添加一个新的循环,并读取城市文件的名称,像现在一样打开并处理它,然后关闭该文件。 Next iteration of new loop will process the next city file, etc. This is assuming that the cities are in separate files.
新循环的下一次迭代将处理下一个城市文件,等等。这是假定城市在单独的文件中。 If they are in one big file, then create arrays to hold information for all of the cities, read all the information into the array, then have a new loop to iterate over the cities.
如果它们在一个大文件中,则创建一个数组以保存所有城市的信息,将所有信息读入该数组,然后有一个新的循环遍历城市。
Also, if you place your function distkm
into a module you won't have to bother with having an interface
for it. 同样,如果您将函数
distkm
放入模块中,则无需为它提供interface
。 Using modules and easier and less error prone. 使用模块,更容易出错。 An example: distkm
例如:distkm
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.