| 1 | #include "cppdefs.h"
 | 
|---|
| 2 |       MODULE nf_fread4d_mod
 | 
|---|
| 3 | !
 | 
|---|
| 4 | !svn $Id$
 | 
|---|
| 5 | !================================================== Hernan G. Arango ===
 | 
|---|
| 6 | !  Copyright (c) 2002-2018 The ROMS/TOMS Group                         !
 | 
|---|
| 7 | !    Licensed under a MIT/X style license                              !
 | 
|---|
| 8 | !    See License_ROMS.txt                                              !
 | 
|---|
| 9 | !=======================================================================
 | 
|---|
| 10 | !                                                                      !
 | 
|---|
| 11 | !  This function reads in a generic floating point 4D array from an    !
 | 
|---|
| 12 | !  input NetCDF file.                                                  !
 | 
|---|
| 13 | !                                                                      !
 | 
|---|
| 14 | !  On Input:                                                           !
 | 
|---|
| 15 | !                                                                      !
 | 
|---|
| 16 | !     ng         Nested grid number (integer)                          !
 | 
|---|
| 17 | !     model      Calling model identifier (integer)                    !
 | 
|---|
| 18 | !     ncname     NetCDF file name (string)                             !
 | 
|---|
| 19 | !     ncid       NetCDF file ID (integer)                              !
 | 
|---|
| 20 | !     ncvname    NetCDF variable name (string)                         !
 | 
|---|
| 21 | !     ncvarid    NetCDF variable ID (integer)                          !
 | 
|---|
| 22 | !     tindex     NetCDF time record index to read (integer)            !
 | 
|---|
| 23 | !     gtype      C-grid type (integer)                                 !
 | 
|---|
| 24 | !     Vsize      Variable dimensions in NetCDF file (integer 1D array) !
 | 
|---|
| 25 | !     LBi        I-dimension Lower bound (integer)                     !
 | 
|---|
| 26 | !     UBi        I-dimension Upper bound (integer)                     !
 | 
|---|
| 27 | !     LBj        J-dimension Lower bound (integer)                     !
 | 
|---|
| 28 | !     UBj        J-dimension Upper bound (integer)                     !
 | 
|---|
| 29 | !     LBk        K-dimension Lower bound (integer)                     !
 | 
|---|
| 30 | !     UBk        K-dimension Upper bound (integer)                     !
 | 
|---|
| 31 | !     LBt        Time-dimension Lower bound (integer)                  !
 | 
|---|
| 32 | !     UBt        Time-dimension Upper bound (integer)                  !
 | 
|---|
| 33 | !     Ascl       Factor to scale field after reading (real).           !
 | 
|---|
| 34 | !     Amask      Land/Sea mask, if any (real 4D array)                 !
 | 
|---|
| 35 | !                                                                      !
 | 
|---|
| 36 | !  On Output:                                                          !
 | 
|---|
| 37 | !                                                                      !
 | 
|---|
| 38 | !     Amin       Field minimum value (real)                            !
 | 
|---|
| 39 | !     Amax       Field maximum value (real)                            !
 | 
|---|
| 40 | !     A          Field to read in (real 4D array)                      !
 | 
|---|
| 41 | !     nf_fread4d Error flag (integer)                                  !
 | 
|---|
| 42 | !                                                                      !
 | 
|---|
| 43 | !=======================================================================
 | 
|---|
| 44 | !
 | 
|---|
| 45 |       implicit none
 | 
|---|
| 46 | 
 | 
|---|
| 47 |       CONTAINS
 | 
|---|
| 48 | 
 | 
|---|
| 49 | #if defined PARALLEL_IO && defined DISTRIBUTE
 | 
|---|
| 50 | !
 | 
|---|
| 51 | !***********************************************************************
 | 
|---|
| 52 |       FUNCTION nf_fread4d (ng, model, ncname, ncid,                     &
 | 
|---|
| 53 |      &                     ncvname, ncvarid,                            &
 | 
|---|
| 54 |      &                     tindex, gtype, Vsize,                        &
 | 
|---|
| 55 |      &                     LBi, UBi, LBj, UBj, LBk, UBk, LBt, UBt,      &
 | 
|---|
| 56 |      &                     Ascl, Amin, Amax,                            &
 | 
|---|
| 57 | # ifdef MASKING
 | 
|---|
| 58 |      &                     Amask,                                       &
 | 
|---|
| 59 | # endif
 | 
|---|
| 60 |      &                     A)
 | 
|---|
| 61 | !***********************************************************************
 | 
|---|
| 62 | !
 | 
|---|
| 63 |       USE mod_param
 | 
|---|
| 64 |       USE mod_parallel
 | 
|---|
| 65 |       USE mod_iounits
 | 
|---|
| 66 |       USE mod_ncparam
 | 
|---|
| 67 |       USE mod_netcdf
 | 
|---|
| 68 |       USE mod_scalars
 | 
|---|
| 69 | !
 | 
|---|
| 70 |       USE distribute_mod, ONLY : mp_bcasti, mp_reduce
 | 
|---|
| 71 | # if defined MASKING && defined READ_WATER
 | 
|---|
| 72 |       USE distribute_mod, ONLY : mp_collect
 | 
|---|
| 73 | # endif
 | 
|---|
| 74 |       USE strings_mod,    ONLY : FoundError
 | 
|---|
| 75 | !
 | 
|---|
| 76 |       implicit none
 | 
|---|
| 77 | !
 | 
|---|
| 78 | !  Imported variable declarations.
 | 
|---|
| 79 | !
 | 
|---|
| 80 |       integer, intent(in) :: ng, model, ncid, ncvarid, tindex, gtype
 | 
|---|
| 81 |       integer, intent(in) :: LBi, UBi, LBj, UBj, LBk, UBk, LBt, UBt
 | 
|---|
| 82 |       integer, intent(in) :: Vsize(4)
 | 
|---|
| 83 | 
 | 
|---|
| 84 |       real(r8), intent(in)  :: Ascl
 | 
|---|
| 85 |       real(r8), intent(out) :: Amin
 | 
|---|
| 86 |       real(r8), intent(out) :: Amax
 | 
|---|
| 87 | 
 | 
|---|
| 88 |       character (len=*), intent(in) :: ncname
 | 
|---|
| 89 |       character (len=*), intent(in) :: ncvname
 | 
|---|
| 90 | 
 | 
|---|
| 91 | # ifdef ASSUMED_SHAPE
 | 
|---|
| 92 | #  ifdef MASKING
 | 
|---|
| 93 |       real(r8), intent(in) :: Amask(LBi:,LBj:)
 | 
|---|
| 94 | #  endif
 | 
|---|
| 95 |       real(r8), intent(out) :: A(LBi:,LBj:,LBk:,LBt:)
 | 
|---|
| 96 | # else
 | 
|---|
| 97 | #  ifdef MASKING
 | 
|---|
| 98 |       real(r8), intent(in) :: Amask(LBi:UBi,LBj:UBj)
 | 
|---|
| 99 | #  endif
 | 
|---|
| 100 |       real(r8), intent(out) :: A(LBi:UBi,LBj:UBj,LBk:UBk,LBt:UBt)
 | 
|---|
| 101 | # endif
 | 
|---|
| 102 | !
 | 
|---|
| 103 | !  Local variable declarations.
 | 
|---|
| 104 | !
 | 
|---|
| 105 |       logical, dimension(3) :: foundit
 | 
|---|
| 106 | 
 | 
|---|
| 107 |       integer :: i, ic, ij, j, jc, k, kc, l, lc, np, Npts
 | 
|---|
| 108 |       integer :: Imin, Imax, Isize, Jmin, Jmax, Jsize, IJsize
 | 
|---|
| 109 |       integer :: Istr, Iend
 | 
|---|
| 110 |       integer :: Ioff, Joff, Koff, Loff
 | 
|---|
| 111 |       integer :: Ilen, Jlen, Klen, Llen, IJlen
 | 
|---|
| 112 |       integer :: Cgrid, MyType, ghost, status, wtype
 | 
|---|
| 113 | 
 | 
|---|
| 114 |       integer, dimension(5) :: start, total
 | 
|---|
| 115 | 
 | 
|---|
| 116 |       integer :: nf_fread4d
 | 
|---|
| 117 | 
 | 
|---|
| 118 |       real(r8) :: Afactor, Aoffset, Aspval
 | 
|---|
| 119 | 
 | 
|---|
| 120 |       real(r8), parameter :: IniVal= 0.0_r8
 | 
|---|
| 121 | 
 | 
|---|
| 122 |       real(r8), dimension(2) :: buffer
 | 
|---|
| 123 |       real(r8), dimension(3) :: AttValue
 | 
|---|
| 124 | 
 | 
|---|
| 125 | # if defined MASKING && defined READ_WATER
 | 
|---|
| 126 |       real(r8), allocatable :: A2d(:)
 | 
|---|
| 127 | # endif
 | 
|---|
| 128 |       real(r8), allocatable :: wrk(:)
 | 
|---|
| 129 | 
 | 
|---|
| 130 |       character (len= 3), dimension(2) :: op_handle
 | 
|---|
| 131 |       character (len=12), dimension(3) :: AttName
 | 
|---|
| 132 | !
 | 
|---|
| 133 | !-----------------------------------------------------------------------
 | 
|---|
| 134 | !  Set starting and ending indices to process.
 | 
|---|
| 135 | !-----------------------------------------------------------------------
 | 
|---|
| 136 | !
 | 
|---|
| 137 | !  Set first and last grid point according to staggered C-grid
 | 
|---|
| 138 | !  classification. Set the offsets for variables with starting
 | 
|---|
| 139 | !  zero-index.  Recall the NetCDF does not support a zero-index.
 | 
|---|
| 140 | !
 | 
|---|
| 141 | !  Notice that (Imin,Jmin) and (Imax,Jmax) are the corner of the
 | 
|---|
| 142 | !  computational tile. If ghost=0, ghost points are not processed.
 | 
|---|
| 143 | !  They will be processed elsewhere by the appropriate call to any
 | 
|---|
| 144 | !  of the routines in "mp_exchange.F".  If ghost=1, the ghost points
 | 
|---|
| 145 | !  are read.
 | 
|---|
| 146 | !
 | 
|---|
| 147 | # ifdef NO_READ_GHOST
 | 
|---|
| 148 |       ghost=0                        ! non-overlapping, no ghost points
 | 
|---|
| 149 | # else
 | 
|---|
| 150 |       IF (model.eq.iADM) THEN
 | 
|---|
| 151 |         ghost=0                      ! non-overlapping, no ghost points
 | 
|---|
| 152 |       ELSE
 | 
|---|
| 153 |         ghost=1                      ! overlapping, read ghost points
 | 
|---|
| 154 |       END IF
 | 
|---|
| 155 | # endif
 | 
|---|
| 156 | 
 | 
|---|
| 157 |       MyType=gtype
 | 
|---|
| 158 | 
 | 
|---|
| 159 |       SELECT CASE (ABS(MyType))
 | 
|---|
| 160 |         CASE (p2dvar, p3dvar)
 | 
|---|
| 161 |           Cgrid=1
 | 
|---|
| 162 |           Isize=IOBOUNDS(ng)%xi_psi
 | 
|---|
| 163 |           Jsize=IOBOUNDS(ng)%eta_psi
 | 
|---|
| 164 |         CASE (r2dvar, r3dvar, w3dvar)
 | 
|---|
| 165 |           Cgrid=2
 | 
|---|
| 166 |           Isize=IOBOUNDS(ng)%xi_rho
 | 
|---|
| 167 |           Jsize=IOBOUNDS(ng)%eta_rho
 | 
|---|
| 168 |         CASE (u2dvar, u3dvar)
 | 
|---|
| 169 |           Cgrid=3
 | 
|---|
| 170 |           Isize=IOBOUNDS(ng)%xi_u
 | 
|---|
| 171 |           Jsize=IOBOUNDS(ng)%eta_u
 | 
|---|
| 172 |         CASE (v2dvar, v3dvar)
 | 
|---|
| 173 |           Cgrid=4
 | 
|---|
| 174 |           Isize=IOBOUNDS(ng)%xi_v
 | 
|---|
| 175 |           Jsize=IOBOUNDS(ng)%eta_v
 | 
|---|
| 176 |         CASE DEFAULT
 | 
|---|
| 177 |           Cgrid=2
 | 
|---|
| 178 |           Isize=IOBOUNDS(ng)%xi_rho
 | 
|---|
| 179 |           Jsize=IOBOUNDS(ng)%eta_rho
 | 
|---|
| 180 |       END SELECT
 | 
|---|
| 181 | 
 | 
|---|
| 182 |       Imin=BOUNDS(ng)%Imin(Cgrid,ghost,MyRank)
 | 
|---|
| 183 |       Imax=BOUNDS(ng)%Imax(Cgrid,ghost,MyRank)
 | 
|---|
| 184 |       Jmin=BOUNDS(ng)%Jmin(Cgrid,ghost,MyRank)
 | 
|---|
| 185 |       Jmax=BOUNDS(ng)%Jmax(Cgrid,ghost,MyRank)
 | 
|---|
| 186 | 
 | 
|---|
| 187 |       Ilen=Imax-Imin+1
 | 
|---|
| 188 |       Jlen=Jmax-Jmin+1
 | 
|---|
| 189 |       Klen=UBk-LBk+1
 | 
|---|
| 190 |       Llen=UBt-LBt+1
 | 
|---|
| 191 | !
 | 
|---|
| 192 | !  Check if the following attributes: "scale_factor", "add_offset", and
 | 
|---|
| 193 | !  "_FillValue" are present in the input NetCDF variable:
 | 
|---|
| 194 | !
 | 
|---|
| 195 | !  If the "scale_value" attribute is present, the data is multiplied by
 | 
|---|
| 196 | !  this factor after reading.
 | 
