【问题标题】:Arguments of different types in a same Fortran subroutine同一个 Fortran 子例程中不同类型的参数
【发布时间】:2021-06-15 10:13:58
【问题描述】:

我想在现代 fortran(90 或更高版本)中定义一个子例程来打印矩阵(整数或实数)或向量(整数 o 数)。

SUBROUTINE print_matrix_vector( A )

! WHAT TYPE CAN I WRITE TO A ???

END SUBROUTINE 

当然,我想调用一个子程序

CALL print_matrix_vector( A )

如果 A 是实数或整数矩阵,并且 A 是实数或整数向量,则独立。

提前感谢您的 cmets。我认为这是很常见的事情,但我没有发现什么清楚的。

【问题讨论】:

    标签: console fortran fortran90


    【解决方案1】:

    所以 Fortran 使用interface 语句来声明函数的重载。我最近做了同样的事情。关键是创建一个接口,我调用show,它用作所有需要的单独函数的别名。

    interface show
        procedure show_vector_i, show_vector_r, show_vector_d
        procedure show_matrix_i, show_matrix_r, show_matrix_d
    end interface
    

    这里是第一个输出。

     Display Matrices/Vectors
    
     vector=
        1
        2
        3
        4
    
     matrix=
        1    5    9   13
        2    6   10   14
        3    7   11   15
        4    8   12   16
    
     A=
     4.47723     3.36660     1.48809    -.752551
     6.36660     7.19091     6.67333     5.54482
     7.48809     9.67333     10.1187     9.77902
     8.24745     11.5448     12.7790     13.0861
    
     u=
     6.36660
     7.19091
     6.67333
     5.54482
    
     v=
     3.36660
     7.19091
     9.67333
     11.5448
    

    和代码

    program FortranConsole1
    use, intrinsic :: iso_fortran_env
    implicit none
    
    interface show
        procedure show_matrix_i, show_matrix_r, show_matrix_d
        procedure show_vector_r, show_vector_d
    end interface
    
    integer :: row(16), matrix(4,4), i
    real(real64), allocatable, target :: A(:,:)
    real(real64), pointer :: B(:,:)
    real(real64), allocatable :: v(:), u(:)
    
    row = [(i,i=1,16)]
    matrix = reshape( row, [4, 4])
    
    print *, "Display Matrices/Vectors"
    print *, ""
    
    print *, "vector="
    call show(row(1:4))
    
    print *, "matrix="
    call show(matrix)
    
    A = dble(matrix)
    
    A = sqrt( matmul( transpose(A), A) ) - A
    
    print *, "A="
    call show(A)
    
    v = A(:,2)
    u = A(2,:)
    
    print *, "u="
    call show(u)
    print *, "v="
    call show(v)
        
    
    contains
    
    subroutine show_vector_i(v, w)
    ! Display the vector 'v' in a single column
    !   v : the array of real numbers
    !   w : the column width. default = 5
    !   s : sig. figures w-5 (calculated)
        integer, intent(in) :: v(:)
        integer, intent(in), optional :: w
        integer :: i,n,wt
        character(len=16) :: fmt
        if(present(w)) then
            wt = w
        else
            wt = 5
        end if
        n = size(v)
        write( fmt, "(a,g0,a)") "(*(g",wt,".0))"
        write( * , fmt ) ( v(i), new_line("A"), i=1,n )    
    end subroutine
    
    subroutine show_vector_r(v, w)
    ! Display the vector 'v' in a single column
    !   v : the array of real numbers
    !   w : the column width. deafult = 12
    !   s : sig. figures w-5 (calculated)
        real(real32), intent(in) :: v(:)
        integer, intent(in), optional :: w
        integer :: i,n,dg,wt
        character(len=16) :: fmt
        if(present(w)) then
            wt = w
        else
            wt = 12
        end if
        dg = wt - 6
        n = size(v)
        write( fmt, "(a,g0,a,g0,a)") "(*(g",wt,".",dg,"))"
        write( * , fmt ) ( v(i), new_line("A"), i=1,n )    
    end subroutine
    
    subroutine show_vector_d(v, w)
    ! Display the vector 'v' in a single column
    !   v : the array of real numbers
    !   w : the column width. deafult = 12
    !   s : sig. figures w-5 (calculated)
        real(real64), intent(in) :: v(:)
        integer, intent(in), optional :: w
        call show_vector_r(real(v),w)
    end subroutine
    
    subroutine show_matrix_i(A, w)
    ! Display the matrix 'A' in columns
    !   A : the array of integers
    !   w : the column width. Default = 5
        integer, intent(in) :: A(:,:)
        integer, intent(in), optional :: w
        integer :: i,j,n,m, wt
        character(len=16) :: fmt
        if(present(w)) then
            wt = w
        else
            wt = 5
        end if
        n = size(A,1)
        m = size(A,2)
        write( fmt, "(a,g0,a)") "(*(g",wt,".0))"        
        write( * , fmt ) ( (A(i,j),j=1,m), new_line("A"), i=1,n )
    end subroutine
    
    subroutine show_matrix_r(A, w)
    ! Display the matrix 'A' in columns
    !   A : the array of real numbers
    !   w : the column width. deafult = 12
    !   s : sig. figures w-5 (calculated)
        real(real32), intent(in) :: A(:,:)
        integer, intent(in), optional :: w
        integer :: i,j,n,m,dg,wt
        character(len=16) :: fmt
        if(present(w)) then
            wt = w
        else
            wt = 12
        end if
        dg = wt - 6
        n = size(A,1)
        m = size(A,2)
        write( fmt, "(a,g0,a,g0,a)") "(*(g",wt,".",dg,"))"
        write( * , fmt ) ( (A(i,j),j=1,m), new_line("A"), i=1,n )
    end subroutine
    
    subroutine show_matrix_d(A,w)
    ! Display the matrix 'A' in columns
    !   A : the array of dble numbers
    !   w : the column width. default = 12
    ! Converts 'A' into single precision and calls `show_matrix_r`
        real(real64), intent(in) :: A(:,:)
        integer, intent(in), optional :: w
        call show_matrix_r(real(A),w)
    end subroutine
    
    end program FortranConsole1
    

    实际上,函数应该在module 文件中,以便在不同的程序中一次又一次地重用。

    【讨论】:

    • 不错的答案,但我想我只想指出,在实际代码中,您几乎可以肯定会淘汰所有重载的例程和模块中的接口并使用它 - 内部过程非常适合示例,但它们的使用有点受限。
    • @IanBush - 是的,放置函数的位置是此答案未考虑的设计决定。
    • 我编辑了答案以更好地反映问题的精神,显示更多整数和实数值的向量和矩阵。
    • 感谢您的回答。我将使用它来测试代码。我喜欢将输出写入文件并用八度(matlab)读取它以进行分析。在那里很容易做像间谍这样的事情,计算行列式......所以它只是调试代码,然后你的答案是完美的。再次感谢。
    • 请注意,show() 调用支持要显示的列宽的可选参数。整数默认为 5,实数默认为 12。此外,由于显示通常不需要超过 5 个有效数字,因此将双精度转换为单精度进行显示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    • 1970-01-01
    • 1970-01-01
    • 2014-07-02
    • 2014-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多