You are not logged in.

#1 2012-09-28 05:52:58

cryptkeeper
Member
From: Zurich, Switzerland
Registered: 2011-12-29
Posts: 63

Fortran90: suppress terminal output of module

I'm writing my first real Fortran90 program (for my masters thesis). I'm using functions of an external module (that is, one not written by me). These functions (or, to be precise, subroutines) produce terminal output. Is there a possibility to supress this output when calling the subroutine in my program without changing the source code of the modules? I'm thinking of an analogue to shell script's >/dev/null.

It's (in this case) not a big problem because the output is actually quite useful, but I'm implementing all my terminal output with a "verbose"-switch, so it would be nice to include these external subroutines.

Offline

#2 2012-09-30 22:15:38

bsilbaugh
Member
From: Maryland, USA
Registered: 2011-11-15
Posts: 141

Re: Fortran90: suppress terminal output of module

If it's sufficient to redirect the output to file, you can open a file on the unit reserved for STDOUT. On most systems STDIN and STDOUT are assigned to 5 and 6, respectively. Here's a toy example:

program test
! A simple program to demonstrate redirection of STDOUT to file.
! This program has been tested with gfortran (GCC 4.7.1)
! On most systems STDOUT is associated with unit 6; however, this association is platform dependent.

    ! Let's define a STDOUT parameter so this is easy to change latter...
    integer, parameter :: stdout=6

    ! This will redirect STDOUT to file instead of printing to terminal. 
    ! Comment this out to enable output to terminal.
    open(unit=stdout, file="stdout.log", form="formatted")

    ! Let's call a subroutine that has obnoxious print statements...
    call foo()

contains

subroutine foo()
! A subroutine containing a hard coded print statement
    print*, "An obnoxious message."
end subroutine foo

end program test

There are a number of ways this code could be improved. For example, you could use preprocessor directives to set the STDOUT file unit instead of hardcoding stdout=6. Also, you could use preprocessor directives to enable/disable the open statement. But, hopefully, you get the idea.

Note that this will redirect the write and print statements to STDOUT of the entire program. If you wanted to only redirect the output of a specific module, then you may need to seek a more innovative solution, or simply fix the offensive module.

EDIT: If you want to simply suppress the output, you could replace "stdout.log" with "/dev/null". (I'm slapping myself for not thinking of this first.) Also, you could use unformatted output to speed up the print/write operations (since you're going to discard the output anyway).

Last edited by bsilbaugh (2012-09-30 22:42:01)


- Good judgement comes from experience; experience comes from bad judgement. -- Mark Twain
- There's a remedy for everything but death. -- The wise fool, Sancho Panza
- The purpose of a system is what it does. -- Anthony Stafford Beer

Offline

#3 2012-09-30 23:00:09

bsilbaugh
Member
From: Maryland, USA
Registered: 2011-11-15
Posts: 141

Re: Fortran90: suppress terminal output of module

Here's a revised example that suppresses STDOUT for "silent" running:

program test
! A simple program to demonstrate suppression of STDOUT.
! This program has been tested with gfortran (GCC 4.7.1)
! On most systems STDOUT is associated with unit 6; however, this association is platform dependent.
! This also assumes the existence of /dev/null (should be available on most Linux systems).

    ! Let's define a STDOUT parameter so this is easy to change later...
    integer, parameter :: stdout=6
    ! Likewise, let's also define null file parameter...
    character(len=*), parameter :: nullfile="/dev/null"

    ! This will cause suppression of STDOUT instead of printing to terminal. 
    ! Comment this out to enable output to terminal.
    open(unit=stdout, file=nullfile, status="old")

    ! Let's call a subroutine that has obnoxious print statements...
    call foo()

contains

subroutine foo()
! A subroutine containing a hard coded print statement
    print*, "An obnoxious message."
end subroutine foo

end program test

Note that tricks like this can end up biting you, or your teammate, down the road. Be sure to clearly document this and put it someplace obvious.


- Good judgement comes from experience; experience comes from bad judgement. -- Mark Twain
- There's a remedy for everything but death. -- The wise fool, Sancho Panza
- The purpose of a system is what it does. -- Anthony Stafford Beer

Offline

#4 2012-10-01 06:01:47

cryptkeeper
Member
From: Zurich, Switzerland
Registered: 2011-12-29
Posts: 63

Re: Fortran90: suppress terminal output of module

Thanks for your solution.  To only supress the output of a single module call, I suppose one just has to change STDOUT back to terminal output, somehow like this:

...
    open(unit=stdout, file=nullfile, status="old")
    call foo()
    open(unit=stdout, file=terminaloutput, status="old")
...

How could that be done, i.e. what is 'terminaloutput'?

EDIT: I've got a few steps nearer to the solution:

...
    print*, "hello"
    open(unit=stdout, file=nullfile, status="old")     ! nullfile="/dev/null"
    call foo()
    open(unit=stdout, file=terminal, status="old")     ! terminal="/dev/stdout"
    print*, "bye bye"
...

This works but gives me a runtime error:

$ ./supress_output
 hello
 bye bye
At line 24 of file supress_output.f90 (unit = 6, file = '/dev/stdout')
Fortran runtime error: Invalid argument

Last edited by cryptkeeper (2012-10-01 06:24:21)

Offline

#5 2012-10-04 17:21:18

bsilbaugh
Member
From: Maryland, USA
Registered: 2011-11-15
Posts: 141

Re: Fortran90: suppress terminal output of module

The only other trick that I can think of is to write a small C library that redirects STDOUT for you. I think this can be safely done in C using freopen. Nowadays, binding C and Fortran can be done in a portable fashion using the C interoperability features introduced with Fortran 2003; most compilers support this feature (gcc, intel, open64, ...). Of course, you need to weight this against the effort required to fix your noisy module.

All other things being equal, I would think fixing your noisy module would be the better long term solution. How hard would it be to write a patch that replaces all occurances of "print*," with "write(logunit,*)", and "write(*" with "write(logunit", where logunit is some integer variable that you can control from your main program (perhaps through a module init subroutine)?


- Good judgement comes from experience; experience comes from bad judgement. -- Mark Twain
- There's a remedy for everything but death. -- The wise fool, Sancho Panza
- The purpose of a system is what it does. -- Anthony Stafford Beer

Offline

#6 2012-10-05 07:56:51

cryptkeeper
Member
From: Zurich, Switzerland
Registered: 2011-12-29
Posts: 63

Re: Fortran90: suppress terminal output of module

That's definitely not worth the effort. In any case, "noisy" is not really the right term for the output the module produces. I just thought I'll ask if there's an easy solution (such as >/dev/null in bash) to supress this output without editing the module source code (which I easily could). And I still think there is, because apart from the runtime error, the solution above (my modification of your code) DOES indeed work. No idea how to get rid of this runtime error (or why there is this error in the first place)?

Offline

Board footer

Powered by FluxBB