【问题标题】:Parsing a huge file in Fortran在 Fortran 中解析一个巨大的文件
【发布时间】:2020-08-30 16:04:13
【问题描述】:

我正在尝试解析一个流行的 QM 程序的输出文件,以便提取与两个相关属性相对应的数据:“频率”和“强度”。输出文件的外观示例如下:

 Max difference between off-diagonal Polar Derivs IMax=       2 JMax=       3 KMax=      13 EMax= 8.65D-04
 Full mass-weighted force constant matrix:
 Low frequencies ---   -2.0296   -1.7337   -1.3848   -0.0005   -0.0003    0.0007
 Low frequencies ---  216.4611  263.3990  368.1703
 Diagonal vibrational polarizability:
       18.1080784       9.1046025      11.9153848
 Diagonal vibrational hyperpolarizability:
      127.1032599       2.7794305      -8.7599786
 Harmonic frequencies (cm**-1), IR intensities (KM/Mole), Raman scattering
 activities (A**4/AMU), depolarization ratios for plane and unpolarized
 incident light, reduced masses (AMU), force constants (mDyne/A),
 and normal coordinates:
                     1                      2                      3
                     A                      A                      A
 Frequencies --   216.4611               263.3989               368.1703
 Red. masses --     3.3756                 1.0427                 3.0817
 Frc consts  --     0.0932                 0.0426                 0.2461
 IR Inten    --     3.6192                21.7801                 0.2120
 Raman Activ --     1.0049                 0.1635                 0.9226
 Depolar (P) --     0.6948                 0.6536                 0.7460
 Depolar (U) --     0.8199                 0.7905                 0.8546
  Atom  AN      X      Y      Z        X      Y      Z        X      Y      Z
     1   6     0.00   0.00   0.22     0.00   0.01   0.02     0.06   0.15  -0.01
     2   7     0.00   0.00   0.00     0.00   0.00   0.00     0.10  -0.02   0.00
     3   6     0.00   0.00  -0.23     0.00  -0.01   0.00     0.01  -0.07   0.00
     4   6     0.00   0.00   0.00     0.00   0.00   0.00    -0.08  -0.02   0.00
     5   6     0.00   0.00   0.21     0.00   0.01  -0.03    -0.06   0.15   0.00
     6   6     0.00   0.00   0.11     0.00   0.01   0.00    -0.01   0.17   0.00
     7   7    -0.02   0.00  -0.22     0.00   0.03   0.00    -0.01  -0.26   0.00
     8   1     0.10  -0.02  -0.32     0.02  -0.30   0.66     0.34  -0.39  -0.13
     9   1     0.07  -0.02  -0.39    -0.05  -0.25  -0.63    -0.37  -0.40   0.12
    10   1     0.00   0.00   0.39     0.01   0.01   0.07     0.18   0.22  -0.03
    11   1     0.00   0.00  -0.53     0.00  -0.01   0.01     0.02  -0.15   0.01
    12   1     0.00   0.00  -0.03    -0.01   0.00  -0.02    -0.18  -0.09   0.00
    13   1     0.00   0.00   0.31     0.00   0.00  -0.09    -0.18   0.22   0.03
                     4                      5                      6
                     A                      A                      A
 Frequencies --   411.0849               501.4206               548.5728
 Red. masses --     3.4204                 2.8766                 6.5195
 Frc consts  --     0.3406                 0.4261                 1.1559
 IR Inten    --     4.2311                30.8234                 6.3698
 Raman Activ --     0.1512                 0.8402                 4.2329
 Depolar (P) --     0.7404                 0.1511                 0.4224
 Depolar (U) --     0.8508                 0.2625                 0.5939
  Atom  AN      X      Y      Z        X      Y      Z        X      Y      Z
     1   6     0.00   0.00   0.20     0.00  -0.01   0.01     0.02  -0.12  -0.01
     2   7     0.00   0.00  -0.21     0.00   0.00  -0.16     0.06  -0.18   0.02
     3   6     0.00   0.00  -0.03     0.01   0.00   0.15     0.32  -0.01  -0.02
     4   6     0.00   0.00   0.27     0.01   0.00  -0.08     0.18   0.10   0.01
     5   6     0.00   0.00  -0.23     0.00   0.00  -0.03     0.11   0.19   0.00
     6   6     0.00   0.00  -0.02     0.00   0.00   0.32    -0.26   0.01  -0.04
     7   7     0.00  -0.01   0.01    -0.04   0.00  -0.04    -0.39   0.02   0.04
     8   1    -0.01   0.05  -0.10     0.17   0.03  -0.36    -0.36   0.06  -0.08
     9   1    -0.02   0.04   0.16     0.15  -0.01  -0.35    -0.30   0.02  -0.11
    10   1     0.01   0.01   0.48     0.01   0.00  -0.35     0.22  -0.01   0.03
    11   1     0.00   0.00  -0.12     0.01   0.00   0.23     0.31   0.13  -0.02
    12   1     0.00   0.00   0.54     0.00   0.00  -0.39    -0.02  -0.03   0.05
    13   1    -0.01   0.00  -0.47     0.01   0.00  -0.45     0.34   0.06   0.04
                     7                      8                      9
                     A                      A                      A
 Frequencies --   629.8582               652.6212               716.4846
 Red. masses --     7.0000                 1.4491                 2.4272
 Frc consts  --     1.6362                 0.3637                 0.7341
 IR Inten    --     9.4587               253.3389                18.8342
 Raman Activ --     3.5151                11.7363                 0.2311
 Depolar (P) --     0.7397                 0.2892                 0.7423
 Depolar (U) --     0.8504                 0.4486                 0.8521
  Atom  AN      X      Y      Z        X      Y      Z        X      Y      Z
     1   6     0.24  -0.18  -0.01    -0.02   0.03  -0.04     0.00   0.00  -0.12
     2   7     0.30   0.27   0.02    -0.02   0.00   0.04     0.00   0.00   0.17
     3   6     0.06   0.12  -0.02    -0.03  -0.01  -0.04     0.00   0.00  -0.15
     4   6    -0.23   0.23   0.01     0.02  -0.04   0.02     0.00   0.00   0.18
     5   6    -0.22  -0.20  -0.01     0.02   0.00  -0.04     0.00   0.00  -0.08
     6   6    -0.04  -0.15  -0.02     0.04   0.01  -0.04     0.00   0.00   0.13
     7   7    -0.13  -0.07   0.06    -0.05   0.00   0.14     0.01   0.00  -0.01
     8   1     0.02  -0.03  -0.20     0.30   0.13  -0.57     0.00  -0.02   0.05
     9   1     0.00  -0.12  -0.26     0.29  -0.10  -0.63    -0.01   0.02   0.05

我使用的代码是:

     program gau_parser
     implicit none
     integer :: ierr    ! Error value for read statement
     integer, parameter :: iu = 20 ! input unit
     integer, parameter :: ou = 30 ! output unit
     character (len=*), parameter :: search_str = " Frequencies --"  ! this is the property I'm looking for
     !                                            ^===============^   there are 15 characters here. First character is blank.
     !
     ! NOTE: a typical string looks like this: " Frequencies --   411.0849               501.4206               548.5728"
     !                                           ==============   ========               ========               ========
     !                                             search_str       xx(1)                  xx(2)                  xx(3)
     !
     ! the string length is 73 but may be variable but very seldomly more than 80
     !
     real :: xx(3)                       ! this will be the three values associated to the above property
     character (len=80) :: text
     character (len=15) :: word

    open (unit=iu,file="dummy.log",action="read")   ! read the file I wish to parse
    open (unit=ou,file='output.log',action="write") ! Open a file where I wish the parse results to be written to!

    do                                  ! the search is done line by line, until the end of the file
     read (iu,"(a)",iostat=ierr) text   ! read line into character variable
        
        if (ierr /= 0) then
        cycle                           ! If a reading error occurs, advance to new line
        end if                       
             
    read (text,*) word                  ! read first word of line
    
      if (word == search_str) then      ! found search string at beginning of line
      read (text,*) word,xx             ! read the entire line
      write(30,*) word,xx               ! write the entire line
    end if
    
    end do                              ! finish the search cycle
    end program gau_parser

我的问题如下:

a) 当前代码是可编译的,但在执行时会“挂起”。任何人都可以编译他们自己的版本,看看他们是否发生了同样的事情?什么(用户引起的)错误可能导致这种行为?

b) 如何将 'xx' 的多个值按顺序写入单个数组中?也就是说,它们应该像这样从解析的文件中读取

word xx(1) xx(2) xx(3)
...
junk
...
word xx(4) xx(5) xx(6)
... 
more junk
...
word xx(7) xx(8) xx(9)

我知道我已经在程序中声明了数组的维度(3),但这只是为了测试。实际上,它必须被分配但未指定,直到到达解析文件的末尾,它必须INQUIRE:SIZE。我的想法是将其打印到临时文件中,对其进行评估,然后将其写回内存中,作为xx(INQUIRE:SIZE) 维度数组。任何关于此事的想法都将受到欢迎!


编辑:在尝试调试程序后,我意识到它实际上是在循环!我插入了几个write 语句,看看可能出了什么问题

 open (unit=iu,file="dummy.log",action="read")   ! read the file I wish to parse
        print*,'file opened'
      !  open (unit=ou,file='output.log',action="write") ! Open a file where I wish the parse results to be written to!
        do                                  ! the search is done line by line, until the end of the file
         print*,'Do loop has started'
         read (iu,"(a)",iostat=ierr) text   ! read line into character variable
            
            if (ierr /= 0) then
            write(*,*)'Error!'
            cycle                           ! If a reading error occurs, advance to new line
            end if        

还有……瞧!我的屏幕开始被一阵阵的

填满了
 Error!
 Do has started

消息!本质上,我陷入了一个循环!我哪里失败了?

【问题讨论】:

    标签: parsing fortran


    【解决方案1】:

    代码中有一个细微的错误。声明

    read (iu,"(a)",iostat=ierr) text   ! read line into character variable
    

    从文件中读取一行文本到变量text,它使用编辑描述符"(a)",这意味着text是你所期望的。另一方面声明

    read (text,*) word
    

    使用 listdirected 输入(这就是 * 的含义),并且它不会从该行中获取例如字符串 Frequencies。有助于编译器去除前导空白字符,word 得到字符串 Frequencies(没有前导空格)。这永远不会匹配搜索到的字符串。

    旁白:尤其是在开发代码时不要让循环运行 无限期地,放入一个合理的最大循环迭代,例如do ix = 1,200 用于您的测试用例,这将阻止您浪费时间盯着 永远不会完成的计算。

    代码永远运行的原因是没有结束条件。相反,代码块

    if (ierr /= 0) then
    cycle                           ! If a reading error occurs, advance to new line
    end if 
    

    将执行发送回do 语句 - ad infinitum。我会使用这样的停止条件:

    IF (IS_IOSTAT_END(ierr)) EXIT
    

    函数IS_IOSTAT_END 使您不必弄清楚编译器上文件结尾的错误代码是什么,这些代码的值不是标准化的。 IS_IOSTAT_EOR 对于检查记录结束很有用。

    你会发现下一个错误是语句

    read (text,*) word
    

    也不会使word 匹配Frequencies --。同样,使用 list-directed 输入意味着编译器会将输入文件中的空格视为分隔符,并且该行代码只会将Frequencies 转换为word。但这会导致另一个问题,

    read (text,*) word,xx             ! read the entire line
    

    会尝试将字符串--读入实变量xx,但结果并不理想。

    这一系列问题的一个,也许是解决方案,是在读取语句中使用显式编辑描述符,就像这样。第一次改变

    read (text,*) word
    

    到

    read (text,'(a15)') word
    

    接下来,您必须将xx 的行改为类似

    read (text,'(a15,3(f18.4))') word,xx             ! read the entire line
    

    您会发现,就目前而言,这一行并没有正确地将所有 3 个值读入xx。那是因为编辑描述符3(f18.4) 并不能完全正确地描述行的布局,实际上它可能需要f(18.4),2(fNN.4),当然您可以将NN 替换为文件的适当字段宽度。是时候做一些工作了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-29
      • 2023-03-15
      • 2013-11-07
      • 2014-07-22
      相关资源
      最近更新 更多