Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Progress bar in Fortran.

woshiwuxin
Novice
3,104 Views
Hi, everyone. I want to produce a simple progress bar in a text console by using Fortran 90. The bar would be like this.
[bash] 10% |*         |[/bash]
I want to useadvance="no"in a write statement to generate the bar. Below is therelevantcode.
[fortran]program test
  implicit none
  integer(kind=4)::i
  do i=1, 10
    ! Just spend some cpu time to calculate pi.
    ! This could be replaced by non-standard subroutine sleep(n).
    call pi
    call progress(i) ! generate the progress bar.
  enddo
  stop
end

subroutine progress(j)
  implicit none
  integer(kind=4)::j,k
  character(len=17)::bar="???% |          |"
  write(unit=bar(1:3),fmt="(i3)") 10*j
  do k=1, j
    bar(6+k:6+k)="*"
  enddo
  ! print the progress bar.
  write(unit=6,fmt="(a1,a17)",advance="no") char(13), bar
  if (j/=10) then
    flush(unit=6)
  else
    write(unit=6,fmt=*)
  endif
  return
end subroutine progress[/fortran]
I found the binary produced by ifort could only print the final bar, which is
[bash]100%|**********|[/bash]
The intermediates are somehow omitted. Some other compilers could produce the desired results.
Is this a bug of my code or ifort?
Thanks in advance!
0 Kudos
4 Replies
Steven_L_Intel1
Employee
3,104 Views
It is not a bug in ifort. The Fortran standard does not guarantee that the output with advance='no' is immediately available - this is used to "build" a record. Some implementations do this, some do not.

The following works in Intel Fortran, but may not be portable. Note that the unit has to be opened for FORTRAN carriage control.

[fortran]program test
use ifport
  implicit none
  integer(kind=4)::i
  open (unit=6, carriagecontrol='fortran')
  do i=1, 10
    ! Just spend some cpu time to calculate pi.
    ! This could be replaced by non-standard subroutine sleep(n).
    call sleepqq(300)
    call progress(i) ! generate the progress bar.
  enddo
  stop
end

subroutine progress(j)
  implicit none
  integer(kind=4)::j,k
  character(len=17)::bar="???% |          |"
  write(unit=bar(1:3),fmt="(i3)") 10*j
  do k=1, j
    bar(6+k:6+k)="*"
  enddo
  ! print the progress bar.
  write(unit=6,fmt="(a1,a1,a17)") '+',char(13), bar
  return
end subroutine progress[/fortran]
0 Kudos
woshiwuxin
Novice
3,104 Views
Thank you, Steve!
I'm notmajoredin computer science. Prior to reading your post, I have no idea about byte-oriented and record-oriented file systems. I think the I/O facilities provided by record-oriented file systems, e.g. in VMS, are really more powerful than those provided in *nix.
BTW, I find that the desired results could also be produced by using -vms option without defining carriagecontrol in open statement. The only drawback is the first byte of each record is always wasted. Moreover, a compiler supports the VMS I/O system is also required. :(
0 Kudos
woshiwuxin
Novice
3,104 Views
I personally think a non-standard, but least-demanded trick is to write it in this way.
[fortran]write(unit=6,fmt="(a1,a20,$)") char(13), bar[/fortran]
The only compiler I've tried that does NOT support the Dollar is f90 from SUN. However, f95 does support it.
May we say that previously SUN was not compatible with "Dollar", but later this might be changed? :D
0 Kudos
Steven_L_Intel1
Employee
3,104 Views
The -vms option implicitly sets carriagecontrol='fortran'. What you're looking for is not really tied to the file system, but rather the semantics of Fortran record I/O.

0 Kudos
Reply