FV3 Bundle
diag_integral.F90
Go to the documentation of this file.
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
10 !*
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 !* for more details.
15 !*
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
19 
20 !> \file
21 !! \brief Contains the \ref diag_integral_mod module
22 
24 #include <fms_platform.h>
25 
26 
27 
28 !###############################################################################
29 !> \defgroup diag_integral_mod diag_integral_mod
30 !!
31 !! \author Fei Liu <Fei.Liu@noaa.gov>
32 !!
33 !! \brief This module computes and outputs global and / or hemispheric physics
34 !! integrals.
35 !!
36 !! <b> Modules Included: </b>
37 !!
38 !! <table>
39 !! <tr>
40 !! <th> Module Name </th>
41 !! <th> Included Values </th>
42 !! </tr>
43 !! <tr>
44 !! <td> time_manager_mod </td>
45 !! <td> time_type, get_time, set_time, time_manager_init, operator(+),
46 !! operator(-), operator(==), operator(>=), operator(/=) </td>
47 !! </tr>
48 !! <tr>
49 !! <td> mpp_mod </td>
50 !! <td> input_nml_file <\td>
51 !! </tr>
52 !! <tr>
53 !! <td> fms_mod </td>
54 !! <td> open_file, file_exist, error_mesg, open_namelist_file,
55 !! check_nml_error, fms_init, mpp_pe, mpp_root_pe, FATAL,
56 !! write_version_number, stdlog, close_file </td>
57 !! </tr>
58 !! <tr>
59 !! <td> constants_mod </td>
60 !! <td> radius, constants_init </td>
61 !! </tr>
62 !! <tr>
63 !! <td> mpp_mod </td>
64 !! <td> mpp_sum, mpp_init </td>
65 !! </tr>
66 !! </table>
67 !!
68 !! <b> Public Interfaces: </b>
69 !!
70 !! - sum_diag_integral_field
71 !!
72 !! <b> Public Subroutines: </b>
73 !!
74 !! - diag_integral_init
75 !! - diag_integral_field_init
76 !! - diag_integral_output
77 !! - diag_integral_end
78 !! - sum_field_2d
79 !! - sum_field_3d
80 !! - sum_field_wght_3d
81 !! - sum_field_2d_hemi
82 !!
83 !! <b> Private Functions: </b>
84 !!
85 !! - set_axis_time
86 !! - get_field_index
87 !! - get_axis_time
88 !! - diag_integral_alarm
89 !! - vert_diag_integral
90 !!
91 !! <b> Private Subroutines: </b>
92 !!
93 !! - write_field_averages
94 !! - format_text_init
95 !! - format_data_init
96 !!
97 
100  operator(+), operator(-), &
101  operator(==), operator(>=), &
102  operator(/=)
103 use mpp_mod, only: input_nml_file
104 use fms_mod, only: open_file, file_exist, error_mesg, &
105  open_namelist_file, check_nml_error, &
106  fms_init, &
107  mpp_pe, mpp_root_pe,&
108  fatal, write_version_number, &
109  stdlog, close_file
111 use mpp_mod, only: mpp_sum, mpp_init
112 
113 !-------------------------------------------------------------------------------
114 
115 implicit none
116 private
117 
118 !-------------------------------------------------------------------------------
119 !----------- version number for this module -------------------
120 
121 character(len=128) :: version = '$Id$'
122 character(len=128) :: tagname = '$Name$'
123 
124 
125 !-------------------------------------------------------------------------------
126 !------ interfaces ------
127 
128 public &
132 
133 
134 
135 !###############################################################################
136 !> \defgroup sum_diag_integral_field sum_diag_integral_field
137 !! \ingroup diag_integral_mod
138 !!
139 !! This interface can be called in any one of three ways:
140 !!
141 !! \code{.f90}
142 !! call sum_diag_integral_field (name, data, is, js)
143 !! call sum_diag_integral_field (name, data, wt, is, js)
144 !! call sum_diag_integral_field (name, data, is, ie, js, je)
145 !! \endcode
146 !!
147 !! in the first option above, `data` may be either
148 !! \code{.f90}
149 !! real, intent(in) :: data(:,:) ![ sum_field_2d ]
150 !! real, intent(in) :: data(:,:,:) ![ sum_field_3d ]
151 !! \endcode
152 !!
153 !! <b> Parameters: </b>
154 !!
155 !! \code{.f90}
156 !! character(len=*), intent(in) :: name
157 !! real, intent(in) :: wt(:,:,:)
158 !! integer, optional, intent(in) :: is, ie, js, je
159 !! \endcode
160 !!
161 !! \param [in] <name> name associated with integral
162 !! \param [in] <data> field of integrands to be summed over
163 !! \param [in] <wt> vertical weighting factor to be applied to integrands
164 !! when summing
165 !! \param [in] <is, ie, js, je> starting/ending i,j indices over which summation
166 !! is to occur
167 !!
169  module procedure sum_field_2d, &
171  sum_field_3d, &
173 end interface
174 
175 
176 
177 private &
178 
179 ! from diag_integral_init:
180  set_axis_time, &
181 
182 ! from diag_integral_field_init and sum_diag_integral_field:
183  get_field_index, &
184 
185 ! from diag_integral_output and diag_integral_end:
187 
188 ! from write_field_averages:
190  get_axis_time, &
191 
192 ! from diag_integral_output:
194 
195 ! from sum_diag_integral_field:
197 
198 !-------------------------------------------------------------------------------
199 !------ namelist -------
200 
201 integer, parameter :: &
202  mxch = 64 ! maximum number of characters in
203  ! the optional output file name
204 real :: &
205  output_interval = -1.0 ! time interval at which integrals
206  ! are to be output
207 character(len=8) :: &
208  time_units = 'hours' ! time units associated with
209  ! output_interval
210 character(len=mxch) :: &
211  file_name = ' ' ! optional integrals output file name
212 logical :: &
213  print_header = .true. ! print a header for the integrals
214  ! file ?
215 integer :: &
216  fields_per_print_line = 4 ! number of fields to write per line
217  ! of output
218 
219 
220 namelist / diag_integral_nml / &
224 
225 !-------------------------------------------------------------------------------
226 !------- public data ------
227 
228 
229 !-------------------------------------------------------------------------------
230 !------- private data ------
231 
232 !-------------------------------------------------------------------------------
233 ! variables associated with the determination of when integrals
234 ! are to be written.
235 ! Next_alarm_time next time at which integrals are to be
236 ! written
237 ! Alarm_interval time interval between writing integrals
238 ! Zero_time time_type variable set to (0,0); used as
239 ! flag to indicate integrals are not being
240 ! output
241 ! Time_init_save initial time associated with experiment;
242 ! used as a base for defining time
243 !-------------------------------------------------------------------------------
246 
247 !-------------------------------------------------------------------------------
248 ! variables used in determining weights associated with each
249 ! contribution to the integrand.
250 ! area area of each grid box
251 ! idim x dimension of grid on local processor
252 ! jdim y dimension of grid on local processor
253 ! field_size number of columns on global domain
254 ! sum_area surface area of globe
255 !-------------------------------------------------------------------------------
256 real, allocatable, dimension(:,:) :: area
257 integer :: idim, jdim, field_size
258 real :: sum_area
259 
260 !-------------------------------------------------------------------------------
261 ! variables used to define the integral fields:
262 ! max_len_name maximum length of name associated with integral
263 ! max_num_field maximum number of integrals allowed
264 ! num_field number of integrals that have been activated
265 ! field_name(i) name associated with integral i
266 ! field_format(i) output format for integral i
267 ! field_sum(i) integrand for integral i
268 ! field_count(i) number of values in integrand i
269 !-------------------------------------------------------------------------------
270 integer, parameter :: max_len_name = 12
271 integer, parameter :: max_num_field = 32
272 integer :: num_field = 0
273 character(len=max_len_name) :: field_name (max_num_field)
274 character(len=16) :: field_format (max_num_field)
277 
278 !-------------------------------------------------------------------------------
279 ! variables defining output formats.
280 ! format_text format statement for header
281 ! format_data format statement for data output
282 ! do_format_data a data format needs to be generated ?
283 ! nd number of characters in data format statement
284 ! nt number of characters in text format statement
285 !-------------------------------------------------------------------------------
286 character(len=160) :: format_text, format_data
287 logical :: do_format_data = .true.
288 integer :: nd, nt
289 
290 !-------------------------------------------------------------------------------
291 ! miscellaneous variables.
292 !-------------------------------------------------------------------------------
293 integer :: diag_unit = 0 ! unit number for output file
294 logical :: module_is_initialized = .false.
295  ! module is initialized ?
296 
297 
298 
299  contains
300 
301 
302 
303 !###############################################################################
304 !
305 ! PUBLIC SUBROUTINES
306 !
307 !###############################################################################
308 
309 
310 
311 !###############################################################################
312 !> \fn diag_integral_init
313 !!
314 !! \brief diag_integral_init is the constructor for diag_integral_mod.
315 !!
316 !! <b> Template: </b>
317 !!
318 !! \code{.f90}
319 !! call diag_integral_init (Time_init, Time, blon, blat)
320 !! \endcode
321 !!
322 !! <b> Parameters: </b>
323 !!
324 !! \code{.f90}
325 !! type (time_type), intent(in), optional :: Time_init, Time
326 !! real,dimension(:,:), intent(in), optional :: blon, blat, area_in
327 !! \endcode
328 !!
329 !! \param [in] <Time_init> Initial time to start the integral
330 !! \param [in] <Time> current time
331 !! \param [in] <latb> array of model latitudes at cell boundaries [radians]
332 !! \param [in] <lonb> array of model longitudes at cell boundaries [radians]
333 !!
334 subroutine diag_integral_init (Time_init, Time, blon, blat, area_in)
336 type(time_type), intent(in), optional :: time_init, time
337 real,dimension(:,:), intent(in), optional :: blon, blat, area_in
338 
339 !-------------------------------------------------------------------------------
340 ! local variables:
341 ! r2
342 ! rsize
343 ! unit
344 ! io
345 ! ierr
346 ! seconds
347 ! nc
348 ! i,j
349 !-------------------------------------------------------------------------------
350  real :: rsize
351  integer :: unit, io, ierr, nc, logunit
352  integer :: field_size_local
353  real :: sum_area_local
354 
355 !-------------------------------------------------------------------------------
356 ! if routine has already been executed, exit.
357 !-------------------------------------------------------------------------------
358  if (module_is_initialized) return
359 
360 !-------------------------------------------------------------------------------
361 ! verify that modules used by this module that are not called later
362 ! have already been initialized.
363 !-------------------------------------------------------------------------------
364  call fms_init
365  call mpp_init
366  call constants_init
367  call time_manager_init
368 
369 !-------------------------------------------------------------------------------
370 ! if this is the initialization call, proceed. if this was simply
371 ! a verification of previous initialization, return.
372 !-------------------------------------------------------------------------------
373  if (present(time_init) .and. present(time) .and. &
374  present(blon) .and. present(blat) ) then
375 
376 !-------------------------------------------------------------------------------
377 ! read namelist.
378 !-------------------------------------------------------------------------------
379  if ( file_exist('input.nml')) then
380 #ifdef INTERNAL_FILE_NML
381  read (input_nml_file, nml=diag_integral_nml, iostat=io)
382  ierr = check_nml_error(io,'diag_integral_nml')
383 #else
384  unit = open_namelist_file( )
385  ierr=1; do while (ierr /= 0)
386  read (unit, nml=diag_integral_nml, iostat=io, end=10)
387  ierr = check_nml_error(io,'diag_integral_nml')
388  end do
389 10 call close_file (unit)
390 #endif
391  endif
392 
393 !-------------------------------------------------------------------------------
394 ! write version number and namelist to logfile.
395 !-------------------------------------------------------------------------------
396  call write_version_number (version, tagname)
397  logunit = stdlog()
398  if (mpp_pe() == mpp_root_pe() ) &
399  write (logunit, nml=diag_integral_nml)
400 
401 !-------------------------------------------------------------------------------
402 ! save the initial time to time-stamp the integrals which will be
403 ! calculated.
404 !-------------------------------------------------------------------------------
405  time_init_save = time_init
406 
407 !-------------------------------------------------------------------------------
408 ! define the model grid sizes and the total number of columns on
409 ! the processor. sum over all processors and store the global
410 ! number of columns in field_size.
411 !-------------------------------------------------------------------------------
412  idim = size(blon,1) - 1
413  jdim = size(blon,2) - 1
414  field_size_local = idim*jdim
415  rsize = real(field_size_local)
416  call mpp_sum (rsize)
417  field_size = nint(rsize)
418 
419 !-------------------------------------------------------------------------------
420 ! define an array to hold the surface area of each grid column
421 ! so that the integrals may be weighted properly. sum over the
422 ! processor, and then over all processors, storing the total
423 ! global surface area in sum_area.
424 !-------------------------------------------------------------------------------
425  allocate (area(idim,jdim))
426 
427  area = area_in
428 
429  sum_area_local = sum(area)
430  sum_area = sum_area_local
431  call mpp_sum (sum_area)
432 
433 !-------------------------------------------------------------------------------
434 ! if integral output is to go to a file, open the file on unit
435 ! diag_unit.
436 !-------------------------------------------------------------------------------
437  if (file_name(1:1) /= ' ' ) then
438  nc = len_trim(file_name)
439  diag_unit = open_file(file_name(1:nc), action='write')
440  endif
441 
442 !-------------------------------------------------------------------------------
443 ! define the variables needed to control the time interval of
444 ! output. Zero time is a flag indicating that the alarm is not set,
445 ! i.e., integrals are not desired. otherwise set the next time to
446 ! output integrals to be at the value of nml variable
447 ! output_interval from now.
448 !-------------------------------------------------------------------------------
449  zero_time = set_time(0,0)
450  if (output_interval >= -0.01) then
453  else
455  endif
457 
458 !-------------------------------------------------------------------------------
459 ! deallocate the local array and mark the module as initialized.
460 !-------------------------------------------------------------------------------
461  module_is_initialized = .true.
462  endif ! (present optional arguments)
463 
464 end subroutine diag_integral_init
465 
466 
467 
468 !###############################################################################
469 !> \fn diag_integral_field_init
470 !!
471 !! \brief diag_integral_field_init registers and intializes an integral field
472 !!
473 !! <b> Template: </b>
474 !!
475 !! \code{.f90}
476 !! call diag_integral_field_init (name, format)
477 !! \endcode
478 !!
479 !! <b> Parameters: </b>
480 !!
481 !! \code{.f90}
482 !! character(len=*), intent(in) :: name, format
483 !! \endcode
484 !!
485 !! \param [in] <name> Name of the field to be integrated
486 !! \param [in] <format> Output format of the field to be integrated
487 !!
488 subroutine diag_integral_field_init (name, format)
490 character(len=*), intent(in) :: name, format
491 
492 !-------------------------------------------------------------------------------
493 ! local variables:
494 !-------------------------------------------------------------------------------
495  integer :: field ! index assigned to the current integral
496 
497 !-------------------------------------------------------------------------------
498 ! note: no initialization is required for this interface. all needed
499 ! variables are initialized in the source.
500 !-------------------------------------------------------------------------------
501 
502 !-------------------------------------------------------------------------------
503 ! make sure the integral name is not too long.
504 !-------------------------------------------------------------------------------
505  if (len(name) > max_len_name ) then
506  call error_mesg ('diag_integral_mod', &
507  ' integral name too long', fatal)
508  endif
509 
510 !-------------------------------------------------------------------------------
511 ! check to be sure the integral name has not already been
512 ! initialized.
513 !-------------------------------------------------------------------------------
514  field = get_field_index(name)
515  if (field /= 0) then
516  call error_mesg ('diag_integral_mod', &
517  'integral name already exists', fatal)
518  endif
519 
520 !-------------------------------------------------------------------------------
521 ! prepare to register the integral. make sure that there are not
522 ! more integrals registered than space was provided for; if so, exit.
523 !-------------------------------------------------------------------------------
524  num_field = num_field + 1
525  if (num_field > max_num_field) then
526  call error_mesg ('diag_integral_mod', &
527  'too many fields initialized', fatal)
528  endif
529 
530 !-------------------------------------------------------------------------------
531 ! register the name and output format desired for the given integral.
532 ! initialize its value and the number of grid points that have been
533 ! counted to zero.
534 !-------------------------------------------------------------------------------
535  field_name(num_field) = name
536  field_format(num_field) = format
537  field_sum(num_field) = 0.0
539 
540 end subroutine diag_integral_field_init
541 
542 
543 
544 !###############################################################################
545 !> \fn sum_field_2d
546 !! \implements sum_diag_integral_field
547 !!
548 !! \brief Perform a 2 dimensional summation of named field
549 !!
550 !! <b> Template: </b>
551 !!
552 !! \code{.f90}
553 !! call sum_field_2d (name, data, is, js)
554 !! \endcode
555 !!
556 !! <b> Parameters: </b>
557 !!
558 !! \code{.f90}
559 !! character(len=*), intent(in) :: name
560 !! real, intent(in) :: data(:,:)
561 !! integer, optional, intent(in) :: is, js
562 !! \endcode
563 !!
564 !! \param [in] <name> Name of the field to be integrated
565 !! \param [in] <data> field of integrands to be summed over
566 !! \param [in] <is, js> starting i,j indices over which summation is to occur
567 !!
568 subroutine sum_field_2d (name, data, is, js)
570 character(len=*), intent(in) :: name
571 real, intent(in) :: data(:,:)
572 integer, optional, intent(in) :: is, js
573 
574 !-------------------------------------------------------------------------------
575 ! local variables:
576 !-------------------------------------------------------------------------------
577  integer :: field ! index of desired integral
578  integer :: i1, j1, i2, j2 ! location indices of current data in
579  ! processor-global coordinates
580 
581 !-------------------------------------------------------------------------------
582 ! be sure module has been initialized.
583 !-------------------------------------------------------------------------------
584  if (.not. module_is_initialized ) then
585  call error_mesg ('diag_integral_mod', &
586  'module has not been initialized', fatal )
587  endif
588 
589 !-------------------------------------------------------------------------------
590 ! obtain the index of the current integral. make certain it is valid.
591 !-------------------------------------------------------------------------------
592  field = get_field_index(name)
593  if (field == 0) then
594  call error_mesg ('diag_integral_mod', &
595  'field does not exist', fatal)
596  endif
597 
598 !-------------------------------------------------------------------------------
599 ! define the processor-global indices of the current data. use the
600 ! value 1 for the initial grid points, if is and js are not input.
601 !-------------------------------------------------------------------------------
602  i1 = 1; if (present(is)) i1 = is
603  j1 = 1; if (present(js)) j1 = js
604  i2 = i1 + size(data,1) - 1
605  j2 = j1 + size(data,2) - 1
606 
607 !-------------------------------------------------------------------------------
608 ! increment the count of points toward this integral and add the
609 ! values at this set of grid points to the accumulation array.
610 !-------------------------------------------------------------------------------
611 !$OMP CRITICAL
612  field_count(field) = field_count(field) + &
613  size(data,1)*size(data,2)
614  field_sum(field) = field_sum(field) + &
615  sum(data * area(i1:i2,j1:j2))
616 
617 !$OMP END CRITICAL
618 
619 end subroutine sum_field_2d
620 
621 
622 
623 !###############################################################################
624 !> \fn sum_field_3d
625 !! \implements sum_diag_integral_field
626 !!
627 !! \brief Perform a 3 dimensional summation of named field
628 !!
629 !! <b> Template: </b>
630 !!
631 !! \code{.f90}
632 !! call sum_field_3d (name, data, is, js)
633 !! \endcode
634 !!
635 !! <b> Parameters: </b>
636 !!
637 !! \code{.f90}
638 !! character(len=*), intent(in) :: name
639 !! real, intent(in) :: data(:,:,:)
640 !! integer, optional, intent(in) :: is, js
641 !! \endcode
642 !!
643 !! \param [in] <name> Name of the field to be integrated
644 !! \param [in] <data> field of integrands to be summed over
645 !! \param [in] <is, js> starting i,j indices over which summation is to occur
646 !!
647 subroutine sum_field_3d (name, data, is, js)
649 character(len=*), intent(in) :: name
650 real, intent(in) :: data(:,:,:)
651 integer, optional, intent(in) :: is, js
652 
653 !-------------------------------------------------------------------------------
654 ! local variables:
655 ! data2
656 ! field ! index of desired integral
657 ! i1, j1, i2, j2 ! location indices of current data in
658 ! processor-global coordinates
659 !-------------------------------------------------------------------------------
660  real, dimension (size(data,1), & size(data,2)) :: data2
661 
662  integer :: field
663  integer :: i1, j1, i2, j2
664 
665 
666 !-------------------------------------------------------------------------------
667 ! be sure module has been initialized.
668 !-------------------------------------------------------------------------------
669  if (.not. module_is_initialized ) then
670  call error_mesg ('diag_integral_mod', &
671  'module has not been initialized', fatal )
672  endif
673 
674 !-------------------------------------------------------------------------------
675 ! obtain the index of the current integral. make certain it is valid.
676 !-------------------------------------------------------------------------------
677  field = get_field_index(name)
678  if (field == 0) then
679  call error_mesg ('diag_integral_mod', &
680  'field does not exist', fatal)
681  endif
682 
683 !-------------------------------------------------------------------------------
684 ! define the processor-global indices of the current data. use the
685 ! value 1 for the initial grid points, if is and js are not input.
686 !-------------------------------------------------------------------------------
687  i1 = 1; if (present(is)) i1 = is
688  j1 = 1; if (present(js)) j1 = js
689  i2 = i1 + size(data,1) - 1
690  j2 = j1 + size(data,2) - 1
691 
692 !-------------------------------------------------------------------------------
693 ! increment the count of points toward this integral. sum first
694 ! in the vertical and then add the values at this set of grid points
695 ! to the accumulation array.
696 !-------------------------------------------------------------------------------
697 !$OMP CRITICAL
698  field_count(field) = field_count(field) + &
699  size(data,1)*size(data,2)
700  data2 = sum(data,3)
701  field_sum(field) = field_sum(field) + &
702  sum(data2 * area(i1:i2,j1:j2))
703 
704 !$OMP END CRITICAL
705 
706 end subroutine sum_field_3d
707 
708 
709 
710 !###############################################################################
711 !> \fn sum_field_wght_3d
712 !! \implements sum_diag_integral_field
713 !!
714 !! \brief Perform a 3 dimensional weighted summation of named field
715 !!
716 !! <b> Template: </b>
717 !!
718 !! \code{.f90}
719 !! call sum_field_wght_3d (name, data, wt, is, js)
720 !! \endcode
721 !!
722 !! <b> Parameters: </b>
723 !!
724 !! \code{.f90}
725 !! character(len=*), intent(in) :: name
726 !! real, intent(in) :: data(:,:,:), wt(:,:,:)
727 !! integer, optional, intent(in) :: is, js
728 !! \endcode
729 !!
730 !! \param [in] <name> Name of the field to be integrated
731 !! \param [in] <data> field of integrands to be summed over
732 !! \param [in] <wt> the weight function to be evaluated at summation
733 !! \param [in] <is, js> starting i,j indices over which summation is to occur
734 !!
735 subroutine sum_field_wght_3d (name, data, wt, is, js)
736 
737 character(len=*), intent(in) :: name
738 real, intent(in) :: data(:,:,:), wt(:,:,:)
739 integer, optional, intent(in) :: is, js
740 
741 !-------------------------------------------------------------------------------
742 ! local variables:
743 ! data2
744 ! field ! index of desired integral
745 ! i1, j1, i2, j2 ! location indices of current data in
746 ! processor-global coordinates
747 !-------------------------------------------------------------------------------
748  real, dimension (size(data,1),size(data,2)) :: data2
749  integer :: field, i1, j1, i2, j2
750 
751 !-------------------------------------------------------------------------------
752 ! be sure module has been initialized.
753 !-------------------------------------------------------------------------------
754  if (.not. module_is_initialized ) then
755  call error_mesg ('diag_integral_mod', &
756  'module has not been initialized', fatal )
757  endif
758 
759 !-------------------------------------------------------------------------------
760 ! obtain the index of the current integral. make certain it is valid.
761 !-------------------------------------------------------------------------------
762  field = get_field_index(name)
763  if (field == 0) then
764  call error_mesg ('diag_integral_mod', &
765  'field does not exist', fatal)
766  endif
767 
768 !-------------------------------------------------------------------------------
769 ! define the processor-global indices of the current data. use the
770 ! value 1 for the initial grid points, if is and js are not input.
771 !-------------------------------------------------------------------------------
772  i1 = 1; if (present(is)) i1 = is
773  j1 = 1; if (present(js)) j1 = js
774  i2 = i1 + size(data,1) - 1
775  j2 = j1 + size(data,2) - 1
776 
777 !-------------------------------------------------------------------------------
778 ! increment the count of points toward this integral. sum first
779 ! in the vertical (including a vertical weighting factor) and then
780 ! add the values at this set of grid points to the accumulation
781 ! array.
782 !-------------------------------------------------------------------------------
783 !$OMP CRITICAL
784  field_count(field) = field_count(field) + &
785  size(data,1)*size(data,2)
786  data2 = vert_diag_integral(data, wt)
787  field_sum(field) = field_sum(field) + &
788  sum(data2 * area(i1:i2,j1:j2))
789 
790 !$OMP END CRITICAL
791 
792 end subroutine sum_field_wght_3d
793 
794 
795 
796 !###############################################################################
797 !> \fn sum_field_2d_hemi
798 !! \implements sum_diag_integral_field
799 !!
800 !! \brief Perform a 2 dimensional hemispherical summation of named field
801 !!
802 !! <b> Template: </b>
803 !!
804 !! \code{.f90}
805 !! call sum_field_2d_hemi (name, data, is, ie, js, je)
806 !! \endcode
807 !!
808 !! <b> Parameters: </b>
809 !!
810 !! \code{.f90}
811 !! character(len=*), intent(in) :: name
812 !! real, intent(in) :: data(:,:)
813 !! integer, intent(in) :: is, js, ie, je
814 !! \endcode
815 !!
816 !! \param [in] <name> Name of the field to be integrated
817 !! \param [in] <data> field of integrands to be summed over
818 !! \param [in] <is, js, ie, je> starting/ending i,j indices over which summation
819 !! is to occur
820 !!
821 subroutine sum_field_2d_hemi (name, data, is, ie, js, je)
822 
823 character(len=*), intent(in) :: name
824 real, intent(in) :: data(:,:)
825 integer, intent(in) :: is, js, ie, je
826 
827 !-------------------------------------------------------------------------------
828 ! local variables:
829 ! field ! index of desired integral
830 ! i1, j1, i2, j2 ! location indices of current data in
831 ! processor-global coordinates
832 !-------------------------------------------------------------------------------
833  integer :: field, i1, j1, i2, j2
834 
835 !-------------------------------------------------------------------------------
836 ! be sure module has been initialized.
837 !-------------------------------------------------------------------------------
838  if (.not. module_is_initialized ) then
839  call error_mesg ('diag_integral_mod', &
840  'module has not been initialized', fatal )
841  endif
842 
843 !-------------------------------------------------------------------------------
844 ! obtain the index of the current integral. make certain it is valid.
845 !-------------------------------------------------------------------------------
846  field = get_field_index(name)
847  if (field == 0) then
848  call error_mesg ('diag_integral_mod', &
849  'field does not exist', fatal)
850  endif
851 
852 !-------------------------------------------------------------------------------
853 ! define the processor-global indices of the current data. this form
854 ! is needed to handle case of 2d domain decomposition with physics
855 ! window smaller than processor domain size.
856 !-------------------------------------------------------------------------------
857  i1 = mod( (is-1), size(data,1) ) + 1
858  i2 = i1 + size(data,1) - 1
859 
860 !-------------------------------------------------------------------------------
861 ! for a hemispheric sum, sum one jrow at a time in case a processor
862 ! has data from both hemispheres.
863 !-------------------------------------------------------------------------------
864  j1 = mod( (js-1) ,size(data,2) ) + 1
865  j2 = j1
866 
867 !-------------------------------------------------------------------------------
868 ! increment the count of points toward this integral. include hemi-
869 ! spheric factor of 2 in field_count. add the data values at this
870 ! set of grid points to the accumulation array.
871 !-------------------------------------------------------------------------------
872 !$OMP CRITICAL
873  field_count(field) = field_count(field) + 2* (i2-i1+1)*(j2-j1+1)
874  field_sum(field) = field_sum(field) + &
875  sum(data(i1:i2,j1:j2)*area(is:ie,js:je))
876 
877 !$OMP END CRITICAL
878 
879 end subroutine sum_field_2d_hemi
880 
881 
882 
883 !###############################################################################
884 !> \fn diag_integral_output
885 !!
886 !! \brief diag_integral_output determines if this is a timestep on which
887 !! integrals are to be written. if not, it returns; if so, it calls
888 !! write_field_averages.
889 !!
890 !!
891 !! <b> Template: </b>
892 !!
893 !! \code{.f90}
894 !! call diag_integral_output (Time)
895 !! \endcode
896 !!
897 !! <b> Parameters: </b>
898 !!
899 !! \code{.f90}
900 !! type (time_type), intent(in) :: Time
901 !! \endcode
902 !!
903 !! \param [in] <Time> integral time stamp at the current time
904 !!
905 subroutine diag_integral_output (Time)
906 
907 type(time_type), intent(in) :: time
908 
909 !-------------------------------------------------------------------------------
910 ! be sure module has been initialized.
911 !-------------------------------------------------------------------------------
912  if (.not. module_is_initialized ) then
913  call error_mesg ('diag_integral_mod', &
914  'module has not been initialized', fatal )
915  endif
916 
917 !-------------------------------------------------------------------------------
918 ! see if integral output is desired at this time.
919 !-------------------------------------------------------------------------------
920  if ( diag_integral_alarm(time) ) then
921 
922 !-------------------------------------------------------------------------------
923 ! write the integrals by calling write_field_averages. upon return
924 ! reset the alarm to the next diagnostics time.
925 !-------------------------------------------------------------------------------
926  call write_field_averages (time)
928  endif
929 
930 end subroutine diag_integral_output
931 
932 
933 
934 !###############################################################################
935 !> \fn diag_integral_end
936 !!
937 !! \brief diag_integral_end is the destructor for diag_integral_mod.
938 !!
939 !! <b> Template: </b>
940 !!
941 !! \code{.f90}
942 !! call diag_integral_end (Time)
943 !! \endcode
944 !!
945 !! <b> Parameters: </b>
946 !!
947 !! \code{.f90}
948 !! type (time_type), intent(in) :: Time
949 !! \endcode
950 !!
951 !! \param [in] <Time> integral time stamp at the current time
952 !!
953 subroutine diag_integral_end (Time)
954 
955 type(time_type), intent(in) :: time
956 
957 !-------------------------------------------------------------------------------
958 ! be sure module has been initialized.
959 !-------------------------------------------------------------------------------
960  if (.not. module_is_initialized ) then
961  call error_mesg ('diag_integral_mod', &
962  'module has not been initialized', fatal )
963  endif
964 
965 !-------------------------------------------------------------------------------
966 ! if the alarm interval was set to Zero_time (meaning no integral
967 ! output during the model run) call write_field_averages to output
968 ! the integrals valid over the entire period of integration.
969 !-------------------------------------------------------------------------------
970  if (alarm_interval == zero_time ) then
971 ! if (Alarm_interval /= Zero_time ) then
972 ! else
973  call write_field_averages (time)
974  endif
975 
976 !-------------------------------------------------------------------------------
977 ! deallocate module variables.
978 !-------------------------------------------------------------------------------
979  deallocate (area)
980 
981 !-------------------------------------------------------------------------------
982 ! mark the module as uninitialized.
983 !-------------------------------------------------------------------------------
984  module_is_initialized = .false.
985 
986 end subroutine diag_integral_end
987 
988 
989 
990 !###############################################################################
991 !
992 ! PRIVATE SUBROUTINES
993 !
994 !###############################################################################
995 
996 
997 
998 !###############################################################################
999 !> \fn set_axis_time
1000 !!
1001 !! \brief Function to convert input time to a time_type
1002 !!
1003 !! <b> Template: </b>
1004 !!
1005 !! \code{.f90}
1006 !! time = set_axis_time (atime, units)
1007 !! \endcode
1008 !!
1009 !! <b> Parameters: </b>
1010 !!
1011 !! \code{.f90}
1012 !! real, intent(in) :: atime
1013 !! character(len=*), intent(in) :: units
1014 !! type(time_type) :: Time
1015 !! \endcode
1016 !!
1017 !! \param [in] <atime> integral time stamp at the current time
1018 !! \param [in] <units> input units, not used
1019 !! \param [out] <Time>
1020 !!
1021 function set_axis_time (atime, units) result (Time)
1022 
1023 real, intent(in) :: atime
1024 character(len=*), intent(in) :: units
1025 type(time_type) :: time
1026 
1027 !-------------------------------------------------------------------------------
1028 ! local variables:
1029 !-------------------------------------------------------------------------------
1030  integer :: sec ! seconds corresponding to the input
1031  ! variable atime
1032  integer :: day = 0 ! day component of time_type variable
1033 
1034 !-------------------------------------------------------------------------------
1035 ! convert the input time to seconds, regardless of input units.
1036 !-------------------------------------------------------------------------------
1037  if (units(1:3) == 'sec') then
1038  sec = int(atime + 0.5)
1039  else if (units(1:3) == 'min') then
1040  sec = int(atime*60. + 0.5)
1041  else if (units(1:3) == 'hou') then
1042  sec = int(atime*3600. + 0.5)
1043  else if (units(1:3) == 'day') then
1044  sec = int(atime*86400. + 0.5)
1045  else
1046  call error_mesg('diag_integral_mod', &
1047  'Invalid units sent to set_axis_time', fatal)
1048  endif
1049 
1050 !-------------------------------------------------------------------------------
1051 ! convert the time in seconds to a time_type variable.
1052 !-------------------------------------------------------------------------------
1053  time = set_time(sec, day)
1054 
1055 end function set_axis_time
1056 
1057 
1058 
1059 !###############################################################################
1060 !> \fn get_field_index
1061 !!
1062 !! \brief get_field_index returns returns the index associated with an
1063 !! integral name.
1064 !!
1065 !! <b> Template: </b>
1066 !!
1067 !! \code{.f90}
1068 !! index = get_field_index (name)
1069 !! \endcode
1070 !!
1071 !! <b> Parameters: </b>
1072 !!
1073 !! \code{.f90}
1074 !! character(len=*), intent(in) :: name
1075 !! integer :: index
1076 !! \endcode
1077 !!
1078 !! \param [in] <name> Name associated with an integral
1079 !! \param [out] <index>
1080 !!
1081 function get_field_index (name) result (index)
1082 
1083 character(len=*), intent(in) :: name
1084 integer :: index
1085 
1086 !-------------------------------------------------------------------------------
1087 ! local variables:
1088 !-------------------------------------------------------------------------------
1089  integer :: nc
1090  integer :: i
1091 
1092  nc = len_trim(name)
1093  if (nc > max_len_name) then
1094  call error_mesg ('diag_integral_mod', &
1095  'name too long', fatal)
1096  endif
1097 
1098 !-------------------------------------------------------------------------------
1099 ! search each field name for the current string. when found exit
1100 ! with the index. if not found index will be 0 upon return, which
1101 ! initiates error condition.
1102 !-------------------------------------------------------------------------------
1103  index = 0
1104  do i = 1, num_field
1105  if (name(1:nc) == &
1106  field_name(i) (1:len_trim(field_name(i))) ) then
1107  index = i
1108  exit
1109  endif
1110  end do
1111 
1112 end function get_field_index
1113 
1114 
1115 
1116 !###############################################################################
1117 !> \fn write_field_averages
1118 !!
1119 !! \brief Subroutine to sum multiple fields, average them and then write the
1120 !! result to an output file.
1121 !!
1122 !! <b> Template: </b>
1123 !!
1124 !! \code{.f90}
1125 !! call write_field_averages (Time)
1126 !! \endcode
1127 !!
1128 !! <b> Parameters: </b>
1129 !!
1130 !! \code{.f90}
1131 !! type (time_type), intent(in) :: Time
1132 !! \endcode
1133 !!
1134 !! \param [in] <Time> integral time stamp at the current time
1135 !!
1136 subroutine write_field_averages (Time)
1137 
1138 type(time_type), intent(in) :: time
1139 
1140 !-------------------------------------------------------------------------------
1141 ! local variables:
1142 ! field_avg
1143 ! xtime
1144 ! rcount
1145 ! nn
1146 ! ninc
1147 ! nst
1148 ! nend
1149 ! fields_to_print
1150 ! i
1151 ! kount
1152 !-------------------------------------------------------------------------------
1153  real :: field_avg(max_num_field)
1154  real :: xtime, rcount
1155  integer :: nn, ninc, nst, nend, fields_to_print
1156  integer :: i, kount
1157  integer(LONG_KIND) :: icount
1158 
1159 !-------------------------------------------------------------------------------
1160 ! each header and data format may be different and must be generated
1161 ! as needed.
1162 !-------------------------------------------------------------------------------
1163  fields_to_print = 0
1164  do i = 1, num_field
1165 
1166 !-------------------------------------------------------------------------------
1167 ! increment the fields_to_print counter. sum the integrand and the
1168 ! number of data points contributing to it over all processors.
1169 !-------------------------------------------------------------------------------
1170  fields_to_print = fields_to_print + 1
1171  rcount = real(field_count(i))
1172  call mpp_sum (rcount)
1173  call mpp_sum (field_sum(i))
1174  icount = rcount
1175 
1176 !-------------------------------------------------------------------------------
1177 ! verify that all the data expected for an integral has been
1178 ! obtained.
1179 !-------------------------------------------------------------------------------
1180  if (icount == 0 ) call error_mesg &
1181  ('diag_integral_mod', &
1182  'field_count equals zero for field_name ' // &
1183  field_name(i)(1:len_trim(field_name(i))), fatal )
1184  kount = icount/field_size
1185  if ((field_size)*kount /= icount) then
1186  print*,"name,pe,kount,field_size,icount,rcount=",trim(field_name(i)),mpp_pe(),kount,field_size,icount,rcount
1187  call error_mesg &
1188  ('diag_integral_mod', &
1189  'field_count not a multiple of field_size', fatal )
1190  endif
1191 !-------------------------------------------------------------------------------
1192 ! define the global integral for field i. reinitialize the point
1193 ! and data accumulators.
1194 !-------------------------------------------------------------------------------
1195  field_avg(fields_to_print) = field_sum(i)/ &
1196  (sum_area*float(kount))
1197  field_sum(i) = 0.0
1198  field_count(i) = 0
1199  end do
1200 
1201 !-------------------------------------------------------------------------------
1202 ! only the root pe will write out data.
1203 !-------------------------------------------------------------------------------
1204  if ( mpp_pe() /= mpp_root_pe() ) return
1205 
1206 !-------------------------------------------------------------------------------
1207 ! define the time associated with the integrals just calculated.
1208 !-------------------------------------------------------------------------------
1209  xtime = get_axis_time(time-time_init_save, time_units)
1210 
1211 !-------------------------------------------------------------------------------
1212 ! generate the new header and data formats.
1213 !-------------------------------------------------------------------------------
1214  nst = 1
1215  nend = fields_per_print_line
1216  ninc = (num_field-1)/fields_per_print_line + 1
1217  do nn=1, ninc
1218  nst = 1 + (nn-1)*fields_per_print_line
1219  nend = min(nn*fields_per_print_line, num_field)
1220  if (print_header) call format_text_init (nst, nend)
1221  call format_data_init (nst, nend)
1222  if (diag_unit /= 0) then
1223  write (diag_unit,format_data(1:nd)) &
1224  xtime, (field_avg(i),i=nst,nend)
1225  else
1226  write (*, format_data(1:nd)) &
1227  xtime, (field_avg(i),i=nst,nend)
1228  endif
1229  end do
1230 
1231 end subroutine write_field_averages
1232 
1233 
1234 
1235 !###############################################################################
1236 !> \fn format_text_init
1237 !!
1238 !! \brief format_text_init generates the header records to be output in the
1239 !! integrals file.
1240 !!
1241 !! <b> Template: </b>
1242 !!
1243 !! \code{.f90}
1244 !! call format_text_init (nst_in, nend_in)
1245 !! \endcode
1246 !!
1247 !! <b> Parameters: </b>
1248 !!
1249 !! \code{.f90}
1250 !! integer, intent(in), optional :: nst_in, nend_in
1251 !! \endcode
1252 !!
1253 !! \param [in] <nst_in, nend_in> starting/ending integral index which will be
1254 !! included in this format statement
1255 !!
1256 subroutine format_text_init (nst_in, nend_in)
1257 
1258 integer, intent(in), optional :: nst_in, nend_in
1259 
1260 !-------------------------------------------------------------------------------
1261 ! local variables:
1262 ! i
1263 ! nc
1264 ! nst
1265 ! nend
1266 !-------------------------------------------------------------------------------
1267  integer :: i, nc, nst, nend
1268 
1269 !-------------------------------------------------------------------------------
1270 ! only the root pe need execute this routine, since only it will
1271 ! be outputting integrals.
1272 !-------------------------------------------------------------------------------
1273  if (mpp_pe() /= mpp_root_pe()) return
1274 
1275 !-------------------------------------------------------------------------------
1276 ! define the starting and ending integral indices that will be
1277 ! included in this format statement.
1278 !-------------------------------------------------------------------------------
1279  if (present (nst_in) ) then
1280  nst = nst_in
1281  nend = nend_in
1282  else
1283  nst = 1
1284  nend = num_field
1285  endif
1286 
1287 !-------------------------------------------------------------------------------
1288 ! define the first 11 characters in the format statement.
1289 !-------------------------------------------------------------------------------
1290  nt = 11
1291  format_text(1:nt) = "('# time"
1292 
1293 !-------------------------------------------------------------------------------
1294 ! generate the rest of the format statement, which will cover
1295 ! integral indices nst to nend. if satndard printout is desired,
1296 ! cycle through the loop.
1297 !-------------------------------------------------------------------------------
1298  do i=nst,nend
1299  nc = len_trim(field_name(i))
1300  format_text(nt+1:nt+nc+5) = ' ' // field_name(i)(1:nc)
1301  nt = nt+nc+5
1302  end do
1303 
1304 !-------------------------------------------------------------------------------
1305 ! include the end of the format statement.
1306 !-------------------------------------------------------------------------------
1307  format_text(nt+1:nt+2) = "')"
1308  nt = nt+2
1309 
1310 !-------------------------------------------------------------------------------
1311 ! write the format statement to either an output file or to stdout.
1312 !-------------------------------------------------------------------------------
1313  if (diag_unit /= 0) then
1314  write (diag_unit, format_text(1:nt))
1315  else
1316  write (*, format_text(1:nt))
1317  endif
1318 
1319 end subroutine format_text_init
1320 
1321 
1322 
1323 !###############################################################################
1324 !> \fn format_data_init
1325 !!
1326 !! \brief format_text_init generates the format to be output in the
1327 !! integrals file.
1328 !!
1329 !! <b> Template: </b>
1330 !!
1331 !! \code{.f90}
1332 !! call format_data_init (nst_in, nend_in)
1333 !! \endcode
1334 !!
1335 !! <b> Parameters: </b>
1336 !!
1337 !! \code{.f90}
1338 !! integer, intent(in), optional :: nst_in, nend_in
1339 !! \endcode
1340 !!
1341 !! \param [in] <nst_in, nend_in> starting/ending integral index which will be
1342 !! included in this format statement
1343 !!
1344 subroutine format_data_init (nst_in, nend_in)
1345 
1346 integer, intent(in), optional :: nst_in, nend_in
1347 
1348 !-------------------------------------------------------------------------------
1349 ! local variables:
1350 ! i
1351 ! nc
1352 ! nst
1353 ! nend
1354 !-------------------------------------------------------------------------------
1355  integer :: i, nc, nst, nend
1356 
1357 !-------------------------------------------------------------------------------
1358 ! define the start of the format, which covers the time stamp of the
1359 ! integrals. this section is 9 characters long.
1360 !-------------------------------------------------------------------------------
1361  nd = 9
1362  format_data(1:nd) = '(1x,f10.2'
1363 
1364 !-------------------------------------------------------------------------------
1365 ! define the indices of the integrals that are to be written by this
1366 ! format statement.
1367 !-------------------------------------------------------------------------------
1368  if ( present (nst_in) ) then
1369  nst = nst_in
1370  nend = nend_in
1371  else
1372  nst = 1
1373  nend = num_field
1374  endif
1375 
1376 !-------------------------------------------------------------------------------
1377 ! complete the data format. use the format defined for the
1378 ! particular integral in setting up the format statement.
1379 !-------------------------------------------------------------------------------
1380  do i=nst,nend
1381  nc = len_trim(field_format(i))
1382  format_data(nd+1:nd+nc+5) = ',1x,' // field_format(i)(1:nc)
1383  nd = nd+nc+5
1384  end do
1385 
1386 !-------------------------------------------------------------------------------
1387 ! close the format statement.
1388 !-------------------------------------------------------------------------------
1389  format_data(nd+1:nd+1) = ')'
1390  nd = nd + 1
1391 
1392 end subroutine format_data_init
1393 
1394 
1395 
1396 !###############################################################################
1397 !> \fn get_axis_time
1398 !!
1399 !! \brief Function to convert the time_type input variable into units of
1400 !! units and returns it in atime.
1401 !!
1402 !! <b> Template: </b>
1403 !!
1404 !! \code{.f90}
1405 !! atime = get_axis_time (Time, units)
1406 !! \endcode
1407 !!
1408 !! <b> Parameters: </b>
1409 !!
1410 !! \code{.f90}
1411 !! type(time_type), intent(in) :: Time
1412 !! character(len=*), intent(in) :: units
1413 !! real :: atime
1414 !! \endcode
1415 !!
1416 !! \param [in] <Time> integral time stamp
1417 !! \param [in] <units> input units of time_type
1418 !! \param [out] <atime>
1419 !!
1420 function get_axis_time (Time, units) result (atime)
1421 
1422 type(time_type), intent(in) :: time
1423 character(len=*), intent(in) :: units
1424 real :: atime
1425 
1426 !-------------------------------------------------------------------------------
1427 ! local variables:
1428 !-------------------------------------------------------------------------------
1429  integer :: sec, day ! components of time_type variable
1430 
1431  call get_time (time, sec, day)
1432  if (units(1:3) == 'sec') then
1433  atime = float(sec) + 86400.*float(day)
1434  else if (units(1:3) == 'min') then
1435  atime = float(sec)/60. + 1440.*float(day)
1436  else if (units(1:3) == 'hou') then
1437  atime = float(sec)/3600. + 24.*float(day)
1438  else if (units(1:3) == 'day') then
1439  atime = float(sec)/86400. + float(day)
1440  endif
1441 
1442 end function get_axis_time
1443 
1444 
1445 
1446 !###############################################################################
1447 !> \fn diag_integral_alarm
1448 !!
1449 !! \brief Function to check if it is time to write integrals.
1450 !! if not writing integrals, return.
1451 !!
1452 !! <b> Template: </b>
1453 !!
1454 !! \code{.f90}
1455 !! result = diag_integral_alarm (Time)
1456 !! \endcode
1457 !!
1458 !! <b> Parameters: </b>
1459 !!
1460 !! \code{.f90}
1461 !! type (time_type), intent(in) :: Time
1462 !! logical :: answer
1463 !! \endcode
1464 !!
1465 !! \param [in] <Time> current time
1466 !! \param [out] <answer>
1467 !!
1468 function diag_integral_alarm (Time) result (answer)
1469 
1470 type(time_type), intent(in) :: time
1471 logical :: answer
1472 
1473  answer = .false.
1474  if (alarm_interval == zero_time) return
1475  if (time >= next_alarm_time) answer = .true.
1476 
1477 end function diag_integral_alarm
1478 
1479 
1480 
1481 !###############################################################################
1482 !> \fn vert_diag_integral
1483 !!
1484 !! \brief Function to perform a weighted integral in the vertical
1485 !! direction of a 3d data field
1486 !!
1487 !! <b> Template: </b>
1488 !!
1489 !! \code{.f90}
1490 !! data2 = vert_diag_integral (data, wt)
1491 !! \endcode
1492 !!
1493 !! <b> Parameters: </b>
1494 !!
1495 !! \code{.f90}
1496 !! real, dimension (:,:,:), intent(in) :: data, wt
1497 !! real, dimension (size(data,1),size(data,2)) :: data2
1498 !! \endcode
1499 !!
1500 !! \param [in] <data> integral field data arrays
1501 !! \param [in] <wt> integral field weighting functions
1502 !! \param [out] <data2>
1503 function vert_diag_integral (data, wt) result (data2)
1504 
1505 real, dimension (:,:,:), intent(in) :: data, wt
1506 real, dimension (size(data,1),size(data,2)) :: data2
1507 
1508 !-------------------------------------------------------------------------------
1509 ! local variables:
1510 ! wt2
1511 !-------------------------------------------------------------------------------
1512  real, dimension(size(data,1),size(data,2)) :: wt2
1513 
1514 !-------------------------------------------------------------------------------
1515  wt2 = sum(wt,3)
1516  if (count(wt2 == 0.) > 0) then
1517  call error_mesg ('diag_integral_mod', &
1518  'vert sum of weights equals zero', fatal)
1519  endif
1520  data2 = sum(data*wt,3) / wt2
1521 
1522 end function vert_diag_integral
1523 
1524 
1525 
1526 
1527 
1528  end module diag_integral_mod
1529 
type(time_type) alarm_interval
Definition: fms.F90:20
subroutine sum_field_2d(name, data, is, js)
real, parameter, public radius
Radius of the Earth [m].
Definition: constants.F90:72
subroutine, private write_field_averages(Time)
real function, dimension(size(data, 1), size(data, 2)), private vert_diag_integral(data, wt)
character(len=160) format_text
integer, parameter max_num_field
character(len=8) time_units
type(time_type) function, private set_axis_time(atime, units)
subroutine, private format_data_init(nst_in, nend_in)
character(len=max_len_name), dimension(max_num_field) field_name
character(len=16), dimension(max_num_field) field_format
Definition: mpp.F90:39
integer function, public check_nml_error(IOSTAT, NML_NAME)
Definition: fms.F90:658
subroutine, private format_text_init(nst_in, nend_in)
subroutine, public diag_integral_init(Time_init, Time, blon, blat, area_in)
subroutine sum_field_3d(name, data, is, js)
subroutine, public diag_integral_field_init(name, format)
character(len=input_str_length), dimension(:), allocatable, target, public input_nml_file
Definition: mpp.F90:1378
character(len=128) tagname
character(len=128) version
logical function, private diag_integral_alarm(Time)
integer function, private get_field_index(name)
integer, dimension(max_num_field) field_count
integer, parameter mxch
subroutine, public fms_init(localcomm)
Definition: fms.F90:353
real, dimension(:,:), allocatable area
integer fields_per_print_line
subroutine sum_field_wght_3d(name, data, wt, is, js)
subroutine sum_field_2d_hemi(name, data, is, ie, js, je)
subroutine, public time_manager_init()
subroutine, public diag_integral_output(Time)
character(len=160) format_data
real function, private get_axis_time(Time, units)
character(len=mxch) file_name
type(time_type) time_init_save
real, dimension(max_num_field) field_sum
subroutine, public diag_integral_end(Time)
logical module_is_initialized
integer, parameter max_len_name
#define min(a, b)
Definition: mosaic_util.h:32
subroutine, public get_time(Time, seconds, days, ticks, err_msg)
subroutine, public error_mesg(routine, message, level)
Definition: fms.F90:529
type(time_type) zero_time
type(time_type) next_alarm_time
subroutine, public constants_init
dummy routine.
Definition: constants.F90:141