Dynamic array rank

谁都会走 提交于 2019-12-11 06:05:18

问题


I have a few array variables in a module that are dynamic, and later allocated in one of two subroutines outside of the module. However, in one subroutine I want the array to be 1D, in the other subroutine I want it to be 2D.

In principle I would want something like this in the module, but I don't believe this is possible in the declaration area?:

if (option1) then
  real (kind=8), allocatable :: arr1(:)
else
  real (kind=8), allocatable :: arr1(:,:)
endif

Is there a way in the allocatable declarations to have the dimension be dynamic?

Edit1: The reason I'm doing this is I'm adding a new subroutine to an existing codebase, but I want to be backwards compatible. arr1 is only used by the two separate subroutines, the main program doesn't use it at all. Here is some more complete code showing the idea:

program myprog
use inputs

call read_inputs

if (option1) then
    call do1
else
    call do2
endif

contains
    subroutine read_inputs
        use inputs
        use mymod
        !!!read from file .logical. option1, integers N1, N2

        !allocate arrays
        if (option1) then 

        else

        endif
    end subroutine read_inputs

    subroutine do1
        use inputs
        use mymod

        allocate(arr1(N1))

        !do stuff with arr1
    end subroutine do1

    subroutine do2
        use inputs
        use mymod

        allocate(arr1(N1,N2))

        !do stuff with arr1
    end subroutine do2

end program

module inputs
    logical :: option1
    integer :: N1, N2

end module inputs

module mymod
    use inputs
    !!!!can I do something here to make the rank of arr1 dynamic? I don't think the following will work
    if (option1)
        real (kind=8), allocatable :: arr1(:)
    else
        real (kind=8), allocatable :: arr1(:,:)
    endif
end module mymod

I may just have two separate variable in mymod, arr1 and arr1_new. I was just hoping to avoid that.


回答1:


I think the 'olden' ways to do something like this is to pass the first element instead of the whole array and the size of the array separately:

program dyn_array
    implicit none
    integer :: a(2, 3)
    integer :: i
    call set1d(a(1,1), size(a))
    do i = 1, 3
        write(*, '(2I4)') a(:,i)
    end do
    contains
        subroutine set1d(array, s)
            implicit none
            integer, intent(in) :: s
            integer, intent(out) :: array(s)
            integer :: i
            do i = 1, s
                array(i) = 3 * i
            end do
        end subroutine set1d
end program dyn_array



回答2:


"Can you pass a 2D array into a subroutine that expects a 1D array and get the right size?"

You can use reshape, but if you code is relying on the compiler to help then a 2D into a 1D is dicey. You could use RESHAPE before and after... Or you can have 2 routines, which we can call set1d and set2d. Then in the module you can have it choose what one you want to use. You could have integer(s), float(s), complex(s), byte.

You would CALL Array$Set(Array,s)

MODULE Stuff
  PUBLIC :: Array$Set

  PRIVATE
    INTERFACE Array$Set
  MODULE PROCEDURE Set1d_Float, Set1D_Double, set2D_Float, Set2D_Double
END INTERFACE Array$Set

CONTAINS

SUBROUTINE  Set1D_Float(Array,S)...
!$DIR ATRIBUTES ASUUME_ALIGND:64                :: Array
REAL, DIMENSION(:,:), CONTIGUOUS, INTENT(INOUT) :: Array
REAL, DIMENSION(:,:),             INTENT(IN   ) :: S
REAL, DIMENSION(2)                              :: Shapez
...
Shapez = Shape(Array)
DO I =  1, Shapez(1)
  DO J = 1, Shapez(2)
...
END SUBROUTINE Set1D_Float

END MODULE Stuff

For your example: if (option1) then real (kind=8), allocatable :: arr1(:) else real (kind=8), allocatable :: arr1(:,:) endif

I would suggest this:

!DIR ATTRIBUTES ALIGN:64        :: Arr1
REAL, DIMENSION(:), ALLOCATABLE :: Arr1
...


if (option1) then
  ALLOCATE(Arr1(<#>))
else
  ALLOCATE(Arr1(<#>*<#2>))
  RESHAPE(Arr1, SHAPE=/(#1,#2)) !Check the syntax
endif

CALL Array$Set(Arr1,s) !It'll find the right one...

!... at the bottom ...
IF(ALLOCATED(Arr1)) DEALLOCATE(Arr1)
END PROGRAM


来源:https://stackoverflow.com/questions/38387460/dynamic-array-rank

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!