|---|
| 197 | !  If the "add_offset" attribute is present, this value is added to the
 | 
|---|
| 198 | !  data after reading.
 | 
|---|
| 199 | !  If both "scale_factor" and "add_offset" attributes are present, the
 | 
|---|
| 200 | !  data are first scaled before the offset is added.
 | 
|---|
| 201 | !  If the "_FillValue" attribute is present, the data having this value
 | 
|---|
| 202 | !  is treated as missing and it is replaced with zero. This feature it
 | 
|---|
| 203 | !  is usually related with the land/sea masking.
 | 
|---|
| 204 | !
 | 
|---|
| 205 |       AttName(1)='scale_factor'
 | 
|---|
| 206 |       AttName(2)='add_offset  '
 | 
|---|
| 207 |       AttName(3)='_FillValue  '
 | 
|---|
| 208 | 
 | 
|---|
| 209 |       CALL netcdf_get_fatt (ng, model, ncname, ncvarid, AttName,        &
 | 
|---|
| 210 |      &                      AttValue, foundit,                          &
 | 
|---|
| 211 |      &                      ncid = ncid)
 | 
|---|
| 212 |       IF (FoundError(exit_flag, NoError, __LINE__,                      &
 | 
|---|
| 213 |      &               __FILE__)) THEN
 | 
|---|
| 214 |         nf_fread4d=ioerror
 | 
|---|
| 215 |         RETURN
 | 
|---|
| 216 |       END IF
 | 
|---|
| 217 | 
 | 
|---|
| 218 |       IF (.not.foundit(1)) THEN
 | 
|---|
| 219 |         Afactor=1.0_r8
 | 
|---|
| 220 |       ELSE
 | 
|---|
| 221 |         Afactor=AttValue(1)
 | 
|---|
| 222 |       END IF
 | 
|---|
| 223 | 
 | 
|---|
| 224 |       IF (.not.foundit(2)) THEN
 | 
|---|
| 225 |         Aoffset=0.0_r8
 | 
|---|
| 226 |       ELSE
 | 
|---|
| 227 |         Aoffset=AttValue(2)
 | 
|---|
| 228 |       END IF
 | 
|---|
| 229 | 
 | 
|---|
| 230 |       IF (.not.foundit(3)) THEN
 | 
|---|
| 231 |         Aspval=spval_check
 | 
|---|
| 232 |       ELSE
 | 
|---|
| 233 |         Aspval=AttValue(3)
 | 
|---|
| 234 |       END IF
 | 
|---|
| 235 | !
 | 
|---|
| 236 | !-----------------------------------------------------------------------
 | 
|---|
| 237 | !  Parallel I/O: Read in tile data from requested field and scale it.
 | 
|---|
| 238 | !                Processing both water and land points.
 | 
|---|
| 239 | !-----------------------------------------------------------------------
 | 
|---|
| 240 | !
 | 
|---|
| 241 |       IF (gtype.gt.0) THEN
 | 
|---|
| 242 | !
 | 
|---|
| 243 | !  Set offsets due the NetCDF dimensions. Recall that some output
 | 
|---|
| 244 | !  variables not always start at one.
 | 
|---|
| 245 | !
 | 
|---|
| 246 |         SELECT CASE (ABS(MyType))
 | 
|---|
| 247 |           CASE (p2dvar, p3dvar)
 | 
|---|
| 248 |             Ioff=0
 | 
|---|
| 249 |             Joff=0
 | 
|---|
| 250 |           CASE (r2dvar, r3dvar, w3dvar)
 | 
|---|
| 251 |             Ioff=1
 | 
|---|
| 252 |             Joff=1
 | 
|---|
| 253 |           CASE (u2dvar, u3dvar)
 | 
|---|
| 254 |             Ioff=0
 | 
|---|
| 255 |             Joff=1
 | 
|---|
| 256 |           CASE (v2dvar, v3dvar)
 | 
|---|
| 257 |             Ioff=1
 | 
|---|
| 258 |             Joff=0
 | 
|---|
| 259 |           CASE DEFAULT
 | 
|---|
| 260 |             Ioff=1
 | 
|---|
| 261 |             Joff=1
 | 
|---|
| 262 |         END SELECT
 | 
|---|
| 263 | 
 | 
|---|
| 264 |         IF (LBk.eq.0) THEN
 | 
|---|
| 265 |           Koff=1
 | 
|---|
| 266 |         ELSE
 | 
|---|
| 267 |           Koff=0
 | 
|---|
| 268 |         END IF
 | 
|---|
| 269 | 
 | 
|---|
| 270 |         IF (LBt.eq.0) THEN
 | 
|---|
| 271 |           Loff=1
 | 
|---|
| 272 |         ELSE
 | 
|---|
| 273 |           Loff=0
 | 
|---|
| 274 |         END IF
 | 
|---|
| 275 | 
 | 
|---|
| 276 |         Npts=Ilen*Jlen*Klen*Llen
 | 
|---|
| 277 | !
 | 
|---|
| 278 | !  Allocate scratch work array.
 | 
|---|
| 279 | !
 | 
|---|
| 280 |         IF (.not.allocated(wrk)) THEN
 | 
|---|
| 281 |           allocate ( wrk(Npts) )
 | 
|---|
| 282 |           wrk=0.0_r8
 | 
|---|
| 283 |         END IF
 | 
|---|
| 284 | !
 | 
|---|
| 285 | !  Read in data: all parallel nodes read their own tile data.
 | 
|---|
| 286 | !
 | 
|---|
| 287 |         start(1)=Imin+Ioff
 | 
|---|
| 288 |         total(1)=Ilen
 | 
|---|
| 289 |         start(2)=Jmin+Joff
 | 
|---|
| 290 |         total(2)=Jlen
 | 
|---|
| 291 |         start(3)=LBk+Koff
 | 
|---|
| 292 |         total(3)=Klen
 | 
|---|
| 293 |         start(4)=LBt+Loff
 | 
|---|
| 294 |         total(4)=Llen
 | 
|---|
| 295 |         start(5)=tindex
 | 
|---|
| 296 |         total(5)=1
 | 
|---|
| 297 | 
 | 
|---|
| 298 |         status=nf90_get_var(ncid, ncvarid, wrk, start, total)
 | 
|---|
| 299 |         nf_fread4d=status
 | 
|---|
| 300 | !
 | 
|---|
| 301 | !  Scale read data and process fill values, if any.  Compute minimum
 | 
|---|
| 302 | !  and maximum values.
 | 
|---|
| 303 | !
 | 
|---|
| 304 |         IF (status.eq.nf90_noerr) THEN
 | 
|---|
| 305 |           Amin=spval
 | 
|---|
| 306 |           Amax=-spval
 | 
|---|
| 307 |           DO i=1,Npts
 | 
|---|
| 308 |             IF (ABS(wrk(i)).ge.ABS(Aspval)) THEN
 | 
|---|
| 309 |               wrk(i)=0.0_r8                   ! masked with _FillValue
 | 
|---|
| 310 |             ELSE
 | 
