前言
我正在编写的Fortran程序应该根据ndims
处理1D、2D和3D问题,CCD_1可以是1、2或3,并且是从输入文件中读取的。
在这些情况下,感兴趣的数量可以存储在阵列中(一个可以被命名为phi
(
- 3(
ALLOCATABLE(:)
或ALLOCATABLE(:,:)
或ALLOCATABLE(:,:,:)
( - 或者在秩3的阵列中(
ALLOCATABLE(:,:,:)
,其中第三维度在2D中被设置为等于1,或者第二维度和第三维度两者在1D中都等于1(
这两种情况在这个答案中都得到了很好的解释。第一种方法对我来说似乎更优雅,但在下面我假设第二种方法,它肯定更简单。
这些量必须由沿着ndims
维度的几个子程序(例如mysub
(来操作(沿着"铅笔"应该给出一个图形概念(,所以我应该称之为
SELECT CASE (ndims)
! 3D case
CASE (3)
DO j = ...
DO k = ...
CALL mysub(phi(:,j,k))
END DO
END DO
DO i = ...
DO k = ...
CALL mysub(phi(i,:,k))
END DO
END DO
DO i = ...
DO j = ...
CALL mysub(phi(i,j,:))
END DO
END DO
! 2D case
CASE (2)
DO j = ...
DO k = ...
CALL mysub(phi(:,j,1))
END DO
END DO
DO i = ...
DO k = ...
CALL mysub(phi(i,:,1))
END DO
END DO
! 1D case
CASE (1)
DO j = ...
DO k = ...
CALL mysub(phi(:,1,1))
END DO
END DO
END SELECT
实际问题
有人能建议我(或帮助我设计!(一种不同的存储phi
的方法吗?(可能涉及派生数据类型?(这样我就可以按如下方式折叠前面的代码了?
DO id = 1, ndims
CALL mysub2(phi,id)
END DO
(此处mysub2
作用于mysub
的位置。(
所以问题是我应该如何存储phi,以便用第二个代码替换第一个代码?
也许我可以回到前言,决定遵循第1点,在这种情况下,编写通用接口会更容易。我认为,这只是一种"隐藏"SELECT CASE
的确切功能的方法。两者(SELECT CASE
/通用INTERFACE
(中的哪一个更有效?
面对这个问题,只有这两种方法吗?
也许我误解了,但我认为具体问题的答案是根本不更改phi的存储或声明。
在原始代码中,三维数据(区分数据的秩和用于存储数据的数组的秩(是沿着第一维度、第二维度、第三维度分片处理的。二维数据沿第一条处理,然后沿第二条处理,而一维数据仅沿第一条进行处理。
因此,当id从1到数据中的维数时,考虑以下mysub2
的实现:
SUBROUTINE mysub2(phi, id)
TYPE(pink_elephant), INTENT(IN) :: phi(:,:,:)
INTEGER, INTENT(IN) :: id
INTEGER :: i, j, k
SELECT CASE (id)
CASE (1)
DO j = ...
DO k = ...
CALL mysub(phi(:,j,k))
END DO
END DO
CASE (2)
DO i = ...
DO k = ...
CALL mysub(phi(i,:,k))
END DO
END DO
CASE (3)
DO i = ...
DO j = ...
CALL mysub(phi(i,j,:))
END DO
END DO
END SELECT
END SUBROUTINE mysub2
~~
泛型接口总是可以在"编译时"解析——特定CALL语句或函数引用将调用的特定过程(非类型绑定(或绑定(类型绑定(可以通过查看代码中的声明来确定。
如果你有一种情况,"运行时"信息将影响过程的选择,那么除了通用的解析之外,还必须有一些其他可执行机制发挥作用——If语句、select case、动态调度等。
因此,询问通用解决方案是否比可执行决策更有效并没有特别的意义——它们是不同的。
您可能想要这样的东西:
program test
integer :: j,ndims
integer :: n ! rank of each dimension, could also be read from input an allocated separately
type arr
real(8) :: x(n) ! one array for each dimension
end type
type(arr),allocatable :: phi
read(*,*) ndims
allocate(phi(ndims))
do j=1,ndims
call mysub(phi(j)%x) ! acts on the array in dimension j
end do
contains
subroutine mysub(x)
...
end subroutine
end program