*IF DEF,C96_1A,OR,DEF,C96_1B                                               GPB0F403.3250   
*IF DEF,MPP                                                                STGFLD1A.2      
C *****************************COPYRIGHT******************************     STGFLD1A.3      
C (c) CROWN COPYRIGHT 1996, METEOROLOGICAL OFFICE, All Rights Reserved.    STGFLD1A.4      
C                                                                          STGFLD1A.5      
C Use, duplication or disclosure of this code is subject to the            STGFLD1A.6      
C restrictions as set forth in the contract.                               STGFLD1A.7      
C                                                                          STGFLD1A.8      
C                Meteorological Office                                     STGFLD1A.9      
C                London Road                                               STGFLD1A.10     
C                BRACKNELL                                                 STGFLD1A.11     
C                Berkshire UK                                              STGFLD1A.12     
C                RG12 2SZ                                                  STGFLD1A.13     
C                                                                          STGFLD1A.14     
C If no contract has been raised with this copy of the code, the use,      STGFLD1A.15     
C duplication or disclosure of it is strictly prohibited.  Permission      STGFLD1A.16     
C to do so must first be obtained in writing from the Head of Numerical    STGFLD1A.17     
C Modelling at the above address.                                          STGFLD1A.18     
C ******************************COPYRIGHT******************************    STGFLD1A.19     
!                                                                          STGFLD1A.20     
!+ Gathers STASHed data from many processors to one processor              GPB0F403.3251   
!                                                                          STGFLD1A.22     
! Subroutine interface:                                                    STGFLD1A.23     

      SUBROUTINE STASH_GATHER_FIELD (                                       7,6STGFLD1A.24     
     &  LOCAL_FIELD , GLOBAL_FIELD ,                                       STGFLD1A.25     
     &  LOCAL_SIZE, GLOBAL_SIZE, LEVELS,                                   STGFLD1A.26     
     &  GLOBAL_NORTH , GLOBAL_EAST_IN , GLOBAL_SOUTH , GLOBAL_WEST,        GPB0F403.3252   
     &  GRIDTYPE_CODE ,                                                    GPB0F403.3253   
     &  GATHER_PE,                                                         STGFLD1A.29     
     &  DATA_EXTRACTED ,                                                   GPB0F403.3254   
     &  ICODE, CMESSAGE)                                                   STGFLD1A.31     
                                                                           STGFLD1A.32     
      IMPLICIT NONE                                                        STGFLD1A.33     
                                                                           STGFLD1A.34     
! Description:                                                             STGFLD1A.35     
! Takes a decomposed, STASH processed field and gathers                    STGFLD1A.36     
! it to a single processor, ready for I/O,                                 STGFLD1A.37     
!                                                                          STGFLD1A.38     
! Method:                                                                  STGFLD1A.39     
! See in-line documentation                                                STGFLD1A.40     
!                                                                          STGFLD1A.41     
! Current code owner : P.Burton                                            STGFLD1A.42     
!                                                                          STGFLD1A.43     
! History:                                                                 STGFLD1A.44     
!  Model    Date      Modification history from model version 4.2          STGFLD1A.45     
!  version                                                                 STGFLD1A.46     
!   4.2     17/09/96  New DECK created for MPP version of STASH            STGFLD1A.47     
!                     P.Burton                                             STGFLD1A.48     
!   4.3     13/03/97  Recoded version                    P.Burton          GPB0F403.3255   
!   4.3     13/06/97  More robust handling of zonal fields   P.Burton      GPB0F404.310    
!                     Fix for global_start_row               P.Burton      GPB0F404.311    
!                                                                          STGFLD1A.49     
! Subroutine arguments:                                                    STGFLD1A.50     
                                                                           STGFLD1A.51     
      INTEGER                                                              STGFLD1A.52     
     &  LOCAL_SIZE      ! IN: size of level of LOCAL_FIELD                 STGFLD1A.53     
     &, GLOBAL_SIZE     ! IN: size of level of GLOBAL_FIELD                STGFLD1A.54     
     &, LEVELS          ! IN: number of levels                             STGFLD1A.55     
     &, GLOBAL_NORTH    ! IN: specification of subdomain boundaries        STGFLD1A.56     
     &, GLOBAL_EAST_IN  ! IN: ""                                           GPB0F403.3256   
     &, GLOBAL_SOUTH    ! IN: ""                                           STGFLD1A.58     
     &, GLOBAL_WEST     ! IN: ""                                           STGFLD1A.59     
     &, GRIDTYPE_CODE   ! IN: indicates the type of grid output            STGFLD1A.60     
     &, GATHER_PE       ! IN: the PE to gather the global field to         STGFLD1A.63     
     &, ICODE           ! OUT: return code, 0=OK                           STGFLD1A.64     
                                                                           STGFLD1A.65     
      LOGICAL                                                              STGFLD1A.66     
     &  DATA_EXTRACTED  ! IN: TRUE if the data in LOCAL_FIELD has          GPB0F403.3257   
