Fortran:选择可分配数组的等级

时间:2016-06-27 15:40:27

标签: arrays fortran rank allocatable-array

我正在尝试编写一个程序,我希望可分配数组A的等级为1,2或3,具体取决于我在运行时的输入。我想这样做,因为A上的后续操作是相似的,我在模块中定义了一个接口work,其中包含模块过程,当A上的操作时,会给出所需的结果。

我目前正在做的是:

program main
implicit none
integer :: rank,n=10
real*8, allocatable :: A1(:)
real*8, allocatable :: A2(:,:)
read (*,*) rank

if (rank.eq.1) then
    allocate (A1(n))
else if (rank.eq.2) then
    allocate (A2(n,n))
end if

! operate on the array
if (rank.eq.1) then
    call work(A1)
else if (rank.eq.2) then
    call work(A2)
end if

end program

如果以某种方式我可以选择A的等级,事情就会容易得多,因为不需要if语句。也许这是不可能的,但所有的帮助都表示赞赏。

2 个答案:

答案 0 :(得分:2)

下一个Fortran标准(2015)的select rank结构类似于select case。我的示例在假定等级虚拟变量的select case内在函数上使用rank构造。

    module my_type

  use, intrinsic :: iso_fortran_env, &
       ip => INT32, &
       wp => REAL64

  implicit none
  private
  public :: MyType

  type MyType
     real (wp)              :: rank0
     real (wp), allocatable :: rank1(:)
     real (wp), allocatable :: rank2(:,:)
     real (wp), allocatable :: rank3(:,:,:)
   contains
     procedure :: create => create_my_type
     procedure :: destroy => destroy_my_type
  end type MyType

contains

  subroutine create_my_type(this, array)
    ! calling arguments
    class (MyType), intent (in out) :: this
    real (wp),      intent (in)     :: array(..) !! Assumed-rank dummy variable

    ! local variables
    integer (ip), allocatable :: r(:)

    select case(rank(array))
    case (0)
       return
    case (1)
       r = shape(array)
       allocate( this%rank1(r(1)) )
    case (2)
       r = shape(array)
       allocate( this%rank2(r(1), r(2)) )
    case (3)
       r = shape(array)
       allocate( this%rank3(r(1), r(2), r(3)) )
    case default
       error stop 'array must have rank 0,1,2, or 3'
    end select

    ! Release memory
    if (allocated(r)) deallocate( r )

  end subroutine create_my_type


  subroutine destroy_my_type(this)
    ! calling arguments
    class (MyType), intent (in out) :: this

    if (allocated(this%rank1)) deallocate( this%rank1 )
    if (allocated(this%rank2)) deallocate( this%rank2 )
    if (allocated(this%rank3)) deallocate( this%rank3 )

  end subroutine destroy_my_type

end module my_type

program main

  use, intrinsic :: iso_fortran_env, only: &
       ip => INT32, &
       wp => REAL64

  use my_type, only: &
       MyType

  implicit none

  type (MyType) :: foo
  real (wp)     :: a0, a1(42), a2(42,42), a3(42,42,42)

  print *, rank(a0)
  print *, rank(a1)
  print *, rank(a2)
  print *, rank(a3)

  ! Allocate array of rank 3
  call foo%create(a3)

  print *, rank(foo%rank3)
  print *, shape(foo%rank3)
  print *, size(foo%rank3)

  ! Release memory
  call foo%destroy()

end program main

答案 1 :(得分:1)

将数组声明为rank 3。如果需要较低级别的数组,请将相关的尾随维度分配为大小为一。

real, allocatable :: array(:,:,:)
...
select case (desired_rank)
case (1) ; allocate(array(n,1,1))
case (2) ; allocate(array(n,n,1))
case (3) ; allocate(array(n,n,n))
case default ; error stop 'bad desired rank'
end select

然后,您可以使用数组部分来获得与您所需排名一致的array的连续切片。或者,编写对数组进行操作的相关过程以获得三级参数,并使它们了解更高维度的大小一个范围的含义。