LoginSignup
5
4

More than 3 years have passed since last update.

[Fortran] ネームリスト

Last updated at Posted at 2019-07-24

Qiita@earth06: 数値モデルにでてくるFORTRAN77文法~完結編#NAMELISTによる変数への値の代入

基本

コード

program main
    implicit none
    character(len=256), parameter :: nml_path = './test.nml'
    integer, parameter :: unit = 11
    integer :: a = 1, b = 2
    namelist /test/ a, b

    open(unit, file=trim(nml_path), status='old')
    read(unit, nml=test)
    close(unit)
    write(*, *) 'a', a
    write(*, *) 'b', b
end program main

ネームリストに該当する変数が存在しない場合,単純に読み込みがスキップされるだけでエラーは発生しない
→デフォルト値を設定しておき,それを変更する場合のみネームリストを使う,ということができる

ネームリスト

書式

&{ネームリスト名前}で始め,/または&endで結ぶ.

test.nml
&test
a = 11
b = 12
/ ! &endでも良い
改行・カンマはなくとも良い

以下はいずれも動作する.但し,/&endのどちらかは必ず必要.

test.nml
&test a = 11  b = 12 /
&test a = 11, b = 12 /
&test a = 11  b = 12 &end
&test a = 11, b = 12 &end

私見:
改行して書くなら終わりは/でも&endでも良いと思うが,
1行に書くなら&endの方が視認性高そう(/だと書き忘れたときに気が付きにくい).

複数のネームリストがある場合,最初にヒットしたものが有効になる

1つ目のネームリストでbを与えない場合,2つ目からbを読み取る,ということはない

test.nml
&test a = 11, b = 12 &end
&test a = 21, b = 22 &end
! -> a = 11, b = 12

&test a = 11 &end
&test a = 21, b = 22 &end
! a = 11, b = 2

ネームリストのコメントアウト

変数のコメントアウト
test.nml
&test
!a = 11
b = 12
/
! -> a = 1, b = 12

aとbを共にコメントアウトしてもOK (-> a = 1, b = 2).
改行のないネームリストとは相性が悪いが,
bをコメントアウトするときはa = 11!, b = 12でもa = 11, !b = 12でも良い.

ネームリスト自体のコメントアウト

最初に示したコードだと,ネームリスト自体&testを削除するのはNG.
しかし,以下の通りIOErrorを陽に処理すると,この場合でも動作する(ネームリストが存在しない場合,デフォルト値のまま).

main.f90
integer :: ios
read(unit, nml=test, iostat=ios)

配列の読み込み

2019年7月24日:ページ分割

ネームリスト内では(/[などで囲まず,配列の要素をそのまま列挙する.

test.nml
&nml_test
a = 1,2,3
/
  • プログラム内で/ネームリスト名/として指定する際には,(:)は付けない
  • ネームリストより配列が大きい場合でも問題なし
  • ネームリストより小さい場合にはエラー
  • 未割り付けの配列に読み込むことは不可

従ってネームリスト内の配列の大きさが分からない場合,

  • 十分大きな配列を用意する
  • センチネル値(ありえない値→その値になったらループを終える)を予め全要素に代入しておく
namelist.f90
program main
    implicit none
    integer, allocatable :: a(:)
    character(len=256), parameter :: nml_path = './test.nml'
    integer           , parameter :: nml_unit = 11, nml_size = 3
    namelist /nml_test/ a ! "a(:)"と書くとコンパイラを通らない

    allocate(a(nml_size)); a(:) = 0
    open(nml_unit, file=trim(nml_path), status='old')
    read(nml_unit, nml=nml_test)
    close(nml_unit)
    write(*, *) a(:) ! 1 2 3
    deallocate(a)

    allocate(a(nml_size+1)); a(:) = 0
    open(nml_unit, file=trim(nml_path), status='old')
    read(nml_unit, nml=nml_test)
    close(nml_unit)
    write(*, *) a(:) ! 1 2 3 0
    deallocate(a)

    allocate(a(nml_size-1)); a(:) = 0
    open(nml_unit, file=trim(nml_path), status='old')
    read(nml_unit, nml=nml_test) ! forrtl: severe (18): too many values for NAMELIST variable
    close(nml_unit)
    write(*, *) a(:)
    deallocate(a)

    open(nml_unit, file=trim(nml_path), status='old')
    read(nml_unit, nml=nml_test) ! forrtl: severe (174): SIGSEGV, segmentation fault occurred
    close(nml_unit)
    write(*, *) a(:)
    deallocate(a)
end program main
5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4