!                       !     already been extracted, or FASLE if          GPB0F403.3258   
!                       !     the extraction must be done here.            GPB0F403.3259   
                                                                           STGFLD1A.72     
      REAL                                                                 STGFLD1A.73     
     &  LOCAL_FIELD(LOCAL_SIZE,LEVELS)                                     STGFLD1A.74     
!        ! IN : local data                                                 STGFLD1A.75     
     &, GLOBAL_FIELD(GLOBAL_SIZE,LEVELS)                                   STGFLD1A.76     
!        ! OUT : (PE GATHER_PE only) - full gathered field                 STGFLD1A.77     
                                                                           STGFLD1A.78     
      CHARACTER*80                                                         STGFLD1A.79     
     &  CMESSAGE        ! OUT: Error message if ICODE .NE. 0               STGFLD1A.80     
                                                                           STGFLD1A.81     
! Parameters and common blocks                                             STGFLD1A.82     
*CALL STPARAM                                                              STGFLD1A.83     
*CALL CPPXREF                                                              GPB0F404.312    
*CALL PARVARS                                                              STGFLD1A.84     
*CALL GCCOM                                                                STGFLD1A.85     
*CALL AMAXSIZE                                                             GPB0F403.3260   
                                                                           STGFLD1A.86     
! Local variables                                                          STGFLD1A.87     
                                                                           STGFLD1A.88     
      INTEGER                                                              STGFLD1A.89     
     &  GLOBAL_EAST   ! copy of GLOBAL_EAST_IN with wrap around s.t.       GPB0F403.3261   
!                     ! GLOBAL_EAST > GLOBAL_ROW_LEN                       GPB0F403.3262   
     &, global_x      ! size of global data EW                             GPB0F404.313    
     &, global_y      ! size of global data NS                             GPB0F404.314    
     &, fld_type      ! indicates if field is on P or U grid               GPB0F403.3263   
     &, level         ! loop index for loop over levels                    GPB0F403.3264   
     &, proc_topleft_x,proc_topleft_y   ! processors at corners of         GPB0F403.3265   
     &, proc_botright_x,proc_botright_y ! the subarea                      GPB0F403.3266   
     &, dummy1,dummy2 ! ignored return arguments                           GPB0F403.3267   
     &, procx,procy   ! loop indexes for loops over processors             GPB0F403.3268   
     &, eff_procx     ! real x co-ord of processor column procx            GPB0F403.3269   
     &, procid        ! processor id of (procx,procy)                      GPB0F403.3270   
     &, local_xstart,local_xend  ! boundaries of subdomain for             GPB0F403.3271   
     &, local_ystart,local_yend  ! processor procid                        GPB0F403.3272   
     &, local_start_row   ! first row to send from procid                  GPB0F403.3273   
     &, local_start_col   ! first column to send from procid               GPB0F403.3274   
     &, sendsize_x        ! number of points on each row to send           GPB0F403.3275   
     &, nrows_to_send     ! number of rows to send from procid             GPB0F403.3276   
     &, local_row_length  ! size of sending array EW                       GPB0F403.3277   
     &, global_start_row  ! first row to receive at on GATHER_PE           GPB0F403.3278   
     &, global_start_col  ! first col. to recieve on GATHER_PE             GPB0F403.3279   
     &, global_row_length ! size of receiving array EW                     GPB0F403.3280   
     &, flag,info         ! GCOM arguments                                 GPB0F403.3281   
                                                                           GPB0F403.3282   
