3

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

我只编写一些自己的子程序并使用 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
4

3 回答 3

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

更新:注意:这种方法可用于在两个例程之间传递信息,而无需主程序访问模块......对于问题,无需修改原始主程序。该示例的一部分是如何分配数组:该示例通过让首先使用数组的子例程测试数组是否已分配来做到这一点——如果没有,它会分配数组。

于 2013-08-23T15:33:52.763 回答
1

下面的三个示例都适用于 gfortran。第二个可能在某些编译器上失败,因为它使用 F2003 功能(可分配的虚拟参数),并且并非所有编译器都 100% 兼容 F2003。但是,大多数实施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

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

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
于 2013-08-26T09:42:47.477 回答
0

我不明白为什么写 aMODULE行不通,但是您考虑过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数组。

于 2013-08-23T13:41:16.467 回答