Ticket #784: nf_fread4d.F

File nf_fread4d.F, 25.2 KB (added by dwhitt, 6 years ago)
Line 
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