Skip to content

forbearProgress bars for Fortran

Bars, spinners, ETA and messages for long-running Fortran programs: one object, three calls, pure Fortran 2008. On a terminal it animates; in a batch log it writes clean lines.

forbear

a pretend CFD run: a mesh bar, then nested time-step and Newton bars, with checkpoints printed above, a residual and the ETA, and a closing summary

A (pretend) CFD run: nested bars, messages above the bar, ETA and summary. Every frame is drawn by forbear.

Quick start ​

Initialize the bar, start it, update it at every step: this is a whole program.

f90
program minimal
!< The smallest progress bar: the default range is [0, 1].
use, intrinsic :: iso_fortran_env, only : R8P=>real64
use forbear, only : bar_object
implicit none
type(bar_object) :: bar ! the progress bar
real(R8P)        :: x   ! progress, in [0, 1]
integer          :: i   ! counter
integer          :: j   ! counter
real(R8P)        :: y   ! work result

x = 0._R8P
call bar%initialize(filled_char_string='+', prefix_string='progress |', suffix_string='|',  &
                    add_progress_percent=.true.)
call bar%start
do i = 1, 20
   x = x + 0.05_R8P
   do j = 1, 1000000
      y = sqrt(x) ! just spend some time
   enddo
   call bar%update(current=x)
enddo
if (y < 0._R8P) print *, y
endprogram minimal
$ minimal
progress |++++++++++++++++++++++++++++++++| 100%

A 1980s dashboard ​

Segments lit and unlit, a redline, a rising tachometer, a scanner and seven-segment numbers: theme, bar_zones, bar_profile, pulse_trail and digits.

three bars at once: a blue-green segmented bar with a redline, an amber rising ramp, a red scanner, seven-segment numbers

All of it in chapter 11 of the tutorial.

40 spinners ​

Every spinner of forbear is a bar too: here eighteen of them, each one a bar on its own line.

eighteen spinners animating, one per line

The whole catalogue is in Spinners.

Every kind of output forbear draws, each the real output of a program of the docs (on a terminal, at the end of the run or while running); the title leads to its recipe in the cookbook.

The bar ​

The smallest bar

$ minimal
progress |++++++++++++++++++++++++++++++++| 100%

A bar over the steps of a loop

$ march
********************************
march: 50 time steps done

A loop of many iterations

$ many
records ******************************** 100%

A smooth bar

$ march
march β–•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–                     ▏

A Unicode bar

$ march
march β–•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–‘β–

Colours and dashboard looks ​

A coloured, solid bar

$ march
march [β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ] time steps

Exact colours, #rrggbb

$ march
march β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ  50%

A redline: colours by position

$ tach
RPM β–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œ  80%

A rising ramp

$ tach
RPM β–β–β–β–β–β–β–‚β–‚β–‚β–‚β–‚β–‚β–ƒβ–ƒβ–ƒβ–ƒβ–ƒβ–„β–„β–„β–„β–„β–„β–…β–…β–…β–…β–…β–†β–†β–†β–†β–†β–†β–‡β–‡β–‡β–‡β–‡β–ˆ  80%

Seven-segment numbers

$ march
march β–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œ 🯸🯸🯡% 🯸🯸🯷/🯱🯲🯰

Three dashboard themes

$ march
vfd   β–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œ  58%
amber β–β–β–β–β–β–‚β–‚β–‚β–‚β–ƒβ–ƒβ–ƒβ–ƒβ–„β–„β–„β–„β–…β–…β–…β–…β–†β–†β–†β–†β–‡β–‡β–‡β–‡β–ˆ  58%
kitt  β–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œβ–Œ 29

What the bar reports ​

Percent, count, speed, ETA, scale, times, summary

$ march
      [ 0.00 (min)        (max) 50.00]
march [##############################] 100% 50/50 ( nn.nn%/s) ETA hh:mm:ss
[yyyy/mm/dd hh:mm:ss - yyyy/mm/dd hh:mm:ss]
[done in n.nn s, nn.nn/s]

A prefix that names the phase

$ march
solve    [***********************-------]  78%

Spinners and counters ​

A spinner next to the bar

$ march
march [####################....................] β ΄

A spinner alone

$ march
march [########################################] β ‹
march β ΄

A percentage alone

$ march
march [########################################] β ‹
march β ‹
march   50%

Talking while the bar runs ​

Lines above the bar, a message at its end

$ march
step 10: solution saved
step 20: solution saved
step 30: solution saved
step 40: solution saved
step 50: solution saved
march [##############################] 100% residual 8.88E-16

Output of a library while the bar runs

$ march
io_library: writing solution_0020.h5
io_library: done, 2.1 MB
io_library: writing solution_0040.h5
io_library: done, 2.1 MB
march [##############################] 100%

Many bars ​

A bar for each loop of a nest

$ march
time step [β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ                  ] 2/5
  newton  [β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ            ]  6/10

Several bars one after another

$ sequence
mesh     ********************************
solve    ********************************
write    ********************************
mesh     [==============================] 100%
solve    [==============================] 100%
write    [==============================] 100%

Layouts and fields ​

A layout of your own

$ layout
load  50% [**********----------]  6/12 files, hh:mm:ss left

A field of your own

$ march
march β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 100% step 50/50 ETA hh:mm:ss res 8.9E-16

Unknown ends ​

A loop of unknown length

$ march
solve β ‡ [........#####.......] 8 iterations, hh:mm:ss

A scanner for a loop of unknown length

$ solve
solve β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬β–¬ 31

Leaving a loop early

$ march
solve β ™ [####################] 20 iterations, hh:mm:ss
march [##################............]  60% steady state

Logs, batch jobs and other units ​

A clean log in a batch job

$ march > run.log; cat run.log
march [..............................]   0%  0/50 ETA --:--:--
march [###...........................]  10%  5/50 ETA hh:mm:ss
march [######........................]  20% 10/50 ETA hh:mm:ss
march [#########.....................]  30% 15/50 ETA hh:mm:ss
march [############..................]  40% 20/50 ETA hh:mm:ss
march [###############...............]  50% 25/50 ETA hh:mm:ss
march [##################............]  60% 30/50 ETA hh:mm:ss
march [#####################.........]  70% 35/50 ETA hh:mm:ss
march [########################......]  80% 40/50 ETA hh:mm:ss
march [###########################...]  90% 45/50 ETA hh:mm:ss
march [##############################] 100% 50/50 ETA hh:mm:ss
[done in n.nn s, nn.nn/s]
march: done

A log line every so often

$ march > run.log; cat run.log
solve 0 iterations, hh:mm:ss elapsed
solve 2 iterations, hh:mm:ss elapsed
solve 4 iterations, hh:mm:ss elapsed
solve 6 iterations, hh:mm:ss elapsed
solve 8 iterations, hh:mm:ss elapsed
solve 10 iterations, hh:mm:ss elapsed

No bars at all

$ FORBEAR_DISABLE=1 march
march: done

The bar on standard error

$ stderr > results.txt
march [########################################] 100%

Mistakes stop the program ​

A scale on a narrow bar

$ scale_narrow
ERROR STOP error: for adding scale bar the bar width must be at least 22 chars
[exit status 1]

Where next ​

Learn forbear step by step in the tutorial, find quick answers in the cookbook, look up every keyword in the reference.

Authors ​

Contributions are welcome β€” see the Contributing page.

Released under the GPL v3, BSD 2-Clause, BSD 3-Clause or MIT License.