How to wrap the fortran write-statement

帅比萌擦擦* 提交于 2020-02-28 08:05:28

问题


I want to wrap the fortran write-statement in a custom subroutine or function which includes some additional debug-logic.

But I'm currently stuck with defining the prototype of the function/subroutine. Is this possible? If yes, how?


回答1:


The title of your question exhibits a misunderstanding, though the text suggests you know better. Nevertheless, for the record, write is a Fortran statement, it is neither a subroutine nor a function.

I think you have a number of options. One, which I have used occasionally, would be to write a function which returns a string. Perhaps

function error_message(error)
    character(len=*), intent(in) :: error
    character(len=:), allocatable :: error_message
    error_message = 'ERROR: '//trim(error)
end function error_message

which you can then use like this

write(*,*) error_message('Oh s**t')

You could certainly write a subroutine or a function with side effects which include writing to an ouput channel, but if you adopt this approach you have to be careful to observe the rules for recursive i/o.

EDIT

after OP's comment.

If you want to switch off debug messages another option you have is to direct them to a null device or file, eg /dev/null on Linux or NUL on Windows. Something like

integer, parameter :: debug_channel = 99
logical, parameter :: debugging = .false.
...
if (debugging) then
   open(debug_channel, file='NUL')
else
   open(debug_channel, file='debuglog'
end if

and then

write(debug_channel,*) 'message'



回答2:


a relatively simple way to accomplish most of what you want is to simply put the if inline in front of every write that is subject to debug control:

    if(debug)write(..,..).. 

where debug is a global logical value, or even:

    if(debugf(level))write(..,..).. 

where the logical function debugf determines whether to write based on some argument.




回答3:


In addition to the other answers, you may be able to avoid using if (debug) write... with derived type IO.

I say "may", as it is quite silly unless you already have a suitable structure, and compiler support is currently rare.

However, as an example, compiled with ifort 14.0.1:

module errormod

  type error_t
     character(len=:), allocatable :: message
   contains
     procedure write_error
     generic :: write(formatted) => write_error
  end type error_t

  logical debug_verbose

contains

  subroutine write_error(err, unit, iotype, v_list, iostat, iomsg)
    class(error_t), intent(in)  :: err
    integer, intent(in)  :: unit
    character(len=*), intent(in)  :: iotype
    integer, intent(in), dimension(:)  :: v_list
    integer, intent(out)  :: iostat
    character(len=*), intent(inout)  :: iomsg

    if (debug_verbose) then
       write(unit, '("Error: ", A)', iostat=iostat, iomsg=iomsg) err%message
    else
       write(unit, '()', advance='no')
    end if

  end subroutine write_error

end module errormod


program test

  use errormod

  implicit none

  type(error_t) error

  debug_verbose = .TRUE.
  error%message = "This error will be reported."
  write(*, '(dt)') error

  debug_verbose = .FALSE.
  error%message = "This error will not be reported."
  write(*, '(dt)') error

  debug_verbose = .TRUE.
  error%message = "This final error will also be reported."
  write(*, '(dt)') error

end program test

The first and third messages will appear, but not the second.



来源:https://stackoverflow.com/questions/19906446/how-to-wrap-the-fortran-write-statement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!