Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Fortran 如何为';分配';_Fortran - Fatal编程技术网

Fortran 如何为';分配';

Fortran 如何为';分配';,fortran,Fortran,我试图为'allocate'函数编写一个包装器,即接收数组和维度、分配内存并返回已分配数组的函数。最重要的是,函数必须使用不同秩的数组。但我必须在函数接口中显式地声明数组的秩,在这种情况下,只有当我将某个秩的数组作为参数传递时,代码才会编译。例如,此代码不编译: module memory_allocator contains subroutine memory(array, length) implicit none real(8), allocatable, int

我试图为'allocate'函数编写一个包装器,即接收数组和维度、分配内存并返回已分配数组的函数。最重要的是,函数必须使用不同秩的数组。但我必须在函数接口中显式地声明数组的秩,在这种情况下,只有当我将某个秩的数组作为参数传递时,代码才会编译。例如,此代码不编译:

module memory_allocator
contains 

  subroutine memory(array, length)
    implicit none

    real(8), allocatable, intent(out), dimension(:) :: array
    integer, intent(in) :: length

    integer :: ierr

    print *, "memory: before: ", allocated(array)

    allocate(array(length), stat=ierr)
    if (ierr /= 0) then
      print *, "error allocating memory: ierr=", ierr
    end if

    print *, "memory: after: ", allocated(array)

  end subroutine memory

  subroutine freem(array)
    implicit none

    real(8), allocatable, dimension(:) :: array

    print *, "freem: before: ", allocated(array)
    deallocate(array)
    print *, "freem: after: ", allocated(array)

  end subroutine freem

end module memory_allocator

program alloc
  use memory_allocator
  implicit none

  integer, parameter :: n = 3
  real(8), allocatable, dimension(:,:,:) :: foo
  integer :: i, j, k

  print *, "main: before memory: ", allocated(foo)
  call memory(foo, n*n*n)
  print *, "main: after memory: ", allocated(foo)

  do i = 1,n
    do j = 1,n
      do k = 1, n
        foo(i, j, k) = real(i*j*k)
      end do
    end do
  end do

  print *, foo

  print *, "main: before freem: ", allocated(foo)
  call freem(foo)  
  print *, "main: after freem: ", allocated(foo)

end program alloc
编译错误:

gfortran -o alloc alloc.f90 -std=f2003
alloc.f90:46.14:

  call memory(foo, n*n*n)
              1
Error: Rank mismatch in argument 'array' at (1) (1 and 3)
alloc.f90:60.13:

  call freem(foo)  
             1
Error: Rank mismatch in argument 'array' at (1) (1 and 3)  
有没有办法实现这样的包装器

谢谢

子例程内存(数组,长度)
具有第一个虚拟参数1维数组(
real(8)、可分配、意图(out)、维度(:)::数组

使用3维数组foo(
real(8),可分配,维度(:,:,:)::foo
)从主程序调用此子例程显然是错误的。这就是编译器实际上说的

如果您确实需要这样的子程序,请为每个不同维度的数组编写一对
内存
/
freem
子程序-一对子程序用于一维数组,另一对子程序用于二维数组,等等


顺便说一下,
内存
子例程通常是不同的,因为为了分配n维数组,您需要将n个区段传递给上述子例程。

这可以通过通用接口块来完成。您必须为要处理的每个列组创建过程,例如,memory_1d、memory_2d。。。记忆4d。(显然需要大量剪切和粘贴。)然后编写一个通用接口块,为所有这些过程提供可选名称内存作为通用过程名称。调用内存时,编译器会根据参数的秩来区分应该调用哪个内存。freem函数也是如此

这就是像sin这样的内在函数长期以来的工作原理——您可以使用各种前导的实参或复杂参数调用sin,编译器会计算出要调用的实际sin函数。在真正古老的FORTRAN中,不同的sin函数必须使用不同的名称。现在,使用现代Fortran,您可以使用自己的例程设置相同的内容

编辑:添加演示方法和语法的代码示例:

module double_array_mod

   implicit none

   interface double_array
      module procedure double_vector
      module procedure double_array_2D
   end interface double_array

   private  ! hides items not listed on public statement 
   public :: double_array

contains

   subroutine double_vector (vector)
      integer, dimension (:), intent (inout) :: vector
      vector = 2 * vector
   end subroutine double_vector

   subroutine double_array_2D (array)
      integer, dimension (:,:), intent (inout) :: array
      array = 2 * array
   end subroutine double_array_2D

end module double_array_mod


program demo_user_generic

   use double_array_mod

   implicit none

   integer, dimension (2) :: A = [1, 2]
   integer, dimension (2,2) :: B = reshape ( [11, 12, 13, 14], [2,2] )
   integer :: i

   write (*, '( / "vector before:", / 2(2X, I3) )' )  A
   call double_array (A)
   write (*, '( / "vector after:", / 2(2X, I3) )' )  A

   write (*, '( / "2D array before:" )' )
   do i=1, 2
      write (*, '( 2(2X, I3) )' )  B (i, :)
   end do
   call double_array (B)
   write (*, '( / "2D array after:" )' )
   do i=1, 2
      write (*, '( 2(2X, I3) )' )  B (i, :)
   end do   

   stop
end program demo_user_generic

kemiisto我知道这个编译错误是非常明显的。我也知道实现我想要的一种方法是为不同的列组编写单独的分配器。我将不得不这样做作为最后的手段:)但我的问题是-有没有一种合法的fortran方式来编写一个包装器来分配相同的功能,即universal wrt rank。。。无论如何谢谢你!谢谢!虽然它需要在分配器模块中复制代码,但至少在调用此分配器函数时可以使用公共名称。这就是我想要的。