MOM6
mom_diag_mediator Module Reference

Detailed Description

The subroutines here provide convenient wrappers to the fms diag_manager interfaces with additional diagnostic capabilies.

Data Types

type  axes_grp
 A group of 1D axes that comprise a 1D/2D/3D mesh. More...
 
type  diag_ctrl
 The following data type a list of diagnostic fields an their variants, as well as variables that control the handling of model output. More...
 
type  diag_dsamp
 Contained for down sampled masks. More...
 
type  diag_grid_storage
 Stores all the remapping grids and the model's native space thicknesses. More...
 
type  diag_grids_type
 Contains an array to store a diagnostic target grid. More...
 
type  diag_type
 This type is used to represent a diagnostic at the diag_mediator level. More...
 
type  diagcs_dsamp
 Container for down sampling information. More...
 
interface  downsample_diag_field
 Down sample a diagnostic field. More...
 
interface  downsample_field
 Down sample a field. More...
 
interface  downsample_mask
 Down sample the mask of a field. More...
 
interface  post_data
 Make a diagnostic available for averaging or output. More...
 

Variables

integer psp =121
 x:point,y:sum,z:point
 
integer pss =122
 x:point,y:sum,z:point
 
integer psm =123
 x:point,y:sum,z:mean
 
integer pmp =131
 x:point,y:mean,z:point
 
integer pmm =133
 x:point,y:mean,z:mean
 
integer spp =211
 x:sum,y:point,z:point
 
integer sps =212
 x:sum,y:point,z:sum
 
integer ssp =221
 x:sum;y:sum,z:point
 
integer mpp =311
 x:mean,y:point,z:point
 
integer mpm =313
 x:mean,y:point,z:mean
 
integer mmp =331
 x:mean,y:mean,z:point
 
integer mms =332
 x:mean,y:mean,z:sum
 
integer sss =222
 x:sum,y:sum,z:sum
 
integer mmm =333
 x:mean,y:mean,z:mean
 
integer msk =-1
 Use the downsample method of a mask.
 
integer id_clock_diag_mediator
 Sets up diagnostics axes. More...
 
integer id_clock_diag_remap
 Sets up diagnostics axes. More...
 
integer id_clock_diag_grid_updates
 Sets up diagnostics axes. More...
 
subroutine, public set_axes_info (G, GV, US, param_file, diag_cs, set_vertical)
 Sets up diagnostics axes. More...
 
subroutine set_axes_info_dsamp (G, GV, param_file, diag_cs, id_zl_native, id_zi_native)
 
subroutine, public set_masks_for_axes (G, diag_cs)
 set_masks_for_axes sets up the 2d and 3d masks for diagnostics using the current grid recorded after calling diag_update_remap_grids() More...
 
subroutine set_masks_for_axes_dsamp (G, diag_cs)
 
subroutine, public diag_register_area_ids (diag_cs, id_area_t, id_area_q)
 Attaches the id of cell areas to axes groups for use with cell_measures. More...
 
subroutine, public register_cell_measure (G, diag, Time)
 Sets a handle inside diagnostics mediator to associate 3d cell measures. More...
 
subroutine, public diag_associate_volume_cell_measure (diag_cs, id_h_volume)
 Attaches the id of cell volumes to axes groups for use with cell_measures. More...
 
integer function, public diag_get_volume_cell_measure_dm_id (diag_cs)
 Returns diag_manager id for cell measure of h-cells. More...
 
subroutine, public define_axes_group (diag_cs, handles, axes, nz, vertical_coordinate_number, x_cell_method, y_cell_method, v_cell_method, is_h_point, is_q_point, is_u_point, is_v_point, is_layer, is_interface, is_native, needs_remapping, needs_interpolating, xyave_axes)
 Defines a group of "axes" from list of handles. More...
 
subroutine define_axes_group_dsamp (diag_cs, handles, axes, dl, nz, vertical_coordinate_number, x_cell_method, y_cell_method, v_cell_method, is_h_point, is_q_point, is_u_point, is_v_point, is_layer, is_interface, is_native, needs_remapping, needs_interpolating, xyave_axes)
 Defines a group of downsampled "axes" from list of handles. More...
 
subroutine, public set_diag_mediator_grid (G, diag_cs)
 Set up the array extents for doing diagnostics. More...
 
subroutine post_data_0d (diag_field_id, field, diag_cs, is_static)
 Make a real scalar diagnostic available for averaging or output. More...
 
subroutine, public post_data_1d_k (diag_field_id, field, diag_cs, is_static)
 Make a real 1-d array diagnostic available for averaging or output. More...
 
subroutine post_data_2d (diag_field_id, field, diag_cs, is_static, mask)
 Make a real 2-d array diagnostic available for averaging or output. More...
 
subroutine post_data_2d_low (diag, field, diag_cs, is_static, mask)
 Make a real 2-d array diagnostic available for averaging or output using a diag_type instead of an integer id. More...
 
subroutine post_data_3d (diag_field_id, field, diag_cs, is_static, mask, alt_h)
 Make a real 3-d array diagnostic available for averaging or output. More...
 
subroutine post_data_3d_low (diag, field, diag_cs, is_static, mask)
 Make a real 3-d array diagnostic available for averaging or output using a diag_type instead of an integer id. More...
 
subroutine post_xy_average (diag_cs, diag, field)
 Post the horizontally area-averaged diagnostic. More...
 
subroutine, public enable_averaging (time_int_in, time_end_in, diag_cs)
 This subroutine enables the accumulation of time averages over the specified time interval. More...
 
subroutine, public disable_averaging (diag_cs)
 Call this subroutine to avoid averaging any offered fields. More...
 
logical function, public query_averaging_enabled (diag_cs, time_int, time_end)
 Call this subroutine to determine whether the averaging is currently enabled. .true. is returned if it is. More...
 
type(time_type) function, public get_diag_time_end (diag_cs)
 This function returns the valid end time for use with diagnostics that are handled outside of the MOM6 diagnostics infrastructure. More...
 
integer function, public register_diag_field (module_name, field_name, axes_in, init_time, long_name, units, missing_value, range, mask_variant, standard_name, verbose, do_not_log, err_msg, interp_method, tile_count, cmor_field_name, cmor_long_name, cmor_units, cmor_standard_name, cell_methods, x_cell_method, y_cell_method, v_cell_method, conversion, v_extensive)
 Returns the "diag_mediator" handle for a group (native, CMOR, z-coord, ...) of diagnostics derived from one field. More...
 
logical function register_diag_field_expand_cmor (dm_id, module_name, field_name, axes, init_time, long_name, units, missing_value, range, mask_variant, standard_name, verbose, do_not_log, err_msg, interp_method, tile_count, cmor_field_name, cmor_long_name, cmor_units, cmor_standard_name, cell_methods, x_cell_method, y_cell_method, v_cell_method, conversion, v_extensive)
 Returns True if either the native or CMOr version of the diagnostic were registered. Updates 'dm_id' after calling register_diag_field_expand_axes() for both native and CMOR variants of the field. More...
 
integer function register_diag_field_expand_axes (module_name, field_name, axes, init_time, long_name, units, missing_value, range, mask_variant, standard_name, verbose, do_not_log, err_msg, interp_method, tile_count)
 Returns an FMS id from register_diag_field_fms (the diag_manager routine) after expanding axes (axes-group) into handles and conditionally adding an FMS area_id for cell_measures. More...
 
subroutine add_diag_to_list (diag_cs, dm_id, fms_id, this_diag, axes, module_name, field_name, msg)
 Create a diagnostic type and attached to list. More...
 
subroutine add_xyz_method (diag, axes, x_cell_method, y_cell_method, v_cell_method, v_extensive)
 Adds the encoded "cell_methods" for a diagnostics as a diag% property This allows access to the cell_method for a given diagnostics at the time of sending. More...
 
subroutine attach_cell_methods (id, axes, ostring, cell_methods, x_cell_method, y_cell_method, v_cell_method, v_extensive)
 Attaches "cell_methods" attribute to a variable based on defaults for axes_grp or optional arguments. More...
 
integer function, public register_scalar_field (module_name, field_name, init_time, diag_cs, long_name, units, missing_value, range, standard_name, do_not_log, err_msg, interp_method, cmor_field_name, cmor_long_name, cmor_units, cmor_standard_name)
 
integer function, public register_static_field (module_name, field_name, axes, long_name, units, missing_value, range, mask_variant, standard_name, do_not_log, interp_method, tile_count, cmor_field_name, cmor_long_name, cmor_units, cmor_standard_name, area, x_cell_method, y_cell_method, area_cell_method, conversion)
 Registers a static diagnostic, returning an integer handle. More...
 
subroutine describe_option (opt_name, value, diag_CS)
 Describe an option setting in the diagnostic files. More...
 
integer function, public ocean_register_diag (var_desc, G, diag_CS, day)
 Registers a diagnostic using the information encapsulated in the vardesc type argument and returns an integer handle to this diagostic. That integer handle is negative if the diagnostic is unused. More...
 
subroutine, public diag_mediator_infrastructure_init (err_msg)
 
subroutine, public diag_mediator_init (G, GV, US, nz, param_file, diag_cs, doc_file_dir)
 diag_mediator_init initializes the MOM diag_mediator and opens the available diagnostics file, if appropriate. More...
 
subroutine, public diag_set_state_ptrs (h, T, S, eqn_of_state, diag_cs)
 Set pointers to the default state fields used to remap diagnostics. More...
 
subroutine, public diag_update_remap_grids (diag_cs, alt_h, alt_T, alt_S)
 Build/update vertical grids for diagnostic remapping. More...
 
subroutine, public diag_masks_set (G, nz, diag_cs)
 Sets up the 2d and 3d masks for native diagnostics. More...
 
subroutine, public diag_mediator_close_registration (diag_CS)
 
subroutine, public diag_mediator_end (time, diag_CS, end_diag_manager)
 
character(len=15) function i2s (a, n_in)
 Convert the first n elements (up to 3) of an integer array to an underscore delimited string. More...
 
integer function get_new_diag_id (diag_cs)
 Returns a new diagnostic id, it may be necessary to expand the diagnostics array. More...
 
subroutine initialize_diag_type (diag)
 Initializes a diag_type (used after allocating new memory) More...
 
subroutine alloc_diag_with_id (diag_id, diag_cs, diag)
 Make a new diagnostic. Either use memory which is in the array of 'primary' diagnostics, or if that is in use, insert it to the list of secondary diags. More...
 
subroutine log_available_diag (used, module_name, field_name, cell_methods_string, comment, diag_CS, long_name, units, standard_name)
 Log a diagnostic to the available diagnostics file. More...
 
subroutine log_chksum_diag (docunit, description, chksum)
 Log the diagnostic chksum to the chksum diag file. More...
 
subroutine, public diag_grid_storage_init (grid_storage, G, diag)
 Allocates fields necessary to store diagnostic remapping fields. More...
 
subroutine, public diag_copy_diag_to_storage (grid_storage, h_state, diag)
 Copy from the main diagnostic arrays to the grid storage as well as the native thicknesses. More...
 
subroutine, public diag_copy_storage_to_diag (diag, grid_storage)
 Copy from the stored diagnostic arrays to the main diagnostic grids. More...
 
subroutine, public diag_save_grids (diag)
 Save the current diagnostic grids in the temporary structure within diag. More...
 
subroutine, public diag_restore_grids (diag)
 Restore the diagnostic grids from the temporary structure within diag. More...
 
subroutine, public diag_grid_storage_end (grid_storage)
 Deallocates the fields in the remapping fields container. More...
 
subroutine downsample_diag_masks_set (G, nz, diag_cs)
 
subroutine downsample_diag_indices_get (fo1, fo2, dl, diag_cs, isv, iev, jsv, jev)
 Get the diagnostics-compute indices (to be passed to send_data) based on the shape of the diag field (the same way they are deduced for non-downsampled fields) More...
 
subroutine downsample_diag_field_3d (locfield, locfield_dsamp, dl, diag_cs, diag, isv, iev, jsv, jev, mask)
 This subroutine allocates and computes a downsampled array from an input array It also determines the diagnostics-compurte indices for the downsampled array 3d interface. More...
 
subroutine downsample_diag_field_2d (locfield, locfield_dsamp, dl, diag_cs, diag, isv, iev, jsv, jev, mask)
 This subroutine allocates and computes a downsampled array from an input array It also determines the diagnostics-compurte indices for the downsampled array 2d interface. More...
 
subroutine downsample_field_3d (field_in, field_out, dl, method, mask, diag_cs, diag, isv_o, jsv_o, isv_d, iev_d, jsv_d, jev_d)
 This subroutine allocates and computes a down sampled 3d array given an input array The down sample method is based on the "cell_methods" for the diagnostics as explained in the above table. More...
 
subroutine downsample_field_2d (field_in, field_out, dl, method, mask, diag_cs, diag, isv_o, jsv_o, isv_d, iev_d, jsv_d, jev_d)
 This subroutine allocates and computes a down sampled 2d array given an input array The down sample method is based on the "cell_methods" for the diagnostics as explained in the above table. More...
 
subroutine downsample_mask_2d (field_in, field_out, dl, isc_o, jsc_o, isc_d, iec_d, jsc_d, jec_d, isd_d, ied_d, jsd_d, jed_d)
 Allocate and compute the 2d down sampled mask The masks are down sampled based on a minority rule, i.e., a coarse cell is open (1) if at least one of the sub-cells are open, otherwise it's closed (0) More...
 
subroutine downsample_mask_3d (field_in, field_out, dl, isc_o, jsc_o, isc_d, iec_d, jsc_d, jec_d, isd_d, ied_d, jsd_d, jed_d)
 Allocate and compute the 3d down sampled mask The masks are down sampled based on a minority rule, i.e., a coarse cell is open (1) if at least one of the sub-cells are open, otherwise it's closed (0) More...
 

Function/Subroutine Documentation

◆ add_diag_to_list()

subroutine mom_diag_mediator::add_diag_to_list ( type(diag_ctrl), pointer  diag_cs,
integer, intent(inout)  dm_id,
integer, intent(in)  fms_id,
type(diag_type), pointer  this_diag,
type(axes_grp), intent(in), target  axes,
character(len=*), intent(in)  module_name,
character(len=*), intent(in)  field_name,
character(len=*), intent(in)  msg 
)
private

Create a diagnostic type and attached to list.

Parameters
diag_csDiagnostics mediator control structure
[in,out]dm_idThe diag_mediator ID for this diagnostic group
[in]fms_idThe FMS diag_manager ID for this diagnostic
this_diagThis diagnostic
[in]axesContainer w/ up to 3 integer handles that indicates axes for this field
[in]module_nameName of this module, usually "ocean_model" or "ice_shelf_model"
[in]field_nameName of diagnostic
[in]msgMessage for errors

Definition at line 2368 of file MOM_diag_mediator.F90.

