Fortranで出力したデータを、call system() とシェルスクリプトを使ってその場ですぐに xz で圧縮し、元データは削除する
まえがき
前にも書いたかもだけど忘れそうなのでメモしとく。
まず Fortran 側で FV_00001.xyz, ...(グリッド)とか FV_00001.func, ...(流れ場)とか FV_00001.q, ...(時刻)といったファイルを出力している。これらは流れの可視化用のデータで、そのままだとでかい。計算機からローカルへの転送時間を短縮したいというのもあるけど、それ以上に、計算機自体の/homeディレクトリの節約のために、計算を続けながら、その場ですぐに圧縮したい。圧縮には xz を使ってるけど、お好みで gzip なり bzip2 なりにしてください。
前に書いた
システムコールとシェルスクリプトを利用して、Fortranのコードから「ディレクトリがなければ作る」を実行 - dynamicsoarの日記
と
natures flyers: Fortran で call system() するときに変数 (variable) を渡す方法
も参照。
Fortran側のコード
変数の意味
- n_file_FV
- ファイルの番号(連番)で、保存するごとに増えてくやつ
- if_compress_FV_grid, if_compress_FV_flow, if_compress_FV_q
- いずれも設定ファイルから読み込むパラメタ (integer) で、0, 1, 2 のいずれかを取る。意味は、0=圧縮しない, 1=圧縮してオリジナルデータは残す, 2=圧縮してオリジナルデータは削除。本来の目的からいって、僕は基本的には 2 を使ってるけど、グリッドの位置調整とかには 0 が便利だし、容量節約よりも計算機上での可視化&後でのデータ転送高速化を目的として 1 を使うこともある。
グリッド保存用サブルーチン
!! ファイル名(パスを含む)を設定 write(out_grid,"('./output/FV_grid/FV_',i5.5,'.xyz')") n_file_FV <実際の出力作業は省略> !! 圧縮 write(command,"('sh ./src/compress_output_file.sh ',i1,1x,'grid',1x,i5.5)") if_compress_FV_grid, n_file_FV call system(command)
流れ場保存用サブルーチン
function ファイルなんだけど僕らは伝統的に q ファイルでなくこっちに流れ場を書いてるので。
!! ファイル名(パスを含む)を設定 write(out_func,"('./output/FV_func/FV_',i5.5,'.func')") n_file_FV <実際の出力作業は省略> !! 圧縮 write(command,"('sh ./src/compress_output_file.sh ',i1,1x,'func',1x,i5.5)") if_compress_FV_func, n_file_FV call system(command)
その他データ(自分の場合は時刻のみ)保存用サブルーチン
!! ファイル名(パスを含む)を設定 write(out_q,"('./output/FV_q/FV_',i5.5,'.q')") n_file_FV <実際の出力作業は省略> !! 圧縮 write(command,"('sh ./src/compress_output_file.sh ',i1,1x,'q',1x,i5.5)") if_compress_FV_q, n_file_FV call system(command)
いま考えたらこれら3つのサブルーチンはまとめるべきだな…ほとんど同じなんだから。まぁとりあえずこのまま書いておく。
シェルスクリプト側のコード
シェルスクリプト(bash以外は知らないが)ではイコールの前後に半角スペースを入れたらダメなので注意。参考:bashの変数代入の=の前後にスペースを入れてはいけない理由 - mollifier delta blog
compress_output_file.sh
これが Fortran の call system() で呼ばれる。引数を3つ取る。if_compress_FV_grid/func/q と、ファイルの種類と、n_file_FV の3つ。
そのまま functions.sh という別のファイルにある compress_output_file という関数に全部横流しする(だけ)。
#!/bin/bash ## 関数の読み込み . ./src/functions.sh compress_output_file $1 $2 $3
functions.sh
compress_output_file の部分のみ抜粋。他にもいろいろな関数をまとめておいている。
#!/bin/bash #// if_compress: 0=no compress; 1=compress only; 2=compress & delete original file #// kind: either one of: "grid", "func", or "q" #// FVnum: FV number(Fortran側でいう n_file_FV) #// option: xz のオプション。要は -k を使うかどうか #// 参考: http://shellscript.sunone.me/case.html compress_output_file() { # 引数を変数にセット if_compress=$1 kind=$2 FVnum=$3 ## if_compress に応じて、圧縮の際の option をセット case ${if_compress} in 0 ) return ;; ## 何もしないで関数を抜ける 1 ) option="-f -k" ;; ## 圧縮。元ファイルは残す 2 ) option="-f" ;; ## 圧縮 & 元ファイル削除 * ) "Something's wrong. Check [compress_output_file] in ./src/functions.sh" ;; ## * は case default の意味 esac ## ファイルの種類に応じた圧縮作業 case ${kind} in "grid" ) xz ${option} ./output/FV_${kind}/FV_${FVnum}.xyz & ;; # {kind}はgridなんだけど拡張子はxyzなので場合分けしてる。 "func" | "q" ) xz ${option} ./output/FV_${kind}/FV_${FVnum}.${kind} & ;; # | は or の意味 * ) "Something's wrong. Check [compress_output_file] in ./src/functions.sh" ;; esac }