!########################################################################
!########################################################################
!######### #########
!######### SUBROUTINE MPIPROCESS #########
!######### #########
!######### Developed by #########
!######### Center for Analysis and Prediction of Storms #########
!######### University of Oklahoma #########
!######### #########
!########################################################################
!########################################################################
SUBROUTINE mpiprocess(nobmpi,indexmpi,np,kitem,kitemmax, & 2,4
isrc,item1,nx,ny,xmpi,ympi,xs,ys)
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Determine which processor "owns" an ob. Later, when we need info,
! we know who to "contact".
!
!-----------------------------------------------------------------------
!
! AUTHOR: Kevin W. Thomas, CAPS
! December 2, 2005
!
! MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
! Force explicit declarations
!
!-----------------------------------------------------------------------
IMPLICIT NONE
!-----------------------------------------------------------------------
!
! Subroutine arguments
!
!-----------------------------------------------------------------------
INTEGER, INTENT(IN) :: nobmpi ! Total number of single-point
! observations stored in arrays
INTEGER, INTENT(INOUT) :: indexmpi(nobmpi) ! Owner
INTEGER, INTENT(IN) :: np ! Number of processors (nprocs)
INTEGER, INTENT(INOUT) :: kitem(np) ! Number obs handled by each processor
INTEGER, INTENT(INOUT) :: kitemmax ! Largest "kitem" value
INTEGER, INTENT(INOUT) :: isrc(nobmpi) ! Data source number
INTEGER, INTENT(INOUT) :: item1(nobmpi) ! Work array
REAL, INTENT(INOUT) :: xmpi(nobmpi) ! Observation x grid coordinate (m)
REAL, INTENT(INOUT) :: ympi(nobmpi) ! Observation y grid coordinate (m)
INTEGER, INTENT(IN) :: nx,ny ! Grid dimensions.
REAL, INTENT(IN) :: xs(nx) ! x-coordinates of grid scalar points (m)
REAL, INTENT(IN) :: ys(ny) ! y-coordinates of grid scalar points (m)
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
INCLUDE 'mp.inc'
!-----------------------------------------------------------------------
!
! Misc. local variables
!
!-----------------------------------------------------------------------
INTEGER :: ksta
INTEGER :: ipt,jpt
INTEGER :: indom
INTEGER :: ierror
INTEGER :: k
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
DO ksta=1,nobmpi
indexmpi(ksta) = -1
!
! If we've been declared "bad" or joined via "suprob", then stop here.
!
IF (isrc(ksta) == 0 ) CYCLE
CALL findlc
(nx,ny,xs,ys,xmpi(ksta),ympi(ksta),ipt,jpt,indom)
IF (indom == 0 ) indexmpi(ksta) = myproc
END DO
!
! Collect and merge the data.
!
IF (myproc > 0 ) THEN
CALL mpsendi
(indexmpi,nobmpi,0,1000+myproc,ierror)
ELSE
DO k=1,nprocs-1
CALL mprecvi
(item1,nobmpi,k,1000+k,ierror)
DO ksta=1,nobmpi
IF ( item1(ksta) == -1 ) CYCLE
!-------------------------------------------------------------------------
!
! Since there are overlapping grids in MPI, it is possible for an ob to
! be available to more than one processor. We select the first processor.
! There is no need for more than one processor to make identical
! computations.
!
! The WARNING message is commented out, as it is useful for debugging,
! however, it will likely confuse anyone else.
!
!-------------------------------------------------------------------------
! IF ( indexmpi(ksta) .ne. -1 ) THEN
! WRITE(6,*) 'WARNING: station ',ksta,' found in ', &
! indexmpi(ksta),' and ',item1(ksta)
! END IF
indexmpi(ksta) = item1(ksta)
END DO
END DO
END IF
! Dump the station to processor mapping. Useful only for code debugging.
! if ( myproc == 0 ) then
! write(6,*) 'MAPPING: '
! do ksta=1,nobmpi
! write(6,*) ksta,indexmpi(ksta)
! end do
! endif
CALL mpupdatei
(indexmpi,nobmpi)
!
! Everybody computes the same table of how many obs each processor owns.
!
kitem = 0
DO k=1,nobmpi
IF(indexmpi(k) >= 0) kitem(indexmpi(k)+1) = kitem(indexmpi(k)+1) + 1
END DO
kitemmax = 0
DO k=1,np
IF(kitem(k) > kitemmax) kitemmax = kitem(k)
ENDDO
RETURN
END SUBROUTINE mpiprocess
!########################################################################
!########################################################################
!######### #########
!######### SUBROUTINE MPIPROCESS_UPDATE #########
!######### #########
!######### Developed by #########
!######### Center for Analysis and Prediction of Storms #########
!######### University of Oklahoma #########
!######### #########
!########################################################################
!########################################################################
!SUBROUTINE mpiprocess_update(nobmpi,indexmpi,item1)
SUBROUTINE mpiprocess_update(nobmpi,indexmpi) 1,3
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Update the communications index table if it has been altered. This
! is a hook for cloud soundings.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Kevin W. Thomas, CAPS
! December 2, 2005
!
! MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
! Force explicit declarations
!
!-----------------------------------------------------------------------
IMPLICIT NONE
!-----------------------------------------------------------------------
!
! Subroutine arguments
!
!-----------------------------------------------------------------------
INTEGER, INTENT(IN) :: nobmpi ! Total number of single-point
! observations stored in arrays
INTEGER, INTENT(INOUT) :: indexmpi(nobmpi) ! Owner
! INTEGER, INTENT(INOUT) :: item1(nobmpi) ! Work array
INTEGER :: item1(nobmpi)
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
INCLUDE 'mp.inc'
!-----------------------------------------------------------------------
!
! Misc. local variables
!
!-----------------------------------------------------------------------
INTEGER :: ksta
INTEGER :: ipt,jpt
INTEGER :: indom
INTEGER :: ierror
INTEGER :: k
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Collect and merge the data.
!
IF (myproc > 0 ) THEN
CALL mpsendi
(indexmpi,nobmpi,0,1000+myproc,ierror)
ELSE
DO k=1,nprocs-1
CALL mprecvi
(item1,nobmpi,k,1000+k,ierror)
DO ksta=1,nobmpi
IF ( item1(ksta) == -1 ) CYCLE
!-------------------------------------------------------------------------
!
! Since there are overlapping grids in MPI, it is possible for an ob to
! be available to more than one processor. We select the first processor.
! There is no need for more than one processor to make identical
! computations.
!
! The WARNING message is commented out, as it is useful for debugging,
! however, it will likely confuse anyone else.
!
! There is a potential issue affecting cloud soundings that doesn't exist
! in "mpiprocess" above. Stations *outside* of the domain are permitted.
! These are assigned a processor inside of "insert_sao1". It *is* possible
! for a point to be assigned to more than one processors, however, only one
! of them is correct, if the non-MPI and MPI solutions are to be the same.
!
! For now, we'll use the rule that processor 0 will always override any
! other ownership claims. This is based on one case. If other problems
! are seen, something else will have to be done.
!
!
!-------------------------------------------------------------------------
IF ( indexmpi(ksta) .eq. 0 ) CYCLE
! IF ( indexmpi(ksta) .ne. -1 ) THEN
! WRITE(6,*) 'WARNING: station ',ksta,' found in ', &
! indexmpi(ksta),' and ',item1(ksta)
! END IF
indexmpi(ksta) = item1(ksta)
END DO
END DO
END IF
! Dump the station to processor mapping. Useful only for code debugging.
! if ( myproc == 0 ) then
! write(6,*) 'MAPPING: '
! do ksta=1,nobmpi
! write(6,*) ksta,indexmpi(ksta)
! end do
! endif
CALL mpupdatei
(indexmpi,nobmpi)
RETURN
END SUBROUTINE mpiprocess_update
SUBROUTINE make_mpi_map(mpi_map,nmap,iproc,jproc,nx,ny) 1
!-----------------------------------------------------------------------
!
! PURPOSE:
! Build a map of who needs to communicate with other processors.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Kevin W. Thomas, CAPS
! October 6, 2006
!
! MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
! Force explicit declarations
!
!-----------------------------------------------------------------------
IMPLICIT NONE
!-----------------------------------------------------------------------
!
! Subroutine arguments
!
!-----------------------------------------------------------------------
INTEGER, INTENT(IN) :: nmap ! Number of map entries
INTEGER, INTENT(INOUT) :: mpi_map(nmap,2) ! The map
INTEGER, INTENT(IN) :: iproc ! Number of x-direction offsets
INTEGER, INTENT(IN) :: jproc ! Number of y-direction offsets
INTEGER, INTENT(IN) :: nx ! Number of x-direction grid pts
INTEGER, INTENT(IN) :: ny ! Number of y-direction grid pts
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
INCLUDE 'mp.inc'
!-----------------------------------------------------------------------
!
! Misc. local variables
!
!-----------------------------------------------------------------------
INTEGER :: i,j,k,n
INTEGER :: lx, ly
IF (mp_opt == 0) RETURN
mpi_map = -1
!
! Receive map.
!
k = 0
DO j=-jproc,jproc
ly = loc_y + j
IF (ly < 1 .OR. ly > nproc_y) THEN
k = k + (2 * iproc + 1 )
CYCLE
END IF
DO i=-iproc,iproc
k = k + 1
IF (i == 0 .and. j == 0) CYCLE
lx = loc_x + i
IF (lx < 1 .OR. lx > nproc_x) CYCLE
n = myproc + j * nproc_x + i
IF (n >= nprocs) CYCLE
mpi_map(k,2) = n
END DO
END DO
!
! Send map, just flip flop the receive map.
!
DO k=1,nmap
mpi_map(k,1) = mpi_map(nmap-k+1,2)
END DO
END SUBROUTINE make_mpi_map
SUBROUTINE mpi_1di_collect(m, nobmpi, indexmpi, & 1,4
np, kdata, kdatamax, mpi_map, nmap, tmps, tmpr )
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Collect all the processor dependent calculations and merge them into a
! single array which we will broadcast.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Kevin W. Thomas, CAPS
! January 10, 2006
!
! MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
! Force explicit declarations
!
!-----------------------------------------------------------------------
IMPLICIT NONE
!-----------------------------------------------------------------------
!
! Subroutine arguments
!
!-----------------------------------------------------------------------
INTEGER, INTENT(IN) :: nobmpi ! Actual number of stations
INTEGER, INTENT(IN) :: indexmpi(nobmpi) ! Array saying which ob is on which
! processor.
REAL, INTENT(INOUT) :: m(nobmpi) ! Data to be collected and updated.
INTEGER, INTENT(IN) :: np ! Just "nprocs"
INTEGER, INTENT(IN) :: kdata(np) ! Number of obs owned by each processor
INTEGER, INTENT(IN) :: kdatamax ! Largest "kdata" value
INTEGER, INTENT(IN) :: nmap ! Number of entries in "mpi_map"
INTEGER, INTENT(IN) :: mpi_map(nmap,2)! Mapping scheme
REAL, INTENT(INOUT) :: tmps(kdatamax)
REAL, INTENT(INOUT) :: tmpr(kdatamax)
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
INCLUDE 'mp.inc'
!-----------------------------------------------------------------------
!
! Misc. local variables
!
!-----------------------------------------------------------------------
INTEGER :: istat
INTEGER :: isum
INTEGER :: itag
INTEGER :: ierror
INTEGER :: i, j, k, l, ksta
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
isum = kdatamax
!
! Save our data.
!
k = 0
DO j=1,nobmpi
IF (indexmpi(j) == myproc) THEN
k=k+1
tmps(k) = m(j)
END IF
END DO
!
! Sanity.
!
IF ( k .ne. kdata(myproc+1) ) THEN
WRITE(6,*) 'mpi_1di_collect inconsistency: ',k,kdata(myproc+1)
CALL arpsstop
("mpi_1di_collect",1)
END IF
DO k=1,nmap
CALL inctag
itag = gentag
!
! Are we a sender?
!
IF (mpi_map(k,1) .NE. -1 ) THEN
CALL mpsendr
(tmps,isum,mpi_map(k,1),itag,ierror)
ENDIF
!
! Are we a receiver?
!
IF (mpi_map(k,2) .NE. -1) THEN
CALL mprecvr
(tmpr,isum,mpi_map(k,2),itag,ierror)
ELSE
CYCLE
END IF
l = 0
DO ksta=1,nobmpi
!
! Make sure we are the right processor.
!
IF (indexmpi(ksta) .NE. mpi_map(k,2)) CYCLE
l = l + 1
m(ksta) = tmpr(l)
END DO
END DO
RETURN
END SUBROUTINE mpi_1di_collect
SUBROUTINE mpi_1dr_collect(m, nobmpi, indexmpi, & 4,4
np, kdata, kdatamax, mpi_map, nmap, tmps, tmpr )
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Collect all the processor dependent calculations and merge them into a
! single array which we will broadcast.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Kevin W. Thomas, CAPS
! January 10, 2006
!
! MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
! Force explicit declarations
!
!-----------------------------------------------------------------------
IMPLICIT NONE
!-----------------------------------------------------------------------
!
! Subroutine arguments
!
!-----------------------------------------------------------------------
INTEGER, INTENT(IN) :: nobmpi ! Actual number of stations
INTEGER, INTENT(IN) :: indexmpi(nobmpi) ! Array saying which ob is on which
! processor.
REAL, INTENT(INOUT) :: m(nobmpi) ! Data to be collected and updated.
INTEGER, INTENT(IN) :: np ! Just "nprocs"
INTEGER, INTENT(IN) :: kdata(np) ! Number of obs owned by each processor
INTEGER, INTENT(IN) :: kdatamax ! Largest "kdata" value
INTEGER, INTENT(IN) :: nmap ! Number of entries in "mpi_map"
INTEGER, INTENT(IN) :: mpi_map(nmap,2)! Mapping scheme
REAL, INTENT(INOUT) :: tmps(kdatamax)
REAL, INTENT(INOUT) :: tmpr(kdatamax)
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
INCLUDE 'mp.inc'
!-----------------------------------------------------------------------
!
! Misc. local variables
!
!-----------------------------------------------------------------------
INTEGER :: istat
INTEGER :: isum
INTEGER :: itag
INTEGER :: ierror
INTEGER :: i, j, k, l, ksta
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
isum = kdatamax
!
! Save our data.
!
k = 0
DO j=1,nobmpi
IF (indexmpi(j) == myproc) THEN
k=k+1
tmps(k) = m(j)
END IF
END DO
!
! Sanity.
!
IF ( k .ne. kdata(myproc+1) ) THEN
WRITE(6,*) 'mpi_1dr_collect inconsistency: ',k,kdata(myproc+1)
CALL arpsstop
("mpi_1dr_collect",1)
END IF
DO k=1,nmap
CALL inctag
itag = gentag
!
! Are we a sender?
!
IF (mpi_map(k,1) .NE. -1 ) THEN
CALL mpsendr
(tmps,isum,mpi_map(k,1),itag,ierror)
ENDIF
!
! Are we a receiver?
!
IF (mpi_map(k,2) .NE. -1) THEN
CALL mprecvr
(tmpr,isum,mpi_map(k,2),itag,ierror)
ELSE
CYCLE
END IF
l = 0
DO ksta=1,nobmpi
!
! Make sure we are the right processor.
!
IF (indexmpi(ksta) .NE. mpi_map(k,2)) CYCLE
l = l + 1
m(ksta) = tmpr(l)
END DO
END DO
RETURN
END SUBROUTINE mpi_1dr_collect
SUBROUTINE mpi_2dr_collect(q, nvar, mxmpi, nobmpi, indexmpi, & 9,4
np, kdata, kdatamax, mpi_map, nmap, tmps, tmpr )
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Collect all the processor dependent calculations and merge them into a
! single array which we will broadcast.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Kevin W. Thomas, CAPS
! January 10, 2006
!
! MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
! Force explicit declarations
!
!-----------------------------------------------------------------------
IMPLICIT NONE
!-----------------------------------------------------------------------
!
! Subroutine arguments
!
!-----------------------------------------------------------------------
INTEGER, INTENT(IN) :: nvar ! Number of variables
INTEGER, INTENT(IN) :: mxmpi ! Max possible stations
INTEGER, INTENT(IN) :: nobmpi ! Actual number of stations
INTEGER, INTENT(IN) :: indexmpi(nobmpi) ! Array saying which ob is on which
! processor.
REAL, INTENT(INOUT) :: q(nvar,mxmpi) ! Data to be collected and updated.
INTEGER, INTENT(IN) :: np ! Just "nprocs"
INTEGER, INTENT(IN) :: kdata(np) ! Number of obs owned by each processor
INTEGER, INTENT(IN) :: kdatamax ! Largest "kdata" value
INTEGER, INTENT(IN) :: nmap ! Number of entries in "mpi_map"
INTEGER, INTENT(IN) :: mpi_map(nmap,2)! Mapping scheme
REAL, INTENT(INOUT) :: tmps(nvar,kdatamax)
REAL, INTENT(INOUT) :: tmpr(nvar,kdatamax)
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
INCLUDE 'mp.inc'
!-----------------------------------------------------------------------
!
! Misc. local variables
!
!-----------------------------------------------------------------------
INTEGER :: istat
INTEGER :: isum
INTEGER :: itag
INTEGER :: ierror
INTEGER :: i, j, k, l, ksta
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
isum = nvar * kdatamax
!
! Save our data.
!
k = 0
DO j=1,nobmpi
IF (indexmpi(j) == myproc) THEN
k=k+1
DO i=1,nvar
tmps(i,k) = q(i,j)
END DO
END IF
END DO
!
! Sanity.
!
IF ( k .ne. kdata(myproc+1) ) THEN
WRITE(6,*) 'mpi_2dr_collect inconsistency: ',k,kdata(myproc+1)
CALL arpsstop
("mpi_2dr_collect",1)
END IF
DO k=1,nmap
CALL inctag
itag = gentag
!
! Are we a sender?
!
IF (mpi_map(k,1) .NE. -1 ) THEN
CALL mpsendr
(tmps,isum,mpi_map(k,1),itag,ierror)
ENDIF
!
! Are we a receiver?
!
IF (mpi_map(k,2) .NE. -1) THEN
CALL mprecvr
(tmpr,isum,mpi_map(k,2),itag,ierror)
ELSE
CYCLE
END IF
l = 0
DO ksta=1,nobmpi
!
! Make sure we are the right processor.
!
IF (indexmpi(ksta) .NE. mpi_map(k,2)) CYCLE
l = l + 1
DO i=1,nvar
q(i,ksta) = tmpr(i,l)
END DO
END DO
END DO
RETURN
END SUBROUTINE mpi_2dr_collect
SUBROUTINE mpi_2dcr_collect(q, mxmpi, nvar, nobmpi, indexmpi ) 2,4
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Collect all the processor dependent calculations and merge them into a
! single array which we will broadcast.
!
! Same as "mpi_2dr_collect" except the subscripts are reversed. Most of
! the arrays have the station index as the last subscript. For "cloud
! soundings, the station index is the first subscript.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Kevin W. Thomas, CAPS
! September 15, 2006
!
! MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
! Force explicit declarations
!
!-----------------------------------------------------------------------
IMPLICIT NONE
!-----------------------------------------------------------------------
!
! Subroutine arguments
!
!-----------------------------------------------------------------------
INTEGER, INTENT(IN) :: nvar ! Number of variables
INTEGER, INTENT(IN) :: mxmpi ! Max possible stations
INTEGER, INTENT(IN) :: nobmpi ! Actual number of stations
INTEGER, INTENT(IN) :: indexmpi(nobmpi) ! Array saying which ob is on which
! processor.
REAL, INTENT(INOUT) :: q(mxmpi,nvar) ! Data to be collected and updated.
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
INCLUDE 'mp.inc'
!-----------------------------------------------------------------------
!
! Misc. local variables
!
!-----------------------------------------------------------------------
REAL, ALLOCATABLE :: tmp(:,:)
INTEGER :: istat
INTEGER :: isum
INTEGER :: ierror
INTEGER :: i, k, ksta
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
ALLOCATE(tmp(mxmpi,nvar),STAT=istat)
CALL check_alloc_status
(istat, "mpi_2dcr_collect:tmp")
isum = nvar * mxmpi
!
! Collect and merge the data.
!
IF (myproc > 0 ) THEN
CALL mpsendr
(q,isum,0,4000+myproc,ierror)
ELSE
DO k=1,nprocs-1
CALL mprecvr
(tmp,isum,k,4000+k,ierror)
!
! We only have to process "nobmpi" of the obs, even the array has space for
! "mxmpi" obs.
!
DO ksta=1,nobmpi
!
! Make sure we are the right processor.
!
IF (indexmpi(ksta) .NE. k) CYCLE
DO i=1,nvar
q(ksta,i) = tmp(ksta,i)
END DO
END DO
END DO
END IF
CALL mpupdater
(q,isum)
DEALLOCATE(tmp)
RETURN
END SUBROUTINE mpi_2dcr_collect
SUBROUTINE mpi_3dr_collect(q, nvar, nzmpi, mxmpi, nobmpi, indexmpi, & 9,4
np, kdata, kdatamax, mpi_map, nmap, tmps, tmpr)
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Collect all the processor dependent calculations and merge them into a
! single array which we will broadcast.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Kevin W. Thomas, CAPS
! January 10, 2006
!
! MODIFICATION HISTORY:
!
!-----------------------------------------------------------------------
!
! Force explicit declarations
!
!-----------------------------------------------------------------------
IMPLICIT NONE
!-----------------------------------------------------------------------
!
! Subroutine arguments
!
!-----------------------------------------------------------------------
INTEGER, INTENT(IN) :: nvar ! Number of variables
INTEGER, INTENT(IN) :: nzmpi ! Number of vertical levels
INTEGER, INTENT(IN) :: mxmpi ! Max possible stations
INTEGER, INTENT(IN) :: nobmpi ! Actual number of stations
INTEGER, INTENT(IN) :: indexmpi(nobmpi) ! Array saying which ob is on which
! processor.
REAL, INTENT(INOUT) :: q(nvar,nzmpi,mxmpi)! Data to be collected and updated.
INTEGER, INTENT(IN) :: np ! Just "nprocs"
INTEGER, INTENT(IN) :: kdata(np) ! Number of obs owned by each processor
INTEGER, INTENT(IN) :: kdatamax ! Largest "kdata" value
INTEGER, INTENT(IN) :: nmap ! Number of entries in "mpi_map"
INTEGER, INTENT(IN) :: mpi_map(nmap,2)! Mapping scheme
REAL, INTENT(INOUT) :: tmps(nvar,nzmpi,kdatamax)
REAL, INTENT(INOUT) :: tmpr(nvar,nzmpi,kdatamax)
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
INCLUDE 'mp.inc'
!-----------------------------------------------------------------------
!
! Misc. local variables
!
!-----------------------------------------------------------------------
INTEGER :: istat
INTEGER :: isum
INTEGER :: itag
INTEGER :: ierror
INTEGER :: i, j, k, l, m, ksta
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
isum = nvar * nzmpi *kdatamax
!
! Save our data.
!
m = 0
DO k=1,nobmpi
IF (indexmpi(k) == myproc) THEN
m=m+1
DO j=1,nzmpi
DO i=1,nvar
tmps(i,j,m) = q(i,j,k)
END DO
END DO
END IF
END DO
!
! Sanity.
!
IF ( m .ne. kdata(myproc+1) ) THEN
WRITE(6,*) 'mpi_3dr_collect inconsistency: ',m,kdata(myproc+1)
CALL arpsstop
("mpi_3dr_collect",1)
END IF
DO l=1,nmap
CALL inctag
itag = gentag
!
! Are we a sender?
!
IF (mpi_map(l,1) .NE. -1 ) THEN
CALL mpsendr
(tmps,isum,mpi_map(l,1),itag,ierror)
ENDIF
!
! Are we a receiver?
!
IF (mpi_map(l,2) .NE. -1) THEN
CALL mprecvr
(tmpr,isum,mpi_map(l,2),itag,ierror)
ELSE
CYCLE
END IF
m = 0
DO ksta=1,nobmpi
!
! Make sure we are the right processor.
!
IF (indexmpi(ksta) .NE. mpi_map(l,2)) CYCLE
m = m + 1
DO j=1,nzmpi
DO i=1,nvar
q(i,j,ksta) = tmpr(i,j,m)
END DO
END DO
END DO
END DO
RETURN
END SUBROUTINE mpi_3dr_collect