共享可分配的数组

时间:2013-08-23 12:23:29

标签: arrays fortran

我有一些可分配的数组,我需要在一些子程序之间共享。我通常只是将它们作为参数传递或者可以在模块中写入所有内容,但我担心这在我的情况下是不可能的。

我只编写一些自己的子程序,并使用由FEM-Solver提供和描述的子程序。所以我不能改变这个子程序的参数或将它们包装在一个模块中。

据我所知,在编译时也无法使用未知大小的数组构建公共块。

还有别的东西要通过我的阵列吗?

更新
目前我的程序环境如下:

我有一个由FEM程序提供的子程序,它在每次递增后调用,这会调用我的几个子程序,我为每个节点或其中一个子集计算一些值。

要在模拟后显示这些值,我必须将它们传递给另一个子程序。 FEM子解算器在增量结束时为每个节点调用该子程序。因此,将我的代码转移到此子例程会产生大量开销。

我的想法是计算一次值,将值存储在数组中并将此数组传递给第二个子例程,在那里它们将被写入计算数据库。

更新
一些伪代码:
假设程序行为:

 Program FEM-solver
     *magic* 
     call ENDINC(ar1,ar2)
     *something* 
     do NodeID=1,Sum_Of_Nodes
        do valueID=1,Sum_Of_User_Computed_Values !(defined in preprocessing)
           call nodeval(NodeID,valueID,Value,ar3,...,arN)
        end do
     end do
     *voodoo* 
 end program FEM-solver    

写作和工作:

Subroutine ENDINC(ar1,ar2)
  *Computation of some node values*
  *Calling of own Subroutines, which compute more values*
  *Writing an array with results values for some/each node(s)*
   nodersltArr(NodeID,rslt)=*some Value*
end Subroutine ENDINC

需要将计算值写入节点解决方案数据库:

Subroutine nodeval(NodeID,valueID,Value,ar3,...,arN)  
  *called for each NodeID and valueID*
   value=noderslArr(NodeID,valueID)
end subroutine nodeval

3 个答案:

答案 0 :(得分:2)

只要在调用之前分配了数组,就可以将可分配数组传递给未声明为使用可分配数组的过程。 (当然,在没有该属性的情况下,您不能将该数组用作可分配数组。)或许这将解决您的问题。在您编写的代码中分配数组,而不是将其作为参数传递给FEM解算器。

示例代码:(我通常会将该函数放入模块中,但您说不能这样做,所以我写了一个示例,显示了不使用模块的情况。)

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

----------编辑:第二个概念---------

在两个子程序之间共享一个可分配的数组,而不需要调用例程“知道”该数组。

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

更新:注意:此方法可用于在两个例程之间传递信息,而主程序无需访问模块...对于问题,而无需修改原始主要的prpgram。该示例的一部分是如何分配数组:该示例通过使用首先使用数组的子例程来测试数组是否已分配 - 如果不是,则分配数组。

答案 1 :(得分:1)

下面的三个例子都与gfortran有关。第二个可能在某些编译器上失败,因为它使用F2003功能(可分配的伪参数)和not all compilers are 100% F2003 compliant。但是,大多数实现ISO TR 15581(包括此功能)。

第一个版本,您可以使用指向可分配数组的公共指针。

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

第二个版本,在子程序中分配然后调用另一个。还需要在主程序中声明数组。

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

第三版,这里我们首先调用一个返回指针的函数,然后通过一个公共指针传递给一个子程序。该函数执行分配,如第二个示例所示。指针在主程序中被释放,但可能在其他地方。

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

答案 2 :(得分:0)

我不明白为什么写MODULE不起作用,但您考虑过CONTAINS吗? CONTAINS下面的子程序可以看到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

输出为

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

这也适用于ALLOCATABLE数组。