计算一个进程中的一个值,并将其发送到根进程mpi

时间:2019-02-28 18:46:36

标签: mpi

我有问题,我不知道怎么了。我的代码正在尝试在其中一个过程计算出数字后发送值。

这是我的伪代码:

*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

我知道时间太长,但是正如我在上面解释的那样,只有一个进程插值该值,并且仅当该进程不是根(零)时才需要将其发送到根进程,但是我的代码没有工作。

0 个答案:

没有答案