C $Header: /u/gcmpack/MITgcm/pkg/exch2/w2_map_procs.F,v 1.2 2013/11/27 00:34:05 jmc Exp $
C $Name: $
#include "CPP_EEOPTIONS.h"
CBOP
C !ROUTINE: W2_MAP_PROCS
C !INTERFACE:
SUBROUTINE W2_MAP_PROCS( myThid )
C !DESCRIPTION:
C *==========================================================*
C | SUBROUTINE W2_MAP_PROCS
C | o Setup Mapping of W2-topology tiles to processes
C *==========================================================*
C | Set which process "own" which tiles
C | and store the 2-way relation between, on one side,
C | tile Id from W2-topology and, on the other side,
C | process Id with local tile indices bi,bj.
C *==========================================================*
C !USES:
IMPLICIT NONE
#include "SIZE.h"
#include "EEPARAMS.h"
#include "W2_EXCH2_SIZE.h"
#include "W2_EXCH2_TOPOLOGY.h"
#include "W2_EXCH2_PARAMS.h"
C !INPUT PARAMETERS:
C myThid :: my Thread Id number
C (Note: not relevant since threading has not yet started)
INTEGER myThid
CEOP
C !FUNCTIONS:
C !LOCAL VARIABLES:
INTEGER thisProc
CHARACTER*(MAX_LEN_MBUF) msgBuf
CHARACTER commFlag
INTEGER myTileId
INTEGER I, J
INTEGER np, ii, jj, bi, bj
INTEGER iErr, tNx, tNy
C-- Initialise common blocs W2_MAP_TILE2PROC & W2_EXCH2_COMMFLAG:
DO I = 1,W2_maxNbTiles
W2_tileProc(I) = 0
W2_tileIndex(I) = 0
c W2_tileRank(I) = 0
ENDDO
DO bj=1,nSy
DO bi=1,nSx
W2_myTileList(bi,bj) = 0
DO np=1,nPx*nPy
W2_procTileList(bi,bj,np) = 0
ENDDO
DO J=1,W2_maxNeighbours
W2_myCommFlag(J,bi,bj) = ' '
ENDDO
ENDDO
ENDDO
C-- Decide which tiles this process handles - do this inline for now, but
C should go in subroutine.
C Set which rank processes "own" which tiles. This should probably
C be queried as part of some hand-shaking but for now we use the
C functional relationship that was used above.
C Fill also W2_procTileList for Single-CPU-IO.
C Number of tiles I handle is nSx*nSy
thisProc = 1 + myProcId
J = 0
DO I=1,exch2_nTiles
IF ( exch2_myFace(I) .NE. 0 ) THEN
C-- old ordering (makes no difference if nSy*nPy=1 )
c np = 1 + J/(nSx*nSy)
c jj = MOD(J,nSx*nSy)
c bj = 1 + jj/nSx
c bi = 1 + MOD(jj,nSx)
C-- new ordering: for single sub-domain (nFacets=1) case, match default setting
jj = J/(nSx*nPx)
ii = MOD(J,nSx*nPx)
C-- natural way to order processors:
c np = 1 + ii/nSx + (jj/nSy)*nPx
C-- switch processor order to match MPI_CART set-up
np = 1 + jj/nSy + (ii/nSx)*nPy
bj = 1 + MOD(jj,nSy)
bi = 1 + MOD(ii,nSx)
C--
W2_tileProc(I) = np
W2_tileIndex(I)= bi + (bj-1)*nSx
W2_procTileList(bi,bj,np) = I
IF ( np.EQ.thisProc ) W2_myTileList(bi,bj) = I
J = J + 1
c W2_tileRank(I) = J
ENDIF
ENDDO
IF ( J .NE. nSx*nSy*nPx*nPy ) THEN
STOP
& 'ERROR W2_MAP_PROCS: number of active tiles not =nPx*nSx*nPy*nSy'
ENDIF
C-- Check tile sizes
iErr = 0
DO bj=1,nSy
DO bi=1,nSx
myTileId = W2_myTileList(bi,bj)
tNx = exch2_tNx(myTileId)
tNy = exch2_tNy(myTileId)
IF ( tNx .NE. sNx ) THEN
WRITE(msgBuf,'(3(A,I5))')
& 'ERROR: S/R W2_MAP_PROCS Topology for tile', myTileId,
& 'tNx=', tNx, ' is not equal to subgrid size sNx=', sNx
CALL PRINT_MESSAGE(msgBuf,
& errorMessageUnit, SQUEEZE_RIGHT, 1 )
iErr = iErr+1
ENDIF
IF ( tNy .NE. sNy ) THEN
WRITE(msgBuf,'(3(A,I5))')
& 'ERROR: S/R W2_MAP_PROCS Topology for tile', myTileId,
& 'tNy=', tNy, ' is not equal to subgrid size sNy=', sNy
CALL PRINT_MESSAGE(msgBuf,
& errorMessageUnit, SQUEEZE_RIGHT, 1 )
iErr = iErr+1
ENDIF
ENDDO
ENDDO
IF ( iErr .NE. 0 ) THEN
STOP 'ABNORMAL END: W2_MAP_PROCS'
ENDIF
C-- Print tiles connection for this process and set myCommonFlag :
WRITE(msgBuf,'(A)') '===== W2 TILE TOPOLOGY ====='
CALL PRINT_MESSAGE( msgBuf, W2_oUnit, SQUEEZE_BOTH, myThid )
DO bj=1,nSy
DO bi=1,nSx
myTileId = W2_myTileList(bi,bj)
WRITE(msgBuf,'(A,I5,A,2I4,2A,I3)')
& ' TILE: ', myTileId,' (bi,bj=', bi, bj, ' )',
& ', Nb of Neighbours =', exch2_nNeighbours(myTileId)
c WRITE(msgBuf,'(2(A,I5),A,I3)') ' TILE: ', myTileId,
c & ' , rank=', W2_tileRank(myTileId),
c & ' , Nb of Neighbours =', exch2_nNeighbours(myTileId)
CALL PRINT_MESSAGE( msgBuf, W2_oUnit, SQUEEZE_RIGHT, myThid )
DO J=1,exch2_nNeighbours(myTileId)
commFlag = 'M'
jj = exch2_neighbourId(J,myTileId)
IF ( W2_tileProc(jj).EQ.thisProc ) commFlag = 'P'
IF ( commFlag .EQ. 'M' ) THEN
WRITE(msgBuf,'(A,I3,A,I5,A,I3,2A,I5,A)')
& ' NEIGHBOUR',J,' = TILE', exch2_neighbourId(J,myTileId),
& ' (n=', exch2_opposingSend(J,myTileId), ') Comm = MSG',
& ' (PROC=',W2_tileProc(exch2_neighbourId(J,myTileId)),')'
CALL PRINT_MESSAGE( msgBuf, W2_oUnit, SQUEEZE_RIGHT, myThid )
ENDIF
IF ( commFlag .EQ. 'P' ) THEN
WRITE(msgBuf,'(A,I3,A,I5,A,I3,2A,I5,A)')
& ' NEIGHBOUR',J,' = TILE', exch2_neighbourId(J,myTileId),
& ' (n=', exch2_opposingSend(J,myTileId), ') Comm = PUT',
& ' (PROC=',W2_tileProc(exch2_neighbourId(J,myTileId)),')'
CALL PRINT_MESSAGE( msgBuf, W2_oUnit, SQUEEZE_RIGHT, myThid )
ENDIF
W2_myCommFlag(J,bi,bj) = commFlag
ENDDO
ENDDO
ENDDO
RETURN
END