Fortran 如何为';分配';
我试图为'allocate'函数编写一个包装器,即接收数组和维度、分配内存并返回已分配数组的函数。最重要的是,函数必须使用不同秩的数组。但我必须在函数接口中显式地声明数组的秩,在这种情况下,只有当我将某个秩的数组作为参数传递时,代码才会编译。例如,此代码不编译:Fortran 如何为';分配';,fortran,Fortran,我试图为'allocate'函数编写一个包装器,即接收数组和维度、分配内存并返回已分配数组的函数。最重要的是,函数必须使用不同秩的数组。但我必须在函数接口中显式地声明数组的秩,在这种情况下,只有当我将某个秩的数组作为参数传递时,代码才会编译。例如,此代码不编译: module memory_allocator contains subroutine memory(array, length) implicit none real(8), allocatable, int
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。。。无论如何谢谢你!谢谢!虽然它需要在分配器模块中复制代码,但至少在调用此分配器函数时可以使用公共名称。这就是我想要的。