所以我试图想出一个聪明的方法来让这个程序读取目录并将任何属于特定空间“网格”框的内容放在一起,并将该框中的数据平均在一起。我会在下面粘贴我的可怕尝试,希望你会看到我正在尝试做什么。我无法使程序正常工作(它被困在一个我没有调试过的循环中),而且在我再次撞击它之前我想知道这是否看起来像是一个逻辑的操作集合我希望这样做,或者是否有更好的方法来实现这一目标。
编辑:为了澄清,参数部分用于修剪参数---“lmin lmax bmin bmax”设置整体框架,“deg”设置平方度增量。
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 * cos(b)”。对于每个0.5 x 0.5度的截面,我需要在该块内具有E(B-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
^它在两行后卡住了。
答案 0 :(得分:0)
我认为该程序可以执行您希望它执行的操作,但您正在寻找一些可以整理代码的方法。
首先,我会修复缩进。
其次,我不会使用低于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)
第三,我不会使用GOTO
和标签。你可以更容易地在循环中做到这一点:
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
您的代码中存在一些危险,即使在上面的这一个中:它可能导致无限循环。例如,如果infile
的开头失败(例如文件不存在),它会循环回标签3,但没有任何变化,因此最终会再次尝试打开同一个文件,并且可能会同样的错误。
同上:如果READ
在没有前进的情况下反复失败,并且错误不是EOF
,那么读取循环将不会终止。
你必须考虑你希望你的程序在发生这样的事情时做什么,并对其进行编码。(例如:如果无法打开文件,则打印错误消息和STOP
。)
你有一个很长的FORMAT
声明。你可以这样离开,虽然我可能会尝试缩短它:
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, ...
再次,这是一个较少的标签。