#はじめに
長い計算の途中経過を知りたい場合、プログレスバーが欲しくなります。
端末上でプログレスバーを表示するサブルーチンをFortranで作ってみました。
ASCIIコードを指定して出力することで、(cursesライブラリなどがなくても)端末上に色々なメッセージを出すことができます。
#サブルーチン
端末の50文字程度を使ってプログレスバーを表示するサブルーチンです。引数の意味や注意点は以下の通り。
- iparcent 整数型で1〜100までの数
- uni 書き出す装置番号
- 1行前に戻って行末まで削除し、その後進捗を表示
- 本ルーチン呼び出しの合間に他の処理で同一装置番号に出力が有る場合、プログレスバーの表示が崩れます。
subroutine progressbar(iparcent,uni)
use iso_fortran_env
implicit none
integer,intent(in) :: iparcent
integer,intent(in) :: uni
integer :: i
character(len=1),parameter :: esc=achar(27)
character(len=1),parameter :: cr=achar(13)
i=1
write(uni,'(A)',advance='no') esc//"[1A"//esc//"[0J"
write(uni,'(A)',advance='no') cr//"|"
do while(i<iparcent/2)
write(uni,'(A,I3)',advance='no') "="
i=i+1
end do
select case(mod(i,3))
case(0)
write(uni,'(A,I3)',advance='no') "\"
case(1)
write(uni,'(A,I3)',advance='no') "/"
case default
write(uni,'(A,I3)',advance='no') "."
end select
do while(i<100/2)
write(uni,'(A,I3)',advance='no') " "
i=i+1
end do
write(uni,'(A,I3,A)',advance='yes') "|",iparcent,"%"
end subroutine
#テストプログラム
- sleepはGNU拡張なので、コンパイラによっては使えない場合があります。
- 何かの処理の合間に、整数で%を指定してコールするとプログレスバーが表示されます。
- 標準出力に書き出すことが前提で、ファイルに書き出すと読みにくいデータの羅列になります。したがって、出力先はerror_unitとしています。
- 動作確認はLinuxのターミナルで行いました。
program main
use iso_fortran_env
implicit none
integer :: i
!integer :: tb,te,cr,cm
do i=1,100
!call system_clock(tb,cr,cm)
call sleep(1)
call progressbar(i,error_unit)
!call system_clock(te)
end do
end program
#おわりに
数十分程度かかる計算をするとき、こういうルーチンを挟むことで計算時間を見積もり易くなりました。