快速泊松解算器(MKL)对Fortran 90中基于零的索引的自适应
我有一个问题,我试图通过使用“英特尔MKL”子例程集(快速泊松解算器子例程)求解泊松方程(这只是迭代过程中三个耦合方程中的一个)。 现在,我必须指出,我的整个代码(几千行)都是在假设以零为基础的索引的情况下以以下方式编写的:快速泊松解算器(MKL)对Fortran 90中基于零的索引的自适应,fortran,intel-mkl,Fortran,Intel Mkl,我有一个问题,我试图通过使用“英特尔MKL”子例程集(快速泊松解算器子例程)求解泊松方程(这只是迭代过程中三个耦合方程中的一个)。 现在,我必须指出,我的整个代码(几千行)都是在假设以零为基础的索引的情况下以以下方式编写的: arbitrary_array(0:N),arbitrary_matrix(0:N,0:M) 其中N和M分别是x和y方向上的网格点。 因为我知道MKL Poisson solver有一个基于索引的索引,所以我编写了以下子例程来进行必要的转换: SUBROUTINE
arbitrary_array(0:N),arbitrary_matrix(0:N,0:M)
其中N和M分别是x和y方向上的网格点。
因为我知道MKL Poisson solver有一个基于索引的索引,所以我编写了以下子例程来进行必要的转换:
SUBROUTINE POISSON_SOLVER_MKL(N,M,Phi,Div,Ja,Lx,Ly,dx,dy)
IMPLICIT NONE
!
INTEGER,INTENT(IN)::N,M !Zero-based index count
REAL(DP),INTENT(IN)::Div(0:N,0:M) !This is right-hand side of PE
REAL(DP),INTENT(IN)::Ja,Lx,Ly,dx,dy !BC,X and Y size of the system,unit cell size
REAL(DP),INTENT(OUT)::Phi(0:N,0:M) !This is left-hand side of PE
INTEGER::NX,NY !One-based index count
INTEGER::stat,ipar(128) !MKL parameters
REAL(DP)::ax,bx,ay,by,q
REAL(DP),ALLOCATABLE::dpar(:),f_POISSON(:,:),bd_ax(:),bd_bx(:),bd_ay(:),bd_by(:)
TYPE(DFTI_DESCRIPTOR),POINTER::xhandle
CHARACTER(4)::BCtype
NX=N+1 !This is where indices are shifted
NY=M+1
ALLOCATE(dpar(13*NX/2+7),f_POISSON(NX+1,NY+1),bd_ax(NY+1),bd_bx(NY+1),bd_ay(NX+1),bd_by(NX+1))
!Allocation of the arrays and matrices required for MKL solver
q=0.d0 !Set for Poisson equation
ax=0.d0 !First coordinate in x direction
bx=Lx !Last coordiante in x direction
ay=0.d0
by=Ly
BCtype='NNNN' !Set the Boundary Conditions to be all Neumann
bd_ax=0.d0
bd_bx=0.d0
bd_ay=-Ja
bd_by=Ja
ipar=0
CALL D_INIT_HELMHOLTZ_2D(ax,bx,ay,by,NX,NY,BCtype,q,ipar,dpar,stat)
PRINT*,'STAT=',STAT
f_POISSON(1:NX+1,1:NY+1)=Div(0:N,0:M) !Transferring the variables from zero-based indexing to one-based indexing
CALL D_COMMIT_HELMHOLTZ_2D(f_POISSON,bd_ax,bd_bx,bd_ay,bd_by,xhandle,ipar,dpar,stat)
PRINT*,'STAT=',STAT
CALL D_HELMHOLTZ_2D(f_POISSON,bd_ax,bd_bx,bd_ay,bd_by,xhandle,ipar,dpar,stat)
PRINT*,'STAT=',STAT
Phi(0:N,0:M)=f_POISSON(1:NX+1,1:NY+1) !Returning the variables from one-based indexing to zero-based indexing
CALL FREE_HELMHOLTZ_2D(xhandle,ipar,stat)
PRINT*,'STAT=',STAT
DEALLOCATE(dpar,f_POISSON,bd_ax,bd_bx,bd_ay,bd_by)
END SUBROUTINE POISSON_SOLVER_MKL
不幸的是,这整段代码编译时没有任何错误,但我得到的结果没有多大意义。
这让我得出一个结论,我可能在索引转换和分配中犯了一个错误,但我根本不知道这个错误在哪里
有人遇到过类似类型的问题吗?接下来,NX
和NY
似乎是网格间隔的数量(不是网格点),因此在伪参数中可以将Div
作为Div(0:N,0:M)
或Div(N+1,M+1)
(与Phi
相同)并设置Nx=N
和Ny=M
。如果使用后者,修改后的代码可能如下所示(但尚未测试,因此请尝试使用实际数据):
请注意,我们不需要修改调用子例程(那里使用的数组可能是基于0的,如Div(0:N,0:M)
),并且我们不需要使用f\u poisson
进行Div
的复制/复制
我们也可以使用基于0的索引编写相同的例程(如问题中所示)。在这种情况下,对于i=0,1,…,nx(类似于y),网格点变成
x(i)=ax+i*(bx-ax)/nx
,并且可能更好地声明边界阵列也是基于0的,例如
SUBROUTINE POISSON_SOLVER_MKL(N,M,Phi,Div,Ja,Lx,Ly,dx,dy)
IMPLICIT NONE
!
INTEGER,INTENT(IN)::N,M ! Number of mesh intervals
REAL(DP),INTENT(IN) ::Div( 0:N, 0:M ) !This is right-hand side of PE
REAL(DP),INTENT(OUT)::Phi( 0:N, 0:M ) !This is left-hand side of PE
...
Nx = N
Ny = M
ALLOCATE( dpar(13*Nx/2+7), bd_ax(0:Ny), bd_bx(0:Ny), bd_ay(0:Nx), bd_by(0:Nx) )
...
! other parts are the same
为调试目的打开边界检查。f_POISSON(1:NX+1,1:NY+1)=Div(0:N,0:M),NX=N+1和NY=M+1,那么大小不一致?因此,我不太确定是否理解@HighPerformanceMark给出的注释,但我现在做的是:我编写了另一个子例程,用于假定的形状数组参数。但即使在这种情况下,我仍然需要网格空间的大小,这样我就可以在内部定义BC。这个页面可能很有用:谢谢@roygvib,我整天都在看这个,我试图模仿这里提供的示例中的形式,但我仍然得到了相同的结果,而不是收敛,解现在振荡。编辑>另外,你知道为什么在该页提供的示例中,在定义nx和ny之后,所有循环都从1变为nx,y+1吗?@Itzaak因为我从未在MKL中使用过泊松解算器,并且非常粗略地编写了上面修改的代码,可能仍然存在错误,所以请小心!对不起,我声明Nx和Ny为实变量,但它们当然应该是整数(
SUBROUTINE POISSON_SOLVER_MKL(N,M,Phi,Div,Ja,Lx,Ly,dx,dy)
IMPLICIT NONE
!
INTEGER,INTENT(IN)::N,M ! Number of mesh intervals
REAL(DP),INTENT(IN) ::Div( 0:N, 0:M ) !This is right-hand side of PE
REAL(DP),INTENT(OUT)::Phi( 0:N, 0:M ) !This is left-hand side of PE
...
Nx = N
Ny = M
ALLOCATE( dpar(13*Nx/2+7), bd_ax(0:Ny), bd_bx(0:Ny), bd_ay(0:Nx), bd_by(0:Nx) )
...
! other parts are the same