! Copies of arguments / variables used to decide if we can use the         GPB0F403.3283   
! send/receive maps used in the last call                                  GPB0F403.3284   
                                                                           GPB0F403.3285   
      INTEGER                                                              GPB0F403.3286   
     &  old_LOCAL_SIZE , old_GLOBAL_SIZE                                   GPB0F403.3287   
     &, old_GLOBAL_NORTH , old_GLOBAL_EAST_IN                              GPB0F403.3288   
     &, old_GLOBAL_SOUTH , old_GLOBAL_WEST                                 GPB0F403.3289   
     &, old_GRIDTYPE_CODE , old_GATHER_PE                                  GPB0F403.3290   
     &, old_current_decomp_type                                            GPB0F403.3291   
                                                                           STGFLD1A.128    
      INTEGER                                                              STGFLD1A.129    
! variables defining send and receive maps to be passed to                 STGFLD1A.130    
! GC_RALL_TO_ALL, defining the data transposition                          STGFLD1A.131    
     &  send_map(7,2)                                                      GPB0F403.3292   
     &, receive_map(7,2*MAXPROC)                                           GPB0F403.3293   
     &, n_sends,n_recvs  ! number of sends and receives                    GPB0F403.3294   
                                                                           GPB0F403.3295   
                                                                           STGFLD1A.138    
      LOGICAL                                                              STGFLD1A.139    
     &  wrap  ! if the subdomain wraps over 0 degree meridion              STGFLD1A.140    
     &, wrap_special ! if there is a wrap around, which starts and         GPB0F403.3296   
!                      ends on the same processor                          GPB0F403.3297   
     &, zonal_data   ! if this is a zonal data grid                        GPB0F404.315    
     &, fullfield    ! if this is a full field - NOT a subarea             GPB0F403.3298   
                                                                           STGFLD1A.143    
! Save all the variables that may be used in the next call                 GPB0F403.3299   
      SAVE                                                                 GPB0F403.3300   
     &  old_LOCAL_SIZE , old_GLOBAL_SIZE                                   GPB0F403.3301   
     &, old_GLOBAL_NORTH , old_GLOBAL_EAST_IN                              GPB0F403.3302   
     &, old_GLOBAL_SOUTH , old_GLOBAL_WEST                                 GPB0F403.3303   
     &, old_GRIDTYPE_CODE , old_GATHER_PE                                  GPB0F403.3304   
     &, old_current_decomp_type                                            GPB0F403.3305   
     &, send_map,receive_map,n_sends,n_recvs                               GPB0F403.3306   
                                                                           STGFLD1A.144    
! Set all the old_* variables to a number indicating they've               GPB0F403.3307   
! not been used yet                                                        GPB0F403.3308   
                                                                           GPB0F403.3309   
      DATA                                                                 GPB0F403.3310   
     &  old_LOCAL_SIZE , old_GLOBAL_SIZE                                   GPB0F403.3311   
     &, old_GLOBAL_NORTH , old_GLOBAL_EAST_IN                              GPB0F403.3312   
     &, old_GLOBAL_SOUTH , old_GLOBAL_WEST                                 GPB0F403.3313   
     &, old_GRIDTYPE_CODE , old_GATHER_PE                                  GPB0F403.3314   
     &, old_current_decomp_type                                            GPB0F403.3315   
     &  / -1,-1,-1,-1,-1,-1,-1,-1,-1 /                                     GPB0F403.3316   
                                                                           GPB0F403.3317   
! Functions                                                                GPB0F403.3318   
                                                                           GPB0F403.3319   
      INTEGER GET_FLD_TYPE                                                 GPB0F403.3320   
! ------------------------------------------------------------------       STGFLD1A.145    
                                                                           STGFLD1A.146    
      ICODE=0                                                              GPB0F403.3321   
                                                                           STGFLD1A.149    
! See if there is wrap around over meridion, and if so make                GPB0F403.3322   
! sure that GLOBAL_EAST is > glsize(1)                                     GPB0F403.3323   
                                                                           STGFLD1A.152    
      GLOBAL_EAST=GLOBAL_EAST_IN                                           GPB0F403.3324   
      IF (GLOBAL_EAST .GT. glsize(1)) THEN                                 GPB0F403.3325   
        wrap=.TRUE.                                                        GPB0F403.3326   
      ELSEIF (GLOBAL_EAST .LT. GLOBAL_WEST) THEN                           GPB0F403.3327   
        wrap=.TRUE.                                                        GPB0F403.3328   
        GLOBAL_EAST=GLOBAL_EAST_IN+glsize(1)                               GPB0F403.3329   
      ELSE                                                                 GPB0F403.3330   
        wrap=.FALSE.                                                       GPB0F403.3331   
      ENDIF                                                                GPB0F403.3332   
                                                                           STGFLD1A.158    
      IF ((GRIDTYPE_CODE .EQ. ppx_atm_tzonal) .OR. ! Atmos T zonal         GPB0F404.316    
     &   ( GRIDTYPE_CODE .EQ. ppx_atm_uzonal) .OR. ! Atmos U zonal         GPB0F404.317    
     &   ( GRIDTYPE_CODE .EQ. ppx_ocn_tzonal) .OR. ! Ocean T zonal         GPB0F404.318    
     &   ( GRIDTYPE_CODE .EQ. ppx_ocn_uzonal))     ! Atmos U zonal         GPB0F404.319    
     &  THEN                                                               GPB0F404.320    
                                                                           GPB0F404.321    
