3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Fortranで動的割付した配列をcsv形式で出力したい場合

Last updated at Posted at 2020-05-07

こんにちは。
この記事では、Fortranで動的割付けallocateされている場合のcsv形式の出力でつまづいた点を共有させていただきます。

##Fortranでcsv形式で出力する場合
x_outをcsv形式を行う場合、下記の通りに記述します。

csv.f90
real(4)        :: x_out(3)
character(256) :: linebuf

open (1, file='./your_outfile.csv', form='formatted', status='replace')
  write(linebuf, '2(f7.2, ","), f7.2)') ! *** (書式設定)
  call del_spaces(linebuf) ! *** (空白を詰めるサブルーチン)
  write(1, '(a)') trim(linebuf)
close(1)

x_out(3)と配列数が決まっている場合は、
Fortranの書式設定に(f7.2, ",")のように記述して、小数点数字とカンマを記述しています。

※書式設定について
()の前に数値を加えると書式設定が数値分反映されますが、配列数から一つ引いた分を記述しています。
配列数を全て加えると最後にカンマを残して出力されてしまうので、配列数から一つ引いた値を繰り返して、最後に独立して同じ書式を再び書いて、カンマをなくしています。

※サブルーチンについて
call del_spacesのサブルーチンは、下記に記述している参考サイトから引用しております。
内容は、通常のwriteでは一つの出力の後に空白を出してしまうので、それを詰める機能となっています。

##本命の部分
以下、今回の状況になります。
上記と同様に、x_outをcsv形式で出力したいと考えています。

上記との違いは,
Fortran内で動的割付をしており、shで配列の大きさを指定して渡し、出力したい点です。

以下、上手く行ったコードです。

compile.sh(${prg}はコンパイル済みの.f90)
nx = 40
today=$(date "+%Y%m%d%H%M")
./${prg} > ./log/${today}.log << EOF
  &set_parm
    nx = ${nx}
  /
EOF
allocate_csv.f90
real(4), allocate :: x_out(:)
integer           :: nx

character(4)      :: cfmt_num
character(24)     :: cfmt
character(256)    :: linebuf

namelist /set_parm/ nx
read(5, nml=set_parm)
allocate(x_out(nx))

write(6,*) '-------------------------------------------------------'
write(6,*) '+++ Check Writing output system,  '
cfmt = '(xx(F12.7, ","), F12.7)'
write(cfmt_num,"(I2)") nx-1
cfmt(2:3) = cfmt_num
open(2, file='./your_outfile.csv', form='formatted', status='replace')
  write(linebuf, cfmt) x_out
  call del_spaces(linebuf)
  write(2,'(a)') linebuf
close(2)
write(6,*) ' && Successfuly output !!!        '  

この場合で、少し手間取った点は下記に記述しました。

  • 書式設定内に変数を入れ込みたい

csv形式を出力したいので、コンマを記述する必要があります。
その際に配列数は動的なので、書式設定内も逐一変更しないで、変数を入れることで解決したいです。

cfmt = '(nx-1(F12.7, ","), F12.7)'
! *** →もちろん、ダメだった。

cfmt = '(' + str(nx) + '(F12.7, ","), F12.7)'
! *** →イメージとしては、こんな感じにしたい。

※ 書式設定内は文字列なので、配列数の整数型の数字を文字列に変換させて結合したいです。

この時、壁は二つあります。

  1. shから受け取った整数を、文字列に変換する。 
    →その際には、@implicit_noneさんの記事を参考にさせていただきました。
  2. 文字列を結合する。
    →fortranの文字列結合には、//がありますが2つ以上の連結では使用できませんでした。

そのため、あらかじめ数字が入るところにxxを入れて、そこにcfmt(2:3) = cfmt_num受け取った整数を文字列化した者を入れることで対応しました。

これらを行った結果、無事に今回のねらいを実装することができました。
より良い書き方などお気づきになった方はコメント等でご教授いただければ幸いです。

同じような点で困った人の手助けになれたら幸いです。
最後まで見ていただき、ありがとうございました。

##参考

・Fortran Tips集: csvファイルを書き出す方法
https://www.nag-j.co.jp/fortran/tips/tips_writeCSV.html
・Fortranで整数を文字列に変換する
https://qiita.com/implicit_none/items/39018f2848b5237fc3ea

3
0
3

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
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?