如何在Fortran中将指针分配给复杂的3D数组 [英] How to assign pointers to a complex 3d array in Fortran

查看:59
本文介绍了如何在Fortran中将指针分配给复杂的3D数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would like to know how to assign two pointers, one to the real part of a complex 3d array and another to the imaginary part of the same array in Fortran.

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

Let's say I have defined a 3d array as such:

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

complex*16, dimension(:,:,:), allocatable, target :: vftmp

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

and I would like to assign a pointer to the real part of vftmp(2,1,1) and a pointer to the imaginary part of vftmp(2,1,1). Could someone help me with a snippet please? Thanks.

推荐答案

我希望以下内容是可能的

I hope something like the following is possible

real, pointer :: re
complex, target :: z
re => z % re
! or
real, pointer :: re(:,:,:)
complex, target :: z(2,3,4)
re => z(:,:,:) % re

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

but it seems not (or possible with very new compilers...?) So a workaround approach below:

1)如果目标是获取复杂数组单个元素的Re和Im部分的(标量)指针,我想我们可以使用 c_f_pointer 这样

1) If the goal is to get (scalar) pointers for the Re and Im parts of a single element of a complex array, I guess we can use c_f_pointer such that

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

结果(gfortran-8.2):

Result (gfortran-8.2):

 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 


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


2) If the goal is to get array pointers for the entire complex array, I guess we can use rank-remapping pointer assignments (to point to non-contiguous memory with constant gaps). For example, in the 2D case (for simplicity),

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

其中 re im 是2D数组指针,而 buf 是真正的1D数组指针,它指向可分配的2D复杂数组(通过 c_f_pointer ).一个最小的例子可能是这样的:

where re and im are 2D array pointers and buf is a real 1D array pointer that points to an allocatable 2D complex array (via c_f_pointer). A minimum example may look like this:

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

结果(gfortran 8.2):

Result (gfortran 8.2):

 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  


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


Below are some materials we can find on the net:

Fortran 2003的新功能(N1597):3.7指针作业"

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

"...Remapping of the elements of a rank-one array is permitted:

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

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

The mapping is in array-element order and the target array must be large enough. The bounds may be any scalar integer expressions. The limitation to rank-one arrays is because pointer arrays need not occupy contiguous storage:

a => b(1:10:2)

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

but all the gaps have the same length in the rank-one case."

Fortran 2003扩展:5.4.3等级重映射指针分配(此页面)

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

"...This feature allows a multi-dimensional pointer to point to a single-dimensional object. For example:

REAL,POINTER :: diagonal(:),matrix(:,:),base(:)
...
ALLOCATE(base(n*n))
matrix(1:n,1:n) => base
diagonal => base(::n+1)
!
! DIAGONAL now points to the diagonal elements of MATRIX.
!

请注意,在进行排名重映射时,必须为所有维度明确指定上下限的值,没有默认值."

Note that when rank-remapping, the values for both the lower and upper bounds must be explicitly specified for all dimensions, there are no defaults."

这篇关于如何在Fortran中将指针分配给复杂的3D数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