! This is a zonal field                                                    GPB0F404.322    
                                                                           GPB0F404.323    
        zonal_data=.TRUE.                                                  GPB0F404.324    
        global_x=1                                                         GPB0F404.325    
                                                                           GPB0F404.326    
        IF ((GRIDTYPE_CODE .EQ. ppx_atm_tzonal) .OR. ! Atmos T zonal       GPB0F404.327    
     &      ( GRIDTYPE_CODE .EQ. ppx_ocn_tzonal))    ! Ocean T zonal       GPB0F404.328    
     &  THEN                                                               GPB0F404.329    
          fld_type=fld_type_p                                              GPB0F404.330    
        ELSE                                                               GPB0F404.331    
          fld_type=fld_type_u                                              GPB0F404.332    
        ENDIF                                                              GPB0F404.333    
      ELSE                                                                 GPB0F404.334    
                                                                           GPB0F404.335    
! This is a normal field                                                   GPB0F404.336    
                                                                           GPB0F404.337    
        zonal_data=.FALSE.                                                 GPB0F404.338    
        global_x=glsize(1)                                                 GPB0F404.339    
                                                                           GPB0F404.340    
        fld_type=GET_FLD_TYPE(GRIDTYPE_CODE)                               GPB0F404.341    
                                                                           GPB0F404.342    
        IF (fld_type .EQ. fld_type_unknown) THEN                           GPB0F404.343    
          WRITE(6,*) 'STASH_GATHER_FIELD encountered ',                    GPB0F404.344    
     &      'field with gridtype code ',GRIDTYPE_CODE                      GPB0F404.345    
          WRITE(6,*) 'Unable to process this field.'                       GPB0F404.346    
          CMESSAGE='MPP : STASH_GATHER_FIELD could not process field'      GPB0F404.347    
          ICODE=1                                                          GPB0F404.348    
          GOTO 9999                                                        GPB0F404.349    
        ENDIF                                                              GPB0F404.350    
                                                                           GPB0F404.351    
      ENDIF                                                                GPB0F404.352    
                                                                           GPB0F404.353    
      IF (fld_type .EQ. fld_type_p) THEN                                   GPB0F404.354    
        global_y=glsize(2)                                                 GPB0F404.355    
      ELSE                                                                 GPB0F404.356    
        global_y=glsize(2)-1                                               GPB0F404.357    
      ENDIF                                                                GPB0F404.358    
                                                                           STGFLD1A.180    
! Set up logical indicating if this is a full field, or just               GPB0F403.3343   
! a subdomain                                                              GPB0F403.3344   
                                                                           STGFLD1A.187    
      IF (zonal_data) THEN                                                 GPB0F404.359    
                                                                           GPB0F404.360    
        fullfield= ( ( GLOBAL_NORTH .EQ. 1) .AND.                          GPB0F404.361    
     &             ( GLOBAL_SOUTH .EQ. global_y))                          GPB0F404.362    
                                                                           GPB0F404.363    
      ELSE                                                                 GPB0F404.364    
                                                                           GPB0F404.365    
        fullfield = (( GLOBAL_WEST .EQ. 1) .AND.                           GPB0F404.366    
     &               ( GLOBAL_EAST .EQ. global_x) .AND.                    GPB0F404.367    
     &               ( GLOBAL_NORTH .EQ. 1) .AND.                          GPB0F404.368    
     &               ( GLOBAL_SOUTH .EQ. global_y))                        GPB0F404.369    
                                                                           GPB0F404.370    
      ENDIF                                                                GPB0F404.371    
                                                                           GPB0F404.372    
! If this a fullfield, we can simply use the standard                      GPB0F404.373    
! GATHER_FIELD routine                                                     GPB0F404.374    
                                                                           GPB0F404.375    
      IF (fullfield) THEN                                                  GPB0F404.376    
                                                                           GPB0F404.377    
        IF (zonal_data) THEN                                               GPB0F404.378    
                                                                           GPB0F404.379    
          CALL GATHER_ZONAL_FIELD( LOCAL_FIELD,GLOBAL_FIELD,               GPB0F404.380    
     &                             lasize(2),global_y,                     GPB0F404.381    
     &                             LEVELS,GRIDTYPE_CODE,                   GPB0F404.382    
     &                             GATHER_PE)                              GPB0F404.383    
                                                                           GPB0F404.384    
        ELSE                                                               GPB0F404.385    
                                                                           GPB0F404.386    
          DO level=1,LEVELS                                                GPB0F404.387    
                                                                           GPB0F404.388    
            CALL GATHER_FIELD( LOCAL_FIELD(1,level) ,                      GPB0F404.389    
     &                         GLOBAL_FIELD(1,level),                      GPB0F404.390    
     &                         lasize(1),lasize(2),                        GPB0F404.391    
     &                         global_x,global_y,                          GPB0F404.392    
     &                         GATHER_PE,GC_ALL_PROC_GROUP,                GPB0F404.393    
     &                         info)                                       GPB0F404.394    
                                                                           GPB0F404.395    
           ENDDO                                                           GPB0F404.396    
                                                                           GPB0F404.397    
         ENDIF                                                             GPB0F404.398    
       ELSE                                                                GPB0F403.3373   
! for subdomains, life is not so easy - we must explicitly                 GPB0F403.3374   
! calculate our own send and receive maps, and use GCG_RALLTOALLE          GPB0F403.3375   
! to shift the data around.                                                GPB0F403.3376   
                                                                           GPB0F403.3377   
! If the same arguments are used as were used in the last call             GPB0F403.3378   
! to this routine, we can just use the previously calculated               GPB0F403.3379   
! send and receive maps, otherwise we need to calculate new maps           GPB0F403.3380   
                                                                           GPB0F403.3381   
        IF (.NOT. (                                                        GPB0F403.3382   
     &    (LOCAL_SIZE .EQ. old_LOCAL_SIZE) .AND.                           GPB0F403.3383   
     &    (GLOBAL_SIZE .EQ. old_GLOBAL_SIZE) .AND.                         GPB0F403.3384   
     &    (GLOBAL_NORTH .EQ. old_GLOBAL_NORTH) .AND.                       GPB0F403.3385   
     &    (GLOBAL_EAST_IN .EQ. old_GLOBAL_EAST_IN) .AND.                   GPB0F403.3386   
     &    (GLOBAL_SOUTH .EQ. old_GLOBAL_SOUTH) .AND.                       GPB0F403.3387   
     &    (GLOBAL_WEST .EQ. old_GLOBAL_WEST) .AND.                         GPB0F403.3388   
     &    (GRIDTYPE_CODE .EQ. old_GRIDTYPE_CODE) .AND.                     GPB0F403.3389   
     &    (GATHER_PE .EQ. old_GATHER_PE) .AND.                             GPB0F403.3390   
     &    (current_decomp_type .EQ. old_current_decomp_type ))) THEN       GPB0F403.3391   
                                                                           GPB0F403.3392   
          old_LOCAL_SIZE=LOCAL_SIZE                                        GPB0F403.3393   
          old_GLOBAL_SIZE=GLOBAL_SIZE                                      GPB0F403.3394   
          old_GLOBAL_NORTH=GLOBAL_NORTH                                    GPB0F403.3395   
          old_GLOBAL_EAST_IN=GLOBAL_EAST_IN                                GPB0F403.3396   
          old_GLOBAL_SOUTH=GLOBAL_SOUTH                                    GPB0F403.3397   
          old_GLOBAL_WEST=GLOBAL_WEST                                      GPB0F403.3398   
          old_GRIDTYPE_CODE=GRIDTYPE_CODE                                  GPB0F403.3399   
          old_GATHER_PE=GATHER_PE                                          GPB0F403.3400   
          old_current_decomp_type=current_decomp_type                      GPB0F403.3401   
                                                                           GPB0F403.3402   
