Share allocatable Arrays

后端 未结 3 842
离开以前
离开以前 2021-01-23 01:06

I have some allocatable arrays which I need to share between some subroutines. I usually would just pass them as arguments or maybe write everything in a Module, but I\'m afraid

相关标签:
3条回答
  • 2021-01-23 01:44

    You can pass an allocatable array to procedure that isn't declared to use allocatable arrays, as long as the array is allocated before the call. (Of course, you can't use the array as an allocatable array in the procedure in which it is declared without that property.) Perhaps that will solve your problem. Allocate the array in the code that you write, than pass it as an argument to the FEM solver.

    Example code: (I'd normally put the function into a module but you say that you can't do that, so I write an example showing the case of not using a module.)

    function MySum ( RegArray )
    
    real :: MySum
    real, dimension (:), intent (in) :: RegArray
    
    MySum = sum (RegArray)
    
    end function MySum
    
    
    program TestArray
    
       implicit none
    
       interface AFunc
    
          function MySum ( SomeArray )
    
             real :: MySum
             real, dimension (:), intent (in) :: SomeArray
    
          end function MySum
    
       end interface AFunc
    
       real, dimension (:), allocatable :: AllocArray
       integer :: N
       real :: answer
    
       write (*, '("Input array size: ")', advance="no")
       read (*, *) N
    
       allocate ( AllocArray (1:N) )
       AllocArray = 1.0
    
       answer = MySum ( AllocArray )
       write (*, *) answer
    
    end program TestArray
    

    ---------- EDIT: Second Concept ---------

    Sharing an allocatable array between two subroutines, without the calling routine being "aware" of the array.

    module MySubs
    
       real, allocatable, dimension (:,:) :: array
    
    contains
    
    
    subroutine One ( x, y, ... N, M )
    
       integer, intent (in) :: N, M
    
       if ( .NOT. allocated (array) ) allocate ( array (N, M) )
    
    
    end subroutine One
    
    
    subroutine Two ( .... )
    
    
    end subroutine Two
    
    
    end module MySubs
    

    UPDATE: note: This approach can be used to pass information between the two routines without the main program having access the module ... for the question, without modifying the original main prpgram. Part of the example is how to allocate the arrays: the example does that by having the subroutine that would first use the array test whether the array is allocated -- if not, it allocates the array.

    0 讨论(0)
  • 2021-01-23 01:55

    The three examples below all work with gfortran. The second may fail on some compilers as it uses a F2003 feature (allocatable dummy arguments), and not all compilers are 100% F2003 compliant. However, most implement ISO TR 15581 (which includes this feature).

    First version, you can use a common pointer to allocatable array.

    program hip
       implicit none
       double precision, dimension(:, :), pointer :: p
       common /hiphop/ p
       double precision, allocatable, dimension(:, :), target :: a
       allocate(a(100, 100))
       a(1, 1) = 3.1416d0
       p => a
       call hop
       deallocate(a)
    end program
    
    subroutine hop
       implicit none
       double precision, dimension(:, :), pointer :: p
       common /hiphop/ p
       print *, size(p, 1), size(p, 2), p(1, 1)
    end subroutine
    

    Second version, allocating in a subroutine then calling another. One still needs to declare the array in main program.

    program hip
       implicit none
    
       interface
          subroutine hip_alloc(arr)
             double precision, allocatable, dimension(:, :) :: arr
          end subroutine
       end interface
    
       double precision, dimension(:, :), pointer :: p
       common /hiphop/ p
       double precision, allocatable, dimension(:, :) :: a
       p => null()
       print *, "a:", allocated(a)
       print *, "p:", associated(p)
       call hip_alloc(a)
       print *, "a:", allocated(a)
       print *, "p:", associated(p)
       call hop
       deallocate(a)
    end program
    
    subroutine hip_alloc(arr)
       implicit none
       double precision, dimension(:, :), pointer :: p
       common /hiphop/ p
       double precision, allocatable, dimension(:, :), target :: arr
       allocate(arr(100, 100))
       arr(1, 1) = 3.1416d0
       p => arr
    end subroutine
    
    subroutine hop
       implicit none
       double precision, dimension(:, :), pointer :: p
       common /hiphop/ p
       print *, size(p, 1), size(p, 2), p(1, 1)
    end subroutine
    

    Third version, here we first call a function returning a pointer, then pass this pointer to a subroutine through a common. The function does the allocation, as in second example. The pointer is deallocated in main program, but could be elsewhere.

    program hip
       implicit none
    
       interface
          function hip_alloc(n)
             integer :: n
             double precision, dimension(:, :), pointer :: hip_alloc
          end function
       end interface
    
       double precision, dimension(:, :), pointer :: p
       common /hiphop/ p
       p => null()
       print *, "p:", associated(p)
       p => hip_alloc(100)
       print *, "p:", associated(p)
       call hop
       deallocate(p)
    end program
    
    function hip_alloc(n)
       implicit none
       integer :: n
       double precision, dimension(:, :), pointer :: hip_alloc
       allocate(hip_alloc(n, n))
       hip_alloc(1, 1) = 3.1416d0
    end function
    
    subroutine hop
       implicit none
       double precision, dimension(:, :), pointer :: p
       common /hiphop/ p
       print *, size(p, 1), size(p, 2), p(1, 1)
    end subroutine
    
    0 讨论(0)
  • 2021-01-23 01:55

    I do not understand why writing a MODULE would not work, but have you considered CONTAINS? Everything above the CONTAINS declaration is visible to the subroutines below the CONTAINS:

    PROGRAM call_both
       INTEGER,DIMENSION(2) :: a, b
       a = 1
       b = 2
       PRINT *,"main sees", a, b
       CALL subA
       CALL subB
     CONTAINS
       SUBROUTINE subA
          PRINT *,"subA sees",a,b
       END SUBROUTINE subA
    
       SUBROUTINE subB
          PRINT *,"subB sees",a,b
       END SUBROUTINE subB
    END PROGRAM call_both
    

    The output would be

    main sees           1           1           2           2
    subA sees           1           1           2           2
    subB sees           1           1           2           2
    

    This works with ALLOCATABLE arrays as well.

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