|---|
| 311 |               wrk(i)=Ascl*(Afactor*wrk(i)+Aoffset)
 | 
|---|
| 312 |               Amin=MIN(Amin,wrk(i))
 | 
|---|
| 313 |               Amax=MAX(Amax,wrk(i))
 | 
|---|
| 314 |             END IF
 | 
|---|
| 315 |           END DO
 | 
|---|
| 316 | !
 | 
|---|
| 317 | !  Set minimum and maximum values: global reduction.
 | 
|---|
| 318 | !
 | 
|---|
| 319 |           buffer(1)=Amin
 | 
|---|
| 320 |           op_handle(1)='MIN'
 | 
|---|
| 321 |           buffer(2)=Amax
 | 
|---|
| 322 |           op_handle(2)='MAX'
 | 
|---|
| 323 |           CALL mp_reduce (ng, model, 2, buffer, op_handle)
 | 
|---|
| 324 |           Amin=buffer(1)
 | 
|---|
| 325 |           Amax=buffer(2)
 | 
|---|
| 326 | !
 | 
|---|
| 327 | !  Unpack read data.
 | 
|---|
| 328 | !
 | 
|---|
| 329 |           ic=0
 | 
|---|
| 330 |           DO l=LBt,UBt
 | 
|---|
| 331 |             DO k=LBk,UBk
 | 
|---|
| 332 |               DO j=Jmin,Jmax
 | 
|---|
| 333 |                 DO i=Imin,Imax
 | 
|---|
| 334 |                   ic=ic+1
 | 
|---|
| 335 |                   A(i,j,k,l)=wrk(ic)
 | 
|---|
| 336 |                 END DO
 | 
|---|
| 337 |               END DO
 | 
|---|
| 338 |             END DO
 | 
|---|
| 339 |           END DO
 | 
|---|
| 340 |         ELSE
 | 
|---|
| 341 |           exit_flag=2
 | 
|---|
| 342 |           ioerror=status
 | 
|---|
| 343 |         END IF
 | 
|---|
| 344 |       END IF
 | 
|---|
| 345 | 
 | 
|---|
| 346 | # if defined MASKING && defined READ_WATER
 | 
|---|
| 347 | !
 | 
|---|
| 348 | !-----------------------------------------------------------------------
 | 
|---|
| 349 | !  Parallel I/O: Read in tile data from requested field and scale it.
 | 
|---|
| 350 | !                Processing water points only.
 | 
|---|
| 351 | !-----------------------------------------------------------------------
 | 
|---|
| 352 | !
 | 
|---|
| 353 |       IF (gtype.lt.0) THEN
 | 
|---|
| 354 | !
 | 
|---|
| 355 | !  Set number of points to process, grid type switch, and offsets due
 | 
|---|
| 356 | !  array packing into 1D array in column-major order.
 | 
|---|
| 357 | !
 | 
|---|
| 358 |         SELECT CASE (ABS(MyType))
 | 
|---|
| 359 |           CASE (p3dvar)
 | 
|---|
| 360 |             IJlen=IOBOUNDS(ng)%xy_psi
 | 
|---|
| 361 |             wtype=p2dvar
 | 
|---|
| 362 |             Ioff=0
 | 
|---|
| 363 |             Joff=1
 | 
|---|
| 364 |           CASE (r3dvar, w3dvar)
 | 
|---|
| 365 |             IJlen=IOBOUNDS(ng)%xy_rho
 | 
|---|
| 366 |             wtype=r2dvar
 | 
|---|
| 367 |             Ioff=1
 | 
|---|
| 368 |             Joff=0
 | 
|---|
| 369 |           CASE (u3dvar)
 | 
|---|
| 370 |             IJlen=IOBOUNDS(ng)%xy_u
 | 
|---|
| 371 |             wtype=u2dvar
 | 
|---|
| 372 |             Ioff=0
 | 
|---|
| 373 |             Joff=0
 | 
|---|
| 374 |           CASE (v3dvar)
 | 
|---|
| 375 |             IJlen=IOBOUNDS(ng)%xy_v
 | 
|---|
| 376 |             wtype=v2dvar
 | 
|---|
| 377 |             Ioff=1
 | 
|---|
| 378 |             Joff=1
 | 
|---|
| 379 |           CASE DEFAULT
 | 
|---|
| 380 |             IJlen=IOBOUNDS(ng)%xy_rho
 | 
|---|
| 381 |             wtype=r2dvar
 | 
|---|
| 382 |             Ioff=1
 | 
|---|
| 383 |             Joff=0
 | 
|---|
| 384 |         END SELECT
 | 
|---|
| 385 | 
 | 
|---|
| 386 |         IF (LBk.eq.0) THEN
 | 
|---|
| 387 |           Koff=0
 | 
|---|
| 388 |         ELSE
 | 
|---|
| 389 |           Koff=1
 | 
|---|
| 390 |         END IF
 | 
|---|
| 391 | 
 | 
|---|
| 392 |         IF (LBt.eq.0) THEN
 | 
|---|
| 393 |           Loff=1
 | 
|---|
| 394 |         ELSE
 | 
|---|
| 395 |           Loff=0
 | 
|---|
| 396 |         END IF
 | 
|---|
| 397 | 
 | 
|---|
| 398 |         Npts=IJlen*Klen*Llen
 | 
|---|
| 399 |         IJsize=Isize*Jsize
 | 
|---|
| 400 | !
 | 
|---|
| 401 | !  Allocate scratch work arrays.
 | 
|---|
| 402 | !
 | 
|---|
| 403 |         IF (.not.allocated(A2d)) THEN
 | 
|---|
| 404 |           allocate ( A2d(IJsize) )
 | 
|---|
| 405 |         END IF
 | 
|---|
| 406 |         IF (.not.allocated(wrk)) THEN
 | 
|---|
| 407 |           allocate ( wrk(Npts) )
 | 
|---|
| 408 |           wrk=IniVal
 | 
|---|
| 409 |         END IF
 | 
|---|
| 410 | !
 | 
|---|
| 411 | !  Read in data: all parallel nodes read a segment of the 1D data.
 | 
|---|
| 412 | !  Recall that water points are pack in the NetCDF file in a single
 | 
|---|
| 413 | !  dimension.
 | 
|---|
| 414 | !
 | 
|---|
| 415 |         CALL tile_bounds_1d (ng, MyRank, Npts, Istr, Iend)
 | 
|---|
| 416 | 
 | 
|---|
| 417 |         start(1)=Istr
 | 
|---|
| 418 |         total(1)=Iend-Istr+1
 | 
|---|
| 419 |         start(2)=1
 | 
|---|
| 420 |         total(2)=tindex
 | 
|---|
| 421 | 
 | 
|---|
| 422 |         status=nf90_get_var(ncid, ncvarid, wrk(Istr:), start, total)
 | 
|---|
| 423 |         nf_fread4d=status
 | 
|---|
| 424 | !
 | 
|---|
| 425 | !  Global reduction of work array.  We need this because the packing
 | 
|---|
| 426 | !  of the water point only affects the model tile partition.
 | 
|---|
| 427 | !
 | 
|---|
| 428 |         IF (status.eq.nf90_noerr) THEN
 | 
|---|
| 429 |           CALL mp_collect (ng, model, Npts, IniVal, wrk)
 | 
|---|
| 430 | !
 | 
|---|
| 431 | !  Scale read data and process fill values, if any.  Compute minimum
 | 
|---|
| 432 | !  and maximum values.
 | 
|---|
| 433 | !
 | 
|---|
| 434 |           Amin=spval
 | 
|---|
| 435 |           Amax=-spval
 | 
|---|
| 436 |           DO i=1,Npts
 | 
|---|
| 437 |             IF (ABS(wrk(i)).ge.ABS(Aspval)) THEN
 | 
|---|
| 438 |               wrk(i)=0.0_r8             ! set _FillValue to zero
 | 
|---|
| 439 |             ELSE
 | 
|---|
| 440 |               wrk(i)=Ascl*(Afactor*wrk(i)+Aoffset)
 | 
|---|
| 441 |               Amin=MIN(Amin,wrk(i))
 | 
|---|
| 442 |               Amax=MAX(Amax,wrk(i))
 | 
|---|
| 443 |             END IF
 | 
|---|
| 444 |           END DO
 | 
|---|
| 445 | !
 | 
|---|
| 446 | !  Unpack read data.  This is tricky in parallel I/O.  The cheapeast
 | 
|---|
| 447 | !  thing to do is reconstruct a packed 2D global array and then select
 | 
|---|
| 448 | !  the appropriate values for the tile.
 | 
|---|
| 449 | !
 | 
|---|
| 450 |           DO l=LBt,UBt
 | 
|---|
| 451 |             lc=(l-Loff)*IJlen*Klen
 | 
|---|
| 452 |             DO k=LBk,UBk
 | 
|---|
| 453 |               kc=(k-Koff)*IJlen+lc
 | 
|---|
| 454 |               A2d=IniVal
 | 
|---|
| 455 |               DO np=1,IJlen
 | 
|---|
| 456 |                 ij=SCALARS(ng)%IJwater(np,wtype)
 | 
|---|
| 457 |                 A2d(ij)=wrk(np+kc)
 | 
|---|
| 458 |               END DO
 | 
|---|
| 459 |               DO j=Jmin,Jmax
 | 
|---|
| 460 |                 jc=(j-Joff)*Isize
 | 
|---|
| 461 |                 DO i=Imin,Imax
 | 
|---|
| 462 |                   ij=i+Ioff+jc
 | 
|---|
| 463 |                   A(i,j,k,l)=A2d(ij)
 | 
|---|
| 464 |                 END DO
 | 
|---|
| 465 |               END DO
 | 
|---|
| 466 |             END DO
 | 
|---|
| 467 |           END DO
 | 
|---|
| 468 |         ELSE
 | 
|---|
| 469 |           exit_flag=2
 | 
|---|
| 470 |           ioerror=status
 | 
|---|
| 471 |         END IF
 | 
|---|
| 472 |       END IF
 | 
|---|
| 473 | # endif
 | 
|---|
| 474 | !
 | 
|---|
| 475 | !-----------------------------------------------------------------------
 | 
|---|
| 476 | !  Deallocate scratch work vector.
 | 
|---|
| 477 | !-----------------------------------------------------------------------
 | 
|---|
| 478 | !
 | 
|---|
| 479 | # if defined MASKING && defined READ_WATER
 | 
|---|
| 480 |       IF (allocated(A2d)) THEN
 | 
|---|
| 481 |         deallocate (A2d)
 | 
|---|
| 482 |       END IF
 | 
|---|
| 483 | # endif
 | 
|---|
| 484 | 
 | 
|---|
| 485 |       IF (allocated(wrk)) THEN
 | 
|---|
| 486 |         deallocate (wrk)
 | 
|---|
| 487 |       END IF
 | 
|---|
| 488 | 
 | 
|---|
| 489 |       RETURN
 | 
|---|
| 490 |       END FUNCTION nf_fread4d
 | 
|---|
| 491 | 
 | 
|---|
| 492 | #else
 | 
|---|
| 493 | 
 | 
|---|
| 494 | !
 | 
|---|
| 495 | !***********************************************************************
 | 
|---|
| 496 |       FUNCTION nf_fread4d (ng, model, ncname, ncid,                     &
 | 
|---|
| 497 |      &                     ncvname, ncvarid,                            &
 | 
|---|
| 498 |      &                     tindex, gtype, Vsize,                        &
 | 
|---|
| 499 |      &                     LBi, UBi, LBj, UBj, LBk, UBk, LBt, UBt,      &
 | 
|---|
| 500 |      &                     Ascl, Amin, Amax,                            &
 | 
|---|
| 501 | # ifdef MASKING
 | 
|---|
| 502 |      &                     Amask,                                       &
 | 
|---|
| 503 | # endif
 | 
|---|
| 504 |      &                     A)
 | 
|---|
| 505 | !***********************************************************************
 | 
|---|
| 506 | !
 | 
|---|
| 507 |       USE mod_param
 | 
|---|
| 508 |       USE mod_parallel
 | 
|---|
| 509 |       USE mod_iounits
 | 
|---|
| 510 |       USE mod_ncparam
 | 
|---|
| 511 |       USE mod_netcdf
 | 
|---|
| 512 |       USE mod_scalars
 | 
|---|
| 513 | !
 | 
|---|
| 514 | # ifdef DISTRIBUTE
 | 
|---|
| 515 |       USE distribute_mod, ONLY : mp_bcasti
 | 
|---|
| 516 | #  ifdef INLINE_2DIO
 | 
|---|
| 517 |       USE distribute_mod, ONLY : mp_scatter2d
 | 
|---|
| 518 | #  else
 | 
|---|
| 519 |       USE distribute_mod, ONLY : mp_scatter3d
 | 
|---|
| 520 | #  endif
 | 
|---|
| 521 | 
 | 
|---|
| 522 | # endif
 | 
|---|
| 523 |       USE strings_mod,    ONLY : FoundError
 | 
|---|
| 524 | !
 | 
|---|
| 525 |       implicit none
 | 
|---|
| 526 | !
 | 
|---|
| 527 | !  Imported variable declarations.
 | 
|---|
| 528 | !
 | 
|---|
| 529 |       integer, intent(in) :: ng, model, ncid, ncvarid, tindex, gtype
 | 
|---|
| 530 |       integer, intent(in) :: LBi, UBi, LBj, UBj, LBk, UBk, LBt, UBt
 | 
|---|
| 531 |       integer, intent(in) :: Vsize(4)
 | 
|---|
| 532 | 
 | 
|---|
| 533 |       real(r8), intent(in)  :: Ascl
 | 
|---|
| 534 |       real(r8), intent(out) :: Amin
 | 
|---|
| 535 |       real(r8), intent(out) :: Amax
 | 
|---|
| 536 | 
 | 
|---|
| 537 |       character (len=*), intent(in) :: ncname
 | 
|---|
| 538 |       character (len=*), intent(in) :: ncvname
 | 
|---|
| 539 | 
 | 
|---|
| 540 | # ifdef ASSUMED_SHAPE
 | 
|---|
| 541 | #  ifdef MASKING
 | 
|---|
| 542 |       real(r8), intent(in) :: Amask(LBi:,LBj:)
 | 
|---|
| 543 | #  endif
 | 
|---|
| 544 |       real(r8), intent(out) :: A(LBi:,LBj:,LBk:,LBt:)
 | 
|---|
| 545 | # else
 | 
|---|
| 546 | #  ifdef MASKING
 | 
|---|
| 547 |       real(r8), intent(in) :: Amask(LBi:UBi,LBj:UBj)
 | 
|---|
| 548 | #  endif
 | 
|---|
| 549 |       real(r8), intent(out) :: A(LBi:UBi,LBj:UBj,LBk:UBk,LBt:UBt)
 | 
|---|
| 550 | # endif
 | 
|---|
| 551 | !
 | 
|---|
| 552 | !  Local variable declarations.
 | 
|---|
| 553 | !
 | 
|---|
| 554 |       logical, dimension(3) :: foundit
 | 
|---|
| 555 | 
 | 
|---|
| 556 |       integer :: i, j, k, ic, fourth, Npts, NWpts, status, wtype
 | 
|---|
| 557 |       integer :: Imin, Imax, Jmin, Jmax, Loff, Koff
 | 
|---|
| 558 |       integer :: Ilen, Jlen, Klen, IJlen, MyType
 | 
|---|
| 559 | # ifdef DISTRIBUTE
 | 
|---|
| 560 |       integer :: Nghost
 | 
|---|
| 561 | # endif
 | 
|---|
| 562 |       integer, dimension(5) :: start, total
 | 
|---|
| 563 | 
 | 
|---|
| 564 |       integer :: nf_fread4d
 | 
|---|
| 565 | 
 | 
|---|
| 566 |       real(r8) :: Afactor, Aoffset, Aspval
 | 
|---|
| 567 | 
 | 
|---|
| 568 |       real(r8), dimension(3) :: AttValue
 | 
|---|
| 569 | 
 | 
|---|
| 570 | # if defined INLINE_2DIO && defined DISTRIBUTE
 | 
|---|
| 571 |       real(r8), dimension(2+(Lm(ng)+2)*(Mm(ng)+2)) :: wrk
 | 
|---|
| 572 | # else
 | 
|---|
| 573 |       real(r8), dimension(2+(Lm(ng)+2)*(Mm(ng)+2)*(UBk-LBk+1)) :: wrk
 | 
|---|
| 574 | # endif
 | 
|---|
| 575 | 
 | 
|---|
| 576 |       character (len=12), dimension(3) :: AttName
 | 
|---|
| 577 | !
 | 
|---|
| 578 | !-----------------------------------------------------------------------
 | 
|---|
| 579 | !  Set starting and ending indices to process.
 | 
|---|
| 580 | !-----------------------------------------------------------------------
 | 
|---|
| 581 | !
 | 
|---|
| 582 | !  Set first and last grid point according to staggered C-grid
 | 
|---|
| 583 | !  classification. Set loops offsets.
 | 
|---|
| 584 | !
 | 
|---|
| 585 |       MyType=gtype
 | 
|---|
| 586 | 
 | 
|---|
| 587 |       SELECT CASE (ABS(MyType))
 | 
|---|
| 588 |         CASE (p2dvar, p3dvar)
 | 
|---|
| 589 |           Imin=IOBOUNDS(ng)%ILB_psi
 | 
|---|
| 590 |           Imax=IOBOUNDS(ng)%IUB_psi
 | 
|---|
| 591 |           Jmin=IOBOUNDS(ng)%JLB_psi
 | 
|---|
| 592 |           Jmax=IOBOUNDS(ng)%JUB_psi
 | 
|---|
| 593 |         CASE (r2dvar, r3dvar, w3dvar)
 | 
|---|
| 594 |           Imin=IOBOUNDS(ng)%ILB_rho
 | 
|---|
| 595 |           Imax=IOBOUNDS(ng)%IUB_rho
 | 
|---|
| 596 |           Jmin=IOBOUNDS(ng)%JLB_rho
 | 
|---|
| 597 |           Jmax=IOBOUNDS(ng)%JUB_rho
 | 
|---|
| 598 |         CASE (u2dvar, u3dvar)
 | 
|---|
| 599 |           Imin=IOBOUNDS(ng)%ILB_u
 | 
|---|
| 600 |           Imax=IOBOUNDS(ng)%IUB_u
 | 
|---|
| 601 |           Jmin=IOBOUNDS(ng)%JLB_u
 | 
|---|
| 602 |           Jmax=IOBOUNDS(ng)%JUB_u
 | 
|---|
| 603 |         CASE (v2dvar, v3dvar)
 | 
|---|
| 604 |           Imin=IOBOUNDS(ng)%ILB_v
 | 
|---|
| 605 |           Imax=IOBOUNDS(ng)%IUB_v
 | 
|---|
| 606 |           Jmin=IOBOUNDS(ng)%JLB_v
 | 
|---|
| 607 |           Jmax=IOBOUNDS(ng)%JUB_v
 | 
|---|
| 608 |         CASE DEFAULT
 | 
|---|
| 609 |           Imin=IOBOUNDS(ng)%ILB_rho
 | 
|---|
| 610 |           Imax=IOBOUNDS(ng)%IUB_rho
 | 
|---|
| 611 |           Jmin=IOBOUNDS(ng)%JLB_rho
 | 
|---|
| 612 |           Jmax=IOBOUNDS(ng)%JUB_rho
 | 
|---|
| 613 |       END SELECT
 | 
|---|
| 614 | 
 | 
|---|
| 615 |       Ilen=Imax-Imin+1
 | 
|---|
| 616 |       Jlen=Jmax-Jmin+1
 | 
|---|
| 617 |       Klen=UBk-LBk+1
 | 
|---|
| 618 |       IJlen=Ilen*Jlen
 | 
|---|
| 619 | 
 | 
|---|
| 620 |       IF (LBt.eq.0) THEN
 | 
|---|
| 621 |         Loff=1
 | 
|---|
| 622 |       ELSE
 | 
|---|
| 623 |         Loff=0
 | 
|---|
| 624 |       END IF
 | 
|---|
| 625 | #ifdef INLINE_2DIO
 | 
|---|
| 626 |       IF (LBk.eq.0) THEN
 | 
|---|
| 627 |         Koff=0
 | 
|---|
| 628 |       ELSE
 | 
|---|
| 629 |         Koff=1
 | 
|---|
| 630 |       END IF
 | 
|---|
| 631 | #endif
 | 
|---|
| 632 | 
 | 
|---|
| 633 | !
 | 
|---|
| 634 | !  Check if the following attributes: "scale_factor", "add_offset", and
 | 
|---|
| 635 | !  "_FillValue" are present in the input NetCDF variable:
 | 
|---|
| 636 | !
 | 
|---|
| 637 | !  If the "scale_value" attribute is present, the data is multiplied by
 | 
|---|
| 638 | !  this factor after reading.
 | 
|---|
| 639 | !  If the "add_offset" attribute is present, this value is added to the
 | 
|---|
| 640 | !  data after reading.
 | 
|---|
| 641 | !  If both "scale_factor" and "add_offset" attributes are present, the
 | 
|---|
| 642 | !  data are first scaled before the offset is added.
 | 
|---|
| 643 | !  If the "_FillValue" attribute is present, the data having this value
 | 
|---|
| 644 | !  is treated as missing and it is replaced with zero. This feature it
 | 
|---|
| 645 | !  is usually related with the land/sea masking.
 | 
|---|
| 646 | !
 | 
|---|
| 647 |       AttName(1)='scale_factor'
 | 
|---|
| 648 |       AttName(2)='add_offset  '
 | 
|---|
| 649 |       AttName(3)='_FillValue  '
 | 
|---|
| 650 | 
 | 
|---|
| 651 |       CALL netcdf_get_fatt (ng, model, ncname, ncvarid, AttName,        &
 | 
|---|
| 652 |      &                      AttValue, foundit,                          &
 | 
|---|
| 653 |      &                      ncid = ncid)
 | 
|---|
| 654 |       IF (FoundError(exit_flag, NoError, __LINE__,                      &
 | 
|---|
| 655 |      &               __FILE__)) THEN
 | 
|---|
| 656 |         nf_fread4d=ioerror
 | 
|---|
| 657 |         RETURN
 | 
|---|
| 658 |       END IF
 | 
|---|
| 659 | 
 | 
|---|
| 660 |       IF (.not.foundit(1)) THEN
 | 
|---|
| 661 |         Afactor=1.0_r8
 | 
|---|
| 662 |       ELSE
 | 
|---|
| 663 |         Afactor=AttValue(1)
 | 
|---|
| 664 |       END IF
 | 
|---|
| 665 | 
 | 
|---|
| 666 |       IF (.not.foundit(2)) THEN
 | 
|---|
| 667 |         Aoffset=0.0_r8
 | 
|---|
| 668 |       ELSE
 | 
|---|
| 669 |         Aoffset=AttValue(2)
 | 
|---|
| 670 |       END IF
 | 
|---|
| 671 | 
 | 
|---|
| 672 |       IF (.not.foundit(3)) THEN
 | 
|---|
| 673 |         Aspval=spval_check
 | 
|---|
| 674 |       ELSE
 | 
|---|
| 675 |         Aspval=AttValue(3)
 | 
|---|
| 676 |       END IF
 | 
|---|
| 677 | 
 | 
|---|
| 678 | # ifdef DISTRIBUTE
 | 
|---|
| 679 | !
 | 
|---|
| 680 | !  Set the number of tile ghost points, Nghost, to scatter in
 | 
|---|
| 681 | !  distributed-memory applications. If Nghost=0, the ghost points
 | 
|---|
| 682 | !  are not processed.  They will be processed elsewhere by the
 | 
|---|
| 683 | !  appropriate call to any of the routines in "mp_exchange.F".
 | 
|---|
| 684 | !
 | 
|---|
| 685 | #  ifdef NO_READ_GHOST
 | 
|---|
| 686 |       Nghost=0
 | 
|---|
| 687 | #  else
 | 
|---|
| 688 |       IF (model.eq.iADM) THEN
 | 
|---|
| 689 |         Nghost=0
 | 
|---|
| 690 |       ELSE
 | 
|---|
| 691 |         Nghost=NghostPoints
 | 
|---|
| 692 |       END IF
 | 
|---|
| 693 | #  endif
 | 
|---|
| 694 | # endif
 | 
|---|
| 695 | # if defined READ_WATER && defined MASKING
 | 
|---|
| 696 | !
 | 
|---|
| 697 | !  If processing water points only, set number of points and type
 | 
|---|
| 698 | !  switch.
 | 
|---|
| 699 | !
 | 
|---|
| 700 |       SELECT CASE (ABS(MyType))
 | 
|---|
| 701 |         CASE (p3dvar)
 | 
|---|
| 702 |           Npts=IOBOUNDS(ng)%xy_psi
 | 
|---|
| 703 |           wtype=p2dvar
 | 
|---|
| 704 |         CASE (r3dvar, w3dvar)
 | 
|---|
| 705 |           Npts=IOBOUNDS(ng)%xy_rho
 | 
|---|
| 706 |           wtype=r2dvar
 | 
|---|
| 707 |         CASE (u3dvar)
 | 
|---|
| 708 |           Npts=IOBOUNDS(ng)%xy_u
 | 
|---|
| 709 |           wtype=u2dvar
 | 
|---|
| 710 |         CASE (v3dvar)
 | 
|---|
| 711 |           Npts=IOBOUNDS(ng)%xy_v
 | 
|---|
| 712 |           wtype=v2dvar
 | 
|---|
| 713 |         CASE DEFAULT
 | 
|---|
| 714 |           Npts=IOBOUNDS(ng)%xy_rho
 | 
|---|
| 715 |           wtype=r2dvar
 | 
|---|
| 716 |       END SELECT
 | 
|---|
| 717 |       NWpts=(Lm(ng)+2)*(Mm(ng)+2)
 | 
|---|
| 718 | #  if !(defined INLINE_2DIO && defined DISTRIBUTE)
 | 
|---|
| 719 |       Npts=Npts*Klen
 | 
|---|
| 720 | #  endif
 | 
|---|
| 721 | # endif
 | 
|---|
| 722 | !
 | 
|---|
| 723 | !  Initialize local array to avoid denormalized numbers. This
 | 
|---|
| 724 | !  facilitates processing and debugging.
 | 
|---|
| 725 | !
 | 
|---|
| 726 |       wrk=0.0_r8
 | 
|---|
| 727 | !
 | 
|---|
| 728 | !-----------------------------------------------------------------------
 | 
|---|
| 729 | !  Serial I/O: Read in requested field and scale it.
 | 
|---|
| 730 | !-----------------------------------------------------------------------
 | 
|---|
| 731 | !
 | 
|---|
| 732 | !  Proccess data as 3D slides.
 | 
|---|
| 733 | !
 | 
|---|
| 734 |       Amin=spval
 | 
|---|
| 735 |       Amax=-spval
 | 
|---|
| 736 | 
 | 
|---|
| 737 |       DO fourth=LBt,UBt
 | 
|---|
| 738 |         IF (MyType.gt.0) THEN
 | 
|---|
| 739 |           start(1)=1
 | 
|---|
| 740 |           total(1)=Ilen
 | 
|---|
| 741 |           start(2)=1
 | 
|---|
| 742 |           total(2)=Jlen
 | 
|---|
| 743 |           start(3)=1
 | 
|---|
| 744 |           total(3)=Klen
 | 
|---|
| 745 |           start(4)=fourth+Loff
 | 
|---|
| 746 |           total(4)=1
 | 
|---|
| 747 |           start(5)=tindex
 | 
|---|
| 748 |           total(5)=1
 | 
|---|
| 749 |           Npts=IJlen
 | 
|---|
| 750 | # if !(defined INLINE_2DIO && defined DISTRIBUTE)
 | 
|---|
| 751 |           Npts=Npts*Klen
 | 
|---|
| 752 | # endif
 | 
|---|
| 753 | # if defined READ_WATER && defined MASKING
 | 
|---|
| 754 |         ELSE
 | 
|---|
| 755 |           start(1)=1+(fourth+Loff-1)*Npts
 | 
|---|
| 756 |           total(1)=Npts
 | 
|---|
| 757 |           start(2)=1
 | 
|---|
| 758 |           total(2)=tindex
 | 
|---|
| 759 | # endif
 | 
|---|
| 760 |         END IF
 | 
|---|
| 761 | # if defined INLINE_2DIO && defined DISTRIBUTE
 | 
|---|
| 762 | !
 | 
|---|
| 763 | !  If appropriate, process 3D data level by level to reduce memory
 | 
|---|
| 764 | !  requirements.
 | 
|---|
| 765 | !
 | 
|---|
| 766 |       DO k=LBk,UBk
 | 
|---|
| 767 |         start(3)=k-Koff+1
 | 
|---|
| 768 |         total(3)=1
 | 
|---|
| 769 | # endif
 | 
|---|
| 770 |         status=nf90_noerr
 | 
|---|
| 771 |         IF (InpThread) THEN
 | 
|---|
| 772 |           status=nf90_get_var(ncid, ncvarid, wrk, start, total)
 | 
|---|
| 773 |           IF (status.eq.nf90_noerr) THEN
 | 
|---|
| 774 |             DO i=1,Npts
 | 
|---|
| 775 |               IF (ABS(wrk(i)).ge.ABS(Aspval)) THEN
 | 
|---|
| 776 |                 wrk(i)=0.0_r8                 ! masked with _FillValue
 | 
|---|
| 777 |               ELSE
 | 
|---|
| 778 |                 wrk(i)=Ascl*(Afactor*wrk(i)+Aoffset)
 | 
|---|
| 779 |                 Amin=MIN(Amin,wrk(i))
 | 
|---|
| 780 |                 Amax=MAX(Amax,wrk(i))
 | 
|---|
| 781 |               END IF
 | 
|---|
| 782 |             END DO
 | 
|---|
| 783 |           END IF
 | 
|---|
| 784 |         END IF
 | 
|---|
| 785 | # ifdef DISTRIBUTE
 | 
|---|
| 786 |         CALL mp_bcasti (ng, model, status)
 | 
|---|
| 787 | # endif
 | 
|---|
| 788 |         IF (FoundError(status, nf90_noerr, __LINE__,                    &
 | 
|---|
| 789 |      &                 __FILE__)) THEN
 | 
|---|
| 790 |           exit_flag=2
 | 
|---|
| 791 |           ioerror=status
 | 
|---|
| 792 |           nf_fread4d=status
 | 
|---|
| 793 |           RETURN
 | 
|---|
| 794 |         END IF
 | 
|---|
| 795 | !
 | 
|---|
| 796 | !-----------------------------------------------------------------------
 | 
|---|
| 797 | !  Serial I/O: Unpack read field.
 | 
|---|
| 798 | !-----------------------------------------------------------------------
 | 
|---|
| 799 | !
 | 
|---|
| 800 | # ifdef DISTRIBUTE
 | 
|---|
| 801 | #  ifdef INLINE_2DIO
 | 
|---|
| 802 |         CALL mp_scatter2d (ng, model, LBi, UBi, LBj, UBj,               &
 | 
|---|
| 803 |      &                     Nghost, MyType, Amin, Amax,                  &
 | 
|---|
| 804 | #   if defined READ_WATER && defined MASKING
 | 
|---|
| 805 |      &                     NWpts, SCALARS(ng)%IJwater(:,wtype),         &
 | 
|---|
| 806 | #   endif
 | 
|---|
| 807 |      &                     Npts, wrk, A(:,:,k,fourth))
 | 
|---|
| 808 |       END DO
 | 
|---|
| 809 | #  else
 | 
|---|
| 810 |         CALL mp_scatter3d (ng, model, LBi, UBi, LBj, UBj, LBk, UBk,     &
 | 
|---|
| 811 |      &                     Nghost, MyType, Amin, Amax,                  &
 | 
|---|
| 812 | #   if defined READ_WATER && defined MASKING
 | 
|---|
| 813 |      &                     NWpts, SCALARS(ng)%IJwater(:,wtype),         &
 | 
|---|
| 814 | #   endif
 | 
|---|
| 815 |      &                     Npts, wrk, A(:,:,:,fourth))
 | 
|---|
| 816 | #  endif
 | 
|---|
| 817 | # else
 | 
|---|
| 818 |         IF (MyType.gt.0) THEN
 | 
|---|
| 819 |           ic=0
 | 
|---|
| 820 |           DO k=LBk,UBk
 | 
|---|
| 821 |             DO j=Jmin,Jmax
 | 
|---|
| 822 |               DO i=Imin,Imax
 | 
|---|
| 823 |                 ic=ic+1
 | 
|---|
| 824 |                 A(i,j,k,fourth)=wrk(ic)
 | 
|---|
| 825 |               END DO
 | 
|---|
| 826 |             END DO
 | 
|---|
| 827 |           END DO
 | 
|---|
| 828 | #  if defined MASKING || defined READ_WATER
 | 
|---|
| 829 |         ELSE
 | 
|---|
| 830 |           ic=0
 | 
|---|
| 831 |           DO k=LBk,UBk
 | 
|---|
| 832 |             DO j=Jmin,Jmax
 | 
|---|
| 833 |               DO i=Imin,Imax
 | 
|---|
| 834 |                 IF (Amask(i,j).gt.0.0_r8) THEN
 | 
|---|
| 835 |                   ic=ic+1
 | 
|---|
| 836 |                   A(i,j,k,fourth)=wrk(ic)
 | 
|---|
| 837 |                 ELSE
 | 
|---|
| 838 |                   A(i,j,k,fourth)=0.0_r8
 | 
|---|
| 839 |                 END IF
 | 
|---|
| 840 |               END DO
 | 
|---|
| 841 |             END DO
 | 
|---|
| 842 |           END DO
 | 
|---|
| 843 | #  endif
 | 
|---|
| 844 |         END IF
 | 
|---|
| 845 | # endif
 | 
|---|
| 846 |       END DO
 | 
|---|
| 847 | 
 | 
|---|
| 848 |       nf_fread4d=status
 | 
|---|
| 849 | 
 | 
|---|
| 850 |       RETURN
 | 
|---|
| 851 |       END FUNCTION nf_fread4d
 | 
|---|
| 852 | #endif
 | 
|---|
| 853 |       END MODULE nf_fread4d_mod
 | 
|---|