! Find out what the boundaries of the subdomain area                       GPB0F403.3403   
                                                                           GPB0F403.3404   
          CALL GLOBAL_TO_LOCAL_RC(GRIDTYPE_CODE,                           GPB0F403.3405   
     &                            GLOBAL_WEST,GLOBAL_NORTH,                GPB0F403.3406   
     &                            proc_topleft_x,proc_topleft_y,           GPB0F403.3407   
     &                            dummy1,dummy2)                           GPB0F403.3408   
          CALL GLOBAL_TO_LOCAL_RC(GRIDTYPE_CODE,                           GPB0F403.3409   
     &                            GLOBAL_EAST,GLOBAL_SOUTH,                GPB0F403.3410   
     &                            proc_botright_x,proc_botright_y,         GPB0F403.3411   
     &                            dummy1,dummy2)                           GPB0F403.3412   
                                                                           STGFLD1A.220    
! Ensure that the processor x co-ords are such that the botright_x is      STGFLD1A.221    
! always greater than (or equal to) top_left_x.                            STGFLD1A.222    
          IF (wrap) proc_botright_x=gridsize(1)+proc_botright_x            STGFLD1A.223    
                                                                           STGFLD1A.224    
! wrap_special is set to true if there is a wrap around which starts       GPB0F403.3413   
! and ends on the same processor. This case requires extra work as         GPB0F403.3414   
! the processor in question                                                GPB0F403.3415   
          IF (wrap .AND. (proc_topleft_x+gridsize(1) .EQ.                  GPB0F403.3416   
     &                    proc_botright_x)) THEN                           GPB0F403.3417   
            wrap_special=.TRUE.                                            GPB0F403.3418   
          ELSE                                                             GPB0F403.3419   
            wrap_special=.FALSE.                                           GPB0F403.3420   
          ENDIF                                                            GPB0F403.3421   
                                                                           GPB0F403.3422   
          n_sends=0                                                        GPB0F403.3423   
          n_recvs=0                                                        GPB0F403.3424   
                                                                           STGFLD1A.226    
          DO procy=proc_topleft_y,proc_botright_y                          STGFLD1A.227    
            DO procx=proc_topleft_x,proc_botright_x                        STGFLD1A.228    
                                                                           STGFLD1A.229    
              eff_procx=MOD(procx,gridsize(1))                             STGFLD1A.230    
              procid=eff_procx+procy*gridsize(1)                           STGFLD1A.231    
                                                                           STGFLD1A.232    
              CALL GLOBAL_TO_LOCAL_SUBDOMAIN(                              GPB0F403.3425   
     &          .TRUE.,.TRUE.,                                             GPB0F403.3426   
     &          GRIDTYPE_CODE,procid,                                      GPB0F403.3427   
     &          GLOBAL_NORTH,GLOBAL_EAST,                                  GPB0F403.3428   
     &          GLOBAL_SOUTH,GLOBAL_WEST,                                  GPB0F403.3429   
     &          local_ystart,local_xend,                                   GPB0F403.3430   
     &          local_yend  ,local_xstart)                                 GPB0F403.3431   
                                                                           STGFLD1A.242    
! Calculate the shape of the arrays, and where to start sending/           GPB0F403.3432   
! receiving data, and how many rows to send                                GPB0F403.3433   
                                                                           GPB0F403.3434   
              IF (DATA_EXTRACTED) THEN                                     GPB0F403.3435   
                local_start_row=1                                          GPB0F403.3436   
              ELSE                                                         GPB0F403.3437   
                local_start_row=local_ystart                               GPB0F403.3438   
              ENDIF                                                        GPB0F403.3439   
              nrows_to_send=local_yend-local_ystart+1                      GPB0F403.3440   
                                                                           GPB0F403.3441   
              global_start_row=g_datastart(2,procid)+local_ystart-         GPB0F403.3442   
     &                         Offy-GLOBAL_NORTH                           GPB0F404.399    
              global_row_length=GLOBAL_EAST-GLOBAL_WEST+1                  GPB0F403.3444   
                                                                           GPB0F403.3445   
