Fortran 程序创建空间网格,将网格内的平均值写入表格
因此,我试图想出一个聪明的方法,让这个程序读取一个目录,并将特定空间网格框内的所有数据取平均值。我将把我可怕的尝试贴在下面,希望你能看到我在尝试做什么。我无法让程序正常运行,它陷入了一个我没有调试过的循环中,在我再次尝试之前,我想知道这是否是我想要做的事情的一组逻辑操作,或者是否有更好的方法来实现这一点 编辑:为了澄清,参数部分用于修剪参数——lmin lmax bmin bmax设置整体框架,deg设置平方度增量Fortran 程序创建空间网格,将网格内的平均值写入表格,fortran,astronomy,Fortran,Astronomy,因此,我试图想出一个聪明的方法,让这个程序读取一个目录,并将特定空间网格框内的所有数据取平均值。我将把我可怕的尝试贴在下面,希望你能看到我在尝试做什么。我无法让程序正常运行,它陷入了一个我没有调试过的循环中,在我再次尝试之前,我想知道这是否是我想要做的事情的一组逻辑操作,或者是否有更好的方法来实现这一点 编辑:为了澄清,参数部分用于修剪参数——lmin lmax bmin bmax设置整体框架,deg设置平方度增量 program redgrid implicit none ! Variab
program redgrid
implicit none
! Variable declarations and settings:
integer :: ncrt, c, i, j, k, count, n, iarg, D, db, cn
real :: dsun, pma, pmd, epma, epmd, ra, dec, degbin
real :: V, Per, Amp, FeH, EBV, Dm, Fi, FeHav, EBVav
real :: lmin, lmax, bmin, bmax, l, b, deg, lbin, bbin
real :: bbinmax, bbinmin, lbinmax, lbinmin
character(len=60) :: infile, outfile, word, name
parameter(D=20000)
dimension :: EBV(D), FeH(D), lbinmax(D), bbinmax(D)
dimension :: bbinmin(D), lbinmin(D)
103 format(1x,i6,4x,f6.2,4x,f6.2,4x,f7.2,3x,f6.2,4x,f5.2,4x,f5.2,4x,f5.2,4x,f6.4)
3 continue
iarg=iargc()
if(iarg.lt.7) then
print*, 'Usage: redgrid infile outfile lmin lmax bmin bmax square_deg'
stop
endif
call getarg(1, infile)
call getarg(2, outfile)
call getarg(3, word)
read(word,*) lmin
call getarg(4, word)
read(word,*) lmax
call getarg(5, word)
read(word,*) bmin
call getarg(6, word)
read(word,*) bmax
call getarg(7, word)
read(word,*) deg
open(unit=1,file=infile,status='old',err=3)
open(unit=2,file=outfile,status='unknown')
write(2,*)"| l center | b center | [Fe/H] avg | E(B-V) avg | "
FeHav = 0.0
EBVav = 0.0
lbinmin(1) = lmin
bbinmin(1) = bmin
degbin = (bmax-bmin)/deg
db = NINT(degbin)
do j = 1, db
bbinmax(j) = bbinmin(j) + deg
lbinmax(j) = lbinmin(j)*cos(bbinmax(j))
print*, lbinmin(j), bbinmin(j), db
cn = 1
7 continue
read(1,*,err=7,end=8) ncrt, ra, dec, l, b,&
V, dsun, FeH(cn), EBV(cn)
if(b.ge.bbinmin(j).and.b.lt.bbinmax(j)) then
if(l.ge.lbinmin(j).and.l.lt.lbinmax(j)) then
FeHav = FeHav + FeH(cn)
EBVav = EBVav + EBV(cn)
cn = cn + 1
end if
end if
goto 7
8 continue
FeHav = FeHav/cn
EBVav = EBVav/cn
write(2,*) lbinmax(j), bbinmax(j), FeHav, EBVav
bbinmin(j+1) = bbinmin(j) + deg
lbinmin(j+1) = lbinmin(j) + deg
end do
close(1)
close(2)
end program redgrid
下面是我正在使用的表格的一小部分。l和b是我正在使用的两个坐标——它们是有角度的,因此需要制作网格组件b和l*cosb。对于每个0.5 x 0.5度的截面,我需要该块内的EB-V和[Fe/H]的平均值。当我写这个文件时,我只需要四列:框所在的两个坐标,以及框的两个平均值
| Ncrt | ra | dec | l | b | V | dkpc | [Fe/H] | E(B-V) |
7888 216.53 -43.85 -39.56 15.78 15.68 8.90 -1.19 0.1420
7889 217.49 -43.13 -38.61 16.18 16.15 10.67 -1.15 0.1750
7893 219.16 -43.26 -37.50 15.58 15.38 7.79 -1.40 0.1580
现在,程序被困在循环周期的某个地方。我已经粘贴了运行它时发生的终端输出,以及运行它时使用的命令行。请让我知道,如果我可以帮助澄清。对于像我这样的Fortran新手来说,这是一个相当复杂的问题——也许我缺少了一些基础知识,这些知识会使问题变得更简单。无论如何,先谢谢你
./redgrid table2.above redtest.trim -40 0 15 30 0.5
-40.0000000 15.0000000 30 0.00000000 0.00000000
-39.5000000 15.5000000 30 -1.18592596 0.353437036
^两行代码之后,它就卡住了。我假设程序做了您希望它做的事情,但是您正在寻找一些东西来整理代码 首先,我要修复压痕 第二,我不会使用低于10的单元号
INTEGER, PARAMETER :: in_unit = 100
INTEGER, PARAMETER :: out_unit = 101
...
OPEN(unit=in_unit, file=infile, status='OLD")
...
READ(in_unit, *) ...
...
CLOSE(in_unit)
第三,我不会使用GOTOs和标签。您可以在循环中轻松地执行此操作:
INTEGER :: read_status
DO j = 1, db
...
read_loop : DO
READ(in_unit, *, IOSTAT=read_status) ...
IF (read_status == -1) THEN ! EOF
EXIT read_loop
ELSEIF (read_status /= 0) THEN
CYCLE read_loop
ENDIF
...
END DO read_loop
...
END DO
在您的代码中,甚至在上面的代码中,也存在一些危险:它可能导致无限循环。例如,如果infle的打开失败,例如文件不存在,它将循环回标签3,但没有任何更改,因此它最终将再次尝试打开同一文件,并且可能会出现相同的错误
如上所述:如果读取重复失败而不前进,并且错误不是EOF,则读取循环将不会终止
当类似的事情发生时,您必须考虑您希望您的程序做什么,并编写代码。例如:打印错误消息,如果无法打开文件,则停止
你有一个很长的格式声明。你可以这样留着,不过我可能会尽量把它缩短一点:
103 FORMAT(I7, 2F10.2, F11.2, 4F9.2, F10.4)
这应该是同一行,因为数字通常是右对齐的。您还可以使用字符串作为格式,因此您还可以执行以下操作:
CHARACTER(LEN=*), PARAMETER :: data_out_form = &
'(I7, 2F10.2, F11.2, 4F9.2, F10.4)'
WRITE(*, data_out_form) var1, var2, var3, ...
再一次,这少了一个标签。谢谢,我感谢你的回复,我一定会尝试整理一下你的建议。我想我忘了在现在编辑的主要帖子中具体说明,因为程序还没有运行,我也不确定我列出的方法是否符合逻辑。因此,在对read_循环进行了一些修补和实现之后,我让它运行起来。非常感谢——阅读循环是我不知道的,它非常有用。这不是问题,但它帮助我隔离了问题。问题是,在文件开始时,我打开了infle,因此当它在循环一次之后读取文件时,它将没有更多的行并冻结。它打印两行的原因是因为print命令出现在第二次读取尝试之前。需要注意的是:我使用的Fortran手册中有end=和err=语句,它们都标有“请勿使用大危险”。我真的认为应该使用IOSTAT和IOMSG参数。顺便说一下:read_循环是一个名称,因此它可以是任何名称,但必须在范围内是唯一的。