Fortran: Choosing the rank of an allocatable array

前端 未结 2 2022
萌比男神i
萌比男神i 2020-12-20 03:58

I am trying to write a program where I want the allocatable array A to be of either rank 1, 2, or 3, depending on my input at run-time. I want to do this since

相关标签:
2条回答
  • 2020-12-20 04:36

    The next Fortran standard (2015) has the select rank construct similar to select case. My example uses the select case construct on the rank intrinsic of an assumed-rank dummy variable.

        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
    
    0 讨论(0)
  • 2020-12-20 04:44

    Declare the array to be rank three. If a lower rank array is required, allocate the relevant trailing dimensions to be of size one.

    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
    

    You can then use an array section to get a contiguous slice of array that is consistent with your desired rank. Alternatively, write the relevant procedures that operate on array to take a rank three argument, and make them aware of the meaning of a size one extent for the higher dimensions.

    0 讨论(0)
提交回复
热议问题