! Calculate the following variables:                                       GPB0F403.3446   
! local_row_length : the X dimension size of the local array               GPB0F403.3447   
! local_send_offx  : the offset into each row to start sending from        GPB0F403.3448   
! sendsize_x       : the number of points on each row to send              GPB0F403.3449   
! The calculation of these numbers is different for processors             GPB0F403.3450   
! at the start and end of a wrap_special case                              GPB0F403.3451   
                                                                           GPB0F403.3452   
              IF (wrap_special .AND. procx .EQ. proc_topleft_x) THEN       GPB0F403.3453   
                IF (DATA_EXTRACTED) THEN                                   GPB0F403.3454   
                  local_row_length=g_lasize(1,procid)+local_xend-          GPB0F403.3455   
     &                             local_xstart-2*Offx+1                   GPB0F403.3456   
                  local_start_col=1                                        GPB0F403.3457   
                ELSE                                                       GPB0F403.3458   
                  local_row_length=g_lasize(1,procid)                      GPB0F403.3459   
                  local_start_col=local_xstart                             GPB0F403.3460   
                                                                           GPB0F403.3461   
                ENDIF                                                      GPB0F403.3462   
                sendsize_x=g_lasize(1,procid)-local_xstart                 GPB0F403.3463   
                global_start_col=1                                         GPB0F403.3464   
                                                                           GPB0F403.3465   
              ELSEIF (wrap_special .AND. procx .EQ. proc_botright_x)       GPB0F403.3466   
     &        THEN                                                         STGFLD1A.245    
                IF (DATA_EXTRACTED) THEN                                   GPB0F403.3467   
                  local_row_length=g_lasize(1,procid)+local_xend-          GPB0F403.3468   
     &                             local_xstart-2*Offx+1                   GPB0F403.3469   
                  local_start_col=local_row_length-local_xend+Offx+1       GPB0F403.3470   
                ELSE                                                       GPB0F403.3471   
                  local_row_length=g_lasize(1,procid)                      GPB0F403.3472   
                  local_start_col=Offx+1                                   GPB0F403.3473   
                ENDIF                                                      GPB0F403.3474   
                sendsize_x=local_xend-Offx                                 GPB0F403.3475   
                global_start_col=global_row_length-sendsize_x+1            GPB0F403.3476   
                                                                           GPB0F403.3477   
              ELSE                                                         STGFLD1A.253    
                IF (DATA_EXTRACTED) THEN                                   GPB0F403.3478   
                  local_row_length=local_xend-local_xstart+1               GPB0F403.3479   
                  local_start_col=1                                        GPB0F403.3480   
                ELSE                                                       GPB0F403.3481   
                  local_row_length=g_lasize(1,procid)                      GPB0F403.3482   
                  local_start_col=local_xstart                             GPB0F403.3483   
                ENDIF                                                      GPB0F403.3484   
                sendsize_x=local_xend-local_xstart+1                       GPB0F403.3485   
                global_start_col=local_xstart-(Offx+1)+                    GPB0F403.3486   
     &                           g_datastart(1,procid)-GLOBAL_WEST+1       GPB0F403.3487   
              ENDIF                                                        STGFLD1A.255    
                                                                           STGFLD1A.256    
              IF (global_start_col .LT. 0) THEN                            GPB0F403.3488   
! Wrapped around field, but this processor is not start or end             GPB0F403.3489   
! processor                                                                GPB0F403.3490   
                global_start_col=global_start_col+glsize(1)                GPB0F403.3491   
              ENDIF                                                        GPB0F403.3492   
                                                                           STGFLD1A.267    
! Now we can set up the send and receive map entries for the data on       GPB0F403.3493   
! this processor                                                           GPB0F403.3494   
                                                                           STGFLD1A.269    
              IF (mype .EQ. procid) THEN  ! I need to send some data       GPB0F403.3495   
                                                                           STGFLD1A.294    
                                                                           STGFLD1A.295    
                n_sends=n_sends+1                                          GPB0F403.3496   
                                                                           STGFLD1A.308    
                send_map(S_DESTINATION_PE,n_sends) = GATHER_PE             GPB0F403.3497   
                send_map(S_BASE_ADDRESS_IN_SEND_ARRAY,n_sends) =           GPB0F403.3498   
     &            (local_start_row-1)*local_row_length +                   GPB0F403.3499   
     &            local_start_col                                          GPB0F403.3500   
                send_map(S_NUMBER_OF_ELEMENTS_IN_ITEM,n_sends) =           GPB0F403.3501   
     &            nrows_to_send                                            GPB0F403.3502   
                send_map(S_STRIDE_IN_SEND_ARRAY,n_sends) =                 GPB0F403.3503   
     &            local_row_length                                         GPB0F403.3504   
                send_map(S_ELEMENT_LENGTH,n_sends) = sendsize_x            GPB0F403.3505   
                send_map(S_BASE_ADDRESS_IN_RECV_ARRAY,n_sends) =           GPB0F403.3506   
     &            (global_start_row-1)*global_row_length +                 GPB0F403.3507   
     &            global_start_col                                         GPB0F403.3508   
                send_map(S_STRIDE_IN_RECV_ARRAY,n_sends) =                 GPB0F403.3509   
     &            global_row_length                                        GPB0F403.3510   
                                                                           STGFLD1A.311    
              ENDIF ! if I'm sending data                                  GPB0F403.3511   
                                                                           STGFLD1A.319    
              IF (mype .EQ. GATHER_PE) THEN  ! I need to receive data      GPB0F403.3512   
                                                                           STGFLD1A.322    
                n_recvs=n_recvs+1                                          GPB0F403.3513   
                                                                           STGFLD1A.325    
                receive_map(R_SOURCE_PE,n_recvs) = procid                  GPB0F403.3514   
                receive_map(R_BASE_ADDRESS_IN_RECV_ARRAY,n_recvs) =        GPB0F403.3515   
     &            (global_start_row-1)*global_row_length +                 GPB0F403.3516   
     &            global_start_col                                         GPB0F403.3517   
                receive_map(R_NUMBER_OF_ELEMENTS_IN_ITEM,n_recvs) =        GPB0F403.3518   
     &            nrows_to_send                                            GPB0F403.3519   
                receive_map(R_STRIDE_IN_RECV_ARRAY,n_recvs) =              GPB0F403.3520   
     &            global_row_length                                        GPB0F403.3521   
                receive_map(R_ELEMENT_LENGTH,n_recvs) = sendsize_x         GPB0F403.3522   
                receive_map(R_BASE_ADDRESS_IN_SEND_ARRAY,n_recvs) =        GPB0F403.3523   
     &            (local_start_row-1)*local_row_length +                   GPB0F403.3524   
     &            local_start_col                                          GPB0F403.3525   
                receive_map(R_STRIDE_IN_SEND_ARRAY,n_recvs) =              GPB0F403.3526   
     &            local_row_length                                         GPB0F403.3527   
                                                                           STGFLD1A.327    
              ENDIF ! if I'm receiving data                                GPB0F403.3528   
                                                                           STGFLD1A.335    
            ENDDO ! procx : loop along processor row                       GPB0F403.3529   
                                                                           STGFLD1A.338    
          ENDDO ! procy : loop down processor column                       GPB0F403.3530   
                                                                           STGFLD1A.341    
        ENDIF ! if I need to recalculate my send/receive maps              GPB0F403.3531   
                                                                           STGFLD1A.343    
! Send / receive the data using GCG_RALLTOALLE                             GPB0F403.3532   
                                                                           STGFLD1A.383    
                                                                           STGFLD1A.384    
        DO level=1,LEVELS                                                  GPB0F403.3533   
                                                                           STGFLD1A.386    
          flag=0  ! This is currently ignored at GCG v1.1                  GPB0F403.3534   
                                                                           STGFLD1A.388    
          CALL GC_SETOPT(GC_SHM_DIR,GC_SHM_PUT,info)  ! set as gather      GPB0F403.3535   
                                                                           STGFLD1A.390    
          info=GC_NONE                                                     GPB0F403.3536   
                                                                           STGFLD1A.406    
          CALL GCG_RALLTOALLE(                                             GPB0F403.3537   
     &      LOCAL_FIELD(1,level)  ,                                        GPB0F403.3538   
     &      send_map    , n_sends  ,LOCAL_SIZE  ,                          GPB0F403.3539   
     &      GLOBAL_FIELD(1,level) ,                                        GPB0F403.3540   
     &      receive_map , n_recvs , GLOBAL_SIZE ,                          GPB0F403.3541   
     &      GC_ALL_PROC_GROUP , flag, info)                                GPB0F403.3542   
                                                                           STGFLD1A.408    
        ENDDO                                                              GPB0F403.3543   
                                                                           STGFLD1A.410    
        ENDIF ! if this is a full or extracted field                       GPB0F403.3544   
                                                                           STGFLD1A.470    
 9999 CONTINUE                                                             STGFLD1A.471    
                                                                           STGFLD1A.472    
      RETURN                                                               STGFLD1A.473    
      END                                                                  STGFLD1A.474    
                                                                           STGFLD1A.475    
*ENDIF                                                                     GPB0F403.3545   
*ENDIF                                                                     STGFLD1A.476