ROMS
Loading...
Searching...
No Matches
nf_fwrite4d.F
Go to the documentation of this file.
1#include "cppdefs.h"
3!
4!git $Id$
5!================================================== Hernan G. Arango ===
6! Copyright (c) 2002-2025 The ROMS Group !
7! Licensed under a MIT/X style license !
8! See License_ROMS.md !
9!=======================================================================
10! !
11! This function writes out a generic floating point 4D array into an !
12! output NetCDF file. !
13! !
14! On Input: !
15! !
16! ng Nested grid number !
17! model Calling model identifier !
18! ncid NetCDF file ID !
19! ifield Field metadata index (integer) !
20#if defined PIO_LIB && defined DISTRIBUTE
21!or pioFile PIO file descriptor structure, TYPE(file_desc_t) !
22! pioFile%fh file handler !
23! pioFile%iosystem IO system descriptor (struct) !
24#endif
25! ncvarid NetCDF variable ID !
26#if defined PIO_LIB && defined DISTRIBUTE
27!or pioVar PIO variable descriptor structure, TYPE(My_VarDesc) !
28! pioVar%vd variable descriptor TYPE(Var_Desc_t)!
29! pioVar%dkind variable data kind !
30! pioVar%gtype variable C-gridtype !
31#endif
32! tindex NetCDF time record index to write !
33! gtype Grid type. If negative, only write water points !
34#if defined PIO_LIB && defined DISTRIBUTE
35!or pioDesc IO data decomposition descriptor, TYPE(IO_desc_t) !
36#endif
37! LBi I-dimension Lower bound !
38! UBi I-dimension Upper bound !
39! LBj J-dimension Lower bound !
40! UBj J-dimension Upper bound !
41! LBk K-dimension Lower bound !
42! UBk K-dimension Upper bound !
43! LBt Time-dimension Lower bound !
44! UBt Time-dimension Upper bound !
45! Amask land/Sea mask, if any (real) !
46! Ascl Factor to scale field before writing (real) !
47! Adat Field to write out (real) !
48! SetFillVal Logical switch to set fill value in land areas !
49! (OPTIONAL) !
50! ExtractField Field extraction flag (integer, OPTIONAL) !
51! ExtractField = 0 no extraction !
52! ExtractField = 1 extraction by intrpolation !
53! ExtractField > 1 extraction by decimation !
54! !
55! On Output: !
56! !
57! status Error flag (integer) !
58! MinValue Minimum value (real, OPTIONAL) !
59! MaxValue Maximum value (real, OPTIONAL) !
60! !
61#ifdef POSITIVE_ZERO
62! Starting F95 zero values can be signed (-0 or +0) following the !
63! IEEE 754 floating point standard. This may produce different !
64! output data in serial and parallel applications. Since comparing !
65! serial and parallel output is essential for tracking parallel !
66! partition bugs, "positive zero" is enforced. !
67! !
68#endif
69!=======================================================================
70!
71 USE mod_param
72 USE mod_parallel
73 USE mod_ncparam
74 USE mod_scalars
75!
77!
78 implicit none
79!
80 INTERFACE nf_fwrite4d
81 MODULE PROCEDURE nf90_fwrite4d
82#if defined PIO_LIB && defined DISTRIBUTE
83 MODULE PROCEDURE pio_fwrite4d
84#endif
85 END INTERFACE nf_fwrite4d
86!
87 CONTAINS
88
89#if defined PARALLEL_IO && defined DISTRIBUTE
90!
91!***********************************************************************
92 FUNCTION nf90_fwrite4d (ng, model, ncid, ifield, &
93 & ncvarid, tindex, gtype, &
94 & LBi, UBi, LBj, UBj, LBk, UBk, LBt, UBt, &
95 & Ascl, &
96# ifdef MASKING
97 & Amask, &
98# endif
99 & Adat, &
100 & SetFillVal, &
101 & ExtractField, &
102 & MinValue, MaxValue) RESULT (status)
103!***********************************************************************
104!
105 USE mod_netcdf
106!
107# ifdef MASKING
108 USE distribute_mod, ONLY : mp_collect
109# endif
111!
112! Imported variable declarations.
113!
114 logical, intent(in), optional :: setfillval
115!
116 integer, intent(in) :: ng, model, ncid, ncvarid, tindex, gtype
117 integer, intent(in) :: ifield
118 integer, intent(in) :: lbi, ubi, lbj, ubj, lbk, ubk, lbt, ubt
119!
120 integer, intent(in), optional :: extractfield
121!
122 real(dp), intent(in) :: ascl
123!
124# ifdef ASSUMED_SHAPE
125# ifdef MASKING
126 real(r8), intent(in) :: amask(lbi:,lbj:)
127# endif
128 real(r8), intent(in) :: adat(lbi:,lbj:,lbk:,lbt:)
129# else
130# ifdef MASKING
131 real(r8), intent(in) :: amask(lbi:ubi,lbj:ubj)
132# endif
133 real(r8), intent(in) :: adat(lbi:ubi,lbj:ubj,lbk:ubk,lbt:ubt)
134# endif
135 real(r8), intent(out), optional :: minvalue
136 real(r8), intent(out), optional :: maxvalue
137!
138! Local variable declarations.
139!
140 logical :: landfill
141!
142 integer :: extract_flag
143 integer :: i, ic, j, jc, k, kc, l, lc, npts
144 integer :: imin, imax, jmin, jmax, kmin, kmax
145 integer :: ioff, joff, koff, loff
146 integer :: istr, iend
147 integer :: ilen, isize, jlen, jsize, ijlen, ijklen, klen, llen
148 integer :: mytype
149 integer :: status
150
151 integer, dimension(5) :: start, total
152!
153 real(r8), parameter :: inival = 0.0_r8
154
155 real(r8), allocatable :: awrk(:)
156!
157!-----------------------------------------------------------------------
158! Set starting and ending indices to process.
159!-----------------------------------------------------------------------
160!
161 status=nf90_noerr
162!
163! Set first and last grid point according to staggered C-grid
164! classification.
165!
166 mytype=gtype
167!
168 SELECT CASE (abs(mytype))
169 CASE (p2dvar, p3dvar)
170 imin=bounds(ng)%Istr (myrank)
171 imax=bounds(ng)%IendR(myrank)
172 jmin=bounds(ng)%Jstr (myrank)
173 jmax=bounds(ng)%JendR(myrank)
174 isize=iobounds(ng)%xi_psi
175 jsize=iobounds(ng)%eta_psi
176 CASE (r2dvar, r3dvar)
177 imin=bounds(ng)%IstrR(myrank)
178 imax=bounds(ng)%IendR(myrank)
179 jmin=bounds(ng)%JstrR(myrank)
180 jmax=bounds(ng)%JendR(myrank)
181 isize=iobounds(ng)%xi_rho
182 jsize=iobounds(ng)%eta_rho
183 CASE (u2dvar, u3dvar)
184 imin=bounds(ng)%Istr (myrank)
185 imax=bounds(ng)%IendR(myrank)
186 jmin=bounds(ng)%JstrR(myrank)
187 jmax=bounds(ng)%JendR(myrank)
188 isize=iobounds(ng)%xi_u
189 jsize=iobounds(ng)%eta_u
190 CASE (v2dvar, v3dvar)
191 imin=bounds(ng)%IstrR(myrank)
192 imax=bounds(ng)%IendR(myrank)
193 jmin=bounds(ng)%Jstr (myrank)
194 jmax=bounds(ng)%JendR(myrank)
195 isize=iobounds(ng)%xi_v
196 jsize=iobounds(ng)%eta_v
197 CASE DEFAULT
198 imin=bounds(ng)%IstrR(myrank)
199 imax=bounds(ng)%IendR(myrank)
200 jmin=bounds(ng)%JstrR(myrank)
201 jmax=bounds(ng)%JendR(myrank)
202 isize=iobounds(ng)%xi_rho
203 jsize=iobounds(ng)%eta_rho
204 END SELECT
205!
206 ilen=imax-imin+1
207 jlen=jmax-jmin+1
208 klen=ubk-lbk+1
209 llen=ubt-lbt+1
210!
211! Set switch to replace land areas with fill value, spval.
212!
213# ifdef MASKING
214 IF (PRESENT(setfillval)) THEN
215 landfill=setfillval
216 ELSE
217 landfill=tindex.gt.0
218 END IF
219# else
220 landfill=.false.
221# endif
222!
223! If appropriate, set the field extraction flag to the provided grid
224! geometry through interpolation or decimation.
225!
226 IF (PRESENT(extractfield)) THEN
227 extract_flag=extractfield
228 ELSE
229 extract_flag=0
230 END IF
231!
232!-----------------------------------------------------------------------
233! Parallel I/O: Pack tile data into 1D array in column-major order.
234# ifdef MASKING
235! Overwrite masked points with special value.
236# endif
237!-----------------------------------------------------------------------
238!
239 IF (gtype.gt.0) THEN
240!
241! Set offsets due the NetCDF dimensions. Recall that some output
242! variables not always start at one.
243!
244 SELECT CASE (abs(mytype))
245 CASE (p2dvar, p3dvar)
246 ioff=0
247 joff=0
248 CASE (r2dvar, r3dvar)
249 ioff=1
250 joff=1
251 CASE (u2dvar, u3dvar)
252 ioff=0
253 joff=1
254 CASE (v2dvar, v3dvar)
255 ioff=1
256 joff=0
257 CASE DEFAULT
258 ioff=1
259 joff=1
260 END SELECT
261
262 IF (lbk.eq.0) THEN
263 koff=1
264 ELSE
265 koff=0
266 END IF
267
268 IF (lbt.eq.0) THEN
269 loff=1
270 ELSE
271 loff=0
272 END IF
273!
274! Allocate and initialize scratch work array.
275!
276 ijlen=ilen*jlen
277 ijklen=ijlen*klen
278 npts=ijklen*llen
279
280 IF (.not.allocated(awrk)) THEN
281 allocate ( awrk(npts) )
282 awrk=inival
283 END IF
284!
285! Pack and scale tile data.
286!
287 ic=0
288 DO l=lbt,ubt
289 DO k=lbk,ubk
290 DO j=jmin,jmax
291 DO i=imin,imax
292 ic=ic+1
293 awrk(ic)=adat(i,j,k,l)*ascl
294# ifdef POSITIVE_ZERO
295 IF (abs(awrk(ic)).eq.0.0_r8) THEN
296 awrk(ic)=0.0_r8 ! impose positive zero
297 END IF
298# endif
299# ifdef MASKING
300 IF ((amask(i,j).eq.0.0_r8).and.landfill) THEN
301 awrk(ic)=spval
302 END IF
303# endif
304 END DO
305 END DO
306 END DO
307 END DO
308!
309! Write out data: all parallel nodes write their own packed tile data.
310!
311 start(1)=imin+ioff
312 total(1)=ilen
313 start(2)=jmin+joff
314 total(2)=jlen
315 start(3)=lbk+koff
316 total(3)=klen
317 start(4)=lbt+loff
318 total(4)=llen
319 start(5)=tindex
320 total(5)=1
321
322 status=nf90_put_var(ncid, ncvarid, awrk, start, total)
323 END IF
324
325# if defined WRITE_WATER && defined MASKING
326!
327!-----------------------------------------------------------------------
328! Parallel I/O: Remove land points and pack tile data into 1D array.
329!-----------------------------------------------------------------------
330!
331 IF (gtype.lt.0) THEN
332!
333! Set offsets due array packing into 1D array in column-major order.
334!
335 SELECT CASE (abs(mytype))
336 CASE (p2dvar, p3dvar)
337 ioff=0
338 joff=1
339 CASE (r2dvar, r3dvar)
340 ioff=1
341 joff=0
342 CASE (u2dvar, u3dvar)
343 ioff=0
344 joff=0
345 CASE (v2dvar, v3dvar)
346 ioff=1
347 joff=1
348 CASE DEFAULT
349 ioff=1
350 joff=0
351 END SELECT
352
353 IF (lbk.eq.0) THEN
354 koff=0
355 ELSE
356 koff=1
357 END IF
358
359 IF (lbt.eq.0) THEN
360 loff=0
361 ELSE
362 loff=1
363 END IF
364!
365! Allocate and initialize scratch work array.
366!
367 ijlen=isize*jsize
368 ijklen=ijlen*klen
369 npts=ijklen*llen
370
371 IF (.not.allocated(awrk)) THEN
372 allocate ( awrk(npts) )
373 awrk=inival
374 END IF
375!
376! Scale and gather data from all spawned nodes. Store data into a 1D
377! global array, packed in column-major order. Flag land point with
378! special value.
379!
380 DO l=lbt,ubt
381 lc=(l-loff)*ijklen
382 DO k=lbk,ubk
383 kc=(k-koff)*ijlen+lc
384 DO j=jmin,jmax
385 jc=(j-joff)*isize+kc
386 DO i=imin,imax
387 ic=i+ioff+jc
388 awrk(ic)=adat(i,j,k,l)*ascl
389# ifdef POSITIVE_ZERO
390 IF (abs(awrk(ic)).eq.0.0_r8) THEN
391 awrk(ic)=0.0_r8 ! impose positive zero
392 END IF
393# endif
394 IF (amask(i,j).eq.0.0_r8) THEN
395 awrk(ic)=spval
396 END IF
397 END DO
398 END DO
399 END DO
400 END DO
401!
402! Global reduction of work array.
403!
404 CALL mp_collect (ng, model, npts, inival, awrk)
405!
406! Remove land points.
407!
408 ic=0
409 DO i=1,npts
410 IF (awrk(i).lt.spval) THEN
411 ic=ic+1
412 awrk(ic)=awrk(i)
413 END IF
414 END DO
415 npts=ic
416!
417! Write out data: all parallel nodes write a section of the packed
418! data.
419!
420 CALL tile_bounds_1d (ng, myrank, npts, istr, iend)
421!
422 start(1)=istr
423 total(1)=iend-istr+1
424 start(2)=tindex
425 total(2)=1
426
427 status=nf90_put_var(ncid, ncvarid, awrk(istr:), start, total)
428 END IF
429# endif
430!
431!-----------------------------------------------------------------------
432! Deallocate scratch work array.
433!-----------------------------------------------------------------------
434!
435 IF (allocated(awrk)) THEN
436 deallocate (awrk)
437 END IF
438!
439 RETURN
440 END FUNCTION nf90_fwrite4d
441
442#else
443
444!
445!***********************************************************************
446 FUNCTION nf90_fwrite4d (ng, model, ncid, ifield, &
447 & ncvarid, tindex, gtype, &
448 & LBi, UBi, LBj, UBj, LBk, UBk, LBt, UBt, &
449 & Ascl, &
450# ifdef MASKING
451 & Amask, &
452# endif
453 & Adat, &
454 & SetFillVal, &
455 & ExtractField, &
456 & MinValue, MaxValue) RESULT (status)
457!***********************************************************************
458!
459 USE mod_netcdf
460
461# ifdef DISTRIBUTE
462!
463 USE distribute_mod, ONLY : mp_bcasti
464# ifdef INLINE_2DIO
465 USE distribute_mod, ONLY : mp_gather2d
466# else
467 USE distribute_mod, ONLY : mp_gather3d
468# endif
469# endif
470# ifdef OUTPUT_STATS
471 USE stats_mod, ONLY : stats_4dfld
472# endif
473!
474! Imported variable declarations.
475!
476 logical, intent(in), optional :: setfillval
477!
478 integer, intent(in) :: ng, model, ncid, ncvarid, tindex, gtype
479 integer, intent(in) :: ifield
480 integer, intent(in) :: lbi, ubi, lbj, ubj, lbk, ubk, lbt, ubt
481!
482 integer, intent(in), optional :: extractfield
483!
484 real(dp), intent(in) :: ascl
485!
486# ifdef ASSUMED_SHAPE
487# ifdef MASKING
488 real(r8), intent(in) :: amask(lbi:,lbj:)
489# endif
490 real(r8), intent(in) :: adat(lbi:,lbj:,lbk:,lbt:)
491# else
492# ifdef MASKING
493 real(r8), intent(in) :: amask(lbi:ubi,lbj:ubj)
494# endif
495 real(r8), intent(in) :: adat(lbi:ubi,lbj:ubj,lbk:ubk,lbt:ubt)
496# endif
497 real(r8), intent(out), optional :: minvalue
498 real(r8), intent(out), optional :: maxvalue
499!
500! Local variable declarations.
501!
502 logical :: landfill
503!
504 integer :: extract_flag
505 integer :: i, fourth, npts, tile
506 integer :: status
507
508 integer, dimension(5) :: start, total
509!
510 real(r8), dimension((Lm(ng)+2)*(Mm(ng)+2)*(UBk-LBk+1)) :: awrk
511
512# ifdef OUTPUT_STATS
513!
514 TYPE (t_stats) :: stats
515# endif
516!
517!-----------------------------------------------------------------------
518! Set starting and ending indices to process.
519!-----------------------------------------------------------------------
520!
521 status=nf90_noerr
522!
523! Set parallel tile.
524!
525# ifdef DISTRIBUTE
526 tile=myrank
527# else
528 tile=-1
529# endif
530!
531! Set switch to replace land areas with fill value, spval.
532!
533# ifdef MASKING
534 IF (PRESENT(setfillval)) THEN
535 landfill=setfillval
536 ELSE
537 landfill=tindex.gt.0
538 END IF
539# else
540 landfill=.false.
541# endif
542!
543! If appropriate, set the field extraction flag to the provided grid
544! geometry through interpolation or decimation.
545!
546 IF (PRESENT(extractfield)) THEN
547 extract_flag=extractfield
548 ELSE
549 extract_flag=0
550 END IF
551
552# ifdef OUTPUT_STATS
553!
554! Initialize output variable statistics structure.
555!
556 stats % checksum=0_i8b
557 stats % count=0
558 stats % min=spval
559 stats % max=-spval
560 stats % avg=0.0_r8
561 stats % rms=0.0_r8
562# endif
563!
564! If appropriate, initialize minimum and maximum processed values.
565!
566 IF (PRESENT(minvalue)) THEN
567 minvalue=spval
568 maxvalue=-spval
569 END IF
570!
571! Initialize local array to avoid denormalized numbers. This
572! facilitates processing and debugging.
573!
574 awrk=0.0_r8
575!
576!-----------------------------------------------------------------------
577! Pack 4D field data into 1D array. Proccess fourth dimension record
578! by record.
579!-----------------------------------------------------------------------
580!
581 dim4_loop : DO fourth=lbt,ubt
582 CALL pack_field4d (ng, model, tile, &
583 & gtype, ifield, tindex, &
584 & landfill, extract_flag, &
585 & lbi, ubi, lbj, ubj, lbk, ubk, lbt, ubt, &
586 & fourth, &
587# ifdef MASKING
588 & amask, &
589# endif
590 & ascl, adat, &
591 & start, total, npts, awrk)
592!
593!-----------------------------------------------------------------------
594! If applicable, compute output field minimum and maximum values.
595!-----------------------------------------------------------------------
596!
597 IF (PRESENT(minvalue)) THEN
598 IF (outthread) THEN
599 DO i=1,npts
600 IF (abs(awrk(i)).lt.spval) THEN
601 minvalue=min(minvalue,awrk(i))
602 maxvalue=max(maxvalue,awrk(i))
603 END IF
604 END DO
605 END IF
606 END IF
607!
608!-----------------------------------------------------------------------
609! Write output buffer into NetCDF file.
610!-----------------------------------------------------------------------
611!
612 IF (outthread) THEN
613 status=nf90_put_var(ncid, ncvarid, awrk, start, total)
614 END IF
615 END DO dim4_loop
616
617# ifdef OUTPUT_STATS
618!
619!-----------------------------------------------------------------------
620! Compute and report output field statistics.
621!-----------------------------------------------------------------------
622!
623 CALL stats_4dfld (ng, tile, model, gtype, stats, &
624 & extract_flag, &
625 & lbi, ubi, lbj, ubj, lbk, ubk, lbt, ubt, &
626 & adat, &
627# ifdef MASKING
628 & fmask = amask, &
629# endif
630 & debug = .false.)
631 IF (outthread) THEN
632 WRITE (stdout,10) trim(vname(1,ifield)), stats%min, stats%max, &
633 & stats%checksum
634 10 FORMAT (4x,'- ',a,':',t35,'Min = ',1p,e15.8,', Max = ', &
635 & 1p,e15.8,', CheckSum = ',i0)
636 END IF
637# endif
638# ifdef DISTRIBUTE
639!
640!-----------------------------------------------------------------------
641! Broadcast IO error flag to all nodes.
642!-----------------------------------------------------------------------
643!
644 CALL mp_bcasti (ng, model, status)
645# endif
646!
647 RETURN
648 END FUNCTION nf90_fwrite4d
649#endif
650
651#if defined PIO_LIB && defined DISTRIBUTE
652!
653!***********************************************************************
654 FUNCTION pio_fwrite4d (ng, model, pioFile, ifield, &
655 & pioVar, tindex, pioDesc, &
656 & LBi, UBi, LBj, UBj, LBk, UBk, LBt, UBt, &
657 & Ascl, &
658# ifdef MASKING
659 & Amask, &
660# endif
661 & Adat, SetFillVal, &
662 & MinValue, MaxValue) RESULT (status)
663!***********************************************************************
664!
666!
667 USE distribute_mod, ONLY : mp_reduce
668# ifdef OUTPUT_STATS
669 USE stats_mod, ONLY : stats_4dfld
670# endif
671!
672! Imported variable declarations.
673!
674 logical, intent(in), optional :: setfillval
675!
676 integer, intent(in) :: ng, model, tindex
677 integer, intent(in) :: ifield
678 integer, intent(in) :: lbi, ubi, lbj, ubj, lbk, ubk, lbt, ubt
679!
680 integer, intent(in), optional :: extractfield
681!
682 real(dp), intent(in) :: ascl
683!
684# ifdef ASSUMED_SHAPE
685# ifdef MASKING
686 real(r8), intent(in) :: amask(lbi:,lbj:)
687# endif
688 real(r8), intent(in) :: adat(lbi:,lbj:,lbk:,lbt:)
689# else
690# ifdef MASKING
691 real(r8), intent(in) :: amask(lbi:ubi,lbj:ubj)
692# endif
693 real(r8), intent(in) :: adat(lbi:ubi,lbj:ubj,lbk:ubk,lbt:ubt)
694# endif
695 real(r8), intent(out), optional :: minvalue
696 real(r8), intent(out), optional :: maxvalue
697!
698 TYPE (file_desc_t), intent(inout) :: piofile
699 TYPE (io_desc_t), intent(inout) :: piodesc
700 TYPE (my_vardesc), intent(inout) :: piovar
701!
702! Local variable declarations.
703!
704 logical :: landfill, lminmax
705
706 logical, pointer :: lwater(:,:,:,:)
707!
708 integer :: extract_flag
709 integer :: i, j, k, l, tile
710 integer :: imin, imax, jmin, jmax
711 integer :: cgrid, dkind, ghost, gtype
712 integer :: status
713
714 integer, dimension(5) :: start, total
715!
716 real(r8), dimension(2) :: rbuffer
717
718 real(r4), pointer :: awrk4(:,:,:,:)
719 real(r8), pointer :: awrk8(:,:,:,:)
720
721# ifdef OUTPUT_STATS
722!
723 TYPE (t_stats) :: stats
724# endif
725!
726 character (len= 3), dimension(2) :: op_handle
727!
728!-----------------------------------------------------------------------
729! Set starting and ending indices to process.
730!-----------------------------------------------------------------------
731!
732 status=pio_noerr
733!
734! Set first and last grid point according to staggered C-grid
735! classification. Set loops offsets.
736!
737 ghost=0
738 dkind=piovar%dkind
739 gtype=piovar%gtype
740!
741 SELECT CASE (abs(gtype))
742 CASE (p3dvar)
743 cgrid=1
744 CASE (l3dvar, l4dvar, r3dvar)
745 cgrid=2
746 CASE (u3dvar)
747 cgrid=3
748 CASE (v3dvar)
749 cgrid=4
750 CASE DEFAULT
751 cgrid=2
752 END SELECT
753!
754 imin=bounds(ng)%Imin(cgrid,ghost,myrank)
755 imax=bounds(ng)%Imax(cgrid,ghost,myrank)
756 jmin=bounds(ng)%Jmin(cgrid,ghost,myrank)
757 jmax=bounds(ng)%Jmax(cgrid,ghost,myrank)
758!
759! Set switch to compute minimum and maximum values.
760!
761 IF (PRESENT(minvalue)) THEN
762 lminmax=.true.
763 IF (.not.associated(lwater)) THEN
764 allocate ( lwater(lbi:ubi,lbj:ubj,lbk:ubk,lbt:ubt) )
765 lwater=.true.
766 END IF
767 ELSE
768 lminmax=.false.
769 END IF
770!
771! Set switch to replace land areas with fill value, spval.
772!
773# ifdef MASKING
774 IF (PRESENT(setfillval)) THEN
775 landfill=setfillval
776 ELSE
777 landfill=tindex.gt.0
778 END IF
779# else
780 landfill=.false.
781# endif
782!
783! If appropriate, set the field extraction flag to the provided grid
784! geometry through interpolation or decimation.
785!
786 IF (PRESENT(extractfield)) THEN
787 extract_flag=extractfield
788 ELSE
789 extract_flag=0
790 END IF
791
792# ifdef OUTPUT_STATS
793!
794! Initialize output variable statistics structure.
795!
796 stats % checksum=0_i8b
797 stats % count=0
798 stats % min=spval
799 stats % max=-spval
800 stats % avg=0.0_r8
801 stats % rms=0.0_r8
802# endif
803!
804!-----------------------------------------------------------------------
805! Write out data into NetCDF file.
806!-----------------------------------------------------------------------
807!
808! Allocate, initialize and load data into local array used for
809! writing. Overwrite masked points with special value.
810!
811 IF (dkind.eq.pio_double) THEN ! double precision
812 IF (.not.associated(awrk8)) THEN
813 allocate ( awrk8(lbi:ubi,lbj:ubj,lbk:ubk,lbt:ubt) )
814 awrk8=0.0_r8
815 END IF
816!
817 DO l=lbt,ubt
818 DO k=lbk,ubk
819 DO j=jmin,jmax
820 DO i=imin,imax
821 awrk8(i,j,k,l)=adat(i,j,k,l)*ascl
822# ifdef MASKING
823 IF ((amask(i,j).eq.0.0_r8).and.landfill) THEN
824 awrk8(i,j,k,l)=spval
825 IF (lminmax) lwater(i,j,k,l)=.false.
826 END IF
827# endif
828 END DO
829 END DO
830 END DO
831 END DO
832 IF (lminmax) THEN
833 rbuffer(1)=minval(awrk8, mask=lwater)
834 rbuffer(2)=maxval(awrk8, mask=lwater)
835 END IF
836 ELSE ! single precision
837 IF (.not.associated(awrk4)) THEN
838 allocate ( awrk4(lbi:ubi,lbj:ubj,lbk:ubk,lbt:ubt) )
839 awrk4=0.0_r8
840 END IF
841!
842 DO l=lbt,ubt
843 DO k=lbk,ubk
844 DO j=jmin,jmax
845 DO i=imin,imax
846 awrk4(i,j,k,l)=real(adat(i,j,k,l)*ascl, r4)
847# ifdef MASKING
848 IF ((amask(i,j).eq.0.0_r8).and.landfill) THEN
849 awrk4(i,j,k,l)=real(spval, r4)
850 END IF
851# endif
852 END DO
853 END DO
854 END DO
855 END DO
856 IF (lminmax) THEN
857 rbuffer(1)=real(minval(awrk4, mask=lwater),r8)
858 rbuffer(2)=real(maxval(awrk4, mask=lwater),r8)
859 END IF
860 END IF
861!
862! Set unlimited time dimension record to write, if any.
863!
864 IF (tindex.gt.0) THEN
865 CALL pio_setframe (piofile, &
866 & piovar%vd, &
867 & int(tindex, kind=pio_offset_kind))
868 END IF
869!
870! Write out data into NetCDF.
871!
872 IF (dkind.eq.pio_double) THEN ! double precision
873 CALL pio_write_darray (piofile, &
874 & piovar%vd, &
875 & piodesc, &
876 & awrk8(imin:imax,jmin:jmax, &
877 & lbk:ubk,lbt:ubt), &
878 & status)
879 ELSE ! single precision
880 CALL pio_write_darray (piofile, &
881 & piovar%vd, &
882 & piodesc, &
883 & awrk4(imin:imax,jmin:jmax, &
884 & lbk:ubk,lbt:ubt), &
885 & status)
886 END IF
887
888# ifdef OUTPUT_STATS
889!
890!-----------------------------------------------------------------------
891! Compute and report output field statistics.
892!-----------------------------------------------------------------------
893!
894# ifdef DISTRIBUTE
895 tile=myrank
896# else
897 tile=-1
898# endif
899 CALL stats_4dfld (ng, tile, model, gtype, stats, &
900 & extract_flag, &
901 & lbi, ubi, lbj, ubj, lbk, ubk, lbt, ubt, &
902 & adat, &
903# ifdef MASKING
904 & fmask = amask, &
905# endif
906 & debug = .false.)
907 IF (outthread) THEN
908 WRITE (stdout,10) trim(vname(1,ifield)), stats%min, stats%max, &
909 & stats%checksum
910 10 FORMAT (4x,'- ',a,':',t35,'Min = ',1p,e15.8,', Max = ', &
911 & 1p,e15.8,', CheckSum = ',i0)
912 END IF
913# endif
914!
915!-----------------------------------------------------------------------
916! If applicable, compute global minimum and maximum values.
917!-----------------------------------------------------------------------
918!
919 IF (lminmax) THEN
920 op_handle(1)='MIN'
921 op_handle(2)='MAX'
922 CALL mp_reduce (ng, model, 2, rbuffer, op_handle)
923 minvalue=rbuffer(1)
924 maxvalue=rbuffer(2)
925 IF (associated(lwater)) deallocate (lwater)
926 END IF
927!
928! Deallocate local array.
929!
930 IF (dkind.eq.pio_double) THEN
931 IF (associated(awrk8)) deallocate (awrk8)
932 ELSE
933 IF (associated(awrk4)) deallocate (awrk4)
934 END IF
935!
936 RETURN
937 END FUNCTION pio_fwrite4d
938#endif
939!
940 END MODULE nf_fwrite4d_mod
subroutine mp_gather3d(ng, model, lbi, ubi, lbj, ubj, lbk, ubk, tindex, gtype, ascl, amask, a, npts, awrk, setfillval)
subroutine mp_gather2d(ng, model, lbi, ubi, lbj, ubj, tindex, gtype, ascl, amask, a, npts, awrk, setfillval)
subroutine, public tile_bounds_1d(ng, tile, imax, istr, iend)
Definition get_bounds.F:921
character(len=maxlen), dimension(6, 0:nv) vname
logical outthread
type(t_bounds), dimension(:), allocatable bounds
Definition mod_param.F:232
integer, parameter r3dvar
Definition mod_param.F:721
integer, parameter l4dvar
Definition mod_param.F:727
type(t_iobounds), dimension(:), allocatable iobounds
Definition mod_param.F:282
integer, parameter u3dvar
Definition mod_param.F:722
integer, parameter u2dvar
Definition mod_param.F:718
integer, parameter p2dvar
Definition mod_param.F:716
integer, parameter r2dvar
Definition mod_param.F:717
integer, parameter l3dvar
Definition mod_param.F:726
integer, parameter v2dvar
Definition mod_param.F:719
integer, parameter p3dvar
Definition mod_param.F:720
integer, parameter v3dvar
Definition mod_param.F:723
real(dp), parameter spval
integer function pio_fwrite4d(ng, model, piofile, ifield, piovar, tindex, piodesc, lbi, ubi, lbj, ubj, lbk, ubk, lbt, ubt, ascl, amask, adat, setfillval, minvalue, maxvalue)
integer function nf90_fwrite4d(ng, model, ncid, ifield, ncvarid, tindex, gtype, lbi, ubi, lbj, ubj, lbk, ubk, lbt, ubt, ascl, amask, adat, setfillval, extractfield, minvalue, maxvalue)
subroutine, public pack_field4d(ng, model, tile, gtype, ifield, tindex, landfill, extract_flag, lbi, ubi, lbj, ubj, lbk, ubk, lbt, ubt, fourth, amask, ascl, adat, start, total, npts, awrk)
subroutine, public stats_4dfld(ng, tile, model, gtype, s, extract_flag, lbi, ubi, lbj, ubj, lbk, ubk, lbt, ubt, f, fmask, debug)
Definition stats.F:646