--- MITgcm/eesupp/src/exch_rx.template 2001/03/28 19:48:51 1.1 +++ MITgcm/eesupp/src/exch_rx.template 2001/03/28 19:48:51 1.1.2.1 @@ -0,0 +1,201 @@ +C $Header: /home/ubuntu/mnt/e9_copy/MITgcm/eesupp/src/Attic/exch_rx.template,v 1.1.2.1 2001/03/28 19:48:51 adcroft Exp $ +C $Name: $ + +#include "CPP_EEOPTIONS.h" + + SUBROUTINE EXCH_RX( + U array, + I myOLw, myOLe, myOLs, myOLn, myNz, + I exchWidthX, exchWidthY, + I simulationMode, cornerMode, myThid ) +C /==========================================================\ +C | SUBROUTINE EXCH_RX | +C | o Control edge exchanges for RX array. | +C |==========================================================| +C | | +C | Controlling routine for exchange of XY edges of an array | +C | distributed in X and Y. The routine interfaces to | +C | communication routines that can use messages passing | +C | exchanges, put type exchanges or get type exchanges. | +C | This allows anything from MPI to raw memory channel to | +C | memmap segments to be used as a inter-process and/or | +C | inter-thread communiation and synchronisation | +C | mechanism. | +C | Notes -- | +C | 1. Some low-level mechanisms such as raw memory-channel | +C | or SGI/CRAY shmem put do not have direct Fortran bindings| +C | and are invoked through C stub routines. | +C | 2. Although this routine is fairly general but it does | +C | require nSx and nSy are the same for all innvocations. | +C | There are many common data structures ( myByLo, | +C | westCommunicationMode, mpiIdW etc... ) tied in with | +C | (nSx,nSy). To support arbitray nSx and nSy would require | +C | general forms of these. | +C | | +C \==========================================================/ + IMPLICIT NONE + +C == Global data == +#include "SIZE.h" +#include "EEPARAMS.h" +#include "EESUPPORT.h" +#include "EXCH.h" + +C == Routine arguments == +C array - Array with edges to exchange. +C myOLw - West, East, North and South overlap region sizes. +C myOLe +C myOLn +C myOLs +C exchWidthX - Width of data region exchanged in X. +C exchWidthY - Width of data region exchanged in Y. +C Note -- +C 1. In theory one could have a send width and +C a receive width for each face of each tile. The only +C restriction woul be that the send width of one +C face should equal the receive width of the sent to +C tile face. Dont know if this would be useful. I +C have left it out for now as it requires additional +C bookeeping. +C simulationMode - Forward or reverse mode exchange ( provides +C support for adjoint integration of code. ) +C cornerMode - Flag indicating whether corner updates are +C needed. +C myThid - Thread number of this instance of S/R EXCH... + INTEGER myOLw + INTEGER myOLe + INTEGER myOLs + INTEGER myOLn + INTEGER myNz + INTEGER exchWidthX + INTEGER exchWidthY + INTEGER simulationMode + INTEGER cornerMode + INTEGER myThid + _RX array(1-myOLw:sNx+myOLe, + & 1-myOLs:sNy+myOLn, + & myNZ, nSx, nSy) + +C == Local variables == +C theSimulationMode - Holds working copy of simulation mode +C theCornerMode - Holds working copy of corner mode + INTEGER theSimulationMode + INTEGER theCornerMode + INTEGER I,J,K,bi,bj + + theSimulationMode = simulationMode + theCornerMode = cornerMode + +C-- Error checks + IF ( exchWidthX .GT. myOLw ) + & STOP ' S/R EXCH_RX: exchWidthX .GT. myOLw' + IF ( exchWidthX .GT. myOLe ) + & STOP ' S/R EXCH_RX: exchWidthX .GT. myOLe' + IF ( exchWidthY .GT. myOLs ) + & STOP ' S/R EXCH_RX: exchWidthY .GT. myOLs' + IF ( exchWidthY .GT. myOLn ) + & STOP ' S/R EXCH_RX: exchWidthY .GT. myOLn' + IF ( myOLw .GT. MAX_OLX_EXCH ) + & STOP ' S/R EXCH_RX: myOLw .GT. MAX_OLX_EXCH' + IF ( myOLe .GT. MAX_OLX_EXCH ) + & STOP ' S/R EXCH_RX: myOLe .GT. MAX_OLX_EXCH' + IF ( myOLn .GT. MAX_OLX_EXCH ) + & STOP ' S/R EXCH_RX: myOLn .GT. MAX_OLY_EXCH' + IF ( myOLs .GT. MAX_OLY_EXCH ) + & STOP ' S/R EXCH_RX: myOLs .GT. MAX_OLY_EXCH' + IF ( myNZ .GT. MAX_NR_EXCH ) + & STOP ' S/R EXCH_RX: myNZ .GT. MAX_NR_EXCH ' + IF ( theSimulationMode .NE. FORWARD_SIMULATION + & .AND. theSimulationMode .NE. REVERSE_SIMULATION + & ) STOP ' S/R EXCH_RX: Unrecognised simulationMode ' + IF ( theCornerMode .NE. EXCH_IGNORE_CORNERS + & .AND. theCornerMode .NE. EXCH_UPDATE_CORNERS + & ) STOP ' S/R EXCH_RX: Unrecognised cornerMode ' + +C-- Cycle edge buffer level + CALL EXCH_CYCLE_EBL( myThid ) + + IF ( theSimulationMode .EQ. FORWARD_SIMULATION ) THEN +C-- "Put" east and west edges. + CALL EXCH_RX_SEND_PUT_X( array, + I myOLw, myOLe, myOLs, myOLn, myNz, + I exchWidthX, exchWidthY, + I theSimulationMode, theCornerMode, myThid ) +C-- If corners are important then sync and update east and west edges +C-- before doing north and south exchanges. + IF ( theCornerMode .EQ. EXCH_UPDATE_CORNERS ) THEN + CALL EXCH_RX_RECV_GET_X( array, + I myOLw, myOLe, myOLs, myOLn, myNz, + I exchWidthX, exchWidthY, + I theSimulationMode, theCornerMode, myThid ) + ENDIF +C "Put" north and south edges. + CALL EXCH_RX_SEND_PUT_Y( array, + I myOLw, myOLe, myOLs, myOLn, myNz, + I exchWidthX, exchWidthY, + I theSimulationMode, theCornerMode, myThid ) +C-- Sync and update north, south (and east, west if corner updating +C-- not active). + IF ( theCornerMode .NE. EXCH_UPDATE_CORNERS ) THEN + CALL EXCH_RX_RECV_GET_X( array, + I myOLw, myOLe, myOLs, myOLn, myNz, + I exchWidthX, exchWidthY, + I theSimulationMode, theCornerMode, myThid ) + ENDIF + CALL EXCH_RX_RECV_GET_Y( array, + I myOLw, myOLe, myOLs, myOLn, myNz, + I exchWidthX, exchWidthY, + I theSimulationMode, theCornerMode, myThid ) + ENDIF + + IF ( theSimulationMode .EQ. REVERSE_SIMULATION ) THEN +C "Put" north and south edges. + CALL EXCH_RX_SEND_PUT_Y( array, + I myOLw, myOLe, myOLs, myOLn, myNz, + I exchWidthX, exchWidthY, + I theSimulationMode, theCornerMode, myThid ) +C-- If corners are important then sync and update east and west edges +C-- before doing north and south exchanges. + IF ( theCornerMode .EQ. EXCH_UPDATE_CORNERS ) THEN + CALL EXCH_RX_RECV_GET_Y( array, + I myOLw, myOLe, myOLs, myOLn, myNz, + I exchWidthX, exchWidthY, + I theSimulationMode, theCornerMode, myThid ) + ENDIF +C-- "Put" east and west edges. + CALL EXCH_RX_SEND_PUT_X( array, + I myOLw, myOLe, myOLs, myOLn, myNz, + I exchWidthX, exchWidthY, + I theSimulationMode, theCornerMode, myThid ) +C-- Sync and update east, west (and north, south if corner updating +C-- not active). + IF ( theCornerMode .NE. EXCH_UPDATE_CORNERS ) THEN + CALL EXCH_RX_RECV_GET_Y( array, + I myOLw, myOLe, myOLs, myOLn, myNz, + I exchWidthX, exchWidthY, + I theSimulationMode, theCornerMode, myThid ) + ENDIF + CALL EXCH_RX_RECV_GET_X( array, + I myOLw, myOLe, myOLs, myOLn, myNz, + I exchWidthX, exchWidthY, + I theSimulationMode, theCornerMode, myThid ) + ENDIF +C Special case for zonal average model i.e. case where sNx == 1 +C In this case a forward mode exchange simply sets array to +C the i=1 value for all i. + IF ( sNx .EQ. 1 ) THEN + DO bj=myByLo(myThid),myByHi(myThid) + DO bi=myBxLo(myThid),myBxHi(myThid) + DO K = 1,myNz + DO J = 1-myOLs,sNy+myOLn + DO I = 1-myOLw,sNx+myOLe + array(I,J,K,bi,bj) = array(sNx,J,K,bi,bj) + ENDDO + ENDDO + ENDDO + ENDDO + ENDDO + ENDIF + + RETURN + END