简体   繁体   English

Fortran:如何使用多个文件重复执行作业

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM