前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Fortran中的陷阱-NAMELIST

Fortran中的陷阱-NAMELIST

作者头像
用户7592569
发布2020-07-27 14:53:40
3.4K0
发布2020-07-27 14:53:40
举报
文章被收录于专栏:量子化学

1. NAMELIST简介

NAMELIST(有名列表)是一种特殊的I/O方法,它将一组变量和数值封装在一起,进行输入/输出操作。其声明形式如下:

代码语言:javascript
复制
NAMELIST /nl_group_name/ var1[,var2,...]

其中nl_group_name是有名列表的名字,var1、var2等是列表中的变量。同一个NAMELIST中可以有不同类型的变量或数组。

NAMELIST的输出语句形式如下:

代码语言:javascript
复制
WRITE(UNIT=unit,NML=nl_group_name,[...])

其中unit是数据写入的I/O单元,nl_group_name是被写的有名列表的名字。当执行WRITE语句时,列表中的所有变量名都会和其值一起按照特定的顺序输出。输出的第一项是&,然后紧跟列表的名字,然后是一系列按照"Name=Value"格式的输出值。最后,列表以一个斜杠/结束。每个数值的输出格式是由编译器自行决定的。

例如,对有名列表

NAMELIST /MYLIST/ i,j

当i=1,j=2时

执行WRITE(UNIT=*,NML=MYLIST)后,屏幕会显示

&MYLIST

I = 1,

J = 2

/

有名列表的READ语句通用形式如下:

代码语言:javascript
复制
READ(UNIT=unit,NML=nl_group_name,[...])

其中unit是将要读取数据的I/O单元,nl_group_name是被读的有名列表的名字。当执行表控有名列表的READ语句时,程序搜索带有&nl_group_name的输入文件行,它表示有名列表的开始。然后读取有名列表中的所有数值,直到碰到字符"/"终止READ。列表变量可以不出现在输入文件的有名列表中,此时READ前后这些变量的值保持不变。而且输入文件中列表变量可以出现在&nl_group_name和字符"/"间的任意一行。

使用NAMELIST可以比较方便地在程序之间传递一系列数据,省去了很多文件读写格式上的麻烦。

2. 陷阱展示

2.1 操作环境

编译器:ifort 19.0.1.144

操作系统:Ubuntu 18.04.2

2.2 文件准备

现在我们先创建一个包含NAMELIST的MODULE,将其写在namelist.f90中:

代码语言:javascript
复制
module namelist_module
    implicit none
    integer :: i,j
    namelist /int_list/ i
end module namelist_module

注意,此时namelist_module中有i和j两个值,但是int_list中目前只有一个i。

然后写一个主程序完成NAMELIST的READ和WRITE,将其写在Pitfall.f90中:

代码语言:javascript
复制
program main
    use namelist_module
    implicit none
    integer :: io
    open(newunit=io,file='Input')
    read(unit=io,nml=int_list)
    write(unit=*,nml=int_list)
end program

NAMELIST的输入是通过读取文件Input完成的,输出则是直接输出到屏幕上。Input的内容为:

& int_list

i=1

/

为了方便编译,需要写一个Makefile文件,内容如下:

代码语言:javascript
复制
namelist.o : namelist.f90
  ifort namelist.f90 -c
Pitfall.o : Pitfall.f90
  ifort Pitfall.f90 -c
Pitfall : namelist.o Pitfall.o 
  ifort namelist.o Pitfall.o -o Pitfall
clean :
  rm -f *.o *.mod && rm -f Pitfall

2.3 开始操作

2.3.1 程序编译

命令行输入:

代码语言:javascript
复制
make Pitfall

屏幕输出:

代码语言:javascript
复制
ifort namelist.f90 -c
ifort Pitfall.f90 -c
ifort namelist.o Pitfall.o -o Pitfall

说明程序编译正常结束。

2.3.2 程序运行

命令行输入

代码语言:javascript
复制
./Pitfall

屏幕输出:

&INT_LIST

I = 1

/

NAMELIST输出正常。

2.3.3 修改源代码与Input文件

将namelist.f90中的第4行改写为

代码语言:javascript
复制
namelist /int_list/ i,j

即namelist中多出了一个变量j。

在Input中第3行插入

j=2

即在Input中读取变量j的值。

2.3.4 重新编译程序

命令行输入:

代码语言:javascript
复制
make Pitfall

屏幕输出:

代码语言:javascript
复制
ifort namelist.f90 -c
ifort namelist.o Pitfall.o -o Pitfall

说明程序编译正常结束。注意,由于我没有修改Pitfall.f90,Pitfall.f90没有被重新编译。

2.3.5 重新运行程序

命令行输入

代码语言:javascript
复制
./Pitfall

屏幕输出:

代码语言:javascript
复制
forrtl: severe (19): invalid reference to variable in NAMELIST input, unit -129, file /home/zxli/Documents/Pitfall-in-Fortran/namelist/Input, line 3, position 2
Image              PC                Routine            Line        Source             
Pitfall            00000000004441CB  Unknown               Unknown  Unknown
Pitfall            0000000000411446  Unknown               Unknown  Unknown
Pitfall            0000000000402C13  Unknown               Unknown  Unknown
Pitfall            0000000000402B02  Unknown               Unknown  Unknown
libc-2.27.so       00001552E1EE0B97  __libc_start_main     Unknown  Unknown
Pitfall            00000000004029EA  Unknown               Unknown  Unknown

这说明重新编译过后,程序无法正常读取新的NAMELIST中的变量j。

2.3.6 再次修改并重新运行程序

将Input中的在步骤3中添加的内容删除,再次运行程序。

命令行输入

代码语言:javascript
复制
./Pitfall

屏幕输出:

&INT_LIST

I = 1

/

这说明主程序认为NAMELIST中只有变量i。这是因为步骤4中Pitfall.f90没有被重新编译。

2.3.7 再次重新编译并运行程序

命令行输入

代码语言:javascript
复制
make clean && make Pitfall

屏幕输出:

代码语言:javascript
复制
rm -f *.o *.mod && rm -f Pitfall
ifort namelist.f90 -c
ifort Pitfall.f90 -c
ifort namelist.o Pitfall.o -o Pitfall

重新在Input第3行插入

j=2

命令行输入

代码语言:javascript
复制
./Pitfall

屏幕输出:

&INT_LIST

I = 1,

J = 2

/

此时程序正常运行。

3. 总结

当NAMELIST写在MODULE中时,修改NAMELIST的内容,但不重新编译调用了这个MODULE的代码,就会出现错误。为了解决这个问题,可以在每次修改NAMELIST后重新编译所有文件,或者在Makefile中让调用了MODULE的文件依赖写有NAMELIST的MODULE文件。

参考资料:《Fortran 95/2003 程序设计 : 第3版》,p547-549

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-12-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 量子化学 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档