2368  type(diag_ctrl), pointer :: diag_cs !< Diagnostics mediator control structure
2369  integer, intent(inout) :: dm_id !< The diag_mediator ID for this diagnostic group
2370  integer, intent(in) :: fms_id !< The FMS diag_manager ID for this diagnostic
2371  type(diag_type), pointer :: this_diag !< This diagnostic
2372  type(axes_grp), target, intent(in) :: axes !< Container w/ up to 3 integer handles that
2373  !! indicates axes for this field
2374  character(len=*), intent(in) :: module_name !< Name of this module, usually
2375  !! "ocean_model" or "ice_shelf_model"
2376  character(len=*), intent(in) :: field_name !< Name of diagnostic
2377  character(len=*), intent(in) :: msg !< Message for errors
2378 
2379  ! If the diagnostic is needed obtain a diag_mediator ID (if needed)
2380  if (dm_id == -1) dm_id = get_new_diag_id(diag_cs)
2381  ! Create a new diag_type to store links in
2382  call alloc_diag_with_id(dm_id, diag_cs, this_diag)
2383  call assert(associated(this_diag), trim(msg)//': diag_type allocation failed')
2384  ! Record FMS id, masks and conversion factor, in diag_type
2385  this_diag%fms_diag_id = fms_id
2386  this_diag%debug_str = trim(module_name)//"-"//trim(field_name)
2387  this_diag%axes => axes
2388 

◆ add_xyz_method()

subroutine mom_diag_mediator::add_xyz_method ( type(diag_type), pointer  diag,
type(axes_grp), intent(in)  axes,
character(len=*), intent(in), optional  x_cell_method,
character(len=*), intent(in), optional  y_cell_method,
character(len=*), intent(in), optional  v_cell_method,
logical, intent(in), optional  v_extensive 
)
private

Adds the encoded "cell_methods" for a diagnostics as a diag% property This allows access to the cell_method for a given diagnostics at the time of sending.

Parameters
diagThis diagnostic
[in]axesContainer w/ up to 3 integer handles that indicates axes for this field
[in]x_cell_methodSpecifies the cell method for the x-direction. Use '' have no method.
[in]y_cell_methodSpecifies the cell method for the y-direction. Use '' have no method.
[in]v_cell_methodSpecifies the cell method for the vertical direction. Use '' have no method.
[in]v_extensiveTrue for vertically extensive fields (vertically integrated). Default/absent for intensive.

Definition at line 2394 of file MOM_diag_mediator.F90.

2394  type(diag_type), pointer :: diag !< This diagnostic
2395  type(axes_grp), intent(in) :: axes !< Container w/ up to 3 integer handles that indicates
2396  !! axes for this field
2397  character(len=*), optional, intent(in) :: x_cell_method !< Specifies the cell method for the x-direction.
2398  !! Use '' have no method.
2399  character(len=*), optional, intent(in) :: y_cell_method !< Specifies the cell method for the y-direction.
2400  !! Use '' have no method.
2401  character(len=*), optional, intent(in) :: v_cell_method !< Specifies the cell method for the vertical direction.
2402  !! Use '' have no method.
2403  logical, optional, intent(in) :: v_extensive !< True for vertically extensive fields
2404  !! (vertically integrated). Default/absent for intensive.
2405  integer :: xyz_method
2406  character(len=9) :: mstr
2407 
2408  !This is a simple way to encode the cell method information made from 3 strings
2409  !(x_cell_method,y_cell_method,v_cell_method) in a 3 digit integer xyz
2410  !x_cell_method,y_cell_method,v_cell_method can each be 'point' or 'sum' or 'mean'
2411  !We can encode these with setting 1 for 'point', 2 for 'sum, 3 for 'mean' in
2412  !the 100s position for x, 10s position for y, 1s position for z
2413  !E.g., x:sum,y:point,z:mean is 213
2414 
2415  xyz_method = 111
2416 
2417  mstr = diag%axes%v_cell_method
2418  if (present(v_extensive)) then
2419  if (present(v_cell_method)) call mom_error(fatal, "attach_cell_methods: " // &
2420  'Vertical cell method was specified along with the vertically extensive flag.')
2421  if(v_extensive) then
2422  mstr='sum'
2423  else
2424  mstr='mean'
2425  endif
2426  elseif (present(v_cell_method)) then
2427  mstr = v_cell_method
2428  endif
2429  if (trim(mstr)=='sum') then
2430  xyz_method = xyz_method + 1
2431  elseif (trim(mstr)=='mean') then
2432  xyz_method = xyz_method + 2
2433  endif
2434 
2435  mstr = diag%axes%y_cell_method
2436  if (present(y_cell_method)) mstr = y_cell_method
2437  if (trim(mstr)=='sum') then
2438  xyz_method = xyz_method + 10
2439  elseif (trim(mstr)=='mean') then
2440  xyz_method = xyz_method + 20
2441  endif
2442 
2443  mstr = diag%axes%x_cell_method
2444  if (present(x_cell_method)) mstr = x_cell_method
2445  if (trim(mstr)=='sum') then
2446  xyz_method = xyz_method + 100
2447  elseif (trim(mstr)=='mean') then
2448  xyz_method = xyz_method + 200
2449  endif
2450 
2451  diag%xyz_method = xyz_method

◆ alloc_diag_with_id()

subroutine mom_diag_mediator::alloc_diag_with_id ( integer, intent(in)  diag_id,
type(diag_ctrl), intent(inout), target  diag_cs,
type(diag_type), pointer  diag 
)
private

Make a new diagnostic. Either use memory which is in the array of 'primary' diagnostics, or if that is in use, insert it to the list of secondary diags.

Parameters
[in]diag_idid for the diagnostic
[in,out]diag_csstructure used to regulate diagnostic output
diagstructure representing a diagnostic (inout)

Definition at line 3399 of file MOM_diag_mediator.F90.

3399  integer, intent(in ) :: diag_id !< id for the diagnostic
3400  type(diag_ctrl), target, intent(inout) :: diag_cs !< structure used to regulate diagnostic output
3401  type(diag_type), pointer :: diag !< structure representing a diagnostic (inout)
3402 
3403  type(diag_type), pointer :: tmp => null()
3404 
3405  if (.not. diag_cs%diags(diag_id)%in_use) then
3406  diag => diag_cs%diags(diag_id)
3407  else
3408  allocate(diag)
3409  tmp => diag_cs%diags(diag_id)%next
3410  diag_cs%diags(diag_id)%next => diag
3411  diag%next => tmp
3412  endif
3413  diag%in_use = .true.
3414 

◆ attach_cell_methods()

subroutine mom_diag_mediator::attach_cell_methods ( integer, intent(in)  id,
type(axes_grp), intent(in)  axes,
character(len=*), intent(out)  ostring,
character(len=*), intent(in), optional  cell_methods,
character(len=*), intent(in), optional  x_cell_method,
character(len=*), intent(in), optional  y_cell_method,
character(len=*), intent(in), optional  v_cell_method,
logical, intent(in), optional  v_extensive 
)
private

Attaches "cell_methods" attribute to a variable based on defaults for axes_grp or optional arguments.

Parameters
[in]idHandle to diagnostic
[in]axesContainer w/ up to 3 integer handles that indicates axes for this field
[out]ostringThe cell_methods strings that would appear in the file
[in]cell_methodsString to append as cell_methods attribute. Use '' to have no attribute. If present, this overrides the default constructed from the default for each individual axis direction.
[in]x_cell_methodSpecifies the cell method for the x-direction. Use '' have no method.
[in]y_cell_methodSpecifies the cell method for the y-direction. Use '' have no method.
[in]v_cell_methodSpecifies the cell method for the vertical direction. Use '' have no method.
[in]v_extensiveTrue for vertically extensive fields (vertically integrated). Default/absent for intensive.

Definition at line 2457 of file MOM_diag_mediator.F90.

2457  integer, intent(in) :: id !< Handle to diagnostic
2458  type(axes_grp), intent(in) :: axes !< Container w/ up to 3 integer handles that indicates
2459  !! axes for this field
2460  character(len=*), intent(out) :: ostring !< The cell_methods strings that would appear in the file
2461  character(len=*), optional, intent(in) :: cell_methods !< String to append as cell_methods attribute.
2462  !! Use '' to have no attribute. If present, this
2463  !! overrides the default constructed from the default
2464  !! for each individual axis direction.
2465  character(len=*), optional, intent(in) :: x_cell_method !< Specifies the cell method for the x-direction.
2466  !! Use '' have no method.
2467  character(len=*), optional, intent(in) :: y_cell_method !< Specifies the cell method for the y-direction.
2468  !! Use '' have no method.
2469  character(len=*), optional, intent(in) :: v_cell_method !< Specifies the cell method for the vertical direction.
2470  !! Use '' have no method.
2471  logical, optional, intent(in) :: v_extensive !< True for vertically extensive fields
2472  !! (vertically integrated). Default/absent for intensive.
2473  ! Local variables
2474  character(len=9) :: axis_name
2475  logical :: x_mean, y_mean, x_sum, y_sum
2476 
2477  x_mean = .false.
2478  y_mean = .false.
2479  x_sum = .false.
2480  y_sum = .false.
2481 
2482  ostring = ''
2483  if (present(cell_methods)) then
2484  if (present(x_cell_method) .or. present(y_cell_method) .or. present(v_cell_method) &
2485  .or. present(v_extensive)) then
2486  call mom_error(fatal, "attach_cell_methods: " // &
2487  'Individual direction cell method was specified along with a "cell_methods" string.')
2488  endif
2489  if (len(trim(cell_methods))>0) then
2490  call diag_field_add_attribute(id, 'cell_methods', trim(cell_methods))
2491  ostring = trim(cell_methods)
2492  endif
2493  else
2494  if (present(x_cell_method)) then
2495  if (len(trim(x_cell_method))>0) then
2496  call get_diag_axis_name(axes%handles(1), axis_name)
2497  call diag_field_add_attribute(id, 'cell_methods', trim(axis_name)//':'//trim(x_cell_method))
2498  ostring = trim(adjustl(ostring))//' '//trim(axis_name)//':'//trim(x_cell_method)
2499  if (trim(x_cell_method)=='mean') x_mean=.true.
2500  if (trim(x_cell_method)=='sum') x_sum=.true.
2501  endif
2502  else
2503  if (len(trim(axes%x_cell_method))>0) then
2504  call get_diag_axis_name(axes%handles(1), axis_name)
2505  call diag_field_add_attribute(id, 'cell_methods', trim(axis_name)//':'//trim(axes%x_cell_method))
2506  ostring = trim(adjustl(ostring))//' '//trim(axis_name)//':'//trim(axes%x_cell_method)
2507  if (trim(axes%x_cell_method)=='mean') x_mean=.true.
2508  if (trim(axes%x_cell_method)=='sum') x_sum=.true.
2509  endif
2510  endif
2511  if (present(y_cell_method)) then
2512  if (len(trim(y_cell_method))>0) then
2513  call get_diag_axis_name(axes%handles(2), axis_name)
2514  call diag_field_add_attribute(id, 'cell_methods', trim(axis_name)//':'//trim(y_cell_method))
2515  ostring = trim(adjustl(ostring))//' '//trim(axis_name)//':'//trim(y_cell_method)
2516  if (trim(y_cell_method)=='mean') y_mean=.true.
2517  if (trim(y_cell_method)=='sum') y_sum=.true.
2518  endif
2519  else
2520  if (len(trim(axes%y_cell_method))>0) then
2521  call get_diag_axis_name(axes%handles(2), axis_name)
2522  call diag_field_add_attribute(id, 'cell_methods', trim(axis_name)//':'//trim(axes%y_cell_method))
2523  ostring = trim(adjustl(ostring))//' '//trim(axis_name)//':'//trim(axes%y_cell_method)
2524  if (trim(axes%y_cell_method)=='mean') y_mean=.true.
2525  if (trim(axes%y_cell_method)=='sum') y_sum=.true.
2526  endif
2527  endif
2528  if (present(v_cell_method)) then
2529  if (present(v_extensive)) call mom_error(fatal, "attach_cell_methods: " // &
2530  'Vertical cell method was specified along with the vertically extensive flag.')
2531  if (len(trim(v_cell_method))>0) then
2532  if (axes%rank==1) then
2533  call get_diag_axis_name(axes%handles(1), axis_name)
2534  elseif (axes%rank==3) then
2535  call get_diag_axis_name(axes%handles(3), axis_name)
2536  endif
2537  call diag_field_add_attribute(id, 'cell_methods', trim(axis_name)//':'//trim(v_cell_method))
2538  ostring = trim(adjustl(ostring))//' '//trim(axis_name)//':'//trim(v_cell_method)
2539  endif
2540  elseif (present(v_extensive)) then
2541  if(v_extensive) then
2542  if (axes%rank==1) then
2543  call get_diag_axis_name(axes%handles(1), axis_name)
2544  elseif (axes%rank==3) then
2545  call get_diag_axis_name(axes%handles(3), axis_name)
2546  endif
2547  call diag_field_add_attribute(id, 'cell_methods', trim(axis_name)//':sum')
2548  ostring = trim(adjustl(ostring))//' '//trim(axis_name)//':sum'
2549  endif
2550  else
2551  if (len(trim(axes%v_cell_method))>0) then
2552  if (axes%rank==1) then
2553  call get_diag_axis_name(axes%handles(1), axis_name)
2554  elseif (axes%rank==3) then
2555  call get_diag_axis_name(axes%handles(3), axis_name)
2556  endif
2557  call diag_field_add_attribute(id, 'cell_methods', trim(axis_name)//':'//trim(axes%v_cell_method))
2558  ostring = trim(adjustl(ostring))//' '//trim(axis_name)//':'//trim(axes%v_cell_method)
2559  endif
2560  endif
2561  if (x_mean .and. y_mean) then
2562  call diag_field_add_attribute(id, 'cell_methods', 'area:mean')
2563  ostring = trim(adjustl(ostring))//' area:mean'
2564  elseif (x_sum .and. y_sum) then
2565  call diag_field_add_attribute(id, 'cell_methods', 'area:sum')
2566  ostring = trim(adjustl(ostring))//' area:sum'
2567  endif
2568  endif
2569  ostring = adjustl(ostring)

◆ define_axes_group()

subroutine, public mom_diag_mediator::define_axes_group ( type(diag_ctrl), intent(in), target  diag_cs,
integer, dimension(:), intent(in)  handles,
type(axes_grp), intent(out)  axes,
integer, intent(in), optional  nz,
integer, intent(in), optional  vertical_coordinate_number,
character(len=*), intent(in), optional  x_cell_method,
character(len=*), intent(in), optional  y_cell_method,
character(len=*), intent(in), optional  v_cell_method,
logical, intent(in), optional  is_h_point,
logical, intent(in), optional  is_q_point,
logical, intent(in), optional  is_u_point,
logical, intent(in), optional  is_v_point,
logical, intent(in), optional  is_layer,
logical, intent(in), optional  is_interface,
logical, intent(in), optional  is_native,
logical, intent(in), optional  needs_remapping,
logical, intent(in), optional  needs_interpolating,
type(axes_grp), optional, target  xyave_axes 
)

Defines a group of "axes" from list of handles.

Parameters
[in]diag_csDiagnostics control structure
[in]handlesA list of 1D axis handles
[out]axesThe group of 1D axes
[in]nzNumber of layers in this diagnostic grid
[in]vertical_coordinate_numberIndex number for vertical coordinate
[in]x_cell_methodA x-direction cell method used to construct the "cell_methods" attribute in CF convention
[in]y_cell_methodA y-direction cell method used to construct the "cell_methods" attribute in CF convention
[in]v_cell_methodA vertical direction cell method used to construct the "cell_methods" attribute in CF convention
[in]is_h_pointIf true, indicates this axes group for h-point located fields
[in]is_q_pointIf true, indicates this axes group for q-point located fields
[in]is_u_pointIf true, indicates this axes group for u-point located fields
[in]is_v_pointIf true, indicates this axes group for v-point located fields
[in]is_layerIf true, indicates that this axes group is for a layer vertically-located field.
[in]is_interfaceIf true, indicates that this axes group is for an interface vertically-located field.
[in]is_nativeIf true, indicates that this axes group is for a native model grid. False for any other grid.
[in]needs_remappingIf true, indicates that this axes group is for a intensive layer-located field that must be remapped to these axes. Used for rank>2.
[in]needs_interpolatingIf true, indicates that this axes group is for a sampled interface-located field that must be interpolated to these axes. Used for rank>2.
xyave_axesThe corresponding axes group for horizontally area-average diagnostics

Definition at line 943 of file MOM_diag_mediator.F90.

943  type(diag_ctrl), target, intent(in) :: diag_cs !< Diagnostics control structure
944  integer, dimension(:), intent(in) :: handles !< A list of 1D axis handles
945  type(axes_grp), intent(out) :: axes !< The group of 1D axes
946  integer, optional, intent(in) :: nz !< Number of layers in this diagnostic grid
947  integer, optional, intent(in) :: vertical_coordinate_number !< Index number for vertical coordinate
948  character(len=*), optional, intent(in) :: x_cell_method !< A x-direction cell method used to construct the
949  !! "cell_methods" attribute in CF convention
950  character(len=*), optional, intent(in) :: y_cell_method !< A y-direction cell method used to construct the
951  !! "cell_methods" attribute in CF convention
952  character(len=*), optional, intent(in) :: v_cell_method !< A vertical direction cell method used to construct
953  !! the "cell_methods" attribute in CF convention
954  logical, optional, intent(in) :: is_h_point !< If true, indicates this axes group for h-point
955  !! located fields
956  logical, optional, intent(in) :: is_q_point !< If true, indicates this axes group for q-point
957  !! located fields
958  logical, optional, intent(in) :: is_u_point !< If true, indicates this axes group for
959  !! u-point located fields
960  logical, optional, intent(in) :: is_v_point !< If true, indicates this axes group for
961  !! v-point located fields
962  logical, optional, intent(in) :: is_layer !< If true, indicates that this axes group is
963  !! for a layer vertically-located field.
964  logical, optional, intent(in) :: is_interface !< If true, indicates that this axes group
965  !! is for an interface vertically-located field.
966  logical, optional, intent(in) :: is_native !< If true, indicates that this axes group is
967  !! for a native model grid. False for any other grid.
968  logical, optional, intent(in) :: needs_remapping !< If true, indicates that this axes group is
969  !! for a intensive layer-located field that must
970  !! be remapped to these axes. Used for rank>2.
971  logical, optional, intent(in) :: needs_interpolating !< If true, indicates that this axes group
972  !! is for a sampled interface-located field that must
973  !! be interpolated to these axes. Used for rank>2.
974  type(axes_grp), optional, target :: xyave_axes !< The corresponding axes group for horizontally
975  !! area-average diagnostics
976  ! Local variables
977  integer :: n
978 
979  n = size(handles)
980  if (n<1 .or. n>3) call mom_error(fatal, "define_axes_group: wrong size for list of handles!")
981  allocate( axes%handles(n) )
982  axes%id = i2s(handles, n) ! Identifying string
983  axes%rank = n
984  axes%handles(:) = handles(:)
985  axes%diag_cs => diag_cs ! A [circular] link back to the diag_cs structure
986  if (present(x_cell_method)) then
987  if (axes%rank<2) call mom_error(fatal, 'define_axes_group: ' // &
988  'Can not set x_cell_method for rank<2.')
989  axes%x_cell_method = trim(x_cell_method)
990  else
991  axes%x_cell_method = ''
992  endif
993  if (present(y_cell_method)) then
994  if (axes%rank<2) call mom_error(fatal, 'define_axes_group: ' // &
995  'Can not set y_cell_method for rank<2.')
996  axes%y_cell_method = trim(y_cell_method)
997  else
998  axes%y_cell_method = ''
999  endif
1000  if (present(v_cell_method)) then
1001  if (axes%rank/=1 .and. axes%rank/=3) call mom_error(fatal, 'define_axes_group: ' // &
1002  'Can not set v_cell_method for rank<>1 or 3.')
1003  axes%v_cell_method = trim(v_cell_method)
1004  else
1005  axes%v_cell_method = ''
1006  endif
1007  if (present(nz)) axes%nz = nz
1008  if (present(vertical_coordinate_number)) axes%vertical_coordinate_number = vertical_coordinate_number
1009  if (present(is_h_point)) axes%is_h_point = is_h_point
1010  if (present(is_q_point)) axes%is_q_point = is_q_point
1011  if (present(is_u_point)) axes%is_u_point = is_u_point
1012  if (present(is_v_point)) axes%is_v_point = is_v_point
1013  if (present(is_layer)) axes%is_layer = is_layer
1014  if (present(is_interface)) axes%is_interface = is_interface
1015  if (present(is_native)) axes%is_native = is_native
1016  if (present(needs_remapping)) axes%needs_remapping = needs_remapping
1017  if (present(needs_interpolating)) axes%needs_interpolating = needs_interpolating
1018  if (present(xyave_axes)) axes%xyave_axes => xyave_axes
1019 
1020  ! Setup masks for this axes group
1021  axes%mask2d => null()
1022  if (axes%rank==2) then
1023  if (axes%is_h_point) axes%mask2d => diag_cs%mask2dT
1024  if (axes%is_u_point) axes%mask2d => diag_cs%mask2dCu
1025  if (axes%is_v_point) axes%mask2d => diag_cs%mask2dCv
1026  if (axes%is_q_point) axes%mask2d => diag_cs%mask2dBu
1027  endif
1028  ! A static 3d mask for non-native coordinates can only be setup when a grid is available
1029  axes%mask3d => null()
1030  if (axes%rank==3 .and. axes%is_native) then
1031  ! Native variables can/should use the native masks copied into diag_cs
1032  if (axes%is_layer) then
1033  if (axes%is_h_point) axes%mask3d => diag_cs%mask3dTL
1034  if (axes%is_u_point) axes%mask3d => diag_cs%mask3dCuL
1035  if (axes%is_v_point) axes%mask3d => diag_cs%mask3dCvL
1036  if (axes%is_q_point) axes%mask3d => diag_cs%mask3dBL
1037  elseif (axes%is_interface) then
1038  if (axes%is_h_point) axes%mask3d => diag_cs%mask3dTi
1039  if (axes%is_u_point) axes%mask3d => diag_cs%mask3dCui
1040  if (axes%is_v_point) axes%mask3d => diag_cs%mask3dCvi
1041  if (axes%is_q_point) axes%mask3d => diag_cs%mask3dBi
1042  endif
1043  endif
1044 

◆ define_axes_group_dsamp()

subroutine mom_diag_mediator::define_axes_group_dsamp ( type(diag_ctrl), intent(in), target  diag_cs,
integer, dimension(:), intent(in)  handles,
type(axes_grp), intent(out)  axes,
integer, intent(in)  dl,
integer, intent(in), optional  nz,
integer, intent(in), optional  vertical_coordinate_number,
character(len=*), intent(in), optional  x_cell_method,
character(len=*), intent(in), optional  y_cell_method,
character(len=*), intent(in), optional  v_cell_method,
logical, intent(in), optional  is_h_point,
logical, intent(in), optional  is_q_point,
logical, intent(in), optional  is_u_point,
logical, intent(in), optional  is_v_point,
logical, intent(in), optional  is_layer,
logical, intent(in), optional  is_interface,
logical, intent(in), optional  is_native,
logical, intent(in), optional  needs_remapping,
logical, intent(in), optional  needs_interpolating,
type(axes_grp), optional, target  xyave_axes 
)
private

Defines a group of downsampled "axes" from list of handles.

Parameters
[in]diag_csDiagnostics control structure
[in]handlesA list of 1D axis handles
[out]axesThe group of 1D axes
[in]dlDownsample level
[in]nzNumber of layers in this diagnostic grid
[in]vertical_coordinate_numberIndex number for vertical coordinate
[in]x_cell_methodA x-direction cell method used to construct the "cell_methods" attribute in CF convention
[in]y_cell_methodA y-direction cell method used to construct the "cell_methods" attribute in CF convention
[in]v_cell_methodA vertical direction cell method used to construct the "cell_methods" attribute in CF convention
[in]is_h_pointIf true, indicates this axes group for h-point located fields
[in]is_q_pointIf true, indicates this axes group for q-point located fields
[in]is_u_pointIf true, indicates this axes group for u-point located fields
[in]is_v_pointIf true, indicates this axes group for v-point located fields
[in]is_layerIf true, indicates that this axes group is for a layer vertically-located field.
[in]is_interfaceIf true, indicates that this axes group is for an interface vertically-located field.
[in]is_nativeIf true, indicates that this axes group is for a native model grid. False for any other grid.
[in]needs_remappingIf true, indicates that this axes group is for a intensive layer-located field that must be remapped to these axes. Used for rank>2.
[in]needs_interpolatingIf true, indicates that this axes group is for a sampled interface-located field that must be interpolated to these axes. Used for rank>2.
xyave_axesThe corresponding axes group for horizontally area-average diagnostics

Definition at line 1054 of file MOM_diag_mediator.F90.

1054  type(diag_ctrl), target, intent(in) :: diag_cs !< Diagnostics control structure
1055  integer, dimension(:), intent(in) :: handles !< A list of 1D axis handles
1056  type(axes_grp), intent(out) :: axes !< The group of 1D axes
1057  integer, intent(in) :: dl !< Downsample level
1058  integer, optional, intent(in) :: nz !< Number of layers in this diagnostic grid
1059  integer, optional, intent(in) :: vertical_coordinate_number !< Index number for vertical coordinate
1060  character(len=*), optional, intent(in) :: x_cell_method !< A x-direction cell method used to construct the
1061  !! "cell_methods" attribute in CF convention
1062  character(len=*), optional, intent(in) :: y_cell_method !< A y-direction cell method used to construct the
1063  !! "cell_methods" attribute in CF convention
1064  character(len=*), optional, intent(in) :: v_cell_method !< A vertical direction cell method used to construct
1065  !! the "cell_methods" attribute in CF convention
1066  logical, optional, intent(in) :: is_h_point !< If true, indicates this axes group for h-point
1067  !! located fields
1068  logical, optional, intent(in) :: is_q_point !< If true, indicates this axes group for q-point
1069  !! located fields
1070  logical, optional, intent(in) :: is_u_point !< If true, indicates this axes group for
1071  !! u-point located fields
1072  logical, optional, intent(in) :: is_v_point !< If true, indicates this axes group for
1073  !! v-point located fields
1074  logical, optional, intent(in) :: is_layer !< If true, indicates that this axes group is
1075  !! for a layer vertically-located field.
1076  logical, optional, intent(in) :: is_interface !< If true, indicates that this axes group
1077  !! is for an interface vertically-located field.
1078  logical, optional, intent(in) :: is_native !< If true, indicates that this axes group is
1079  !! for a native model grid. False for any other grid.
1080  logical, optional, intent(in) :: needs_remapping !< If true, indicates that this axes group is
1081  !! for a intensive layer-located field that must
1082  !! be remapped to these axes. Used for rank>2.
1083  logical, optional, intent(in) :: needs_interpolating !< If true, indicates that this axes group
1084  !! is for a sampled interface-located field that must
1085  !! be interpolated to these axes. Used for rank>2.
1086  type(axes_grp), optional, target :: xyave_axes !< The corresponding axes group for horizontally
1087  !! area-average diagnostics
1088  ! Local variables
1089  integer :: n
1090 
1091  n = size(handles)
1092  if (n<1 .or. n>3) call mom_error(fatal, "define_axes_group: wrong size for list of handles!")
1093  allocate( axes%handles(n) )
1094  axes%id = i2s(handles, n) ! Identifying string
1095  axes%rank = n
1096  axes%handles(:) = handles(:)
1097  axes%diag_cs => diag_cs ! A [circular] link back to the diag_cs structure
1098  if (present(x_cell_method)) then
1099  if (axes%rank<2) call mom_error(fatal, 'define_axes_group: ' // &
1100  'Can not set x_cell_method for rank<2.')
1101  axes%x_cell_method = trim(x_cell_method)
1102  else
1103  axes%x_cell_method = ''
1104  endif
1105  if (present(y_cell_method)) then
1106  if (axes%rank<2) call mom_error(fatal, 'define_axes_group: ' // &
1107  'Can not set y_cell_method for rank<2.')
1108  axes%y_cell_method = trim(y_cell_method)
1109  else
1110  axes%y_cell_method = ''
1111  endif
1112  if (present(v_cell_method)) then
1113  if (axes%rank/=1 .and. axes%rank/=3) call mom_error(fatal, 'define_axes_group: ' // &
1114  'Can not set v_cell_method for rank<>1 or 3.')
1115  axes%v_cell_method = trim(v_cell_method)
1116  else
1117  axes%v_cell_method = ''
1118  endif
1119  axes%downsample_level = dl
1120  if (present(nz)) axes%nz = nz
1121  if (present(vertical_coordinate_number)) axes%vertical_coordinate_number = vertical_coordinate_number
1122  if (present(is_h_point)) axes%is_h_point = is_h_point
1123  if (present(is_q_point)) axes%is_q_point = is_q_point
1124  if (present(is_u_point)) axes%is_u_point = is_u_point
1125  if (present(is_v_point)) axes%is_v_point = is_v_point
1126  if (present(is_layer)) axes%is_layer = is_layer
1127  if (present(is_interface)) axes%is_interface = is_interface
1128  if (present(is_native)) axes%is_native = is_native
1129  if (present(needs_remapping)) axes%needs_remapping = needs_remapping
1130  if (present(needs_interpolating)) axes%needs_interpolating = needs_interpolating
1131  if (present(xyave_axes)) axes%xyave_axes => xyave_axes
1132 
1133  ! Setup masks for this axes group
1134 
1135  axes%mask2d => null()
1136  if (axes%rank==2) then
1137  if (axes%is_h_point) axes%mask2d => diag_cs%mask2dT
1138  if (axes%is_u_point) axes%mask2d => diag_cs%mask2dCu
1139  if (axes%is_v_point) axes%mask2d => diag_cs%mask2dCv
1140  if (axes%is_q_point) axes%mask2d => diag_cs%mask2dBu
1141  endif
1142  ! A static 3d mask for non-native coordinates can only be setup when a grid is available
1143  axes%mask3d => null()
1144  if (axes%rank==3 .and. axes%is_native) then
1145  ! Native variables can/should use the native masks copied into diag_cs
1146  if (axes%is_layer) then
1147  if (axes%is_h_point) axes%mask3d => diag_cs%mask3dTL
1148  if (axes%is_u_point) axes%mask3d => diag_cs%mask3dCuL
1149  if (axes%is_v_point) axes%mask3d => diag_cs%mask3dCvL
1150  if (axes%is_q_point) axes%mask3d => diag_cs%mask3dBL
1151  elseif (axes%is_interface) then
1152  if (axes%is_h_point) axes%mask3d => diag_cs%mask3dTi
1153  if (axes%is_u_point) axes%mask3d => diag_cs%mask3dCui
1154  if (axes%is_v_point) axes%mask3d => diag_cs%mask3dCvi
1155  if (axes%is_q_point) axes%mask3d => diag_cs%mask3dBi
1156  endif
1157  endif
1158 
1159  axes%dsamp(dl)%mask2d => null()
1160  if (axes%rank==2) then
1161  if (axes%is_h_point) axes%dsamp(dl)%mask2d => diag_cs%dsamp(dl)%mask2dT
1162  if (axes%is_u_point) axes%dsamp(dl)%mask2d => diag_cs%dsamp(dl)%mask2dCu
1163  if (axes%is_v_point) axes%dsamp(dl)%mask2d => diag_cs%dsamp(dl)%mask2dCv
1164  if (axes%is_q_point) axes%dsamp(dl)%mask2d => diag_cs%dsamp(dl)%mask2dBu
1165  endif
1166  ! A static 3d mask for non-native coordinates can only be setup when a grid is available
1167  axes%dsamp(dl)%mask3d => null()
1168  if (axes%rank==3 .and. axes%is_native) then
1169  ! Native variables can/should use the native masks copied into diag_cs
1170  if (axes%is_layer) then
1171  if (axes%is_h_point) axes%dsamp(dl)%mask3d => diag_cs%dsamp(dl)%mask3dTL
1172  if (axes%is_u_point) axes%dsamp(dl)%mask3d => diag_cs%dsamp(dl)%mask3dCuL
1173  if (axes%is_v_point) axes%dsamp(dl)%mask3d => diag_cs%dsamp(dl)%mask3dCvL
1174  if (axes%is_q_point) axes%dsamp(dl)%mask3d => diag_cs%dsamp(dl)%mask3dBL
1175  elseif (axes%is_interface) then
1176  if (axes%is_h_point) axes%dsamp(dl)%mask3d => diag_cs%dsamp(dl)%mask3dTi
1177  if (axes%is_u_point) axes%dsamp(dl)%mask3d => diag_cs%dsamp(dl)%mask3dCui
1178  if (axes%is_v_point) axes%dsamp(dl)%mask3d => diag_cs%dsamp(dl)%mask3dCvi
1179  if (axes%is_q_point) axes%dsamp(dl)%mask3d => diag_cs%dsamp(dl)%mask3dBi
1180  endif
1181  endif
1182 

◆ describe_option()

subroutine mom_diag_mediator::describe_option ( character(len=*), intent(in)  opt_name,
character(len=*), intent(in)  value,
type(diag_ctrl), intent(in)  diag_CS 
)
private

Describe an option setting in the diagnostic files.

Parameters
[in]opt_nameThe name of the option
[in]valueA character string with the setting of the option.
[in]diag_csStructure used to regulate diagnostic output

Definition at line 2823 of file MOM_diag_mediator.F90.

2823  character(len=*), intent(in) :: opt_name !< The name of the option
2824  character(len=*), intent(in) :: value !< A character string with the setting of the option.
2825  type(diag_ctrl), intent(in) :: diag_CS !< Structure used to regulate diagnostic output
2826 
2827  character(len=240) :: mesg
2828  integer :: len_ind
2829 
2830  len_ind = len_trim(value) ! Add error handling for long values?
2831 
2832  mesg = " ! "//trim(opt_name)//": "//trim(value)
2833  write(diag_cs%available_diag_doc_unit, '(a)') trim(mesg)

◆ diag_associate_volume_cell_measure()

subroutine, public mom_diag_mediator::diag_associate_volume_cell_measure ( type(diag_ctrl), intent(inout)  diag_cs,
integer, intent(in)  id_h_volume 
)

Attaches the id of cell volumes to axes groups for use with cell_measures.

Parameters
[in,out]diag_csDiagnostics control structure
[in]id_h_volumeDiag_manager id for volume of h-cells

Definition at line 908 of file MOM_diag_mediator.F90.

908  type(diag_ctrl), intent(inout) :: diag_cs !< Diagnostics control structure
909  integer, intent(in) :: id_h_volume !< Diag_manager id for volume of h-cells
910  ! Local variables
911  type(diag_type), pointer :: tmp => null()
912 
913  if (id_h_volume<=0) return ! Do nothing
914  diag_cs%volume_cell_measure_dm_id = id_h_volume ! Record for diag_get_volume_cell_measure_dm_id()
915 
916  ! Set the cell measure for this axes group to the FMS id in this coordinate system
917  diag_cs%diags(id_h_volume)%axes%id_volume = diag_cs%diags(id_h_volume)%fms_diag_id
918 
919  tmp => diag_cs%diags(id_h_volume)%next ! First item in the list, if any
920  do while (associated(tmp))
921  ! Set the cell measure for this axes group to the FMS id in this coordinate system
922  tmp%axes%id_volume = tmp%fms_diag_id
923  tmp => tmp%next ! Move to next axes group for this field
924  enddo
925 

◆ diag_copy_diag_to_storage()

subroutine, public mom_diag_mediator::diag_copy_diag_to_storage ( type(diag_grid_storage), intent(inout)  grid_storage,
real, dimension(:,:,:), intent(in)  h_state,
type(diag_ctrl), intent(in)  diag 
)

Copy from the main diagnostic arrays to the grid storage as well as the native thicknesses.

Parameters
[in,out]grid_storageStructure containing a snapshot of the target grids
[in]h_stateCurrent model thicknesses
[in]diagDiagnostic control structure used as the contructor

Definition at line 3489 of file MOM_diag_mediator.F90.

3489  type(diag_grid_storage), intent(inout) :: grid_storage !< Structure containing a snapshot of the target grids
3490  real, dimension(:,:,:), intent(in) :: h_state !< Current model thicknesses
3491  type(diag_ctrl), intent(in) :: diag !< Diagnostic control structure used as the contructor
3492 
3493  integer :: m
3494 
3495  ! Don't do anything else if there are no remapped coordinates
3496  if (grid_storage%num_diag_coords < 1) return
3497 
3498  grid_storage%h_state(:,:,:) = h_state(:,:,:)
3499  do m = 1,grid_storage%num_diag_coords
3500  if (diag%diag_remap_cs(m)%nz > 0) &
3501  grid_storage%diag_grids(m)%h(:,:,:) = diag%diag_remap_cs(m)%h(:,:,:)
3502  enddo
3503 

◆ diag_copy_storage_to_diag()

subroutine, public mom_diag_mediator::diag_copy_storage_to_diag ( type(diag_ctrl), intent(inout)  diag,
type(diag_grid_storage), intent(in)  grid_storage 
)

Copy from the stored diagnostic arrays to the main diagnostic grids.

Parameters
[in,out]diagDiagnostic control structure used as the contructor
[in]grid_storageStructure containing a snapshot of the target grids

Definition at line 3508 of file MOM_diag_mediator.F90.

3508  type(diag_ctrl), intent(inout) :: diag !< Diagnostic control structure used as the contructor
3509  type(diag_grid_storage), intent(in) :: grid_storage !< Structure containing a snapshot of the target grids
3510 
3511  integer :: m
3512 
3513  ! Don't do anything else if there are no remapped coordinates
3514  if (grid_storage%num_diag_coords < 1) return
3515 
3516  diag%diag_grid_overridden = .true.
3517  do m = 1,grid_storage%num_diag_coords
3518  if (diag%diag_remap_cs(m)%nz > 0) &
3519  diag%diag_remap_cs(m)%h(:,:,:) = grid_storage%diag_grids(m)%h(:,:,:)
3520  enddo
3521 

◆ diag_get_volume_cell_measure_dm_id()

integer function, public mom_diag_mediator::diag_get_volume_cell_measure_dm_id ( type(diag_ctrl), intent(in)  diag_cs)

Returns diag_manager id for cell measure of h-cells.

Parameters
[in]diag_csDiagnostics control structure

Definition at line 930 of file MOM_diag_mediator.F90.

930  type(diag_ctrl), intent(in) :: diag_cs !< Diagnostics control structure
931 
932  diag_get_volume_cell_measure_dm_id = diag_cs%volume_cell_measure_dm_id
933 

◆ diag_grid_storage_end()

subroutine, public mom_diag_mediator::diag_grid_storage_end ( type(diag_grid_storage), intent(inout)  grid_storage)

Deallocates the fields in the remapping fields container.

Parameters
[in,out]grid_storageStructure containing a snapshot of the target grids

Definition at line 3559 of file MOM_diag_mediator.F90.

3559  type(diag_grid_storage), intent(inout) :: grid_storage !< Structure containing a snapshot of the target grids
3560  ! Local variables
3561  integer :: m, nz
3562 
3563  ! Don't do anything else if there are no remapped coordinates
3564  if (grid_storage%num_diag_coords < 1) return
3565 
3566  ! Deallocate memory for the native space
3567  deallocate(grid_storage%h_state)
3568  ! Loop through and deallocate memory for the grid on each target coordinate
3569  do m = 1, grid_storage%num_diag_coords
3570  deallocate(grid_storage%diag_grids(m)%h)
3571  enddo
3572  ! Deallocate diagnostic remapping structures
3573  deallocate(grid_storage%diag_grids)

◆ diag_grid_storage_init()

subroutine, public mom_diag_mediator::diag_grid_storage_init ( type(diag_grid_storage), intent(inout)  grid_storage,
type(ocean_grid_type), intent(in)  G,
type(diag_ctrl), intent(in)  diag 
)

Allocates fields necessary to store diagnostic remapping fields.

Parameters
[in,out]grid_storageStructure containing a snapshot of the target grids
[in]gHorizontal grid
[in]diagDiagnostic control structure used as the contructor template for this routine

Definition at line 3464 of file MOM_diag_mediator.F90.

3464  type(diag_grid_storage), intent(inout) :: grid_storage !< Structure containing a snapshot of the target grids
3465  type(ocean_grid_type), intent(in) :: G !< Horizontal grid
3466  type(diag_ctrl), intent(in) :: diag !< Diagnostic control structure used as the contructor
3467  !! template for this routine
3468 
3469  integer :: m, nz
3470  grid_storage%num_diag_coords = diag%num_diag_coords
3471 
3472  ! Don't do anything else if there are no remapped coordinates
3473  if (grid_storage%num_diag_coords < 1) return
3474 
3475  ! Allocate memory for the native space
3476  allocate(grid_storage%h_state(g%isd:g%ied,g%jsd:g%jed, g%ke))
3477  ! Allocate diagnostic remapping structures
3478  allocate(grid_storage%diag_grids(diag%num_diag_coords))
3479  ! Loop through and allocate memory for the grid on each target coordinate
3480  do m = 1, diag%num_diag_coords
3481  nz = diag%diag_remap_cs(m)%nz
3482  allocate(grid_storage%diag_grids(m)%h(g%isd:g%ied,g%jsd:g%jed, nz))
3483  enddo
3484 

◆ diag_masks_set()

subroutine, public mom_diag_mediator::diag_masks_set ( type(ocean_grid_type), intent(in), target  G,
integer, intent(in)  nz,
type(diag_ctrl), pointer  diag_cs 
)

Sets up the 2d and 3d masks for native diagnostics.

Parameters
[in]gThe ocean grid type.
[in]nzThe number of layers in the model's native grid.
diag_csA pointer to a type with many variables used for diagnostics

Definition at line 3220 of file MOM_diag_mediator.F90.

3220  type(ocean_grid_type), target, intent(in) :: G !< The ocean grid type.
3221  integer, intent(in) :: nz !< The number of layers in the model's native grid.
3222  type(diag_ctrl), pointer :: diag_cs !< A pointer to a type with many variables
3223  !! used for diagnostics
3224  ! Local variables
3225  integer :: k
3226 
3227  ! 2d masks point to the model masks since they are identical
3228  diag_cs%mask2dT => g%mask2dT
3229  diag_cs%mask2dBu => g%mask2dBu
3230  diag_cs%mask2dCu => g%mask2dCu
3231  diag_cs%mask2dCv => g%mask2dCv
3232 
3233  ! 3d native masks are needed by diag_manager but the native variables
3234  ! can only be masked 2d - for ocean points, all layers exists.
3235  allocate(diag_cs%mask3dTL(g%isd:g%ied,g%jsd:g%jed,1:nz))
3236  allocate(diag_cs%mask3dBL(g%IsdB:g%IedB,g%JsdB:g%JedB,1:nz))
3237  allocate(diag_cs%mask3dCuL(g%IsdB:g%IedB,g%jsd:g%jed,1:nz))
3238  allocate(diag_cs%mask3dCvL(g%isd:g%ied,g%JsdB:g%JedB,1:nz))
3239  do k=1,nz
3240  diag_cs%mask3dTL(:,:,k) = diag_cs%mask2dT(:,:)
3241  diag_cs%mask3dBL(:,:,k) = diag_cs%mask2dBu(:,:)
3242  diag_cs%mask3dCuL(:,:,k) = diag_cs%mask2dCu(:,:)
3243  diag_cs%mask3dCvL(:,:,k) = diag_cs%mask2dCv(:,:)
3244  enddo
3245  allocate(diag_cs%mask3dTi(g%isd:g%ied,g%jsd:g%jed,1:nz+1))
3246  allocate(diag_cs%mask3dBi(g%IsdB:g%IedB,g%JsdB:g%JedB,1:nz+1))
3247  allocate(diag_cs%mask3dCui(g%IsdB:g%IedB,g%jsd:g%jed,1:nz+1))
3248  allocate(diag_cs%mask3dCvi(g%isd:g%ied,g%JsdB:g%JedB,1:nz+1))
3249  do k=1,nz+1
3250  diag_cs%mask3dTi(:,:,k) = diag_cs%mask2dT(:,:)
3251  diag_cs%mask3dBi(:,:,k) = diag_cs%mask2dBu(:,:)
3252  diag_cs%mask3dCui(:,:,k) = diag_cs%mask2dCu(:,:)
3253  diag_cs%mask3dCvi(:,:,k) = diag_cs%mask2dCv(:,:)
3254  enddo
3255 
3256  !Allocate and initialize the downsampled masks
3257  call downsample_diag_masks_set(g, nz, diag_cs)
3258 

◆ diag_mediator_close_registration()

subroutine, public mom_diag_mediator::diag_mediator_close_registration ( type(diag_ctrl), intent(inout)  diag_CS)
Parameters
[in,out]diag_csStructure used to regulate diagnostic output

Definition at line 3262 of file MOM_diag_mediator.F90.

3262  type(diag_ctrl), intent(inout) :: diag_CS !< Structure used to regulate diagnostic output
3263 
3264  integer :: i
3265 
3266  if (diag_cs%available_diag_doc_unit > -1) then
3267  close(diag_cs%available_diag_doc_unit) ; diag_cs%available_diag_doc_unit = -2
3268  endif
3269 
3270  do i=1, diag_cs%num_diag_coords
3271  call diag_remap_diag_registration_closed(diag_cs%diag_remap_cs(i))
3272  enddo
3273 

◆ diag_mediator_end()

subroutine, public mom_diag_mediator::diag_mediator_end ( type(time_type), intent(in)  time,
type(diag_ctrl), intent(inout)  diag_CS,
logical, intent(in), optional  end_diag_manager 
)
Parameters
[in]timeThe current model time
[in,out]diag_csStructure used to regulate diagnostic output
[in]end_diag_managerIf true, call diag_manager_end()

Definition at line 3277 of file MOM_diag_mediator.F90.

3277  type(time_type), intent(in) :: time !< The current model time
3278  type(diag_ctrl), intent(inout) :: diag_CS !< Structure used to regulate diagnostic output
3279  logical, optional, intent(in) :: end_diag_manager !< If true, call diag_manager_end()
3280 
3281  ! Local variables
3282  integer :: i
3283 
3284  if (diag_cs%available_diag_doc_unit > -1) then
3285  close(diag_cs%available_diag_doc_unit) ; diag_cs%available_diag_doc_unit = -3
3286  endif
3287  if (diag_cs%chksum_iounit > -1) then
3288  close(diag_cs%chksum_iounit) ; diag_cs%chksum_iounit = -3
3289  endif
3290 
3291  deallocate(diag_cs%diags)
3292 
3293  do i=1, diag_cs%num_diag_coords
3294  call diag_remap_end(diag_cs%diag_remap_cs(i))
3295  enddo
3296 
3297  call diag_grid_storage_end(diag_cs%diag_grid_temp)
3298  deallocate(diag_cs%mask3dTL)
3299  deallocate(diag_cs%mask3dBL)
3300  deallocate(diag_cs%mask3dCuL)
3301  deallocate(diag_cs%mask3dCvL)
3302  deallocate(diag_cs%mask3dTi)
3303  deallocate(diag_cs%mask3dBi)
3304  deallocate(diag_cs%mask3dCui)
3305  deallocate(diag_cs%mask3dCvi)
3306  do i=2,max_dsamp_lev
3307  deallocate(diag_cs%dsamp(i)%mask2dT)
3308  deallocate(diag_cs%dsamp(i)%mask2dBu)
3309  deallocate(diag_cs%dsamp(i)%mask2dCu)
3310  deallocate(diag_cs%dsamp(i)%mask2dCv)
3311  deallocate(diag_cs%dsamp(i)%mask3dTL)
3312  deallocate(diag_cs%dsamp(i)%mask3dBL)
3313  deallocate(diag_cs%dsamp(i)%mask3dCuL)
3314  deallocate(diag_cs%dsamp(i)%mask3dCvL)
3315  deallocate(diag_cs%dsamp(i)%mask3dTi)
3316  deallocate(diag_cs%dsamp(i)%mask3dBi)
3317  deallocate(diag_cs%dsamp(i)%mask3dCui)
3318  deallocate(diag_cs%dsamp(i)%mask3dCvi)
3319  enddo
3320 
3321 #if defined(DEBUG) || defined(__DO_SAFETY_CHECKS__)
3322  deallocate(diag_cs%h_old)
3323 #endif
3324 
3325  if (present(end_diag_manager)) then
3326  if (end_diag_manager) call diag_manager_end(time)
3327  endif
3328 

◆ diag_mediator_infrastructure_init()

subroutine, public mom_diag_mediator::diag_mediator_infrastructure_init ( character(len=*), intent(out), optional  err_msg)
Parameters
[out]err_msgAn error message

Definition at line 2943 of file MOM_diag_mediator.F90.

2943  ! This subroutine initializes the FMS diag_manager.
2944  character(len=*), optional, intent(out) :: err_msg !< An error message
2945 
2946  call diag_manager_init(err_msg=err_msg)

◆ diag_mediator_init()

subroutine, public mom_diag_mediator::diag_mediator_init ( type(ocean_grid_type), intent(inout), target  G,
type(verticalgrid_type), intent(in), target  GV,
type(unit_scale_type), intent(in), target  US,
integer, intent(in)  nz,
type(param_file_type), intent(in)  param_file,
type(diag_ctrl), intent(inout)  diag_cs,
character(len=*), intent(in), optional  doc_file_dir 
)

diag_mediator_init initializes the MOM diag_mediator and opens the available diagnostics file, if appropriate.

Parameters
[in,out]gThe ocean grid type.
[in]gvThe ocean vertical grid structure
[in]usA dimensional unit scaling type
[in]nzThe number of layers in the model's native grid.
[in]param_fileParameter file structure
[in,out]diag_csA pointer to a type with many variables used for diagnostics
[in]doc_file_dirA directory in which to create the file

Definition at line 2952 of file MOM_diag_mediator.F90.

2952  type(ocean_grid_type), target, intent(inout) :: G !< The ocean grid type.
2953  type(verticalGrid_type), target, intent(in) :: GV !< The ocean vertical grid structure
2954  type(unit_scale_type), target, intent(in) :: US !< A dimensional unit scaling type
2955  integer, intent(in) :: nz !< The number of layers in the model's native grid.
2956  type(param_file_type), intent(in) :: param_file !< Parameter file structure
2957  type(diag_ctrl), intent(inout) :: diag_cs !< A pointer to a type with many variables
2958  !! used for diagnostics
2959  character(len=*), optional, intent(in) :: doc_file_dir !< A directory in which to create the
2960  !! file
2961 
2962  ! This subroutine initializes the diag_mediator and the diag_manager.
2963  ! The grid type should have its dimensions set by this point, but it
2964  ! is not necessary that the metrics and axis labels be set up yet.
2965  integer :: ios, i, new_unit
2966  logical :: opened, new_file
2967  character(len=8) :: this_pe
2968  character(len=240) :: doc_file, doc_file_dflt, doc_path
2969  character(len=240), allocatable :: diag_coords(:)
2970 ! This include declares and sets the variable "version".
2971 #include "version_variable.h"
2972  character(len=40) :: mdl = "MOM_diag_mediator" ! This module's name.
2973  character(len=32) :: filename_appendix = '' !fms appendix to filename for ensemble runs
2974 
2975  id_clock_diag_mediator = cpu_clock_id('(Ocean diagnostics framework)', grain=clock_module)
2976  id_clock_diag_remap = cpu_clock_id('(Ocean diagnostics remapping)', grain=clock_routine)
2977  id_clock_diag_grid_updates = cpu_clock_id('(Ocean diagnostics grid updates)', grain=clock_routine)
2978 
2979  ! Allocate and initialize list of all diagnostics (and variants)
2980  allocate(diag_cs%diags(diag_alloc_chunk_size))
2981  diag_cs%next_free_diag_id = 1
2982  do i=1, diag_alloc_chunk_size
2983  call initialize_diag_type(diag_cs%diags(i))
2984  enddo
2985 
2986  ! Read all relevant parameters and write them to the model log.
2987  call log_version(param_file, mdl, version, "")
2988 
2989  call get_param(param_file, mdl, 'NUM_DIAG_COORDS', diag_cs%num_diag_coords, &
2990  'The number of diagnostic vertical coordinates to use. '//&
2991  'For each coordinate, an entry in DIAG_COORDS must be provided.', &
2992  default=1)
2993  if (diag_cs%num_diag_coords>0) then
2994  allocate(diag_coords(diag_cs%num_diag_coords))
2995  if (diag_cs%num_diag_coords==1) then ! The default is to provide just one instance of Z*
2996  call get_param(param_file, mdl, 'DIAG_COORDS', diag_coords, &
2997  'A list of string tuples associating diag_table modules to '//&
2998  'a coordinate definition used for diagnostics. Each string '//&
2999  'is of the form "MODULE_SUFFIX PARAMETER_SUFFIX COORDINATE_NAME".', &
3000  default='z Z ZSTAR')
3001  else ! If using more than 1 diagnostic coordinate, all must be explicitly defined
3002  call get_param(param_file, mdl, 'DIAG_COORDS', diag_coords, &
3003  'A list of string tuples associating diag_table modules to '//&
3004  'a coordinate definition used for diagnostics. Each string '//&
3005  'is of the form "MODULE_SUFFIX,PARAMETER_SUFFIX,COORDINATE_NAME".', &
3006  fail_if_missing=.true.)
3007  endif
3008  allocate(diag_cs%diag_remap_cs(diag_cs%num_diag_coords))
3009  ! Initialize each diagnostic vertical coordinate
3010  do i=1, diag_cs%num_diag_coords
3011  call diag_remap_init(diag_cs%diag_remap_cs(i), diag_coords(i))
3012  enddo
3013  deallocate(diag_coords)
3014  endif
3015 
3016  call get_param(param_file, mdl, 'DIAG_MISVAL', diag_cs%missing_value, &
3017  'Set the default missing value to use for diagnostics.', &
3018  default=1.e20)
3019  call get_param(param_file, mdl, 'DIAG_AS_CHKSUM', diag_cs%diag_as_chksum, &
3020  'Instead of writing diagnostics to the diag manager, write '//&
3021  'a text file containing the checksum (bitcount) of the array.', &
3022  default=.false.)
3023 
3024  if (diag_cs%diag_as_chksum) &
3025  diag_cs%num_chksum_diags = 0
3026 
3027  ! Keep pointers grid, h, T, S needed diagnostic remapping
3028  diag_cs%G => g
3029  diag_cs%GV => gv
3030  diag_cs%US => us
3031  diag_cs%h => null()
3032  diag_cs%T => null()
3033  diag_cs%S => null()
3034  diag_cs%eqn_of_state => null()
3035 
3036 #if defined(DEBUG) || defined(__DO_SAFETY_CHECKS__)
3037  allocate(diag_cs%h_old(g%isd:g%ied,g%jsd:g%jed,nz))
3038  diag_cs%h_old(:,:,:) = 0.0
3039 #endif
3040 
3041  diag_cs%is = g%isc - (g%isd-1) ; diag_cs%ie = g%iec - (g%isd-1)
3042  diag_cs%js = g%jsc - (g%jsd-1) ; diag_cs%je = g%jec - (g%jsd-1)
3043  diag_cs%isd = g%isd ; diag_cs%ied = g%ied
3044  diag_cs%jsd = g%jsd ; diag_cs%jed = g%jed
3045 
3046  !Downsample indices for dl=2 (should be generalized to arbitrary dl, perhaps via a G array)
3047  diag_cs%dsamp(2)%isc = g%HId2%isc - (g%HId2%isd-1) ; diag_cs%dsamp(2)%iec = g%HId2%iec - (g%HId2%isd-1)
3048  diag_cs%dsamp(2)%jsc = g%HId2%jsc - (g%HId2%jsd-1) ; diag_cs%dsamp(2)%jec = g%HId2%jec - (g%HId2%jsd-1)
3049  diag_cs%dsamp(2)%isd = g%HId2%isd ; diag_cs%dsamp(2)%ied = g%HId2%ied
3050  diag_cs%dsamp(2)%jsd = g%HId2%jsd ; diag_cs%dsamp(2)%jed = g%HId2%jed
3051  diag_cs%dsamp(2)%isg = g%HId2%isg ; diag_cs%dsamp(2)%ieg = g%HId2%ieg
3052  diag_cs%dsamp(2)%jsg = g%HId2%jsg ; diag_cs%dsamp(2)%jeg = g%HId2%jeg
3053  diag_cs%dsamp(2)%isgB = g%HId2%isgB ; diag_cs%dsamp(2)%iegB = g%HId2%iegB
3054  diag_cs%dsamp(2)%jsgB = g%HId2%jsgB ; diag_cs%dsamp(2)%jegB = g%HId2%jegB
3055 
3056  ! Initialze available diagnostic log file
3057  if (is_root_pe() .and. (diag_cs%available_diag_doc_unit < 0)) then
3058  write(this_pe,'(i6.6)') pe_here()
3059  doc_file_dflt = "available_diags."//this_pe
3060  call get_param(param_file, mdl, "AVAILABLE_DIAGS_FILE", doc_file, &
3061  "A file into which to write a list of all available "//&
3062  "ocean diagnostics that can be included in a diag_table.", &
3063  default=doc_file_dflt, do_not_log=(diag_cs%available_diag_doc_unit/=-1))
3064  if (len_trim(doc_file) > 0) then
3065  new_file = .true. ; if (diag_cs%available_diag_doc_unit /= -1) new_file = .false.
3066  ! Find an unused unit number.
3067  do new_unit=512,42,-1
3068  inquire( new_unit, opened=opened)
3069  if (.not.opened) exit
3070  enddo
3071  if (opened) call mom_error(fatal, &
3072  "diag_mediator_init failed to find an unused unit number.")
3073 
3074  doc_path = doc_file
3075  if (present(doc_file_dir)) then ; if (len_trim(doc_file_dir) > 0) then
3076  doc_path = trim(slasher(doc_file_dir))//trim(doc_file)
3077  endif ; endif
3078 
3079  diag_cs%available_diag_doc_unit = new_unit
3080 
3081  if (new_file) then
3082  open(diag_cs%available_diag_doc_unit, file=trim(doc_path), access='SEQUENTIAL', form='FORMATTED', &
3083  action='WRITE', status='REPLACE', iostat=ios)
3084  else ! This file is being reopened, and should be appended.
3085  open(diag_cs%available_diag_doc_unit, file=trim(doc_path), access='SEQUENTIAL', form='FORMATTED', &
3086  action='WRITE', status='OLD', position='APPEND', iostat=ios)
3087  endif
3088  inquire(diag_cs%available_diag_doc_unit, opened=opened)
3089  if ((.not.opened) .or. (ios /= 0)) then
3090  call mom_error(fatal, "Failed to open available diags file "//trim(doc_path)//".")
3091  endif
3092  endif
3093  endif
3094 
3095  if (is_root_pe() .and. (diag_cs%chksum_iounit < 0) .and. diag_cs%diag_as_chksum) then
3096  !write(this_pe,'(i6.6)') PE_here()
3097  !doc_file_dflt = "chksum_diag."//this_pe
3098  doc_file_dflt = "chksum_diag"
3099  call get_param(param_file, mdl, "CHKSUM_DIAG_FILE", doc_file, &
3100  "A file into which to write all checksums of the "//&
3101  "diagnostics listed in the diag_table.", &
3102  default=doc_file_dflt, do_not_log=(diag_cs%chksum_iounit/=-1))
3103 
3104  call get_filename_appendix(filename_appendix)
3105  if (len_trim(filename_appendix) > 0) then
3106  doc_file = trim(doc_file) //'.'//trim(filename_appendix)
3107  endif
3108 #ifdef STATSLABEL
3109  doc_file = trim(doc_file)//"."//trim(adjustl(statslabel))
3110 #endif
3111 
3112  if (len_trim(doc_file) > 0) then
3113  new_file = .true. ; if (diag_cs%chksum_iounit /= -1) new_file = .false.
3114  ! Find an unused unit number.
3115  do new_unit=512,42,-1
3116  inquire( new_unit, opened=opened)
3117  if (.not.opened) exit
3118  enddo
3119  if (opened) call mom_error(fatal, &
3120  "diag_mediator_init failed to find an unused unit number.")
3121 
3122  doc_path = doc_file
3123  if (present(doc_file_dir)) then ; if (len_trim(doc_file_dir) > 0) then
3124  doc_path = trim(slasher(doc_file_dir))//trim(doc_file)
3125  endif ; endif
3126 
3127  diag_cs%chksum_iounit = new_unit
3128 
3129  if (new_file) then
3130  open(diag_cs%chksum_iounit, file=trim(doc_path), access='SEQUENTIAL', form='FORMATTED', &
3131  action='WRITE', status='REPLACE', iostat=ios)
3132  else ! This file is being reopened, and should be appended.
3133  open(diag_cs%chksum_iounit, file=trim(doc_path), access='SEQUENTIAL', form='FORMATTED', &
3134  action='WRITE', status='OLD', position='APPEND', iostat=ios)
3135  endif
3136  inquire(diag_cs%chksum_iounit, opened=opened)
3137  if ((.not.opened) .or. (ios /= 0)) then
3138  call mom_error(fatal, "Failed to open checksum diags file "//trim(doc_path)//".")
3139  endif
3140  endif
3141  endif
3142 

◆ diag_register_area_ids()

subroutine, public mom_diag_mediator::diag_register_area_ids ( type(diag_ctrl), intent(inout)  diag_cs,
integer, intent(in), optional  id_area_t,
integer, intent(in), optional  id_area_q 
)

Attaches the id of cell areas to axes groups for use with cell_measures.

Parameters
[in,out]diag_csDiagnostics control structure
[in]id_area_tDiag_mediator id for area of h-cells
[in]id_area_qDiag_mediator id for area of q-cells

Definition at line 864 of file MOM_diag_mediator.F90.

864  type(diag_ctrl), intent(inout) :: diag_cs !< Diagnostics control structure
865  integer, optional, intent(in) :: id_area_t !< Diag_mediator id for area of h-cells
866  integer, optional, intent(in) :: id_area_q !< Diag_mediator id for area of q-cells
867  ! Local variables
868  integer :: fms_id, i
869  if (present(id_area_t)) then
870  fms_id = diag_cs%diags(id_area_t)%fms_diag_id
871  diag_cs%axesT1%id_area = fms_id
872  diag_cs%axesTi%id_area = fms_id
873  diag_cs%axesTL%id_area = fms_id
874  do i=1, diag_cs%num_diag_coords
875  diag_cs%remap_axesTL(i)%id_area = fms_id
876  diag_cs%remap_axesTi(i)%id_area = fms_id
877  enddo
878  endif
879  if (present(id_area_q)) then
880  fms_id = diag_cs%diags(id_area_q)%fms_diag_id
881  diag_cs%axesB1%id_area = fms_id
882  diag_cs%axesBi%id_area = fms_id
883  diag_cs%axesBL%id_area = fms_id
884  do i=1, diag_cs%num_diag_coords
885  diag_cs%remap_axesBL(i)%id_area = fms_id
886  diag_cs%remap_axesBi(i)%id_area = fms_id
887  enddo
888  endif

◆ diag_restore_grids()

subroutine, public mom_diag_mediator::diag_restore_grids ( type(diag_ctrl), intent(inout)  diag)

Restore the diagnostic grids from the temporary structure within diag.

Parameters
[in,out]diagDiagnostic control structure used as the contructor

Definition at line 3542 of file MOM_diag_mediator.F90.

3542  type(diag_ctrl), intent(inout) :: diag !< Diagnostic control structure used as the contructor
3543 
3544  integer :: m
3545 
3546  ! Don't do anything else if there are no remapped coordinates
3547  if (diag%num_diag_coords < 1) return
3548 
3549  diag%diag_grid_overridden = .false.
3550  do m = 1,diag%num_diag_coords
3551  if (diag%diag_remap_cs(m)%nz > 0) &
3552  diag%diag_remap_cs(m)%h(:,:,:) = diag%diag_grid_temp%diag_grids(m)%h(:,:,:)
3553  enddo
3554 

◆ diag_save_grids()

subroutine, public mom_diag_mediator::diag_save_grids ( type(diag_ctrl), intent(inout)  diag)

Save the current diagnostic grids in the temporary structure within diag.

Parameters
[in,out]diagDiagnostic control structure used as the contructor

Definition at line 3526 of file MOM_diag_mediator.F90.

3526  type(diag_ctrl), intent(inout) :: diag !< Diagnostic control structure used as the contructor
3527 
3528  integer :: m
3529 
3530  ! Don't do anything else if there are no remapped coordinates
3531  if (diag%num_diag_coords < 1) return
3532 
3533  do m = 1,diag%num_diag_coords
3534  if (diag%diag_remap_cs(m)%nz > 0) &
3535  diag%diag_grid_temp%diag_grids(m)%h(:,:,:) = diag%diag_remap_cs(m)%h(:,:,:)
3536  enddo
3537 

◆ diag_set_state_ptrs()

subroutine, public mom_diag_mediator::diag_set_state_ptrs ( real, dimension(:,:,:), intent(in), target  h,
real, dimension(:,:,:), intent(in), target  T,
real, dimension(:,:,:), intent(in), target  S,
type(eos_type), intent(in), target  eqn_of_state,
type(diag_ctrl), intent(inout)  diag_cs 
)

Set pointers to the default state fields used to remap diagnostics.

Parameters
[in]hthe model thickness array
[in]tthe model temperature array
[in]sthe model salinity array
[in]eqn_of_stateEquation of state structure
[in,out]diag_csdiag mediator control structure

Definition at line 3147 of file MOM_diag_mediator.F90.

3147  real, dimension(:,:,:), target, intent(in ) :: h !< the model thickness array
3148  real, dimension(:,:,:), target, intent(in ) :: T !< the model temperature array
3149  real, dimension(:,:,:), target, intent(in ) :: S !< the model salinity array
3150  type(EOS_type), target, intent(in ) :: eqn_of_state !< Equation of state structure
3151  type(diag_ctrl), intent(inout) :: diag_cs !< diag mediator control structure
3152 
3153  ! Keep pointers to h, T, S needed for the diagnostic remapping
3154  diag_cs%h => h
3155  diag_cs%T => t
3156  diag_cs%S => s
3157  diag_cs%eqn_of_state => eqn_of_state
3158 

◆ diag_update_remap_grids()

subroutine, public mom_diag_mediator::diag_update_remap_grids ( type(diag_ctrl), intent(inout)  diag_cs,
real, dimension(:,:,:), intent(in), optional, target  alt_h,
real, dimension(:,:,:), intent(in), optional, target  alt_T,
real, dimension(:,:,:), intent(in), optional, target  alt_S 
)

Build/update vertical grids for diagnostic remapping.

Note
The target grids need to be updated whenever sea surface height changes.
Parameters
[in,out]diag_csDiagnostics control structure
[in]alt_hUsed if remapped grids should be something other than the current thicknesses
[in]alt_tUsed if remapped grids should be something other than the current temperatures
[in]alt_sUsed if remapped grids should be something other than the current salinity

Definition at line 3165 of file MOM_diag_mediator.F90.

3165  type(diag_ctrl), intent(inout) :: diag_cs !< Diagnostics control structure
3166  real, target, optional, intent(in ) :: alt_h(:,:,:) !< Used if remapped grids should be something other than
3167  !! the current thicknesses
3168  real, target, optional, intent(in ) :: alt_T(:,:,:) !< Used if remapped grids should be something other than
3169  !! the current temperatures
3170  real, target, optional, intent(in ) :: alt_S(:,:,:) !< Used if remapped grids should be something other than
3171  !! the current salinity
3172  ! Local variables
3173  integer :: i
3174  real, dimension(:,:,:), pointer :: h_diag => null()
3175  real, dimension(:,:,:), pointer :: T_diag => null(), s_diag => null()
3176 
3177  if (present(alt_h)) then
3178  h_diag => alt_h
3179  else
3180  h_diag => diag_cs%h
3181  endif
3182 
3183  if (present(alt_t)) then
3184  t_diag => alt_t
3185  else
3186  t_diag => diag_cs%T
3187  endif
3188 
3189  if (present(alt_s)) then
3190  s_diag => alt_s
3191  else
3192  s_diag => diag_cs%S
3193  endif
3194 
3195  if (id_clock_diag_grid_updates>0) call cpu_clock_begin(id_clock_diag_grid_updates)
3196 
3197  if (diag_cs%diag_grid_overridden) then
3198  call mom_error(fatal, "diag_update_remap_grids was called, but current grids in "// &
3199  "diagnostic structure have been overridden")
3200  endif
3201 
3202  do i=1, diag_cs%num_diag_coords
3203  call diag_remap_update(diag_cs%diag_remap_cs(i), &
3204  diag_cs%G, diag_cs%GV, diag_cs%US, h_diag, t_diag, s_diag, &
3205  diag_cs%eqn_of_state)
3206  enddo
3207 
3208 #if defined(DEBUG) || defined(__DO_SAFETY_CHECKS__)
3209  ! Keep a copy of H - used to check whether grids are up-to-date
3210  ! when doing remapping.
3211  diag_cs%h_old(:,:,:) = diag_cs%h(:,:,:)
3212 #endif
3213 
3214  if (id_clock_diag_grid_updates>0) call cpu_clock_end(id_clock_diag_grid_updates)
3215 

◆ disable_averaging()

subroutine, public mom_diag_mediator::disable_averaging ( type(diag_ctrl), intent(inout)  diag_cs)

Call this subroutine to avoid averaging any offered fields.

Parameters
[in,out]diag_csStructure used to regulate diagnostic output

Definition at line 1820 of file MOM_diag_mediator.F90.

1820  type(diag_ctrl), intent(inout) :: diag_CS !< Structure used to regulate diagnostic output
1821 
1822  diag_cs%time_int = 0.0
1823  diag_cs%ave_enabled = .false.
1824 

◆ downsample_diag_field_2d()

subroutine mom_diag_mediator::downsample_diag_field_2d ( real, dimension(:,:), pointer  locfield,
real, dimension(:,:), intent(inout), allocatable  locfield_dsamp,
integer, intent(in)  dl,
type(diag_ctrl), intent(in)  diag_cs,
type(diag_type), intent(in)  diag,
integer, intent(inout)  isv,
integer, intent(inout)  iev,
integer, intent(inout)  jsv,
integer, intent(inout)  jev,
real, dimension(:,:), intent(in), optional, target  mask 
)
private

This subroutine allocates and computes a downsampled array from an input array It also determines the diagnostics-compurte indices for the downsampled array 2d interface.

Parameters
locfieldInput array pointer
[in,out]locfield_dsampOutput (downsampled) array
[in]diag_csStructure used to regulate diagnostic output
[in]diagA structure describing the diagnostic to post
[in]dlLevel of down sampling
[in,out]isvi-start index for diagnostics
[in,out]ievi-end index for diagnostics
[in,out]jsvj-start index for diagnostics
[in,out]jevj-end index for diagnostics
[in]maskIf present, use this real array as the data mask.

Definition at line 3752 of file MOM_diag_mediator.F90.

3752  real, dimension(:,:), pointer :: locfield !< Input array pointer
3753  real, dimension(:,:), allocatable, intent(inout) :: locfield_dsamp !< Output (downsampled) array
3754  type(diag_ctrl), intent(in) :: diag_CS !< Structure used to regulate diagnostic output
3755  type(diag_type), intent(in) :: diag !< A structure describing the diagnostic to post
3756  integer, intent(in) :: dl !< Level of down sampling
3757  integer, intent(inout) :: isv !< i-start index for diagnostics
3758  integer, intent(inout) :: iev !< i-end index for diagnostics
3759  integer, intent(inout) :: jsv !< j-start index for diagnostics
3760  integer, intent(inout) :: jev !< j-end index for diagnostics
3761  real, optional,target, intent(in) :: mask(:,:) !< If present, use this real array as the data mask.
3762  ! Locals
3763  real, dimension(:,:), pointer :: locmask
3764  integer :: f1,f2,isv_o,jsv_o
3765 
3766  locmask => null()
3767  !Get the correct indices corresponding to input field
3768  !Shape of the input diag field
3769  f1=size(locfield,1)
3770  f2=size(locfield,2)
3771  !Save the extents of the original (fine) domain
3772  isv_o=isv;jsv_o=jsv
3773  !Get the shape of the downsampled field and overwrite isv,iev,jsv,jev with them
3774  call downsample_diag_indices_get(f1,f2, dl, diag_cs,isv,iev,jsv,jev)
3775  !Set the non-downsampled mask, it must be associated and initialized
3776  if (present(mask)) then
3777  locmask => mask
3778  elseif (associated(diag%axes%mask2d)) then
3779  locmask => diag%axes%mask2d
3780  else
3781  call mom_error(fatal, "downsample_diag_field_2d: Cannot downsample without a mask!!! ")
3782  endif
3783 
3784  call downsample_field(locfield, locfield_dsamp, dl, diag%xyz_method, locmask, diag_cs,diag, &
3785  isv_o,jsv_o,isv,iev,jsv,jev)
3786 

◆ downsample_diag_field_3d()

subroutine mom_diag_mediator::downsample_diag_field_3d ( real, dimension(:,:,:), pointer  locfield,
real, dimension(:,:,:), intent(inout), allocatable  locfield_dsamp,
integer, intent(in)  dl,
type(diag_ctrl), intent(in)  diag_cs,
type(diag_type), intent(in)  diag,
integer, intent(inout)  isv,
integer, intent(inout)  iev,
integer, intent(inout)  jsv,
integer, intent(inout)  jev,
real, dimension(:,:,:), intent(in), optional, target  mask 
)
private

This subroutine allocates and computes a downsampled array from an input array It also determines the diagnostics-compurte indices for the downsampled array 3d interface.

Parameters
locfieldInput array pointer
[in,out]locfield_dsampOutput (downsampled) array
[in]diag_csStructure used to regulate diagnostic output
[in]diagA structure describing the diagnostic to post
[in]dlLevel of down sampling
[in,out]isvi-start index for diagnostics
[in,out]ievi-end index for diagnostics
[in,out]jsvj-start index for diagnostics
[in,out]jevj-end index for diagnostics
[in]maskIf present, use this real array as the data mask.

Definition at line 3711 of file MOM_diag_mediator.F90.

3711  real, dimension(:,:,:), pointer :: locfield !< Input array pointer
3712  real, dimension(:,:,:), allocatable, intent(inout) :: locfield_dsamp !< Output (downsampled) array
3713  type(diag_ctrl), intent(in) :: diag_CS !< Structure used to regulate diagnostic output
3714  type(diag_type), intent(in) :: diag !< A structure describing the diagnostic to post
3715  integer, intent(in) :: dl !< Level of down sampling
3716  integer, intent(inout) :: isv !< i-start index for diagnostics
3717  integer, intent(inout) :: iev !< i-end index for diagnostics
3718  integer, intent(inout) :: jsv !< j-start index for diagnostics
3719  integer, intent(inout) :: jev !< j-end index for diagnostics
3720  real, optional,target, intent(in) :: mask(:,:,:) !< If present, use this real array as the data mask.
3721  ! Locals
3722  real, dimension(:,:,:), pointer :: locmask
3723  integer :: f1,f2,isv_o,jsv_o
3724 
3725  locmask => null()
3726  !Get the correct indices corresponding to input field
3727  !Shape of the input diag field
3728  f1=size(locfield,1)
3729  f2=size(locfield,2)
3730  !Save the extents of the original (fine) domain
3731  isv_o=isv;jsv_o=jsv
3732  !Get the shape of the downsampled field and overwrite isv,iev,jsv,jev with them
3733  call downsample_diag_indices_get(f1,f2, dl, diag_cs,isv,iev,jsv,jev)
3734  !Set the non-downsampled mask, it must be associated and initialized
3735  if (present(mask)) then
3736  locmask => mask
3737  elseif (associated(diag%axes%mask3d)) then
3738  locmask => diag%axes%mask3d
3739  else
3740  call mom_error(fatal, "downsample_diag_field_3d: Cannot downsample without a mask!!! ")
3741  endif
3742 
3743  call downsample_field(locfield, locfield_dsamp, dl, diag%xyz_method, locmask, diag_cs, diag, &
3744  isv_o,jsv_o,isv,iev,jsv,jev)
3745 

◆ downsample_diag_indices_get()

subroutine mom_diag_mediator::downsample_diag_indices_get ( integer, intent(in)  fo1,
integer, intent(in)  fo2,
integer, intent(in)  dl,
type(diag_ctrl), intent(in)  diag_cs,
integer, intent(out)  isv,
integer, intent(out)  iev,
integer, intent(out)  jsv,
integer, intent(out)  jev 
)
private

Get the diagnostics-compute indices (to be passed to send_data) based on the shape of the diag field (the same way they are deduced for non-downsampled fields)

Parameters
[in]fo1The size of the diag field in x
[in]fo2The size of the diag field in y
[in]dlInteger downsample level
[in]diag_csStructure used to regulate diagnostic output
[out]isvi-start index for diagnostics
[out]ievi-end index for diagnostics
[out]jsvj-start index for diagnostics
[out]jevj-end index for diagnostics

Definition at line 3638 of file MOM_diag_mediator.F90.

3638  integer, intent(in) :: fo1 !< The size of the diag field in x
3639  integer, intent(in) :: fo2 !< The size of the diag field in y
3640  integer, intent(in) :: dl !< Integer downsample level
3641  type(diag_ctrl), intent(in) :: diag_CS !< Structure used to regulate diagnostic output
3642  integer, intent(out) :: isv !< i-start index for diagnostics
3643  integer, intent(out) :: iev !< i-end index for diagnostics
3644  integer, intent(out) :: jsv !< j-start index for diagnostics
3645  integer, intent(out) :: jev !< j-end index for diagnostics
3646  ! Local variables
3647  integer :: dszi,cszi,dszj,cszj,f1,f2
3648  character(len=500) :: mesg
3649  logical, save :: first_check = .true.
3650 
3651  !Check ONCE that the downsampled diag-compute domain is commensurate with the original
3652  !non-downsampled diag-compute domain.
3653  !This is a major limitation of the current implementation of the downsampled diagnostics.
3654  !We assume that the compute domain can be subdivided to dl*dl cells, hence avoiding the need of halo updates.
3655  !We want this check to error out only if there was a downsampled diagnostics requested and about to post that is
3656  !why the check is here and not in the init routines. This check need to be done only once, hence the outer if.
3657  if(first_check) then
3658  if(mod(diag_cs%ie-diag_cs%is+1, dl) .ne. 0 .OR. mod(diag_cs%je-diag_cs%js+1, dl) .ne. 0) then
3659  write (mesg,*) "Non-commensurate downsampled domain is not supported. "//&
3660  "Please choose a layout such that NIGLOBAL/Layout_X and NJGLOBAL/Layout_Y are both divisible by dl=",dl,&
3661  " Current domain extents: ", diag_cs%is,diag_cs%ie, diag_cs%js,diag_cs%je
3662  call mom_error(fatal,"downsample_diag_indices_get: "//trim(mesg))
3663  endif
3664  first_check = .false.
3665  endif
3666 
3667  cszi = diag_cs%dsamp(dl)%iec-diag_cs%dsamp(dl)%isc +1 ; dszi = diag_cs%dsamp(dl)%ied-diag_cs%dsamp(dl)%isd +1
3668  cszj = diag_cs%dsamp(dl)%jec-diag_cs%dsamp(dl)%jsc +1 ; dszj = diag_cs%dsamp(dl)%jed-diag_cs%dsamp(dl)%jsd +1
3669  isv = diag_cs%dsamp(dl)%isc ; iev = diag_cs%dsamp(dl)%iec
3670  jsv = diag_cs%dsamp(dl)%jsc ; jev = diag_cs%dsamp(dl)%jec
3671  f1 = fo1/dl
3672  f2 = fo2/dl
3673  !Correction for the symmetric case
3674  if (diag_cs%G%symmetric) then
3675  f1 = f1 + mod(fo1,dl)
3676  f2 = f2 + mod(fo2,dl)
3677  endif
3678  if ( f1 == dszi ) then
3679  isv = diag_cs%dsamp(dl)%isc ; iev = diag_cs%dsamp(dl)%iec ! field on Data domain, take compute domain indcies
3680  !The rest is not taken with the full MOM6 diag_table
3681  elseif ( f1 == dszi + 1 ) then
3682  isv = diag_cs%dsamp(dl)%isc ; iev = diag_cs%dsamp(dl)%iec+1 ! Symmetric data domain
3683  elseif ( f1 == cszi) then
3684  isv = 1 ; iev = (diag_cs%dsamp(dl)%iec-diag_cs%dsamp(dl)%isc) +1 ! Computational domain
3685  elseif ( f1 == cszi + 1 ) then
3686  isv = 1 ; iev = (diag_cs%dsamp(dl)%iec-diag_cs%dsamp(dl)%isc) +2 ! Symmetric computational domain
3687  else
3688  write (mesg,*) " peculiar size ",f1," in i-direction\n"//&
3689  "does not match one of ", cszi, cszi+1, dszi, dszi+1
3690  call mom_error(fatal,"downsample_diag_indices_get: "//trim(mesg))
3691  endif
3692  if ( f2 == dszj ) then
3693  jsv = diag_cs%dsamp(dl)%jsc ; jev = diag_cs%dsamp(dl)%jec ! Data domain
3694  elseif ( f2 == dszj + 1 ) then
3695  jsv = diag_cs%dsamp(dl)%jsc ; jev = diag_cs%dsamp(dl)%jec+1 ! Symmetric data domain
3696  elseif ( f2 == cszj) then
3697  jsv = 1 ; jev = (diag_cs%dsamp(dl)%jec-diag_cs%dsamp(dl)%jsc) +1 ! Computational domain
3698  elseif ( f2 == cszj + 1 ) then
3699  jsv = 1 ; jev = (diag_cs%dsamp(dl)%jec-diag_cs%dsamp(dl)%jsc) +2 ! Symmetric computational domain
3700  else
3701  write (mesg,*) " peculiar size ",f2," in j-direction\n"//&
3702  "does not match one of ", cszj, cszj+1, dszj, dszj+1
3703  call mom_error(fatal,"downsample_diag_indices_get: "//trim(mesg))
3704  endif

◆ downsample_diag_masks_set()

subroutine mom_diag_mediator::downsample_diag_masks_set ( type(ocean_grid_type), intent(in), target  G,
integer, intent(in)  nz,
type(diag_ctrl), pointer  diag_cs 
)
private
Parameters
[in]gThe ocean grid type.
[in]nzThe number of layers in the model's native grid.
diag_csA pointer to a type with many variables used for diagnostics

Definition at line 3579 of file MOM_diag_mediator.F90.

3579  type(ocean_grid_type), target, intent(in) :: G !< The ocean grid type.
3580  integer, intent(in) :: nz !< The number of layers in the model's native grid.
3581  type(diag_ctrl), pointer :: diag_cs !< A pointer to a type with many variables
3582  !! used for diagnostics
3583  ! Local variables
3584  integer :: i,j,k,ii,jj,dl
3585 
3586 !print*,'original c extents ',G%isc,G%iec,G%jsc,G%jec
3587 !print*,'original c extents ',G%iscb,G%iecb,G%jscb,G%jecb
3588 !print*,'coarse c extents ',G%HId2%isc,G%HId2%iec,G%HId2%jsc,G%HId2%jec
3589 !print*,'original d extents ',G%isd,G%ied,G%jsd,G%jed
3590 !print*,'coarse d extents ',G%HId2%isd,G%HId2%ied,G%HId2%jsd,G%HId2%jed
3591 ! original c extents 5 52 5 52
3592 ! original cB-nonsym extents 5 52 5 52
3593 ! original cB-sym extents 4 52 4 52
3594 ! coarse c extents 3 26 3 26
3595 ! original d extents 1 56 1 56
3596 ! original dB-nonsym extents 1 56 1 56
3597 ! original dB-sym extents 0 56 0 56
3598 ! coarse d extents 1 28 1 28
3599 
3600  do dl=2,max_dsamp_lev
3601  ! 2d mask
3602  call downsample_mask(g%mask2dT, diag_cs%dsamp(dl)%mask2dT, dl,g%isc, g%jsc, &
3603  g%HId2%isc, g%HId2%iec, g%HId2%jsc, g%HId2%jec, g%HId2%isd, g%HId2%ied, g%HId2%jsd, g%HId2%jed)
3604  call downsample_mask(g%mask2dBu,diag_cs%dsamp(dl)%mask2dBu, dl,g%IscB,g%JscB, &
3605  g%HId2%IscB,g%HId2%IecB,g%HId2%JscB,g%HId2%JecB,g%HId2%IsdB,g%HId2%IedB,g%HId2%JsdB,g%HId2%JedB)
3606  call downsample_mask(g%mask2dCu,diag_cs%dsamp(dl)%mask2dCu, dl,g%IscB,g%JscB, &
3607  g%HId2%IscB,g%HId2%IecB,g%HId2%jsc, g%HId2%jec,g%HId2%IsdB,g%HId2%IedB,g%HId2%jsd, g%HId2%jed)
3608  call downsample_mask(g%mask2dCv,diag_cs%dsamp(dl)%mask2dCv, dl,g%isc ,g%JscB, &
3609  g%HId2%isc ,g%HId2%iec, g%HId2%JscB,g%HId2%JecB,g%HId2%isd ,g%HId2%ied, g%HId2%JsdB,g%HId2%JedB)
3610  ! 3d native masks are needed by diag_manager but the native variables
3611  ! can only be masked 2d - for ocean points, all layers exists.
3612  allocate(diag_cs%dsamp(dl)%mask3dTL(g%HId2%isd:g%HId2%ied,g%HId2%jsd:g%HId2%jed,1:nz))
3613  allocate(diag_cs%dsamp(dl)%mask3dBL(g%HId2%IsdB:g%HId2%IedB,g%HId2%JsdB:g%HId2%JedB,1:nz))
3614  allocate(diag_cs%dsamp(dl)%mask3dCuL(g%HId2%IsdB:g%HId2%IedB,g%HId2%jsd:g%HId2%jed,1:nz))
3615  allocate(diag_cs%dsamp(dl)%mask3dCvL(g%HId2%isd:g%HId2%ied,g%HId2%JsdB:g%HId2%JedB,1:nz))
3616  do k=1,nz
3617  diag_cs%dsamp(dl)%mask3dTL(:,:,k) = diag_cs%dsamp(dl)%mask2dT(:,:)
3618  diag_cs%dsamp(dl)%mask3dBL(:,:,k) = diag_cs%dsamp(dl)%mask2dBu(:,:)
3619  diag_cs%dsamp(dl)%mask3dCuL(:,:,k) = diag_cs%dsamp(dl)%mask2dCu(:,:)
3620  diag_cs%dsamp(dl)%mask3dCvL(:,:,k) = diag_cs%dsamp(dl)%mask2dCv(:,:)
3621  enddo
3622  allocate(diag_cs%dsamp(dl)%mask3dTi(g%HId2%isd:g%HId2%ied,g%HId2%jsd:g%HId2%jed,1:nz+1))
3623  allocate(diag_cs%dsamp(dl)%mask3dBi(g%HId2%IsdB:g%HId2%IedB,g%HId2%JsdB:g%HId2%JedB,1:nz+1))
3624  allocate(diag_cs%dsamp(dl)%mask3dCui(g%HId2%IsdB:g%HId2%IedB,g%HId2%jsd:g%HId2%jed,1:nz+1))
3625  allocate(diag_cs%dsamp(dl)%mask3dCvi(g%HId2%isd:g%HId2%ied,g%HId2%JsdB:g%HId2%JedB,1:nz+1))
3626  do k=1,nz+1
3627  diag_cs%dsamp(dl)%mask3dTi(:,:,k) = diag_cs%dsamp(dl)%mask2dT(:,:)
3628  diag_cs%dsamp(dl)%mask3dBi(:,:,k) = diag_cs%dsamp(dl)%mask2dBu(:,:)
3629  diag_cs%dsamp(dl)%mask3dCui(:,:,k) = diag_cs%dsamp(dl)%mask2dCu(:,:)
3630  diag_cs%dsamp(dl)%mask3dCvi(:,:,k) = diag_cs%dsamp(dl)%mask2dCv(:,:)
3631  enddo
3632  enddo

◆ downsample_field_2d()

subroutine mom_diag_mediator::downsample_field_2d ( real, dimension(:,:), pointer  field_in,
real, dimension(:,:), allocatable  field_out,
integer, intent(in)  dl,
integer, intent(in)  method,
real, dimension(:,:), pointer  mask,
type(diag_ctrl), intent(in)  diag_cs,
type(diag_type), intent(in)  diag,
integer, intent(in)  isv_o,
integer, intent(in)  jsv_o,
integer, intent(in)  isv_d,
integer, intent(in)  iev_d,
integer, intent(in)  jsv_d,
integer, intent(in)  jev_d 
)
private

This subroutine allocates and computes a down sampled 2d array given an input array The down sample method is based on the "cell_methods" for the diagnostics as explained in the above table.

Parameters
field_inOriginal field to be down sampled
field_outDown sampled field
[in]dlLevel of down sampling
[in]methodSampling method
maskMask for field
[in]diag_csStructure used to regulate diagnostic output
[in]diagA structure describing the diagnostic to post
[in]isv_oOriginal i-start index
[in]jsv_oOriginal j-start index
[in]isv_di-start index of down sampled data
[in]iev_di-end index of down sampled data
[in]jsv_dj-start index of down sampled data
[in]jev_dj-end index of down sampled data

Definition at line 3998 of file MOM_diag_mediator.F90.

3998  real, dimension(:,:), pointer :: field_in !< Original field to be down sampled
3999  real, dimension(:,:), allocatable :: field_out !< Down sampled field
4000  integer, intent(in) :: dl !< Level of down sampling
4001  integer, intent(in) :: method !< Sampling method
4002  real, dimension(:,:), pointer :: mask !< Mask for field
4003  type(diag_ctrl), intent(in) :: diag_CS !< Structure used to regulate diagnostic output
4004  type(diag_type), intent(in) :: diag !< A structure describing the diagnostic to post
4005  integer, intent(in) :: isv_o !< Original i-start index
4006  integer, intent(in) :: jsv_o !< Original j-start index
4007  integer, intent(in) :: isv_d !< i-start index of down sampled data
4008  integer, intent(in) :: iev_d !< i-end index of down sampled data
4009  integer, intent(in) :: jsv_d !< j-start index of down sampled data
4010  integer, intent(in) :: jev_d !< j-end index of down sampled data
4011  ! Locals
4012  character(len=240) :: mesg
4013  integer :: i,j,ii,jj,i0,j0,f1,f2,f_in1,f_in2
4014  real :: ave,total_weight,weight
4015  real :: epsilon = 1.0e-20
4016 
4017  ! Allocate the down sampled field on the down sampled data domain
4018 ! allocate(field_out(diag_cs%dsamp(dl)%isd:diag_cs%dsamp(dl)%ied,diag_cs%dsamp(dl)%jsd:diag_cs%dsamp(dl)%jed))
4019 ! allocate(field_out(1:size(field_in,1)/dl,1:size(field_in,2)/dl))
4020  ! Fill the down sampled field on the down sampled diagnostics (almost always compuate) domain
4021  f_in1 = size(field_in,1)
4022  f_in2 = size(field_in,2)
4023  f1 = f_in1/dl
4024  f2 = f_in2/dl
4025  ! Correction for the symmetric case
4026  if (diag_cs%G%symmetric) then
4027  f1 = f1 + mod(f_in1,dl)
4028  f2 = f2 + mod(f_in2,dl)
4029  endif
4030  allocate(field_out(1:f1,1:f2))
4031 
4032  if(method .eq. mmp) then
4033  do j=jsv_d,jev_d ; do i=isv_d,iev_d
4034  i0 = isv_o+dl*(i-isv_d)
4035  j0 = jsv_o+dl*(j-jsv_d)
4036  ave = 0.0
4037  total_weight = 0.0
4038  do jj=j0,j0+dl-1 ; do ii=i0,i0+dl-1
4039 ! do ii=i0,i0+dl-1 ; do jj=j0,j0+dl-1
4040  weight = mask(ii,jj)*diag_cs%G%areaT(ii,jj)
4041  total_weight = total_weight + weight
4042  ave=ave+field_in(ii,jj)*weight
4043  enddo; enddo
4044  field_out(i,j) = ave/(total_weight+epsilon) !Avoid zero mask at all aggregating cells where ave=0.0
4045  enddo; enddo
4046  elseif(method .eq. ssp) then ! e.g., T_dfxy_cont_tendency_2d
4047  do j=jsv_d,jev_d ; do i=isv_d,iev_d
4048  i0 = isv_o+dl*(i-isv_d)
4049  j0 = jsv_o+dl*(j-jsv_d)
4050  ave = 0.0
4051  total_weight = 0.0
4052  do jj=j0,j0+dl-1 ; do ii=i0,i0+dl-1
4053 ! do ii=i0,i0+dl-1 ; do jj=j0,j0+dl-1
4054  weight = mask(ii,jj)
4055  total_weight = total_weight + weight
4056  ave=ave+field_in(ii,jj)*weight
4057  enddo; enddo
4058  field_out(i,j) = ave/(total_weight+epsilon) !Avoid zero mask at all aggregating cells where ave=0.0
4059  enddo; enddo
4060  elseif(method .eq. psp) then ! e.g., umo_2d
4061  do j=jsv_d,jev_d ; do i=isv_d,iev_d
4062  i0 = isv_o+dl*(i-isv_d)
4063  j0 = jsv_o+dl*(j-jsv_d)
4064  ave = 0.0
4065  total_weight = 0.0
4066  ii=i0
4067  do jj=j0,j0+dl-1
4068  weight =mask(ii,jj)
4069  total_weight = total_weight +weight
4070  ave=ave+field_in(ii,jj)*weight
4071  enddo
4072  field_out(i,j) = ave/(total_weight+epsilon) !Avoid zero mask at all aggregating cells where ave=0.0
4073  enddo; enddo
4074  elseif(method .eq. spp) then ! e.g., vmo_2d
4075  do j=jsv_d,jev_d ; do i=isv_d,iev_d
4076  i0 = isv_o+dl*(i-isv_d)
4077  j0 = jsv_o+dl*(j-jsv_d)
4078  ave = 0.0
4079  total_weight = 0.0
4080  jj=j0
4081  do ii=i0,i0+dl-1
4082  weight =mask(ii,jj)
4083  total_weight = total_weight +weight
4084  ave=ave+field_in(ii,jj)*weight
4085  enddo
4086  field_out(i,j) = ave/(total_weight+epsilon) !Avoid zero mask at all aggregating cells where ave=0.0
4087  enddo; enddo
4088  elseif(method .eq. pmp) then
4089  do j=jsv_d,jev_d ; do i=isv_d,iev_d
4090  i0 = isv_o+dl*(i-isv_d)
4091  j0 = jsv_o+dl*(j-jsv_d)
4092  ave = 0.0
4093  total_weight = 0.0
4094  ii=i0
4095  do jj=j0,j0+dl-1
4096  weight =mask(ii,jj)*diag_cs%G%dyCu(ii,jj)!*diag_cs%h(ii,jj,1) !Niki?
4097  total_weight = total_weight +weight
4098  ave=ave+field_in(ii,jj)*weight
4099  enddo
4100  field_out(i,j) = ave/(total_weight+epsilon) !Avoid zero mask at all aggregating cells where ave=0.0
4101  enddo; enddo
4102  elseif(method .eq. mpp) then
4103  do j=jsv_d,jev_d ; do i=isv_d,iev_d
4104  i0 = isv_o+dl*(i-isv_d)
4105  j0 = jsv_o+dl*(j-jsv_d)
4106  ave = 0.0
4107  total_weight = 0.0
4108  jj=j0
4109  do ii=i0,i0+dl-1
4110  weight =mask(ii,jj)*diag_cs%G%dxCv(ii,jj)!*diag_cs%h(ii,jj,1) !Niki?
4111  total_weight = total_weight +weight
4112  ave=ave+field_in(ii,jj)*weight
4113  enddo
4114  field_out(i,j) = ave/(total_weight+epsilon) !Avoid zero mask at all aggregating cells where ave=0.0
4115  enddo; enddo
4116  elseif(method .eq. msk) then !The input field is a mask, subsample
4117  field_out(:,:) = 0.0
4118  do j=jsv_d,jev_d ; do i=isv_d,iev_d
4119  i0 = isv_o+dl*(i-isv_d)
4120  j0 = jsv_o+dl*(j-jsv_d)
4121  ave = 0.0
4122  do jj=j0,j0+dl-1 ; do ii=i0,i0+dl-1
4123  ave=ave+field_in(ii,jj)
4124  enddo; enddo
4125  if(ave > 0.0) field_out(i,j)=1.0
4126  enddo; enddo
4127  else
4128  write (mesg,*) " unknown sampling method: ",method
4129  call mom_error(fatal, "downsample_field_2d: "//trim(mesg)//" "//trim(diag%debug_str))
4130  endif
4131 

◆ downsample_field_3d()

subroutine mom_diag_mediator::downsample_field_3d ( real, dimension(:,:,:), pointer  field_in,
real, dimension(:,:,:), allocatable  field_out,
integer, intent(in)  dl,
integer, intent(in)  method,
real, dimension(:,:,:), pointer  mask,
type(diag_ctrl), intent(in)  diag_cs,
type(diag_type), intent(in)  diag,
integer, intent(in)  isv_o,
integer, intent(in)  jsv_o,
integer, intent(in)  isv_d,
integer, intent(in)  iev_d,
integer, intent(in)  jsv_d,
integer, intent(in)  jev_d 
)
private

This subroutine allocates and computes a down sampled 3d array given an input array The down sample method is based on the "cell_methods" for the diagnostics as explained in the above table.

The down sample algorithm

The down sample method could be deduced (before send_data call) from the diagx_cell_method, diagy_cell_method and diagv_cell_method

This is the summary of the down sample algoritm for a diagnostic field f:

\[ f(Id,Jd) = \sum_{i,j} f(Id+i,Jd+j) * weight(Id+i,Jd+j) / [ \sum_{i,j} weight(Id+i,Jd+j)] \]

Here, i and j run from 0 to dl-1 (dl being the down sample level). Id,Jd are the down sampled (coarse grid) indices run over the coarsened compute grid, if and jf are the original (fine grid) indices.

 Example   x_cell y_cell v_cell algorithm_id    implemented weight(if,jf)
 ---------------------------------------------------------------------------------------
 theta     mean   mean   mean   MMM =222        G%areaT(if,jf)*h(if,jf)
 u         point  mean   mean   PMM =022        dyCu(if,jf)*h(if,jf)*delta(if,Id)
 v         mean   point  mean   MPM =202        dxCv(if,jf)*h(if,jf)*delta(jf,Jd)
 ?         point  sum    mean   PSM =012        h(if,jf)*delta(if,Id)
 volcello  sum    sum    sum    SSS =111        1
 T_dfxy_co sum    sum    point  SSP =110        1
 umo       point  sum    sum    PSS =011        1*delta(if,Id)
 vmo       sum    point  sum    SPS =101        1*delta(jf,Jd)
 umo_2d    point  sum    point  PSP =010        1*delta(if,Id)
 vmo_2d    sum    point  point  SPP =100        1*delta(jf,Jd)
 ?         point  mean   point  PMP =020        dyCu(if,jf)*delta(if,Id)
 ?         mean   point  point  MPP =200        dxCv(if,jf)*delta(jf,Jd)
 w         mean   mean   point  MMP =220        G%areaT(if,jf)
 h*theta   mean   mean   sum    MMS =221        G%areaT(if,jf)

 delta is the Kronecker delta
Parameters
field_inOriginal field to be down sampled
field_outdown sampled field
[in]dlLevel of down sampling
[in]methodSampling method
maskMask for field
[in]diag_csStructure used to regulate diagnostic output
[in]diagA structure describing the diagnostic to post
[in]isv_oOriginal i-start index
[in]jsv_oOriginal j-start index
[in]isv_di-start index of down sampled data
[in]iev_di-end index of down sampled data
[in]jsv_dj-start index of down sampled data
[in]jev_dj-end index of down sampled data

Definition at line 3827 of file MOM_diag_mediator.F90.

3827  real, dimension(:,:,:), pointer :: field_in !< Original field to be down sampled
3828  real, dimension(:,:,:), allocatable :: field_out !< down sampled field
3829  integer, intent(in) :: dl !< Level of down sampling
3830  integer, intent(in) :: method !< Sampling method
3831  real, dimension(:,:,:), pointer :: mask !< Mask for field
3832  type(diag_ctrl), intent(in) :: diag_CS !< Structure used to regulate diagnostic output
3833  type(diag_type), intent(in) :: diag !< A structure describing the diagnostic to post
3834  integer, intent(in) :: isv_o !< Original i-start index
3835  integer, intent(in) :: jsv_o !< Original j-start index
3836  integer, intent(in) :: isv_d !< i-start index of down sampled data
3837  integer, intent(in) :: iev_d !< i-end index of down sampled data
3838  integer, intent(in) :: jsv_d !< j-start index of down sampled data
3839  integer, intent(in) :: jev_d !< j-end index of down sampled data
3840  ! Locals
3841  character(len=240) :: mesg
3842  integer :: i,j,ii,jj,i0,j0,f1,f2,f_in1,f_in2
3843  integer :: k,ks,ke
3844  real :: ave,total_weight,weight
3845  real :: epsilon = 1.0e-20
3846 
3847  ks=1 ; ke =size(field_in,3)
3848  ! Allocate the down sampled field on the down sampled data domain
3849 ! allocate(field_out(diag_cs%dsamp(dl)%isd:diag_cs%dsamp(dl)%ied,diag_cs%dsamp(dl)%jsd:diag_cs%dsamp(dl)%jed,ks:ke))
3850 ! allocate(field_out(1:size(field_in,1)/dl,1:size(field_in,2)/dl,ks:ke))
3851  f_in1 = size(field_in,1)
3852  f_in2 = size(field_in,2)
3853  f1 = f_in1/dl
3854  f2 = f_in2/dl
3855  !Correction for the symmetric case
3856  if (diag_cs%G%symmetric) then
3857  f1 = f1 + mod(f_in1,dl)
3858  f2 = f2 + mod(f_in2,dl)
3859  endif
3860  allocate(field_out(1:f1,1:f2,ks:ke))
3861 
3862  ! Fill the down sampled field on the down sampled diagnostics (almost always compuate) domain
3863  if(method .eq. mmm) then
3864  do k= ks,ke ; do j=jsv_d,jev_d ; do i=isv_d,iev_d
3865  i0 = isv_o+dl*(i-isv_d)
3866  j0 = jsv_o+dl*(j-jsv_d)
3867  ave = 0.0
3868  total_weight = 0.0
3869  do jj=j0,j0+dl-1 ; do ii=i0,i0+dl-1
3870 ! do ii=i0,i0+dl-1 ; do jj=j0,j0+dl-1 !This seems to be faster!!!!
3871  weight = mask(ii,jj,k)*diag_cs%G%areaT(ii,jj)*diag_cs%h(ii,jj,k)
3872  total_weight = total_weight + weight
3873  ave=ave+field_in(ii,jj,k)*weight
3874  enddo; enddo
3875  field_out(i,j,k) = ave/(total_weight+epsilon) !Avoid zero mask at all aggregating cells where ave=0.0
3876  enddo; enddo; enddo
3877  elseif(method .eq. sss) then !e.g., volcello
3878  do k= ks,ke ; do j=jsv_d,jev_d ; do i=isv_d,iev_d
3879  i0 = isv_o+dl*(i-isv_d)
3880  j0 = jsv_o+dl*(j-jsv_d)
3881  ave = 0.0
3882  total_weight = 0.0
3883  do jj=j0,j0+dl-1 ; do ii=i0,i0+dl-1
3884 ! do ii=i0,i0+dl-1 ; do jj=j0,j0+dl-1
3885  weight = mask(ii,jj,k)
3886  total_weight = total_weight + weight
3887  ave=ave+field_in(ii,jj,k)*weight
3888  enddo; enddo
3889  field_out(i,j,k) = ave/(total_weight+epsilon) !Avoid zero mask at all aggregating cells where ave=0.0
3890  enddo; enddo; enddo
3891  elseif(method .eq. mmp .or. method .eq. mms) then !e.g., T_advection_xy
3892  do k= ks,ke ; do j=jsv_d,jev_d ; do i=isv_d,iev_d
3893  i0 = isv_o+dl*(i-isv_d)
3894  j0 = jsv_o+dl*(j-jsv_d)
3895  ave = 0.0
3896  total_weight = 0.0
3897  do jj=j0,j0+dl-1 ; do ii=i0,i0+dl-1
3898 ! do ii=i0,i0+dl-1 ; do jj=j0,j0+dl-1
3899  weight = mask(ii,jj,k)*diag_cs%G%areaT(ii,jj)
3900  total_weight = total_weight + weight
3901  ave=ave+field_in(ii,jj,k)*weight
3902  enddo; enddo
3903  field_out(i,j,k) = ave/(total_weight+epsilon) !Avoid zero mask at all aggregating cells where ave=0.0
3904  enddo; enddo; enddo
3905  elseif(method .eq. pmm) then
3906  do k= ks,ke ; do j=jsv_d,jev_d ; do i=isv_d,iev_d
3907  i0 = isv_o+dl*(i-isv_d)
3908  j0 = jsv_o+dl*(j-jsv_d)
3909  ave = 0.0
3910  total_weight = 0.0
3911  ii=i0
3912  do jj=j0,j0+dl-1
3913  weight =mask(ii,jj,k)*diag_cs%G%dyCu(ii,jj)*diag_cs%h(ii,jj,k)
3914  total_weight = total_weight +weight
3915  ave=ave+field_in(ii,jj,k)*weight
3916  enddo
3917  field_out(i,j,k) = ave/(total_weight+epsilon) !Avoid zero mask at all aggregating cells where ave=0.0
3918  enddo; enddo; enddo
3919  elseif(method .eq. psm) then
3920  do k= ks,ke ; do j=jsv_d,jev_d ; do i=isv_d,iev_d
3921  i0 = isv_o+dl*(i-isv_d)
3922  j0 = jsv_o+dl*(j-jsv_d)
3923  ave = 0.0
3924  total_weight = 0.0
3925  ii=i0
3926  do jj=j0,j0+dl-1
3927  weight =mask(ii,jj,k)*diag_cs%h(ii,jj,k)
3928  total_weight = total_weight +weight
3929  ave=ave+field_in(ii,jj,k)*weight
3930  enddo
3931  field_out(i,j,k) = ave/(total_weight+epsilon) !Avoid zero mask at all aggregating cells where ave=0.0
3932  enddo; enddo; enddo
3933  elseif(method .eq. pss) then !e.g. umo
3934  do k= ks,ke ; do j=jsv_d,jev_d ; do i=isv_d,iev_d
3935  i0 = isv_o+dl*(i-isv_d)
3936  j0 = jsv_o+dl*(j-jsv_d)
3937  ave = 0.0
3938  total_weight = 0.0
3939  ii=i0
3940  do jj=j0,j0+dl-1
3941  weight =mask(ii,jj,k)
3942  total_weight = total_weight +weight
3943  ave=ave+field_in(ii,jj,k)*weight
3944  enddo
3945  field_out(i,j,k) = ave/(total_weight+epsilon) !Avoid zero mask at all aggregating cells where ave=0.0
3946  enddo; enddo; enddo
3947  elseif(method .eq. sps) then !e.g. vmo
3948  do k= ks,ke ; do j=jsv_d,jev_d ; do i=isv_d,iev_d
3949  i0 = isv_o+dl*(i-isv_d)
3950  j0 = jsv_o+dl*(j-jsv_d)
3951  ave = 0.0
3952  total_weight = 0.0
3953  jj=j0
3954  do ii=i0,i0+dl-1
3955  weight =mask(ii,jj,k)
3956  total_weight = total_weight +weight
3957  ave=ave+field_in(ii,jj,k)*weight
3958  enddo
3959  field_out(i,j,k) = ave/(total_weight+epsilon) !Avoid zero mask at all aggregating cells where ave=0.0
3960  enddo; enddo; enddo
3961  elseif(method .eq. mpm) then
3962  do k= ks,ke ; do j=jsv_d,jev_d ; do i=isv_d,iev_d
3963  i0 = isv_o+dl*(i-isv_d)
3964  j0 = jsv_o+dl*(j-jsv_d)
3965  ave = 0.0
3966  total_weight = 0.0
3967  jj=j0
3968  do ii=i0,i0+dl-1
3969  weight = mask(ii,jj,k)*diag_cs%G%dxCv(ii,jj)*diag_cs%h(ii,jj,k)
3970  total_weight = total_weight + weight
3971  ave=ave+field_in(ii,jj,k)*weight
3972  enddo
3973  field_out(i,j,k) = ave/(total_weight+epsilon) !Avoid zero mask at all aggregating cells where ave=0.0
3974  enddo; enddo; enddo
3975  elseif(method .eq. msk) then !The input field is a mask, subsample
3976  field_out(:,:,:) = 0.0
3977  do k= ks,ke ; do j=jsv_d,jev_d ; do i=isv_d,iev_d
3978  i0 = isv_o+dl*(i-isv_d)
3979  j0 = jsv_o+dl*(j-jsv_d)
3980  ave = 0.0
3981  do jj=j0,j0+dl-1 ; do ii=i0,i0+dl-1
3982  ave=ave+field_in(ii,jj,k)
3983  enddo; enddo
3984  if(ave > 0.0) field_out(i,j,k)=1.0
3985  enddo; enddo; enddo
3986  else
3987  write (mesg,*) " unknown sampling method: ",method
3988  call mom_error(fatal, "downsample_field_3d: "//trim(mesg)//" "//trim(diag%debug_str))
3989  endif
3990 

◆ downsample_mask_2d()

subroutine mom_diag_mediator::downsample_mask_2d ( real, dimension(:,:), intent(in)  field_in,
real, dimension(:,:), pointer  field_out,
integer, intent(in)  dl,
integer, intent(in)  isc_o,
integer, intent(in)  jsc_o,
integer, intent(in)  isc_d,
integer, intent(in)  iec_d,
integer, intent(in)  jsc_d,
integer, intent(in)  jec_d,
integer, intent(in)  isd_d,
integer, intent(in)  ied_d,
integer, intent(in)  jsd_d,
integer, intent(in)  jed_d 
)
private

Allocate and compute the 2d down sampled mask The masks are down sampled based on a minority rule, i.e., a coarse cell is open (1) if at least one of the sub-cells are open, otherwise it's closed (0)

Parameters
[in]field_inOriginal field to be down sampled
field_outDown sampled field
[in]dlLevel of down sampling
[in]isc_oOriginal i-start index
[in]jsc_oOriginal j-start index
[in]isc_dComputational i-start index of down sampled data
[in]iec_dComputational i-end index of down sampled data
[in]jsc_dComputational j-start index of down sampled data
[in]jec_dComputational j-end index of down sampled data
[in]isd_dComputational i-start index of down sampled data
[in]ied_dComputational i-end index of down sampled data
[in]jsd_dComputational j-start index of down sampled data
[in]jed_dComputational j-end index of down sampled data

Definition at line 4139 of file MOM_diag_mediator.F90.

4139  real, dimension(:,:), intent(in) :: field_in !< Original field to be down sampled
4140  real, dimension(:,:), pointer :: field_out !< Down sampled field
4141  integer, intent(in) :: dl !< Level of down sampling
4142  integer, intent(in) :: isc_o !< Original i-start index
4143  integer, intent(in) :: jsc_o !< Original j-start index
4144  integer, intent(in) :: isc_d !< Computational i-start index of down sampled data
4145  integer, intent(in) :: iec_d !< Computational i-end index of down sampled data
4146  integer, intent(in) :: jsc_d !< Computational j-start index of down sampled data
4147  integer, intent(in) :: jec_d !< Computational j-end index of down sampled data
4148  integer, intent(in) :: isd_d !< Computational i-start index of down sampled data
4149  integer, intent(in) :: ied_d !< Computational i-end index of down sampled data
4150  integer, intent(in) :: jsd_d !< Computational j-start index of down sampled data
4151  integer, intent(in) :: jed_d !< Computational j-end index of down sampled data
4152  ! Locals
4153  integer :: i,j,ii,jj,i0,j0
4154  real :: tot_non_zero
4155  ! down sampled mask = 0 unless the mask value of one of the down sampling cells is 1
4156  allocate(field_out(isd_d:ied_d,jsd_d:jed_d))
4157  field_out(:,:) = 0.0
4158  do j=jsc_d,jec_d ; do i=isc_d,iec_d
4159  i0 = isc_o+dl*(i-isc_d)
4160  j0 = jsc_o+dl*(j-jsc_d)
4161  tot_non_zero = 0.0
4162  do jj=j0,j0+dl-1 ; do ii=i0,i0+dl-1
4163  tot_non_zero = tot_non_zero + field_in(ii,jj)
4164  enddo;enddo
4165  if(tot_non_zero > 0.0) field_out(i,j)=1.0
4166  enddo; enddo

◆ downsample_mask_3d()

subroutine mom_diag_mediator::downsample_mask_3d ( real, dimension(:,:,:), intent(in)  field_in,
real, dimension(:,:,:), pointer  field_out,
integer, intent(in)  dl,
integer, intent(in)  isc_o,
integer, intent(in)  jsc_o,
integer, intent(in)  isc_d,
integer, intent(in)  iec_d,
integer, intent(in)  jsc_d,
integer, intent(in)  jec_d,
integer, intent(in)  isd_d,
integer, intent(in)  ied_d,
integer, intent(in)  jsd_d,
integer, intent(in)  jed_d 
)
private

Allocate and compute the 3d down sampled mask The masks are down sampled based on a minority rule, i.e., a coarse cell is open (1) if at least one of the sub-cells are open, otherwise it's closed (0)

Parameters
[in]field_inOriginal field to be down sampled
field_outdown sampled field
[in]dlLevel of down sampling
[in]isc_oOriginal i-start index
[in]jsc_oOriginal j-start index
[in]isc_dComputational i-start index of down sampled data
[in]iec_dComputational i-end index of down sampled data
[in]jsc_dComputational j-start index of down sampled data
[in]jec_dComputational j-end index of down sampled data
[in]isd_dComputational i-start index of down sampled data
[in]ied_dComputational i-end index of down sampled data
[in]jsd_dComputational j-start index of down sampled data
[in]jed_dComputational j-end index of down sampled data

Definition at line 4174 of file MOM_diag_mediator.F90.

4174  real, dimension(:,:,:), intent(in) :: field_in !< Original field to be down sampled
4175  real, dimension(:,:,:), pointer :: field_out !< down sampled field
4176  integer, intent(in) :: dl !< Level of down sampling
4177  integer, intent(in) :: isc_o !< Original i-start index
4178  integer, intent(in) :: jsc_o !< Original j-start index
4179  integer, intent(in) :: isc_d !< Computational i-start index of down sampled data
4180  integer, intent(in) :: iec_d !< Computational i-end index of down sampled data
4181  integer, intent(in) :: jsc_d !< Computational j-start index of down sampled data
4182  integer, intent(in) :: jec_d !< Computational j-end index of down sampled data
4183  integer, intent(in) :: isd_d !< Computational i-start index of down sampled data
4184  integer, intent(in) :: ied_d !< Computational i-end index of down sampled data
4185  integer, intent(in) :: jsd_d !< Computational j-start index of down sampled data
4186  integer, intent(in) :: jed_d !< Computational j-end index of down sampled data
4187  ! Locals
4188  integer :: i,j,ii,jj,i0,j0,k,ks,ke
4189  real :: tot_non_zero
4190  ! down sampled mask = 0 unless the mask value of one of the down sampling cells is 1
4191  ks = lbound(field_in,3) ; ke = ubound(field_in,3)
4192  allocate(field_out(isd_d:ied_d,jsd_d:jed_d,ks:ke))
4193  field_out(:,:,:) = 0.0
4194  do k= ks,ke ; do j=jsc_d,jec_d ; do i=isc_d,iec_d
4195  i0 = isc_o+dl*(i-isc_d)
4196  j0 = jsc_o+dl*(j-jsc_d)
4197  tot_non_zero = 0.0
4198  do jj=j0,j0+dl-1 ; do ii=i0,i0+dl-1
4199  tot_non_zero = tot_non_zero + field_in(ii,jj,k)
4200  enddo;enddo
4201  if(tot_non_zero > 0.0) field_out(i,j,k)=1.0
4202  enddo; enddo; enddo

◆ enable_averaging()

subroutine, public mom_diag_mediator::enable_averaging ( real, intent(in)  time_int_in,
type(time_type), intent(in)  time_end_in,
type(diag_ctrl), intent(inout)  diag_cs 
)

This subroutine enables the accumulation of time averages over the specified time interval.

Parameters
[in]time_int_inThe time interval [s] over which any values that are offered are valid.
[in]time_end_inThe end time of the valid interval
[in,out]diag_csStructure used to regulate diagnostic output

Definition at line 1804 of file MOM_diag_mediator.F90.

1804  real, intent(in) :: time_int_in !< The time interval [s] over which any
1805  !! values that are offered are valid.
1806  type(time_type), intent(in) :: time_end_in !< The end time of the valid interval
1807  type(diag_ctrl), intent(inout) :: diag_CS !< Structure used to regulate diagnostic output
1808 
1809 ! This subroutine enables the accumulation of time averages over the
1810 ! specified time interval.
1811 
1812 ! if (num_file==0) return
1813  diag_cs%time_int = time_int_in
1814  diag_cs%time_end = time_end_in
1815  diag_cs%ave_enabled = .true.

◆ get_diag_time_end()

type(time_type) function, public mom_diag_mediator::get_diag_time_end ( type(diag_ctrl), intent(in)  diag_cs)

This function returns the valid end time for use with diagnostics that are handled outside of the MOM6 diagnostics infrastructure.

Parameters
[in]diag_csStructure used to regulate diagnostic output

Definition at line 1843 of file MOM_diag_mediator.F90.

1843  type(diag_ctrl), intent(in) :: diag_CS !< Structure used to regulate diagnostic output
1844  type(time_type) :: get_diag_time_end
1845  ! This function returns the valid end time for diagnostics that are handled
1846  ! outside of the MOM6 infrastructure, such as via the generic tracer code.
1847 
1848  get_diag_time_end = diag_cs%time_end

◆ get_new_diag_id()

integer function mom_diag_mediator::get_new_diag_id ( type(diag_ctrl), intent(inout)  diag_cs)
private

Returns a new diagnostic id, it may be necessary to expand the diagnostics array.

Parameters
[in,out]diag_csDiagnostics control structure

Definition at line 3355 of file MOM_diag_mediator.F90.

3355  type(diag_ctrl), intent(inout) :: diag_cs !< Diagnostics control structure
3356  ! Local variables
3357  type(diag_type), dimension(:), allocatable :: tmp
3358  integer :: i
3359 
3360  if (diag_cs%next_free_diag_id > size(diag_cs%diags)) then
3361  call assert(diag_cs%next_free_diag_id - size(diag_cs%diags) == 1, &
3362  'get_new_diag_id: inconsistent diag id')
3363 
3364  ! Increase the size of diag_cs%diags and copy data over.
3365  ! Do not use move_alloc() because it is not supported by Fortran 90
3366  allocate(tmp(size(diag_cs%diags)))
3367  tmp(:) = diag_cs%diags(:)
3368  deallocate(diag_cs%diags)
3369  allocate(diag_cs%diags(size(tmp) + diag_alloc_chunk_size))
3370  diag_cs%diags(1:size(tmp)) = tmp(:)
3371  deallocate(tmp)
3372 
3373  ! Initialize new part of the diag array.
3374  do i=diag_cs%next_free_diag_id, size(diag_cs%diags)
3375  call initialize_diag_type(diag_cs%diags(i))
3376  enddo
3377  endif
3378 
3379  get_new_diag_id = diag_cs%next_free_diag_id
3380  diag_cs%next_free_diag_id = diag_cs%next_free_diag_id + 1
3381 

◆ i2s()

character(len=15) function mom_diag_mediator::i2s ( integer, dimension(:), intent(in)  a,
integer, intent(in), optional  n_in 
)
private

Convert the first n elements (up to 3) of an integer array to an underscore delimited string.

Parameters
[in]aThe array of integers to translate
[in]n_inThe number of elements to translate, by default all
Returns
The returned string

Definition at line 3333 of file MOM_diag_mediator.F90.

3333  ! "Convert the first n elements of an integer array to a string."
3334  ! Perhaps this belongs elsewhere in the MOM6 code?
3335  integer, dimension(:), intent(in) :: a !< The array of integers to translate
3336  integer, optional , intent(in) :: n_in !< The number of elements to translate, by default all
3337  character(len=15) :: i2s !< The returned string
3338 
3339  character(len=15) :: i2s_temp
3340  integer :: i,n
3341 
3342  n=size(a)
3343  if (present(n_in)) n = n_in
3344 
3345  i2s = ''
3346  do i=1,min(n,3)
3347  write (i2s_temp, '(I4.4)') a(i)
3348  i2s = trim(i2s) //'_'// trim(i2s_temp)
3349  enddo
3350  i2s = adjustl(i2s)

◆ initialize_diag_type()

subroutine mom_diag_mediator::initialize_diag_type ( type(diag_type), intent(inout)  diag)
private

Initializes a diag_type (used after allocating new memory)

Parameters
[in,out]diagdiag_type to be initialized

Definition at line 3386 of file MOM_diag_mediator.F90.

3386  type(diag_type), intent(inout) :: diag !< diag_type to be initialized
3387 
3388  diag%in_use = .false.
3389  diag%fms_diag_id = -1
3390  diag%axes => null()
3391  diag%next => null()
3392  diag%conversion_factor = 0.
3393 

◆ log_available_diag()

subroutine mom_diag_mediator::log_available_diag ( logical, intent(in)  used,
character(len=*), intent(in)  module_name,
character(len=*), intent(in)  field_name,
character(len=*), intent(in)  cell_methods_string,
character(len=*), intent(in)  comment,
type(diag_ctrl), intent(in)  diag_CS,
character(len=*), intent(in), optional  long_name,
character(len=*), intent(in), optional  units,
character(len=*), intent(in), optional  standard_name 
)
private

Log a diagnostic to the available diagnostics file.

Parameters
[in]usedWhether this diagnostic was in the diag_table or not
[in]module_nameName of the diagnostic module
[in]field_nameName of this diagnostic field
[in]cell_methods_stringThe spatial component of the CF cell_methods attribute
[in]commentA comment to append after [Used|Unused]
[in]diag_csThe diagnotics control structure
[in]long_nameCF long name of diagnostic
[in]unitsUnits for diagnostic
[in]standard_nameCF standardized name of diagnostic

Definition at line 3420 of file MOM_diag_mediator.F90.

3420  logical, intent(in) :: used !< Whether this diagnostic was in the diag_table or not
3421  character(len=*), intent(in) :: module_name !< Name of the diagnostic module
3422  character(len=*), intent(in) :: field_name !< Name of this diagnostic field
3423  character(len=*), intent(in) :: cell_methods_string !< The spatial component of the CF cell_methods attribute
3424  character(len=*), intent(in) :: comment !< A comment to append after [Used|Unused]
3425  type(diag_ctrl), intent(in) :: diag_CS !< The diagnotics control structure
3426  character(len=*), optional, intent(in) :: long_name !< CF long name of diagnostic
3427  character(len=*), optional, intent(in) :: units !< Units for diagnostic
3428  character(len=*), optional, intent(in) :: standard_name !< CF standardized name of diagnostic
3429  ! Local variables
3430  character(len=240) :: mesg
3431 
3432  if (used) then
3433  mesg = '"'//trim(module_name)//'", "'//trim(field_name)//'" [Used]'
3434  else
3435  mesg = '"'//trim(module_name)//'", "'//trim(field_name)//'" [Unused]'
3436  endif
3437  if (len(trim((comment)))>0) then
3438  write(diag_cs%available_diag_doc_unit, '(a,x,"(",a,")")') trim(mesg),trim(comment)
3439  else
3440  write(diag_cs%available_diag_doc_unit, '(a)') trim(mesg)
3441  endif
3442  if (present(long_name)) call describe_option("long_name", long_name, diag_cs)
3443  if (present(units)) call describe_option("units", units, diag_cs)
3444  if (present(standard_name)) &
3445  call describe_option("standard_name", standard_name, diag_cs)
3446  if (len(trim((cell_methods_string)))>0) &
3447  call describe_option("cell_methods", trim(cell_methods_string), diag_cs)
3448 

◆ log_chksum_diag()

subroutine mom_diag_mediator::log_chksum_diag ( integer, intent(in)  docunit,
character(len=*), intent(in)  description,
integer, intent(in)  chksum 
)
private

Log the diagnostic chksum to the chksum diag file.

Parameters
[in]docunitHandle of the log file
[in]descriptionName of the diagnostic module
[in]chksumchksum of the diagnostic

Definition at line 3453 of file MOM_diag_mediator.F90.

3453  integer, intent(in) :: docunit !< Handle of the log file
3454  character(len=*), intent(in) :: description !< Name of the diagnostic module
3455  integer, intent(in) :: chksum !< chksum of the diagnostic
3456 
3457  write(docunit, '(a,x,i9.8)') description, chksum
3458  flush(docunit)
3459 

◆ ocean_register_diag()

integer function, public mom_diag_mediator::ocean_register_diag ( type(vardesc), intent(in)  var_desc,
type(ocean_grid_type), intent(in)  G,
type(diag_ctrl), intent(in), target  diag_CS,
type(time_type), intent(in)  day 
)

Registers a diagnostic using the information encapsulated in the vardesc type argument and returns an integer handle to this diagostic. That integer handle is negative if the diagnostic is unused.

Returns
An integer handle to this diagnostic.
Parameters
[in]var_descThe vardesc type describing the diagnostic
[in]gThe ocean's grid type
[in]diag_csThe diagnotic control structure
[in]dayThe current model time

Definition at line 2840 of file MOM_diag_mediator.F90.

2840  integer :: ocean_register_diag !< An integer handle to this diagnostic.
2841  type(vardesc), intent(in) :: var_desc !< The vardesc type describing the diagnostic
2842  type(ocean_grid_type), intent(in) :: G !< The ocean's grid type
2843  type(diag_ctrl), intent(in), target :: diag_CS !< The diagnotic control structure
2844  type(time_type), intent(in) :: day !< The current model time
2845 
2846  character(len=64) :: var_name ! A variable's name.
2847  character(len=48) :: units ! A variable's units.
2848  character(len=240) :: longname ! A variable's longname.
2849  character(len=8) :: hor_grid, z_grid ! Variable grid info.
2850  type(axes_grp), pointer :: axes => null()
2851 
2852  call query_vardesc(var_desc, units=units, longname=longname, hor_grid=hor_grid, &
2853  z_grid=z_grid, caller="ocean_register_diag")
2854 
2855  ! Use the hor_grid and z_grid components of vardesc to determine the
2856  ! desired axes to register the diagnostic field for.
2857  select case (z_grid)
2858 
2859  case ("L")
2860  select case (hor_grid)
2861  case ("q")
2862  axes => diag_cs%axesBL
2863  case ("h")
2864  axes => diag_cs%axesTL
2865  case ("u")
2866  axes => diag_cs%axesCuL
2867  case ("v")
2868  axes => diag_cs%axesCvL
2869  case ("Bu")
2870  axes => diag_cs%axesBL
2871  case ("T")
2872  axes => diag_cs%axesTL
2873  case ("Cu")
2874  axes => diag_cs%axesCuL
2875  case ("Cv")
2876  axes => diag_cs%axesCvL
2877  case ("z")
2878  axes => diag_cs%axeszL
2879  case default
2880  call mom_error(fatal, "ocean_register_diag: " // &
2881  "unknown hor_grid component "//trim(hor_grid))
2882  end select
2883 
2884  case ("i")
2885  select case (hor_grid)
2886  case ("q")
2887  axes => diag_cs%axesBi
2888  case ("h")
2889  axes => diag_cs%axesTi
2890  case ("u")
2891  axes => diag_cs%axesCui
2892  case ("v")
2893  axes => diag_cs%axesCvi
2894  case ("Bu")
2895  axes => diag_cs%axesBi
2896  case ("T")
2897  axes => diag_cs%axesTi
2898  case ("Cu")
2899  axes => diag_cs%axesCui
2900  case ("Cv")
2901  axes => diag_cs%axesCvi
2902  case ("z")
2903  axes => diag_cs%axeszi
2904  case default
2905  call mom_error(fatal, "ocean_register_diag: " // &
2906  "unknown hor_grid component "//trim(hor_grid))
2907  end select
2908 
2909  case ("1")
2910  select case (hor_grid)
2911  case ("q")
2912  axes => diag_cs%axesB1
2913  case ("h")
2914  axes => diag_cs%axesT1
2915  case ("u")
2916  axes => diag_cs%axesCu1
2917  case ("v")
2918  axes => diag_cs%axesCv1
2919  case ("Bu")
2920  axes => diag_cs%axesB1
2921  case ("T")
2922  axes => diag_cs%axesT1
2923  case ("Cu")
2924  axes => diag_cs%axesCu1
2925  case ("Cv")
2926  axes => diag_cs%axesCv1
2927  case default
2928  call mom_error(fatal, "ocean_register_diag: " // &
2929  "unknown hor_grid component "//trim(hor_grid))
2930  end select
2931 
2932  case default
2933  call mom_error(fatal,&
2934  "ocean_register_diag: unknown z_grid component "//trim(z_grid))
2935  end select
2936 
2937  ocean_register_diag = register_diag_field("ocean_model", trim(var_name), &
2938  axes, day, trim(longname), trim(units), missing_value=-1.0e+34)
2939 

◆ post_data_0d()

subroutine mom_diag_mediator::post_data_0d ( integer, intent(in)  diag_field_id,
real, intent(in)  field,
type(diag_ctrl), intent(in), target  diag_cs,
logical, intent(in), optional  is_static 
)
private

Make a real scalar diagnostic available for averaging or output.

Parameters
[in]diag_field_idThe id for an output variable returned by a previous call to register_diag_field.
[in]fieldreal value being offered for output or averaging
[in]diag_csStructure used to regulate diagnostic output
[in]is_staticIf true, this is a static field that is always offered.

Definition at line 1199 of file MOM_diag_mediator.F90.

1199  integer, intent(in) :: diag_field_id !< The id for an output variable returned by a
1200  !! previous call to register_diag_field.
1201  real, intent(in) :: field !< real value being offered for output or averaging
1202  type(diag_ctrl), target, intent(in) :: diag_CS !< Structure used to regulate diagnostic output
1203  logical, optional, intent(in) :: is_static !< If true, this is a static field that is always offered.
1204 
1205  ! Local variables
1206  logical :: used, is_stat
1207  type(diag_type), pointer :: diag => null()
1208 
1209  if (id_clock_diag_mediator>0) call cpu_clock_begin(id_clock_diag_mediator)
1210  is_stat = .false. ; if (present(is_static)) is_stat = is_static
1211 
1212  ! Iterate over list of diag 'variants', e.g. CMOR aliases, call send_data
1213  ! for each one.
1214  call assert(diag_field_id < diag_cs%next_free_diag_id, &
1215  'post_data_0d: Unregistered diagnostic id')
1216  diag => diag_cs%diags(diag_field_id)
1217  do while (associated(diag))
1218  if (diag_cs%diag_as_chksum) then
1219  call chksum0(field, diag%debug_str, logunit=diag_cs%chksum_iounit)
1220  else if (is_stat) then
1221  used = send_data(diag%fms_diag_id, field)
1222  elseif (diag_cs%ave_enabled) then
1223  used = send_data(diag%fms_diag_id, field, diag_cs%time_end)
1224  endif
1225  diag => diag%next
1226  enddo
1227 
1228  if (id_clock_diag_mediator>0) call cpu_clock_end(id_clock_diag_mediator)

◆ post_data_1d_k()

subroutine, public mom_diag_mediator::post_data_1d_k ( integer, intent(in)  diag_field_id,
real, dimension(:), intent(in), target  field,
type(diag_ctrl), intent(in), target  diag_cs,
logical, intent(in), optional  is_static 
)

Make a real 1-d array diagnostic available for averaging or output.

Parameters
[in]diag_field_idThe id for an output variable returned by a previous call to register_diag_field.
[in]field1-d array being offered for output or averaging
[in]diag_csStructure used to regulate diagnostic output
[in]is_staticIf true, this is a static field that is always offered.

Definition at line 1233 of file MOM_diag_mediator.F90.

1233  integer, intent(in) :: diag_field_id !< The id for an output variable returned by a
1234  !! previous call to register_diag_field.
1235  real, target, intent(in) :: field(:) !< 1-d array being offered for output or averaging
1236  type(diag_ctrl), target, intent(in) :: diag_CS !< Structure used to regulate diagnostic output
1237  logical, optional, intent(in) :: is_static !< If true, this is a static field that is always offered.
1238 
1239  ! Local variables
1240  logical :: used ! The return value of send_data is not used for anything.
1241  real, dimension(:), pointer :: locfield => null()
1242  logical :: is_stat
1243  integer :: k, ks, ke
1244  type(diag_type), pointer :: diag => null()
1245 
1246  if (id_clock_diag_mediator>0) call cpu_clock_begin(id_clock_diag_mediator)
1247  is_stat = .false. ; if (present(is_static)) is_stat = is_static
1248 
1249  ! Iterate over list of diag 'variants', e.g. CMOR aliases.
1250  call assert(diag_field_id < diag_cs%next_free_diag_id, &
1251  'post_data_1d_k: Unregistered diagnostic id')
1252  diag => diag_cs%diags(diag_field_id)
1253  do while (associated(diag))
1254 
1255  if ((diag%conversion_factor /= 0.) .and. (diag%conversion_factor /= 1.)) then
1256  ks = lbound(field,1) ; ke = ubound(field,1)
1257  allocate( locfield( ks:ke ) )
1258 
1259  do k=ks,ke
1260  if (field(k) == diag_cs%missing_value) then
1261  locfield(k) = diag_cs%missing_value
1262  else
1263  locfield(k) = field(k) * diag%conversion_factor
1264  endif
1265  enddo
1266  else
1267  locfield => field
1268  endif
1269 
1270  if (diag_cs%diag_as_chksum) then
1271  call zchksum(locfield, diag%debug_str, logunit=diag_cs%chksum_iounit)
1272  else if (is_stat) then
1273  used = send_data(diag%fms_diag_id, locfield)
1274  elseif (diag_cs%ave_enabled) then
1275  used = send_data(diag%fms_diag_id, locfield, diag_cs%time_end, weight=diag_cs%time_int)
1276  endif
1277  if ((diag%conversion_factor /= 0.) .and. (diag%conversion_factor /= 1.)) deallocate( locfield )
1278 
1279  diag => diag%next
1280  enddo
1281 
1282  if (id_clock_diag_mediator>0) call cpu_clock_end(id_clock_diag_mediator)

◆ post_data_2d()

subroutine mom_diag_mediator::post_data_2d ( integer, intent(in)  diag_field_id,
real, dimension(:,:), intent(in)  field,
type(diag_ctrl), intent(in), target  diag_cs,
logical, intent(in), optional  is_static,
real, dimension(:,:), intent(in), optional  mask 
)
private

Make a real 2-d array diagnostic available for averaging or output.

Parameters
[in]diag_field_idThe id for an output variable returned by a previous call to register_diag_field.
[in]field2-d array being offered for output or averaging
[in]diag_csStructure used to regulate diagnostic output
[in]is_staticIf true, this is a static field that is always offered.
[in]maskIf present, use this real array as the data mask.

Definition at line 1287 of file MOM_diag_mediator.F90.

1287  integer, intent(in) :: diag_field_id !< The id for an output variable returned by a
1288  !! previous call to register_diag_field.
1289  real, intent(in) :: field(:,:) !< 2-d array being offered for output or averaging
1290  type(diag_ctrl), target, intent(in) :: diag_CS !< Structure used to regulate diagnostic output
1291  logical, optional, intent(in) :: is_static !< If true, this is a static field that is always offered.
1292  real, optional, intent(in) :: mask(:,:) !< If present, use this real array as the data mask.
1293 
1294  ! Local variables
1295  type(diag_type), pointer :: diag => null()
1296 
1297  if (id_clock_diag_mediator>0) call cpu_clock_begin(id_clock_diag_mediator)
1298 
1299  ! Iterate over list of diag 'variants' (e.g. CMOR aliases) and post each.
1300  call assert(diag_field_id < diag_cs%next_free_diag_id, &
1301  'post_data_2d: Unregistered diagnostic id')
1302  diag => diag_cs%diags(diag_field_id)
1303  do while (associated(diag))
1304  call post_data_2d_low(diag, field, diag_cs, is_static, mask)
1305  diag => diag%next
1306  enddo
1307 
1308  if (id_clock_diag_mediator>0) call cpu_clock_end(id_clock_diag_mediator)

◆ post_data_2d_low()

subroutine mom_diag_mediator::post_data_2d_low ( type(diag_type), intent(in)  diag,
real, dimension(:,:), intent(in), target  field,
type(diag_ctrl), intent(in)  diag_cs,
logical, intent(in), optional  is_static,
real, dimension(:,:), intent(in), optional, target  mask 
)
private

Make a real 2-d array diagnostic available for averaging or output using a diag_type instead of an integer id.

Parameters
[in]diagA structure describing the diagnostic to post
[in]field2-d array being offered for output or averaging
[in]diag_csStructure used to regulate diagnostic output
[in]is_staticIf true, this is a static field that is always offered.
[in]maskIf present, use this real array as the data mask.

Definition at line 1314 of file MOM_diag_mediator.F90.

1314  type(diag_type), intent(in) :: diag !< A structure describing the diagnostic to post
1315  real, target, intent(in) :: field(:,:) !< 2-d array being offered for output or averaging
1316  type(diag_ctrl), intent(in) :: diag_CS !< Structure used to regulate diagnostic output
1317  logical, optional, intent(in) :: is_static !< If true, this is a static field that is always offered.
1318  real, optional,target, intent(in) :: mask(:,:) !< If present, use this real array as the data mask.
1319 
1320  ! Local variables
1321  real, dimension(:,:), pointer :: locfield
1322  real, dimension(:,:), pointer :: locmask
1323  character(len=300) :: mesg
1324  logical :: used, is_stat
1325  integer :: cszi, cszj, dszi, dszj
1326  integer :: isv, iev, jsv, jev, i, j, chksum, isv_o,jsv_o
1327  real, dimension(:,:), allocatable, target :: locfield_dsamp
1328  real, dimension(:,:), allocatable, target :: locmask_dsamp
1329  integer :: dl
1330 
1331  locfield => null()
1332  locmask => null()
1333  is_stat = .false. ; if (present(is_static)) is_stat = is_static
1334 
1335  ! Determine the propery array indices, noting that because of the (:,:)
1336  ! declaration of field, symmetric arrays are using a SW-grid indexing,
1337  ! but non-symmetric arrays are using a NE-grid indexing. Send_data
1338  ! actually only uses the difference between ie and is to determine
1339  ! the output data size and assumes that halos are symmetric.
1340  isv = diag_cs%is ; iev = diag_cs%ie ; jsv = diag_cs%js ; jev = diag_cs%je
1341 
1342  cszi = diag_cs%ie-diag_cs%is +1 ; dszi = diag_cs%ied-diag_cs%isd +1
1343  cszj = diag_cs%je-diag_cs%js +1 ; dszj = diag_cs%jed-diag_cs%jsd +1
1344  if ( size(field,1) == dszi ) then
1345  isv = diag_cs%is ; iev = diag_cs%ie ! Data domain
1346  elseif ( size(field,1) == dszi + 1 ) then
1347  isv = diag_cs%is ; iev = diag_cs%ie+1 ! Symmetric data domain
1348  elseif ( size(field,1) == cszi) then
1349  isv = 1 ; iev = cszi ! Computational domain
1350  elseif ( size(field,1) == cszi + 1 ) then
1351  isv = 1 ; iev = cszi+1 ! Symmetric computational domain
1352  else
1353  write (mesg,*) " peculiar size ",size(field,1)," in i-direction\n"//&
1354  "does not match one of ", cszi, cszi+1, dszi, dszi+1
1355  call mom_error(fatal,"post_data_2d_low: "//trim(diag%debug_str)//trim(mesg))
1356  endif
1357 
1358  if ( size(field,2) == dszj ) then
1359  jsv = diag_cs%js ; jev = diag_cs%je ! Data domain
1360  elseif ( size(field,2) == dszj + 1 ) then
1361  jsv = diag_cs%js ; jev = diag_cs%je+1 ! Symmetric data domain
1362  elseif ( size(field,2) == cszj ) then
1363  jsv = 1 ; jev = cszj ! Computational domain
1364  elseif ( size(field,2) == cszj+1 ) then
1365  jsv = 1 ; jev = cszj+1 ! Symmetric computational domain
1366  else
1367  write (mesg,*) " peculiar size ",size(field,2)," in j-direction\n"//&
1368  "does not match one of ", cszj, cszj+1, dszj, dszj+1
1369  call mom_error(fatal,"post_data_2d_low: "//trim(diag%debug_str)//trim(mesg))
1370  endif
1371 
1372  if ((diag%conversion_factor /= 0.) .and. (diag%conversion_factor /= 1.)) then
1373  allocate( locfield( lbound(field,1):ubound(field,1), lbound(field,2):ubound(field,2) ) )
1374  do j=jsv,jev ; do i=isv,iev
1375  if (field(i,j) == diag_cs%missing_value) then
1376  locfield(i,j) = diag_cs%missing_value
1377  else
1378  locfield(i,j) = field(i,j) * diag%conversion_factor
1379  endif
1380  enddo ; enddo
1381  locfield(isv:iev,jsv:jev) = field(isv:iev,jsv:jev) * diag%conversion_factor
1382  else
1383  locfield => field
1384  endif
1385 
1386  if (present(mask)) then
1387  locmask => mask
1388  elseif(.NOT. is_stat) then
1389  if(associated(diag%axes%mask2d)) locmask => diag%axes%mask2d
1390  endif
1391 
1392  dl=1
1393  if(.NOT. is_stat) dl = diag%axes%downsample_level !static field downsample i not supported yet
1394  !Downsample the diag field and mask (if present)
1395  if (dl > 1) then
1396  isv_o=isv ; jsv_o=jsv
1397  call downsample_diag_field(locfield, locfield_dsamp, dl, diag_cs, diag,isv,iev,jsv,jev, mask)
1398  if ((diag%conversion_factor /= 0.) .and. (diag%conversion_factor /= 1.)) deallocate( locfield )
1399  locfield => locfield_dsamp
1400  if (present(mask)) then
1401  call downsample_field_2d(locmask, locmask_dsamp, dl, msk, locmask, diag_cs,diag,isv_o,jsv_o,isv,iev,jsv,jev)
1402  locmask => locmask_dsamp
1403  elseif(associated(diag%axes%dsamp(dl)%mask2d)) then
1404  locmask => diag%axes%dsamp(dl)%mask2d
1405  endif
1406  endif
1407 
1408  if (diag_cs%diag_as_chksum) then
1409  if (diag%axes%is_h_point) then
1410  call hchksum(locfield, diag%debug_str, diag_cs%G%HI, &
1411  logunit=diag_cs%chksum_iounit)
1412  else if (diag%axes%is_u_point) then
1413  call uchksum(locfield, diag%debug_str, diag_cs%G%HI, &
1414  logunit=diag_cs%chksum_iounit)
1415  else if (diag%axes%is_v_point) then
1416  call vchksum(locfield, diag%debug_str, diag_cs%G%HI, &
1417  logunit=diag_cs%chksum_iounit)
1418  else if (diag%axes%is_q_point) then
1419  call bchksum(locfield, diag%debug_str, diag_cs%G%HI, &
1420  logunit=diag_cs%chksum_iounit)
1421  else
1422  call mom_error(fatal, "post_data_2d_low: unknown axis type.")
1423  endif
1424  else
1425  if (is_stat) then
1426  if (present(mask)) then
1427  call assert(size(locfield) == size(locmask), &
1428  'post_data_2d_low is_stat: mask size mismatch: '//diag%debug_str)
1429  used = send_data(diag%fms_diag_id, locfield, &
1430  is_in=isv, js_in=jsv, ie_in=iev, je_in=jev, rmask=locmask)
1431  !elseif (associated(diag%axes%mask2d)) then
1432  ! used = send_data(diag%fms_diag_id, locfield, &
1433  ! is_in=isv, js_in=jsv, ie_in=iev, je_in=jev, rmask=diag%axes%mask2d)
1434  else
1435  used = send_data(diag%fms_diag_id, locfield, &
1436  is_in=isv, js_in=jsv, ie_in=iev, je_in=jev)
1437  endif
1438  elseif (diag_cs%ave_enabled) then
1439  if (associated(locmask)) then
1440  call assert(size(locfield) == size(locmask), &
1441  'post_data_2d_low: mask size mismatch: '//diag%debug_str)
1442  used = send_data(diag%fms_diag_id, locfield, diag_cs%time_end, &
1443  is_in=isv, js_in=jsv, ie_in=iev, je_in=jev, &
1444  weight=diag_cs%time_int, rmask=locmask)
1445  else
1446  used = send_data(diag%fms_diag_id, locfield, diag_cs%time_end, &
1447  is_in=isv, js_in=jsv, ie_in=iev, je_in=jev, &
1448  weight=diag_cs%time_int)
1449  endif
1450  endif
1451  endif
1452  if ((diag%conversion_factor /= 0.) .and. (diag%conversion_factor /= 1.) .and. dl<2) &
1453  deallocate( locfield )

◆ post_data_3d()

subroutine mom_diag_mediator::post_data_3d ( integer, intent(in)  diag_field_id,
real, dimension(:,:,:), intent(in)  field,
type(diag_ctrl), intent(in), target  diag_cs,
logical, intent(in), optional  is_static,
real, dimension(:,:,:), intent(in), optional  mask,
real, dimension(:,:,:), intent(in), optional, target  alt_h 
)
private

Make a real 3-d array diagnostic available for averaging or output.

Parameters
[in]diag_field_idThe id for an output variable returned by a previous call to register_diag_field.
[in]field3-d array being offered for output or averaging
[in]diag_csStructure used to regulate diagnostic output
[in]is_staticIf true, this is a static field that is always offered.
[in]maskIf present, use this real array as the data mask.
[in]alt_hAn alternate thickness to use for vertically

Definition at line 1458 of file MOM_diag_mediator.F90.

1458 
1459  integer, intent(in) :: diag_field_id !< The id for an output variable returned by a
1460  !! previous call to register_diag_field.
1461  real, intent(in) :: field(:,:,:) !< 3-d array being offered for output or averaging
1462  type(diag_ctrl), target, intent(in) :: diag_CS !< Structure used to regulate diagnostic output
1463  logical, optional, intent(in) :: is_static !< If true, this is a static field that is always offered.
1464  real, optional, intent(in) :: mask(:,:,:) !< If present, use this real array as the data mask.
1465  real, dimension(:,:,:), &
1466  target, optional, intent(in) :: alt_h !< An alternate thickness to use for vertically
1467  !! remapping this diagnostic [H ~> m or kg m-2].
1468 
1469  ! Local variables
1470  type(diag_type), pointer :: diag => null()
1471  integer :: nz, i, j, k
1472  real, dimension(:,:,:), allocatable :: remapped_field
1473  logical :: staggered_in_x, staggered_in_y
1474  real, dimension(:,:,:), pointer :: h_diag => null()
1475 
1476  if (present(alt_h)) then
1477  h_diag => alt_h
1478  else
1479  h_diag => diag_cs%h
1480  endif
1481 
1482  if (id_clock_diag_mediator>0) call cpu_clock_begin(id_clock_diag_mediator)
1483 
1484  ! Iterate over list of diag 'variants', e.g. CMOR aliases, different vertical
1485  ! grids, and post each.
1486  call assert(diag_field_id < diag_cs%next_free_diag_id, &
1487  'post_data_3d: Unregistered diagnostic id')
1488  diag => diag_cs%diags(diag_field_id)
1489  do while (associated(diag))
1490  call assert(associated(diag%axes), 'post_data_3d: axes is not associated')
1491 
1492  staggered_in_x = diag%axes%is_u_point .or. diag%axes%is_q_point
1493  staggered_in_y = diag%axes%is_v_point .or. diag%axes%is_q_point
1494 
1495  if (diag%v_extensive .and. .not.diag%axes%is_native) then
1496  ! The field is vertically integrated and needs to be re-gridded
1497  if (present(mask)) then
1498  call mom_error(fatal,"post_data_3d: no mask for regridded field.")
1499  endif
1500 
1501  if (id_clock_diag_remap>0) call cpu_clock_begin(id_clock_diag_remap)
1502  allocate(remapped_field(size(field,1), size(field,2), diag%axes%nz))
1503  call vertically_reintegrate_diag_field( &
1504  diag_cs%diag_remap_cs(diag%axes%vertical_coordinate_number), &
1505  diag_cs%G, h_diag, staggered_in_x, staggered_in_y, &
1506  diag%axes%mask3d, diag_cs%missing_value, field, remapped_field)
1507  if (id_clock_diag_remap>0) call cpu_clock_end(id_clock_diag_remap)
1508  if (associated(diag%axes%mask3d)) then
1509  ! Since 3d masks do not vary in the vertical, just use as much as is
1510  ! needed.
1511  call post_data_3d_low(diag, remapped_field, diag_cs, is_static, &
1512  mask=diag%axes%mask3d)
1513  else
1514  call post_data_3d_low(diag, remapped_field, diag_cs, is_static)
1515  endif
1516  if (id_clock_diag_remap>0) call cpu_clock_begin(id_clock_diag_remap)
1517  deallocate(remapped_field)
1518  if (id_clock_diag_remap>0) call cpu_clock_end(id_clock_diag_remap)
1519  elseif (diag%axes%needs_remapping) then
1520  ! Remap this field to another vertical coordinate.
1521  if (present(mask)) then
1522  call mom_error(fatal,"post_data_3d: no mask for regridded field.")
1523  endif
1524 
1525  if (id_clock_diag_remap>0) call cpu_clock_begin(id_clock_diag_remap)
1526  allocate(remapped_field(size(field,1), size(field,2), diag%axes%nz))
1527  call diag_remap_do_remap(diag_cs%diag_remap_cs( &
1528  diag%axes%vertical_coordinate_number), &
1529  diag_cs%G, diag_cs%GV, h_diag, staggered_in_x, staggered_in_y, &
1530  diag%axes%mask3d, diag_cs%missing_value, field, remapped_field)
1531  if (id_clock_diag_remap>0) call cpu_clock_end(id_clock_diag_remap)
1532  if (associated(diag%axes%mask3d)) then
1533  ! Since 3d masks do not vary in the vertical, just use as much as is
1534  ! needed.
1535  call post_data_3d_low(diag, remapped_field, diag_cs, is_static, &
1536  mask=diag%axes%mask3d)
1537  else
1538  call post_data_3d_low(diag, remapped_field, diag_cs, is_static)
1539  endif
1540  if (id_clock_diag_remap>0) call cpu_clock_begin(id_clock_diag_remap)
1541  deallocate(remapped_field)
1542  if (id_clock_diag_remap>0) call cpu_clock_end(id_clock_diag_remap)
1543  elseif (diag%axes%needs_interpolating) then
1544  ! Interpolate this field to another vertical coordinate.
1545  if (present(mask)) then
1546  call mom_error(fatal,"post_data_3d: no mask for regridded field.")
1547  endif
1548 
1549  if (id_clock_diag_remap>0) call cpu_clock_begin(id_clock_diag_remap)
1550  allocate(remapped_field(size(field,1), size(field,2), diag%axes%nz+1))
1551  call vertically_interpolate_diag_field(diag_cs%diag_remap_cs( &
1552  diag%axes%vertical_coordinate_number), &
1553  diag_cs%G, h_diag, staggered_in_x, staggered_in_y, &
1554  diag%axes%mask3d, diag_cs%missing_value, field, remapped_field)
1555  if (id_clock_diag_remap>0) call cpu_clock_end(id_clock_diag_remap)
1556  if (associated(diag%axes%mask3d)) then
1557  ! Since 3d masks do not vary in the vertical, just use as much as is
1558  ! needed.
1559  call post_data_3d_low(diag, remapped_field, diag_cs, is_static, &
1560  mask=diag%axes%mask3d)
1561  else
1562  call post_data_3d_low(diag, remapped_field, diag_cs, is_static)
1563  endif
1564  if (id_clock_diag_remap>0) call cpu_clock_begin(id_clock_diag_remap)
1565  deallocate(remapped_field)
1566  if (id_clock_diag_remap>0) call cpu_clock_end(id_clock_diag_remap)
1567  else
1568  call post_data_3d_low(diag, field, diag_cs, is_static, mask)
1569  endif
1570  diag => diag%next
1571  enddo
1572  if (id_clock_diag_mediator>0) call cpu_clock_end(id_clock_diag_mediator)
1573 

◆ post_data_3d_low()

subroutine mom_diag_mediator::post_data_3d_low ( type(diag_type), intent(in)  diag,
real, dimension(:,:,:), intent(in), target  field,
type(diag_ctrl), intent(in)  diag_cs,
logical, intent(in), optional  is_static,
real, dimension(:,:,:), intent(in), optional, target  mask 
)
private

Make a real 3-d array diagnostic available for averaging or output using a diag_type instead of an integer id.

Parameters
[in]diagA structure describing the diagnostic to post
[in]field3-d array being offered for output or averaging
[in]diag_csStructure used to regulate diagnostic output
[in]is_staticIf true, this is a static field that is always offered.
[in]maskIf present, use this real array as the data mask.

Definition at line 1579 of file MOM_diag_mediator.F90.

1579  type(diag_type), intent(in) :: diag !< A structure describing the diagnostic to post
1580  real, target, intent(in) :: field(:,:,:) !< 3-d array being offered for output or averaging
1581  type(diag_ctrl), intent(in) :: diag_CS !< Structure used to regulate diagnostic output
1582  logical, optional, intent(in) :: is_static !< If true, this is a static field that is always offered.
1583  real, optional,target, intent(in) :: mask(:,:,:) !< If present, use this real array as the data mask.
1584 
1585  ! Local variables
1586  real, dimension(:,:,:), pointer :: locfield
1587  real, dimension(:,:,:), pointer :: locmask
1588  character(len=300) :: mesg
1589  logical :: used ! The return value of send_data is not used for anything.
1590  logical :: staggered_in_x, staggered_in_y
1591  logical :: is_stat
1592  integer :: cszi, cszj, dszi, dszj
1593  integer :: isv, iev, jsv, jev, ks, ke, i, j, k, isv_c, jsv_c, isv_o,jsv_o
1594  integer :: chksum
1595  real, dimension(:,:,:), allocatable, target :: locfield_dsamp
1596  real, dimension(:,:,:), allocatable, target :: locmask_dsamp
1597  integer :: dl
1598 
1599  locfield => null()
1600  locmask => null()
1601  is_stat = .false. ; if (present(is_static)) is_stat = is_static
1602 
1603  ! Determine the proper array indices, noting that because of the (:,:)
1604  ! declaration of field, symmetric arrays are using a SW-grid indexing,
1605  ! but non-symmetric arrays are using a NE-grid indexing. Send_data
1606  ! actually only uses the difference between ie and is to determine
1607  ! the output data size and assumes that halos are symmetric.
1608  isv = diag_cs%is ; iev = diag_cs%ie ; jsv = diag_cs%js ; jev = diag_cs%je
1609 
1610  cszi = (diag_cs%ie-diag_cs%is) +1 ; dszi = (diag_cs%ied-diag_cs%isd) +1
1611  cszj = (diag_cs%je-diag_cs%js) +1 ; dszj = (diag_cs%jed-diag_cs%jsd) +1
1612  if ( size(field,1) == dszi ) then
1613  isv = diag_cs%is ; iev = diag_cs%ie ! Data domain
1614  elseif ( size(field,1) == dszi + 1 ) then
1615  isv = diag_cs%is ; iev = diag_cs%ie+1 ! Symmetric data domain
1616  elseif ( size(field,1) == cszi) then
1617  isv = 1 ; iev = cszi ! Computational domain
1618  elseif ( size(field,1) == cszi + 1 ) then
1619  isv = 1 ; iev = cszi+1 ! Symmetric computational domain
1620  else
1621  write (mesg,*) " peculiar size ",size(field,1)," in i-direction\n"//&
1622  "does not match one of ", cszi, cszi+1, dszi, dszi+1
1623  call mom_error(fatal,"post_data_3d_low: "//trim(diag%debug_str)//trim(mesg))
1624  endif
1625 
1626  if ( size(field,2) == dszj ) then
1627  jsv = diag_cs%js ; jev = diag_cs%je ! Data domain
1628  elseif ( size(field,2) == dszj + 1 ) then
1629  jsv = diag_cs%js ; jev = diag_cs%je+1 ! Symmetric data domain
1630  elseif ( size(field,2) == cszj ) then
1631  jsv = 1 ; jev = cszj ! Computational domain
1632  elseif ( size(field,2) == cszj+1 ) then
1633  jsv = 1 ; jev = cszj+1 ! Symmetric computational domain
1634  else
1635  write (mesg,*) " peculiar size ",size(field,2)," in j-direction\n"//&
1636  "does not match one of ", cszj, cszj+1, dszj, dszj+1
1637  call mom_error(fatal,"post_data_3d_low: "//trim(diag%debug_str)//trim(mesg))
1638  endif
1639 
1640  ks = lbound(field,3) ; ke = ubound(field,3)
1641  if ((diag%conversion_factor /= 0.) .and. (diag%conversion_factor /= 1.)) then
1642  allocate( locfield( lbound(field,1):ubound(field,1), lbound(field,2):ubound(field,2), ks:ke ) )
1643  ! locfield(:,:,:) = 0.0 ! Zeroing out this array would be a good idea, but it appears
1644  ! not to be necessary.
1645  isv_c = isv ; jsv_c = jsv
1646  if (diag%fms_xyave_diag_id>0) then
1647  staggered_in_x = diag%axes%is_u_point .or. diag%axes%is_q_point
1648  staggered_in_y = diag%axes%is_v_point .or. diag%axes%is_q_point
1649  ! When averaging a staggered field, edge points are always required.
1650  if (staggered_in_x) isv_c = iev - (diag_cs%ie - diag_cs%is) - 1
1651  if (staggered_in_y) jsv_c = jev - (diag_cs%je - diag_cs%js) - 1
1652  if (isv_c < lbound(locfield,1)) call mom_error(fatal, &
1653  "It is an error to average a staggered diagnostic field that does not "//&
1654  "have i-direction space to represent the symmetric computational domain.")
1655  if (jsv_c < lbound(locfield,2)) call mom_error(fatal, &
1656  "It is an error to average a staggered diagnostic field that does not "//&
1657  "have j-direction space to represent the symmetric computational domain.")
1658  endif
1659 
1660  do k=ks,ke ; do j=jsv,jev ; do i=isv,iev
1661  if (field(i,j,k) == diag_cs%missing_value) then
1662  locfield(i,j,k) = diag_cs%missing_value
1663  else
1664  locfield(i,j,k) = field(i,j,k) * diag%conversion_factor
1665  endif
1666  enddo ; enddo ; enddo
1667  else
1668  locfield => field
1669  endif
1670 
1671  if (present(mask)) then
1672  locmask => mask
1673  elseif(associated(diag%axes%mask3d)) then
1674  locmask => diag%axes%mask3d
1675  endif
1676 
1677  dl=1
1678  if(.NOT. is_stat) dl = diag%axes%downsample_level !static field downsample i not supported yet
1679  !Downsample the diag field and mask (if present)
1680  if (dl > 1) then
1681  isv_o=isv ; jsv_o=jsv
1682  call downsample_diag_field(locfield, locfield_dsamp, dl, diag_cs, diag,isv,iev,jsv,jev, mask)
1683  if ((diag%conversion_factor /= 0.) .and. (diag%conversion_factor /= 1.)) deallocate( locfield )
1684  locfield => locfield_dsamp
1685  if (present(mask)) then
1686  call downsample_field_3d(locmask, locmask_dsamp, dl, msk, locmask, diag_cs,diag,isv_o,jsv_o,isv,iev,jsv,jev)
1687  locmask => locmask_dsamp
1688  elseif(associated(diag%axes%dsamp(dl)%mask3d)) then
1689  locmask => diag%axes%dsamp(dl)%mask3d
1690  endif
1691  endif
1692 
1693  if (diag%fms_diag_id>0) then
1694  if (diag_cs%diag_as_chksum) then
1695  if (diag%axes%is_h_point) then
1696  call hchksum(locfield, diag%debug_str, diag_cs%G%HI, &
1697  logunit=diag_cs%chksum_iounit)
1698  else if (diag%axes%is_u_point) then
1699  call uchksum(locfield, diag%debug_str, diag_cs%G%HI, &
1700  logunit=diag_cs%chksum_iounit)
1701  else if (diag%axes%is_v_point) then
1702  call vchksum(locfield, diag%debug_str, diag_cs%G%HI, &
1703  logunit=diag_cs%chksum_iounit)
1704  else if (diag%axes%is_q_point) then
1705  call bchksum(locfield, diag%debug_str, diag_cs%G%HI, &
1706  logunit=diag_cs%chksum_iounit)
1707  else
1708  call mom_error(fatal, "post_data_3d_low: unknown axis type.")
1709  endif
1710  else
1711  if (is_stat) then
1712  if (present(mask)) then
1713  call assert(size(locfield) == size(locmask), &
1714  'post_data_3d_low is_stat: mask size mismatch: '//diag%debug_str)
1715  used = send_data(diag%fms_diag_id, locfield, &
1716  is_in=isv, js_in=jsv, ie_in=iev, je_in=jev, rmask=locmask)
1717  !elseif (associated(diag%axes%mask2d)) then
1718  ! used = send_data(diag%fms_diag_id, locfield, &
1719  ! is_in=isv, js_in=jsv, ie_in=iev, je_in=jev, rmask=diag%axes%mask2d)
1720  else
1721  used = send_data(diag%fms_diag_id, locfield, &
1722  is_in=isv, js_in=jsv, ie_in=iev, je_in=jev)
1723  endif
1724  elseif (diag_cs%ave_enabled) then
1725  if (associated(locmask)) then
1726  call assert(size(locfield) == size(locmask), &
1727  'post_data_3d_low: mask size mismatch: '//diag%debug_str)
1728  used = send_data(diag%fms_diag_id, locfield, diag_cs%time_end, &
1729  is_in=isv, js_in=jsv, ie_in=iev, je_in=jev, &
1730  weight=diag_cs%time_int, rmask=locmask)
1731  else
1732  used = send_data(diag%fms_diag_id, locfield, diag_cs%time_end, &
1733  is_in=isv, js_in=jsv, ie_in=iev, je_in=jev, &
1734  weight=diag_cs%time_int)
1735  endif
1736  endif
1737  endif
1738  endif
1739 
1740  if (diag%fms_xyave_diag_id>0) then
1741  call post_xy_average(diag_cs, diag, locfield)
1742  endif
1743 
1744  if ((diag%conversion_factor /= 0.) .and. (diag%conversion_factor /= 1.) .and. dl<2) &
1745  deallocate( locfield )
1746 

◆ post_xy_average()

subroutine mom_diag_mediator::post_xy_average ( type(diag_ctrl), intent(in)  diag_cs,
type(diag_type), intent(in)  diag,
real, dimension(:,:,:), intent(in), target  field 
)
private

Post the horizontally area-averaged diagnostic.

Parameters
[in]diagThis diagnostic
[in]fieldDiagnostic field
[in]diag_csDiagnostics mediator control structure

Definition at line 1751 of file MOM_diag_mediator.F90.

1751  type(diag_type), intent(in) :: diag !< This diagnostic
1752  real, target, intent(in) :: field(:,:,:) !< Diagnostic field
1753  type(diag_ctrl), intent(in) :: diag_cs !< Diagnostics mediator control structure
1754  ! Local variable
1755  real, dimension(size(field,3)) :: averaged_field
1756  logical, dimension(size(field,3)) :: averaged_mask
1757  logical :: staggered_in_x, staggered_in_y, used
1758  integer :: nz, remap_nz, coord
1759 
1760  if (.not. diag_cs%ave_enabled) then
1761  return
1762  endif
1763 
1764  staggered_in_x = diag%axes%is_u_point .or. diag%axes%is_q_point
1765  staggered_in_y = diag%axes%is_v_point .or. diag%axes%is_q_point
1766 
1767  if (diag%axes%is_native) then
1768  call horizontally_average_diag_field(diag_cs%G, diag_cs%h, &
1769  staggered_in_x, staggered_in_y, &
1770  diag%axes%is_layer, diag%v_extensive, &
1771  diag_cs%missing_value, field, &
1772  averaged_field, averaged_mask)
1773  else
1774  nz = size(field, 3)
1775  coord = diag%axes%vertical_coordinate_number
1776  remap_nz = diag_cs%diag_remap_cs(coord)%nz
1777 
1778  call assert(diag_cs%diag_remap_cs(coord)%initialized, &
1779  'post_xy_average: remap_cs not initialized.')
1780 
1781  call assert(implies(diag%axes%is_layer, nz == remap_nz), &
1782  'post_xy_average: layer field dimension mismatch.')
1783  call assert(implies(.not. diag%axes%is_layer, nz == remap_nz+1), &
1784  'post_xy_average: interface field dimension mismatch.')
1785 
1786  call horizontally_average_diag_field(diag_cs%G, diag_cs%diag_remap_cs(coord)%h, &
1787  staggered_in_x, staggered_in_y, &
1788  diag%axes%is_layer, diag%v_extensive, &
1789  diag_cs%missing_value, field, &
1790  averaged_field, averaged_mask)
1791  endif
1792 
1793  if (diag_cs%diag_as_chksum) then
1794  call zchksum(averaged_field, trim(diag%debug_str)//'_xyave', &
1795  logunit=diag_cs%chksum_iounit)
1796  else
1797  used = send_data(diag%fms_xyave_diag_id, averaged_field, diag_cs%time_end, &
1798  weight=diag_cs%time_int, mask=averaged_mask)
1799  endif

◆ query_averaging_enabled()

logical function, public mom_diag_mediator::query_averaging_enabled ( type(diag_ctrl), intent(in)  diag_cs,
real, intent(out), optional  time_int,
type(time_type), intent(out), optional  time_end 
)

Call this subroutine to determine whether the averaging is currently enabled. .true. is returned if it is.

Parameters
[in]diag_csStructure used to regulate diagnostic output
[out]time_intCurrent setting of diagtime_int [s]
[out]time_endCurrent setting of diagtime_end

Definition at line 1830 of file MOM_diag_mediator.F90.

1830  type(diag_ctrl), intent(in) :: diag_CS !< Structure used to regulate diagnostic output
1831  real, optional, intent(out) :: time_int !< Current setting of diag%time_int [s]
1832  type(time_type), optional, intent(out) :: time_end !< Current setting of diag%time_end
1833  logical :: query_averaging_enabled
1834 
1835  if (present(time_int)) time_int = diag_cs%time_int
1836  if (present(time_end)) time_end = diag_cs%time_end
1837  query_averaging_enabled = diag_cs%ave_enabled

◆ register_cell_measure()

subroutine, public mom_diag_mediator::register_cell_measure ( type(ocean_grid_type), intent(in)  G,
type(diag_ctrl), intent(inout), target  diag,
type(time_type), intent(in)  Time 
)

Sets a handle inside diagnostics mediator to associate 3d cell measures.

Parameters
[in]gOcean grid structure
[in,out]diagRegulates diagnostic output
[in]timeModel time

Definition at line 893 of file MOM_diag_mediator.F90.

893  type(ocean_grid_type), intent(in) :: G !< Ocean grid structure
894  type(diag_ctrl), target, intent(inout) :: diag !< Regulates diagnostic output
895  type(time_type), intent(in) :: Time !< Model time
896  ! Local variables
897  integer :: id
898  id = register_diag_field('ocean_model', 'volcello', diag%axesTL, &
899  time, 'Ocean grid-cell volume', 'm3', &
900  standard_name='ocean_volume', v_extensive=.true., &
901  x_cell_method='sum', y_cell_method='sum')
902  call diag_associate_volume_cell_measure(diag, id)
903 

◆ register_diag_field()

integer function, public mom_diag_mediator::register_diag_field ( character(len=*), intent(in)  module_name,
character(len=*), intent(in)  field_name,
type(axes_grp), intent(in), target  axes_in,
type(time_type), intent(in)  init_time,
character(len=*), intent(in), optional  long_name,
character(len=*), intent(in), optional  units,
real, intent(in), optional  missing_value,
real, dimension(2), intent(in), optional  range,
logical, intent(in), optional  mask_variant,
character(len=*), intent(in), optional  standard_name,
logical, intent(in), optional  verbose,
logical, intent(in), optional  do_not_log,
character(len=*), intent(out), optional  err_msg,
character(len=*), intent(in), optional  interp_method,
integer, intent(in), optional  tile_count,
character(len=*), intent(in), optional  cmor_field_name,
character(len=*), intent(in), optional  cmor_long_name,
character(len=*), intent(in), optional  cmor_units,
character(len=*), intent(in), optional  cmor_standard_name,
character(len=*), intent(in), optional  cell_methods,
character(len=*), intent(in), optional  x_cell_method,
character(len=*), intent(in), optional  y_cell_method,
character(len=*), intent(in), optional  v_cell_method,
real, intent(in), optional  conversion,
logical, intent(in), optional  v_extensive 
)

Returns the "diag_mediator" handle for a group (native, CMOR, z-coord, ...) of diagnostics derived from one field.

Parameters
[in]module_nameName of this module, usually "ocean_model" or "ice_shelf_model"
[in]field_nameName of the diagnostic field
[in]axes_inContainer w/ up to 3 integer handles that indicates axes for this field
[in]init_timeTime at which a field is first available?
[in]long_nameLong name of a field.
[in]unitsUnits of a field.
[in]standard_nameStandardized name associated with a field
[in]missing_valueA value that indicates missing values.
[in]rangeValid range of a variable (not used in MOM?)
[in]mask_variantIf true a logical mask must be provided with post_data calls (not used in MOM?)
[in]verboseIf true, FMS is verbose (not used in MOM?)
[in]do_not_logIf true, do not log something (not used in MOM?)
[out]err_msgString into which an error message might be placed (not used in MOM?)
[in]interp_methodIf 'none' indicates the field should not be interpolated as a scalar
[in]tile_countno clue (not used in MOM?)
[in]cmor_field_nameCMOR name of a field
[in]cmor_long_nameCMOR long name of a field
[in]cmor_unitsCMOR units of a field
[in]cmor_standard_nameCMOR standardized name associated with a field
[in]cell_methodsString to append as cell_methods attribute. Use '' to have no attribute. If present, this overrides the default constructed from the default for each individual axis direction.
[in]x_cell_methodSpecifies the cell method for the x-direction. Use '' have no method.
[in]y_cell_methodSpecifies the cell method for the y-direction. Use '' have no method.
[in]v_cell_methodSpecifies the cell method for the vertical direction. Use '' have no method.
[in]conversionA value to multiply data by before writing to file
[in]v_extensiveTrue for vertically extensive fields (vertically integrated). Default/absent for intensive.

Definition at line 1858 of file MOM_diag_mediator.F90.

1858  character(len=*), intent(in) :: module_name !< Name of this module, usually "ocean_model"
1859  !! or "ice_shelf_model"
1860  character(len=*), intent(in) :: field_name !< Name of the diagnostic field
1861  type(axes_grp), target, intent(in) :: axes_in !< Container w/ up to 3 integer handles that
1862  !! indicates axes for this field
1863  type(time_type), intent(in) :: init_time !< Time at which a field is first available?
1864  character(len=*), optional, intent(in) :: long_name !< Long name of a field.
1865  character(len=*), optional, intent(in) :: units !< Units of a field.
1866  character(len=*), optional, intent(in) :: standard_name !< Standardized name associated with a field
1867  real, optional, intent(in) :: missing_value !< A value that indicates missing values.
1868  real, optional, intent(in) :: range(2) !< Valid range of a variable (not used in MOM?)
1869  logical, optional, intent(in) :: mask_variant !< If true a logical mask must be provided with
1870  !! post_data calls (not used in MOM?)
1871  logical, optional, intent(in) :: verbose !< If true, FMS is verbose (not used in MOM?)
1872  logical, optional, intent(in) :: do_not_log !< If true, do not log something (not used in MOM?)
1873  character(len=*), optional, intent(out):: err_msg !< String into which an error message might be
1874  !! placed (not used in MOM?)
1875  character(len=*), optional, intent(in) :: interp_method !< If 'none' indicates the field should not
1876  !! be interpolated as a scalar
1877  integer, optional, intent(in) :: tile_count !< no clue (not used in MOM?)
1878  character(len=*), optional, intent(in) :: cmor_field_name !< CMOR name of a field
1879  character(len=*), optional, intent(in) :: cmor_long_name !< CMOR long name of a field
1880  character(len=*), optional, intent(in) :: cmor_units !< CMOR units of a field
1881  character(len=*), optional, intent(in) :: cmor_standard_name !< CMOR standardized name associated with a field
1882  character(len=*), optional, intent(in) :: cell_methods !< String to append as cell_methods attribute. Use '' to
1883  !! have no attribute. If present, this overrides the
1884  !! default constructed from the default for
1885  !! each individual axis direction.
1886  character(len=*), optional, intent(in) :: x_cell_method !< Specifies the cell method for the x-direction.
1887  !! Use '' have no method.
1888  character(len=*), optional, intent(in) :: y_cell_method !< Specifies the cell method for the y-direction.
1889  !! Use '' have no method.
1890  character(len=*), optional, intent(in) :: v_cell_method !< Specifies the cell method for the vertical direction.
1891  !! Use '' have no method.
1892  real, optional, intent(in) :: conversion !< A value to multiply data by before writing to file
1893  logical, optional, intent(in) :: v_extensive !< True for vertically extensive fields (vertically
1894  !! integrated). Default/absent for intensive.
1895  ! Local variables
1896  real :: MOM_missing_value
1897  type(diag_ctrl), pointer :: diag_cs => null()
1898  type(axes_grp), pointer :: remap_axes => null()
1899  type(axes_grp), pointer :: axes => null()
1900  integer :: dm_id, i, dl
1901  character(len=256) :: new_module_name
1902  logical :: active
1903 
1904  axes => axes_in
1905  mom_missing_value = axes%diag_cs%missing_value
1906  if (present(missing_value)) mom_missing_value = missing_value
1907 
1908  diag_cs => axes%diag_cs
1909  dm_id = -1
1910 
1911  if (axes_in%id == diag_cs%axesTL%id) then
1912  axes => diag_cs%axesTL
1913  elseif (axes_in%id == diag_cs%axesBL%id) then
1914  axes => diag_cs%axesBL
1915  elseif (axes_in%id == diag_cs%axesCuL%id ) then
1916  axes => diag_cs%axesCuL
1917  elseif (axes_in%id == diag_cs%axesCvL%id) then
1918  axes => diag_cs%axesCvL
1919  elseif (axes_in%id == diag_cs%axesTi%id) then
1920  axes => diag_cs%axesTi
1921  elseif (axes_in%id == diag_cs%axesBi%id) then
1922  axes => diag_cs%axesBi
1923  elseif (axes_in%id == diag_cs%axesCui%id ) then
1924  axes => diag_cs%axesCui
1925  elseif (axes_in%id == diag_cs%axesCvi%id) then
1926  axes => diag_cs%axesCvi
1927  endif
1928 
1929  ! Register the native diagnostic
1930  active = register_diag_field_expand_cmor(dm_id, module_name, field_name, axes, &
1931  init_time, long_name=long_name, units=units, missing_value=mom_missing_value, &
1932  range=range, mask_variant=mask_variant, standard_name=standard_name, &
1933  verbose=verbose, do_not_log=do_not_log, err_msg=err_msg, &
1934  interp_method=interp_method, tile_count=tile_count, &
1935  cmor_field_name=cmor_field_name, cmor_long_name=cmor_long_name, &
1936  cmor_units=cmor_units, cmor_standard_name=cmor_standard_name, &
1937  cell_methods=cell_methods, x_cell_method=x_cell_method, &
1938  y_cell_method=y_cell_method, v_cell_method=v_cell_method, &
1939  conversion=conversion, v_extensive=v_extensive)
1940 
1941  ! For each diagnostic coordinate register the diagnostic again under a different module name
1942  do i=1,diag_cs%num_diag_coords
1943  new_module_name = trim(module_name)//'_'//trim(diag_cs%diag_remap_cs(i)%diag_module_suffix)
1944 
1945  ! Register diagnostics remapped to z vertical coordinate
1946  if (axes_in%rank == 3) then
1947  remap_axes => null()
1948  if ((axes_in%id == diag_cs%axesTL%id)) then
1949  remap_axes => diag_cs%remap_axesTL(i)
1950  elseif (axes_in%id == diag_cs%axesBL%id) then
1951  remap_axes => diag_cs%remap_axesBL(i)
1952  elseif (axes_in%id == diag_cs%axesCuL%id ) then
1953  remap_axes => diag_cs%remap_axesCuL(i)
1954  elseif (axes_in%id == diag_cs%axesCvL%id) then
1955  remap_axes => diag_cs%remap_axesCvL(i)
1956  elseif (axes_in%id == diag_cs%axesTi%id) then
1957  remap_axes => diag_cs%remap_axesTi(i)
1958  elseif (axes_in%id == diag_cs%axesBi%id) then
1959  remap_axes => diag_cs%remap_axesBi(i)
1960  elseif (axes_in%id == diag_cs%axesCui%id ) then
1961  remap_axes => diag_cs%remap_axesCui(i)
1962  elseif (axes_in%id == diag_cs%axesCvi%id) then
1963  remap_axes => diag_cs%remap_axesCvi(i)
1964  endif
1965  ! When the MOM_diag_to_Z module has been obsoleted we can assume remap_axes will
1966  ! always exist but in the mean-time we have to do this check:
1967  ! call assert(associated(remap_axes), 'register_diag_field: remap_axes not set')
1968  if (associated(remap_axes)) then
1969  if (remap_axes%needs_remapping .or. remap_axes%needs_interpolating) then
1970  active = register_diag_field_expand_cmor(dm_id, new_module_name, field_name, remap_axes, &
1971  init_time, long_name=long_name, units=units, missing_value=mom_missing_value, &
1972  range=range, mask_variant=mask_variant, standard_name=standard_name, &
1973  verbose=verbose, do_not_log=do_not_log, err_msg=err_msg, &
1974  interp_method=interp_method, tile_count=tile_count, &
1975  cmor_field_name=cmor_field_name, cmor_long_name=cmor_long_name, &
1976  cmor_units=cmor_units, cmor_standard_name=cmor_standard_name, &
1977  cell_methods=cell_methods, x_cell_method=x_cell_method, &
1978  y_cell_method=y_cell_method, v_cell_method=v_cell_method, &
1979  conversion=conversion, v_extensive=v_extensive)
1980  if (active) then
1981  call diag_remap_set_active(diag_cs%diag_remap_cs(i))
1982  endif
1983  endif ! remap_axes%needs_remapping
1984  endif ! associated(remap_axes)
1985  endif ! axes%rank == 3
1986  enddo ! i
1987 
1988  !Register downsampled diagnostics
1989  do dl=2,max_dsamp_lev
1990  ! Do not attempt to checksum the downsampled diagnostics
1991  if (diag_cs%diag_as_chksum) cycle
1992 
1993  new_module_name = trim(module_name)//'_d2'
1994 
1995  if (axes_in%rank == 3 .or. axes_in%rank == 2 ) then
1996  axes => null()
1997  if (axes_in%id == diag_cs%axesTL%id) then
1998  axes => diag_cs%dsamp(dl)%axesTL
1999  elseif (axes_in%id == diag_cs%axesBL%id) then
2000  axes => diag_cs%dsamp(dl)%axesBL
2001  elseif (axes_in%id == diag_cs%axesCuL%id ) then
2002  axes => diag_cs%dsamp(dl)%axesCuL
2003  elseif (axes_in%id == diag_cs%axesCvL%id) then
2004  axes => diag_cs%dsamp(dl)%axesCvL
2005  elseif (axes_in%id == diag_cs%axesTi%id) then
2006  axes => diag_cs%dsamp(dl)%axesTi
2007  elseif (axes_in%id == diag_cs%axesBi%id) then
2008  axes => diag_cs%dsamp(dl)%axesBi
2009  elseif (axes_in%id == diag_cs%axesCui%id ) then
2010  axes => diag_cs%dsamp(dl)%axesCui
2011  elseif (axes_in%id == diag_cs%axesCvi%id) then
2012  axes => diag_cs%dsamp(dl)%axesCvi
2013  elseif (axes_in%id == diag_cs%axesT1%id) then
2014  axes => diag_cs%dsamp(dl)%axesT1
2015  elseif (axes_in%id == diag_cs%axesB1%id) then
2016  axes => diag_cs%dsamp(dl)%axesB1
2017  elseif (axes_in%id == diag_cs%axesCu1%id ) then
2018  axes => diag_cs%dsamp(dl)%axesCu1
2019  elseif (axes_in%id == diag_cs%axesCv1%id) then
2020  axes => diag_cs%dsamp(dl)%axesCv1
2021  else
2022  !Niki: Should we worry about these, e.g., diag_to_Z_CS?
2023  call mom_error(warning,"register_diag_field: Could not find a proper axes for " &
2024  //trim( new_module_name)//"-"//trim(field_name))
2025  endif
2026  endif
2027  ! Register the native diagnostic
2028  if (associated(axes)) then
2029  active = register_diag_field_expand_cmor(dm_id, new_module_name, field_name, axes, &
2030  init_time, long_name=long_name, units=units, missing_value=mom_missing_value, &
2031  range=range, mask_variant=mask_variant, standard_name=standard_name, &
2032  verbose=verbose, do_not_log=do_not_log, err_msg=err_msg, &
2033  interp_method=interp_method, tile_count=tile_count, &
2034  cmor_field_name=cmor_field_name, cmor_long_name=cmor_long_name, &
2035  cmor_units=cmor_units, cmor_standard_name=cmor_standard_name, &
2036  cell_methods=cell_methods, x_cell_method=x_cell_method, &
2037  y_cell_method=y_cell_method, v_cell_method=v_cell_method, &
2038  conversion=conversion, v_extensive=v_extensive)
2039  endif
2040 
2041  ! For each diagnostic coordinate register the diagnostic again under a different module name
2042  do i=1,diag_cs%num_diag_coords
2043  new_module_name = trim(module_name)//'_'//trim(diag_cs%diag_remap_cs(i)%diag_module_suffix)//'_d2'
2044 
2045  ! Register diagnostics remapped to z vertical coordinate
2046  if (axes_in%rank == 3) then
2047  remap_axes => null()
2048  if ((axes_in%id == diag_cs%axesTL%id)) then
2049  remap_axes => diag_cs%dsamp(dl)%remap_axesTL(i)
2050  elseif (axes_in%id == diag_cs%axesBL%id) then
2051  remap_axes => diag_cs%dsamp(dl)%remap_axesBL(i)
2052  elseif (axes_in%id == diag_cs%axesCuL%id ) then
2053  remap_axes => diag_cs%dsamp(dl)%remap_axesCuL(i)
2054  elseif (axes_in%id == diag_cs%axesCvL%id) then
2055  remap_axes => diag_cs%dsamp(dl)%remap_axesCvL(i)
2056  elseif (axes_in%id == diag_cs%axesTi%id) then
2057  remap_axes => diag_cs%dsamp(dl)%remap_axesTi(i)
2058  elseif (axes_in%id == diag_cs%axesBi%id) then
2059  remap_axes => diag_cs%dsamp(dl)%remap_axesBi(i)
2060  elseif (axes_in%id == diag_cs%axesCui%id ) then
2061  remap_axes => diag_cs%dsamp(dl)%remap_axesCui(i)
2062  elseif (axes_in%id == diag_cs%axesCvi%id) then
2063  remap_axes => diag_cs%dsamp(dl)%remap_axesCvi(i)
2064  endif
2065 
2066  ! When the MOM_diag_to_Z module has been obsoleted we can assume remap_axes will
2067  ! always exist but in the mean-time we have to do this check:
2068  ! call assert(associated(remap_axes), 'register_diag_field: remap_axes not set')
2069  if (associated(remap_axes)) then
2070  if (remap_axes%needs_remapping .or. remap_axes%needs_interpolating) then
2071  active = register_diag_field_expand_cmor(dm_id, new_module_name, field_name, remap_axes, &
2072  init_time, long_name=long_name, units=units, missing_value=mom_missing_value, &
2073  range=range, mask_variant=mask_variant, standard_name=standard_name, &
2074  verbose=verbose, do_not_log=do_not_log, err_msg=err_msg, &
2075  interp_method=interp_method, tile_count=tile_count, &
2076  cmor_field_name=cmor_field_name, cmor_long_name=cmor_long_name, &
2077  cmor_units=cmor_units, cmor_standard_name=cmor_standard_name, &
2078  cell_methods=cell_methods, x_cell_method=x_cell_method, &
2079  y_cell_method=y_cell_method, v_cell_method=v_cell_method, &
2080  conversion=conversion, v_extensive=v_extensive)
2081  if (active) then
2082  call diag_remap_set_active(diag_cs%diag_remap_cs(i))
2083  endif
2084  endif ! remap_axes%needs_remapping
2085  endif ! associated(remap_axes)
2086  endif ! axes%rank == 3
2087  enddo ! i
2088  enddo
2089 
2090  register_diag_field = dm_id
2091 

◆ register_diag_field_expand_axes()

integer function mom_diag_mediator::register_diag_field_expand_axes ( character(len=*), intent(in)  module_name,
character(len=*), intent(in)  field_name,
type(axes_grp), intent(in), target  axes,
type(time_type), intent(in)  init_time,
character(len=*), intent(in), optional  long_name,
character(len=*), intent(in), optional  units,
real, intent(in), optional  missing_value,
real, dimension(2), intent(in), optional  range,
logical, intent(in), optional  mask_variant,
character(len=*), intent(in), optional  standard_name,
logical, intent(in), optional  verbose,
logical, intent(in), optional  do_not_log,
character(len=*), intent(out), optional  err_msg,
character(len=*), intent(in), optional  interp_method,
integer, intent(in), optional  tile_count 
)
private

Returns an FMS id from register_diag_field_fms (the diag_manager routine) after expanding axes (axes-group) into handles and conditionally adding an FMS area_id for cell_measures.

Parameters
[in]module_nameName of this module, usually "ocean_model" or "ice_shelf_model"
[in]field_nameName of the diagnostic field
[in]axesContainer w/ up to 3 integer handles that indicates axes for this field
[in]init_timeTime at which a field is first available?
[in]long_nameLong name of a field.
[in]unitsUnits of a field.
[in]standard_nameStandardized name associated with a field
[in]missing_valueA value that indicates missing values.
[in]rangeValid range of a variable (not used in MOM?)
[in]mask_variantIf true a logical mask must be provided with post_data calls (not used in MOM?)
[in]verboseIf true, FMS is verbose (not used in MOM?)
[in]do_not_logIf true, do not log something (not used in MOM?)
[out]err_msgString into which an error message might be placed (not used in MOM?)
[in]interp_methodIf 'none' indicates the field should not be interpolated as a scalar
[in]tile_countno clue (not used in MOM?)

Definition at line 2266 of file MOM_diag_mediator.F90.

2266  character(len=*), intent(in) :: module_name !< Name of this module, usually "ocean_model"
2267  !! or "ice_shelf_model"
2268  character(len=*), intent(in) :: field_name !< Name of the diagnostic field
2269  type(axes_grp), target, intent(in) :: axes !< Container w/ up to 3 integer handles that indicates
2270  !! axes for this field
2271  type(time_type), intent(in) :: init_time !< Time at which a field is first available?
2272  character(len=*), optional, intent(in) :: long_name !< Long name of a field.
2273  character(len=*), optional, intent(in) :: units !< Units of a field.
2274  character(len=*), optional, intent(in) :: standard_name !< Standardized name associated with a field
2275  real, optional, intent(in) :: missing_value !< A value that indicates missing values.
2276  real, optional, intent(in) :: range(2) !< Valid range of a variable (not used in MOM?)
2277  logical, optional, intent(in) :: mask_variant !< If true a logical mask must be provided
2278  !! with post_data calls (not used in MOM?)
2279  logical, optional, intent(in) :: verbose !< If true, FMS is verbose (not used in MOM?)
2280  logical, optional, intent(in) :: do_not_log !< If true, do not log something
2281  !! (not used in MOM?)
2282  character(len=*), optional, intent(out):: err_msg !< String into which an error message might be
2283  !! placed (not used in MOM?)
2284  character(len=*), optional, intent(in) :: interp_method !< If 'none' indicates the field should
2285  !! not be interpolated as a scalar
2286  integer, optional, intent(in) :: tile_count !< no clue (not used in MOM?)
2287  ! Local variables
2288  integer :: fms_id, area_id, volume_id
2289 
2290  ! This gets the cell area associated with the grid location of this variable
2291  area_id = axes%id_area
2292  volume_id = axes%id_volume
2293 
2294  ! Get the FMS diagnostic id
2295  if (axes%diag_cs%diag_as_chksum) then
2296  fms_id = axes%diag_cs%num_chksum_diags + 1
2297  axes%diag_cs%num_chksum_diags = fms_id
2298  else if (present(interp_method) .or. axes%is_h_point) then
2299  ! If interp_method is provided we must use it
2300  if (area_id>0) then
2301  if (volume_id>0) then
2302  fms_id = register_diag_field_fms(module_name, field_name, axes%handles, &
2303  init_time, long_name=long_name, units=units, missing_value=missing_value, &
2304  range=range, mask_variant=mask_variant, standard_name=standard_name, &
2305  verbose=verbose, do_not_log=do_not_log, err_msg=err_msg, &
2306  interp_method=interp_method, tile_count=tile_count, area=area_id, volume=volume_id)
2307  else
2308  fms_id = register_diag_field_fms(module_name, field_name, axes%handles, &
2309  init_time, long_name=long_name, units=units, missing_value=missing_value, &
2310  range=range, mask_variant=mask_variant, standard_name=standard_name, &
2311  verbose=verbose, do_not_log=do_not_log, err_msg=err_msg, &
2312  interp_method=interp_method, tile_count=tile_count, area=area_id)
2313  endif
2314  else
2315  if (volume_id>0) then
2316  fms_id = register_diag_field_fms(module_name, field_name, axes%handles, &
2317  init_time, long_name=long_name, units=units, missing_value=missing_value, &
2318  range=range, mask_variant=mask_variant, standard_name=standard_name, &
2319  verbose=verbose, do_not_log=do_not_log, err_msg=err_msg, &
2320  interp_method=interp_method, tile_count=tile_count, volume=volume_id)
2321  else
2322  fms_id = register_diag_field_fms(module_name, field_name, axes%handles, &
2323  init_time, long_name=long_name, units=units, missing_value=missing_value, &
2324  range=range, mask_variant=mask_variant, standard_name=standard_name, &
2325  verbose=verbose, do_not_log=do_not_log, err_msg=err_msg, &
2326  interp_method=interp_method, tile_count=tile_count)
2327  endif
2328  endif
2329  else
2330  ! If interp_method is not provided and the field is not at an h-point then interp_method='none'
2331  if (area_id>0) then
2332  if (volume_id>0) then
2333  fms_id = register_diag_field_fms(module_name, field_name, axes%handles, &
2334  init_time, long_name=long_name, units=units, missing_value=missing_value, &
2335  range=range, mask_variant=mask_variant, standard_name=standard_name, &
2336  verbose=verbose, do_not_log=do_not_log, err_msg=err_msg, &
2337  interp_method='none', tile_count=tile_count, area=area_id, volume=volume_id)
2338  else
2339  fms_id = register_diag_field_fms(module_name, field_name, axes%handles, &
2340  init_time, long_name=long_name, units=units, missing_value=missing_value, &
2341  range=range, mask_variant=mask_variant, standard_name=standard_name, &
2342  verbose=verbose, do_not_log=do_not_log, err_msg=err_msg, &
2343  interp_method='none', tile_count=tile_count, area=area_id)
2344  endif
2345  else
2346  if (volume_id>0) then
2347  fms_id = register_diag_field_fms(module_name, field_name, axes%handles, &
2348  init_time, long_name=long_name, units=units, missing_value=missing_value, &
2349  range=range, mask_variant=mask_variant, standard_name=standard_name, &
2350  verbose=verbose, do_not_log=do_not_log, err_msg=err_msg, &
2351  interp_method='none', tile_count=tile_count, volume=volume_id)
2352  else
2353  fms_id = register_diag_field_fms(module_name, field_name, axes%handles, &
2354  init_time, long_name=long_name, units=units, missing_value=missing_value, &
2355  range=range, mask_variant=mask_variant, standard_name=standard_name, &
2356  verbose=verbose, do_not_log=do_not_log, err_msg=err_msg, &
2357  interp_method='none', tile_count=tile_count)
2358  endif
2359  endif
2360  endif
2361 
2362  register_diag_field_expand_axes = fms_id
2363 

◆ register_diag_field_expand_cmor()

logical function mom_diag_mediator::register_diag_field_expand_cmor ( integer, intent(inout)  dm_id,
character(len=*), intent(in)  module_name,
character(len=*), intent(in)  field_name,
type(axes_grp), intent(in), target  axes,
type(time_type), intent(in)  init_time,
character(len=*), intent(in), optional  long_name,
character(len=*), intent(in), optional  units,
real, intent(in), optional  missing_value,
real, dimension(2), intent(in), optional  range,
logical, intent(in), optional  mask_variant,
character(len=*), intent(in), optional  standard_name,
logical, intent(in), optional  verbose,
logical, intent(in), optional  do_not_log,
character(len=*), intent(out), optional  err_msg,
character(len=*), intent(in), optional  interp_method,
integer, intent(in), optional  tile_count,
character(len=*), intent(in), optional  cmor_field_name,
character(len=*), intent(in), optional  cmor_long_name,
character(len=*), intent(in), optional  cmor_units,
character(len=*), intent(in), optional  cmor_standard_name,
character(len=*), intent(in), optional  cell_methods,
character(len=*), intent(in), optional  x_cell_method,
character(len=*), intent(in), optional  y_cell_method,
character(len=*), intent(in), optional  v_cell_method,
real, intent(in), optional  conversion,
logical, intent(in), optional  v_extensive 
)
private

Returns True if either the native or CMOr version of the diagnostic were registered. Updates 'dm_id' after calling register_diag_field_expand_axes() for both native and CMOR variants of the field.

Parameters
[in,out]dm_idThe diag_mediator ID for this diagnostic group
[in]module_nameName of this module, usually "ocean_model" or "ice_shelf_model"
[in]field_nameName of the diagnostic field
[in]axesContainer w/ up to 3 integer handles that indicates axes for this field
[in]init_timeTime at which a field is first available?
[in]long_nameLong name of a field.
[in]unitsUnits of a field.
[in]standard_nameStandardized name associated with a field
[in]missing_valueA value that indicates missing values.
[in]rangeValid range of a variable (not used in MOM?)
[in]mask_variantIf true a logical mask must be provided with post_data calls (not used in MOM?)
[in]verboseIf true, FMS is verbose (not used in MOM?)
[in]do_not_logIf true, do not log something (not used in MOM?)
[out]err_msgString into which an error message might be placed (not used in MOM?)
[in]interp_methodIf 'none' indicates the field should not be interpolated as a scalar
[in]tile_countno clue (not used in MOM?)
[in]cmor_field_nameCMOR name of a field
[in]cmor_long_nameCMOR long name of a field
[in]cmor_unitsCMOR units of a field
[in]cmor_standard_nameCMOR standardized name associated with a field
[in]cell_methodsString to append as cell_methods attribute. Use '' to have no attribute. If present, this overrides the default constructed from the default for each individual axis direction.
[in]x_cell_methodSpecifies the cell method for the x-direction. Use '' have no method.
[in]y_cell_methodSpecifies the cell method for the y-direction. Use '' have no method.
[in]v_cell_methodSpecifies the cell method for the vertical direction. Use '' have no method.
[in]conversionA value to multiply data by before writing to file
[in]v_extensiveTrue for vertically extensive fields (vertically integrated). Default/absent for intensive.

Definition at line 2101 of file MOM_diag_mediator.F90.

2101  integer, intent(inout) :: dm_id !< The diag_mediator ID for this diagnostic group
2102  character(len=*), intent(in) :: module_name !< Name of this module, usually "ocean_model" or "ice_shelf_model"
2103  character(len=*), intent(in) :: field_name !< Name of the diagnostic field
2104  type(axes_grp), target, intent(in) :: axes !< Container w/ up to 3 integer handles that indicates axes
2105  !! for this field
2106  type(time_type), intent(in) :: init_time !< Time at which a field is first available?
2107  character(len=*), optional, intent(in) :: long_name !< Long name of a field.
2108  character(len=*), optional, intent(in) :: units !< Units of a field.
2109  character(len=*), optional, intent(in) :: standard_name !< Standardized name associated with a field
2110  real, optional, intent(in) :: missing_value !< A value that indicates missing values.
2111  real, optional, intent(in) :: range(2) !< Valid range of a variable (not used in MOM?)
2112  logical, optional, intent(in) :: mask_variant !< If true a logical mask must be provided
2113  !! with post_data calls (not used in MOM?)
2114  logical, optional, intent(in) :: verbose !< If true, FMS is verbose (not used in MOM?)
2115  logical, optional, intent(in) :: do_not_log !< If true, do not log something (not used in MOM?)
2116  character(len=*), optional, intent(out):: err_msg !< String into which an error message might be
2117  !! placed (not used in MOM?)
2118  character(len=*), optional, intent(in) :: interp_method !< If 'none' indicates the field should
2119  !! not be interpolated as a scalar
2120  integer, optional, intent(in) :: tile_count !< no clue (not used in MOM?)
2121  character(len=*), optional, intent(in) :: cmor_field_name !< CMOR name of a field
2122  character(len=*), optional, intent(in) :: cmor_long_name !< CMOR long name of a field
2123  character(len=*), optional, intent(in) :: cmor_units !< CMOR units of a field
2124  character(len=*), optional, intent(in) :: cmor_standard_name !< CMOR standardized name associated with a field
2125  character(len=*), optional, intent(in) :: cell_methods !< String to append as cell_methods attribute.
2126  !! Use '' to have no attribute. If present, this
2127  !! overrides the default constructed from the default
2128  !! for each individual axis direction.
2129  character(len=*), optional, intent(in) :: x_cell_method !< Specifies the cell method for the x-direction.
2130  !! Use '' have no method.
2131  character(len=*), optional, intent(in) :: y_cell_method !< Specifies the cell method for the y-direction.
2132  !! Use '' have no method.
2133  character(len=*), optional, intent(in) :: v_cell_method !< Specifies the cell method for the vertical direction.
2134  !! Use '' have no method.
2135  real, optional, intent(in) :: conversion !< A value to multiply data by before writing to file
2136  logical, optional, intent(in) :: v_extensive !< True for vertically extensive fields (vertically
2137  !! integrated). Default/absent for intensive.
2138  ! Local variables
2139  real :: MOM_missing_value
2140  type(diag_ctrl), pointer :: diag_cs => null()
2141  type(diag_type), pointer :: this_diag => null()
2142  integer :: fms_id, fms_xyave_id
2143  character(len=256) :: posted_cmor_units, posted_cmor_standard_name, posted_cmor_long_name, cm_string, msg
2144 
2145  mom_missing_value = axes%diag_cs%missing_value
2146  if (present(missing_value)) mom_missing_value = missing_value
2147 
2148  register_diag_field_expand_cmor = .false.
2149  diag_cs => axes%diag_cs
2150 
2151  ! Set up the 'primary' diagnostic, first get an underlying FMS id
2152  fms_id = register_diag_field_expand_axes(module_name, field_name, axes, init_time, &
2153  long_name=long_name, units=units, missing_value=mom_missing_value, &
2154  range=range, mask_variant=mask_variant, standard_name=standard_name, &
2155  verbose=verbose, do_not_log=do_not_log, err_msg=err_msg, &
2156  interp_method=interp_method, tile_count=tile_count)
2157  if (.not. diag_cs%diag_as_chksum) &
2158  call attach_cell_methods(fms_id, axes, cm_string, cell_methods, &
2159  x_cell_method, y_cell_method, v_cell_method, &
2160  v_extensive=v_extensive)
2161  if (is_root_pe() .and. diag_cs%available_diag_doc_unit > 0) then
2162  msg = ''
2163  if (present(cmor_field_name)) msg = 'CMOR equivalent is "'//trim(cmor_field_name)//'"'
2164  call log_available_diag(fms_id>0, module_name, field_name, cm_string, &
2165  msg, diag_cs, long_name, units, standard_name)
2166  endif
2167  ! Associated horizontally area-averaged diagnostic
2168  fms_xyave_id = diag_field_not_found
2169  if (associated(axes%xyave_axes)) then
2170  fms_xyave_id = register_diag_field_expand_axes(module_name, trim(field_name)//'_xyave', &
2171  axes%xyave_axes, init_time, &
2172  long_name=long_name, units=units, missing_value=mom_missing_value, &
2173  range=range, mask_variant=mask_variant, standard_name=standard_name, &
2174  verbose=verbose, do_not_log=do_not_log, err_msg=err_msg, &
2175  interp_method=interp_method, tile_count=tile_count)
2176  if (.not. diag_cs%diag_as_chksum) &
2177  call attach_cell_methods(fms_xyave_id, axes%xyave_axes, cm_string, &
2178  cell_methods, v_cell_method, v_extensive=v_extensive)
2179  if (is_root_pe() .and. diag_cs%available_diag_doc_unit > 0) then
2180  msg = ''
2181  if (present(cmor_field_name)) msg = 'CMOR equivalent is "'//trim(cmor_field_name)//'_xyave"'
2182  call log_available_diag(fms_xyave_id>0, module_name, trim(field_name)//'_xyave', cm_string, &
2183  msg, diag_cs, long_name, units, standard_name)
2184  endif
2185  endif
2186  this_diag => null()
2187  if (fms_id /= diag_field_not_found .or. fms_xyave_id /= diag_field_not_found) then
2188  call add_diag_to_list(diag_cs, dm_id, fms_id, this_diag, axes, module_name, field_name, msg)
2189  this_diag%fms_xyave_diag_id = fms_xyave_id
2190  !Encode and save the cell methods for this diag
2191  call add_xyz_method(this_diag, axes, x_cell_method, y_cell_method, v_cell_method, v_extensive)
2192  if (present(v_extensive)) this_diag%v_extensive = v_extensive
2193  if (present(conversion)) this_diag%conversion_factor = conversion
2194  register_diag_field_expand_cmor = .true.
2195  endif
2196 
2197  ! For the CMOR variation of the above diagnostic
2198  if (present(cmor_field_name) .and. .not. diag_cs%diag_as_chksum) then
2199  ! Fallback values for strings set to "NULL"
2200  posted_cmor_units = "not provided" !
2201  posted_cmor_standard_name = "not provided" ! Values might be able to be replaced with a CS%missing field?
2202  posted_cmor_long_name = "not provided" !
2203 
2204  ! If attributes are present for MOM variable names, use them first for the register_diag_field
2205  ! call for CMOR verison of the variable
2206  if (present(units)) posted_cmor_units = units
2207  if (present(standard_name)) posted_cmor_standard_name = standard_name
2208  if (present(long_name)) posted_cmor_long_name = long_name
2209 
2210  ! If specified in the call to register_diag_field, override attributes with the CMOR versions
2211  if (present(cmor_units)) posted_cmor_units = cmor_units
2212  if (present(cmor_standard_name)) posted_cmor_standard_name = cmor_standard_name
2213  if (present(cmor_long_name)) posted_cmor_long_name = cmor_long_name
2214 
2215  fms_id = register_diag_field_expand_axes(module_name, cmor_field_name, axes, init_time, &
2216  long_name=trim(posted_cmor_long_name), units=trim(posted_cmor_units), &
2217  missing_value=mom_missing_value, range=range, mask_variant=mask_variant, &
2218  standard_name=trim(posted_cmor_standard_name), verbose=verbose, do_not_log=do_not_log, &
2219  err_msg=err_msg, interp_method=interp_method, tile_count=tile_count)
2220  call attach_cell_methods(fms_id, axes, cm_string, &
2221  cell_methods, x_cell_method, y_cell_method, v_cell_method, &
2222  v_extensive=v_extensive)
2223  if (is_root_pe() .and. diag_cs%available_diag_doc_unit > 0) then
2224  msg = 'native name is "'//trim(field_name)//'"'
2225  call log_available_diag(fms_id>0, module_name, cmor_field_name, cm_string, &
2226  msg, diag_cs, posted_cmor_long_name, posted_cmor_units, &
2227  posted_cmor_standard_name)
2228  endif
2229  ! Associated horizontally area-averaged diagnostic
2230  fms_xyave_id = diag_field_not_found
2231  if (associated(axes%xyave_axes)) then
2232  fms_xyave_id = register_diag_field_expand_axes(module_name, trim(cmor_field_name)//'_xyave', &
2233  axes%xyave_axes, init_time, &
2234  long_name=trim(posted_cmor_long_name), units=trim(posted_cmor_units), &
2235  missing_value=mom_missing_value, range=range, mask_variant=mask_variant, &
2236  standard_name=trim(posted_cmor_standard_name), verbose=verbose, do_not_log=do_not_log, &
2237  err_msg=err_msg, interp_method=interp_method, tile_count=tile_count)
2238  call attach_cell_methods(fms_xyave_id, axes%xyave_axes, cm_string, &
2239  cell_methods, v_cell_method, v_extensive=v_extensive)
2240  if (is_root_pe() .and. diag_cs%available_diag_doc_unit > 0) then
2241  msg = 'native name is "'//trim(field_name)//'_xyave"'
2242  call log_available_diag(fms_xyave_id>0, module_name, trim(cmor_field_name)//'_xyave', &
2243  cm_string, msg, diag_cs, posted_cmor_long_name, posted_cmor_units, &
2244  posted_cmor_standard_name)
2245  endif
2246  endif
2247  this_diag => null()
2248  if (fms_id /= diag_field_not_found .or. fms_xyave_id /= diag_field_not_found) then
2249  call add_diag_to_list(diag_cs, dm_id, fms_id, this_diag, axes, module_name, field_name, msg)
2250  this_diag%fms_xyave_diag_id = fms_xyave_id
2251  !Encode and save the cell methods for this diag
2252  call add_xyz_method(this_diag, axes, x_cell_method, y_cell_method, v_cell_method, v_extensive)
2253  if (present(v_extensive)) this_diag%v_extensive = v_extensive
2254  if (present(conversion)) this_diag%conversion_factor = conversion
2255  register_diag_field_expand_cmor = .true.
2256  endif
2257  endif
2258 

◆ register_scalar_field()

integer function, public mom_diag_mediator::register_scalar_field ( character(len=*), intent(in)  module_name,
character(len=*), intent(in)  field_name,
type(time_type), intent(in)  init_time,
type(diag_ctrl), intent(inout)  diag_cs,
character(len=*), intent(in), optional  long_name,
character(len=*), intent(in), optional  units,
real, intent(in), optional  missing_value,
real, dimension(2), intent(in), optional  range,
character(len=*), intent(in), optional  standard_name,
logical, intent(in), optional  do_not_log,
character(len=*), intent(out), optional  err_msg,
character(len=*), intent(in), optional  interp_method,
character(len=*), intent(in), optional  cmor_field_name,
character(len=*), intent(in), optional  cmor_long_name,
character(len=*), intent(in), optional  cmor_units,
character(len=*), intent(in), optional  cmor_standard_name 
)
Returns
An integer handle for a diagnostic array.
Parameters
[in]module_nameName of this module, usually "ocean_model" or "ice_shelf_model"
[in]field_nameName of the diagnostic field
[in]init_timeTime at which a field is first available?
[in,out]diag_csStructure used to regulate diagnostic output
[in]long_nameLong name of a field.
[in]unitsUnits of a field.
[in]standard_nameStandardized name associated with a field
[in]missing_valueA value that indicates missing values.
[in]rangeValid range of a variable (not used in MOM?)
[in]do_not_logIf true, do not log something (not used in MOM?)
[out]err_msgString into which an error message might be placed (not used in MOM?)
[in]interp_methodIf 'none' indicates the field should not be interpolated as a scalar
[in]cmor_field_nameCMOR name of a field
[in]cmor_long_nameCMOR long name of a field
[in]cmor_unitsCMOR units of a field
[in]cmor_standard_nameCMOR standardized name associated with a field

Definition at line 2576 of file MOM_diag_mediator.F90.

2576  integer :: register_scalar_field !< An integer handle for a diagnostic array.
2577  character(len=*), intent(in) :: module_name !< Name of this module, usually "ocean_model"
2578  !! or "ice_shelf_model"
2579  character(len=*), intent(in) :: field_name !< Name of the diagnostic field
2580  type(time_type), intent(in) :: init_time !< Time at which a field is first available?
2581  type(diag_ctrl), intent(inout) :: diag_CS !< Structure used to regulate diagnostic output
2582  character(len=*), optional, intent(in) :: long_name !< Long name of a field.
2583  character(len=*), optional, intent(in) :: units !< Units of a field.
2584  character(len=*), optional, intent(in) :: standard_name !< Standardized name associated with a field
2585  real, optional, intent(in) :: missing_value !< A value that indicates missing values.
2586  real, optional, intent(in) :: range(2) !< Valid range of a variable (not used in MOM?)
2587  logical, optional, intent(in) :: do_not_log !< If true, do not log something (not used in MOM?)
2588  character(len=*), optional, intent(out):: err_msg !< String into which an error message might be
2589  !! placed (not used in MOM?)
2590  character(len=*), optional, intent(in) :: interp_method !< If 'none' indicates the field should not
2591  !! be interpolated as a scalar
2592  character(len=*), optional, intent(in) :: cmor_field_name !< CMOR name of a field
2593  character(len=*), optional, intent(in) :: cmor_long_name !< CMOR long name of a field
2594  character(len=*), optional, intent(in) :: cmor_units !< CMOR units of a field
2595  character(len=*), optional, intent(in) :: cmor_standard_name !< CMOR standardized name associated with a field
2596 
2597  ! Local variables
2598  real :: MOM_missing_value
2599  integer :: dm_id, fms_id
2600  type(diag_type), pointer :: diag => null(), cmor_diag => null()
2601  character(len=256) :: posted_cmor_units, posted_cmor_standard_name, posted_cmor_long_name
2602 
2603  mom_missing_value = diag_cs%missing_value
2604  if (present(missing_value)) mom_missing_value = missing_value
2605 
2606  dm_id = -1
2607  diag => null()
2608  cmor_diag => null()
2609 
2610  if (diag_cs%diag_as_chksum) then
2611  fms_id = diag_cs%num_chksum_diags + 1
2612  diag_cs%num_chksum_diags = fms_id
2613  else
2614  fms_id = register_diag_field_fms(module_name, field_name, init_time, &
2615  long_name=long_name, units=units, missing_value=mom_missing_value, &
2616  range=range, standard_name=standard_name, do_not_log=do_not_log, &
2617  err_msg=err_msg)
2618  endif
2619 
2620  if (fms_id /= diag_field_not_found) then
2621  dm_id = get_new_diag_id(diag_cs)
2622  call alloc_diag_with_id(dm_id, diag_cs, diag)
2623  call assert(associated(diag), 'register_scalar_field: diag allocation failed')
2624  diag%fms_diag_id = fms_id
2625  diag%debug_str = trim(module_name)//"-"//trim(field_name)
2626  endif
2627 
2628  if (present(cmor_field_name)) then
2629  ! Fallback values for strings set to "not provided"
2630  posted_cmor_units = "not provided"
2631  posted_cmor_standard_name = "not provided"
2632  posted_cmor_long_name = "not provided"
2633 
2634  ! If attributes are present for MOM variable names, use them first for the register_static_field
2635  ! call for CMOR verison of the variable
2636  if (present(units)) posted_cmor_units = units
2637  if (present(standard_name)) posted_cmor_standard_name = standard_name
2638  if (present(long_name)) posted_cmor_long_name = long_name
2639 
2640  ! If specified in the call to register_static_field, override attributes with the CMOR versions
2641  if (present(cmor_units)) posted_cmor_units = cmor_units
2642  if (present(cmor_standard_name)) posted_cmor_standard_name = cmor_standard_name
2643  if (present(cmor_long_name)) posted_cmor_long_name = cmor_long_name
2644 
2645  fms_id = register_diag_field_fms(module_name, cmor_field_name, init_time, &
2646  long_name=trim(posted_cmor_long_name), units=trim(posted_cmor_units), &
2647  missing_value=mom_missing_value, range=range, &
2648  standard_name=trim(posted_cmor_standard_name), do_not_log=do_not_log, err_msg=err_msg)
2649  if (fms_id /= diag_field_not_found) then
2650  if (dm_id == -1) then
2651  dm_id = get_new_diag_id(diag_cs)
2652  endif
2653  call alloc_diag_with_id(dm_id, diag_cs, cmor_diag)
2654  cmor_diag%fms_diag_id = fms_id
2655  cmor_diag%debug_str = trim(module_name)//"-"//trim(cmor_field_name)
2656  endif
2657  endif
2658 
2659  ! Document diagnostics in list of available diagnostics
2660  if (is_root_pe() .and. diag_cs%available_diag_doc_unit > 0) then
2661  call log_available_diag(associated(diag), module_name, field_name, '', '', diag_cs, &
2662  long_name, units, standard_name)
2663  if (present(cmor_field_name)) then
2664  call log_available_diag(associated(cmor_diag), module_name, cmor_field_name, &
2665  '', '', diag_cs, posted_cmor_long_name, posted_cmor_units, &
2666  posted_cmor_standard_name)
2667  endif
2668  endif
2669 
2670  register_scalar_field = dm_id
2671 

◆ register_static_field()

integer function, public mom_diag_mediator::register_static_field ( character(len=*), intent(in)  module_name,
character(len=*), intent(in)  field_name,
type(axes_grp), intent(in), target  axes,
character(len=*), intent(in), optional  long_name,
character(len=*), intent(in), optional  units,
real, intent(in), optional  missing_value,
real, dimension(2), intent(in), optional  range,
logical, intent(in), optional  mask_variant,
character(len=*), intent(in), optional  standard_name,
logical, intent(in), optional  do_not_log,
character(len=*), intent(in), optional  interp_method,
integer, intent(in), optional  tile_count,
character(len=*), intent(in), optional  cmor_field_name,
character(len=*), intent(in), optional  cmor_long_name,
character(len=*), intent(in), optional  cmor_units,
character(len=*), intent(in), optional  cmor_standard_name,
integer, intent(in), optional  area,
character(len=*), intent(in), optional  x_cell_method,
character(len=*), intent(in), optional  y_cell_method,
character(len=*), intent(in), optional  area_cell_method,
real, intent(in), optional  conversion 
)

Registers a static diagnostic, returning an integer handle.

Returns
An integer handle for a diagnostic array.
Parameters
[in]module_nameName of this module, usually "ocean_model" or "ice_shelf_model"
[in]field_nameName of the diagnostic field
[in]axesContainer w/ up to 3 integer handles that indicates axes for this field
[in]long_nameLong name of a field.
[in]unitsUnits of a field.
[in]standard_nameStandardized name associated with a field
[in]missing_valueA value that indicates missing values.
[in]rangeValid range of a variable (not used in MOM?)
[in]mask_variantIf true a logical mask must be provided with post_data calls (not used in MOM?)
[in]do_not_logIf true, do not log something (not used in MOM?)
[in]interp_methodIf 'none' indicates the field should not be interpolated as a scalar
[in]tile_countno clue (not used in MOM?)
[in]cmor_field_nameCMOR name of a field
[in]cmor_long_nameCMOR long name of a field
[in]cmor_unitsCMOR units of a field
[in]cmor_standard_nameCMOR standardized name associated with a field
[in]areafms_id for area_t
[in]x_cell_methodSpecifies the cell method for the x-direction.
[in]y_cell_methodSpecifies the cell method for the y-direction.
[in]area_cell_methodSpecifies the cell method for area
[in]conversionA value to multiply data by before writing to file

Definition at line 2680 of file MOM_diag_mediator.F90.

2680  integer :: register_static_field !< An integer handle for a diagnostic array.
2681  character(len=*), intent(in) :: module_name !< Name of this module, usually "ocean_model"
2682  !! or "ice_shelf_model"
2683  character(len=*), intent(in) :: field_name !< Name of the diagnostic field
2684  type(axes_grp), target, intent(in) :: axes !< Container w/ up to 3 integer handles that
2685  !! indicates axes for this field
2686  character(len=*), optional, intent(in) :: long_name !< Long name of a field.
2687  character(len=*), optional, intent(in) :: units !< Units of a field.
2688  character(len=*), optional, intent(in) :: standard_name !< Standardized name associated with a field
2689  real, optional, intent(in) :: missing_value !< A value that indicates missing values.
2690  real, optional, intent(in) :: range(2) !< Valid range of a variable (not used in MOM?)
2691  logical, optional, intent(in) :: mask_variant !< If true a logical mask must be provided with
2692  !! post_data calls (not used in MOM?)
2693  logical, optional, intent(in) :: do_not_log !< If true, do not log something (not used in MOM?)
2694  character(len=*), optional, intent(in) :: interp_method !< If 'none' indicates the field should not
2695  !! be interpolated as a scalar
2696  integer, optional, intent(in) :: tile_count !< no clue (not used in MOM?)
2697  character(len=*), optional, intent(in) :: cmor_field_name !< CMOR name of a field
2698  character(len=*), optional, intent(in) :: cmor_long_name !< CMOR long name of a field
2699  character(len=*), optional, intent(in) :: cmor_units !< CMOR units of a field
2700  character(len=*), optional, intent(in) :: cmor_standard_name !< CMOR standardized name associated with a field
2701  integer, optional, intent(in) :: area !< fms_id for area_t
2702  character(len=*), optional, intent(in) :: x_cell_method !< Specifies the cell method for the x-direction.
2703  character(len=*), optional, intent(in) :: y_cell_method !< Specifies the cell method for the y-direction.
2704  character(len=*), optional, intent(in) :: area_cell_method !< Specifies the cell method for area
2705  real, optional, intent(in) :: conversion !< A value to multiply data by before writing to file
2706 
2707  ! Local variables
2708  real :: MOM_missing_value
2709  type(diag_ctrl), pointer :: diag_cs => null()
2710  type(diag_type), pointer :: diag => null(), cmor_diag => null()
2711  integer :: dm_id, fms_id, cmor_id
2712  character(len=256) :: posted_cmor_units, posted_cmor_standard_name, posted_cmor_long_name
2713  character(len=9) :: axis_name
2714 
2715  mom_missing_value = axes%diag_cs%missing_value
2716  if (present(missing_value)) mom_missing_value = missing_value
2717 
2718  diag_cs => axes%diag_cs
2719  dm_id = -1
2720  diag => null()
2721  cmor_diag => null()
2722 
2723  if (diag_cs%diag_as_chksum) then
2724  fms_id = diag_cs%num_chksum_diags + 1
2725  diag_cs%num_chksum_diags = fms_id
2726  else
2727  fms_id = register_static_field_fms(module_name, field_name, axes%handles, &
2728  long_name=long_name, units=units, missing_value=mom_missing_value, &
2729  range=range, mask_variant=mask_variant, standard_name=standard_name, &
2730  do_not_log=do_not_log, &
2731  interp_method=interp_method, tile_count=tile_count, area=area)
2732  endif
2733 
2734  if (fms_id /= diag_field_not_found) then
2735  dm_id = get_new_diag_id(diag_cs)
2736  call alloc_diag_with_id(dm_id, diag_cs, diag)
2737  call assert(associated(diag), 'register_static_field: diag allocation failed')
2738  diag%fms_diag_id = fms_id
2739  diag%debug_str = trim(module_name)//"-"//trim(field_name)
2740  if (present(conversion)) diag%conversion_factor = conversion
2741 
2742  if (diag_cs%diag_as_chksum) then
2743  diag%axes => axes
2744  else
2745  if (present(x_cell_method)) then
2746  call get_diag_axis_name(axes%handles(1), axis_name)
2747  call diag_field_add_attribute(fms_id, 'cell_methods', &
2748  trim(axis_name)//':'//trim(x_cell_method))
2749  endif
2750  if (present(y_cell_method)) then
2751  call get_diag_axis_name(axes%handles(2), axis_name)
2752  call diag_field_add_attribute(fms_id, 'cell_methods', &
2753  trim(axis_name)//':'//trim(y_cell_method))
2754  endif
2755  if (present(area_cell_method)) then
2756  call diag_field_add_attribute(fms_id, 'cell_methods', &
2757  'area:'//trim(area_cell_method))
2758  endif
2759  endif
2760  endif
2761 
2762  if (present(cmor_field_name) .and. .not. diag_cs%diag_as_chksum) then
2763  ! Fallback values for strings set to "not provided"
2764  posted_cmor_units = "not provided"
2765  posted_cmor_standard_name = "not provided"
2766  posted_cmor_long_name = "not provided"
2767 
2768  ! If attributes are present for MOM variable names, use them first for the register_static_field
2769  ! call for CMOR verison of the variable
2770  if (present(units)) posted_cmor_units = units
2771  if (present(standard_name)) posted_cmor_standard_name = standard_name
2772  if (present(long_name)) posted_cmor_long_name = long_name
2773 
2774  ! If specified in the call to register_static_field, override attributes with the CMOR versions
2775  if (present(cmor_units)) posted_cmor_units = cmor_units
2776  if (present(cmor_standard_name)) posted_cmor_standard_name = cmor_standard_name
2777  if (present(cmor_long_name)) posted_cmor_long_name = cmor_long_name
2778 
2779  fms_id = register_static_field_fms(module_name, cmor_field_name, &
2780  axes%handles, long_name=trim(posted_cmor_long_name), units=trim(posted_cmor_units), &
2781  missing_value=mom_missing_value, range=range, mask_variant=mask_variant, &
2782  standard_name=trim(posted_cmor_standard_name), do_not_log=do_not_log, &
2783  interp_method=interp_method, tile_count=tile_count, area=area)
2784  if (fms_id /= diag_field_not_found) then
2785  if (dm_id == -1) then
2786  dm_id = get_new_diag_id(diag_cs)
2787  endif
2788  call alloc_diag_with_id(dm_id, diag_cs, cmor_diag)
2789  cmor_diag%fms_diag_id = fms_id
2790  cmor_diag%debug_str = trim(module_name)//"-"//trim(cmor_field_name)
2791  if (present(conversion)) cmor_diag%conversion_factor = conversion
2792  if (present(x_cell_method)) then
2793  call get_diag_axis_name(axes%handles(1), axis_name)
2794  call diag_field_add_attribute(fms_id, 'cell_methods', trim(axis_name)//':'//trim(x_cell_method))
2795  endif
2796  if (present(y_cell_method)) then
2797  call get_diag_axis_name(axes%handles(2), axis_name)
2798  call diag_field_add_attribute(fms_id, 'cell_methods', trim(axis_name)//':'//trim(y_cell_method))
2799  endif
2800  if (present(area_cell_method)) then
2801  call diag_field_add_attribute(fms_id, 'cell_methods', 'area:'//trim(area_cell_method))
2802  endif
2803  endif
2804  endif
2805 
2806  ! Document diagnostics in list of available diagnostics
2807  if (is_root_pe() .and. diag_cs%available_diag_doc_unit > 0) then
2808  call log_available_diag(associated(diag), module_name, field_name, '', '', diag_cs, &
2809  long_name, units, standard_name)
2810  if (present(cmor_field_name)) then
2811  call log_available_diag(associated(cmor_diag), module_name, cmor_field_name, &
2812  '', '', diag_cs, posted_cmor_long_name, posted_cmor_units, &
2813  posted_cmor_standard_name)
2814  endif
2815  endif
2816 
2817  register_static_field = dm_id
2818 

◆ set_axes_info()

subroutine, public mom_diag_mediator::set_axes_info ( type(ocean_grid_type), intent(inout)  G,
type(verticalgrid_type), intent(in)  GV,
type(unit_scale_type), intent(in)  US,
type(param_file_type), intent(in)  param_file,
type(diag_ctrl), intent(inout)  diag_cs,
logical, intent(in), optional  set_vertical 
)

Sets up diagnostics axes.

Parameters
[in,out]gOcean grid structure
[in]gvocean vertical grid structure
[in]usA dimensional unit scaling type
[in]param_fileParameter file structure
[in,out]diag_csDiagnostics control structure
[in]set_verticalIf true or missing, set up vertical axes

Definition at line 344 of file MOM_diag_mediator.F90.

344  type(ocean_grid_type), intent(inout) :: G !< Ocean grid structure
345  type(verticalGrid_type), intent(in) :: GV !< ocean vertical grid structure
346  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
347  type(param_file_type), intent(in) :: param_file !< Parameter file structure
348  type(diag_ctrl), intent(inout) :: diag_cs !< Diagnostics control structure
349  logical, optional, intent(in) :: set_vertical !< If true or missing, set up
350  !! vertical axes
351  ! Local variables
352  integer :: id_xq, id_yq, id_zl, id_zi, id_xh, id_yh
353  integer :: id_zl_native, id_zi_native
354  integer :: i, j, k, nz
355  real :: zlev(GV%ke), zinter(GV%ke+1)
356  logical :: set_vert
357 
358  set_vert = .true. ; if (present(set_vertical)) set_vert = set_vertical
359 
360  ! Horizontal axes for the native grids
361  if (g%symmetric) then
362  id_xq = diag_axis_init('xq', g%gridLonB(g%isgB:g%iegB), g%x_axis_units, 'x', &
363  'q point nominal longitude', domain2=g%Domain%mpp_domain)
364  id_yq = diag_axis_init('yq', g%gridLatB(g%jsgB:g%jegB), g%y_axis_units, 'y', &
365  'q point nominal latitude', domain2=g%Domain%mpp_domain)
366  else
367  id_xq = diag_axis_init('xq', g%gridLonB(g%isg:g%ieg), g%x_axis_units, 'x', &
368  'q point nominal longitude', domain2=g%Domain%mpp_domain)
369  id_yq = diag_axis_init('yq', g%gridLatB(g%jsg:g%jeg), g%y_axis_units, 'y', &
370  'q point nominal latitude', domain2=g%Domain%mpp_domain)
371  endif
372  id_xh = diag_axis_init('xh', g%gridLonT(g%isg:g%ieg), g%x_axis_units, 'x', &
373  'h point nominal longitude', domain2=g%Domain%mpp_domain)
374  id_yh = diag_axis_init('yh', g%gridLatT(g%jsg:g%jeg), g%y_axis_units, 'y', &
375  'h point nominal latitude', domain2=g%Domain%mpp_domain)
376 
377  if (set_vert) then
378  nz = gv%ke
379  zinter(1:nz+1) = gv%sInterface(1:nz+1)
380  zlev(1:nz) = gv%sLayer(1:nz)
381  id_zl = diag_axis_init('zl', zlev, trim(gv%zAxisUnits), 'z', &
382  'Layer '//trim(gv%zAxisLongName), &
383  direction=gv%direction)
384  id_zi = diag_axis_init('zi', zinter, trim(gv%zAxisUnits), 'z', &
385  'Interface '//trim(gv%zAxisLongName), &
386  direction=gv%direction)
387  else
388  id_zl = -1 ; id_zi = -1
389  endif
390  id_zl_native = id_zl ; id_zi_native = id_zi
391  ! Vertical axes for the interfaces and layers
392  call define_axes_group(diag_cs, (/ id_zi /), diag_cs%axesZi, &
393  v_cell_method='point', is_interface=.true.)
394  call define_axes_group(diag_cs, (/ id_zl /), diag_cs%axesZL, &
395  v_cell_method='mean', is_layer=.true.)
396 
397  ! Axis groupings for the model layers
398  call define_axes_group(diag_cs, (/ id_xh, id_yh, id_zl /), diag_cs%axesTL, &
399  x_cell_method='mean', y_cell_method='mean', v_cell_method='mean', &
400  is_h_point=.true., is_layer=.true., xyave_axes=diag_cs%axesZL)
401  call define_axes_group(diag_cs, (/ id_xq, id_yq, id_zl /), diag_cs%axesBL, &
402  x_cell_method='point', y_cell_method='point', v_cell_method='mean', &
403  is_q_point=.true., is_layer=.true.)
404  call define_axes_group(diag_cs, (/ id_xq, id_yh, id_zl /), diag_cs%axesCuL, &
405  x_cell_method='point', y_cell_method='mean', v_cell_method='mean', &
406  is_u_point=.true., is_layer=.true., xyave_axes=diag_cs%axesZL)
407  call define_axes_group(diag_cs, (/ id_xh, id_yq, id_zl /), diag_cs%axesCvL, &
408  x_cell_method='mean', y_cell_method='point', v_cell_method='mean', &
409  is_v_point=.true., is_layer=.true., xyave_axes=diag_cs%axesZL)
410 
411  ! Axis groupings for the model interfaces
412  call define_axes_group(diag_cs, (/ id_xh, id_yh, id_zi /), diag_cs%axesTi, &
413  x_cell_method='mean', y_cell_method='mean', v_cell_method='point', &
414  is_h_point=.true., is_interface=.true., xyave_axes=diag_cs%axesZi)
415  call define_axes_group(diag_cs, (/ id_xq, id_yq, id_zi /), diag_cs%axesBi, &
416  x_cell_method='point', y_cell_method='point', v_cell_method='point', &
417  is_q_point=.true., is_interface=.true.)
418  call define_axes_group(diag_cs, (/ id_xq, id_yh, id_zi /), diag_cs%axesCui, &
419  x_cell_method='point', y_cell_method='mean', v_cell_method='point', &
420  is_u_point=.true., is_interface=.true., xyave_axes=diag_cs%axesZi)
421  call define_axes_group(diag_cs, (/ id_xh, id_yq, id_zi /), diag_cs%axesCvi, &
422  x_cell_method='mean', y_cell_method='point', v_cell_method='point', &
423  is_v_point=.true., is_interface=.true., xyave_axes=diag_cs%axesZi)
424 
425  ! Axis groupings for 2-D arrays
426  call define_axes_group(diag_cs, (/ id_xh, id_yh /), diag_cs%axesT1, &
427  x_cell_method='mean', y_cell_method='mean', is_h_point=.true.)
428  call define_axes_group(diag_cs, (/ id_xq, id_yq /), diag_cs%axesB1, &
429  x_cell_method='point', y_cell_method='point', is_q_point=.true.)
430  call define_axes_group(diag_cs, (/ id_xq, id_yh /), diag_cs%axesCu1, &
431  x_cell_method='point', y_cell_method='mean', is_u_point=.true.)
432  call define_axes_group(diag_cs, (/ id_xh, id_yq /), diag_cs%axesCv1, &
433  x_cell_method='mean', y_cell_method='point', is_v_point=.true.)
434 
435  ! Axis group for special null axis from diag manager
436  call define_axes_group(diag_cs, (/ null_axis_id /), diag_cs%axesNull)
437 
438 
439  !Non-native Non-downsampled
440  if (diag_cs%num_diag_coords>0) then
441  allocate(diag_cs%remap_axesZL(diag_cs%num_diag_coords))
442  allocate(diag_cs%remap_axesTL(diag_cs%num_diag_coords))
443  allocate(diag_cs%remap_axesBL(diag_cs%num_diag_coords))
444  allocate(diag_cs%remap_axesCuL(diag_cs%num_diag_coords))
445  allocate(diag_cs%remap_axesCvL(diag_cs%num_diag_coords))
446  allocate(diag_cs%remap_axesZi(diag_cs%num_diag_coords))
447  allocate(diag_cs%remap_axesTi(diag_cs%num_diag_coords))
448  allocate(diag_cs%remap_axesBi(diag_cs%num_diag_coords))
449  allocate(diag_cs%remap_axesCui(diag_cs%num_diag_coords))
450  allocate(diag_cs%remap_axesCvi(diag_cs%num_diag_coords))
451  endif
452 
453  do i=1, diag_cs%num_diag_coords
454  ! For each possible diagnostic coordinate
455  call diag_remap_configure_axes(diag_cs%diag_remap_cs(i), gv, us, param_file)
456 
457  ! This vertical coordinate has been configured so can be used.
458  if (diag_remap_axes_configured(diag_cs%diag_remap_cs(i))) then
459 
460  ! This fetches the 1D-axis id for layers and interfaces and overwrite
461  ! id_zl and id_zi from above. It also returns the number of layers.
462  call diag_remap_get_axes_info(diag_cs%diag_remap_cs(i), nz, id_zl, id_zi)
463 
464  ! Axes for z layers
465  call define_axes_group(diag_cs, (/ id_zl /), diag_cs%remap_axesZL(i), &
466  nz=nz, vertical_coordinate_number=i, &
467  v_cell_method='mean', &
468  is_h_point=.true., is_layer=.true., is_native=.false., needs_remapping=.true.)
469  call define_axes_group(diag_cs, (/ id_xh, id_yh, id_zl /), diag_cs%remap_axesTL(i), &
470  nz=nz, vertical_coordinate_number=i, &
471  x_cell_method='mean', y_cell_method='mean', v_cell_method='mean', &
472  is_h_point=.true., is_layer=.true., is_native=.false., needs_remapping=.true., &
473  xyave_axes=diag_cs%remap_axesZL(i))
474 
475  !! \note Remapping for B points is not yet implemented so needs_remapping is not
476  !! provided for remap_axesBL
477  call define_axes_group(diag_cs, (/ id_xq, id_yq, id_zl /), diag_cs%remap_axesBL(i), &
478  nz=nz, vertical_coordinate_number=i, &
479  x_cell_method='point', y_cell_method='point', v_cell_method='mean', &
480  is_q_point=.true., is_layer=.true., is_native=.false.)
481 
482  call define_axes_group(diag_cs, (/ id_xq, id_yh, id_zl /), diag_cs%remap_axesCuL(i), &
483  nz=nz, vertical_coordinate_number=i, &
484  x_cell_method='point', y_cell_method='mean', v_cell_method='mean', &
485  is_u_point=.true., is_layer=.true., is_native=.false., needs_remapping=.true., &
486  xyave_axes=diag_cs%remap_axesZL(i))
487 
488  call define_axes_group(diag_cs, (/ id_xh, id_yq, id_zl /), diag_cs%remap_axesCvL(i), &
489  nz=nz, vertical_coordinate_number=i, &
490  x_cell_method='mean', y_cell_method='point', v_cell_method='mean', &
491  is_v_point=.true., is_layer=.true., is_native=.false., needs_remapping=.true., &
492  xyave_axes=diag_cs%remap_axesZL(i))
493 
494  ! Axes for z interfaces
495  call define_axes_group(diag_cs, (/ id_zi /), diag_cs%remap_axesZi(i), &
496  nz=nz, vertical_coordinate_number=i, &
497  v_cell_method='point', &
498  is_h_point=.true., is_interface=.true., is_native=.false., needs_interpolating=.true.)
499  call define_axes_group(diag_cs, (/ id_xh, id_yh, id_zi /), diag_cs%remap_axesTi(i), &
500  nz=nz, vertical_coordinate_number=i, &
501  x_cell_method='mean', y_cell_method='mean', v_cell_method='point', &
502  is_h_point=.true., is_interface=.true., is_native=.false., needs_interpolating=.true., &
503  xyave_axes=diag_cs%remap_axesZi(i))
504 
505  !! \note Remapping for B points is not yet implemented so needs_remapping is not provided for remap_axesBi
506  call define_axes_group(diag_cs, (/ id_xq, id_yq, id_zi /), diag_cs%remap_axesBi(i), &
507  nz=nz, vertical_coordinate_number=i, &
508  x_cell_method='point', y_cell_method='point', v_cell_method='point', &
509  is_q_point=.true., is_interface=.true., is_native=.false.)
510 
511  call define_axes_group(diag_cs, (/ id_xq, id_yh, id_zi /), diag_cs%remap_axesCui(i), &
512  nz=nz, vertical_coordinate_number=i, &
513  x_cell_method='point', y_cell_method='mean', v_cell_method='point', &
514  is_u_point=.true., is_interface=.true., is_native=.false., &
515  needs_interpolating=.true., xyave_axes=diag_cs%remap_axesZi(i))
516 
517  call define_axes_group(diag_cs, (/ id_xh, id_yq, id_zi /), diag_cs%remap_axesCvi(i), &
518  nz=nz, vertical_coordinate_number=i, &
519  x_cell_method='mean', y_cell_method='point', v_cell_method='point', &
520  is_v_point=.true., is_interface=.true., is_native=.false., &
521  needs_interpolating=.true., xyave_axes=diag_cs%remap_axesZi(i))
522  endif
523  enddo
524 
525  !Define the downsampled axes
526  call set_axes_info_dsamp(g, gv, param_file, diag_cs, id_zl_native, id_zi_native)
527 
528  call diag_grid_storage_init(diag_cs%diag_grid_temp, g, diag_cs)
529 

◆ set_axes_info_dsamp()

subroutine mom_diag_mediator::set_axes_info_dsamp ( type(ocean_grid_type), intent(in)  G,
type(verticalgrid_type), intent(in)  GV,
type(param_file_type), intent(in)  param_file,
type(diag_ctrl), intent(inout)  diag_cs,
integer, intent(in)  id_zl_native,
integer, intent(in)  id_zi_native 
)
private
Parameters
[in]gOcean grid structure
[in]gvocean vertical grid structure
[in]param_fileParameter file structure
[in,out]diag_csDiagnostics control structure
[in]id_zl_nativeID of native layers
[in]id_zi_nativeID of native interfaces

Definition at line 533 of file MOM_diag_mediator.F90.

533  type(ocean_grid_type), intent(in) :: G !< Ocean grid structure
534  type(verticalGrid_type), intent(in) :: GV !< ocean vertical grid structure
535  type(param_file_type), intent(in) :: param_file !< Parameter file structure
536  type(diag_ctrl), intent(inout) :: diag_cs !< Diagnostics control structure
537  integer, intent(in) :: id_zl_native !< ID of native layers
538  integer, intent(in) :: id_zi_native !< ID of native interfaces
539 
540  ! Local variables
541  integer :: id_xq, id_yq, id_zl, id_zi, id_xh, id_yh
542  integer :: i, j, k, nz, dl
543  real, dimension(:), pointer :: gridLonT_dsamp =>null()
544  real, dimension(:), pointer :: gridLatT_dsamp =>null()
545  real, dimension(:), pointer :: gridLonB_dsamp =>null()
546  real, dimension(:), pointer :: gridLatB_dsamp =>null()
547 
548  id_zl = id_zl_native ; id_zi = id_zi_native
549  !Axes group for native downsampled diagnostics
550  do dl=2,max_dsamp_lev
551  if(dl .ne. 2) call mom_error(fatal, "set_axes_info_dsamp: Downsample level other than 2 is not supported yet!")
552  if (g%symmetric) then
553  allocate(gridlonb_dsamp(diag_cs%dsamp(dl)%isgB:diag_cs%dsamp(dl)%iegB))
554  allocate(gridlatb_dsamp(diag_cs%dsamp(dl)%jsgB:diag_cs%dsamp(dl)%jegB))
555  do i=diag_cs%dsamp(dl)%isgB,diag_cs%dsamp(dl)%iegB; gridlonb_dsamp(i) = g%gridLonB(g%isgB+dl*i); enddo
556  do j=diag_cs%dsamp(dl)%jsgB,diag_cs%dsamp(dl)%jegB; gridlatb_dsamp(j) = g%gridLatB(g%jsgB+dl*j); enddo
557  id_xq = diag_axis_init('xq', gridlonb_dsamp, g%x_axis_units, 'x', &
558  'q point nominal longitude', domain2=g%Domain%mpp_domain_d2)
559  id_yq = diag_axis_init('yq', gridlatb_dsamp, g%y_axis_units, 'y', &
560  'q point nominal latitude', domain2=g%Domain%mpp_domain_d2)
561  deallocate(gridlonb_dsamp,gridlatb_dsamp)
562  else
563  allocate(gridlonb_dsamp(diag_cs%dsamp(dl)%isg:diag_cs%dsamp(dl)%ieg))
564  allocate(gridlatb_dsamp(diag_cs%dsamp(dl)%jsg:diag_cs%dsamp(dl)%jeg))
565  do i=diag_cs%dsamp(dl)%isg,diag_cs%dsamp(dl)%ieg; gridlonb_dsamp(i) = g%gridLonB(g%isg+dl*i-2); enddo
566  do j=diag_cs%dsamp(dl)%jsg,diag_cs%dsamp(dl)%jeg; gridlatb_dsamp(j) = g%gridLatB(g%jsg+dl*j-2); enddo
567  id_xq = diag_axis_init('xq', gridlonb_dsamp, g%x_axis_units, 'x', &
568  'q point nominal longitude', domain2=g%Domain%mpp_domain_d2)
569  id_yq = diag_axis_init('yq', gridlatb_dsamp, g%y_axis_units, 'y', &
570  'q point nominal latitude', domain2=g%Domain%mpp_domain_d2)
571  deallocate(gridlonb_dsamp,gridlatb_dsamp)
572  endif
573 
574  allocate(gridlont_dsamp(diag_cs%dsamp(dl)%isg:diag_cs%dsamp(dl)%ieg))
575  allocate(gridlatt_dsamp(diag_cs%dsamp(dl)%jsg:diag_cs%dsamp(dl)%jeg))
576  do i=diag_cs%dsamp(dl)%isg,diag_cs%dsamp(dl)%ieg; gridlont_dsamp(i) = g%gridLonT(g%isg+dl*i-2); enddo
577  do j=diag_cs%dsamp(dl)%jsg,diag_cs%dsamp(dl)%jeg; gridlatt_dsamp(j) = g%gridLatT(g%jsg+dl*j-2); enddo
578  id_xh = diag_axis_init('xh', gridlont_dsamp, g%x_axis_units, 'x', &
579  'h point nominal longitude', domain2=g%Domain%mpp_domain_d2)
580  id_yh = diag_axis_init('yh', gridlatt_dsamp, g%y_axis_units, 'y', &
581  'h point nominal latitude', domain2=g%Domain%mpp_domain_d2)
582 
583  deallocate(gridlont_dsamp,gridlatt_dsamp)
584 
585  ! Axis groupings for the model layers
586  call define_axes_group_dsamp(diag_cs, (/ id_xh, id_yh, id_zl /), diag_cs%dsamp(dl)%axesTL, dl, &
587  x_cell_method='mean', y_cell_method='mean', v_cell_method='mean', &
588  is_h_point=.true., is_layer=.true., xyave_axes=diag_cs%axesZL)
589  call define_axes_group_dsamp(diag_cs, (/ id_xq, id_yq, id_zl /), diag_cs%dsamp(dl)%axesBL, dl, &
590  x_cell_method='point', y_cell_method='point', v_cell_method='mean', &
591  is_q_point=.true., is_layer=.true.)
592  call define_axes_group_dsamp(diag_cs, (/ id_xq, id_yh, id_zl /), diag_cs%dsamp(dl)%axesCuL, dl, &
593  x_cell_method='point', y_cell_method='mean', v_cell_method='mean', &
594  is_u_point=.true., is_layer=.true., xyave_axes=diag_cs%axesZL)
595  call define_axes_group_dsamp(diag_cs, (/ id_xh, id_yq, id_zl /), diag_cs%dsamp(dl)%axesCvL, dl, &
596  x_cell_method='mean', y_cell_method='point', v_cell_method='mean', &
597  is_v_point=.true., is_layer=.true., xyave_axes=diag_cs%axesZL)
598 
599  ! Axis groupings for the model interfaces
600  call define_axes_group_dsamp(diag_cs, (/ id_xh, id_yh, id_zi /), diag_cs%dsamp(dl)%axesTi, dl, &
601  x_cell_method='mean', y_cell_method='mean', v_cell_method='point', &
602  is_h_point=.true., is_interface=.true., xyave_axes=diag_cs%axesZi)
603  call define_axes_group_dsamp(diag_cs, (/ id_xq, id_yq, id_zi /), diag_cs%dsamp(dl)%axesBi, dl, &
604  x_cell_method='point', y_cell_method='point', v_cell_method='point', &
605  is_q_point=.true., is_interface=.true.)
606  call define_axes_group_dsamp(diag_cs, (/ id_xq, id_yh, id_zi /), diag_cs%dsamp(dl)%axesCui, dl, &
607  x_cell_method='point', y_cell_method='mean', v_cell_method='point', &
608  is_u_point=.true., is_interface=.true., xyave_axes=diag_cs%axesZi)
609  call define_axes_group_dsamp(diag_cs, (/ id_xh, id_yq, id_zi /), diag_cs%dsamp(dl)%axesCvi, dl, &
610  x_cell_method='mean', y_cell_method='point', v_cell_method='point', &
611  is_v_point=.true., is_interface=.true., xyave_axes=diag_cs%axesZi)
612 
613  ! Axis groupings for 2-D arrays
614  call define_axes_group_dsamp(diag_cs, (/ id_xh, id_yh /), diag_cs%dsamp(dl)%axesT1, dl, &
615  x_cell_method='mean', y_cell_method='mean', is_h_point=.true.)
616  call define_axes_group_dsamp(diag_cs, (/ id_xq, id_yq /), diag_cs%dsamp(dl)%axesB1, dl, &
617  x_cell_method='point', y_cell_method='point', is_q_point=.true.)
618  call define_axes_group_dsamp(diag_cs, (/ id_xq, id_yh /), diag_cs%dsamp(dl)%axesCu1, dl, &
619  x_cell_method='point', y_cell_method='mean', is_u_point=.true.)
620  call define_axes_group_dsamp(diag_cs, (/ id_xh, id_yq /), diag_cs%dsamp(dl)%axesCv1, dl, &
621  x_cell_method='mean', y_cell_method='point', is_v_point=.true.)
622 
623  !Non-native axes
624  if (diag_cs%num_diag_coords>0) then
625  allocate(diag_cs%dsamp(dl)%remap_axesTL(diag_cs%num_diag_coords))
626  allocate(diag_cs%dsamp(dl)%remap_axesBL(diag_cs%num_diag_coords))
627  allocate(diag_cs%dsamp(dl)%remap_axesCuL(diag_cs%num_diag_coords))
628  allocate(diag_cs%dsamp(dl)%remap_axesCvL(diag_cs%num_diag_coords))
629  allocate(diag_cs%dsamp(dl)%remap_axesTi(diag_cs%num_diag_coords))
630  allocate(diag_cs%dsamp(dl)%remap_axesBi(diag_cs%num_diag_coords))
631  allocate(diag_cs%dsamp(dl)%remap_axesCui(diag_cs%num_diag_coords))
632  allocate(diag_cs%dsamp(dl)%remap_axesCvi(diag_cs%num_diag_coords))
633  endif
634 
635  do i=1, diag_cs%num_diag_coords
636  ! For each possible diagnostic coordinate
637  !call diag_remap_configure_axes(diag_cs%diag_remap_cs(i), GV, param_file)
638 
639  ! This vertical coordinate has been configured so can be used.
640  if (diag_remap_axes_configured(diag_cs%diag_remap_cs(i))) then
641 
642  ! This fetches the 1D-axis id for layers and interfaces and overwrite
643  ! id_zl and id_zi from above. It also returns the number of layers.
644  call diag_remap_get_axes_info(diag_cs%diag_remap_cs(i), nz, id_zl, id_zi)
645 
646  ! Axes for z layers
647  call define_axes_group_dsamp(diag_cs, (/ id_xh, id_yh, id_zl /), diag_cs%dsamp(dl)%remap_axesTL(i), dl, &
648  nz=nz, vertical_coordinate_number=i, &
649  x_cell_method='mean', y_cell_method='mean', v_cell_method='mean', &
650  is_h_point=.true., is_layer=.true., is_native=.false., needs_remapping=.true., &
651  xyave_axes=diag_cs%remap_axesZL(i))
652 
653  !! \note Remapping for B points is not yet implemented so needs_remapping is not
654  !! provided for remap_axesBL
655  call define_axes_group_dsamp(diag_cs, (/ id_xq, id_yq, id_zl /), diag_cs%dsamp(dl)%remap_axesBL(i), dl, &
656  nz=nz, vertical_coordinate_number=i, &
657  x_cell_method='point', y_cell_method='point', v_cell_method='mean', &
658  is_q_point=.true., is_layer=.true., is_native=.false.)
659 
660  call define_axes_group_dsamp(diag_cs, (/ id_xq, id_yh, id_zl /), diag_cs%dsamp(dl)%remap_axesCuL(i), dl, &
661  nz=nz, vertical_coordinate_number=i, &
662  x_cell_method='point', y_cell_method='mean', v_cell_method='mean', &
663  is_u_point=.true., is_layer=.true., is_native=.false., needs_remapping=.true., &
664  xyave_axes=diag_cs%remap_axesZL(i))
665 
666  call define_axes_group_dsamp(diag_cs, (/ id_xh, id_yq, id_zl /), diag_cs%dsamp(dl)%remap_axesCvL(i), dl, &
667  nz=nz, vertical_coordinate_number=i, &
668  x_cell_method='mean', y_cell_method='point', v_cell_method='mean', &
669  is_v_point=.true., is_layer=.true., is_native=.false., needs_remapping=.true., &
670  xyave_axes=diag_cs%remap_axesZL(i))
671 
672  ! Axes for z interfaces
673  call define_axes_group_dsamp(diag_cs, (/ id_xh, id_yh, id_zi /), diag_cs%dsamp(dl)%remap_axesTi(i), dl, &
674  nz=nz, vertical_coordinate_number=i, &
675  x_cell_method='mean', y_cell_method='mean', v_cell_method='point', &
676  is_h_point=.true., is_interface=.true., is_native=.false., needs_interpolating=.true., &
677  xyave_axes=diag_cs%remap_axesZi(i))
678 
679  !! \note Remapping for B points is not yet implemented so needs_remapping is not provided for remap_axesBi
680  call define_axes_group_dsamp(diag_cs, (/ id_xq, id_yq, id_zi /), diag_cs%dsamp(dl)%remap_axesBi(i), dl, &
681  nz=nz, vertical_coordinate_number=i, &
682  x_cell_method='point', y_cell_method='point', v_cell_method='point', &
683  is_q_point=.true., is_interface=.true., is_native=.false.)
684 
685  call define_axes_group_dsamp(diag_cs, (/ id_xq, id_yh, id_zi /), diag_cs%dsamp(dl)%remap_axesCui(i), dl, &
686  nz=nz, vertical_coordinate_number=i, &
687  x_cell_method='point', y_cell_method='mean', v_cell_method='point', &
688  is_u_point=.true., is_interface=.true., is_native=.false., &
689  needs_interpolating=.true., xyave_axes=diag_cs%remap_axesZi(i))
690 
691  call define_axes_group_dsamp(diag_cs, (/ id_xh, id_yq, id_zi /), diag_cs%dsamp(dl)%remap_axesCvi(i), dl, &
692  nz=nz, vertical_coordinate_number=i, &
693  x_cell_method='mean', y_cell_method='point', v_cell_method='point', &
694  is_v_point=.true., is_interface=.true., is_native=.false., &
695  needs_interpolating=.true., xyave_axes=diag_cs%remap_axesZi(i))
696  endif
697  enddo
698  enddo
699 

◆ set_diag_mediator_grid()

subroutine, public mom_diag_mediator::set_diag_mediator_grid ( type(ocean_grid_type), intent(inout)  G,
type(diag_ctrl), intent(inout)  diag_cs 
)

Set up the array extents for doing diagnostics.

Parameters
[in,out]gThe ocean's grid structure
[in,out]diag_csStructure used to regulate diagnostic output

Definition at line 1187 of file MOM_diag_mediator.F90.

1187  type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure
1188  type(diag_ctrl), intent(inout) :: diag_CS !< Structure used to regulate diagnostic output
1189 
1190  diag_cs%is = g%isc - (g%isd-1) ; diag_cs%ie = g%iec - (g%isd-1)
1191  diag_cs%js = g%jsc - (g%jsd-1) ; diag_cs%je = g%jec - (g%jsd-1)
1192  diag_cs%isd = g%isd ; diag_cs%ied = g%ied
1193  diag_cs%jsd = g%jsd ; diag_cs%jed = g%jed
1194 

◆ set_masks_for_axes()

subroutine, public mom_diag_mediator::set_masks_for_axes ( type(ocean_grid_type), intent(in), target  G,
type(diag_ctrl), pointer  diag_cs 
)

set_masks_for_axes sets up the 2d and 3d masks for diagnostics using the current grid recorded after calling diag_update_remap_grids()

Parameters
[in]gThe ocean grid type.
diag_csA pointer to a type with many variables used for diagnostics

Definition at line 706 of file MOM_diag_mediator.F90.

706  type(ocean_grid_type), target, intent(in) :: G !< The ocean grid type.
707  type(diag_ctrl), pointer :: diag_cs !< A pointer to a type with many variables
708  !! used for diagnostics
709  ! Local variables
710  integer :: c, nk, i, j, k, ii, jj
711  type(axes_grp), pointer :: axes => null(), h_axes => null() ! Current axes, for convenience
712 
713  do c=1, diag_cs%num_diag_coords
714  ! This vertical coordinate has been configured so can be used.
715  if (diag_remap_axes_configured(diag_cs%diag_remap_cs(c))) then
716 
717  ! Level/layer h-points in diagnostic coordinate
718  axes => diag_cs%remap_axesTL(c)
719  nk = axes%nz
720  allocate( axes%mask3d(g%isd:g%ied,g%jsd:g%jed,nk) ) ; axes%mask3d(:,:,:) = 0.
721  call diag_remap_calc_hmask(diag_cs%diag_remap_cs(c), g, axes%mask3d)
722 
723  h_axes => diag_cs%remap_axesTL(c) ! Use the h-point masks to generate the u-, v- and q- masks
724 
725  ! Level/layer u-points in diagnostic coordinate
726  axes => diag_cs%remap_axesCuL(c)
727  call assert(axes%nz == nk, 'set_masks_for_axes: vertical size mismatch at u-layers')
728  call assert(.not. associated(axes%mask3d), 'set_masks_for_axes: already associated')
729  allocate( axes%mask3d(g%IsdB:g%IedB,g%jsd:g%jed,nk) ) ; axes%mask3d(:,:,:) = 0.
730  do k = 1, nk ; do j=g%jsc,g%jec ; do i=g%isc-1,g%iec
731  if (h_axes%mask3d(i,j,k) + h_axes%mask3d(i+1,j,k) > 0.) axes%mask3d(i,j,k) = 1.
732  enddo ; enddo ; enddo
733 
734  ! Level/layer v-points in diagnostic coordinate
735  axes => diag_cs%remap_axesCvL(c)
736  call assert(axes%nz == nk, 'set_masks_for_axes: vertical size mismatch at v-layers')
737  call assert(.not. associated(axes%mask3d), 'set_masks_for_axes: already associated')
738  allocate( axes%mask3d(g%isd:g%ied,g%JsdB:g%JedB,nk) ) ; axes%mask3d(:,:,:) = 0.
739  do k = 1, nk ; do j=g%jsc-1,g%jec ; do i=g%isc,g%iec
740  if (h_axes%mask3d(i,j,k) + h_axes%mask3d(i,j+1,k) > 0.) axes%mask3d(i,j,k) = 1.
741  enddo ; enddo ; enddo
742 
743  ! Level/layer q-points in diagnostic coordinate
744  axes => diag_cs%remap_axesBL(c)
745  call assert(axes%nz == nk, 'set_masks_for_axes: vertical size mismatch at q-layers')
746  call assert(.not. associated(axes%mask3d), 'set_masks_for_axes: already associated')
747  allocate( axes%mask3d(g%IsdB:g%IedB,g%JsdB:g%JedB,nk) ) ; axes%mask3d(:,:,:) = 0.
748  do k = 1, nk ; do j=g%jsc-1,g%jec ; do i=g%isc-1,g%iec
749  if (h_axes%mask3d(i,j,k) + h_axes%mask3d(i+1,j+1,k) + &
750  h_axes%mask3d(i+1,j,k) + h_axes%mask3d(i,j+1,k) > 0.) axes%mask3d(i,j,k) = 1.
751  enddo ; enddo ; enddo
752 
753  ! Interface h-points in diagnostic coordinate (w-point)
754  axes => diag_cs%remap_axesTi(c)
755  call assert(axes%nz == nk, 'set_masks_for_axes: vertical size mismatch at h-interfaces')
756  call assert(.not. associated(axes%mask3d), 'set_masks_for_axes: already associated')
757  allocate( axes%mask3d(g%isd:g%ied,g%jsd:g%jed,nk+1) ) ; axes%mask3d(:,:,:) = 0.
758  do j=g%jsc-1,g%jec+1 ; do i=g%isc-1,g%iec+1
759  if (h_axes%mask3d(i,j,1) > 0.) axes%mask3d(i,j,1) = 1.
760  do k = 2, nk
761  if (h_axes%mask3d(i,j,k-1) + h_axes%mask3d(i,j,k) > 0.) axes%mask3d(i,j,k) = 1.
762  enddo
763  if (h_axes%mask3d(i,j,nk) > 0.) axes%mask3d(i,j,nk+1) = 1.
764  enddo ; enddo
765 
766  h_axes => diag_cs%remap_axesTi(c) ! Use the w-point masks to generate the u-, v- and q- masks
767 
768  ! Interface u-points in diagnostic coordinate
769  axes => diag_cs%remap_axesCui(c)
770  call assert(axes%nz == nk, 'set_masks_for_axes: vertical size mismatch at u-interfaces')
771  call assert(.not. associated(axes%mask3d), 'set_masks_for_axes: already associated')
772  allocate( axes%mask3d(g%IsdB:g%IedB,g%jsd:g%jed,nk+1) ) ; axes%mask3d(:,:,:) = 0.
773  do k = 1, nk+1 ; do j=g%jsc,g%jec ; do i=g%isc-1,g%iec
774  if (h_axes%mask3d(i,j,k) + h_axes%mask3d(i+1,j,k) > 0.) axes%mask3d(i,j,k) = 1.
775  enddo ; enddo ; enddo
776 
777  ! Interface v-points in diagnostic coordinate
778  axes => diag_cs%remap_axesCvi(c)
779  call assert(axes%nz == nk, 'set_masks_for_axes: vertical size mismatch at v-interfaces')
780  call assert(.not. associated(axes%mask3d), 'set_masks_for_axes: already associated')
781  allocate( axes%mask3d(g%isd:g%ied,g%JsdB:g%JedB,nk+1) ) ; axes%mask3d(:,:,:) = 0.
782  do k = 1, nk+1 ; do j=g%jsc-1,g%jec ; do i=g%isc,g%iec
783  if (h_axes%mask3d(i,j,k) + h_axes%mask3d(i,j+1,k) > 0.) axes%mask3d(i,j,k) = 1.
784  enddo ; enddo ; enddo
785 
786  ! Interface q-points in diagnostic coordinate
787  axes => diag_cs%remap_axesBi(c)
788  call assert(axes%nz == nk, 'set_masks_for_axes: vertical size mismatch at q-interfaces')
789  call assert(.not. associated(axes%mask3d), 'set_masks_for_axes: already associated')
790  allocate( axes%mask3d(g%IsdB:g%IedB,g%JsdB:g%JedB,nk+1) ) ; axes%mask3d(:,:,:) = 0.
791  do k = 1, nk ; do j=g%jsc-1,g%jec ; do i=g%isc-1,g%iec
792  if (h_axes%mask3d(i,j,k) + h_axes%mask3d(i+1,j+1,k) + &
793  h_axes%mask3d(i+1,j,k) + h_axes%mask3d(i,j+1,k) > 0.) axes%mask3d(i,j,k) = 1.
794  enddo ; enddo ; enddo
795  endif
796  enddo
797 
798  !Allocate and initialize the downsampled masks for the axes
799  call set_masks_for_axes_dsamp(g, diag_cs)
800 

◆ set_masks_for_axes_dsamp()

subroutine mom_diag_mediator::set_masks_for_axes_dsamp ( type(ocean_grid_type), intent(in), target  G,
type(diag_ctrl), pointer  diag_cs 
)
private
Parameters
[in]gThe ocean grid type.
diag_csA pointer to a type with many variables used for diagnostics

Definition at line 804 of file MOM_diag_mediator.F90.

804  type(ocean_grid_type), target, intent(in) :: G !< The ocean grid type.
805  type(diag_ctrl), pointer :: diag_cs !< A pointer to a type with many variables
806  !! used for diagnostics
807  ! Local variables
808  integer :: c, nk, i, j, k, ii, jj
809  integer :: dl
810  type(axes_grp), pointer :: axes => null(), h_axes => null() ! Current axes, for convenience
811 
812  !Each downsampled axis needs both downsampled and non-downsampled mask
813  !The downsampled mask is needed for sending out the diagnostics output via diag_manager
814  !The non-downsampled mask is needed for downsampling the diagnostics field
815  do dl=2,max_dsamp_lev
816  if(dl .ne. 2) call mom_error(fatal, "set_masks_for_axes_dsamp: Downsample level other than 2 is not supported!")
817  do c=1, diag_cs%num_diag_coords
818  ! Level/layer h-points in diagnostic coordinate
819  axes => diag_cs%remap_axesTL(c)
820  call downsample_mask(axes%mask3d, diag_cs%dsamp(dl)%remap_axesTL(c)%dsamp(dl)%mask3d, dl,g%isc, g%jsc, &
821  g%HId2%isc, g%HId2%iec, g%HId2%jsc, g%HId2%jec, g%HId2%isd, g%HId2%ied, g%HId2%jsd, g%HId2%jed)
822  diag_cs%dsamp(dl)%remap_axesTL(c)%mask3d => axes%mask3d !set non-downsampled mask
823  ! Level/layer u-points in diagnostic coordinate
824  axes => diag_cs%remap_axesCuL(c)
825  call downsample_mask(axes%mask3d, diag_cs%dsamp(dl)%remap_axesCuL(c)%dsamp(dl)%mask3d, dl,g%IscB,g%JscB, &
826  g%HId2%IscB,g%HId2%IecB,g%HId2%jsc, g%HId2%jec,g%HId2%IsdB,g%HId2%IedB,g%HId2%jsd, g%HId2%jed)
827  diag_cs%dsamp(dl)%remap_axesCul(c)%mask3d => axes%mask3d !set non-downsampled mask
828  ! Level/layer v-points in diagnostic coordinate
829  axes => diag_cs%remap_axesCvL(c)
830  call downsample_mask(axes%mask3d, diag_cs%dsamp(dl)%remap_axesCvL(c)%dsamp(dl)%mask3d, dl,g%isc ,g%JscB, &
831  g%HId2%isc ,g%HId2%iec, g%HId2%JscB,g%HId2%JecB,g%HId2%isd ,g%HId2%ied, g%HId2%JsdB,g%HId2%JedB)
832  diag_cs%dsamp(dl)%remap_axesCvL(c)%mask3d => axes%mask3d !set non-downsampled mask
833  ! Level/layer q-points in diagnostic coordinate
834  axes => diag_cs%remap_axesBL(c)
835  call downsample_mask(axes%mask3d, diag_cs%dsamp(dl)%remap_axesBL(c)%dsamp(dl)%mask3d, dl,g%IscB,g%JscB, &
836  g%HId2%IscB,g%HId2%IecB,g%HId2%JscB,g%HId2%JecB,g%HId2%IsdB,g%HId2%IedB,g%HId2%JsdB,g%HId2%JedB)
837  diag_cs%dsamp(dl)%remap_axesBL(c)%mask3d => axes%mask3d !set non-downsampled mask
838  ! Interface h-points in diagnostic coordinate (w-point)
839  axes => diag_cs%remap_axesTi(c)
840  call downsample_mask(axes%mask3d, diag_cs%dsamp(dl)%remap_axesTi(c)%dsamp(dl)%mask3d, dl,g%isc, g%jsc, &
841  g%HId2%isc, g%HId2%iec, g%HId2%jsc, g%HId2%jec, g%HId2%isd, g%HId2%ied, g%HId2%jsd, g%HId2%jed)
842  diag_cs%dsamp(dl)%remap_axesTi(c)%mask3d => axes%mask3d !set non-downsampled mask
843  ! Interface u-points in diagnostic coordinate
844  axes => diag_cs%remap_axesCui(c)
845  call downsample_mask(axes%mask3d, diag_cs%dsamp(dl)%remap_axesCui(c)%dsamp(dl)%mask3d, dl,g%IscB,g%JscB, &
846  g%HId2%IscB,g%HId2%IecB,g%HId2%jsc, g%HId2%jec,g%HId2%IsdB,g%HId2%IedB,g%HId2%jsd, g%HId2%jed)
847  diag_cs%dsamp(dl)%remap_axesCui(c)%mask3d => axes%mask3d !set non-downsampled mask
848  ! Interface v-points in diagnostic coordinate
849  axes => diag_cs%remap_axesCvi(c)
850  call downsample_mask(axes%mask3d, diag_cs%dsamp(dl)%remap_axesCvi(c)%dsamp(dl)%mask3d, dl,g%isc ,g%JscB, &
851  g%HId2%isc ,g%HId2%iec, g%HId2%JscB,g%HId2%JecB,g%HId2%isd ,g%HId2%ied, g%HId2%JsdB,g%HId2%JedB)
852  diag_cs%dsamp(dl)%remap_axesCvi(c)%mask3d => axes%mask3d !set non-downsampled mask
853  ! Interface q-points in diagnostic coordinate
854  axes => diag_cs%remap_axesBi(c)
855  call downsample_mask(axes%mask3d, diag_cs%dsamp(dl)%remap_axesBi(c)%dsamp(dl)%mask3d, dl,g%IscB,g%JscB, &
856  g%HId2%IscB,g%HId2%IecB,g%HId2%JscB,g%HId2%JecB,g%HId2%IsdB,g%HId2%IedB,g%HId2%JsdB,g%HId2%JedB)
857  diag_cs%dsamp(dl)%remap_axesBi(c)%mask3d => axes%mask3d !set non-downsampled mask
858  enddo
859  enddo

Variable Documentation

◆ id_clock_diag_grid_updates

integer mom_diag_mediator::id_clock_diag_grid_updates
private

Sets up diagnostics axes.

Parameters
[in,out]gOcean grid structure
[in]gvocean vertical grid structure
[in]usA dimensional unit scaling type
[in]param_fileParameter file structure
[in,out]diag_csDiagnostics control structure
[in]set_verticalIf true or missing, set up vertical axes

Definition at line 338 of file MOM_diag_mediator.F90.

◆ id_clock_diag_mediator

integer mom_diag_mediator::id_clock_diag_mediator

Sets up diagnostics axes.

Parameters
[in,out]gOcean grid structure
[in]gvocean vertical grid structure
[in]usA dimensional unit scaling type
[in]param_fileParameter file structure
[in,out]diag_csDiagnostics control structure
[in]set_verticalIf true or missing, set up vertical axes

Definition at line 338 of file MOM_diag_mediator.F90.

338 integer :: id_clock_diag_mediator, id_clock_diag_remap, id_clock_diag_grid_updates

◆ id_clock_diag_remap

integer mom_diag_mediator::id_clock_diag_remap
private

Sets up diagnostics axes.

Parameters
[in,out]gOcean grid structure
[in]gvocean vertical grid structure
[in]usA dimensional unit scaling type
[in]param_fileParameter file structure
[in,out]diag_csDiagnostics control structure
[in]set_verticalIf true or missing, set up vertical axes

Definition at line 338 of file MOM_diag_mediator.F90.