我有问题,我不知道怎么了。我的代码正在尝试在其中一个过程计算出数字后发送值。
这是我的伪代码:
*calculates which process will compute the value.
if (rank == proc) then
*do some operations and calculate the value
! if the process is not the root, send the value.
if (proc /= 0)
call MPI_SEND(auxvalue,1,MPI_REAL8,0,1,MPI_COMM_WORLD,ierr)
end if
else
if (size>1) then
if (rank==0) then
call MPI_RECV(auxvalue,1,MPI_REAL8,proc,1,MPI_COMM_WORLD,status,ierr)
end if
end if
end if
但是根进程既不接收值,也不从不发送值。
你能帮我吗?
编辑:
正如您在此处建议的那样,这是代码,这只是一个子例程,该子例程在点中(使用双三次方法)内插函数f的值。 mpi的初始功能位于主程序中,这部分仅是内插功能。我在这里使用的模块可以正常工作并经过测试。
real(8)函数bicuinterp(r0,z0,f,Drf,Dzf,Drzf,errorflag)
use mpi
use procinfo
use param
use arrays
implicit none
integer status(MPI_STATUS_SIZE)
logical errorflag ! Flag to control the behaviour of error.
real(8),dimension(1-ghost:Nrmax,1-ghost:Nzmax) :: f,Drf,Dzf,Drzf
! Function and his derivatives to be interpolated.
real(8),dimension (1:4,1:4) :: M, fval, auxA
real(8),dimension (4) :: x,y
! Powers of grid point distances.
real(8) r0,z0 ! Point at which we are interpolating.
real(8) deltar,deltaz ! Distance to the grid point to the left.
real(8) Nauxr, Nauxz ! Coordinates of the processor which owns the grid point.
real(8) rmin,rmax ! Minimum and maximum rho-coordinate.
real(8) zmin,zmax ! Minimum and maximum z-coordinate.
real(8) drdz ! Product of dr*dz
real(8) small
real(8) auxbicuinterp
integer procr, procz, proc ! Processor which owns the grid point.
integer i0,j0 ! Grid point immediatly to the left in rho,z directions.
integer i,j,k,l ! Counters
! Common constants
drdz = dr*dz
! ************************
! *** SANITY CHECK ***
! ************************
! First check that the interpolating point is inside the grid,
! and that there are enough points to either side for bicubic
! interpolation.
rmin = (dble(1-ghost)-0.5d0)*dr
rmax = (dble(Nrtotal)-0.5d0)*dr
if (eqsym) then
zmin = (dble(1-ghost)-0.5d0)*dz
zmax = (dble(Nztotal)-0.5d0)*dz
else
zmin = (-dble(Nztotal)/2.0+0.5d0)*dz
zmax = (dble(Nztotal)/2.0-0.5d0)*dz
end if
if (rank==0) then
if ((r0<rmin).or.(r0>rmax) .or. (z0<zmin) .or. (z0>zmax)) then
print *
print *, 'interp.f90: Interpolating point is outside the grid'
write(*,'(A,ES12.4)') ' Interpolating position =',r0,',',z0
write(*,'(A,ES12.4)') ' Left boundary =',rmin
write(*,'(A,ES12.4)') ' Right boundary =',rmax
write(*,'(A,ES12.4)') ' Lower boundary =',zmin
write(*,'(A,ES12.4)') ' Upper boundary =',zmax
write(*,'(A,I3)') ' Processor =',rank
print *
print *, 'Aborting ...'
print *
bicuinterp = 0.0D0
go to 200
! call die
else if (r0<rmin+dr) then
print *
print *, 'interp.f90: Not enough points to left side for cubic interpolation'
write(*,'(A,ES12.4)') ' Interpolating position =',r0
write(*,'(A,ES12.4)') ' Left boundary =',rmin
write(*,'(A,ES12.4)') ' Grid spacing =',dr
print *
print *, 'Aborting ...'
print *
bicuinterp = 0.0D0
! call die
go to 200
else if (r0>rmax-dr) then
print *
print *, 'interp.f90: Not enough points to right side for cubic interpolation'
write(*,'(A,ES12.4)') ' Interpolating position =',r0
write(*,'(A,ES12.4)') ' Right boundary =',rmax
write(*,'(A,ES12.4)') ' Grid spacing =',dr
print *
print *, 'Aborting ...'
print *
bicuinterp = 0.0D0
go to 200
! call die
else if (z0<zmin+dz) then
print *
print *, 'interp.f90: Not enough points to lower side for cubic interpolation'
write(*,'(A,ES12.4)') ' Interpolating position =',z0
write(*,'(A,ES12.4)') ' Left boundary =',zmin
write(*,'(A,ES12.4)') ' Grid spacing =',dz
print *
print *, 'Aborting ...'
print *
bicuinterp =0.0D0
go to 200
! call die
else if (z0>zmax-dz) then
print *
print *, 'interp.f90: Not enough points to lower side for cubic interpolation'
write(*,'(A,ES12.4)') ' Interpolating position =',z0
write(*,'(A,ES12.4)') ' Left boundary =',zmax
write(*,'(A,ES12.4)') ' Grid spacing =',dz
print *
print *, 'Aborting ...'
print *
bicuinterp = 0.0D0
go to 200
! call die
end if
end if
! **************************************
! *** CHECK IF YOU OWN THE POINT ***
! **************************************
! For multiple processor runs check that you
! own the point to be interpolated and that
! there are enough points for bicubic interpolation.
!
! Notice that we need to make sure that only one
! processor owns the point, which might be a problem
! close to inter-processor boundaries where there is
! an overlap. When that happens here I choose the
! processor to the left as owner of the point (but
! carefull with processor zero that has no neighbour
! to the left).
if (size>1) then
! If you don't own the grid point then either die,
! or return 0.
if ((r0<=r(Nminr(rank),1)).or.(r0>r(Nmaxr(rank),1)) .or.(z0<=z(1,Nminz(rank))).or.(z0>z(1,Nmaxz(rank)))) then
if (errorflag) then
write(*,'(A,3ES12.4)') ' bicuinterp.f90 I do not own the point (r0,z0,rmin,rmax,zmin,zmax):',r0,rmin,rmax
write(*,'(A,I3,A,I3)') ' Processor:',rank
print *, 'Aborting ...'
! call die
print *
else
auxbicuinterp = 0.d0
! return
end if
end if
end if
! *********************************************
! *** FIND GRID POINT TO THE LEFT OF r0 ***
! *********************************************
! Find the processor who owns the grid point.
Nauxr = Nrtotal/nprocr
Nauxz = Nztotal/nprocz
procr = int(r0/(dr*Nauxr))!-1
if (eqsym) then
procz = int(z0/(dz*Nauxz))!-1
else
procz = int((z0/dz+0.5*Nztotal)/Nauxz)
end if
proc = procr + nprocr*procz
! If the grid point at which we are interpolating is at the right boundary of
! the processor, we take the next processor to the right.
if (Nmaxr(proc)*dr<=r0+dr) then
procr = procr+1
end if
if (Nmaxz(proc)*dz<=z0+dr) then
procz = procz+1
end if
proc = procr + nprocr*procz
! Find the grid point to the left to our point (rho,z)
if (rank==proc) then
i0 = int(r0/dr + 0.5D0-Nminr(proc))
if (eqsym) then
j0 = int(z0/dz + 0.5D0-Nminz(proc))
else
j0 = int(z0/dz -Nminz(proc)+0.5*(Nztotal+1-ghost))
end if
! Calculate separation from grid point
deltar = (r0-r(i0,j0))/dr
deltaz = (z0-z(i0,j0))/dz
! Check that the point to be interpolated
! is indeed between grid points (i0,i0+1) and (j0,j0+1).
small = 1.d-10
! if ((deltar<-small).or.(deltar>dr+small)) then
!
! print *
! print *, 'bicuinterp.f90: this should never happen! error in deltar'
! ! print *, 'deltar', deltar, 'dr+small',dr+small, 'rank',rank
! print *, r0,r(i0,j0),r(i0+1,j0),rank,deltar,dr,i0,Nmaxr(proc)*dr
! print *, 'Aborting ...'
! print *
! ! call die
! bicuinterp = 0.0D0
! goto 200
! end if
! if ((deltaz<-small).or.(deltaz>dz+small)) then
!
! print *
! print *, 'bicuinterp.f90: this should never happen! error in deltaz'
! ! print *, 'deltaz', deltaz, 'dz+small',dz+small
! print *, z0,z(i0,j0),z(i0,j0+1),rank,deltaz,dz,j0,z0/dz
! print *, 'Aborting ...'
! print *, 'Nmaxr', Nmaxr(proc), Nminr(proc+1)
! print *
! ! call die
! bicuinterp = 0.0D0
! goto 200
! end if
if ( (r(i0,j0)>r0+small) .or. (r0-small>r(i0+1,j0)) ) then
print *, 'bicuinterp.f90, point outside grid points: ERROR'
! print *, 'r0=',r0,' is not between (',i0,i0+1,')'
! print *, r(i0,j0),r(i0+1,j0)
bicuinterp = 0.0D0
goto 200
end if
if ( (z(i0,j0)>z0+small) .or. (z0-small>z(i0,j0+1)) ) then
print *, 'bicuinterp.f90, point outside grid points: ERROR'
print *, 'z0 is not between (j0,j0+1)'
print *, z0,z(i0,j0),z(i0,j0+1)
bicuinterp = 0.0D0
goto 200
end if
! ********************************
! *** BICUBIC INTERPOLATON ***
! ********************************
! Fill the values of the function and his derivative at the corners for interpolation.
fval(1,1) = f(i0 ,j0 )
fval(1,2) = f(i0 ,j0+1)
fval(1,3) = Dzf(i0 ,j0 )*dz
fval(1,4) = Dzf(i0 ,j0+1)*dz
fval(2,1) = f(i0+1,j0 )
fval(2,2) = f(i0+1,j0+1)
fval(2,3) = Dzf(i0+1,j0 )*dz
fval(2,4) = Dzf(i0+1,j0+1)*dz
fval(3,1) = Drf(i0 ,j0 )*dr
fval(3,2) = Drf(i0 ,j0+1)*dr
fval(3,3) = Drzf(i0 ,j0 )*drdz
fval(3,4) = Drzf(i0 ,j0+1)*drdz
fval(4,1) = Drf(i0+1,j0 )*dr
fval(4,2) = Drf(i0+1,j0+1)*dr
fval(4,3) = Drzf(i0+1,j0 )*drdz
fval(4,4) = Drzf(i0+1,j0+1)*drdz
!Fill coefficients for matrix interpolation
M = 0.0D0
M(1,1) = 1.0D0
M(2,3) = 1.0D0
M(3,1) = -3.0D0
M(3,2) = 3.0D0
M(3,3) = -2.0D0
M(3,4) = -1.0D0
M(4,1) = 2.0D0
M(4,2) = -2.0D0
M(4,3) = 1.0D0
M(4,4) = 1.0D0
! Array with powers of the separation from the grid points
x = 0.0D0
x(1) = 1.0D0
x(2) = deltar
x(3) = deltar**2
x(4) = deltar**3
y = 0.0D0
y(1) = 1.0D0
y(2) = deltaz
y(3) = deltaz**2
y(4) = deltaz**3
auxbicuinterp = 0.0D0
do l=1,4
do k=1,4
do j=1,4
do i=1,4
auxbicuinterp = auxbicuinterp + x(i)*M(i,j)*fval(j,k)*M(l,k)*y(l)
end do
end do
end do
end do
!If the process isn't the root, send it.
if (rank /= 0) then
call MPI_SEND(auxbicuinterp,1,MPI_REAL8,0,1,MPI_COMM_WORLD,ierr)
end if
else
if (size>1) then
!Only the root process receive the value
if (proc /= 0 .and. rank==0) then
call MPI_RECV(auxbicuinterp,1,MPI_REAL8,proc,1,MPI_COMM_WORLD,status,ierr)
end if
end if
end if
bicuinterp = auxbicuinterp
200 continue
return
end function bicuinterp
我知道时间太长,但是正如我在上面解释的那样,只有一个进程插值该值,并且仅当该进程不是根(零)时才需要将其发送到根进程,但是我的代码没有工作。