简体   繁体   English

纯Fortran程序中的I / O.

[英]I/O in pure Fortran procedures

I'm trying to incorporate error checking within a pure procedure I am writing. 我正在尝试将错误检查纳入我正在编写的纯过程中。 I would like something like: 我想要像:

pure real function func1(output_unit,a)
    implicit none
    integer :: a, output_unit

    if (a < 0) then
        write(output_unit,*) 'Error in function func1: argument must be a nonnegative integer. It is ', a
    else
    func1 = a/3

    endif
    return
end function func1

However, pure functions are not allowed to have IO statements to external files, so I tried passing a unit number to the function, eg output_unit = 6 , which is the default output. 但是,不允许纯函数将IO语句赋予外部文件,因此我尝试将单元号传递给函数,例如output_unit = 6 ,这是默认输出。 gfortran still regards this as illegal. gfortran仍然认为这是非法的。 Is there a way around this? 有没有解决的办法? Is it possible to make the function a derived type (instead of intrinsic type real here) which outputs a string when there is an error? 是否有可能使函数成为派生类型(而不是内部类型为real ),在出现错误时输出字符串?

You are not the first person to have this problem, and I'm happy to say that this flaw in the standard will be remedied in Fortran 2015. As stated in this document (page 6, header "Approved changes to the standard"), "the restriction on the appearance of an error stop statement in a pure procedure should be removed" . 您不是第一个遇到此问题的人,我很高兴地说,标准中的这个缺陷将在Fortran 2015中得到纠正。如本文档所述 (第6页,标题为“批准的标准更改”), “应该删除对pure过程中error stop语句的出现的限制”

The Fortran 2008 standard included the error stop statement in the context of some new parallel computing features. Fortran 2008标准在一些新的并行计算功能的上下文中包含了error stop语句。 It signals an error and makes all processes stop as soon as is practicable. 它发出错误信号,并在可行的情况下尽快停止所有进程。 Currently, neither stop nor error stop statements are allowed in pure procedures, because they're obviously not thread-safe. 目前,既没有stop ,也没有error stop语句也可以在pure程序,因为它们显然不是线程安全的。 In practice this is unnecessarily restrictive in cases where an internal error occurs. 实际上,在发生内部错误的情况下,这是不必要的限制。

Depending on your compiler, you may have to wait patiently for the implementation. 根据您的编译器,您可能需要耐心等待实施。 I know that Intel has implemented it in their ifort compiler. 我知道英特尔已经在他们的ifort编译器中实现了它。 ( "F2015: Lift restriction on STOP and ERROR STOP in PURE/ELEMENTAL procedures" ) “F2015:在PURE / ELEMENTAL程序中对STOP和ERROR STOP的提升限制”

alternative 替代

For an alternative approach, you could have a look at this question , though in you case this is probably slightly trickier as you have to change the do concurrent keyword, not just pure . 对于另一种方法,你可以看看这个问题 ,但在你的情况下这可能有点棘手,因为你必须改变do concurrent关键字,而不仅仅是pure

(end of proper answer) (正确答案结束)

if getting dirty hands is an option ... 如果弄脏手是一种选择......

In the meantime you could do something brutal like 与此同时,你可以做一些残酷的事情

pure subroutine internal_error(error_msg)
    ! Try hard to produce a runtime error, regardless of compiler flags.
    ! This is useful in pure subprograms where you want to produce an error, 
    ! preferably with a traceback.
    ! 
    ! Though far from pretty, this solution contains all the ugliness in this 
    ! single subprogram.
    ! 
    ! TODO: replace with ERROR STOP when supported by compiler
    implicit none

    character(*), intent(in) :: error_msg

    integer, dimension(:), allocatable :: molested

    allocate(molested(2))
    allocate(molested(2))
    molested(3) = molested(4)
    molested(1) = -10
    molested(2) = sqrt(real(molested(1)))
    deallocate(molested)
    deallocate(molested)
    molested(3) = molested(-10)
end subroutine internal_error

Should anyone ask, you didn't get this from me. 如果有人问,你没有从我这里得到这个。

I've found an answer myself, detailed here . 我已经找到了答案我自己,详细介绍在这里 It uses what is considered "obsolescent", but still does the trick; 它使用被认为是“过时”的东西,但仍然可以做到这一点; it is called alternate return. 它被称为替代回报。 Write the procedure as a subroutine as it doesn't work on functions. 将过程编写为子例程,因为它不适用于函数。

pure real subroutine procA(arg1)
    implicit none
    integer :: arg1

    if (arg < 0) then
        return 1 ! exit the function and go to the first label supplied
                 ! when function was called. Also return 2, 3 etc.
    else
        procA = ... ! whatever it should do under normal circumstances
    endif
endsubroutine procA

.... 

! later on, procedure is called
num = procA(a, *220)

220 write(6,*) 'Error with func1: you've probably supplied a negative argument'

What would probably be better is what eriktous suggested--get the procedure to return a status, perhaps as a logical value or an integer, and get the program to check this value every time after it calls the procedure. 什么可能会更好的是eriktous建议 - 获取程序返回状态,可能作为逻辑值或整数,并让程序每次调用该过程后检查此值。 If all's well, carry on. 如果一切顺利,继续。 Otherwise, print a relevant error message. 否则,请打印相关的错误消息。

Comments welcome. 欢迎评论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM