ROMS
Loading...
Searching...
No Matches
nf_fread2d_xtr.F
Go to the documentation of this file.
1#include "cppdefs.h"
3
4#ifdef GRID_EXTRACT
5!
6!git $Id$
7!================================================== Hernan G. Arango ===
8! Copyright (c) 2002-2025 The ROMS Group !
9! Licensed under a MIT/X style license !
10! See License_ROMS.md !
11!=======================================================================
12! !
13! This function reads in a generic floating point 2D array from an !
14! input NetCDF file for field extraction. !
15! !
16! On Input: !
17! !
18! ng Nested grid number (integer) !
19! model Calling model identifier (integer) !
20! ncname NetCDF file name (string) !
21! ncid NetCDF file ID (integer) !
22# if defined PIO_LIB && defined DISTRIBUTE
23!or pioFile PIO file descriptor structure, TYPE(file_desc_t) !
24! pioFile%fh file handler !
25! pioFile%iosystem IO system descriptor (struct) !
26# endif
27! ncvname NetCDF variable name (string) !
28! ncvarid NetCDF variable ID (integer) !
29# if defined PIO_LIB && defined DISTRIBUTE
30!or pioVar PIO variable descriptor structure, TYPE(My_VarDesc) !
31! pioVar%vd variable descriptor TYPE(Var_Desc_t) !
32! pioVar%dkind variable data kind !
33! pioVar%gtype variable C-gridtype !
34# endif
35! tindex NetCDF time record index to read (integer) !
36! gtype C-grid type (integer) !
37# if defined PIO_LIB && defined DISTRIBUTE
38!or pioDesc IO data decomposition descriptor, TYPE(IO_desc_t) !
39# endif
40! Vsize Variable dimensions in NetCDF file (integer 1D array) !
41! LBi I-dimension Lower bound (integer) !
42! UBi I-dimension Upper bound (integer) !
43! LBj J-dimension Lower bound (integer) !
44! UBj J-dimension Upper bound (integer) !
45! Ascl Factor to scale field after reading (real). !
46! Amask Land/Sea mask, if any (real 2D array) !
47! !
48! On Output: !
49! !
50! Amin Field minimum value (real) !
51! Amax Field maximum value (real) !
52! Adat Field to read in (real 2D array) !
53! checksum Field checksum value (integer*8; OPTIONAL) !
54! Lregrid Field regrid interpolation switch (logical; OPTIONAL) !
55! status Result error flag (integer) !
56! !
57!=======================================================================
58!
59 USE mod_param
60 USE mod_parallel
61 USE mod_grid
62 USE mod_iounits
63 USE mod_ncparam
64 USE mod_scalars
65!
66 USE get_hash_mod, ONLY : get_hash
67 USE strings_mod, ONLY : founderror
68!
69 implicit none
70!
71 INTERFACE nf_fread2d_xtr
72 MODULE PROCEDURE nf90_fread2d_xtr
73# if defined PIO_LIB && defined DISTRIBUTE
74 MODULE PROCEDURE pio_fread2d_xtr
75# endif
76 END INTERFACE nf_fread2d_xtr
77!
78 CONTAINS
79
80# if defined PARALLEL_IO && defined DISTRIBUTE
81!
82!***********************************************************************
83 FUNCTION nf90_fread2d_xtr (ng, model, ncname, ncid, &
84 & ncvname, ncvarid, &
85 & tindex, gtype, Vsize, &
86 & LBi, UBi, LBj, UBj, &
87 & Ascl, Amin, Amax, &
88# ifdef MASKING
89 & Amask, &
90# endif
91 & Adat, &
92 & checksum, &
93 & Lregrid) RESULT (status)
94!***********************************************************************
95!
96 USE mod_netcdf
97!
100 USE regrid_mod, ONLY : regrid_nf90
101!
102! Imported variable declarations.
103!
104 logical, intent(out), optional :: Lregrid
105!
106 integer, intent(in) :: ng, model, ncid, ncvarid, tindex, gtype
107 integer, intent(in) :: LBi, UBi, LBj, UBj
108 integer, intent(in) :: Vsize(4)
109!
110 integer(i8b), intent(out), optional :: checksum
111!
112 real(dp), intent(in) :: Ascl
113 real(r8), intent(out) :: Amin
114 real(r8), intent(out) :: Amax
115!
116 character (len=*), intent(in) :: ncname
117 character (len=*), intent(in) :: ncvname
118!
119# ifdef ASSUMED_SHAPE
120# ifdef MASKING
121 real(r8), intent(in) :: Amask(LBi:,LBj:)
122# endif
123 real(r8), intent(out) :: Adat(LBi:,LBj:)
124# else
125# ifdef MASKING
126 real(r8), intent(in) :: Amask(LBi:UBi,LBj:UBj)
127# endif
128 real(r8), intent(out) :: Adat(LBi:UBi,LBj:UBj)
129# endif
130!
131! Local variable declarations.
132!
133 logical :: Lchecksum, interpolate
134!
135 logical, dimension(3) :: foundit
136!
137 integer :: i, ic, ij, j, jc, np, MyNpts, Npts
138 integer :: Imin, Imax, Isize, Jmin, Jmax, Jsize, IJsize
139 integer :: Istr, Iend, Jstr, Jend
140 integer :: Ioff, Joff, IJoff
141 integer :: Ilen, Itile, Jlen, Jtile, IJlen
142 integer :: Cgrid, MyType, ghost, status, wtype
143
144 integer, dimension(3) :: start, total
145!
146 real(r8) :: Afactor, Aoffset, Aspval
147
148 real(r8), parameter :: IniVal = 0.0_r8
149
150 real(r8), dimension(2) :: rbuffer
151 real(r8), dimension(3) :: AttValue
152
153 real(r8), allocatable :: Awrk(:,:)
154# if defined MASKING && defined READ_WATER
155 real(r8), allocatable :: A2d(:)
156# endif
157 real(r8), allocatable :: wrk(:)
158!
159 character (len= 3), dimension(2) :: op_handle
160 character (len=12), dimension(3) :: AttName
161
162 character (len=*), parameter :: MyFile = &
163 & __FILE__//", nf90_fread2d"
164!
165!-----------------------------------------------------------------------
166! Set starting and ending indices to process.
167!-----------------------------------------------------------------------
168!
169 status=nf90_noerr
170!
171! Set first and last grid point according to staggered C-grid
172! classification. Set the offsets for variables with starting
173! zero-index. Recall the NetCDF does not support a zero-index.
174!
175! Notice that (Imin,Jmin) and (Imax,Jmax) are the corner of the
176! computational tile. If ghost=0, ghost points are not processed.
177! They will be processed elsewhere by the appropriate call to any
178! of the routines in "mp_exchange.F". If ghost=1, the ghost points
179! are read.
180!
181# ifdef NO_READ_GHOST
182 ghost=0 ! non-overlapping, no ghost points
183# else
184 IF (model.eq.iadm) THEN
185 ghost=0 ! non-overlapping, no ghost points
186 ELSE
187 ghost=1 ! overlapping, read ghost points
188 END IF
189# endif
190
191 mytype=gtype
192
193 SELECT CASE (abs(mytype))
194 CASE (p2dvar, p3dvar)
195 cgrid=1
196 isize=xtr_iobounds(ng)%xi_psi
197 jsize=xtr_iobounds(ng)%eta_psi
198 CASE (r2dvar, r3dvar)
199 cgrid=2
200 isize=xtr_iobounds(ng)%xi_rho
201 jsize=xtr_iobounds(ng)%eta_rho
202 CASE (u2dvar, u3dvar)
203 cgrid=3
204 isize=xtr_iobounds(ng)%xi_u
205 jsize=xtr_iobounds(ng)%eta_u
206 CASE (v2dvar, v3dvar)
207 cgrid=4
208 isize=xtr_iobounds(ng)%xi_v
209 jsize=xtr_iobounds(ng)%eta_v
210 CASE DEFAULT
211 cgrid=2
212 isize=xtr_iobounds(ng)%xi_rho
213 jsize=xtr_iobounds(ng)%eta_rho
214 END SELECT
215
216 imin=xtr_bounds(ng)%Imin(cgrid,ghost,myrank)
217 imax=xtr_bounds(ng)%Imax(cgrid,ghost,myrank)
218 jmin=xtr_bounds(ng)%Jmin(cgrid,ghost,myrank)
219 jmax=xtr_bounds(ng)%Jmax(cgrid,ghost,myrank)
220
221 ilen=imax-imin+1
222 jlen=jmax-jmin+1
223!
224! Determine if interpolating from coarse gridded data to model grid
225! is required. This is only allowed for gridded 2D fields. This is
226! convenient for atmospheric forcing datasets that are usually on
227! coarser grids. The user can provide coarser gridded data to avoid
228! very large input files.
229!
230 interpolate=.false.
231 IF (((vsize(1).gt.0).and.(vsize(1).ne.isize)).or. &
232 & ((vsize(2).gt.0).and.(vsize(2).ne.jsize))) THEN
233 interpolate=.true.
234 ilen=vsize(1)
235 jlen=vsize(2)
236 END IF
237 IF (PRESENT(lregrid)) THEN
238 lregrid=interpolate
239 END IF
240!
241! Check if the following attributes: "scale_factor", "add_offset", and
242! "_FillValue" are present in the input NetCDF variable:
243!
244! If the "scale_value" attribute is present, the data is multiplied by
245! this factor after reading.
246! If the "add_offset" attribute is present, this value is added to the
247! data after reading.
248! If both "scale_factor" and "add_offset" attributes are present, the
249! data are first scaled before the offset is added.
250! If the "_FillValue" attribute is present, the data having this value
251! is treated as missing and it is replaced with zero. This feature it
252! is usually related with the land/sea masking.
253!
254 attname(1)='scale_factor'
255 attname(2)='add_offset '
256 attname(3)='_FillValue '
257
258 CALL netcdf_get_fatt (ng, model, ncname, ncvarid, attname, &
259 & attvalue, foundit, &
260 & ncid = ncid)
261 IF (founderror(exit_flag, noerror, __line__, myfile)) THEN
262 status=ioerror
263 RETURN
264 END IF
265
266 IF (.not.foundit(1)) THEN
267 afactor=1.0_r8
268 ELSE
269 afactor=attvalue(1)
270 END IF
271
272 IF (.not.foundit(2)) THEN
273 aoffset=0.0_r8
274 ELSE
275 aoffset=attvalue(2)
276 END IF
277
278 IF (.not.foundit(3)) THEN
279 aspval=spval_check
280 ELSE
281 aspval=attvalue(3)
282 END IF
283!
284! Initialize checsum value.
285!
286 IF (PRESENT(checksum)) THEN
287 lchecksum=.true.
288 checksum=0_i8b
289 ELSE
290 lchecksum=.false.
291 END IF
292!
293!-----------------------------------------------------------------------
294! Parallel I/O: Read in tile data from requested field and scale it.
295! Processing both water and land points.
296!-----------------------------------------------------------------------
297!
298 IF (gtype.gt.0) THEN
299!
300! Set offsets due the NetCDF dimensions. Recall that some output
301! variables not always start at one.
302!
303 SELECT CASE (abs(mytype))
304 CASE (p2dvar, p3dvar)
305 ioff=0
306 joff=0
307 CASE (r2dvar, r3dvar)
308 ioff=1
309 joff=1
310 CASE (u2dvar, u3dvar)
311 ioff=0
312 joff=1
313 CASE (v2dvar, v3dvar)
314 ioff=1
315 joff=0
316 CASE DEFAULT
317 ioff=1
318 joff=1
319 END SELECT
320
321 npts=ilen*jlen
322!
323! Allocate scratch work arrays.
324!
325 IF (interpolate) THEN
326 IF (.not.allocated(awrk)) THEN
327 allocate ( awrk(ilen,jlen) )
328 awrk=inival
329 END IF
330 IF (.not.allocated(wrk)) THEN
331 allocate ( wrk(npts) )
332 wrk=inival
333 END IF
334 ELSE
335 IF (.not.allocated(wrk)) THEN
336 allocate ( wrk(tilesize(ng)) )
337 wrk=0.0_r8
338 END IF
339 END IF
340!
341! Read in data: all parallel nodes read their own tile data.
342!
343 IF (interpolate) THEN
344 CALL tile_bounds_2d (ng, myrank, ilen, jlen, itile, jtile, &
345 & istr, iend, jstr, jend)
346 start(1)=istr
347 total(1)=iend-istr+1
348 start(2)=jstr
349 total(2)=jend-jstr+1
350 ELSE
351 start(1)=imin+ioff
352 total(1)=ilen
353 start(2)=jmin+joff
354 total(2)=jlen
355 END IF
356 mynpts=total(1)*total(2)
357 start(3)=tindex
358 total(3)=1
359
360 status=nf90_get_var(ncid, ncvarid, wrk, start, total)
361!
362! Scale read data and process fill values, if any. Compute minimum
363! and maximum values.
364!
365 IF (status.eq.nf90_noerr) THEN
366 amin=spval
367 amax=-spval
368 DO i=1,mynpts
369 IF (abs(wrk(i)).ge.abs(aspval)) THEN
370 wrk(i)=0.0_r8 ! masked with _FillValue
371 ELSE
372 wrk(i)=ascl*(afactor*wrk(i)+aoffset)
373 amin=min(amin,wrk(i))
374 amax=max(amax,wrk(i))
375 END IF
376 END DO
377 IF ((abs(amin).ge.abs(aspval)).and. &
378 & (abs(amax).ge.abs(aspval))) THEN
379 amin=0.0_r8 ! the entire data is all
380 amax=0.0_r8 ! field value, _FillValue
381 END IF
382!
383! Set minimum and maximum values: global reduction.
384!
385 rbuffer(1)=amin
386 op_handle(1)='MIN'
387 rbuffer(2)=amax
388 op_handle(2)='MAX'
389 CALL mp_reduce (ng, model, 2, rbuffer, op_handle)
390 amin=rbuffer(1)
391 amax=rbuffer(2)
392!
393! Unpack read data. If not interpolating, the data is loaded into
394! model array.
395!
396 IF (interpolate) THEN
397 CALL mp_collect (ng, model, npts, inival, wrk)
398 ic=0
399 DO j=jstr,jend
400 DO i=istr,iend
401 ic=ic+1
402 awrk(i,j)=wrk(ic)
403 END DO
404 END DO
405 ELSE
406 ic=0
407 DO j=jmin,jmax
408 DO i=imin,imax
409 ic=ic+1
410 adat(i,j)=wrk(ic)
411 END DO
412 END DO
413 END IF
414 ELSE
415 exit_flag=2
416 ioerror=status
417 END IF
418 END IF
419
420# if defined MASKING && defined READ_WATER
421!
422!-----------------------------------------------------------------------
423! Parallel I/O: Read in tile data from requested field and scale it.
424! Processing water points only. Interpolation is not
425! allowed.
426!-----------------------------------------------------------------------
427!
428 IF (gtype.lt.0) THEN
429!
430! Set number of points to process, grid type switch, and offsets due
431! array packing into 1D array in column-major order.
432!
433 SELECT CASE (abs(mytype))
434 CASE (p2dvar)
435 npts=xtr_iobounds(ng)%xy_psi
436 wtype=p2dvar
437 ioff=0
438 joff=1
439 CASE (r2dvar)
440 npts=xtr_iobounds(ng)%xy_rho
441 wtype=r2dvar
442 ioff=1
443 joff=0
444 CASE (u2dvar)
445 npts=xtr_iobounds(ng)%xy_u
446 wtype=u2dvar
447 ioff=0
448 joff=0
449 CASE (v2dvar)
450 npts=xtr_iobounds(ng)%xy_v
451 wtype=v2dvar
452 ioff=1
453 joff=1
454 CASE DEFAULT
455 npts=xtr_iobounds(ng)%xy_rho
456 wtype=r2dvar
457 ioff=1
458 joff=0
459 END SELECT
460 ijsize=isize*jsize
461!
462! Allocate scratch work arrays.
463!
464 IF (.not.allocated(a2d)) THEN
465 allocate ( a2d(ijsize) )
466 a2d=inival
467 END IF
468 IF (.not.allocated(wrk)) THEN
469 allocate ( wrk(npts) )
470 wrk=inival
471 END IF
472!
473! Read in data: all parallel nodes read a segment of the 1D data.
474! Recall that water points are pack in the NetCDF file in a single
475! dimension.
476!
477 CALL tile_bounds_1d (ng, myrank, npts, istr, iend)
478
479 start(1)=istr
480 total(1)=iend-istr+1
481 start(2)=1
482 total(2)=tindex
483
484 status=nf90_get_var(ncid, ncvarid, wrk(istr:), start, total)
485!
486! Global reduction of work array. We need this because the packing
487! of the water point only affects the model tile partition.
488!
489 IF (status.eq.nf90_noerr) THEN
490 CALL mp_collect (ng, model, npts, inival, wrk)
491!
492! Scale read data and process fill values, if any. Compute minimum
493! and maximum values.
494!
495 amin=spval
496 amax=-spval
497 DO i=1,npts
498 IF (abs(wrk(i)).ge.abs(aspval)) THEN
499 wrk(i)=0.0_r8 ! masked with _FillValue
500 ELSE
501 wrk(i)=ascl*(afactor*wrk(i)+aoffset)
502 amin=min(amin,wrk(i))
503 amax=max(amax,wrk(i))
504 END IF
505 END DO
506 IF ((abs(amin).ge.abs(aspval)).and. &
507 & (abs(amax).ge.abs(aspval))) THEN
508 amin=0.0_r8 ! the entire data is all
509 amax=0.0_r8 ! field value, _FillValue
510 END IF
511!
512! Unpack read data. This is tricky in parallel I/O. The cheapeast
513! thing to do is reconstruct a packed global array and then select
514! the appropriate values for the tile.
515!
516 DO np=1,npts
517 ij=scalars(ng)%IJwater(np,wtype)
518 a2d(ij)=wrk(np)
519 END DO
520
521 DO j=jmin,jmax
522 jc=(j-joff)*isize
523 DO i=imin,imax
524 ij=i+ioff+jc
525 adat(i,j)=a2d(ij)
526 END DO
527 END DO
528 ELSE
529 exit_flag=2
530 ioerror=status
531 END IF
532 END IF
533# endif
534!
535!-----------------------------------------------------------------------
536! Parallel I/O: If interpolating from gridded data, read its associated
537! locations and interpolate.
538!-----------------------------------------------------------------------
539!
540 IF (interpolate.and.(status.eq.nf90_noerr)) THEN
541 SELECT CASE (abs(mytype))
542 CASE (p2dvar, p3dvar)
543 IF (spherical) THEN
544 CALL regrid_nf90 (ng, model, ncname, ncid, &
545 & ncvname, ncvarid, mytype, interpflag, &
546 & ilen, jlen, awrk, amin, amax, &
547 & lbi, ubi, lbj, ubj, &
548 & imin, imax, jmin, jmax, &
549# ifdef MASKING
550 & grid(ng) % pmask, &
551# endif
552 & grid(ng) % MyLon, &
553 & grid(ng) % lonp, &
554 & grid(ng) % latp, &
555 & adat)
556 ELSE
557 CALL regrid_nf90 (ng, model, ncname, ncid, &
558 & ncvname, ncvarid, mytype, interpflag, &
559 & ilen, jlen, awrk, amin, amax, &
560 & lbi, ubi, lbj, ubj, &
561 & imin, imax, jmin, jmax, &
562# ifdef MASKING
563 & grid(ng) % pmask, &
564# endif
565 & grid(ng) % MyLon, &
566 & grid(ng) % xp, &
567 & grid(ng) % yp, &
568 & adat)
569 END IF
570 CASE (r2dvar, r3dvar)
571 IF (spherical) THEN
572 CALL regrid_nf90 (ng, model, ncname, ncid, &
573 & ncvname, ncvarid, mytype, interpflag, &
574 & ilen, jlen, awrk, amin, amax, &
575 & lbi, ubi, lbj, ubj, &
576 & imin, imax, jmin, jmax, &
577# ifdef MASKING
578 & grid(ng) % rmask, &
579# endif
580 & grid(ng) % MyLon, &
581 & grid(ng) % lonr, &
582 & grid(ng) % latr, &
583 & adat)
584 ELSE
585 CALL regrid_nf90 (ng, model, ncname, ncid, &
586 & ncvname, ncvarid, mytype, interpflag, &
587 & ilen, jlen, awrk, amin, amax, &
588 & lbi, ubi, lbj, ubj, &
589 & imin, imax, jmin, jmax, &
590# ifdef MASKING
591 & grid(ng) % rmask, &
592# endif
593 & grid(ng) % MyLon, &
594 & grid(ng) % xr, &
595 & grid(ng) % yr, &
596 & adat)
597 END IF
598 CASE (u2dvar, u3dvar)
599 IF (spherical) THEN
600 CALL regrid_nf90 (ng, model, ncname, ncid, &
601 & ncvname, ncvarid, mytype, interpflag, &
602 & ilen, jlen, awrk, amin, amax, &
603 & lbi, ubi, lbj, ubj, &
604 & imin, imax, jmin, jmax, &
605# ifdef MASKING
606 & grid(ng) % umask, &
607# endif
608 & grid(ng) % MyLon, &
609 & grid(ng) % lonu, &
610 & grid(ng) % latu, &
611 & adat)
612 ELSE
613 CALL regrid_nf90 (ng, model, ncname, ncid, &
614 & ncvname, ncvarid, mytype, interpflag, &
615 & ilen, jlen, awrk, amin, amax, &
616 & lbi, ubi, lbj, ubj, &
617 & imin, imax, jmin, jmax, &
618# ifdef MASKING
619 & grid(ng) % umask, &
620# endif
621 & grid(ng) % MyLon, &
622 & grid(ng) % xu, &
623 & grid(ng) % yu, &
624 & adat)
625 END IF
626 CASE (v2dvar, v3dvar)
627 IF (spherical) THEN
628 CALL regrid_nf90 (ng, model, ncname, ncid, &
629 & ncvname, ncvarid, mytype, interpflag, &
630 & ilen, jlen, awrk, amin, amax, &
631 & lbi, ubi, lbj, ubj, &
632 & imin, imax, jmin, jmax, &
633# ifdef MASKING
634 & grid(ng) % vmask, &
635# endif
636 & grid(ng) % MyLon, &
637 & grid(ng) % lonv, &
638 & grid(ng) % latv, &
639 & adat)
640 ELSE
641 CALL regrid_nf90 (ng, model, ncname, ncid, &
642 & ncvname, ncvarid, mytype, interpflag, &
643 & ilen, jlen, awrk, amin, amax, &
644 & lbi, ubi, lbj, ubj, &
645 & imin, imax, jmin, jmax, &
646# ifdef MASKING
647 & grid(ng) % vmask, &
648# endif
649 & grid(ng) % MyLon, &
650 & grid(ng) % xv, &
651 & grid(ng) % yv, &
652 & adat)
653 END IF
654 CASE DEFAULT
655 IF (spherical) THEN
656 CALL regrid_nf90 (ng, model, ncname, ncid, &
657 & ncvname, ncvarid, mytype, interpflag, &
658 & ilen, jlen, awrk, amin, amax, &
659 & lbi, ubi, lbj, ubj, &
660 & imin, imax, jmin, jmax, &
661# ifdef MASKING
662 & grid(ng) % rmask, &
663# endif
664 & grid(ng) % MyLon, &
665 & grid(ng) % lonr, &
666 & grid(ng) % latr, &
667 & adat)
668 ELSE
669 CALL regrid_nf90 (ng, model, ncname, ncid, &
670 & ncvname, ncvarid, mytype, interpflag, &
671 & ilen, jlen, awrk, amin, amax, &
672 & lbi, ubi, lbj, ubj, &
673 & imin, imax, jmin, jmax, &
674# ifdef MASKING
675 & grid(ng) % rmask, &
676# endif
677 & grid(ng) % MyLon, &
678 & grid(ng) % xr, &
679 & grid(ng) % yr, &
680 & adat)
681 END IF
682 END SELECT
683 END IF
684!
685!-----------------------------------------------------------------------
686! Deallocate scratch work arrays.
687!-----------------------------------------------------------------------
688!
689 IF (interpolate) THEN
690 IF (allocated(awrk)) THEN
691 deallocate ( awrk )
692 END IF
693 END IF
694
695# if defined MASKING && defined READ_WATER
696 IF (allocated(a2d)) THEN
697 deallocate (a2d)
698 END IF
699# endif
700
701 IF (allocated(wrk)) THEN
702 deallocate (wrk)
703 END IF
704!
705 RETURN
706 END FUNCTION nf90_fread2d_xtr
707
708# else
709
710!
711!***********************************************************************
712 FUNCTION nf90_fread2d_xtr (ng, model, ncname, ncid, &
713 & ncvname, ncvarid, &
714 & tindex, gtype, Vsize, &
715 & LBi, UBi, LBj, UBj, &
716 & Ascl, Amin, Amax, &
717# ifdef MASKING
718 & Amask, &
719# endif
720 & Adat, &
721 & checksum, &
722 & Lregrid) RESULT (status)
723!***********************************************************************
724!
725 USE mod_netcdf
726
727# ifdef DISTRIBUTE
728!
729 USE distribute_mod, ONLY : mp_bcastf, mp_bcasti, mp_scatter2d_xtr
730# endif
731 USE regrid_mod, ONLY : regrid_nf90
732!
733! Imported variable declarations.
734!
735 logical, intent(out), optional :: Lregrid
736!
737 integer, intent(in) :: ng, model, ncid, ncvarid, tindex, gtype
738 integer, intent(in) :: LBi, UBi, LBj, UBj
739 integer, intent(in) :: Vsize(4)
740!
741 integer(i8b), intent(out), optional :: checksum
742!
743 real(dp), intent(in) :: Ascl
744 real(r8), intent(out) :: Amin
745 real(r8), intent(out) :: Amax
746!
747 character (len=*), intent(in) :: ncname
748 character (len=*), intent(in) :: ncvname
749!
750# ifdef ASSUMED_SHAPE
751# ifdef MASKING
752 real(r8), intent(in) :: Amask(LBi:,LBj:)
753# endif
754 real(r8), intent(out) :: Adat(LBi:,LBj:)
755# else
756# ifdef MASKING
757 real(r8), intent(in) :: Amask(LBi:UBi,LBj:UBj)
758# endif
759 real(r8), intent(out) :: Adat(LBi:UBi,LBj:UBj)
760# endif
761!
762! Local variable declarations.
763!
764 logical :: Lchecksum, interpolate
765
766 logical, dimension(3) :: foundit
767!
768 integer :: i, j, ic, Npts, NWpts, status, wtype
769 integer :: Is, Ie, Js, Je
770 integer :: Imin, Imax, Jmin, Jmax
771 integer :: Ilen, Jlen, IJlen
772 integer :: Cgrid, MyType, ghost
773# ifdef DISTRIBUTE
774 integer :: Nghost
775# endif
776 integer, dimension(3) :: start, total
777!
778 real(r8) :: Afactor, Aoffset, Aspval
779
780 real(r8), dimension(3) :: AttValue
781
782 real(r8), allocatable :: Cwrk(:) ! used for checksum
783 real(r8), allocatable :: wrk(:)
784!
785 character (len=12), dimension(3) :: AttName
786
787 character (len=*), parameter :: MyFile = &
788 & __FILE__//", nf90_fread2d"
789!
790!-----------------------------------------------------------------------
791! Set starting and ending indices to process.
792!-----------------------------------------------------------------------
793!
794 status=nf90_noerr
795!
796! Set global (interior plus boundary) starting and ending grid cell
797! indices in the I- and J-directions according to staggered C-grid
798! classification.
799!
800 mytype=gtype
801
802 SELECT CASE (abs(mytype))
803 CASE (p2dvar)
804 cgrid=1 ! PSI-points
805 is=xtr_iobounds(ng)%ILB_psi
806 ie=xtr_iobounds(ng)%IUB_psi
807 js=xtr_iobounds(ng)%JLB_psi
808 je=xtr_iobounds(ng)%JUB_psi
809 CASE (r2dvar)
810 cgrid=2 ! RHO-points
811 is=xtr_iobounds(ng)%ILB_rho
812 ie=xtr_iobounds(ng)%IUB_rho
813 js=xtr_iobounds(ng)%JLB_rho
814 je=xtr_iobounds(ng)%JUB_rho
815 CASE (u2dvar)
816 cgrid=3 ! U-points
817 is=xtr_iobounds(ng)%ILB_u
818 ie=xtr_iobounds(ng)%IUB_u
819 js=xtr_iobounds(ng)%JLB_u
820 je=xtr_iobounds(ng)%JUB_u
821 CASE (v2dvar)
822 cgrid=4 ! V-points
823 is=xtr_iobounds(ng)%ILB_v
824 ie=xtr_iobounds(ng)%IUB_v
825 js=xtr_iobounds(ng)%JLB_v
826 je=xtr_iobounds(ng)%JUB_v
827 CASE DEFAULT
828 cgrid=2 ! RHO-points
829 is=xtr_iobounds(ng)%ILB_rho
830 ie=xtr_iobounds(ng)%IUB_rho
831 js=xtr_iobounds(ng)%JLB_rho
832 je=xtr_iobounds(ng)%JUB_rho
833 END SELECT
834
835 ilen=ie-is+1
836 jlen=je-js+1
837!
838! Set the tile computational I- and J-bounds (no ghost points).
839!
840 ghost=0
841 imin=xtr_bounds(ng)%Imin(cgrid,ghost,myrank)
842 imax=xtr_bounds(ng)%Imax(cgrid,ghost,myrank)
843 jmin=xtr_bounds(ng)%Jmin(cgrid,ghost,myrank)
844 jmax=xtr_bounds(ng)%Jmax(cgrid,ghost,myrank)
845
846# ifdef DISTRIBUTE
847!
848! Set the number of tile ghost points, Nghost, to scatter in
849! distributed-memory applications. If Nghost=0, the ghost points
850! are not processed. They will be processed elsewhere by the
851! appropriate call to any of the routines in "mp_exchange.F".
852!
853# ifdef NO_READ_GHOST
854 nghost=0 ! no ghost points exchange
855# else
856 IF (model.eq.iadm) THEN
857 nghost=0 ! no ghost points exchange
858 ELSE
859 nghost=nghostpoints ! do ghost points exchange
860 END IF
861# endif
862# endif
863!
864! Determine if interpolating from coarse gridded data to model grid
865! is required. This is only allowed for gridded 2D fields. This is
866! convenient for atmospheric forcing datasets that are usually on
867! coarser grids. The user can provide coarser gridded data to avoid
868! very large input files.
869!
870 interpolate=.false.
871 IF (((vsize(1).gt.0).and.(vsize(1).ne.ilen)).or. &
872 & ((vsize(2).gt.0).and.(vsize(2).ne.jlen))) THEN
873 interpolate=.true.
874 ilen=vsize(1)
875 jlen=vsize(2)
876 END IF
877 IF (PRESENT(lregrid)) THEN
878 lregrid=interpolate
879 END IF
880 ijlen=ilen*jlen
881!
882! Check if the following attributes: "scale_factor", "add_offset", and
883! "_FillValue" are present in the input NetCDF variable:
884!
885! If the "scale_value" attribute is present, the data is multiplied by
886! this factor after reading.
887! If the "add_offset" attribute is present, this value is added to the
888! data after reading.
889! If both "scale_factor" and "add_offset" attributes are present, the
890! data are first scaled before the offset is added.
891! If the "_FillValue" attribute is present, the data having this value
892! is treated as missing and it is replaced with zero. This feature it
893! is usually related with the land/sea masking.
894!
895 attname(1)='scale_factor'
896 attname(2)='add_offset '
897 attname(3)='_FillValue '
898
899 CALL netcdf_get_fatt (ng, model, ncname, ncvarid, attname, &
900 & attvalue, foundit, &
901 & ncid = ncid)
902 IF (founderror(exit_flag, noerror, __line__, myfile)) THEN
903 status=ioerror
904 RETURN
905 END IF
906
907 IF (.not.foundit(1)) THEN
908 afactor=1.0_r8
909 ELSE
910 afactor=attvalue(1)
911 END IF
912
913 IF (.not.foundit(2)) THEN
914 aoffset=0.0_r8
915 ELSE
916 aoffset=attvalue(2)
917 END IF
918
919 IF (.not.foundit(3)) THEN
920 aspval=spval_check
921 ELSE
922 aspval=attvalue(3)
923 END IF
924
925# if defined READ_WATER && defined MASKING
926!
927! If processing water points only, set number of points and type
928! switch.
929!
930 SELECT CASE (abs(mytype))
931 CASE (p2dvar)
932 npts=xtr_iobounds(ng)%xy_psi
933 wtype=p2dvar
934 CASE (r2dvar)
935 npts=xtr_iobounds(ng)%xy_rho
936 wtype=r2dvar
937 CASE (u2dvar)
938 npts=xtr_iobounds(ng)%xy_u
939 wtype=u2dvar
940 CASE (v2dvar)
941 npts=xtr_iobounds(ng)%xy_v
942 wtype=v2dvar
943 CASE DEFAULT
944 npts=xtr_iobounds(ng)%xy_rho
945 wtype=r2dvar
946 END SELECT
947 nwpts=(lm(ng)+2)*(mm(ng)+2)
948# endif
949!
950! Set NetCDF dimension counters for processing requested field.
951!
952 IF (mytype.gt.0) THEN
953 npts=ijlen
954 start(1)=1
955 total(1)=ilen
956 start(2)=1
957 total(2)=jlen
958 start(3)=tindex
959 total(3)=1
960# if defined READ_WATER && defined MASKING
961 ELSE
962 start(1)=1
963 total(1)=npts
964 start(2)=1
965 total(2)=tindex
966# endif
967 END IF
968!
969! Allocate scratch work vector. The dimension of this vector is
970! unknown when interpolating input data to model grid. Notice
971! that the array length is increased by two because the minimum
972! and maximum values are appended in distributed-memory
973! communications.
974!
975 IF (.not.allocated(wrk)) THEN
976 IF (interpolate) THEN
977 allocate ( wrk(npts) )
978 ELSE
979 allocate ( wrk(npts+2) )
980 END IF
981 wrk=0.0_r8
982 END IF
983!
984! Initialize checsum value.
985!
986 IF (PRESENT(checksum)) THEN
987 lchecksum=.true.
988 checksum=0_i8b
989 ELSE
990 lchecksum=.false.
991 END IF
992!
993!-----------------------------------------------------------------------
994! Serial I/O: Read in requested field and scale it.
995!-----------------------------------------------------------------------
996!
997 status=nf90_noerr
998 IF (inpthread) THEN
999 status=nf90_get_var(ncid, ncvarid, wrk, start, total)
1000 IF (status.eq.nf90_noerr) THEN
1001 amin=spval
1002 amax=-spval
1003 DO i=1,npts
1004 IF (abs(wrk(i)).ge.abs(aspval)) THEN
1005 wrk(i)=0.0_r8 ! masked with _FillValue
1006 ELSE
1007 wrk(i)=ascl*(afactor*wrk(i)+aoffset)
1008 amin=min(amin,wrk(i))
1009 amax=max(amax,wrk(i))
1010 END IF
1011 END DO
1012 IF ((abs(amin).ge.abs(aspval)).and. &
1013 & (abs(amax).ge.abs(aspval))) THEN
1014 amin=0.0_r8 ! the entire data is all
1015 amax=0.0_r8 ! field value, _FillValue
1016 END IF
1017 END IF
1018 END IF
1019# ifdef DISTRIBUTE
1020 CALL mp_bcasti (ng, model, status)
1021# endif
1022 IF (founderror(status, nf90_noerr, __line__, myfile)) THEN
1023 exit_flag=2
1024 ioerror=status
1025 RETURN
1026 END IF
1027!
1028!-----------------------------------------------------------------------
1029! Serial I/O: If not interpolating, unpack read field.
1030!-----------------------------------------------------------------------
1031!
1032 IF (.not.interpolate) THEN
1033# ifdef DISTRIBUTE
1034!
1035! Scatter read data over the distributed memory tiles.
1036!
1037 CALL mp_scatter2d_xtr (ng, model, lbi, ubi, lbj, ubj, &
1038 & nghost, mytype, amin, amax, &
1039# if defined READ_WATER && defined MASKING
1040 & nwpts, scalars(ng)%IJwater(:,wtype), &
1041# endif
1042 & npts, wrk, adat)
1043# else
1044!
1045! Unpack data into the global array: serial, serial with partitions,
1046! and shared-memory applications.
1047!
1048 IF (mytype.gt.0) THEN
1049 ic=0
1050 DO j=js,je
1051 DO i=is,ie
1052 ic=ic+1
1053 adat(i,j)=wrk(ic)
1054 END DO
1055 END DO
1056# if defined MASKING || defined READ_WATER
1057 ELSE
1058 ic=0
1059 DO j=js,je
1060 DO i=is,ie
1061 IF (amask(i,j).gt.0.0_r8) THEN
1062 ic=ic+1
1063 adat(i,j)=wrk(ic)
1064 ELSE
1065 adat(i,j)=0.0_r8
1066 END IF
1067 END DO
1068 END DO
1069# endif
1070 END IF
1071# endif
1072# ifdef DISTRIBUTE
1073 ELSE
1074 CALL mp_bcastf (ng, model, wrk)
1075# endif
1076 END IF
1077!
1078!-----------------------------------------------------------------------
1079! Serial I/O: If interpolating from gridded data, read its associated
1080! locations and interpolate.
1081!-----------------------------------------------------------------------
1082!
1083 IF (interpolate) THEN
1084 SELECT CASE (abs(mytype))
1085 CASE (p2dvar, p3dvar)
1086 IF (spherical) THEN
1087 CALL regrid_nf90 (ng, model, ncname, ncid, &
1088 & ncvname, ncvarid, mytype, interpflag, &
1089 & ilen, jlen, wrk, amin, amax, &
1090 & lbi, ubi, lbj, ubj, &
1091 & is, ie, js, je, &
1092# ifdef MASKING
1093 & amask, &
1094# endif
1095 & grid(ng) % MyLon, &
1096 & grid(ng) % lonp, &
1097 & grid(ng) % latp, &
1098 & adat)
1099 ELSE
1100 CALL regrid_nf90 (ng, model, ncname, ncid, &
1101 & ncvname, ncvarid, mytype, interpflag, &
1102 & ilen, jlen, wrk, amin, amax, &
1103 & lbi, ubi, lbj, ubj, &
1104 & is, ie, js, je, &
1105# ifdef MASKING
1106 & amask, &
1107# endif
1108 & grid(ng) % MyLon, &
1109 & grid(ng) % xp, &
1110 & grid(ng) % yp, &
1111 & adat)
1112 END IF
1113 CASE (r2dvar, r3dvar)
1114 IF (spherical) THEN
1115 CALL regrid_nf90 (ng, model, ncname, ncid, &
1116 & ncvname, ncvarid, mytype, interpflag, &
1117 & ilen, jlen, wrk, amin, amax, &
1118 & lbi, ubi, lbj, ubj, &
1119 & is, ie, js, je, &
1120# ifdef MASKING
1121 & grid(ng) % rmask, &
1122# endif
1123 & grid(ng) % MyLon, &
1124 & grid(ng) % lonr, &
1125 & grid(ng) % latr, &
1126 & adat)
1127 ELSE
1128 CALL regrid_nf90 (ng, model, ncname, ncid, &
1129 & ncvname, ncvarid, mytype, interpflag, &
1130 & ilen, jlen, wrk, amin, amax, &
1131 & lbi, ubi, lbj, ubj, &
1132 & is, ie, js, je, &
1133# ifdef MASKING
1134 & grid(ng) % rmask, &
1135# endif
1136 & grid(ng) % MyLon, &
1137 & grid(ng) % xr, &
1138 & grid(ng) % yr, &
1139 & adat)
1140 END IF
1141 CASE (u2dvar, u3dvar)
1142 IF (spherical) THEN
1143 CALL regrid_nf90 (ng, model, ncname, ncid, &
1144 & ncvname, ncvarid, mytype, interpflag, &
1145 & ilen, jlen, wrk, amin, amax, &
1146 & lbi, ubi, lbj, ubj, &
1147 & is, ie, js, je, &
1148# ifdef MASKING
1149 & grid(ng) % umask, &
1150# endif
1151 & grid(ng) % MyLon, &
1152 & grid(ng) % lonu, &
1153 & grid(ng) % latu, &
1154 & adat)
1155 ELSE
1156 CALL regrid_nf90 (ng, model, ncname, ncid, &
1157 & ncvname, ncvarid, mytype, interpflag, &
1158 & ilen, jlen, wrk, amin, amax, &
1159 & lbi, ubi, lbj, ubj, &
1160 & is, ie, js, je, &
1161# ifdef MASKING
1162 & grid(ng) % umask, &
1163# endif
1164 & grid(ng) % MyLon, &
1165 & grid(ng) % xu, &
1166 & grid(ng) % yu, &
1167 & adat)
1168 END IF
1169 CASE (v2dvar, v3dvar)
1170 IF (spherical) THEN
1171 CALL regrid_nf90 (ng, model, ncname, ncid, &
1172 & ncvname, ncvarid, mytype, interpflag, &
1173 & ilen, jlen, wrk, amin, amax, &
1174 & lbi, ubi, lbj, ubj, &
1175 & is, ie, js, je, &
1176# ifdef MASKING
1177 & grid(ng) % vmask, &
1178# endif
1179 & grid(ng) % MyLon, &
1180 & grid(ng) % lonv, &
1181 & grid(ng) % latv, &
1182 & adat)
1183 ELSE
1184 CALL regrid_nf90 (ng, model, ncname, ncid, &
1185 & ncvname, ncvarid, mytype, interpflag, &
1186 & ilen, jlen, wrk, amin, amax, &
1187 & lbi, ubi, lbj, ubj, &
1188 & is, ie, js, je, &
1189# ifdef MASKING
1190 & grid(ng) % vmask, &
1191# endif
1192 & grid(ng) % MyLon, &
1193 & grid(ng) % xv, &
1194 & grid(ng) % yv, &
1195 & adat)
1196 END IF
1197 CASE DEFAULT
1198 IF (spherical) THEN
1199 CALL regrid_nf90 (ng, model, ncname, ncid, &
1200 & ncvname, ncvarid, mytype, interpflag, &
1201 & ilen, jlen, wrk, amin, amax, &
1202 & lbi, ubi, lbj, ubj, &
1203 & is, ie, js, je, &
1204# ifdef MASKING
1205 & grid(ng) % rmask, &
1206# endif
1207 & grid(ng) % MyLon, &
1208 & grid(ng) % lonr, &
1209 & grid(ng) % latr, &
1210 & adat)
1211 ELSE
1212 CALL regrid_nf90 (ng, model, ncname, ncid, &
1213 & ncvname, ncvarid, mytype, interpflag, &
1214 & ilen, jlen, wrk, amin, amax, &
1215 & lbi, ubi, lbj, ubj, &
1216 & is, ie, js, je, &
1217# ifdef MASKING
1218 & grid(ng) % rmask, &
1219# endif
1220 & grid(ng) % MyLon, &
1221 & grid(ng) % xr, &
1222 & grid(ng) % yr, &
1223 & adat)
1224 END IF
1225 END SELECT
1226 END IF
1227!
1228!-----------------------------------------------------------------------
1229! If requested, compute data checksum value.
1230!-----------------------------------------------------------------------
1231!
1232 IF (lchecksum) THEN
1233# ifdef DISTRIBUTE
1234 npts=(imax-imin+1)*(jmax-jmin+1)
1235 IF (.not.allocated(cwrk)) allocate ( cwrk(npts) )
1236 cwrk = pack(adat(imin:imax, jmin:jmax), .true.)
1237 CALL get_hash (cwrk, npts, checksum, .true.)
1238# else
1239 npts=(ie-is+1)*(je-js+1)
1240 IF (.not.allocated(cwrk)) allocate ( cwrk(npts) )
1241 cwrk = pack(adat(is:ie, js:je), .true.)
1242 CALL get_hash (cwrk, npts, checksum)
1243# endif
1244 IF (allocated(cwrk)) deallocate (cwrk)
1245 END IF
1246!
1247!-----------------------------------------------------------------------
1248! Deallocate scratch work vector.
1249!-----------------------------------------------------------------------
1250!
1251 IF (allocated(wrk)) THEN
1252 deallocate (wrk)
1253 END IF
1254!
1255 RETURN
1256 END FUNCTION nf90_fread2d_xtr
1257# endif
1258
1259# if defined PIO_LIB && defined DISTRIBUTE
1260!
1261!***********************************************************************
1262 FUNCTION pio_fread2d_xtr (ng, model, ncname, pioFile, &
1263 & ncvname, pioVar, &
1264 & tindex, pioDesc, Vsize, &
1265 & LBi, UBi, LBj, UBj, &
1266 & Ascl, Amin, Amax, &
1267# ifdef MASKING
1268 & Amask, &
1269# endif
1270 & Adat, &
1271 & checksum, &
1272 & Lregrid) RESULT (status)
1273!***********************************************************************
1274!
1275 USE mod_pio_netcdf
1276!
1277 USE distribute_mod, ONLY : mp_reduce
1278 USE regrid_mod, ONLY : regrid_pio
1279!
1280! Imported variable declarations.
1281!
1282 logical, intent(out), optional :: Lregrid
1283!
1284 integer, intent(in) :: ng, model, tindex
1285 integer, intent(in) :: LBi, UBi, LBj, UBj
1286 integer, intent(in) :: Vsize(4)
1287!
1288 integer(i8b), intent(out), optional :: checksum
1289!
1290 real(dp), intent(in) :: Ascl
1291 real(r8), intent(out) :: Amin
1292 real(r8), intent(out) :: Amax
1293!
1294 character (len=*), intent(in) :: ncname
1295 character (len=*), intent(in) :: ncvname
1296!
1297# ifdef ASSUMED_SHAPE
1298# ifdef MASKING
1299 real(r8), intent(in) :: Amask(LBi:,LBj:)
1300# endif
1301 real(r8), intent(out) :: Adat(LBi:,LBj:)
1302# else
1303# ifdef MASKING
1304 real(r8), intent(in) :: Amask(LBi:UBi,LBj:UBj)
1305# endif
1306 real(r8), intent(out) :: Adat(LBi:UBi,LBj:UBj)
1307# endif
1308!
1309 TYPE (File_desc_t), intent(inout) :: pioFile
1310 TYPE (IO_Desc_t), intent(inout) :: pioDesc
1311 TYPE (My_VarDesc), intent(inout) :: pioVar
1312!
1313! Local variable declarations.
1314!
1315 logical :: Lchecksum, interpolate
1316
1317 logical, dimension(3) :: foundit
1318!
1319 integer :: i, j, Npts, status
1320 integer :: Is, Ie, Js, Je ! global bounds
1321 integer :: Imin, Imax, Jmin, Jmax ! tile bounds
1322 integer :: Ilen, Jlen, IJlen
1323 integer :: Cgrid, ghost, dkind, gtype
1324
1325 integer, dimension(3) :: start, total
1326!
1327 real(r8) :: Afactor, Aoffset, Aspval, Avalue
1328 real(r8) :: my_Amin, my_Amax
1329
1330 real(r8), dimension(3) :: AttValue
1331 real(r8), dimension(2) :: rbuffer
1332!
1333 real(r4), pointer :: Awrk4(:,:) ! single precision
1334 real(r8), pointer :: Awrk8(:,:) ! double precision
1335 real(r8), allocatable :: Cwrk(:) ! used for checksum
1336 real(r8), allocatable :: wrk(:,:) ! interpolating, regrid
1337!
1338 character (len=12), dimension(3) :: AttName
1339 character (len= 3), dimension(2) :: op_handle
1340
1341 character (len=*), parameter :: MyFile = &
1342 & __FILE__//", pio_fread2d"
1343!
1344!-----------------------------------------------------------------------
1345! Set starting and ending indices to process.
1346!-----------------------------------------------------------------------
1347!
1348 status=pio_noerr
1349 amin=spval
1350 amax=-spval
1351 my_amin=spval
1352 my_amax=-spval
1353!
1354! Set global (interior plus boundary) starting and ending grid cell
1355! indices in the I- and J-directions according to staggered C-grid
1356! classification.
1357!
1358 dkind=piovar%dkind
1359 gtype=piovar%gtype
1360!
1361 SELECT CASE (abs(gtype))
1362 CASE (p2dvar, p3dvar)
1363 cgrid=1 ! PSI-points
1364 is=xtr_iobounds(ng)%ILB_psi
1365 ie=xtr_iobounds(ng)%IUB_psi
1366 js=xtr_iobounds(ng)%JLB_psi
1367 je=xtr_iobounds(ng)%JUB_psi
1368 CASE (r2dvar, r3dvar)
1369 cgrid=2 ! RHO-points
1370 is=xtr_iobounds(ng)%ILB_rho
1371 ie=xtr_iobounds(ng)%IUB_rho
1372 js=xtr_iobounds(ng)%JLB_rho
1373 je=xtr_iobounds(ng)%JUB_rho
1374 CASE (u2dvar, u3dvar)
1375 cgrid=3 ! U-points
1376 is=xtr_iobounds(ng)%ILB_u
1377 ie=xtr_iobounds(ng)%IUB_u
1378 js=xtr_iobounds(ng)%JLB_u
1379 je=xtr_iobounds(ng)%JUB_u
1380 CASE (v2dvar, v3dvar)
1381 cgrid=4 ! V-points
1382 is=xtr_iobounds(ng)%ILB_v
1383 ie=xtr_iobounds(ng)%IUB_v
1384 js=xtr_iobounds(ng)%JLB_v
1385 je=xtr_iobounds(ng)%JUB_v
1386 CASE DEFAULT
1387 cgrid=2 ! RHO-points
1388 is=xtr_iobounds(ng)%ILB_rho
1389 ie=xtr_iobounds(ng)%IUB_rho
1390 js=xtr_iobounds(ng)%JLB_rho
1391 je=xtr_iobounds(ng)%JUB_rho
1392 END SELECT
1393!
1394! Compute the global lengths of the I- and J-directions. They are
1395! needed to check if regridding is required.
1396!
1397 ilen=ie-is+1
1398 jlen=je-js+1
1399!
1400! Set the tile computational I- and J-bounds (no ghost points).
1401!
1402 ghost=0
1403 imin=xtr_bounds(ng)%Imin(cgrid,ghost,myrank)
1404 imax=xtr_bounds(ng)%Imax(cgrid,ghost,myrank)
1405 jmin=xtr_bounds(ng)%Jmin(cgrid,ghost,myrank)
1406 jmax=xtr_bounds(ng)%Jmax(cgrid,ghost,myrank)
1407!
1408! Determine if interpolating from coarse gridded data to model grid
1409! is required. This is only allowed for gridded 2D fields. This is
1410! convenient for atmospheric forcing datasets that are usually on
1411! coarser grids. The user can provide coarser gridded data to avoid
1412! very large input files.
1413!
1414 interpolate=.false.
1415 IF (((vsize(1).gt.0).and.(vsize(1).ne.ilen)).or. &
1416 & ((vsize(2).gt.0).and.(vsize(2).ne.jlen))) THEN
1417 interpolate=.true.
1418 ilen=vsize(1) ! data and state variable are incongruent
1419 jlen=vsize(2) ! horizontal interpolation is required
1420 END IF
1421 IF (PRESENT(lregrid)) THEN
1422 lregrid=interpolate
1423 END IF
1424 ijlen=ilen*jlen
1425!
1426! Check if the following attributes: "scale_factor", "add_offset", and
1427! "_FillValue" are present in the input NetCDF variable:
1428!
1429! If the "scale_value" attribute is present, the data is multiplied by
1430! this factor after reading.
1431! If the "add_offset" attribute is present, this value is added to the
1432! data after reading.
1433! If both "scale_factor" and "add_offset" attributes are present, the
1434! data are first scaled before the offset is added.
1435! If the "_FillValue" attribute is present, the data having this value
1436! is treated as missing and it is replaced with zero. This feature it
1437! is usually related with the land/sea masking.
1438!
1439 attname(1)='scale_factor'
1440 attname(2)='add_offset '
1441 attname(3)='_FillValue '
1442
1443 CALL pio_netcdf_get_fatt (ng, model, ncname, piovar%vd, attname, &
1444 & attvalue, foundit, &
1445 & piofile = piofile)
1446 IF (founderror(exit_flag, noerror, __line__, myfile)) THEN
1447 status=ioerror
1448 RETURN
1449 END IF
1450
1451 IF (.not.foundit(1)) THEN
1452 afactor=1.0_r8
1453 ELSE
1454 afactor=attvalue(1)
1455 END IF
1456
1457 IF (.not.foundit(2)) THEN
1458 aoffset=0.0_r8
1459 ELSE
1460 aoffset=attvalue(2)
1461 END IF
1462
1463 IF (.not.foundit(3)) THEN
1464 aspval=spval_check
1465 ELSE
1466 aspval=attvalue(3)
1467 END IF
1468!
1469!-----------------------------------------------------------------------
1470! If interpolting, read in input data with the non-tiled PIO interface.
1471!-----------------------------------------------------------------------
1472!
1473 IF (interpolate) THEN
1474 IF (.not.allocated(wrk)) THEN
1475 allocate ( wrk(ilen,jlen) )
1476 END IF
1477 wrk=0.0_r8
1478!
1479 start(1)=1
1480 total(1)=ilen
1481 start(2)=1
1482 total(2)=jlen
1483 start(3)=tindex
1484 total(3)=1
1485!
1486! The generic routine "pio_netcdf_get_fvar" checks if the attributes
1487! "scale_factor", "add_offset", and "_FillValue" are present in the
1488! input NetCDF variable and it applies its operators.
1489!
1490 CALL pio_netcdf_get_fvar (ng, model, ncname, &
1491 & ncvname, wrk, &
1492 & piofile = piofile, &
1493 & start = start, &
1494 & total = total, &
1495 & broadcast = .false., &
1496 & min_val = amin, &
1497 & max_val = amax)
1498!
1499! Multipy by user metadata scale.
1500!
1501 DO j=1,jlen
1502 DO i=1,ilen
1503 wrk(i,j)=ascl*wrk(i,j)
1504 END DO
1505 END DO
1506 END IF
1507!
1508! Initialize checsum value.
1509!
1510 IF (PRESENT(checksum)) THEN
1511 lchecksum=.true.
1512 checksum=0_i8b
1513 ELSE
1514 lchecksum=.false.
1515 END IF
1516!
1517!-----------------------------------------------------------------------
1518! If not interpolated, read in requested tiled field and scale it.
1519!-----------------------------------------------------------------------
1520!
1521 IF (.not.interpolate) THEN
1522!
1523! Allocate and initialize local array used for reading. The local array
1524! needs to be of the same precision as "A" and its IO decomposition
1525! descriptor "pioDesc".
1526!
1527 IF (dkind.eq.pio_double) THEN ! double precision
1528 IF (.not.associated(awrk8)) THEN
1529 allocate ( awrk8(imin:imax, jmin:jmax) )
1530 END IF
1531 awrk8=0.0_r8
1532 ELSE ! single precision
1533 IF (.not.associated(awrk4)) THEN
1534 allocate ( awrk4(imin:imax, jmin:jmax) )
1535 END IF
1536 awrk4=0.0_r4
1537 END IF
1538!
1539! Set unlimited time dimension record to write, if any.
1540!
1541 IF (tindex.gt.0) THEN
1542 CALL pio_setframe (piofile, &
1543 & piovar%vd, &
1544 & int(tindex, kind=pio_offset_kind))
1545 END IF
1546!
1547! Read in and load double precision data from NetCDF file.
1548!
1549 IF (dkind.eq.pio_double) THEN
1550 CALL pio_read_darray (piofile, &
1551 & piovar%vd, &
1552 & piodesc, &
1553 & awrk8(imin:,jmin:), &
1554 & status)
1555!
1556 DO j=jmin,jmax
1557 DO i=imin,imax
1558 IF (abs(awrk8(i,j)).ge.abs(aspval)) THEN
1559 adat(i,j)=0.0_r8 ! masked with _FillValue
1560 ELSE
1561 avalue=ascl*(afactor*awrk8(i,j)+aoffset)
1562 adat(i,j)=avalue
1563 my_amin=min(my_amin,avalue)
1564 my_amax=max(my_amax,avalue)
1565 END IF
1566 END DO
1567 END DO
1568 IF (associated(awrk8)) deallocate (awrk8)
1569!
1570! Read in and load single precision data from NetCDF file.
1571!
1572 ELSE
1573 CALL pio_read_darray (piofile, &
1574 & piovar%vd, &
1575 & piodesc, &
1576 & awrk4(imin:,jmin:), &
1577 & status)
1578!
1579 DO j=jmin,jmax
1580 DO i=imin,imax
1581 IF (abs(awrk4(i,j)).ge.abs(real(aspval,r4))) THEN
1582 adat(i,j)=0.0_r8 ! masked with _FillValue
1583 ELSE
1584 avalue=real(ascl*(afactor*awrk4(i,j)+aoffset),r8)
1585 adat(i,j)=avalue
1586 my_amin=real(min(my_amin,avalue),r8)
1587 my_amax=real(max(my_amax,avalue),r8)
1588 END IF
1589 END DO
1590 END DO
1591 IF (associated(awrk4)) deallocate (awrk4)
1592 END IF
1593!
1594! Compute global minimum and maximum values.
1595!
1596 rbuffer(1)=my_amin
1597 rbuffer(2)=my_amax
1598 op_handle(1)='MIN'
1599 op_handle(2)='MAX'
1600 CALL mp_reduce (ng, model, 2, rbuffer, op_handle)
1601 amin=rbuffer(1)
1602 amax=rbuffer(2)
1603!
1604 IF ((abs(amin).ge.abs(spval)).and. &
1605 & (abs(amax).ge.abs(spval))) THEN
1606 amin=0.0_r8 ! the entire data is all
1607 amax=0.0_r8 ! field value, _FillValue
1608 END IF ! and was zeroth out
1609 END IF
1610!
1611!-----------------------------------------------------------------------
1612! If interpolating from gridded data, read its associated locations
1613! and interpolate.
1614!-----------------------------------------------------------------------
1615!
1616 IF (interpolate) THEN
1617 SELECT CASE (gtype)
1618 CASE (p2dvar, p3dvar)
1619 IF (spherical) THEN
1620 CALL regrid_pio (ng, model, ncname, piofile, &
1621 & ncvname, piovar, gtype, interpflag, &
1622 & ilen, jlen, wrk, amin, amax, &
1623 & lbi, ubi, lbj, ubj, &
1624 & imin, imax, jmin, jmax, &
1625# ifdef MASKING
1626 & amask, &
1627# endif
1628 & grid(ng) % MyLon, &
1629 & grid(ng) % lonp, &
1630 & grid(ng) % latp, &
1631 & adat)
1632 ELSE
1633 CALL regrid_pio (ng, model, ncname, piofile, &
1634 & ncvname, piovar, gtype, interpflag, &
1635 & ilen, jlen, wrk, amin, amax, &
1636 & lbi, ubi, lbj, ubj, &
1637 & imin, imax, jmin, jmax, &
1638# ifdef MASKING
1639 & amask, &
1640# endif
1641 & grid(ng) % MyLon, &
1642 & grid(ng) % xp, &
1643 & grid(ng) % yp, &
1644 & adat)
1645 END IF
1646 CASE (r2dvar, r3dvar)
1647 IF (spherical) THEN
1648 CALL regrid_pio (ng, model, ncname, piofile, &
1649 & ncvname, piovar, gtype, interpflag, &
1650 & ilen, jlen, wrk, amin, amax, &
1651 & lbi, ubi, lbj, ubj, &
1652 & imin, imax, jmin, jmax, &
1653# ifdef MASKING
1654 & grid(ng) % rmask, &
1655# endif
1656 & grid(ng) % MyLon, &
1657 & grid(ng) % lonr, &
1658 & grid(ng) % latr, &
1659 & adat)
1660 ELSE
1661 CALL regrid_pio (ng, model, ncname, piofile, &
1662 & ncvname, piovar, gtype, interpflag, &
1663 & ilen, jlen, wrk, amin, amax, &
1664 & lbi, ubi, lbj, ubj, &
1665 & imin, imax, jmin, jmax, &
1666# ifdef MASKING
1667 & grid(ng) % rmask, &
1668# endif
1669 & grid(ng) % MyLon, &
1670 & grid(ng) % xr, &
1671 & grid(ng) % yr, &
1672 & adat)
1673 END IF
1674 CASE (u2dvar, u3dvar)
1675 IF (spherical) THEN
1676 CALL regrid_pio (ng, model, ncname, piofile, &
1677 & ncvname, piovar, gtype, interpflag, &
1678 & ilen, jlen, wrk, amin, amax, &
1679 & lbi, ubi, lbj, ubj, &
1680 & imin, imax, jmin, jmax, &
1681# ifdef MASKING
1682 & grid(ng) % umask, &
1683# endif
1684 & grid(ng) % MyLon, &
1685 & grid(ng) % lonu, &
1686 & grid(ng) % latu, &
1687 & adat)
1688 ELSE
1689 CALL regrid_pio (ng, model, ncname, piofile, &
1690 & ncvname, piovar, gtype, interpflag, &
1691 & ilen, jlen, wrk, amin, amax, &
1692 & lbi, ubi, lbj, ubj, &
1693 & imin, imax, jmin, jmax, &
1694# ifdef MASKING
1695 & grid(ng) % umask, &
1696# endif
1697 & grid(ng) % MyLon, &
1698 & grid(ng) % xu, &
1699 & grid(ng) % yu, &
1700 & adat)
1701 END IF
1702 CASE (v2dvar, v3dvar)
1703 IF (spherical) THEN
1704 CALL regrid_pio (ng, model, ncname, piofile, &
1705 & ncvname, piovar, gtype, interpflag, &
1706 & ilen, jlen, wrk, amin, amax, &
1707 & lbi, ubi, lbj, ubj, &
1708 & imin, imax, jmin, jmax, &
1709# ifdef MASKING
1710 & grid(ng) % vmask, &
1711# endif
1712 & grid(ng) % MyLon, &
1713 & grid(ng) % lonv, &
1714 & grid(ng) % latv, &
1715 & adat)
1716 ELSE
1717 CALL regrid_pio (ng, model, ncname, piofile, &
1718 & ncvname, piovar, gtype, interpflag, &
1719 & ilen, jlen, wrk, amin, amax, &
1720 & lbi, ubi, lbj, ubj, &
1721 & imin, imax, jmin, jmax, &
1722# ifdef MASKING
1723 & grid(ng) % vmask, &
1724# endif
1725 & grid(ng) % MyLon, &
1726 & grid(ng) % xv, &
1727 & grid(ng) % yv, &
1728 & adat)
1729 END IF
1730 CASE DEFAULT
1731 IF (spherical) THEN
1732 CALL regrid_pio (ng, model, ncname, piofile, &
1733 & ncvname, piovar, gtype, interpflag, &
1734 & ilen, jlen, wrk, amin, amax, &
1735 & lbi, ubi, lbj, ubj, &
1736 & imin, imax, jmin, jmax, &
1737# ifdef MASKING
1738 & grid(ng) % rmask, &
1739# endif
1740 & grid(ng) % MyLon, &
1741 & grid(ng) % lonr, &
1742 & grid(ng) % latr, &
1743 & adat)
1744 ELSE
1745 CALL regrid_pio (ng, model, ncname, piofile, &
1746 & ncvname, piovar, gtype, interpflag, &
1747 & ilen, jlen, wrk, amin, amax, &
1748 & lbi, ubi, lbj, ubj, &
1749 & imin, imax, jmin, jmax, &
1750# ifdef MASKING
1751 & grid(ng) % rmask, &
1752# endif
1753 & grid(ng) % MyLon, &
1754 & grid(ng) % xr, &
1755 & grid(ng) % yr, &
1756 & adat)
1757 END IF
1758 END SELECT
1759!
1760! Deallocate regridding work array.
1761!
1762 IF (allocated(wrk)) THEN
1763 deallocate (wrk)
1764 END IF
1765 END IF
1766!
1767! If requested, compute input data checksum value.
1768!
1769 IF (lchecksum) THEN
1770 npts=(imax-imin+1)*(jmax-jmin+1)
1771 IF (.not.allocated(cwrk)) allocate ( cwrk(npts) )
1772 cwrk=pack(adat(imin:imax, jmin:jmax), .true.)
1773 CALL get_hash (cwrk, npts, checksum, .true.)
1774 IF (allocated(cwrk)) deallocate (cwrk)
1775 END IF
1776!
1777 RETURN
1778 END FUNCTION pio_fread2d_xtr
1779# endif
1780#endif
1781 END MODULE nf_fread2d_xtr_mod
subroutine, public tile_bounds_2d(ng, tile, imax, jmax, itile, jtile, istr, iend, jstr, jend)
Definition get_bounds.F:974
subroutine, public tile_bounds_1d(ng, tile, imax, istr, iend)
Definition get_bounds.F:921
subroutine, public get_hash(a, asize, hash, lreduce)
Definition get_hash.F:72
type(t_grid), dimension(:), allocatable grid
Definition mod_grid.F:365
integer ioerror
logical inpthread
integer, dimension(:), allocatable tilesize
Definition mod_param.F:705
integer, parameter r3dvar
Definition mod_param.F:721
integer nghostpoints
Definition mod_param.F:710
integer, parameter iadm
Definition mod_param.F:665
integer, parameter u3dvar
Definition mod_param.F:722
integer, dimension(:), allocatable lm
Definition mod_param.F:455
integer, parameter u2dvar
Definition mod_param.F:718
integer, parameter p2dvar
Definition mod_param.F:716
integer, dimension(:), allocatable mm
Definition mod_param.F:456
integer, parameter r2dvar
Definition mod_param.F:717
integer, parameter v2dvar
Definition mod_param.F:719
integer, parameter p3dvar
Definition mod_param.F:720
integer, parameter v3dvar
Definition mod_param.F:723
logical spherical
real(dp), parameter spval
real(dp), parameter spval_check
integer interpflag
integer exit_flag
type(t_scalars), dimension(:), allocatable scalars
Definition mod_scalars.F:65
integer noerror
subroutine, public regrid_nf90(ng, model, ncname, ncid, ncvname, ncvarid, gtype, iflag, nx, ny, finp, amin, amax, lbi, ubi, lbj, ubj, imin, imax, jmin, jmax, mymask, myxout, xout, yout, fout)
Definition regrid.F:107
subroutine, public regrid_pio(ng, model, ncname, piofile, ncvname, piovar, gtype, iflag, nx, ny, finp, amin, amax, lbi, ubi, lbj, ubj, imin, imax, jmin, jmax, mymask, myxout, xout, yout, fout)
Definition regrid.F:378
logical function, public founderror(flag, noerr, line, routine)
Definition strings.F:52