C $Header: /home/ubuntu/mnt/e9_copy/MITgcm/eesupp/src/Attic/exch_rx.template,v 1.2 2001/05/29 14:01:36 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