FMS  2026.01.01-dev
Flexible Modeling System
diag_data.F90
1 !***********************************************************************
2 !* Apache License 2.0
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* Licensed under the Apache License, Version 2.0 (the "License");
7 !* you may not use this file except in compliance with the License.
8 !* You may obtain a copy of the License at
9 !*
10 !* http://www.apache.org/licenses/LICENSE-2.0
11 !*
12 !* FMS is distributed in the hope that it will be useful, but WITHOUT
13 !* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied;
14 !* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15 !* PARTICULAR PURPOSE. See the License for the specific language
16 !* governing permissions and limitations under the License.
17 !***********************************************************************
18 !> @defgroup diag_data_mod diag_data_mod
19 !> @ingroup diag_manager
20 !! @brief Type descriptions and global variables for the diag_manager modules.
21 !! @author Seth Underwood <seth.underwood@noaa.gov>
22 !!
23 !! Notation:
24 !! <DL>
25 !! <DT>input field</DT>
26 !! <DD>The data structure describing the field as
27 !! registered by the model code.</DD>
28 !!
29 !! <DT>output field</DT>
30 !! <DD>The data structure describing the actual
31 !! diagnostic output with requested frequency and
32 !! other options.</DD>
33 !! </DL>
34 !!
35 !! Input fields, output fields, and output files are gathered in arrays called
36 !! "input_fields", "output_fields", and "files", respectively. Indices in these
37 !! arrays are used as pointers to create associations between various data
38 !! structures.
39 !!
40 !! Each input field associated with one or several output fields via array of
41 !! indices output_fields; each output field points to the single "parent" input
42 !! field with the input_field index, and to the output file with the output_file
43 !! index.
44 
45 !> @addtogroup diag_data_mod
46 !> @{
47 MODULE diag_data_mod
48 use platform_mod
49 
50  USE time_manager_mod, ONLY: get_calendar_type, no_calendar, set_date, set_time, month_name, time_type
51  USE constants_mod, ONLY: seconds_per_hour, seconds_per_minute
52  USE mpp_domains_mod, ONLY: domain1d, domain2d, domainug
53  USE fms_mod, ONLY: write_version_number
54  USE fms_diag_bbox_mod, ONLY: fmsdiagibounds_type
55  use mpp_mod, ONLY: mpp_error, fatal, warning, mpp_pe, mpp_root_pe, stdlog
56 
57  ! NF90_FILL_REAL has value of 9.9692099683868690e+36.
58  USE netcdf, ONLY: nf_fill_real => nf90_fill_real
59  use fms2_io_mod
60 
61  IMPLICIT NONE
62 
63  PUBLIC
64 
65  ! Specify storage limits for fixed size tables used for pointers, etc.
66  integer, parameter :: diag_null = -999 !< Integer represening NULL in the diag_object
67  character(len=1), parameter :: diag_null_string = " "
68  integer, parameter :: diag_not_found = -1
69  integer, parameter :: diag_not_registered = 0
70  integer, parameter :: diag_registered_id = 10
71  !> Supported averaging intervals
72  integer, parameter :: monthly = 30
73  integer, parameter :: daily = 24
74  integer, parameter :: diurnal = 2
75  integer, parameter :: yearly = 12
76  integer, parameter :: no_diag_averaging = 0
77  integer, parameter :: instantaneous = 0
78  integer, parameter :: three_hourly = 3
79  integer, parameter :: six_hourly = 6
80  !integer, parameter :: seasonally = 180
81  !> Supported type/kind of the variable
82  !integer, parameter :: r16=16
83  integer, parameter :: r8 = 8
84  integer, parameter :: r4 = 4
85  integer, parameter :: i8 = -8
86  integer, parameter :: i4 = -4
87  integer, parameter :: string = 19 !< s is the 19th letter of the alphabet
88  integer, parameter :: null_type_int = -999
89  INTEGER, PARAMETER :: max_fields_per_file = 300 !< Maximum number of fields per file.
90  INTEGER, PARAMETER :: diag_other = 0
91  INTEGER, PARAMETER :: diag_ocean = 1
92  INTEGER, PARAMETER :: diag_all = 2
93  INTEGER, PARAMETER :: very_large_file_freq = 100000
94  INTEGER, PARAMETER :: very_large_axis_length = 10000
95  INTEGER, PARAMETER :: every_time = 0
96  INTEGER, PARAMETER :: end_of_run = -1
97  INTEGER, PARAMETER :: diag_seconds = 1, diag_minutes = 2, diag_hours = 3
98  INTEGER, PARAMETER :: diag_days = 4, diag_months = 5, diag_years = 6
99  INTEGER, PARAMETER :: max_subaxes = 10
100  INTEGER, PARAMETER :: no_domain = 1 !< Use the FmsNetcdfFile_t fileobj
101  INTEGER, PARAMETER :: two_d_domain = 2 !< Use the FmsNetcdfDomainFile_t fileobj
102  INTEGER, PARAMETER :: ug_domain = 3 !< Use the FmsNetcdfUnstructuredDomainFile_t fileobj
103  INTEGER, PARAMETER :: sub_regional = 4 !< This is a file with a sub_region use the FmsNetcdfFile_t fileobj
104  integer, parameter :: max_dimensions = 5 !< Max number of dimensions allowed (including unlimited dimension)
105  INTEGER, PARAMETER :: direction_up = 1 !< The axis points up if positive
106  INTEGER, PARAMETER :: direction_down = -1 !< The axis points down if positive
107  INTEGER, PARAMETER :: glo_reg_val = -999 !< Value used in the region specification of the diag_table
108  !! to indicate to use the full axis instead of a sub-axis
109  INTEGER, PARAMETER :: glo_reg_val_alt = -1 !< Alternate value used in the region specification of the
110  !! diag_table to indicate to use the full axis instead of a sub-axis
111  REAL(r8_kind), PARAMETER :: cmor_missing_value = 1.0e20 !< CMOR standard missing value
112  INTEGER, PARAMETER :: diag_field_not_found = -1 !< Return value for a diag_field that isn't found in the diag_table
113  INTEGER, PARAMETER :: latlon_gridtype = 1
114  INTEGER, PARAMETER :: index_gridtype = 2
115  INTEGER, PARAMETER :: null_gridtype = diag_null
116  INTEGER, PARAMETER :: time_none = 0 !< There is no reduction method
117  INTEGER, PARAMETER :: time_min = 1 !< The reduction method is min value
118  INTEGER, PARAMETER :: time_max = 2 !< The reduction method is max value
119  INTEGER, PARAMETER :: time_sum = 3 !< The reduction method is sum of values
120  INTEGER, PARAMETER :: time_average= 4 !< The reduction method is average of values
121  INTEGER, PARAMETER :: time_rms = 5 !< The reudction method is root mean square of values
122  INTEGER, PARAMETER :: time_diurnal = 6 !< The reduction method is diurnal
123  INTEGER, PARAMETER :: time_power = 7 !< The reduction method is average with exponents
124  CHARACTER(len=7) :: avg_name = 'average' !< Name of the average fields
125  CHARACTER(len=8) :: no_units = "NO UNITS"!< String indicating that the variable has no units
126  INTEGER, PARAMETER :: begin_time = 1 !< Use the begining of the time average bounds
127  INTEGER, PARAMETER :: middle_time = 2 !< Use the middle of the time average bounds
128  INTEGER, PARAMETER :: end_time = 3 !< Use the end of the time average bounds
129  INTEGER, PARAMETER :: max_str_len = 255 !< Max length for a string
130  INTEGER, PARAMETER :: is_x_axis = 1 !< integer indicating that it is a x axis
131  INTEGER, PARAMETER :: is_y_axis = 2 !< integer indicating that it is a y axis
132  !> @}
133 
134  !> @brief Contains the coordinates of the local domain to output.
135  !> @ingroup diag_data_mod
137  REAL, DIMENSION(3) :: start !< start coordinates (lat,lon,depth) of local domain to output
138  REAL, DIMENSION(3) :: end !< end coordinates (lat,lon,depth) of local domain to output
139  INTEGER, DIMENSION(3) :: l_start_indx !< start indices at each LOCAL PE
140  INTEGER, DIMENSION(3) :: l_end_indx !< end indices at each LOCAL PE
141  INTEGER, DIMENSION(3) :: subaxes !< id returned from diag_subaxes_init of 3 subaxes
142  END TYPE diag_grid
143 
144  !> @brief Diagnostic field type
145  !> @ingroup diag_data_mod
147  TYPE(domain2d) :: Domain
148  TYPE(domainUG) :: DomainU
149  REAL :: miss, miss_pack
150  LOGICAL :: miss_present, miss_pack_present
151  INTEGER :: tile_count
152  character(len=128) :: fieldname !< Fieldname
153  END TYPE diag_fieldtype
154 
155  !> @brief Attribute type for diagnostic fields
156  !> @ingroup diag_data_mod
157  TYPE :: diag_atttype
158  INTEGER :: type !< Data type of attribute values (NF_INT, NF_FLOAT, NF_CHAR)
159  INTEGER :: len !< Number of values in attribute, or if a character string then
160  !! length of the string.
161  CHARACTER(len=128) :: name !< Name of the attribute
162  CHARACTER(len=1280) :: catt !< Character string to hold character value of attribute
163  REAL, allocatable, DIMENSION(:) :: fatt !< REAL array to hold value of REAL attributes
164  INTEGER, allocatable, DIMENSION(:) :: iatt !< INTEGER array to hold value of INTEGER attributes
165  END TYPE diag_atttype
166 
167  !!TODO: coord_type deserves a better name, like coord_interval_type or coord_bbox_type.
168  !! additionally, consider using a 2D array.
169  !> @brief Define the region for field output
170  !> @ingroup diag_data_mod
172  REAL :: xbegin
173  REAL :: xend
174  REAL :: ybegin
175  REAL :: yend
176  REAL :: zbegin
177  REAL :: zend
178  END TYPE coord_type
179 
180  !> @brief Type to define the diagnostic files that will be written as defined by the diagnostic table.
181  !> @ingroup diag_data_mod
183  CHARACTER(len=FMS_FILE_LEN) :: name !< Name of the output file.
184  CHARACTER(len=128) :: long_name
185  INTEGER, DIMENSION(max_fields_per_file) :: fields
186  INTEGER :: num_fields
187  INTEGER :: output_freq
188  INTEGER :: output_units
189  INTEGER :: format
190  INTEGER :: time_units
191  INTEGER :: file_unit
192  INTEGER :: bytes_written
193  INTEGER :: time_axis_id, time_bounds_id
194  INTEGER :: new_file_freq !< frequency to create new file
195  INTEGER :: new_file_freq_units !< time units of new_file_freq (days, hours, years, ...)
196  INTEGER :: duration
197  INTEGER :: duration_units
198  INTEGER :: tile_count
199  LOGICAL :: local !< .TRUE. if fields are output in a region instead of global.
200  TYPE(time_type) :: last_flush
201  TYPE(time_type) :: next_open !< Time to open a new file.
202  TYPE(time_type) :: start_time !< Time file opened.
203  TYPE(time_type) :: close_time !< Time file closed. File does not allow data after close time
204  TYPE(diag_fieldtype):: f_avg_start, f_avg_end, f_avg_nitems, f_bounds
205  TYPE(diag_atttype), allocatable, dimension(:) :: attributes !< Array to hold user definable attributes
206  INTEGER :: num_attributes !< Number of defined attibutes
207 !----------
208 !ug support
209  logical(L4_KIND) :: use_domainug = .false.
210  logical(I4_KIND) :: use_domain2d = .false.
211 !----------
212 !Check if time axis was already registered
213  logical, allocatable :: is_time_axis_registered
214 !Support for fms2_io time
215  real :: rtime_current
216  integer :: time_index
217  CHARACTER(len=10) :: filename_time_bounds
218  END TYPE file_type
219 
220  !> @brief Type to hold the input field description
221  !> @ingroup diag_data_mod
223  CHARACTER(len=128) :: module_name, field_name, long_name, units
224  CHARACTER(len=256) :: standard_name
225  CHARACTER(len=64) :: interp_method
226  INTEGER, DIMENSION(3) :: axes
227  INTEGER :: num_axes
228  LOGICAL :: missing_value_present, range_present
229  REAL :: missing_value
230  REAL, DIMENSION(2) :: range
231  INTEGER, allocatable, dimension(:) :: output_fields
232  INTEGER :: num_output_fields
233  INTEGER, DIMENSION(3) :: size
234  LOGICAL :: static, register, mask_variant, local
235  INTEGER :: numthreads
236  INTEGER :: active_omp_level !< The current level of OpenMP nesting
237  INTEGER :: tile_count
238  TYPE(coord_type) :: local_coord
239  TYPE(time_type) :: time
240  LOGICAL :: issued_mask_ignore_warning !< Indicates if the mask_ignore_warning
241  !! has been issued for this input
242  !! field. Once .TRUE. the warning message
243  !! is suppressed on all subsequent
244  !! send_data calls.
245  END TYPE input_field_type
246 
247  !> @brief Type to hold the output field description.
248  !> @ingroup diag_data_mod
250  INTEGER :: input_field !< index of the corresponding input field in the table
251  INTEGER :: output_file !< index of the output file in the table
252  CHARACTER(len=128) :: output_name
253  LOGICAL :: time_average !< true if the output field is averaged over time interval
254  LOGICAL :: time_rms !< true if the output field is the rms. If true, then time_average is also
255  LOGICAL :: static
256  LOGICAL :: time_max !< true if the output field is maximum over time interval
257  LOGICAL :: time_min !< true if the output field is minimum over time interval
258  LOGICAL :: time_sum !< true if the output field is summed over time interval
259  LOGICAL :: time_ops !< true if any of time_min, time_max, time_rms or time_average is true
260  INTEGER :: pack
261  INTEGER :: pow_value !< Power value to use for mean_pow(n) calculations
262  CHARACTER(len=50) :: time_method !< time method field from the input file
263  ! coordinates of the buffer and counter are (x, y, z, time-of-day)
264  REAL, allocatable, DIMENSION(:,:,:,:) :: buffer !< coordinates of the buffer and counter are (x,
265  !! y, z, time-of-day)
266  REAL, allocatable, DIMENSION(:,:,:,:) :: counter !< coordinates of the buffer and counter are (x,y,z,time-of-day)
267  ! the following two counters are used in time-averaging for some
268  ! combination of the field options. Their size is the length of the
269  ! diurnal axis; the counters must be tracked separately for each of
270  ! the diurnal interval, because the number of time slices accumulated
271  ! in each can be different, depending on time step and the number of
272  ! diurnal samples.
273  REAL, allocatable, DIMENSION(:) :: count_0d !< the following two counters are used in time-averaging for some
274  !! combination of the field options. Their size is the length of the
275  !! diurnal axis; the counters must be tracked separately for each of
276  !! the diurnal interval, because the number of time slices accumulated
277  !! in each can be different, depending on time step and the number of
278  !! diurnal samples.
279  INTEGER, allocatable, dimension(:) :: num_elements !< the following two counters are used in time-averaging
280  !! for some combination of the field options. Their size is the length of the
281  !! diurnal axis; the counters must be tracked separately for each of
282  !! the diurnal interval, because the number of time slices accumulated
283  !! in each can be different, depending on time step and the number of
284  !! diurnal samples.
285 
286  TYPE(time_type) :: last_output, next_output, next_next_output
287  TYPE(diag_fieldtype) :: f_type
288  INTEGER, DIMENSION(4) :: axes
289  INTEGER :: num_axes, total_elements, region_elements
290  INTEGER :: n_diurnal_samples !< number of diurnal sample intervals, 1 or more
291  TYPE(diag_grid) :: output_grid
292  LOGICAL :: local_output, need_compute, phys_window, written_once
293  LOGICAL :: reduced_k_range
294  TYPE(fmsdiagibounds_type) :: buff_bounds
295  TYPE(time_type) :: time_of_prev_field_data
296  TYPE(diag_atttype), allocatable, dimension(:) :: attributes
297  INTEGER :: num_attributes
298 !----------
299 !ug support
300  logical :: reduced_k_unstruct = .false.
301 !----------
302  END TYPE output_field_type
303 
304  !> @brief Type to hold the diagnostic axis description.
305  !> @ingroup diag_data_mod
307  CHARACTER(len=128) :: name
308  CHARACTER(len=256) :: units, long_name
309  CHARACTER(len=1) :: cart_name
310  REAL, DIMENSION(:), POINTER :: diag_type_data
311  INTEGER, DIMENSION(MAX_SUBAXES) :: start
312  INTEGER, DIMENSION(MAX_SUBAXES) :: end
313  CHARACTER(len=128), DIMENSION(MAX_SUBAXES) :: subaxis_name
314  INTEGER :: length, direction, edges, set, shift
315  TYPE(domain1d) :: Domain
316  TYPE(domain2d) :: Domain2
317  TYPE(domain2d), dimension(MAX_SUBAXES) :: subaxis_domain2
318  type(domainUG) :: DomainUG
319  CHARACTER(len=128) :: aux, req
320  INTEGER :: tile_count
321  TYPE(diag_atttype), allocatable, dimension(:) :: attributes !< Array to hold user definable attributes
322  INTEGER :: num_attributes !< Number of defined attibutes
323  INTEGER :: domain_position !< The position in the doman (NORTH or EAST or CENTER)
324  END TYPE diag_axis_type
325 
326  !> @ingroup diag_data_mod
328  CHARACTER(len=128) :: grid_type='regular'
329  CHARACTER(len=128) :: tile_name='N/A'
330  END TYPE diag_global_att_type
331 
332  !> @brief Type to hold the attributes of the field/axis/file
333  !> @ingroup diag_data_mod
335  class(*), allocatable :: att_value(:) !< Value of the attribute
336  character(len=:), allocatable :: att_name !< Name of the attribute
337  contains
338  procedure :: add => fms_add_attribute
339  procedure :: write_metadata
340  end type fmsdiagattribute_type
341 ! Include variable "version" to be written to log file.
342 #include<file_version.h>
343 
344  !> @addtogroup diag_data_mod
345  !> @{
346 
347  ! <!-- Other public variables -->
348  INTEGER :: num_files = 0 !< Number of output files currenly in use by the diag_manager.
349  INTEGER :: num_input_fields = 0 !< Number of input fields in use.
350  INTEGER :: num_output_fields = 0 !< Number of output fields in use.
351  INTEGER :: null_axis_id
352 
353  ! <!-- Namelist variables -->
354  LOGICAL :: append_pelist_name = .false.
355  LOGICAL :: mix_snapshot_average_fields =.false.
356  INTEGER :: max_files = 31 !< Maximum number of output files allowed. Increase via diag_manager_nml.
357  INTEGER :: max_output_fields = 300 !< Maximum number of output fields. Increase via diag_manager_nml.
358  INTEGER :: max_input_fields = 600 !< Maximum number of input fields. Increase via diag_manager_nml.
359  INTEGER :: max_out_per_in_field = 150 !< Maximum number of output_fields per input_field. Increase
360  !! via diag_manager_nml.
361  INTEGER :: max_axes = 60 !< Maximum number of independent axes.
362  LOGICAL :: do_diag_field_log = .false.
363  LOGICAL :: write_bytes_in_file = .false.
364  LOGICAL :: debug_diag_manager = .false.
365  LOGICAL :: flush_nc_files = .false. !< Control if diag_manager will force a
366  !! flush of the netCDF file on each write.
367  !! Note: changing this to .TRUE. can greatly
368  !! reduce the performance of the model, as the
369  !! model must wait until the flush to disk has
370  !! completed.
371  INTEGER :: max_num_axis_sets = 25
372  LOGICAL :: use_cmor = .false. !< Indicates if we should overwrite the MISSING_VALUE to use the CMOR missing value.
373  LOGICAL :: issue_oor_warnings = .true. !< Issue warnings if the output field has values outside the given
374  !! range for a variable.
375  LOGICAL :: oor_warnings_fatal = .false. !< Cause a fatal error if the output field has a value outside the
376  !! given range for a variable.
377  LOGICAL :: region_out_use_alt_value = .true. !< Will determine which value to use when checking a regional
378  !! output if the region is the full axis or a sub-axis.
379  !! The values are defined as <TT>GLO_REG_VAL</TT>
380  !! (-999) and <TT>GLO_REG_VAL_ALT</TT> (-1) in <TT>diag_data_mod</TT>.
381 
382  INTEGER :: max_field_attributes = 4 !< Maximum number of user definable attributes per field. Liptak:
383  !! Changed from 2 to 4 20170718
384  INTEGER :: max_file_attributes = 2 !< Maximum number of user definable global attributes per file.
385  INTEGER :: max_axis_attributes = 4 !< Maximum number of user definable attributes per axis.
386  LOGICAL :: prepend_date = .true. !< Should the history file have the start date prepended to the file name.
387  !! <TT>.TRUE.</TT> is only supported if the diag_manager_init
388  !! routine is called with the optional time_init parameter.
389  LOGICAL :: use_refactored_send = .false. !< Namelist flag to use refactored send_data math funcitons.
390  LOGICAL :: use_modern_diag = .false. !< Namelist flag to use the modernized diag_manager code
391  LOGICAL :: use_clock_average = .false. !< .TRUE. if the averaging of variable is done based on the clock
392  !! For example, if doing daily averages and your start the simulation in
393  !! day1_hour3, it will do the average between day1_hour3 to day2_hour 0
394  !! the default behavior will do the average between day1 hour3 to day2 hour3
395  ! <!-- netCDF variable -->
396 
397  REAL :: fill_value = nf_fill_real !< Fill value used. Value will be <TT>NF90_FILL_REAL</TT> if using the
398  !! netCDF module, otherwise will be 9.9692099683868690e+36.
399  ! from file /usr/local/include/netcdf.inc
400 
401  !! @note `pack_size` and `pack_size_str` are set in diag_manager_init depending on how FMS was compiled
402  !! if FMS was compiled with default reals as 64bit, it will be set to 1 and "double",
403  !! if FMS was compiled with default reals as 32bit, it will set to 2 and "float"
404  !! The time variables will written in the precision defined by `pack_size_str`
405  !! This is to reproduce previous diag manager behavior.
406  !TODO This may not be mixed precision friendly
407  INTEGER :: pack_size = 1 !< 1 for double and 2 for float
408  CHARACTER(len=6) :: pack_size_str="double" !< Pack size as a string to be used in fms2_io register call
409  !! set to "double" or "float"
410 
411  ! <!-- REAL public variables -->
412  REAL(r8_kind) :: empty = 0.0
413  REAL(r8_kind) :: max_value, min_value
414 
415  ! <!-- Global data for all files -->
416  TYPE(time_type) :: diag_init_time !< Time diag_manager_init called. If init_time not included in
417  !! diag_manager_init call, then same as base_time
418  TYPE(time_type), private :: base_time !< The base_time read from diag_table
419  logical, private :: base_time_set !< Flag indicating that the base_time is set
420  !! This is to prevent users from calling set_base_time multiple times
421  INTEGER, private :: base_year, base_month, base_day, base_hour, base_minute, base_second
422  CHARACTER(len = 256):: global_descriptor
423 
424  ! <!-- ALLOCATABLE variables -->
425  TYPE(file_type), SAVE, ALLOCATABLE :: files(:)
426  TYPE(input_field_type), ALLOCATABLE :: input_fields(:)
427  TYPE(output_field_type), ALLOCATABLE :: output_fields(:)
428  type(fmsnetcdfunstructureddomainfile_t),allocatable, target :: fileobju(:)
429  type(fmsnetcdfdomainfile_t),allocatable, target :: fileobj(:)
430  type(fmsnetcdffile_t),allocatable, target :: fileobjnd(:)
431  character(len=2),allocatable :: fnum_for_domain(:) !< If this file number in the array is for the "unstructured"
432  !! or "2d" domain
433 
434  ! <!-- Even More Variables -->
435  TYPE(time_type) :: time_zero
436  LOGICAL :: first_send_data_call = .true.
437  LOGICAL :: module_is_initialized = .false. !< Indicate if diag_manager has been initialized
438  INTEGER :: diag_log_unit
439  CHARACTER(len=10), DIMENSION(6) :: time_unit_list = (/'seconds ', 'minutes ',&
440  & 'hours ', 'days ', 'months ', 'years '/)
441  character(len=32) :: pelist_name
442  INTEGER :: oor_warning = warning
443 
444 CONTAINS
445 
446  !> @brief Initialize and write the version number of this file to the log file.
447  SUBROUTINE diag_data_init()
448  IF (module_is_initialized) THEN
449  RETURN
450  END IF
451 
452  ! Write version number out to log file
453  call write_version_number("DIAG_DATA_MOD", version)
454  module_is_initialized = .true.
455  base_time_set = .false.
456 
457  END SUBROUTINE diag_data_init
458 
459  !> @brief Set the module variable base_time
460  subroutine set_base_time(base_time_int)
461  integer :: base_time_int(6) !< base_time as an array [year month day hour min sec]
462 
463  CHARACTER(len=9) :: amonth !< Month name
464  INTEGER :: stdlog_unit !< Fortran file unit number for the stdlog file.
465 
466  if (.not. module_is_initialized) call mpp_error(fatal, "set_base_time: diag_data is not initialized")
467  if (base_time_set) call mpp_error(fatal, "set_base_time: the base_time is already set!")
468 
469  base_year = base_time_int(1)
470  base_month = base_time_int(2)
471  base_day = base_time_int(3)
472  base_hour = base_time_int(4)
473  base_minute = base_time_int(5)
474  base_second = base_time_int(6)
475 
476  ! Set up the time type for base time
477  IF ( get_calendar_type() /= no_calendar ) THEN
478  IF ( base_year==0 .OR. base_month==0 .OR. base_day==0 ) THEN
479  call mpp_error(fatal, 'diag_data_mod::set_base_time'//&
480  & 'The base_year/month/day can not equal zero')
481  END IF
482  base_time = set_date(base_year, base_month, base_day, base_hour, base_minute, base_second)
483  amonth = month_name(base_month)
484  ELSE
485  ! No calendar - ignore year and month
486  base_time = set_time(nint(base_hour*seconds_per_hour)+nint(base_minute*seconds_per_minute)+base_second, &
487  & base_day)
488  base_year = 0
489  base_month = 0
490  amonth = 'day'
491  END IF
492 
493  ! get the stdlog unit number
494  stdlog_unit = stdlog()
495 
496  IF ( mpp_pe() == mpp_root_pe() ) THEN
497  WRITE (stdlog_unit,'("base date used = ",I4,1X,A,2I3,2(":",I2.2)," gmt")') base_year, trim(amonth), base_day, &
498  & base_hour, base_minute, base_second
499  END IF
500 
501  base_time_set = .true.
502 
503  end subroutine set_base_time
504 
505  !> @brief gets the module variable base_time
506  !> @return the base_time
507  function get_base_time() &
508  result(res)
509  TYPE(time_type) :: res
510  res = base_time
511  end function get_base_time
512 
513  !> @brief gets the module variable base_year
514  !> @return the base_year
515  function get_base_year() &
516  result(res)
517  integer :: res
518  res = base_year
519  end function get_base_year
520 
521  !> @brief gets the module variable base_month
522  !> @return the base_month
523  function get_base_month() &
524  result(res)
525  integer :: res
526  res = base_month
527  end function get_base_month
528 
529  !> @brief gets the module variable base_day
530  !> @return the base_day
531  function get_base_day() &
532  result(res)
533  integer :: res
534  res = base_day
535  end function get_base_day
536 
537  !> @brief gets the module variable base_hour
538  !> @return the base_hour
539  function get_base_hour() &
540  result(res)
541  integer :: res
542  res = base_hour
543  end function get_base_hour
544 
545  !> @brief gets the module variable base_minute
546  !> @return the base_minute
547  function get_base_minute() &
548  result(res)
549  integer :: res
550  res = base_minute
551  end function get_base_minute
552 
553  !> @brief gets the module variable base_second
554  !> @return the base_second
555  function get_base_second() &
556  result(res)
557  integer :: res
558  res = base_second
559  end function get_base_second
560 
561  !> @brief Adds an attribute to the attribute type
562  subroutine fms_add_attribute(this, att_name, att_value)
563  class(fmsdiagattribute_type), intent(inout) :: this !< Diag attribute type
564  character(len=*), intent(in) :: att_name !< Name of the attribute
565  class(*), intent(in) :: att_value(:) !< The attribute value to add
566 
567  integer :: natt !< the size of att_value
568 
569 #ifndef __NVCOMPILER
570  natt = size(att_value)
571  this%att_name = att_name
572  select type (att_value)
573  type is (integer(kind=i4_kind))
574  allocate(integer(kind=i4_kind) :: this%att_value(natt))
575  this%att_value = att_value
576  type is (integer(kind=i8_kind))
577  allocate(integer(kind=i8_kind) :: this%att_value(natt))
578  this%att_value = att_value
579  type is (real(kind=r4_kind))
580  allocate(real(kind=r4_kind) :: this%att_value(natt))
581  this%att_value = att_value
582  type is (real(kind=r8_kind))
583  allocate(real(kind=r8_kind) :: this%att_value(natt))
584  this%att_value = att_value
585  type is (character(len=*))
586  allocate(character(len=len(att_value)) :: this%att_value(natt))
587  select type(aval => this%att_value)
588  type is (character(len=*))
589  aval = att_value
590  end select
591  end select
592 #endif
593  end subroutine fms_add_attribute
594 
595  !> @brief gets the type of a variable
596  !> @return the type of the variable (r4,r8,i4,i8,string)
597  function get_var_type(var) &
598  result(var_type)
599  class(*), intent(in) :: var !< Variable to get the type for
600  integer :: var_type !< The variable's type
601 
602  select type(var)
603  type is (real(r4_kind))
604  var_type = r4
605  type is (real(r8_kind))
606  var_type = r8
607  type is (integer(i4_kind))
608  var_type = i4
609  type is (integer(i8_kind))
610  var_type = i8
611  type is (character(len=*))
612  var_type = string
613  class default
614  call mpp_error(fatal, "get_var_type:: The variable does not have a supported type. &
615  &The supported types are r4, r8, i4, i8 and string.")
616  end select
617  end function get_var_type
618 
619  !> @brief Writes out the attributes from an fmsDiagAttribute_type
620  subroutine write_metadata(this, fileobj, var_name, cell_methods)
621  class(fmsdiagattribute_type), intent(inout) :: this !< Diag attribute type
622  class(fmsnetcdffile_t), INTENT(INOUT) :: fileobj !< Fms2_io fileobj to write to
623  character(len=*), intent(in) :: var_name !< The name of the variable to write to
624  character(len=*), optional, intent(inout) :: cell_methods !< The cell methods attribute
625 
626  select type (att_value =>this%att_value)
627  type is (character(len=*))
628  !< If the attribute is cell methods append to the current cell_methods attribute value
629  !! This will be writen once all of the cell_methods attributes are gathered ...
630  if (present(cell_methods)) then
631  if (trim(this%att_name) .eq. "cell_methods") then
632  cell_methods = trim(cell_methods)//" "//trim(att_value(1))
633  return
634  endif
635  endif
636 
637  call register_variable_attribute(fileobj, var_name, this%att_name, trim(att_value(1)), &
638  str_len=len_trim(att_value(1)))
639  type is (real(kind=r8_kind))
640  call register_variable_attribute(fileobj, var_name, this%att_name, real(att_value, kind=r8_kind))
641  type is (real(kind=r4_kind))
642  call register_variable_attribute(fileobj, var_name, this%att_name, real(att_value, kind=r4_kind))
643  type is (integer(kind=i4_kind))
644  call register_variable_attribute(fileobj, var_name, this%att_name, int(att_value, kind=i4_kind))
645  type is (integer(kind=i8_kind))
646  call register_variable_attribute(fileobj, var_name, this%att_name, int(att_value, kind=i8_kind))
647  end select
648 
649  end subroutine write_metadata
650 END MODULE diag_data_mod
651 !> @}
652 ! close documentation grouping
character(len=8) no_units
String indicating that the variable has no units.
Definition: diag_data.F90:125
integer max_output_fields
Maximum number of output fields. Increase via diag_manager_nml.
Definition: diag_data.F90:357
real fill_value
Fill value used. Value will be NF90_FILL_REAL if using the netCDF module, otherwise will be 9....
Definition: diag_data.F90:397
integer, parameter direction_down
The axis points down if positive.
Definition: diag_data.F90:106
integer, parameter sub_regional
This is a file with a sub_region use the FmsNetcdfFile_t fileobj.
Definition: diag_data.F90:103
integer pack_size
1 for double and 2 for float
Definition: diag_data.F90:407
integer, parameter max_str_len
Max length for a string.
Definition: diag_data.F90:129
integer function get_base_minute()
gets the module variable base_minute
Definition: diag_data.F90:549
integer function get_base_year()
gets the module variable base_year
Definition: diag_data.F90:517
integer num_input_fields
Number of input fields in use.
Definition: diag_data.F90:349
integer function get_base_hour()
gets the module variable base_hour
Definition: diag_data.F90:541
logical use_cmor
Indicates if we should overwrite the MISSING_VALUE to use the CMOR missing value.
Definition: diag_data.F90:372
logical flush_nc_files
Control if diag_manager will force a flush of the netCDF file on each write. Note: changing this to ....
Definition: diag_data.F90:365
integer function get_var_type(var)
gets the type of a variable
Definition: diag_data.F90:599
integer, parameter no_domain
Use the FmsNetcdfFile_t fileobj.
Definition: diag_data.F90:100
character(len=7) avg_name
Name of the average fields.
Definition: diag_data.F90:124
integer, parameter end_time
Use the end of the time average bounds.
Definition: diag_data.F90:128
integer, parameter glo_reg_val_alt
Alternate value used in the region specification of the diag_table to indicate to use the full axis i...
Definition: diag_data.F90:109
integer max_axis_attributes
Maximum number of user definable attributes per axis.
Definition: diag_data.F90:385
integer, parameter monthly
Supported averaging intervals.
Definition: diag_data.F90:72
character(len=6) pack_size_str
Pack size as a string to be used in fms2_io register call set to "double" or "float".
Definition: diag_data.F90:408
logical use_modern_diag
Namelist flag to use the modernized diag_manager code.
Definition: diag_data.F90:390
type(time_type) function get_base_time()
gets the module variable base_time
Definition: diag_data.F90:509
integer max_axes
Maximum number of independent axes.
Definition: diag_data.F90:361
type(time_type), private base_time
The base_time read from diag_table.
Definition: diag_data.F90:418
integer, parameter is_x_axis
integer indicating that it is a x axis
Definition: diag_data.F90:130
integer, parameter diag_field_not_found
Return value for a diag_field that isn't found in the diag_table.
Definition: diag_data.F90:112
integer max_out_per_in_field
Maximum number of output_fields per input_field. Increase via diag_manager_nml.
Definition: diag_data.F90:359
integer max_input_fields
Maximum number of input fields. Increase via diag_manager_nml.
Definition: diag_data.F90:358
logical use_clock_average
.TRUE. if the averaging of variable is done based on the clock For example, if doing daily averages a...
Definition: diag_data.F90:391
integer, parameter string
s is the 19th letter of the alphabet
Definition: diag_data.F90:87
logical issue_oor_warnings
Issue warnings if the output field has values outside the given range for a variable.
Definition: diag_data.F90:373
logical region_out_use_alt_value
Will determine which value to use when checking a regional output if the region is the full axis or a...
Definition: diag_data.F90:377
integer num_output_fields
Number of output fields in use.
Definition: diag_data.F90:350
integer, parameter is_y_axis
integer indicating that it is a y axis
Definition: diag_data.F90:131
integer function get_base_day()
gets the module variable base_day
Definition: diag_data.F90:533
type(time_type) diag_init_time
Time diag_manager_init called. If init_time not included in diag_manager_init call,...
Definition: diag_data.F90:416
integer, parameter time_min
The reduction method is min value.
Definition: diag_data.F90:117
integer, parameter ug_domain
Use the FmsNetcdfUnstructuredDomainFile_t fileobj.
Definition: diag_data.F90:102
subroutine set_base_time(base_time_int)
Set the module variable base_time.
Definition: diag_data.F90:461
integer, parameter time_diurnal
The reduction method is diurnal.
Definition: diag_data.F90:122
integer, parameter time_power
The reduction method is average with exponents.
Definition: diag_data.F90:123
integer max_files
Maximum number of output files allowed. Increase via diag_manager_nml.
Definition: diag_data.F90:356
integer num_files
Number of output files currenly in use by the diag_manager.
Definition: diag_data.F90:348
integer max_file_attributes
Maximum number of user definable global attributes per file.
Definition: diag_data.F90:384
real(r8_kind), parameter cmor_missing_value
CMOR standard missing value.
Definition: diag_data.F90:111
subroutine write_metadata(this, fileobj, var_name, cell_methods)
Writes out the attributes from an fmsDiagAttribute_type.
Definition: diag_data.F90:621
logical prepend_date
Should the history file have the start date prepended to the file name. .TRUE. is only supported if t...
Definition: diag_data.F90:386
character(len=2), dimension(:), allocatable fnum_for_domain
If this file number in the array is for the "unstructured" or "2d" domain.
Definition: diag_data.F90:431
integer, parameter max_dimensions
Max number of dimensions allowed (including unlimited dimension)
Definition: diag_data.F90:104
integer, parameter begin_time
Use the begining of the time average bounds.
Definition: diag_data.F90:126
subroutine diag_data_init()
Initialize and write the version number of this file to the log file.
Definition: diag_data.F90:448
integer, parameter time_average
The reduction method is average of values.
Definition: diag_data.F90:120
integer, parameter direction_up
The axis points up if positive.
Definition: diag_data.F90:105
integer function get_base_month()
gets the module variable base_month
Definition: diag_data.F90:525
integer, parameter time_sum
The reduction method is sum of values.
Definition: diag_data.F90:119
subroutine fms_add_attribute(this, att_name, att_value)
Adds an attribute to the attribute type.
Definition: diag_data.F90:563
integer, parameter time_rms
The reudction method is root mean square of values.
Definition: diag_data.F90:121
integer, parameter middle_time
Use the middle of the time average bounds.
Definition: diag_data.F90:127
logical module_is_initialized
Indicate if diag_manager has been initialized.
Definition: diag_data.F90:437
integer, parameter glo_reg_val
Value used in the region specification of the diag_table to indicate to use the full axis instead of ...
Definition: diag_data.F90:107
logical, private base_time_set
Flag indicating that the base_time is set This is to prevent users from calling set_base_time multipl...
Definition: diag_data.F90:419
integer, parameter time_none
There is no reduction method.
Definition: diag_data.F90:116
logical oor_warnings_fatal
Cause a fatal error if the output field has a value outside the given range for a variable.
Definition: diag_data.F90:375
integer function get_base_second()
gets the module variable base_second
Definition: diag_data.F90:557
integer, parameter time_max
The reduction method is max value.
Definition: diag_data.F90:118
integer, parameter max_fields_per_file
Maximum number of fields per file.
Definition: diag_data.F90:89
logical use_refactored_send
Namelist flag to use refactored send_data math funcitons.
Definition: diag_data.F90:389
integer, parameter r8
Supported type/kind of the variable.
Definition: diag_data.F90:83
integer max_field_attributes
Maximum number of user definable attributes per field. Liptak: Changed from 2 to 4 20170718.
Definition: diag_data.F90:382
integer, parameter two_d_domain
Use the FmsNetcdfDomainFile_t fileobj.
Definition: diag_data.F90:101
Define the region for field output.
Definition: diag_data.F90:171
Attribute type for diagnostic fields.
Definition: diag_data.F90:157
Type to hold the diagnostic axis description.
Definition: diag_data.F90:306
Diagnostic field type.
Definition: diag_data.F90:146
Contains the coordinates of the local domain to output.
Definition: diag_data.F90:136
Type to define the diagnostic files that will be written as defined by the diagnostic table.
Definition: diag_data.F90:182
Type to hold the attributes of the field/axis/file.
Definition: diag_data.F90:334
Type to hold the input field description.
Definition: diag_data.F90:222
Type to hold the output field description.
Definition: diag_data.F90:249
subroutine, public write_version_number(version, tag, unit)
Prints to the log file (or a specified unit) the version id string and tag name.
Definition: fms.F90:701
One dimensional domain used to manage shared data access between pes.
The domain2D type contains all the necessary information to define the global, compute and data domai...
Domain information for managing data on unstructured grids.
integer function stdlog()
This function returns the current standard fortran unit numbers for log messages. Log messages,...
Definition: mpp_util.inc:58
integer function mpp_pe()
Returns processor ID.
Definition: mpp_util.inc:406
Error handler.
Definition: mpp.F90:385
character(len=9) function, public month_name(n)
Returns a character string containing the name of the month corresponding to month number n.
integer function, public get_calendar_type()
Returns default calendar type for mapping from time to date.
Given an input date in year, month, days, etc., creates a time_type that represents this time interva...
Given some number of seconds and days, returns the corresponding time_type.
Type to represent amounts of time. Implemented as seconds and days to allow for larger intervals.
Data structure holding a 3D bounding box. It is commonlyused to represent the interval bounds or limi...