chaoshu的个人博客分享 http://blog.sciencenet.cn/u/chaoshu

博文

bctot出现Fortran语法错误分析(1)

已有 4436 次阅读 2021-6-21 18:28 |个人分类:GAMIT/GLOBK|系统分类:科研笔记

$ bctot 2021 161 brdc1610.21n tbrdc1.161


STATUS :210621:1732:31.0 BCTOT/orbits/bctot: Started BCTOT ver. 10.15 2020/02/3 17:00:00 UTC (Linux) Library ver. 11.34 of 2020/03/17 20:40 UTC (Linux)

STATUS :210621:1732:31.0 BCTOT/orbits/openb: Opened print file: (Name bctot.out)

STATUS :210621:1732:31.0 BCTOT/orbits/openb: Opened output T-file: (Name tbrdce.161)

STATUS :210621:1732:31.0 BCTOT/orbits/openb: Opened input navigation file: (Name brdc1610.21n)

STATUS :210621:1732:31.0 BCTOT/bctot: Opened session.info

STATUS :210621:1732:31.0 BCTOT/orbits/bctot: Successfully read broadcast navigation file: (Name brdc1610.21n)

WARNING:210621:1732:31.0 BCTOT/orbits/bctot: No X-file, using all satellites on the nav-file

STATUS :210621:1732:31.0 BCTOT/orbits/bctot:  Earth-fixed T-file tbrdce.161       being created

STATUS :210621:1732:31.0 BCTOT/orbits/bctot: Successfully wrote earth-fixed T-file: (Name tbrdce.161)

STATUS :210621:1732:31.0 BCTOT/orbits/openb: Opened print file: (Name trot.out)

STATUS :210621:1732:31.0 BCTOT/orbits/openb: Opened output T-file: (Name tbrdc1.161)

STATUS :210621:1732:31.0 BCTOT/orbits/openb: Opened input T-file: (Name tbrdce.161)

STATUS :210621:1732:31.0 BCTOT/orbits/trot: Input T-file is Earth-fixed, converting to inertial

At line 140 of file thdred.f (unit = 16, file = 'tbrdce.161')

Fortran runtime error: I/O past end of record on unformatted file

Error termination. Backtrace:

#0  0x7fd6c74dbea7 in ???

#1  0x7fd6c74dca45 in ???

#2  0x7fd6c74dd1fc in ???

#3  0x7fd6c75acb60 in ???

#4  0x7fd6c7c1baa5 in ???

#5  0x7fd6c7c0e6be in ???

#6  0x7fd6c7c0763d in ???

#7  0x7fd6c7c014b5 in ???

#8  0x7fd6c6d41b96 in ???

#9  0x7fd6c7c01509 in ???

#10  0xffffffffffffffff in ???

上面, 显示错误发生在thdred.f函数中,打开/opt/gamit10.71/gamit/lib/thdred.f查看140行代码:

read(iut) comt,nsat,nintrs, (satnam(isat),(tsatic(i,isat),i=1,nics),isat=1,nsat)

发现在读取T-file的第二行头文件时出现错误!

image.png

IUT的含义在函数头有注释说明:

image.png

thdred.f是被trot.f调用的,查看/opt/gamit10.71/gamit/orbits/trot.f

image.png

出现intin变量在openb.f中边赋值:

image.png

打开/opt/gamit10.71/gamit/orbits/openb.f后,看到了IUTIN=16的赋值!


image.png

终于排查到At line 140 of file thdred.f (unit = 16, file = 'tbrdce.161')这句话错误原因!

OPEN ( UNIT=IUTIN,FILE=tfin,FORM='UNFORMATTED',STATUS='OLD',iostat=ioerr )

注意在Fortran代码中,读取非格式文件

读取文件的时候出现错误,查找写入的情况(thdrit.f为写入头文件函数)

image.png

写入T-file时,第一行语法如下:

 WRITE(iut) HEAD,IME,IDE,IYE,HE,XMINE,SECE

 1              ,IM0,ID0,IY0,H0,XMIN0,SEC0

 2              ,IMF,IDF,IYF,HF,XMINF,SECF

 3              ,DELT,NEPOCH,UT1S,XPOLE,YPOLE

但读取文件的时候为:

 read(iut) head,ite,tee,itb,tbb,itstp,tstp,sdelt,nepcht

然而,第二句头文件部分写入和读取格式一致:

      write(iut) comt,nsat,nintrs

     .          , (satnam(isat),(satics(i,isat),i=1,nics),isat=1,nsat)

      read(iut) comt,nsat,nintrs

     .        , (satnam(isat),(tsatic(i,isat),i=1,nics),isat=1,nsat)

本错误的原因, 很可能就是写入和读取没有严格对应,造成数据读取错误!!

还需要深入研究!对Fortran语法也是一知半解,了解的不够深入!


Fortran中open中有很多参数可以使用,详细如下:

OPEN(UNIT=number, FILE='filename', FORM='...', STATUS='...', ACCESS='...', RECL=length, ERR=label, IOSTAT=iostat, BLANK='...', POSITION='...', ACTION=action, PAD='...', DELIM='...')


UNIT= 'number':   number必须是一个正整数,它可以使用变量或是常量来赋值。number最好避开1,2,5,6。因为2,6是默认的输出位置,也就是屏幕。1,5则是默认的输入位置,键盘。


FILE= 'filename': 指定要打开的文件名称,文件名要符合系统规定。windows下不区分大小写,unix下则会区分大小写,最好不要使用中文文件名。


FORM ='FORMATTED' OR 'UNFORMATTED'

FORM字段只有两个值可以设置:

FORM='FORMATTED'      “文本文件”格式来保存

FORM='UNFORMATTED'   “二进制文件”格式保存

这一栏不给定时候的默认值是: FORM='FORMATTED' 


STATUS ='NEW' or 'OLD' or 'SCRATCH' or 'UNKNOWN' 用来说明打开一个新的文件或已经存在的旧文件。

STATUS='NEW'        打开一个原本不存在的新文件

STATUS='OLD'         打开一个原来已经存在的文件

STATUS='REPLACE'   若文件已经存在则重新创建一次,原来的内容消失;若不存在则会创建新文件。

STATUS='SCRATCH'   表示要打开一个暂存文盘,这个时候可以不需要指定文件名称,也就是FILE这个一栏可以忽略。因为程序本身会自动取一个文件名,至于文件名是啥也不重要,因为暂存盘会在程序结束后自动删除。

STATUS='UNKNOWN' 由各编译器自定义。通常会同REPLACE的效果。

!这一栏不给定时,默认为STATUS='UNKNOWN'。


ACCESS ='SEQUENTIAL' or 'DIRECT'   设置读写文件的方法:

ACCESS='SEQUENTIAL'    读写文件的操作会以“顺序”的方法来做读写,“顺序读取文件”。

ACCESS='DIRET'          读写文件的操作可以任意指定位置,“直接读取文件”。

!不赋值时候,默认为: ACCESS='SEQUENTIAL'。


RECL =length 在顺序读取文件中,RECL字段值用来设置一次可以读取多大容量的数据。

打开“直接读取文件”,RECL=length的length值是用来设置文件中每一个模块单元的分区长度。

length的单位在文本根式下为1个字符,也就是1 byte。在二进制格式下则由编译器自行决定,一般可能为1 byte (G77) 或 4 byte (Visual Fortran)。


ERR=LABEL  这个字段用来设置当文件打开发生错误时,程序会跳跃到LABEL所指定的行代码处来继续执行程序。


IOSTAT=var  这个字段会设置一个整数值给后面的整型变量,这是用来说明文件打开的状态,数值会有下面三种情况:

var>0     表示读取操作错误

var=0     表示读取操作正常

var<0     表示文件终了


BLANK ='NULL' or 'ZERO' 用来设置输入数字时,当所设置的格式字段中有空格存在时所代表的意义。

BLANK='NULL'时,空格代表没有东西。BLANK='ZERO'时,空格部分会自动以0代入。


以下是Fortran 90添加的功能:

POSITION ='ASIS' or 'REWIND' or 'APPEND'   设置文件打开时候的读写位置:

POSITION='ASIS'   表示文件打开时的读取的位置不特别指定,通常就是在文件的开头。是默认值。

POSITION='REWIND'      表示文件打开时的读取位置移到文件的开头。

POSITION='APPEND'     表示文件打开时的读取位置移到文件的结尾。


ACTION ='READ' or 'WRITE' or 'READWRITE'   设置打开文件的读写权限:

ACTION='READWRITE'    表示所打开的文件可以用来读取及写入,这是默认值。

ACTION='READ'          表示所打开的文件只能用来读取数据。

ACTION='WRITE'         表示所打开的文件只能用来写入数据。


PAD ='YES' or 'NO'

PAD='YES'   在格式化输入时,最前面的不足字段会自动以空格填满,默认值是


http://fcode.cn/guide-86-1.html

Fortran流文件-读写二进制任意位置

一. Fortran 读取二进制文件的直接读取法

本站曾发布文章:《Fortran 二进制文件读写》,介绍了以直接读取法进行二进制文件读写的方法。阅读本文前,如有必要,您可先阅读此文,以便了解二进制文件的基本概念。

直接读取(Access = 'Direct' )时,需指定记录长度(RecL)。

而不少二进制文件,其结构不规则,间或有 2 字节、4 字节 或 8 字节、甚至其他长度的数据,例如 SEGY 记录、Surfer 的 grid 网格化文件,此时使用直接读取会显得非常笨拙,常常需要多次 Open 同一个文件,使用不同的 RecL,以便读写特定的数据。

网络上曾有不少文章,介绍可以自由读写任意字节或位置的 fortran 代码,但通常使用扩展的语法实现。或者通过调用操作系统的 API 实现,不规范、只适合一部分编译器。

二. 流文件的基本用法

流文件(access="stream")是 Fortran2003 新增的一种读写方式,目前主流的尚在更新的编译器均支持。(包括但不限于 IVF、GFortran、PGI、NAG、Lahey、Ftn95、Absoft ,不含 CVF 和 PowerStation )

它是一种读写方式,而不是文件本身的格式。它并不把二进制文件视为一个一个的“记录”,而是视为一个整体。因此,无需指定记录长度(RecL)。

文件打开后,操作位置就在文件的第一个字节上,每次读取多少字节,就自动向后移动多少字节。下一次读写紧接着此处。

同时,流文件也提供任意位置(字节数),以及查询当前位置的方法。

1. 打开流文件
一个典型的流文件读写二进制,可使用以下语句:
Open( 12 , File = "fcode_test.bin" , access="stream" , form = "unformatted" )
access 指定打开方式为流文件,form 指定文件为无格式文件(二进制文件)

2.读写
读写时也无需指定记录(rec),典型的读取语句:
Read( 12 ) 变量1 , 变量2 , 变量3...... 变量 N
此时,在当前操作位置读写。读写后,操作位置自动向后移动 M 个字节(M等于所有读写的变量占有的字节数)
注意:无格式读写,不能指定格式,也不能写 * 

如果想在其他位置读写,可使用这样的语句:
Read( 12 , pos = i ) 变量1 , 变量2 , 变量3...... 变量 N
此时,在第 i 个字节处开始读取。读写后,操作位置相对 i 向后移动 M 个字节(M 同上)

3.查询当前操作位置
经过若干 read 语句或 write 语句后,可能就不知道当前读取位置在哪儿了。此时,可通过 Inquire 查询:
Inquire( 12 , Pos = i )
以上语句执行后,i 的值会变为 12 号文件当前的操作位置(字节数)

4.设置当前操作位置
我们经常要跳过若干字节,或回退若干字节进行读写。这可以通过查询操作位置后,加减一定数量,再设置为当前操作位置。例如:
Inquire( 12 , Pos = i )
Read( 12 , Pos= i + 32 , iostat = iErr )
用 Read 语句来设置当前位置为 i + 32(即向后跳过 32 字节),而 Read 后面没有任何变量。
iostat = iErr 可以防止超过文件大小而出错。

5.关闭流文件
使用 Close(12)  关闭,与常规文件没有区别。

可以看出,流文件方式读写,比直接读写更简单,更容易理解。


三. 读取 Surfer 网格化 grd 文件的范例

Surfer 是 Goldensoft 公司出品的一款绘图软件,以等值线绘制为特长,广泛应用在地质、水文等领域。其 grd 文件为(二维)网格化文件。

这种文件有两个版本。6.0 的单精度版本、7.0以上的双精度版本。在这里,我们读取 6.0 的单精度版本,因为它比 7.0 更不规则,更能体现流文件的强大与方便。

以下是它的格式说明
\

可以看出,里面有 4 字节的 char(标识),2 字节的 short(网格大小),8 字节的 double(网格边界:XYZ的最小值最大值),以及 4 字节的 float(网格矩阵)

如果使用直接读写,需要分别考虑读写不同长度数据的记录长度 RecL,多次打开文件。而使用流文件方式,就非常的方便了。

01Program www_fcode_cn
02  Use, Intrinsic :: ISO_C_BINDING !// 使用内部模块,保持与 C 语言变量类型一致
03  Implicit None
04  character(len=4) :: flag !// 4字节的标识,必须为 “DSBB”
05  Integer(kind=C_SHORT) :: , !// 网格大小
06  Real(Kind=C_DOUBLE) :: rXMin , rXMax !// X Y Z 的边界
07  Real(Kind=C_DOUBLE) :: rYMin , rYMax
08  Real(Kind=C_DOUBLE) :: rZMin , rZMax
09  Real , allocatable :: d(:,:) !// 网格矩阵
10  integer :: i
11  Open( 12 , File = "fcode_test.grd" , access="stream" , form = "unformatted" )
12  Read( 12 ) flag
13  Write( * , * ) 'flag=' , flag
14  Read( 12 ) , n
15  Write( * , * ) 'M/N=' , , n
16  allocate( d( , ) )
17  Read( 12 ) rXMin , rXMax , rYMin , rYMax , rZMin , rZMax
18  write( * , * ) 'X_Min=' , rXMin , 'X_Max=' , rXMax
19  write( * , * ) 'Y_Min=' , rYMin , 'Y_Max=' , rYMax
20  write( * , * ) 'Z_Min=' , rZMin , 'Z_Max=' , rZMax
21  Inquire( 12 , Pos = ) !// 查询当前位置
22  write( * , '(a,1x,i4,1x,a)' ) '头部信息一共',i-1,'字节' !//当前操作位置 i 字节
23  Read( 12 ) d(:,:)
24  Do = 1 , n
25    write( * , '(999f6.3)' ) d(:,i)
26  End Do
27  Close( 12 )
28End Program www_fcode_cn


以上代码有注释,相信很容易理解。您可以点这里下载示范数据:focde_test.grd

如果您对派生类型(type)有一定了解,您还可以更方便的一次读取整个头部信息。

01Program www_fcode_cn
02  Use, Intrinsic :: ISO_C_BINDING !// 使用内部模块,保持与 C 语言变量类型一致
03  Implicit None
04  Type , Bind(C) :: GRAD_HEAD
05    character(len=4) :: flag !// 4字节的标识,必须为 “DSBB”
06    Integer(kind=C_SHORT) :: , !// 网格大小
07    Real(Kind=C_DOUBLE) :: rXMin , rXMax !// X Y Z 的边界
08    Real(Kind=C_DOUBLE) :: rYMin , rYMax
09    Real(Kind=C_DOUBLE) :: rZMin , rZMax
10  End Type GRAD_HEAD
11  Type( GRAD_HEAD ) :: Head
12  Real , allocatable :: d(:,:) !// 网格矩阵
13  integer :: 
14  Open( 12 , File = "fcode_test.grd" , access="stream" , form = "unformatted" )
15  Read( 12 ) HEAD
16  allocate( d( HEAD%, HEAD%) )
17  Write( * , * ) 'flag=' , HEAD%flag
18  Write( * , * ) 'M/N=' , HEAD%, HEAD%n
19  write( * , * ) 'X_Min=' , HEAD%rXMin , 'X_Max=' , HEAD%rXMax
20  write( * , * ) 'Y_Min=' , HEAD%rYMin , 'Y_Max=' , HEAD%rYMax
21  write( * , * ) 'Z_Min=' , HEAD%rZMin , 'Z_Max=' , HEAD%rZMax
22  Inquire( 12 , Pos = ) !// 查询当前位置
23  write( * , '(a,1x,i4,1x,a)' ) '头部信息一共',i-1,'字节' !//当前操作位置 i 字节
24  Read( 12 ) d(:,:)
25  Do = 1 , HEAD%n
26    write( * , '(*(f6.3))' ) d(:,i)
27  End Do
28  Close( 12 )
29End Program www_fcode_cn

输出结果应为:
\


image.png


尝试解决:

OPEN ( UNIT=IUTIN,FILE=tfin,ACCESS='STREAM',

.  FORM='UNFORMATTED',STATUS='OLD',iostat=ioerr )

重新编译出现语法错误:

openb.f:71:69:

       OPEN ( UNIT=IUTIN,FILE=tfin,ACCESS='STREAM',FORM='UNFORMATTED',STATUS='OLD'

Error: Syntax error in OPEN statement at (1)




https://blog.sciencenet.cn/blog-858128-1292121.html

上一篇:gamit的tables更新方法
下一篇:bctot出现Fortran语法错误分析(2)
收藏 IP: 119.79.228.*| 热度|

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-4-17 03:20

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部