我正在编写Fortran代码,以便阅读反应列表及其反应类型。该列表位于名为reactions.rx的文件中,如下所示:
H2O O1D OH OH 2BODY .
.
. (Same format continued)
.
CH3C2H HV C3H3 H PHOTO
CH3C2H HV C3H2 H2 PHOTO
CH3C2H HV CH3 C2H PHOTO
CH2CCH2 HV C3H3 H PHOTO
CH2CCH2 HV C3H2 H2 PHOTO
CH2CCH2 HV C2H2 CH23 PHOTO
C2H6 HV CH23 CH23 H2 PHOTO
C2H6 HV CH4 CH21 PHOTO
C2H6 HV C2H2 H2 H2 PHOTO
C2H6 HV C2H4 H H PHOTO
C2H6 HV C2H4 H2 PHOTO
C2H6 HV CH3 CH3 PHOTO
C2H C2H2 HCAER H 2BODY
C2H CH2CCH2 HCAER2 H 2BODY
目标是编写代码,使其在最左边的列中找到第一次出现的指定物种,标签为PHOTO,然后继续读取文件,直到该行不再包含物种或不是PHOTO 。
到目前为止我的代码:
! reactions.rx is opened earlier as file 12
667 FORMAT(A10, A10, A10, A10, A8, A5)
stat = 0
! Reads until a line is found in reactions.rx with reactant1 == species
! and label beginning with "PHOT"
do while((trim(reac1).ne.trim(species).OR.label(1:4).ne.'PHOT')
& .AND.stat == 0)
READ(12,667,IOSTAT=stat) reac1,reac2,prod1,prod2,prod3,label
end do
if(stat.ne.0) then
print*, " *** Species not in reactions.rx!!!! *** "
STOP
endif
! reac1...prod3,label hold the first line of matching info
! Does some work ...
! Continue reading the file until the line is no longer about a PHOT
! reaction beginning with species
do while(trim(reac1).eq.trim(species).AND.
& label(1:4).eq.'PHOT')
if(label(5:5).ne.'O') then
! Does some work ...
else
! Does some work ...
! The following print statements are for testing purposes
print*, "AT SPECIES: ", species
print*, "ON LINE: ", reac1,reac2,prod1,prod2,prod3,label
endif
stat = 0
READ(12, 667, IOSTAT=stat) reac1,reac2,prod1,prod2,prod3,
& label
print*, "NEXT LINE: ",reac1,reac2,prod1,prod2,prod3,label,
& stat
if(stat.ne.0) then
label = 'DONE ' !breaks while
endif
enddo
close(12)
使用此代码我得到输出:(原谅可怜的格式化)
AT SPECIES: H2O
ON LINE: H2O HV H OH PHOTO
NEXT LINE: O3 HV O2 O1D PHOTP 0
AT SPECIES: CO2
ON LINE: CO2 HV CO O PHOTO
NEXT LINE: CO2 HV CO O1D PHOTO 0
AT SPECIES: CO2
ON LINE: CO2 HV CO O1D PHOTO
NEXT LINE: CO OH CO2 H WEIRD 0
AT SPECIES: H2CO
ON LINE: H2CO HV H2 CO PHOTO
NEXT LINE: H2CO HV HCO H PHOTO 0
AT SPECIES: H2CO
ON LINE: H2CO HV HCO H PHOTO
NEXT LINE: HCO HV H CO 2BODY 0
AT SPECIES: CH4
ON LINE: CH4 HV CH21 H2 PHOTO
NEXT LINE: CH4 HV CH3 H PHOTO 0
AT SPECIES: CH4
ON LINE: CH4 HV CH3 H PHOTO
NEXT LINE: CH4 HV CH23 H H PHOTO 0
AT SPECIES: CH4
ON LINE: CH4 HV CH23 H H PHOTO
NEXT LINE: C OH CO H 2BODY 0
AT SPECIES: CH
ON LINE: CH HV C H PHOTO
NEXT LINE: CH S CS H 2BODY 0
AT SPECIES: CH2CO
ON LINE: CH2CO HV CH23 CO PHOTO
NEXT LINE: CH23 CO CH2CO WEIRD 0
AT SPECIES: C2H2
ON LINE: C2H2 HV C2H H PHOTO
NEXT LINE: C2H2 HV C2 H2 PHOTO 0
AT SPECIES: C2H2
ON LINE: C2H2 HV C2 H2 PHOTO
NEXT LINE: C2H2 OH CO CH3 2BODY 0
AT SPECIES: C2H4
ON LINE: C2H4 HV C2H2 H2 PHOTO
NEXT LINE: C2H4 HV C2H2 H H PHOTO 0
AT SPECIES: C2H4
ON LINE: C2H4 HV C2H2 H H PHOTO
NEXT LINE: CH23 CH3 C2H4 H 2BODY 0
AT SPECIES: CH3CHO
ON LINE: CH3CHO HV CH3 HCO PHOTO
NEXT LINE: CH3CHO HV CH4 CO PHOTO 0
AT SPECIES: CH3CHO
ON LINE: CH3CHO HV CH4 CO PHOTO
NEXT LINE: C2H5 CH3 C3H8 WEIRD 0
AT SPECIES: C3H8
ON LINE: C3H8 HV C3H6 H2 PHOTO
NEXT LINE: C3H8 HV C2H6 CH21 PHOTO 0
AT SPECIES: C3H8
ON LINE: C3H8 HV C2H6 CH21 PHOTO
NEXT LINE: C3H8 HV C2H4 CH4 PHOTO 0
AT SPECIES: C3H8
ON LINE: C3H8 HV C2H4 CH4 PHOTO
NEXT LINE: C3H8 HV C2H5 CH3 PHOTO 0
AT SPECIES: C3H8
ON LINE: C3H8 HV C2H5 CH3 PHOTO
NEXT LINE: C2H C3H8 C2H2 C3H7 2BODY 0
AT SPECIES: C3H6
ON LINE: C3H6 HV C2H2 CH3 H PHOTO
NEXT LINE: C3H6 HV CH2CCH2 H2 PHOTO 0
AT SPECIES: C3H6
ON LINE: C3H6 HV CH2CCH2 H2 PHOTO
NEXT LINE: C3H6 HV C2H4 CH23 PHOTO 0
AT SPECIES: C3H6
ON LINE: C3H6 HV C2H4 CH23 PHOTO
NEXT LINE: C3H6 HV C2H CH4 H PHOTO 0
AT SPECIES: C3H6
ON LINE: C3H6 HV C2H CH4 H PHOTO
NEXT LINE: C2H5CHO HV C2H5 HCO PHOTO 0
AT SPECIES: C2H5CHO
ON LINE: C2H5CHO HV C2H5 HCO PHOTO
NEXT LINE: H2O O1D OH OH 2BODY 0
AT SPECIES: C3H3
ON LINE: C3H3 HV C3H2 H PHOTO
NEXT LINE: CH3C2H HV C3H3 H PHOTO 0
AT SPECIES: CH3C2H
ON LINE: CH3C2H HV C3H3 H PHOTO
NEXT LINE: H2O O1D OH OH 2BODY 0
AT SPECIES: CH2CCH2
ON LINE: CH2CCH2 HV C3H3 H PHOTO
NEXT LINE: CH2CCH2 HV C3H2 H2 PHOTO 0
AT SPECIES: CH2CCH2
ON LINE: CH2CCH2 HV C3H2 H2 PHOTO
NEXT LINE: CH2CCH2 HV C2H2 CH23 PHOTO 0
AT SPECIES: CH2CCH2
ON LINE: CH2CCH2 HV C2H2 CH23 PHOTO
NEXT LINE: C2H6 HV CH23 CH23 H2 PHOTO 0
AT SPECIES: C2H6
ON LINE: C2H6 HV CH23 CH23 H2 PHOTO
NEXT LINE: H2O O1D OH OH 2BODY 0
稍微澄清一下,AT SPECIES:告诉我与reac1匹配的物种。 ON LINE打印符合要求(种类和PHOT)的行信息。 NEXT LINE打印下一行读取的行。
我的虫首先出现在物种CH3C2H上。从输出中可以看出,CH3C2H的一条反应线被读取(从输出底部向上15行)。然而,NEXT LINE印刷为“H2O O1D OH OH 2BODY”。在react.rx(应该被读取)的下一行显然是“CH3C2H HV C3H2 H2 PHOTO”。这是我感兴趣的反应,但由于某种原因,行读取是第一行反应.rx。 C2H6也会出现同样的问题(最后在输出中)。对于这个物种,应该从reactions.rx中读取另外5行,但是在第一行NEXT LINE变为H2O后,再次读取...... 2BODY。 H2O行正确地结束了do循环,所以我的问题是我不明白为什么在这两种情况下会读取错误的行。
虽然在某些情况下我评论“!做了一些工作......”但代码更多,因为你可以看到我感兴趣的实际打印和读取语句之间没有其他代码。因此,我不相信它是变量/存储的问题,它似乎是我的循环或实际读取的某种错误。我确信正在阅读正确的文件(reactions.rx)。我甚至对它进行了更改并在代码中打印出整个内容以确保它是正在读取的文件。
我不能为我的生活弄清楚为什么会发生这种错误,特别是因为除了上面讨论的两个以外,代码完全符合其他所有物种的意图。我们非常感谢人们提供的任何帮助或建议。
我正在使用Windows 10机器上的gfortran 5.3.0进行编译。
答案 0 :(得分:1)
您在问题的评论中问我“我的代码版本”。 我所做的是将你的代码变成一个子程序,然后用
调用CALL READ_REACTIONS(species)
首先,这是您的代码,最低限度修改:
SUBROUTINE READ_REACTIONS(species)
implicit none
character(len=10) :: species
character(len=10) :: reac1, reac2, prod1, prod2
character(len=8) :: prod3
character(len=5) :: label
integer stat
PRINT *, "Searching for species " // species
OPEN(12, file="reactions.rx", action="READ")
667 FORMAT(A10, A10, A10, A10, A8, A5)
stat = 0
! Reads until a line is found in reactions.rx with reactant1 == species
! and label beginning with "PHOT"
do while((trim(reac1).ne.trim(species).OR.label(1:4).ne.'PHOT')
& .AND.stat == 0)
READ(12,667,IOSTAT=stat) reac1,reac2,prod1,prod2,prod3,label
end do
if(stat.ne.0) then
print*, " *** Species not in reactions.rx!!!! *** "
GOTO 999 ! < You had a STOP here, but I'd rather make a clean
! exit including the CLOSE
endif
! reac1...prod3,label hold the first line of matching info
! Does some work ...
! Continue reading the file until the line is no longer about a PHOT
! reaction beginning with species
do while(trim(reac1).eq.trim(species).AND.
& label(1:4).eq.'PHOT')
if(label(5:5).ne.'O') then
! Does some work ...
else
! Does some work ...
! The following print statements are for testing purposes
print*, "AT SPECIES: ", species
print*, "ON LINE: ", reac1,reac2,prod1,prod2,prod3,label
endif
stat = 0
READ(12, 667, IOSTAT=stat) reac1,reac2,prod1,prod2,prod3,
& label
print*, "NEXT LINE: ",reac1,reac2,prod1,prod2,prod3,label,
& stat
if(stat.ne.0) then
label = 'DONE ' !breaks while
endif
enddo
999 CONTINUE ! <-- added label for the clean exit if species not found.
close(12)
END SUBROUTINE READ_REACTIONS
正如您所看到的,我只添加了声明块和OPEN
语句,并在关闭文件之前将STOP
更改为GOTO
。
我没有完整的reactions.rx
,但是根据您提供的代码段,它运行正常。
我还创建了自己的read_reactions
版本,我认为这个版本更容易理解。我将整个事情包装在一个模块中,这样我就不需要声明一个显式接口了。在实际代码中,我实际上会做出更好的错误处理,但这篇文章已经太长了。
module mod_read_reactions
implicit none
character(len=*), parameter :: fmt = "(4(A10), A8, A5)"
character(len=*), parameter :: file_name = 'reactions.rx'
contains
subroutine read_reactions(species)
implicit none
character(len=10), intent(in) :: species
integer :: iounit, ios
character(len=200) :: iomsg
character(len=10) :: reac1, reac2, prod1, prod2
character(len=8) :: prod3
character(len=5) :: label
open( newunit=iounit, file=file_name, iostat=ios, &
iomsg=iomsg, status="old", action="read" )
if ( ios /= 0 ) stop "Error opening file " ! Suggest better error handling
searchloop : do
read(iounit, fmt, iostat=ios, iomsg=iomsg) &
reac1, reac2, prod1, prod2, prod3, label
if (ios /= 0) then
print *, "Species " // trim(species) // " not found."
goto 999
end if
if (reac1 == species .and. label == "PHOTO") exit searchloop
end do searchloop
do while (ios == 0 .and. reac1 == species .and. label == 'PHOTO')
! When we come in here, we should already have the first match, so we can
! immediately act upon it (in this case just print it out)
print *, reac1, reac2, prod1, prod2, prod3, label
! Now read the next line.
read(iounit, fmt, iostat=ios, iomsg=iomsg) &
reac1, reac2, prod1, prod2, prod3, label
end do
999 continue
close(iounit)
end subroutine read_reactions
end module mod_read_reactions
我应该补充一点,这段代码仍在重新打开并关闭每个新物种请求的文件,这不太聪明。