如何在Fortran中将指针分配给复杂的3D数组

时间:2019-02-21 23:14:32

标签: fortran

我想知道如何分配两个指针,一个指向复杂的3d数组的实部,另一个分配给Fortran中同一数组的虚部。

假设我已经这样定义了一个3d数组:

复杂* 16,尺寸(:,:,:),可分配,目标:: vftmp

,我想分配一个指向vftmp(2,1,1)实部的指针和一个指向vftmp(2,1,1)虚部的指针。有人可以帮我摘录吗?谢谢。

1 个答案:

答案 0 :(得分:1)

我希望可能出现以下情况

Local

,但似乎不是(或者对于非常新的编译器来说可能...?)所以下面是一种变通方法:


1)如果目标是获取复杂数组中单个元素的Re和Im部分的(标量)指针,我猜我们可以使用real, pointer :: re complex, target :: z re => z % re ! or real, pointer :: re(:,:,:) complex, target :: z(2,3,4) re => z(:,:,:) % re 这样

c_f_pointer

结果(gfortran-8.2):

module testmod
contains
    subroutine getreim_ptr( z, re, im )
        use iso_c_binding
        implicit none
        complex, target, intent(in) :: z
        real, pointer :: re, im, buf(:)

        call c_f_pointer( c_loc( z ), buf, [ 2 ] )

        re => buf( 1 )
        im => buf( 2 )
    end subroutine
end module

program main
    use testmod
    implicit none
    complex :: z( 2, 3 )
    real, pointer :: re, im

    !! Test array.
    z = 0.0
    z( 1, 1 ) = ( 1.0, -1.0 )

    !! Get pointers for the Re/Im parts of z(1,1).
    call getreim_ptr( z( 1, 1 ), re, im )

    print *, "z(1,:) = ", z(1,:)
    print *, "z(2,:) = ", z(2,:)
    print *, "re = ", re
    print *, "im = ", im
end

2)如果目标是获取整个复杂数组的数组指针,我想我们可以使用秩重映射指针分配(指向具有恒定间隔的非连续内存)。例如,在2D情况下(为简单起见),

 z(1,:) =   (1.00000000,-1.00000000)  (0.00000000,0.00000000)  (0.00000000,0.00000000)
 z(2,:) =   (0.00000000,0.00000000)   (0.00000000,0.00000000)  (0.00000000,0.00000000)
 re =    1.00000000    
 im =   -1.00000000 

其中re( 1:n1, 1:n2 ) => buf( 1::2 ) im( 1:n1, 1:n2 ) => buf( 2::2 ) re是2D数组指针,而im是一个实际的1D数组指针,它指向可分配的2D复杂数组(通过buf)。一个最小的例子可能是这样的:

c_f_pointer

结果(gfortran 8.2):

module testmod
contains
    subroutine getreim_ptr2d( zarr, re, im )
        use iso_c_binding
        implicit none
        complex, allocatable, target, intent(in) :: zarr(:,:)
        real, pointer :: re(:,:), im(:,:), buf(:)
        integer :: n1, n2

        n1 = size( zarr, 1 )
        n2 = size( zarr, 2 )
        call c_f_pointer( c_loc( zarr ), buf, [ size(zarr) * 2 ] )

        re( 1:n1, 1:n2 ) => buf( 1::2 )
        im( 1:n1, 1:n2 ) => buf( 2::2 )
    end subroutine
end module

program main
    use testmod
    implicit none
    complex, allocatable :: zarr(:,:)
    real, pointer :: re(:,:), im(:,:)
    integer i

    !! Prepare a test array (zarr).
    allocate( zarr( 2, 3 ) )
    zarr(1,:) = [( complex( 100 + i, -100 -i ), i=1,3 )]
    zarr(2,:) = [( complex( 200 + i, -200 -i ), i=1,3 )]
    print *, "shape( zarr ) = ", shape( zarr )
    print *, "zarr(1,:) = ", zarr(1,:)
    print *, "zarr(2,:) = ", zarr(2,:)

    call getreim_ptr2d( zarr, re, im )

    print *
    print *, "shape( re ) = ", shape( re )
    print *, "re(1,:) = ", re(1,:)
    print *, "re(2,:) = ", re(2,:)
    print *
    print *, "shape( im ) = ", shape( im )
    print *, "im(1,:) = ", im(1,:)
    print *, "im(2,:) = ", im(2,:)
end program

下面是一些我们可以在网上找到的材料:

  

Fortran 2003 (N1597)的新功能:3.7“指针分配”

“ ......允许重排第一级数组的元素:

 shape( zarr ) =            2           3
 zarr(1,:) =  (101.000000,-101.000000)  (102.000000,-102.000000)  (103.000000,-103.000000)
 zarr(2,:) =  (201.000000,-201.000000)  (202.000000,-202.000000)  (203.000000,-203.000000)

 shape( re ) =            2           3
 re(1,:) =    101.000000    102.000000    103.000000    
 re(2,:) =    201.000000    202.000000    203.000000    

 shape( im ) =            2           3
 im(1,:) =   -101.000000   -102.000000   -103.000000    
 im(2,:) =   -201.000000   -202.000000   -203.000000  

映射按数组元素顺序进行,并且目标数组必须足够大。边界可以是任何标量整数表达式。排名第一的数组的限制是因为指针数组不需要占用连续的存储空间:

p(1:m,1:2*m) => a(1:2*m*m)

但在第一种情况下所有间隙的长度都相同。”

  

Fortran 2003扩展:5.4.3排名重映射指针分配(this page)

“ ...此功能允许多维指针指向一维对象。例如:

a => b(1:10:2)

请注意,在进行秩重新映射时,必须为所有维度明确指定上下限的值,没有默认值。”