MOM6
MOM_forcing_type.F90
1 !> This module implements boundary forcing for MOM6.
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
6 use mom_debugging, only : hchksum, uvchksum
7 use mom_cpu_clock, only : cpu_clock_id, cpu_clock_begin, cpu_clock_end, clock_routine
8 use mom_diag_mediator, only : post_data, register_diag_field, register_scalar_field
9 use mom_diag_mediator, only : time_type, diag_ctrl, safe_alloc_alloc, query_averaging_enabled
10 use mom_error_handler, only : mom_error, fatal, warning
13 use mom_grid, only : ocean_grid_type
14 use mom_opacity, only : sumswoverbands, optics_type, extract_optics_slice, optics_nbands
15 use mom_spatial_means, only : global_area_integral, global_area_mean
19 
20 use coupler_types_mod, only : coupler_2d_bc_type, coupler_type_spawn
21 use coupler_types_mod, only : coupler_type_increment_data, coupler_type_initialized
22 use coupler_types_mod, only : coupler_type_copy_data, coupler_type_destructor
23 
24 implicit none ; private
25 
26 #include <MOM_memory.h>
27 
28 public extractfluxes1d, extractfluxes2d, optics_type
29 public mom_forcing_chksum, mom_mech_forcing_chksum
30 public calculatebuoyancyflux1d, calculatebuoyancyflux2d
31 public forcing_accumulate, fluxes_accumulate
32 public forcing_singlepointprint, mech_forcing_diags, forcing_diagnostics
33 public register_forcing_type_diags, allocate_forcing_type, deallocate_forcing_type
34 public copy_common_forcing_fields, allocate_mech_forcing, deallocate_mech_forcing
35 public set_derived_forcing_fields, copy_back_forcing_fields
36 public set_net_mass_forcing, get_net_mass_forcing
37 
38 ! A note on unit descriptions in comments: MOM6 uses units that can be rescaled for dimensional
39 ! consistency testing. These are noted in comments with units like Z, H, L, and T, along with
40 ! their mks counterparts with notation like "a velocity [Z T-1 ~> m s-1]". If the units
41 ! vary with the Boussinesq approximation, the Boussinesq variant is given first.
42 
43 !> Structure that contains pointers to the boundary forcing used to drive the
44 !! liquid ocean simulated by MOM.
45 !!
46 !! Data in this type is allocated in the module MOM_surface_forcing.F90, of which there
47 !! are three: solo, coupled, and ice-shelf. Alternatively, they are allocated in
48 !! MESO_surface_forcing.F90, which is a special case of solo_driver/MOM_surface_forcing.F90.
49 type, public :: forcing
50 
51  ! surface stress components and turbulent velocity scale
52  real, pointer, dimension(:,:) :: &
53  ustar => null(), & !< surface friction velocity scale [Z T-1 ~> m s-1].
54  ustar_gustless => null() !< surface friction velocity scale without any
55  !! any augmentation for gustiness [Z T-1 ~> m s-1].
56 
57  ! surface buoyancy force, used when temperature is not a state variable
58  real, pointer, dimension(:,:) :: &
59  buoy => null() !< buoyancy flux [L2 T-3 ~> m2 s-3]
60 
61  ! radiative heat fluxes into the ocean [W m-2]
62  real, pointer, dimension(:,:) :: &
63  sw => null(), & !< shortwave [W m-2]
64  sw_vis_dir => null(), & !< visible, direct shortwave [W m-2]
65  sw_vis_dif => null(), & !< visible, diffuse shortwave [W m-2]
66  sw_nir_dir => null(), & !< near-IR, direct shortwave [W m-2]
67  sw_nir_dif => null(), & !< near-IR, diffuse shortwave [W m-2]
68  lw => null() !< longwave [W m-2] (typically negative)
69 
70  ! turbulent heat fluxes into the ocean [W m-2]
71  real, pointer, dimension(:,:) :: &
72  latent => null(), & !< latent [W m-2] (typically < 0)
73  sens => null(), & !< sensible [W m-2] (typically negative)
74  seaice_melt_heat => null(), & !< sea ice and snow melt or formation [W m-2] (typically negative)
75  heat_added => null() !< additional heat flux from SST restoring or flux adjustments [W m-2]
76 
77  ! components of latent heat fluxes used for diagnostic purposes
78  real, pointer, dimension(:,:) :: &
79  latent_evap_diag => null(), & !< latent [W m-2] from evaporating liquid water (typically < 0)
80  latent_fprec_diag => null(), & !< latent [W m-2] from melting fprec (typically < 0)
81  latent_frunoff_diag => null() !< latent [W m-2] from melting frunoff (calving) (typically < 0)
82 
83  ! water mass fluxes into the ocean [kg m-2 s-1]; these fluxes impact the ocean mass
84  real, pointer, dimension(:,:) :: &
85  evap => null(), & !< (-1)*fresh water flux evaporated out of the ocean [kg m-2 s-1]
86  lprec => null(), & !< precipitating liquid water into the ocean [kg m-2 s-1]
87  fprec => null(), & !< precipitating frozen water into the ocean [kg m-2 s-1]
88  vprec => null(), & !< virtual liquid precip associated w/ SSS restoring [kg m-2 s-1]
89  lrunoff => null(), & !< liquid river runoff entering ocean [kg m-2 s-1]
90  frunoff => null(), & !< frozen river runoff (calving) entering ocean [kg m-2 s-1]
91  seaice_melt => null(), & !< snow/seaice melt (positive) or formation (negative) [kg m-2 s-1]
92  netmassin => null(), & !< Sum of water mass flux out of the ocean [kg m-2 s-1]
93  netmassout => null(), & !< Net water mass flux into of the ocean [kg m-2 s-1]
94  netsalt => null() !< Net salt entering the ocean [kgSalt m-2 s-1]
95 
96  ! heat associated with water crossing ocean surface
97  real, pointer, dimension(:,:) :: &
98  heat_content_cond => null(), & !< heat content associated with condensating water [W m-2]
99  heat_content_lprec => null(), & !< heat content associated with liquid >0 precip [W m-2] (diagnostic)
100  heat_content_icemelt => null(), & !< heat content associated with snow/seaice melt/formation [W/m^2]
101  heat_content_fprec => null(), & !< heat content associated with frozen precip [W m-2]
102  heat_content_vprec => null(), & !< heat content associated with virtual >0 precip [W m-2]
103  heat_content_lrunoff => null(), & !< heat content associated with liquid runoff [W m-2]
104  heat_content_frunoff => null(), & !< heat content associated with frozen runoff [W m-2]
105  heat_content_massout => null(), & !< heat content associated with mass leaving ocean [W m-2]
106  heat_content_massin => null() !< heat content associated with mass entering ocean [W m-2]
107 
108  ! salt mass flux (contributes to ocean mass only if non-Bouss )
109  real, pointer, dimension(:,:) :: &
110  salt_flux => null(), & !< net salt flux into the ocean [kgSalt m-2 s-1]
111  salt_flux_in => null(), & !< salt flux provided to the ocean from coupler [kgSalt m-2 s-1]
112  salt_flux_added => null() !< additional salt flux from restoring or flux adjustment before adjustment
113  !! to net zero [kgSalt m-2 s-1]
114 
115  ! applied surface pressure from other component models (e.g., atmos, sea ice, land ice)
116  real, pointer, dimension(:,:) :: p_surf_full => null()
117  !< Pressure at the top ocean interface [Pa].
118  !! if there is sea-ice, then p_surf_flux is at ice-ocean interface
119  real, pointer, dimension(:,:) :: p_surf => null()
120  !< Pressure at the top ocean interface [Pa] as used to drive the ocean model.
121  !! If p_surf is limited, p_surf may be smaller than p_surf_full, otherwise they are the same.
122  real, pointer, dimension(:,:) :: p_surf_ssh => null()
123  !< Pressure at the top ocean interface [Pa] that is used in corrections to the sea surface
124  !! height field that is passed back to the calling routines.
125  !! p_surf_SSH may point to p_surf or to p_surf_full.
126  logical :: accumulate_p_surf = .false. !< If true, the surface pressure due to the atmosphere
127  !! and various types of ice needs to be accumulated, and the
128  !! surface pressure explicitly reset to zero at the driver level
129  !! when appropriate.
130 
131  ! tide related inputs
132  real, pointer, dimension(:,:) :: &
133  tke_tidal => null(), & !< tidal energy source driving mixing in bottom boundary layer [W m-2]
134  ustar_tidal => null() !< tidal contribution to bottom ustar [Z T-1 ~> m s-1]
135 
136  ! iceberg related inputs
137  real, pointer, dimension(:,:) :: &
138  ustar_berg => null(), & !< iceberg contribution to top ustar [Z T-1 ~> m s-1].
139  area_berg => null(), & !< area of ocean surface covered by icebergs [m2 m-2]
140  mass_berg => null() !< mass of icebergs [kg m-2]
141 
142  ! land ice-shelf related inputs
143  real, pointer, dimension(:,:) :: ustar_shelf => null() !< Friction velocity under ice-shelves [Z T-1 ~> m s-1].
144  !! as computed by the ocean at the previous time step.
145  real, pointer, dimension(:,:) :: frac_shelf_h => null() !< Fractional ice shelf coverage of
146  !! h-cells, nondimensional from 0 to 1. This is only
147  !! associated if ice shelves are enabled, and are
148  !! exactly 0 away from shelves or on land.
149  real, pointer, dimension(:,:) :: iceshelf_melt => null() !< Ice shelf melt rate (positive)
150  !! or freezing (negative) [m year-1]
151 
152  ! Scalars set by surface forcing modules
153  real :: vprecglobaladj !< adjustment to restoring vprec to zero out global net [kg m-2 s-1]
154  real :: saltfluxglobaladj !< adjustment to restoring salt flux to zero out global net [kgSalt m-2 s-1]
155  real :: netfwglobaladj !< adjustment to net fresh water to zero out global net [kg m-2 s-1]
156  real :: vprecglobalscl !< scaling of restoring vprec to zero out global net ( -1..1 ) [nondim]
157  real :: saltfluxglobalscl !< scaling of restoring salt flux to zero out global net ( -1..1 ) [nondim]
158  real :: netfwglobalscl !< scaling of net fresh water to zero out global net ( -1..1 ) [nondim]
159 
160  logical :: fluxes_used = .true. !< If true, all of the heat, salt, and mass
161  !! fluxes have been applied to the ocean.
162  real :: dt_buoy_accum = -1.0 !< The amount of time over which the buoyancy fluxes
163  !! should be applied [s]. If negative, this forcing
164  !! type variable has not yet been inialized.
165 
166  real :: c_p !< heat capacity of seawater [J kg-1 degC-1].
167  !! C_p is is the same value as in thermovar_ptrs_type.
168 
169  ! passive tracer surface fluxes
170  type(coupler_2d_bc_type) :: tr_fluxes !< This structure contains arrays of
171  !! of named fields used for passive tracer fluxes.
172  !! All arrays in tr_fluxes use the coupler indexing, which has no halos.
173  !! This is not a convenient convention, but imposed on MOM6 by the coupler.
174 
175  ! For internal error tracking
176  integer :: num_msg = 0 !< Number of messages issued about excessive SW penetration
177  integer :: max_msg = 2 !< Maximum number of messages to issue about excessive SW penetration
178 
179 end type forcing
180 
181 !> Structure that contains pointers to the mechanical forcing at the surface
182 !! used to drive the liquid ocean simulated by MOM.
183 !! Data in this type is allocated in the module MOM_surface_forcing.F90,
184 !! of which there are three versions: solo, coupled, and ice-shelf.
185 type, public :: mech_forcing
186  ! surface stress components and turbulent velocity scale
187  real, pointer, dimension(:,:) :: &
188  taux => null(), & !< zonal wind stress [Pa]
189  tauy => null(), & !< meridional wind stress [Pa]
190  ustar => null(), & !< surface friction velocity scale [Z T-1 ~> m s-1].
191  net_mass_src => null() !< The net mass source to the ocean [kg m-2 s-1].
192 
193  ! applied surface pressure from other component models (e.g., atmos, sea ice, land ice)
194  real, pointer, dimension(:,:) :: p_surf_full => null()
195  !< Pressure at the top ocean interface [Pa].
196  !! if there is sea-ice, then p_surf_flux is at ice-ocean interface
197  real, pointer, dimension(:,:) :: p_surf => null()
198  !< Pressure at the top ocean interface [Pa] as used to drive the ocean model.
199  !! If p_surf is limited, p_surf may be smaller than p_surf_full, otherwise they are the same.
200  real, pointer, dimension(:,:) :: p_surf_ssh => null()
201  !< Pressure at the top ocean interface that is used in corrections to the sea surface
202  !! height field that is passed back to the calling routines.
203  !! p_surf_SSH may point to p_surf or to p_surf_full.
204 
205  ! iceberg related inputs
206  real, pointer, dimension(:,:) :: &
207  area_berg => null(), & !< fractional area of ocean surface covered by icebergs [m2 m-2]
208  mass_berg => null() !< mass of icebergs per unit ocean area [kg m-2]
209 
210  ! land ice-shelf related inputs
211  real, pointer, dimension(:,:) :: frac_shelf_u => null() !< Fractional ice shelf coverage of u-cells,
212  !! nondimensional from 0 to 1 [nondim]. This is only associated if ice shelves are enabled,
213  !! and is exactly 0 away from shelves or on land.
214  real, pointer, dimension(:,:) :: frac_shelf_v => null() !< Fractional ice shelf coverage of v-cells,
215  !! nondimensional from 0 to 1 [nondim]. This is only associated if ice shelves are enabled,
216  !! and is exactly 0 away from shelves or on land.
217  real, pointer, dimension(:,:) :: &
218  rigidity_ice_u => null(), & !< Depth-integrated lateral viscosity of ice shelves or sea ice at u-points [m3 s-1]
219  rigidity_ice_v => null() !< Depth-integrated lateral viscosity of ice shelves or sea ice at v-points [m3 s-1]
220  real :: dt_force_accum = -1.0 !< The amount of time over which the mechanical forcing fluxes
221  !! have been averaged [s].
222  logical :: net_mass_src_set = .false. !< If true, an estimate of net_mass_src has been provided.
223  logical :: accumulate_p_surf = .false. !< If true, the surface pressure due to the atmosphere
224  !! and various types of ice needs to be accumulated, and the
225  !! surface pressure explicitly reset to zero at the driver level
226  !! when appropriate.
227  logical :: accumulate_rigidity = .false. !< If true, the rigidity due to various types of
228  !! ice needs to be accumulated, and the rigidity explicitly
229  !! reset to zero at the driver level when appropriate.
230 
231  logical :: initialized = .false. !< This indicates whether the appropriate arrays have been initialized.
232 end type mech_forcing
233 
234 !> Structure that defines the id handles for the forcing type
235 type, public :: forcing_diags
236 
237  !>@{ Forcing diagnostic handles
238  ! mass flux diagnostic handles
239  integer :: id_prcme = -1, id_evap = -1
240  integer :: id_precip = -1, id_vprec = -1
241  integer :: id_lprec = -1, id_fprec = -1
242  integer :: id_lrunoff = -1, id_frunoff = -1
243  integer :: id_net_massout = -1, id_net_massin = -1
244  integer :: id_massout_flux = -1, id_massin_flux = -1
245  integer :: id_seaice_melt = -1
246 
247  ! global area integrated mass flux diagnostic handles
248  integer :: id_total_prcme = -1, id_total_evap = -1
249  integer :: id_total_precip = -1, id_total_vprec = -1
250  integer :: id_total_lprec = -1, id_total_fprec = -1
251  integer :: id_total_lrunoff = -1, id_total_frunoff = -1
252  integer :: id_total_net_massout = -1, id_total_net_massin = -1
253  integer :: id_total_seaice_melt = -1
254 
255  ! global area averaged mass flux diagnostic handles
256  integer :: id_prcme_ga = -1, id_evap_ga = -1
257  integer :: id_lprec_ga = -1, id_fprec_ga= -1
258  integer :: id_precip_ga = -1, id_vprec_ga= -1
259 
260  ! heat flux diagnostic handles
261  integer :: id_net_heat_coupler = -1, id_net_heat_surface = -1
262  integer :: id_sens = -1, id_lwlatsens = -1
263  integer :: id_sw = -1, id_lw = -1
264  integer :: id_sw_vis = -1, id_sw_nir = -1
265  integer :: id_lat_evap = -1, id_lat_frunoff = -1
266  integer :: id_lat = -1, id_lat_fprec = -1
267  integer :: id_heat_content_lrunoff= -1, id_heat_content_frunoff = -1
268  integer :: id_heat_content_lprec = -1, id_heat_content_fprec = -1
269  integer :: id_heat_content_cond = -1, id_heat_content_surfwater= -1
270  integer :: id_heat_content_vprec = -1, id_heat_content_massout = -1
271  integer :: id_heat_added = -1, id_heat_content_massin = -1
272  integer :: id_hfrainds = -1, id_hfrunoffds = -1
273  integer :: id_seaice_melt_heat = -1, id_heat_content_icemelt = -1
274 
275  ! global area integrated heat flux diagnostic handles
276  integer :: id_total_net_heat_coupler = -1, id_total_net_heat_surface = -1
277  integer :: id_total_sens = -1, id_total_lwlatsens = -1
278  integer :: id_total_sw = -1, id_total_lw = -1
279  integer :: id_total_lat_evap = -1, id_total_lat_frunoff = -1
280  integer :: id_total_lat = -1, id_total_lat_fprec = -1
281  integer :: id_total_heat_content_lrunoff= -1, id_total_heat_content_frunoff = -1
282  integer :: id_total_heat_content_lprec = -1, id_total_heat_content_fprec = -1
283  integer :: id_total_heat_content_cond = -1, id_total_heat_content_surfwater= -1
284  integer :: id_total_heat_content_vprec = -1, id_total_heat_content_massout = -1
285  integer :: id_total_heat_added = -1, id_total_heat_content_massin = -1
286  integer :: id_total_seaice_melt_heat = -1, id_total_heat_content_icemelt = -1
287 
288  ! global area averaged heat flux diagnostic handles
289  integer :: id_net_heat_coupler_ga = -1, id_net_heat_surface_ga = -1
290  integer :: id_sens_ga = -1, id_lwlatsens_ga = -1
291  integer :: id_sw_ga = -1, id_lw_ga = -1
292  integer :: id_lat_ga = -1
293 
294  ! salt flux diagnostic handles
295  integer :: id_saltflux = -1
296  integer :: id_saltfluxin = -1
297  integer :: id_saltfluxadded = -1
298 
299  integer :: id_total_saltflux = -1
300  integer :: id_total_saltfluxin = -1
301  integer :: id_total_saltfluxadded = -1
302 
303  integer :: id_vprecglobaladj = -1
304  integer :: id_vprecglobalscl = -1
305  integer :: id_saltfluxglobaladj = -1
306  integer :: id_saltfluxglobalscl = -1
307  integer :: id_netfwglobaladj = -1
308  integer :: id_netfwglobalscl = -1
309 
310  ! momentum flux and forcing diagnostic handles
311  integer :: id_taux = -1
312  integer :: id_tauy = -1
313  integer :: id_ustar = -1
314 
315  integer :: id_psurf = -1
316  integer :: id_tke_tidal = -1
317  integer :: id_buoy = -1
318 
319  ! iceberg diagnostic handles
320  integer :: id_ustar_berg = -1
321  integer :: id_area_berg = -1
322  integer :: id_mass_berg = -1
323 
324  ! Iceberg + Ice shelf diagnostic handles
325  integer :: id_ustar_ice_cover = -1
326  integer :: id_frac_ice_cover = -1
327  !!@}
328 
329  integer :: id_clock_forcing = -1 !< CPU clock id
330 
331 end type forcing_diags
332 
333 contains
334 
335 !> This subroutine extracts fluxes from the surface fluxes type. It works on a j-row
336 !! for optimization purposes. The 2d (i,j) wrapper is the next subroutine below.
337 !! This routine multiplies fluxes by dt, so that the result is an accumulation of fluxes
338 !! over a time step.
339 subroutine extractfluxes1d(G, GV, fluxes, optics, nsw, j, dt, &
340  FluxRescaleDepth, useRiverHeatContent, useCalvingHeatContent, &
341  h, T, netMassInOut, netMassOut, net_heat, net_salt, pen_SW_bnd, tv, &
342  aggregate_FW, nonpenSW, netmassInOut_rate,net_Heat_Rate, &
343  net_salt_rate, pen_sw_bnd_Rate, skip_diags)
344 
345  type(ocean_grid_type), intent(in) :: g !< ocean grid structure
346  type(verticalgrid_type), intent(in) :: gv !< ocean vertical grid structure
347  type(forcing), intent(inout) :: fluxes !< structure containing pointers to possible
348  !! forcing fields. NULL unused fields.
349  type(optics_type), pointer :: optics !< pointer to optics
350  integer, intent(in) :: nsw !< number of bands of penetrating SW
351  integer, intent(in) :: j !< j-index to work on
352  real, intent(in) :: dt !< time step [s]
353  real, intent(in) :: fluxrescaledepth !< min ocean depth before fluxes
354  !! are scaled away [H ~> m or kg m-2]
355  logical, intent(in) :: useriverheatcontent !< logical for river heat content
356  logical, intent(in) :: usecalvingheatcontent !< logical for calving heat content
357  real, dimension(SZI_(G),SZK_(G)), &
358  intent(in) :: h !< layer thickness [H ~> m or kg m-2]
359  real, dimension(SZI_(G),SZK_(G)), &
360  intent(in) :: t !< layer temperatures [degC]
361  real, dimension(SZI_(G)), intent(out) :: netmassinout !< net mass flux (non-Bouss) or volume flux
362  !! (if Bouss) of water in/out of ocean over
363  !! a time step [H ~> m or kg m-2]
364  real, dimension(SZI_(G)), intent(out) :: netmassout !< net mass flux (non-Bouss) or volume flux
365  !! (if Bouss) of water leaving ocean surface
366  !! over a time step [H ~> m or kg m-2].
367  !! netMassOut < 0 means mass leaves ocean.
368  real, dimension(SZI_(G)), intent(out) :: net_heat !< net heat at the surface accumulated over a
369  !! time step for coupler + restoring.
370  !! Exclude two terms from net_heat:
371  !! (1) downwelling (penetrative) SW,
372  !! (2) evaporation heat content,
373  !! (since do not yet know evap temperature).
374  !! [degC H ~> degC m or degC kg m-2].
375  real, dimension(SZI_(G)), intent(out) :: net_salt !< surface salt flux into the ocean
376  !! accumulated over a time step
377  !! [ppt H ~> ppt m or ppt kg m-2].
378  real, dimension(max(1,nsw),G%isd:G%ied), intent(out) :: pen_sw_bnd !< penetrating SW flux, split into bands.
379  !! [degC H ~> degC m or degC kg m-2]
380  !! and array size nsw x SZI_(G), where
381  !! nsw=number of SW bands in pen_SW_bnd.
382  !! This heat flux is not part of net_heat.
383  type(thermo_var_ptrs), intent(inout) :: tv !< structure containing pointers to available
384  !! thermodynamic fields. Used to keep
385  !! track of the heat flux associated with net
386  !! mass fluxes into the ocean.
387  logical, intent(in) :: aggregate_fw !< For determining how to aggregate forcing.
388  real, dimension(SZI_(G)), &
389  optional, intent(out) :: nonpensw !< Non-penetrating SW used in net_heat
390  !! [degC H ~> degC m or degC kg m-2].
391  !! Summed over SW bands when diagnosing nonpenSW.
392  real, dimension(SZI_(G)), &
393  optional, intent(out) :: net_heat_rate !< Rate of net surface heating
394  !! [degC H s-1 ~> degC m s-1 or degC kg m-2 s-1].
395  real, dimension(SZI_(G)), &
396  optional, intent(out) :: net_salt_rate !< Surface salt flux into the ocean
397  !! [ppt H s-1 ~> ppt m s-1 or ppt kg m-2 s-1].
398  real, dimension(SZI_(G)), &
399  optional, intent(out) :: netmassinout_rate !< Rate of net mass flux into the ocean
400  !! [H s-1 ~> m s-1 or kg m-2 s-1].
401  real, dimension(max(1,nsw),G%isd:G%ied), &
402  optional, intent(out) :: pen_sw_bnd_rate !< Rate of penetrative shortwave heating
403  !! [degC H s-1 ~> degC m s-1 or degC kg m-2 s-1].
404  logical, optional, intent(in) :: skip_diags !< If present and true, skip calculating diagnostics
405 
406  ! local
407  real :: htot(szi_(g)) ! total ocean depth [H ~> m or kg m-2]
408  real :: pen_sw_tot(szi_(g)) ! sum across all bands of Pen_SW [degC H ~> degC m or degC kg m-2].
409  real :: pen_sw_tot_rate(szi_(g)) ! Similar but sum but as a rate (no dt in calculation)
410  real :: ih_limit ! inverse depth at which surface fluxes start to be limited [H-1 ~> m-1 or m2 kg-1]
411  real :: scale ! scale scales away fluxes if depth < FluxRescaleDepth
412  real :: j_m2_to_h ! converts J/m^2 to H units (m for Bouss and kg/m^2 for non-Bouss)
413  real :: irho0 ! 1.0 / Rho0 [m3 kg-1]
414  real :: i_cp ! 1.0 / C_p [kg decC J-1]
415  logical :: calculate_diags ! Indicate to calculate/update diagnostic arrays
416  character(len=200) :: mesg
417  integer :: is, ie, nz, i, k, n
418 
419  logical :: do_nhr, do_nsr, do_nmior, do_pswbr
420 
421  !BGR-Jul 5,2017{
422  ! Initializes/sets logicals if 'rates' are requested
423  ! These factors are required for legacy reasons
424  ! and therefore computed only when optional outputs are requested
425  do_nhr = .false.
426  do_nsr = .false.
427  do_nmior = .false.
428  do_pswbr = .false.
429  if (present(net_heat_rate)) do_nhr = .true.
430  if (present(net_salt_rate)) do_nsr = .true.
431  if (present(netmassinout_rate)) do_nmior = .true.
432  if (present(pen_sw_bnd_rate)) do_pswbr = .true.
433  !}BGR
434 
435  ih_limit = 1.0 / fluxrescaledepth
436  irho0 = 1.0 / gv%Rho0
437  i_cp = 1.0 / fluxes%C_p
438  j_m2_to_h = 1.0 / (gv%H_to_kg_m2 * fluxes%C_p)
439 
440  is = g%isc ; ie = g%iec ; nz = g%ke
441 
442  calculate_diags = .true.
443  if (present(skip_diags)) calculate_diags = .not. skip_diags
444 
445  ! error checking
446 
447  if (nsw > 0) then ; if (nsw /= optics_nbands(optics)) call mom_error(warning, &
448  "mismatch in the number of bands of shortwave radiation in MOM_forcing_type extract_fluxes.")
449  endif
450 
451  if (.not.associated(fluxes%sw)) call mom_error(fatal, &
452  "MOM_forcing_type extractFluxes1d: fluxes%sw is not associated.")
453 
454  if (.not.associated(fluxes%lw)) call mom_error(fatal, &
455  "MOM_forcing_type extractFluxes1d: fluxes%lw is not associated.")
456 
457  if (.not.associated(fluxes%latent)) call mom_error(fatal, &
458  "MOM_forcing_type extractFluxes1d: fluxes%latent is not associated.")
459 
460  if (.not.associated(fluxes%sens)) call mom_error(fatal, &
461  "MOM_forcing_type extractFluxes1d: fluxes%sens is not associated.")
462 
463  if (.not.associated(fluxes%evap)) call mom_error(fatal, &
464  "MOM_forcing_type extractFluxes1d: No evaporation defined.")
465 
466  if (.not.associated(fluxes%vprec)) call mom_error(fatal, &
467  "MOM_forcing_type extractFluxes1d: fluxes%vprec not defined.")
468 
469  if ((.not.associated(fluxes%lprec)) .or. &
470  (.not.associated(fluxes%fprec))) call mom_error(fatal, &
471  "MOM_forcing_type extractFluxes1d: No precipitation defined.")
472 
473  do i=is,ie ; htot(i) = h(i,1) ; enddo
474  do k=2,nz ; do i=is,ie ; htot(i) = htot(i) + h(i,k) ; enddo ; enddo
475 
476  if (nsw >= 1) then
477  call extract_optics_slice(optics, j, g, gv, pensw_top=pen_sw_bnd) !, penSW_scale=J_m2_to_H*dt
478  if (do_pswbr) call extract_optics_slice(optics, j, g, gv, pensw_top=pen_sw_bnd_rate) !, penSW_scale=J_m2_to_H
479  endif
480 
481  do i=is,ie
482 
483  scale = 1.0
484  if (htot(i)*ih_limit < 1.0) scale = htot(i)*ih_limit
485 
486  ! Convert the penetrating shortwave forcing to (K * H) and reduce fluxes for shallow depths.
487  ! (H=m for Bouss, H=kg/m2 for non-Bouss)
488  pen_sw_tot(i) = 0.0
489  if (nsw >= 1) then
490  do n=1,nsw
491  pen_sw_bnd(n,i) = j_m2_to_h*scale*dt * max(0.0, pen_sw_bnd(n,i))
492  pen_sw_tot(i) = pen_sw_tot(i) + pen_sw_bnd(n,i)
493  enddo
494  else
495  pen_sw_bnd(1,i) = 0.0
496  endif
497 
498  if (do_pswbr) then ! Repeat the above code w/ dt=1s for legacy reasons
499  pen_sw_tot_rate(i) = 0.0
500  if (nsw >= 1) then
501  do n=1,nsw
502  pen_sw_bnd_rate(n,i) = j_m2_to_h*scale * max(0.0, pen_sw_bnd_rate(n,i))
503  pen_sw_tot_rate(i) = pen_sw_tot_rate(i) + pen_sw_bnd_rate(n,i)
504  enddo
505  else
506  pen_sw_bnd_rate(1,i) = 0.0
507  endif
508  endif
509 
510  ! net volume/mass of liquid and solid passing through surface boundary fluxes
511  netmassinout(i) = dt * (scale * (((((( fluxes%lprec(i,j) &
512  + fluxes%fprec(i,j) ) &
513  + fluxes%evap(i,j) ) &
514  + fluxes%lrunoff(i,j) ) &
515  + fluxes%vprec(i,j) ) &
516  + fluxes%seaice_melt(i,j)) &
517  + fluxes%frunoff(i,j) ))
518 
519  if (do_nmior) then ! Repeat the above code w/ dt=1s for legacy reasons
520  netmassinout_rate(i) = (scale * (((((( fluxes%lprec(i,j) &
521  + fluxes%fprec(i,j) ) &
522  + fluxes%evap(i,j) ) &
523  + fluxes%lrunoff(i,j) ) &
524  + fluxes%vprec(i,j) ) &
525  + fluxes%seaice_melt(i,j)) &
526  + fluxes%frunoff(i,j) ))
527  endif
528 
529  ! smg:
530  ! for non-Bouss, we add/remove salt mass to total ocean mass. to conserve
531  ! total salt mass ocean+ice, the sea ice model must lose mass when salt mass
532  ! is added to the ocean, which may still need to be coded. Not that the units
533  ! of netMassInOut are still kg_m2, so no conversion to H should occur yet.
534  if (.not.gv%Boussinesq .and. associated(fluxes%salt_flux)) then
535  netmassinout(i) = netmassinout(i) + dt * (scale * fluxes%salt_flux(i,j))
536  if (do_nmior) netmassinout_rate(i) = netmassinout_rate(i) + (scale * fluxes%salt_flux(i,j))
537  endif
538 
539  ! net volume/mass of water leaving the ocean.
540  ! check that fluxes are < 0, which means mass is indeed leaving.
541  netmassout(i) = 0.0
542 
543  ! evap > 0 means condensating water is added into ocean.
544  ! evap < 0 means evaporation of water from the ocean, in
545  ! which case heat_content_evap is computed in MOM_diabatic_driver.F90
546  if (fluxes%evap(i,j) < 0.0) then
547  netmassout(i) = netmassout(i) + fluxes%evap(i,j)
548  ! if (associated(fluxes%heat_content_cond)) fluxes%heat_content_cond(i,j) = 0.0 !??? --AJA
549  endif
550 
551  ! lprec < 0 means sea ice formation taking water from the ocean.
552  ! smg: we should split the ice melt/formation from the lprec
553  if (fluxes%lprec(i,j) < 0.0) then
554  netmassout(i) = netmassout(i) + fluxes%lprec(i,j)
555  endif
556 
557  ! seaice_melt < 0 means sea ice formation taking water from the ocean.
558  if (fluxes%seaice_melt(i,j) < 0.0) then
559  netmassout(i) = netmassout(i) + fluxes%seaice_melt(i,j)
560  endif
561 
562  ! vprec < 0 means virtual evaporation arising from surface salinity restoring,
563  ! in which case heat_content_vprec is computed in MOM_diabatic_driver.F90.
564  if (fluxes%vprec(i,j) < 0.0) then
565  netmassout(i) = netmassout(i) + fluxes%vprec(i,j)
566  endif
567  netmassout(i) = dt * scale * netmassout(i)
568 
569  ! convert to H units (Bouss=meter or non-Bouss=kg/m^2)
570  netmassinout(i) = gv%kg_m2_to_H * netmassinout(i)
571  if (do_nmior) netmassinout_rate(i) = gv%kg_m2_to_H * netmassinout_rate(i)
572  netmassout(i) = gv%kg_m2_to_H * netmassout(i)
573 
574  ! surface heat fluxes from radiation and turbulent fluxes (K * H)
575  ! (H=m for Bouss, H=kg/m2 for non-Bouss)
576 
577  ! CIME provides heat flux from snow&ice melt (seaice_melt_heat), so this is added below
578  if (associated(fluxes%seaice_melt_heat)) then
579  net_heat(i) = scale * dt * j_m2_to_h * &
580  ( fluxes%sw(i,j) + ((fluxes%lw(i,j) + fluxes%latent(i,j)) + fluxes%sens(i,j) + &
581  fluxes%seaice_melt_heat(i,j)) )
582  !Repeats above code w/ dt=1. for legacy reason
583  if (do_nhr) net_heat_rate(i) = scale * j_m2_to_h * &
584  ( fluxes%sw(i,j) + ((fluxes%lw(i,j) + fluxes%latent(i,j)) + fluxes%sens(i,j) + &
585  fluxes%seaice_melt_heat(i,j)))
586  else
587  net_heat(i) = scale * dt * j_m2_to_h * &
588  ( fluxes%sw(i,j) + ((fluxes%lw(i,j) + fluxes%latent(i,j)) + fluxes%sens(i,j)) )
589  !Repeats above code w/ dt=1. for legacy reason
590  if (do_nhr) net_heat_rate(i) = scale * j_m2_to_h * &
591  ( fluxes%sw(i,j) + ((fluxes%lw(i,j) + fluxes%latent(i,j)) + fluxes%sens(i,j)) )
592  endif
593 
594  ! Add heat flux from surface damping (restoring) (K * H) or flux adjustments.
595  if (associated(fluxes%heat_added)) then
596  net_heat(i) = net_heat(i) + (scale * (dt * j_m2_to_h)) * fluxes%heat_added(i,j)
597  if (do_nhr) net_heat_rate(i) = net_heat_rate(i) + (scale * (j_m2_to_h)) * fluxes%heat_added(i,j)
598  endif
599 
600  ! Add explicit heat flux for runoff (which is part of the ice-ocean boundary
601  ! flux type). Runoff is otherwise added with a temperature of SST.
602  if (useriverheatcontent) then
603  ! remove lrunoff*SST here, to counteract its addition elsewhere
604  net_heat(i) = (net_heat(i) + (scale*(dt*j_m2_to_h)) * fluxes%heat_content_lrunoff(i,j)) - &
605  (gv%kg_m2_to_H * (scale * dt)) * fluxes%lrunoff(i,j) * t(i,1)
606  !BGR-Jul 5, 2017{
607  !Intentionally neglect the following contribution to rate for legacy reasons.
608  !if (do_NHR) net_heat_rate(i) = (net_heat_rate(i) + (scale*(J_m2_to_H)) * fluxes%heat_content_lrunoff(i,j)) - &
609  ! (GV%kg_m2_to_H * (scale)) * fluxes%lrunoff(i,j) * T(i,1)
610  !}BGR
611  if (calculate_diags .and. associated(tv%TempxPmE)) then
612  tv%TempxPmE(i,j) = tv%TempxPmE(i,j) + (scale * dt) * &
613  (i_cp*fluxes%heat_content_lrunoff(i,j) - fluxes%lrunoff(i,j)*t(i,1))
614  endif
615  endif
616 
617  ! Add explicit heat flux for calving (which is part of the ice-ocean boundary
618  ! flux type). Calving is otherwise added with a temperature of SST.
619  if (usecalvingheatcontent) then
620  ! remove frunoff*SST here, to counteract its addition elsewhere
621  net_heat(i) = net_heat(i) + (scale*(dt*j_m2_to_h)) * fluxes%heat_content_frunoff(i,j) - &
622  (gv%kg_m2_to_H * (scale * dt)) * fluxes%frunoff(i,j) * t(i,1)
623  !BGR-Jul 5, 2017{
624  !Intentionally neglect the following contribution to rate for legacy reasons.
625 ! if (do_NHR) net_heat_rate(i) = net_heat_rate(i) + (scale*(J_m2_to_H)) * fluxes%heat_content_frunoff(i,j) - &
626 ! (GV%kg_m2_to_H * (scale)) * fluxes%frunoff(i,j) * T(i,1)
627  !}BGR
628  if (calculate_diags .and. associated(tv%TempxPmE)) then
629  tv%TempxPmE(i,j) = tv%TempxPmE(i,j) + (scale * dt) * &
630  (i_cp*fluxes%heat_content_frunoff(i,j) - fluxes%frunoff(i,j)*t(i,1))
631  endif
632  endif
633 
634 ! smg: new code
635  ! add heat from all terms that may add mass to the ocean (K * H).
636  ! if evap, lprec, or vprec < 0, then compute their heat content
637  ! inside MOM_diabatic_driver.F90 and fill in fluxes%heat_content_massout.
638  ! we do so since we do not here know the temperature
639  ! of water leaving the ocean, as it could be leaving from more than
640  ! one layer of the upper ocean in the case of very thin layers.
641  ! When evap, lprec, or vprec > 0, then we know their heat content here
642  ! via settings from inside of the appropriate config_src driver files.
643 ! if (associated(fluxes%heat_content_lprec)) then
644 ! net_heat(i) = net_heat(i) + scale * dt * J_m2_to_H * &
645 ! (fluxes%heat_content_lprec(i,j) + (fluxes%heat_content_fprec(i,j) + &
646 ! (fluxes%heat_content_lrunoff(i,j) + (fluxes%heat_content_frunoff(i,j) + &
647 ! (fluxes%heat_content_cond(i,j) + fluxes%heat_content_vprec(i,j))))))
648 ! endif
649 
650  if (fluxes%num_msg < fluxes%max_msg) then
651  if (pen_sw_tot(i) > 1.000001*j_m2_to_h*scale*dt*fluxes%sw(i,j)) then
652  fluxes%num_msg = fluxes%num_msg + 1
653  write(mesg,'("Penetrating shortwave of ",1pe17.10, &
654  &" exceeds total shortwave of ",1pe17.10,&
655  &" at ",1pg11.4,"E, "1pg11.4,"N.")') &
656  pen_sw_tot(i),j_m2_to_h*scale*dt*fluxes%sw(i,j),&
657  g%geoLonT(i,j),g%geoLatT(i,j)
658  call mom_error(warning,mesg)
659  endif
660  endif
661 
662  ! remove penetrative portion of the SW that is NOT absorbed within a
663  ! tiny layer at the top of the ocean.
664  net_heat(i) = net_heat(i) - pen_sw_tot(i)
665  !Repeat above code for 'rate' term
666  if (do_nhr) net_heat_rate(i) = net_heat_rate(i) - pen_sw_tot_rate(i)
667 
668  ! diagnose non-downwelling SW
669  if (present(nonpensw)) then
670  nonpensw(i) = scale * dt * j_m2_to_h * fluxes%sw(i,j) - pen_sw_tot(i)
671  endif
672 
673  ! Salt fluxes
674  net_salt(i) = 0.0
675  if (do_nsr) net_salt_rate(i) = 0.0
676  ! Convert salt_flux from kg (salt)/(m^2 * s) to
677  ! Boussinesq: (ppt * m)
678  ! non-Bouss: (g/m^2)
679  if (associated(fluxes%salt_flux)) then
680  net_salt(i) = (scale * dt * (1000.0 * fluxes%salt_flux(i,j))) * gv%kg_m2_to_H
681  !Repeat above code for 'rate' term
682  if (do_nsr) net_salt_rate(i) = (scale * 1. * (1000.0 * fluxes%salt_flux(i,j))) * gv%kg_m2_to_H
683  endif
684 
685  ! Diagnostics follow...
686  if (calculate_diags) then
687 
688  ! Store Net_salt for unknown reason?
689  if (associated(fluxes%salt_flux)) then
690  if (calculate_diags) fluxes%netSalt(i,j) = net_salt(i)
691  endif
692 
693  ! Initialize heat_content_massin that is diagnosed in mixedlayer_convection or
694  ! applyBoundaryFluxes such that the meaning is as the sum of all incoming components.
695  if (associated(fluxes%heat_content_massin)) then
696  if (aggregate_fw) then
697  if (netmassinout(i) > 0.0) then ! net is "in"
698  fluxes%heat_content_massin(i,j) = -fluxes%C_p * netmassout(i) * t(i,1) * gv%H_to_kg_m2 / dt
699  else ! net is "out"
700  fluxes%heat_content_massin(i,j) = fluxes%C_p * ( netmassinout(i) - netmassout(i) ) * &
701  t(i,1) * gv%H_to_kg_m2 / dt
702  endif
703  else
704  fluxes%heat_content_massin(i,j) = 0.
705  endif
706  endif
707 
708  ! Initialize heat_content_massout that is diagnosed in mixedlayer_convection or
709  ! applyBoundaryFluxes such that the meaning is as the sum of all outgoing components.
710  if (associated(fluxes%heat_content_massout)) then
711  if (aggregate_fw) then
712  if (netmassinout(i) > 0.0) then ! net is "in"
713  fluxes%heat_content_massout(i,j) = fluxes%C_p * netmassout(i) * t(i,1) * gv%H_to_kg_m2 / dt
714  else ! net is "out"
715  fluxes%heat_content_massout(i,j) = -fluxes%C_p * ( netmassinout(i) - netmassout(i) ) * &
716  t(i,1) * gv%H_to_kg_m2 / dt
717  endif
718  else
719  fluxes%heat_content_massout(i,j) = 0.0
720  endif
721  endif
722 
723  ! smg: we should remove sea ice melt from lprec!!!
724  ! fluxes%lprec > 0 means ocean gains mass via liquid precipitation and/or sea ice melt.
725  ! When atmosphere does not provide heat of this precipitation, the ocean assumes
726  ! it enters the ocean at the SST.
727  ! fluxes%lprec < 0 means ocean loses mass via sea ice formation. As we do not yet know
728  ! the layer at which this mass is removed, we cannot compute it heat content. We must
729  ! wait until MOM_diabatic_driver.F90.
730  if (associated(fluxes%heat_content_lprec)) then
731  if (fluxes%lprec(i,j) > 0.0) then
732  fluxes%heat_content_lprec(i,j) = fluxes%C_p*fluxes%lprec(i,j)*t(i,1)
733  else
734  fluxes%heat_content_lprec(i,j) = 0.0
735  endif
736  endif
737 
738  ! fprec SHOULD enter ocean at 0degC if atmos model does not provide fprec heat content.
739  ! However, we need to adjust netHeat above to reflect the difference between 0decC and SST
740  ! and until we do so fprec is treated like lprec and enters at SST. -AJA
741  if (associated(fluxes%heat_content_fprec)) then
742  if (fluxes%fprec(i,j) > 0.0) then
743  fluxes%heat_content_fprec(i,j) = fluxes%C_p*fluxes%fprec(i,j)*t(i,1)
744  else
745  fluxes%heat_content_fprec(i,j) = 0.0
746  endif
747  endif
748 
749  ! Following lprec and fprec, water flux due to sea ice melt (seaice_melt) enters at SST - GMM
750  if (associated(fluxes%heat_content_icemelt)) then
751  if (fluxes%seaice_melt(i,j) > 0.0) then
752  fluxes%heat_content_icemelt(i,j) = fluxes%C_p*fluxes%seaice_melt(i,j)*t(i,1)
753  else
754  fluxes%heat_content_icemelt(i,j) = 0.0
755  endif
756  endif
757 
758  ! virtual precip associated with salinity restoring
759  ! vprec > 0 means add water to ocean, assumed to be at SST
760  ! vprec < 0 means remove water from ocean; set heat_content_vprec in MOM_diabatic_driver.F90
761  if (associated(fluxes%heat_content_vprec)) then
762  if (fluxes%vprec(i,j) > 0.0) then
763  fluxes%heat_content_vprec(i,j) = fluxes%C_p*fluxes%vprec(i,j)*t(i,1)
764  else
765  fluxes%heat_content_vprec(i,j) = 0.0
766  endif
767  endif
768 
769  ! fluxes%evap < 0 means ocean loses mass due to evaporation.
770  ! Evaporation leaves ocean surface at a temperature that has yet to be determined,
771  ! since we do not know the precise layer that the water evaporates. We therefore
772  ! compute fluxes%heat_content_massout at the relevant point inside MOM_diabatic_driver.F90.
773  ! fluxes%evap > 0 means ocean gains moisture via condensation.
774  ! Condensation is assumed to drop into the ocean at the SST, just like lprec.
775  if (associated(fluxes%heat_content_cond)) then
776  if (fluxes%evap(i,j) > 0.0) then
777  fluxes%heat_content_cond(i,j) = fluxes%C_p*fluxes%evap(i,j)*t(i,1)
778  else
779  fluxes%heat_content_cond(i,j) = 0.0
780  endif
781  endif
782 
783  ! Liquid runoff enters ocean at SST if land model does not provide runoff heat content.
784  if (.not. useriverheatcontent) then
785  if (associated(fluxes%lrunoff) .and. associated(fluxes%heat_content_lrunoff)) then
786  fluxes%heat_content_lrunoff(i,j) = fluxes%C_p*fluxes%lrunoff(i,j)*t(i,1)
787  endif
788  endif
789 
790  ! Icebergs enter ocean at SST if land model does not provide calving heat content.
791  if (.not. usecalvingheatcontent) then
792  if (associated(fluxes%frunoff) .and. associated(fluxes%heat_content_frunoff)) then
793  fluxes%heat_content_frunoff(i,j) = fluxes%C_p*fluxes%frunoff(i,j)*t(i,1)
794  endif
795  endif
796 
797  endif ! calculate_diags
798 
799  enddo ! i-loop
800 
801 end subroutine extractfluxes1d
802 
803 
804 !> 2d wrapper for 1d extract fluxes from surface fluxes type.
805 !! This subroutine extracts fluxes from the surface fluxes type. It multiplies the
806 !! fluxes by dt, so that the result is an accumulation of the fluxes over a time step.
807 subroutine extractfluxes2d(G, GV, fluxes, optics, nsw, dt, FluxRescaleDepth, &
808  useRiverHeatContent, useCalvingHeatContent, h, T, &
809  netMassInOut, netMassOut, net_heat, Net_salt, Pen_SW_bnd, tv, &
810  aggregate_FW)
811 
812  type(ocean_grid_type), intent(in) :: g !< ocean grid structure
813  type(verticalgrid_type), intent(in) :: gv !< ocean vertical grid structure
814  type(forcing), intent(inout) :: fluxes !< structure containing pointers to forcing.
815  type(optics_type), pointer :: optics !< pointer to optics
816  integer, intent(in) :: nsw !< number of bands of penetrating SW
817  real, intent(in) :: dt !< time step [s]
818  real, intent(in) :: fluxrescaledepth !< min ocean depth before fluxes
819  !! are scaled away [H ~> m or kg m-2]
820  logical, intent(in) :: useriverheatcontent !< logical for river heat content
821  logical, intent(in) :: usecalvingheatcontent !< logical for calving heat content
822  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
823  intent(in) :: h !< layer thickness [H ~> m or kg m-2]
824  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
825  intent(in) :: t !< layer temperatures [degC]
826  real, dimension(SZI_(G),SZJ_(G)), intent(out) :: netmassinout !< net mass flux (non-Bouss) or volume flux
827  !! (if Bouss) of water in/out of ocean over
828  !! a time step [H ~> m or kg m-2]
829  real, dimension(SZI_(G),SZJ_(G)), intent(out) :: netmassout !< net mass flux (non-Bouss) or volume flux
830  !! (if Bouss) of water leaving ocean surface
831  !! over a time step [H ~> m or kg m-2].
832  real, dimension(SZI_(G),SZJ_(G)), intent(out) :: net_heat !< net heat at the surface accumulated over a
833  !! time step associated with coupler + restore.
834  !! Exclude two terms from net_heat:
835  !! (1) downwelling (penetrative) SW,
836  !! (2) evaporation heat content,
837  !! (since do not yet know temperature of evap).
838  !! [degC H ~> degC m or degC kg m-2]
839  real, dimension(SZI_(G),SZJ_(G)), intent(out) :: net_salt !< surface salt flux into the ocean accumulated
840  !! over a time step [ppt H ~> ppt m or ppt kg m-2]
841  real, dimension(max(1,nsw),G%isd:G%ied,G%jsd:G%jed), intent(out) :: pen_sw_bnd !< penetrating SW flux, by frequency
842  !! band [degC H ~> degC m or degC kg m-2] with array
843  !! size nsw x SZI_(G), where nsw=number of SW bands
844  !! in pen_SW_bnd. This heat flux is not in net_heat.
845  type(thermo_var_ptrs), intent(inout) :: tv !< structure containing pointers to available
846  !! thermodynamic fields. Here it is used to keep
847  !! track of the heat flux associated with net
848  !! mass fluxes into the ocean.
849  logical, intent(in) :: aggregate_fw !< For determining how to aggregate the forcing.
850 
851  integer :: j
852 !$OMP parallel do default(none) shared(G, GV, fluxes, optics, nsw,dt,FluxRescaleDepth, &
853 !$OMP useRiverHeatContent, useCalvingHeatContent, &
854 !$OMP h,T,netMassInOut,netMassOut,Net_heat,Net_salt,Pen_SW_bnd,tv, &
855 !$OMP aggregate_FW)
856  do j=g%jsc, g%jec
857  call extractfluxes1d(g, gv, fluxes, optics, nsw, j, dt, &
858  fluxrescaledepth, useriverheatcontent, usecalvingheatcontent,&
859  h(:,j,:), t(:,j,:), netmassinout(:,j), netmassout(:,j), &
860  net_heat(:,j), net_salt(:,j), pen_sw_bnd(:,:,j), tv, aggregate_fw)
861  enddo
862 
863 end subroutine extractfluxes2d
864 
865 
866 !> This routine calculates surface buoyancy flux by adding up the heat, FW & salt fluxes.
867 !! These are actual fluxes, with units of stuff per time. Setting dt=1 in the call to
868 !! extractFluxes routine allows us to get "stuf per time" rather than the time integrated
869 !! fluxes needed in other routines that call extractFluxes.
870 subroutine calculatebuoyancyflux1d(G, GV, US, fluxes, optics, nsw, h, Temp, Salt, tv, j, &
871  buoyancyFlux, netHeatMinusSW, netSalt, skip_diags)
872  type(ocean_grid_type), intent(in) :: g !< ocean grid
873  type(verticalgrid_type), intent(in) :: gv !< ocean vertical grid structure
874  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
875  type(forcing), intent(inout) :: fluxes !< surface fluxes
876  type(optics_type), pointer :: optics !< penetrating SW optics
877  integer, intent(in) :: nsw !< The number of frequency bands of
878  !! penetrating shortwave radiation
879  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< layer thickness [H ~> m or kg m-2]
880  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: temp !< prognostic temp [degC]
881  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: salt !< salinity [ppt]
882  type(thermo_var_ptrs), intent(inout) :: tv !< thermodynamics type
883  integer, intent(in) :: j !< j-row to work on
884  real, dimension(SZI_(G),SZK_(G)+1), intent(inout) :: buoyancyflux !< buoyancy fluxes [L2 T-3 ~> m2 s-3]
885  real, dimension(SZI_(G)), intent(inout) :: netheatminussw !< surf Heat flux
886  !! [degC H s-1 ~> degC m s-1 or degC kg m-2 s-1]
887  real, dimension(SZI_(G)), intent(inout) :: netsalt !< surf salt flux
888  !! [ppt H s-1 ~> ppt m s-1 or ppt kg m-2 s-1]
889  logical, optional, intent(in) :: skip_diags !< If present and true, skip calculating
890  !! diagnostics inside extractFluxes1d()
891  ! local variables
892  integer :: start, npts, k
893  real, parameter :: dt = 1. ! to return a rate from extractFluxes1d
894  real, dimension(SZI_(G)) :: neth ! net FW flux [H s-1 ~> m s-1 or kg m-2 s-1]
895  real, dimension(SZI_(G)) :: netevap ! net FW flux leaving ocean via evaporation
896  ! [H s-1 ~> m s-1 or kg m-2 s-1]
897  real, dimension(SZI_(G)) :: netheat ! net temp flux [degC H s-1 ~> degC m s-2 or degC kg m-2 s-1]
898  real, dimension(max(nsw,1), SZI_(G)) :: penswbnd ! penetrating SW radiation by band
899  ! [degC H ~> degC m or degC kg m-2]
900  real, dimension(SZI_(G)) :: pressure ! pressurea the surface [Pa]
901  real, dimension(SZI_(G)) :: drhodt ! density partial derivative wrt temp [kg m-3 degC-1]
902  real, dimension(SZI_(G)) :: drhods ! density partial derivative wrt saln [kg m-3 ppt-1]
903  real, dimension(SZI_(G),SZK_(G)+1) :: netpen ! The net penetrating shortwave radiation at each level
904  ! [degC H ~> degC m or degC kg m-2]
905 
906  logical :: useriverheatcontent
907  logical :: usecalvingheatcontent
908  real :: depthbeforescalingfluxes ! A depth scale [H ~> m or kg m-2]
909  real :: gorho ! The gravitational acceleration divided by mean density times some
910  ! unit conversion factors [L2 m3 H-1 s kg-1 T-3 ~> m4 kg-1 s-2 or m7 kg-2 s-2]
911  real :: h_limit_fluxes ! Another depth scale [H ~> m or kg m-2]
912 
913  ! smg: what do we do when have heat fluxes from calving and river?
914  useriverheatcontent = .false.
915  usecalvingheatcontent = .false.
916 
917  depthbeforescalingfluxes = max( gv%Angstrom_H, 1.e-30*gv%m_to_H )
918  pressure(:) = 0. ! Ignore atmospheric pressure
919  gorho = (gv%g_Earth*us%m_to_Z * gv%H_to_m*us%T_to_s) / gv%Rho0
920  start = 1 + g%isc - g%isd
921  npts = 1 + g%iec - g%isc
922 
923  h_limit_fluxes = depthbeforescalingfluxes
924 
925  ! The surface forcing is contained in the fluxes type.
926  ! We aggregate the thermodynamic forcing for a time step into the following:
927  ! netH = water added/removed via surface fluxes [H s-1 ~> m s-1 or kg m-2 s-1]
928  ! netHeat = heat via surface fluxes [degC H s-1 ~> degC m s-1 or degC kg m-2 s-1]
929  ! netSalt = salt via surface fluxes [ppt H s-1 ~> ppt m s-1 or gSalt m-2 s-1]
930  ! Note that unlike other calls to extractFLuxes1d() that return the time-integrated flux
931  ! this call returns the rate because dt=1
932  call extractfluxes1d(g, gv, fluxes, optics, nsw, j, dt, &
933  depthbeforescalingfluxes, useriverheatcontent, usecalvingheatcontent, &
934  h(:,j,:), temp(:,j,:), neth, netevap, netheatminussw, &
935  netsalt, penswbnd, tv, .false., skip_diags=skip_diags)
936 
937  ! Sum over bands and attenuate as a function of depth
938  ! netPen is the netSW as a function of depth
939  call sumswoverbands(g, gv, us, h(:,j,:), optics_nbands(optics), optics, j, dt*us%s_to_T, &
940  h_limit_fluxes, .true., penswbnd, netpen)
941 
942  ! Density derivatives
943  call calculate_density_derivs(temp(:,j,1), salt(:,j,1), pressure, &
944  drhodt, drhods, start, npts, tv%eqn_of_state)
945 
946  ! Adjust netSalt to reflect dilution effect of FW flux
947  netsalt(g%isc:g%iec) = netsalt(g%isc:g%iec) - salt(g%isc:g%iec,j,1) * neth(g%isc:g%iec) ! ppt H/s
948 
949  ! Add in the SW heating for purposes of calculating the net
950  ! surface buoyancy flux affecting the top layer.
951  !netHeat(:) = netHeatMinusSW(:) + sum( penSWbnd, dim=1 )
952  netheat(g%isc:g%iec) = netheatminussw(g%isc:g%iec) + netpen(g%isc:g%iec,1) ! K H/s
953 
954  ! Convert to a buoyancy flux, excluding penetrating SW heating
955  buoyancyflux(g%isc:g%iec,1) = - gorho * ( drhods(g%isc:g%iec) * netsalt(g%isc:g%iec) + &
956  drhodt(g%isc:g%iec) * netheat(g%isc:g%iec) ) ! [L2 T-3 ~> m2 s-3]
957  ! We also have a penetrative buoyancy flux associated with penetrative SW
958  do k=2, g%ke+1
959  buoyancyflux(g%isc:g%iec,k) = - gorho * ( drhodt(g%isc:g%iec) * netpen(g%isc:g%iec,k) ) ! [L2 T-3 ~> m2 s-3]
960  enddo
961 
962 end subroutine calculatebuoyancyflux1d
963 
964 
965 !> Calculates surface buoyancy flux by adding up the heat, FW and salt fluxes,
966 !! for 2d arrays. This is a wrapper for calculateBuoyancyFlux1d.
967 subroutine calculatebuoyancyflux2d(G, GV, US, fluxes, optics, h, Temp, Salt, tv, &
968  buoyancyFlux, netHeatMinusSW, netSalt, skip_diags)
969  type(ocean_grid_type), intent(in) :: g !< ocean grid
970  type(verticalgrid_type), intent(in) :: gv !< ocean vertical grid structure
971  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
972  type(forcing), intent(inout) :: fluxes !< surface fluxes
973  type(optics_type), pointer :: optics !< SW ocean optics
974  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< layer thickness [H ~> m or kg m-2]
975  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: temp !< temperature [degC]
976  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: salt !< salinity [ppt]
977  type(thermo_var_ptrs), intent(inout) :: tv !< thermodynamics type
978  real, dimension(SZI_(G),SZJ_(G),SZK_(G)+1), intent(inout) :: buoyancyflux !< buoyancy fluxes [L2 T-3 ~> m2 s-3]
979  real, dimension(SZI_(G),SZJ_(G)), optional, intent(inout) :: netheatminussw !< surf temp flux
980  !! [degC H ~> degC m or degC kg m-2]
981  real, dimension(SZI_(G),SZJ_(G)), optional, intent(inout) :: netsalt !< surf salt flux
982  !! [ppt H ~> ppt m or ppt kg m-2]
983  logical, optional, intent(in) :: skip_diags !< If present and true, skip calculating
984  !! diagnostics inside extractFluxes1d()
985  ! local variables
986  real, dimension( SZI_(G) ) :: nett ! net temperature flux [degC H s-1 ~> degC m s-2 or degC kg m-2 s-1]
987  real, dimension( SZI_(G) ) :: nets ! net saln flux !! [ppt H s-1 ~> ppt m s-1 or ppt kg m-2 s-1]
988  integer :: j
989 
990  nett(g%isc:g%iec) = 0. ; nets(g%isc:g%iec) = 0.
991 
992  !$OMP parallel do default(shared) firstprivate(netT,netS)
993  do j=g%jsc,g%jec
994  call calculatebuoyancyflux1d(g, gv, us, fluxes, optics, optics_nbands(optics), h, temp, salt, &
995  tv, j, buoyancyflux(:,j,:), nett, nets, skip_diags=skip_diags)
996  if (present(netheatminussw)) netheatminussw(g%isc:g%iec,j) = nett(g%isc:g%iec)
997  if (present(netsalt)) netsalt(g%isc:g%iec,j) = nets(g%isc:g%iec)
998  enddo
999 
1000 end subroutine calculatebuoyancyflux2d
1001 
1002 
1003 !> Write out chksums for thermodynamic fluxes.
1004 subroutine mom_forcing_chksum(mesg, fluxes, G, US, haloshift)
1005  character(len=*), intent(in) :: mesg !< message
1006  type(forcing), intent(in) :: fluxes !< A structure containing thermodynamic forcing fields
1007  type(ocean_grid_type), intent(in) :: g !< grid type
1008  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
1009  integer, optional, intent(in) :: haloshift !< shift in halo
1010 
1011  integer :: is, ie, js, je, nz, hshift
1012  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
1013 
1014  hshift=1; if (present(haloshift)) hshift=haloshift
1015 
1016  ! Note that for the chksum calls to be useful for reproducing across PE
1017  ! counts, there must be no redundant points, so all variables use is..ie
1018  ! and js...je as their extent.
1019  if (associated(fluxes%ustar)) &
1020  call hchksum(fluxes%ustar, mesg//" fluxes%ustar",g%HI, haloshift=hshift, scale=us%Z_to_m*us%s_to_T)
1021  if (associated(fluxes%buoy)) &
1022  call hchksum(fluxes%buoy, mesg//" fluxes%buoy ",g%HI, haloshift=hshift, scale=us%L_to_m**2*us%s_to_T**3)
1023  if (associated(fluxes%sw)) &
1024  call hchksum(fluxes%sw, mesg//" fluxes%sw",g%HI,haloshift=hshift)
1025  if (associated(fluxes%sw_vis_dir)) &
1026  call hchksum(fluxes%sw_vis_dir, mesg//" fluxes%sw_vis_dir",g%HI,haloshift=hshift)
1027  if (associated(fluxes%sw_vis_dif)) &
1028  call hchksum(fluxes%sw_vis_dif, mesg//" fluxes%sw_vis_dif",g%HI,haloshift=hshift)
1029  if (associated(fluxes%sw_nir_dir)) &
1030  call hchksum(fluxes%sw_nir_dir, mesg//" fluxes%sw_nir_dir",g%HI,haloshift=hshift)
1031  if (associated(fluxes%sw_nir_dif)) &
1032  call hchksum(fluxes%sw_nir_dif, mesg//" fluxes%sw_nir_dif",g%HI,haloshift=hshift)
1033  if (associated(fluxes%lw)) &
1034  call hchksum(fluxes%lw, mesg//" fluxes%lw",g%HI,haloshift=hshift)
1035  if (associated(fluxes%latent)) &
1036  call hchksum(fluxes%latent, mesg//" fluxes%latent",g%HI,haloshift=hshift)
1037  if (associated(fluxes%latent_evap_diag)) &
1038  call hchksum(fluxes%latent_evap_diag, mesg//" fluxes%latent_evap_diag",g%HI,haloshift=hshift)
1039  if (associated(fluxes%latent_fprec_diag)) &
1040  call hchksum(fluxes%latent_fprec_diag, mesg//" fluxes%latent_fprec_diag",g%HI,haloshift=hshift)
1041  if (associated(fluxes%latent_frunoff_diag)) &
1042  call hchksum(fluxes%latent_frunoff_diag, mesg//" fluxes%latent_frunoff_diag",g%HI,haloshift=hshift)
1043  if (associated(fluxes%sens)) &
1044  call hchksum(fluxes%sens, mesg//" fluxes%sens",g%HI,haloshift=hshift)
1045  if (associated(fluxes%evap)) &
1046  call hchksum(fluxes%evap, mesg//" fluxes%evap",g%HI,haloshift=hshift)
1047  if (associated(fluxes%lprec)) &
1048  call hchksum(fluxes%lprec, mesg//" fluxes%lprec",g%HI,haloshift=hshift)
1049  if (associated(fluxes%fprec)) &
1050  call hchksum(fluxes%fprec, mesg//" fluxes%fprec",g%HI,haloshift=hshift)
1051  if (associated(fluxes%vprec)) &
1052  call hchksum(fluxes%vprec, mesg//" fluxes%vprec",g%HI,haloshift=hshift)
1053  if (associated(fluxes%seaice_melt)) &
1054  call hchksum(fluxes%seaice_melt, mesg//" fluxes%seaice_melt",g%HI,haloshift=hshift)
1055  if (associated(fluxes%seaice_melt_heat)) &
1056  call hchksum(fluxes%seaice_melt_heat, mesg//" fluxes%seaice_melt_heat",g%HI,haloshift=hshift)
1057  if (associated(fluxes%p_surf)) &
1058  call hchksum(fluxes%p_surf, mesg//" fluxes%p_surf",g%HI,haloshift=hshift)
1059  if (associated(fluxes%salt_flux)) &
1060  call hchksum(fluxes%salt_flux, mesg//" fluxes%salt_flux",g%HI,haloshift=hshift)
1061  if (associated(fluxes%TKE_tidal)) &
1062  call hchksum(fluxes%TKE_tidal, mesg//" fluxes%TKE_tidal",g%HI,haloshift=hshift)
1063  if (associated(fluxes%ustar_tidal)) &
1064  call hchksum(fluxes%ustar_tidal, mesg//" fluxes%ustar_tidal",g%HI,haloshift=hshift, scale=us%Z_to_m*us%s_to_T)
1065  if (associated(fluxes%lrunoff)) &
1066  call hchksum(fluxes%lrunoff, mesg//" fluxes%lrunoff",g%HI,haloshift=hshift)
1067  if (associated(fluxes%frunoff)) &
1068  call hchksum(fluxes%frunoff, mesg//" fluxes%frunoff",g%HI,haloshift=hshift)
1069  if (associated(fluxes%heat_content_lrunoff)) &
1070  call hchksum(fluxes%heat_content_lrunoff, mesg//" fluxes%heat_content_lrunoff",g%HI,haloshift=hshift)
1071  if (associated(fluxes%heat_content_frunoff)) &
1072  call hchksum(fluxes%heat_content_frunoff, mesg//" fluxes%heat_content_frunoff",g%HI,haloshift=hshift)
1073  if (associated(fluxes%heat_content_lprec)) &
1074  call hchksum(fluxes%heat_content_lprec, mesg//" fluxes%heat_content_lprec",g%HI,haloshift=hshift)
1075  if (associated(fluxes%heat_content_fprec)) &
1076  call hchksum(fluxes%heat_content_fprec, mesg//" fluxes%heat_content_fprec",g%HI,haloshift=hshift)
1077  if (associated(fluxes%heat_content_icemelt)) &
1078  call hchksum(fluxes%heat_content_icemelt, mesg//" fluxes%heat_content_icemelt",g%HI,haloshift=hshift)
1079  if (associated(fluxes%heat_content_cond)) &
1080  call hchksum(fluxes%heat_content_cond, mesg//" fluxes%heat_content_cond",g%HI,haloshift=hshift)
1081  if (associated(fluxes%heat_content_massout)) &
1082  call hchksum(fluxes%heat_content_massout, mesg//" fluxes%heat_content_massout",g%HI,haloshift=hshift)
1083 end subroutine mom_forcing_chksum
1084 
1085 !> Write out chksums for the driving mechanical forces.
1086 subroutine mom_mech_forcing_chksum(mesg, forces, G, US, haloshift)
1087  character(len=*), intent(in) :: mesg !< message
1088  type(mech_forcing), intent(in) :: forces !< A structure with the driving mechanical forces
1089  type(ocean_grid_type), intent(in) :: g !< grid type
1090  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
1091  integer, optional, intent(in) :: haloshift !< shift in halo
1092 
1093  integer :: is, ie, js, je, nz, hshift
1094  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = g%ke
1095 
1096  hshift=1; if (present(haloshift)) hshift=haloshift
1097 
1098  ! Note that for the chksum calls to be useful for reproducing across PE
1099  ! counts, there must be no redundant points, so all variables use is..ie
1100  ! and js...je as their extent.
1101  if (associated(forces%taux) .and. associated(forces%tauy)) &
1102  call uvchksum(mesg//" forces%tau[xy]", forces%taux, forces%tauy, g%HI, &
1103  haloshift=hshift, symmetric=.true.)
1104  if (associated(forces%p_surf)) &
1105  call hchksum(forces%p_surf, mesg//" forces%p_surf",g%HI,haloshift=hshift)
1106  if (associated(forces%ustar)) &
1107  call hchksum(forces%ustar, mesg//" forces%ustar",g%HI,haloshift=hshift, scale=us%Z_to_m*us%s_to_T)
1108  if (associated(forces%rigidity_ice_u) .and. associated(forces%rigidity_ice_v)) &
1109  call uvchksum(mesg//" forces%rigidity_ice_[uv]", forces%rigidity_ice_u, &
1110  forces%rigidity_ice_v, g%HI, haloshift=hshift, symmetric=.true.)
1111 
1112 end subroutine mom_mech_forcing_chksum
1113 
1114 !> Write out values of the mechanical forcing arrays at the i,j location. This is a debugging tool.
1115 subroutine mech_forcing_singlepointprint(forces, G, i, j, mesg)
1116  type(mech_forcing), intent(in) :: forces !< A structure with the driving mechanical forces
1117  type(ocean_grid_type), intent(in) :: G !< Grid type
1118  character(len=*), intent(in) :: mesg !< Message
1119  integer, intent(in) :: i !< i-index
1120  integer, intent(in) :: j !< j-index
1121 
1122  write(0,'(2a)') 'MOM_forcing_type, forcing_SinglePointPrint: Called from ',mesg
1123  write(0,'(a,2es15.3)') 'MOM_forcing_type, forcing_SinglePointPrint: lon,lat = ',g%geoLonT(i,j),g%geoLatT(i,j)
1124  call locmsg(forces%taux,'taux')
1125  call locmsg(forces%tauy,'tauy')
1126 
1127  contains
1128  !> Format and write a message depending on associated state of array
1129  subroutine locmsg(array,aname)
1130  real, dimension(:,:), pointer :: array !< Array to write element from
1131  character(len=*) :: aname !< Name of array
1132 
1133  if (associated(array)) then
1134  write(0,'(3a,es15.3)') 'MOM_forcing_type, mech_forcing_SinglePointPrint: ',trim(aname),' = ',array(i,j)
1135  else
1136  write(0,'(4a)') 'MOM_forcing_type, mech_forcing_SinglePointPrint: ',trim(aname),' is not associated.'
1137  endif
1138  end subroutine locmsg
1139 
1140 end subroutine mech_forcing_singlepointprint
1141 
1142 !> Write out values of the fluxes arrays at the i,j location. This is a debugging tool.
1143 subroutine forcing_singlepointprint(fluxes, G, i, j, mesg)
1144  type(forcing), intent(in) :: fluxes !< A structure containing thermodynamic forcing fields
1145  type(ocean_grid_type), intent(in) :: g !< Grid type
1146  character(len=*), intent(in) :: mesg !< Message
1147  integer, intent(in) :: i !< i-index
1148  integer, intent(in) :: j !< j-index
1149 
1150  write(0,'(2a)') 'MOM_forcing_type, forcing_SinglePointPrint: Called from ',mesg
1151  write(0,'(a,2es15.3)') 'MOM_forcing_type, forcing_SinglePointPrint: lon,lat = ',g%geoLonT(i,j),g%geoLatT(i,j)
1152  call locmsg(fluxes%ustar,'ustar')
1153  call locmsg(fluxes%buoy,'buoy')
1154  call locmsg(fluxes%sw,'sw')
1155  call locmsg(fluxes%sw_vis_dir,'sw_vis_dir')
1156  call locmsg(fluxes%sw_vis_dif,'sw_vis_dif')
1157  call locmsg(fluxes%sw_nir_dir,'sw_nir_dir')
1158  call locmsg(fluxes%sw_nir_dif,'sw_nir_dif')
1159  call locmsg(fluxes%lw,'lw')
1160  call locmsg(fluxes%latent,'latent')
1161  call locmsg(fluxes%latent_evap_diag,'latent_evap_diag')
1162  call locmsg(fluxes%latent_fprec_diag,'latent_fprec_diag')
1163  call locmsg(fluxes%latent_frunoff_diag,'latent_frunoff_diag')
1164  call locmsg(fluxes%sens,'sens')
1165  call locmsg(fluxes%evap,'evap')
1166  call locmsg(fluxes%lprec,'lprec')
1167  call locmsg(fluxes%fprec,'fprec')
1168  call locmsg(fluxes%vprec,'vprec')
1169  call locmsg(fluxes%seaice_melt,'seaice_melt')
1170  call locmsg(fluxes%seaice_melt_heat,'seaice_melt_heat')
1171  call locmsg(fluxes%p_surf,'p_surf')
1172  call locmsg(fluxes%salt_flux,'salt_flux')
1173  call locmsg(fluxes%TKE_tidal,'TKE_tidal')
1174  call locmsg(fluxes%ustar_tidal,'ustar_tidal')
1175  call locmsg(fluxes%lrunoff,'lrunoff')
1176  call locmsg(fluxes%frunoff,'frunoff')
1177  call locmsg(fluxes%heat_content_lrunoff,'heat_content_lrunoff')
1178  call locmsg(fluxes%heat_content_frunoff,'heat_content_frunoff')
1179  call locmsg(fluxes%heat_content_lprec,'heat_content_lprec')
1180  call locmsg(fluxes%heat_content_fprec,'heat_content_fprec')
1181  call locmsg(fluxes%heat_content_icemelt,'heat_content_icemelt')
1182  call locmsg(fluxes%heat_content_vprec,'heat_content_vprec')
1183  call locmsg(fluxes%heat_content_cond,'heat_content_cond')
1184  call locmsg(fluxes%heat_content_cond,'heat_content_massout')
1185 
1186  contains
1187  !> Format and write a message depending on associated state of array
1188  subroutine locmsg(array,aname)
1189  real, dimension(:,:), pointer :: array !< Array to write element from
1190  character(len=*) :: aname !< Name of array
1191 
1192  if (associated(array)) then
1193  write(0,'(3a,es15.3)') 'MOM_forcing_type, forcing_SinglePointPrint: ',trim(aname),' = ',array(i,j)
1194  else
1195  write(0,'(4a)') 'MOM_forcing_type, forcing_SinglePointPrint: ',trim(aname),' is not associated.'
1196  endif
1197  end subroutine locmsg
1198 
1199 end subroutine forcing_singlepointprint
1200 
1201 
1202 !> Register members of the forcing type for diagnostics
1203 subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, use_berg_fluxes)
1204  type(time_type), intent(in) :: time !< time type
1205  type(diag_ctrl), intent(inout) :: diag !< diagnostic control type
1206  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
1207  logical, intent(in) :: use_temperature !< True if T/S are in use
1208  type(forcing_diags), intent(inout) :: handles !< handles for diagnostics
1209  logical, optional, intent(in) :: use_berg_fluxes !< If true, allow iceberg flux diagnostics
1210 
1211  ! Clock for forcing diagnostics
1212  handles%id_clock_forcing=cpu_clock_id('(Ocean forcing diagnostics)', grain=clock_routine)
1213 
1214 
1215  handles%id_taux = register_diag_field('ocean_model', 'taux', diag%axesCu1, time, &
1216  'Zonal surface stress from ocean interactions with atmos and ice', 'Pa', &
1217  standard_name='surface_downward_x_stress', cmor_field_name='tauuo', &
1218  cmor_units='N m-2', cmor_long_name='Surface Downward X Stress', &
1219  cmor_standard_name='surface_downward_x_stress')
1220 
1221  handles%id_tauy = register_diag_field('ocean_model', 'tauy', diag%axesCv1, time, &
1222  'Meridional surface stress ocean interactions with atmos and ice', 'Pa', &
1223  standard_name='surface_downward_y_stress', cmor_field_name='tauvo', &
1224  cmor_units='N m-2', cmor_long_name='Surface Downward Y Stress', &
1225  cmor_standard_name='surface_downward_y_stress')
1226 
1227  handles%id_ustar = register_diag_field('ocean_model', 'ustar', diag%axesT1, time, &
1228  'Surface friction velocity = [(gustiness + tau_magnitude)/rho0]^(1/2)', &
1229  'm s-1', conversion=us%Z_to_m*us%s_to_T)
1230 
1231  if (present(use_berg_fluxes)) then
1232  if (use_berg_fluxes) then
1233  handles%id_ustar_berg = register_diag_field('ocean_model', 'ustar_berg', diag%axesT1, time, &
1234  'Friction velocity below iceberg ', 'm s-1', conversion=us%Z_to_m*us%s_to_T)
1235 
1236  handles%id_area_berg = register_diag_field('ocean_model', 'area_berg', diag%axesT1, time, &
1237  'Area of grid cell covered by iceberg ', 'm2 m-2')
1238 
1239  handles%id_mass_berg = register_diag_field('ocean_model', 'mass_berg', diag%axesT1, time, &
1240  'Mass of icebergs ', 'kg m-2')
1241 
1242  handles%id_ustar_ice_cover = register_diag_field('ocean_model', 'ustar_ice_cover', diag%axesT1, time, &
1243  'Friction velocity below iceberg and ice shelf together', 'm s-1', conversion=us%Z_to_m*us%s_to_T)
1244 
1245  handles%id_frac_ice_cover = register_diag_field('ocean_model', 'frac_ice_cover', diag%axesT1, time, &
1246  'Area of grid cell below iceberg and ice shelf together ', 'm2 m-2')
1247  endif
1248  endif
1249 
1250  handles%id_psurf = register_diag_field('ocean_model', 'p_surf', diag%axesT1, time, &
1251  'Pressure at ice-ocean or atmosphere-ocean interface', 'Pa', cmor_field_name='pso', &
1252  cmor_long_name='Sea Water Pressure at Sea Water Surface', &
1253  cmor_standard_name='sea_water_pressure_at_sea_water_surface')
1254 
1255  handles%id_TKE_tidal = register_diag_field('ocean_model', 'TKE_tidal', diag%axesT1, time, &
1256  'Tidal source of BBL mixing', 'W m-2')
1257 
1258  if (.not. use_temperature) then
1259  handles%id_buoy = register_diag_field('ocean_model', 'buoy', diag%axesT1, time, &
1260  'Buoyancy forcing', 'm2 s-3', conversion=us%L_to_m**2*us%s_to_T**3)
1261  return
1262  endif
1263 
1264 
1265  !===============================================================
1266  ! surface mass flux maps
1267 
1268  handles%id_prcme = register_diag_field('ocean_model', 'PRCmE', diag%axesT1, time, &
1269  'Net surface water flux (precip+melt+lrunoff+ice calving-evap)', 'kg m-2 s-1',&
1270  standard_name='water_flux_into_sea_water', cmor_field_name='wfo', &
1271  cmor_standard_name='water_flux_into_sea_water',cmor_long_name='Water Flux Into Sea Water')
1272 
1273  handles%id_evap = register_diag_field('ocean_model', 'evap', diag%axesT1, time, &
1274  'Evaporation/condensation at ocean surface (evaporation is negative)', 'kg m-2 s-1',&
1275  standard_name='water_evaporation_flux', cmor_field_name='evs', &
1276  cmor_standard_name='water_evaporation_flux', &
1277  cmor_long_name='Water Evaporation Flux Where Ice Free Ocean over Sea')
1278 
1279  ! smg: seaice_melt field requires updates to the sea ice model
1280  handles%id_seaice_melt = register_diag_field('ocean_model', 'seaice_melt', &
1281  diag%axesT1, time, 'water flux to ocean from snow/sea ice melting(> 0) or formation(< 0)', &
1282  'kg m-2 s-1', &
1283  standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics', &
1284  cmor_field_name='fsitherm', &
1285  cmor_standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics',&
1286  cmor_long_name='water flux to ocean from sea ice melt(> 0) or form(< 0)')
1287 
1288  handles%id_precip = register_diag_field('ocean_model', 'precip', diag%axesT1, time, &
1289  'Liquid + frozen precipitation into ocean', 'kg m-2 s-1')
1290 
1291  handles%id_fprec = register_diag_field('ocean_model', 'fprec', diag%axesT1, time, &
1292  'Frozen precipitation into ocean', 'kg m-2 s-1', &
1293  standard_name='snowfall_flux', cmor_field_name='prsn', &
1294  cmor_standard_name='snowfall_flux', cmor_long_name='Snowfall Flux where Ice Free Ocean over Sea')
1295 
1296  handles%id_lprec = register_diag_field('ocean_model', 'lprec', diag%axesT1, time, &
1297  'Liquid precipitation into ocean', 'kg m-2 s-1', &
1298  standard_name='rainfall_flux', &
1299  cmor_field_name='prlq', cmor_standard_name='rainfall_flux', &
1300  cmor_long_name='Rainfall Flux where Ice Free Ocean over Sea')
1301 
1302  handles%id_vprec = register_diag_field('ocean_model', 'vprec', diag%axesT1, time, &
1303  'Virtual liquid precip into ocean due to SSS restoring', 'kg m-2 s-1')
1304 
1305  handles%id_frunoff = register_diag_field('ocean_model', 'frunoff', diag%axesT1, time, &
1306  'Frozen runoff (calving) and iceberg melt into ocean', 'kg m-2 s-1', &
1307  standard_name='water_flux_into_sea_water_from_icebergs', &
1308  cmor_field_name='ficeberg', &
1309  cmor_standard_name='water_flux_into_sea_water_from_icebergs', &
1310  cmor_long_name='Water Flux into Seawater from Icebergs')
1311 
1312  handles%id_lrunoff = register_diag_field('ocean_model', 'lrunoff', diag%axesT1, time, &
1313  'Liquid runoff (rivers) into ocean', 'kg m-2 s-1', &
1314  standard_name='water_flux_into_sea_water_from_rivers', cmor_field_name='friver', &
1315  cmor_standard_name='water_flux_into_sea_water_from_rivers', &
1316  cmor_long_name='Water Flux into Sea Water From Rivers')
1317 
1318  handles%id_net_massout = register_diag_field('ocean_model', 'net_massout', diag%axesT1, time, &
1319  'Net mass leaving the ocean due to evaporation, seaice formation', 'kg m-2 s-1')
1320 
1321  handles%id_net_massin = register_diag_field('ocean_model', 'net_massin', diag%axesT1, time, &
1322  'Net mass entering ocean due to precip, runoff, ice melt', 'kg m-2 s-1')
1323 
1324  handles%id_massout_flux = register_diag_field('ocean_model', 'massout_flux', diag%axesT1, time, &
1325  'Net mass flux of freshwater out of the ocean (used in the boundary flux calculation)', &
1326  'kg m-2')
1327 
1328  handles%id_massin_flux = register_diag_field('ocean_model', 'massin_flux', diag%axesT1, time, &
1329  'Net mass flux of freshwater into the ocean (used in boundary flux calculation)', 'kg m-2')
1330  !=========================================================================
1331  ! area integrated surface mass transport
1332 
1333  handles%id_total_prcme = register_scalar_field('ocean_model', 'total_PRCmE', time, diag, &
1334  long_name='Area integrated net surface water flux (precip+melt+liq runoff+ice calving-evap)',&
1335  units='kg s-1', standard_name='water_flux_into_sea_water_area_integrated', &
1336  cmor_field_name='total_wfo', &
1337  cmor_standard_name='water_flux_into_sea_water_area_integrated', &
1338  cmor_long_name='Water Transport Into Sea Water Area Integrated')
1339 
1340  handles%id_total_evap = register_scalar_field('ocean_model', 'total_evap', time, diag,&
1341  long_name='Area integrated evap/condense at ocean surface', &
1342  units='kg s-1', standard_name='water_evaporation_flux_area_integrated', &
1343  cmor_field_name='total_evs', &
1344  cmor_standard_name='water_evaporation_flux_area_integrated', &
1345  cmor_long_name='Evaporation Where Ice Free Ocean over Sea Area Integrated')
1346 
1347  ! seaice_melt field requires updates to the sea ice model
1348  handles%id_total_seaice_melt = register_scalar_field('ocean_model', 'total_icemelt', time, diag, &
1349  long_name='Area integrated sea ice melt (>0) or form (<0)', units='kg s-1', &
1350  standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics_area_integrated', &
1351  cmor_field_name='total_fsitherm', &
1352  cmor_standard_name='water_flux_into_sea_water_due_to_sea_ice_thermodynamics_area_integrated', &
1353  cmor_long_name='Water Melt/Form from Sea Ice Area Integrated')
1354 
1355  handles%id_total_precip = register_scalar_field('ocean_model', 'total_precip', time, diag, &
1356  long_name='Area integrated liquid+frozen precip into ocean', units='kg s-1')
1357 
1358  handles%id_total_fprec = register_scalar_field('ocean_model', 'total_fprec', time, diag,&
1359  long_name='Area integrated frozen precip into ocean', units='kg s-1', &
1360  standard_name='snowfall_flux_area_integrated', &
1361  cmor_field_name='total_prsn', &
1362  cmor_standard_name='snowfall_flux_area_integrated', &
1363  cmor_long_name='Snowfall Flux where Ice Free Ocean over Sea Area Integrated')
1364 
1365  handles%id_total_lprec = register_scalar_field('ocean_model', 'total_lprec', time, diag,&
1366  long_name='Area integrated liquid precip into ocean', units='kg s-1', &
1367  standard_name='rainfall_flux_area_integrated', &
1368  cmor_field_name='total_pr', &
1369  cmor_standard_name='rainfall_flux_area_integrated', &
1370  cmor_long_name='Rainfall Flux where Ice Free Ocean over Sea Area Integrated')
1371 
1372  handles%id_total_vprec = register_scalar_field('ocean_model', 'total_vprec', time, diag, &
1373  long_name='Area integrated virtual liquid precip due to SSS restoring', units='kg s-1')
1374 
1375  handles%id_total_frunoff = register_scalar_field('ocean_model', 'total_frunoff', time, diag, &
1376  long_name='Area integrated frozen runoff (calving) & iceberg melt into ocean', units='kg s-1',&
1377  cmor_field_name='total_ficeberg', &
1378  cmor_standard_name='water_flux_into_sea_water_from_icebergs_area_integrated', &
1379  cmor_long_name='Water Flux into Seawater from Icebergs Area Integrated')
1380 
1381  handles%id_total_lrunoff = register_scalar_field('ocean_model', 'total_lrunoff', time, diag,&
1382  long_name='Area integrated liquid runoff into ocean', units='kg s-1', &
1383  cmor_field_name='total_friver', &
1384  cmor_standard_name='water_flux_into_sea_water_from_rivers_area_integrated', &
1385  cmor_long_name='Water Flux into Sea Water From Rivers Area Integrated')
1386 
1387  handles%id_total_net_massout = register_scalar_field('ocean_model', 'total_net_massout', time, diag, &
1388  long_name='Area integrated mass leaving ocean due to evap and seaice form', units='kg s-1')
1389 
1390  handles%id_total_net_massin = register_scalar_field('ocean_model', 'total_net_massin', time, diag, &
1391  long_name='Area integrated mass entering ocean due to predip, runoff, ice melt', units='kg s-1')
1392 
1393  !=========================================================================
1394  ! area averaged surface mass transport
1395 
1396  handles%id_prcme_ga = register_scalar_field('ocean_model', 'PRCmE_ga', time, diag, &
1397  long_name='Area averaged net surface water flux (precip+melt+liq runoff+ice calving-evap)',&
1398  units='kg m-2 s-1', standard_name='water_flux_into_sea_water_area_averaged', &
1399  cmor_field_name='ave_wfo', &
1400  cmor_standard_name='rainfall_flux_area_averaged', &
1401  cmor_long_name='Water Transport Into Sea Water Area Averaged')
1402 
1403  handles%id_evap_ga = register_scalar_field('ocean_model', 'evap_ga', time, diag,&
1404  long_name='Area averaged evap/condense at ocean surface', &
1405  units='kg m-2 s-1', standard_name='water_evaporation_flux_area_averaged', &
1406  cmor_field_name='ave_evs', &
1407  cmor_standard_name='water_evaporation_flux_area_averaged', &
1408  cmor_long_name='Evaporation Where Ice Free Ocean over Sea Area Averaged')
1409 
1410  handles%id_lprec_ga = register_scalar_field('ocean_model', 'lprec_ga', time, diag,&
1411  long_name='Area integrated liquid precip into ocean', units='kg m-2 s-1', &
1412  standard_name='rainfall_flux_area_averaged', &
1413  cmor_field_name='ave_pr', &
1414  cmor_standard_name='rainfall_flux_area_averaged', &
1415  cmor_long_name='Rainfall Flux where Ice Free Ocean over Sea Area Averaged')
1416 
1417  handles%id_fprec_ga = register_scalar_field('ocean_model', 'fprec_ga', time, diag,&
1418  long_name='Area integrated frozen precip into ocean', units='kg m-2 s-1', &
1419  standard_name='snowfall_flux_area_averaged', &
1420  cmor_field_name='ave_prsn', &
1421  cmor_standard_name='snowfall_flux_area_averaged', &
1422  cmor_long_name='Snowfall Flux where Ice Free Ocean over Sea Area Averaged')
1423 
1424  handles%id_precip_ga = register_scalar_field('ocean_model', 'precip_ga', time, diag, &
1425  long_name='Area averaged liquid+frozen precip into ocean', units='kg m-2 s-1')
1426 
1427  handles%id_vprec_ga = register_scalar_field('ocean_model', 'vrec_ga', time, diag, &
1428  long_name='Area averaged virtual liquid precip due to SSS restoring', units='kg m-2 s-1')
1429 
1430  !===============================================================
1431  ! surface heat flux maps
1432 
1433  handles%id_heat_content_frunoff = register_diag_field('ocean_model', 'heat_content_frunoff', &
1434  diag%axesT1, time, 'Heat content (relative to 0C) of solid runoff into ocean', 'W m-2', &
1435  standard_name='temperature_flux_due_to_solid_runoff_expressed_as_heat_flux_into_sea_water')
1436 
1437  handles%id_heat_content_lrunoff = register_diag_field('ocean_model', 'heat_content_lrunoff', &
1438  diag%axesT1, time, 'Heat content (relative to 0C) of liquid runoff into ocean', 'W m-2', &
1439  standard_name='temperature_flux_due_to_runoff_expressed_as_heat_flux_into_sea_water')
1440 
1441  handles%id_hfrunoffds = register_diag_field('ocean_model', 'hfrunoffds', &
1442  diag%axesT1, time, 'Heat content (relative to 0C) of liquid+solid runoff into ocean', 'W m-2',&
1443  standard_name='temperature_flux_due_to_runoff_expressed_as_heat_flux_into_sea_water')
1444 
1445  handles%id_heat_content_lprec = register_diag_field('ocean_model', 'heat_content_lprec', &
1446  diag%axesT1,time,'Heat content (relative to 0degC) of liquid precip entering ocean', &
1447  'W m-2')
1448 
1449  handles%id_heat_content_fprec = register_diag_field('ocean_model', 'heat_content_fprec',&
1450  diag%axesT1,time,'Heat content (relative to 0degC) of frozen prec entering ocean',&
1451  'W m-2')
1452 
1453  handles%id_heat_content_icemelt = register_diag_field('ocean_model', 'heat_content_icemelt',&
1454  diag%axesT1,time,'Heat content (relative to 0degC) of water flux due to sea ice melting/freezing',&
1455  'W m-2')
1456 
1457  handles%id_heat_content_vprec = register_diag_field('ocean_model', 'heat_content_vprec', &
1458  diag%axesT1,time,'Heat content (relative to 0degC) of virtual precip entering ocean',&
1459  'W m-2')
1460 
1461  handles%id_heat_content_cond = register_diag_field('ocean_model', 'heat_content_cond', &
1462  diag%axesT1,time,'Heat content (relative to 0degC) of water condensing into ocean',&
1463  'W m-2')
1464 
1465  handles%id_hfrainds = register_diag_field('ocean_model', 'hfrainds', &
1466  diag%axesT1,time,'Heat content (relative to 0degC) of liquid+frozen precip entering ocean', &
1467  'W m-2',standard_name='temperature_flux_due_to_rainfall_expressed_as_heat_flux_into_sea_water',&
1468  cmor_long_name='Heat Content (relative to 0degC) of Liquid + Frozen Precipitation')
1469 
1470  handles%id_heat_content_surfwater = register_diag_field('ocean_model', 'heat_content_surfwater',&
1471  diag%axesT1, time, &
1472  'Heat content (relative to 0degC) of net water crossing ocean surface (frozen+liquid)', &
1473  'W m-2')
1474 
1475  handles%id_heat_content_massout = register_diag_field('ocean_model', 'heat_content_massout', &
1476  diag%axesT1, time,'Heat content (relative to 0degC) of net mass leaving ocean ocean via evap and ice form',&
1477  'W m-2', &
1478  cmor_field_name='hfevapds', &
1479  cmor_standard_name='temperature_flux_due_to_evaporation_expressed_as_heat_flux_out_of_sea_water', &
1480  cmor_long_name='Heat Content (relative to 0degC) of Water Leaving Ocean via Evaporation and Ice Formation')
1481 
1482  handles%id_heat_content_massin = register_diag_field('ocean_model', 'heat_content_massin', &
1483  diag%axesT1, time,'Heat content (relative to 0degC) of net mass entering ocean ocean',&
1484  'W m-2')
1485 
1486  handles%id_net_heat_coupler = register_diag_field('ocean_model', 'net_heat_coupler', &
1487  diag%axesT1,time,'Surface ocean heat flux from SW+LW+latent+sensible+seaice_melt_heat (via the coupler)',&
1488  'W m-2')
1489 
1490  handles%id_net_heat_surface = register_diag_field('ocean_model', 'net_heat_surface',diag%axesT1, time, &
1491  'Surface ocean heat flux from SW+LW+lat+sens+mass transfer+frazil+restore+seaice_melt_heat or '// &
1492  'flux adjustments',&
1493  'W m-2',&
1494  standard_name='surface_downward_heat_flux_in_sea_water', cmor_field_name='hfds', &
1495  cmor_standard_name='surface_downward_heat_flux_in_sea_water', &
1496  cmor_long_name='Surface ocean heat flux from SW+LW+latent+sensible+masstransfer+frazil+seaice_melt_heat')
1497 
1498  handles%id_sw = register_diag_field('ocean_model', 'SW', diag%axesT1, time, &
1499  'Shortwave radiation flux into ocean', 'W m-2', &
1500  standard_name='net_downward_shortwave_flux_at_sea_water_surface', &
1501  cmor_field_name='rsntds', &
1502  cmor_standard_name='net_downward_shortwave_flux_at_sea_water_surface', &
1503  cmor_long_name='Net Downward Shortwave Radiation at Sea Water Surface')
1504  handles%id_sw_vis = register_diag_field('ocean_model', 'sw_vis', diag%axesT1, time, &
1505  'Shortwave radiation direct and diffuse flux into the ocean in the visible band', &
1506  'W m-2')
1507  handles%id_sw_nir = register_diag_field('ocean_model', 'sw_nir', diag%axesT1, time, &
1508  'Shortwave radiation direct and diffuse flux into the ocean in the near-infrared band', &
1509  'W m-2')
1510 
1511  handles%id_LwLatSens = register_diag_field('ocean_model', 'LwLatSens', diag%axesT1, time, &
1512  'Combined longwave, latent, and sensible heating at ocean surface', 'W m-2')
1513 
1514  handles%id_lw = register_diag_field('ocean_model', 'LW', diag%axesT1, time, &
1515  'Longwave radiation flux into ocean', 'W m-2', &
1516  standard_name='surface_net_downward_longwave_flux', &
1517  cmor_field_name='rlntds', &
1518  cmor_standard_name='surface_net_downward_longwave_flux', &
1519  cmor_long_name='Surface Net Downward Longwave Radiation')
1520 
1521  handles%id_lat = register_diag_field('ocean_model', 'latent', diag%axesT1, time, &
1522  'Latent heat flux into ocean due to fusion and evaporation (negative means ocean heat loss)', &
1523  'W m-2', cmor_field_name='hflso', &
1524  cmor_standard_name='surface_downward_latent_heat_flux', &
1525  cmor_long_name='Surface Downward Latent Heat Flux due to Evap + Melt Snow/Ice')
1526 
1527  handles%id_lat_evap = register_diag_field('ocean_model', 'latent_evap', diag%axesT1, time, &
1528  'Latent heat flux into ocean due to evaporation/condensation', 'W m-2')
1529 
1530  handles%id_lat_fprec = register_diag_field('ocean_model', 'latent_fprec_diag', diag%axesT1, time,&
1531  'Latent heat flux into ocean due to melting of frozen precipitation', 'W m-2', &
1532  cmor_field_name='hfsnthermds', &
1533  cmor_standard_name='heat_flux_into_sea_water_due_to_snow_thermodynamics', &
1534  cmor_long_name='Latent Heat to Melt Frozen Precipitation')
1535 
1536  handles%id_lat_frunoff = register_diag_field('ocean_model', 'latent_frunoff', diag%axesT1, time, &
1537  'Latent heat flux into ocean due to melting of icebergs', 'W m-2', &
1538  cmor_field_name='hfibthermds', &
1539  cmor_standard_name='heat_flux_into_sea_water_due_to_iceberg_thermodynamics', &
1540  cmor_long_name='Latent Heat to Melt Frozen Runoff/Iceberg')
1541 
1542  handles%id_sens = register_diag_field('ocean_model', 'sensible', diag%axesT1, time,&
1543  'Sensible heat flux into ocean', 'W m-2', &
1544  standard_name='surface_downward_sensible_heat_flux', &
1545  cmor_field_name='hfsso', &
1546  cmor_standard_name='surface_downward_sensible_heat_flux', &
1547  cmor_long_name='Surface Downward Sensible Heat Flux')
1548 
1549  handles%id_seaice_melt_heat = register_diag_field('ocean_model', 'seaice_melt_heat', diag%axesT1, time,&
1550  'Heat flux into ocean due to snow and sea ice melt/freeze', 'W m-2', &
1551  standard_name='snow_ice_melt_heat_flux', &
1552  !GMM TODO cmor_field_name='hfsso', &
1553  cmor_standard_name='snow_ice_melt_heat_flux', &
1554  cmor_long_name='Heat flux into ocean from snow and sea ice melt')
1555 
1556  handles%id_heat_added = register_diag_field('ocean_model', 'heat_added', diag%axesT1, time, &
1557  'Flux Adjustment or restoring surface heat flux into ocean', 'W m-2')
1558 
1559 
1560  !===============================================================
1561  ! area integrated surface heat fluxes
1562 
1563  handles%id_total_heat_content_frunoff = register_scalar_field('ocean_model', &
1564  'total_heat_content_frunoff', time, diag, &
1565  long_name='Area integrated heat content (relative to 0C) of solid runoff', &
1566  units='W', cmor_field_name='total_hfsolidrunoffds', &
1567  cmor_standard_name= &
1568  'temperature_flux_due_to_solid_runoff_expressed_as_heat_flux_into_sea_water_area_integrated',&
1569  cmor_long_name= &
1570  'Temperature Flux due to Solid Runoff Expressed as Heat Flux into Sea Water Area Integrated')
1571 
1572  handles%id_total_heat_content_lrunoff = register_scalar_field('ocean_model', &
1573  'total_heat_content_lrunoff', time, diag, &
1574  long_name='Area integrated heat content (relative to 0C) of liquid runoff', &
1575  units='W', cmor_field_name='total_hfrunoffds', &
1576  cmor_standard_name= &
1577  'temperature_flux_due_to_runoff_expressed_as_heat_flux_into_sea_water_area_integrated',&
1578  cmor_long_name= &
1579  'Temperature Flux due to Runoff Expressed as Heat Flux into Sea Water Area Integrated')
1580 
1581  handles%id_total_heat_content_lprec = register_scalar_field('ocean_model', &
1582  'total_heat_content_lprec', time, diag, &
1583  long_name='Area integrated heat content (relative to 0C) of liquid precip', &
1584  units='W', cmor_field_name='total_hfrainds', &
1585  cmor_standard_name= &
1586  'temperature_flux_due_to_rainfall_expressed_as_heat_flux_into_sea_water_area_integrated',&
1587  cmor_long_name= &
1588  'Temperature Flux due to Rainfall Expressed as Heat Flux into Sea Water Area Integrated')
1589 
1590  handles%id_total_heat_content_fprec = register_scalar_field('ocean_model', &
1591  'total_heat_content_fprec', time, diag, &
1592  long_name='Area integrated heat content (relative to 0C) of frozen precip',&
1593  units='W')
1594 
1595  handles%id_total_heat_content_icemelt = register_scalar_field('ocean_model', &
1596  'total_heat_content_icemelt', time, diag,long_name= &
1597  'Area integrated heat content (relative to 0C) of water flux due sea ice melting/freezing', &
1598  units='W')
1599 
1600  handles%id_total_heat_content_vprec = register_scalar_field('ocean_model', &
1601  'total_heat_content_vprec', time, diag, &
1602  long_name='Area integrated heat content (relative to 0C) of virtual precip',&
1603  units='W')
1604 
1605  handles%id_total_heat_content_cond = register_scalar_field('ocean_model', &
1606  'total_heat_content_cond', time, diag, &
1607  long_name='Area integrated heat content (relative to 0C) of condensate',&
1608  units='W')
1609 
1610  handles%id_total_heat_content_surfwater = register_scalar_field('ocean_model', &
1611  'total_heat_content_surfwater', time, diag, &
1612  long_name='Area integrated heat content (relative to 0C) of water crossing surface',&
1613  units='W')
1614 
1615  handles%id_total_heat_content_massout = register_scalar_field('ocean_model', &
1616  'total_heat_content_massout', time, diag, &
1617  long_name='Area integrated heat content (relative to 0C) of water leaving ocean', &
1618  units='W', &
1619  cmor_field_name='total_hfevapds', &
1620  cmor_standard_name= &
1621  'temperature_flux_due_to_evaporation_expressed_as_heat_flux_out_of_sea_water_area_integrated',&
1622  cmor_long_name='Heat Flux Out of Sea Water due to Evaporating Water Area Integrated')
1623 
1624  handles%id_total_heat_content_massin = register_scalar_field('ocean_model', &
1625  'total_heat_content_massin', time, diag, &
1626  long_name='Area integrated heat content (relative to 0C) of water entering ocean',&
1627  units='W')
1628 
1629  handles%id_total_net_heat_coupler = register_scalar_field('ocean_model', &
1630  'total_net_heat_coupler', time, diag, &
1631  long_name='Area integrated surface heat flux from SW+LW+latent+sensible+seaice_melt_heat (via the coupler)',&
1632  units='W')
1633 
1634  handles%id_total_net_heat_surface = register_scalar_field('ocean_model', &
1635  'total_net_heat_surface', time, diag, &
1636  long_name='Area integrated surface heat flux from SW+LW+lat+sens+mass+frazil+restore or flux adjustments', &
1637  units='W', &
1638  cmor_field_name='total_hfds', &
1639  cmor_standard_name='surface_downward_heat_flux_in_sea_water_area_integrated', &
1640  cmor_long_name= &
1641  'Surface Ocean Heat Flux from SW+LW+latent+sensible+mass transfer+frazil Area Integrated')
1642 
1643  handles%id_total_sw = register_scalar_field('ocean_model', &
1644  'total_sw', time, diag, &
1645  long_name='Area integrated net downward shortwave at sea water surface', &
1646  units='W', &
1647  cmor_field_name='total_rsntds', &
1648  cmor_standard_name='net_downward_shortwave_flux_at_sea_water_surface_area_integrated',&
1649  cmor_long_name= &
1650  'Net Downward Shortwave Radiation at Sea Water Surface Area Integrated')
1651 
1652  handles%id_total_LwLatSens = register_scalar_field('ocean_model',&
1653  'total_LwLatSens', time, diag, &
1654  long_name='Area integrated longwave+latent+sensible heating',&
1655  units='W')
1656 
1657  handles%id_total_lw = register_scalar_field('ocean_model', &
1658  'total_lw', time, diag, &
1659  long_name='Area integrated net downward longwave at sea water surface', &
1660  units='W', &
1661  cmor_field_name='total_rlntds', &
1662  cmor_standard_name='surface_net_downward_longwave_flux_area_integrated',&
1663  cmor_long_name= &
1664  'Surface Net Downward Longwave Radiation Area Integrated')
1665 
1666  handles%id_total_lat = register_scalar_field('ocean_model', &
1667  'total_lat', time, diag, &
1668  long_name='Area integrated surface downward latent heat flux', &
1669  units='W', &
1670  cmor_field_name='total_hflso', &
1671  cmor_standard_name='surface_downward_latent_heat_flux_area_integrated',&
1672  cmor_long_name= &
1673  'Surface Downward Latent Heat Flux Area Integrated')
1674 
1675  handles%id_total_lat_evap = register_scalar_field('ocean_model', &
1676  'total_lat_evap', time, diag, &
1677  long_name='Area integrated latent heat flux due to evap/condense',&
1678  units='W')
1679 
1680  handles%id_total_lat_fprec = register_scalar_field('ocean_model', &
1681  'total_lat_fprec', time, diag, &
1682  long_name='Area integrated latent heat flux due to melting frozen precip', &
1683  units='W', &
1684  cmor_field_name='total_hfsnthermds', &
1685  cmor_standard_name='heat_flux_into_sea_water_due_to_snow_thermodynamics_area_integrated',&
1686  cmor_long_name= &
1687  'Latent Heat to Melt Frozen Precipitation Area Integrated')
1688 
1689  handles%id_total_lat_frunoff = register_scalar_field('ocean_model', &
1690  'total_lat_frunoff', time, diag, &
1691  long_name='Area integrated latent heat flux due to melting icebergs', &
1692  units='W', &
1693  cmor_field_name='total_hfibthermds', &
1694  cmor_standard_name='heat_flux_into_sea_water_due_to_iceberg_thermodynamics_area_integrated',&
1695  cmor_long_name= &
1696  'Heat Flux into Sea Water due to Iceberg Thermodynamics Area Integrated')
1697 
1698  handles%id_total_sens = register_scalar_field('ocean_model', &
1699  'total_sens', time, diag, &
1700  long_name='Area integrated downward sensible heat flux', &
1701  units='W', &
1702  cmor_field_name='total_hfsso', &
1703  cmor_standard_name='surface_downward_sensible_heat_flux_area_integrated',&
1704  cmor_long_name= &
1705  'Surface Downward Sensible Heat Flux Area Integrated')
1706 
1707  handles%id_total_heat_added = register_scalar_field('ocean_model',&
1708  'total_heat_adjustment', time, diag, &
1709  long_name='Area integrated surface heat flux from restoring and/or flux adjustment', &
1710  units='W')
1711 
1712  handles%id_total_seaice_melt_heat = register_scalar_field('ocean_model',&
1713  'total_seaice_melt_heat', time, diag, &
1714  long_name='Area integrated surface heat flux from snow and sea ice melt', &
1715  units='W')
1716 
1717  !===============================================================
1718  ! area averaged surface heat fluxes
1719 
1720  handles%id_net_heat_coupler_ga = register_scalar_field('ocean_model', &
1721  'net_heat_coupler_ga', time, diag, &
1722  long_name='Area averaged surface heat flux from SW+LW+latent+sensible+seaice_melt_heat (via the coupler)',&
1723  units='W m-2')
1724 
1725  handles%id_net_heat_surface_ga = register_scalar_field('ocean_model', &
1726  'net_heat_surface_ga', time, diag, long_name= &
1727  'Area averaged surface heat flux from SW+LW+lat+sens+mass+frazil+restore+seaice_melt_heat or flux adjustments', &
1728  units='W m-2', &
1729  cmor_field_name='ave_hfds', &
1730  cmor_standard_name='surface_downward_heat_flux_in_sea_water_area_averaged', &
1731  cmor_long_name= &
1732  'Surface Ocean Heat Flux from SW+LW+latent+sensible+mass transfer+frazil Area Averaged')
1733 
1734  handles%id_sw_ga = register_scalar_field('ocean_model', &
1735  'sw_ga', time, diag, &
1736  long_name='Area averaged net downward shortwave at sea water surface', &
1737  units='W m-2', &
1738  cmor_field_name='ave_rsntds', &
1739  cmor_standard_name='net_downward_shortwave_flux_at_sea_water_surface_area_averaged',&
1740  cmor_long_name= &
1741  'Net Downward Shortwave Radiation at Sea Water Surface Area Averaged')
1742 
1743  handles%id_LwLatSens_ga = register_scalar_field('ocean_model',&
1744  'LwLatSens_ga', time, diag, &
1745  long_name='Area averaged longwave+latent+sensible heating',&
1746  units='W m-2')
1747 
1748  handles%id_lw_ga = register_scalar_field('ocean_model', &
1749  'lw_ga', time, diag, &
1750  long_name='Area averaged net downward longwave at sea water surface', &
1751  units='W m-2', &
1752  cmor_field_name='ave_rlntds', &
1753  cmor_standard_name='surface_net_downward_longwave_flux_area_averaged',&
1754  cmor_long_name= &
1755  'Surface Net Downward Longwave Radiation Area Averaged')
1756 
1757  handles%id_lat_ga = register_scalar_field('ocean_model', &
1758  'lat_ga', time, diag, &
1759  long_name='Area averaged surface downward latent heat flux', &
1760  units='W m-2', &
1761  cmor_field_name='ave_hflso', &
1762  cmor_standard_name='surface_downward_latent_heat_flux_area_averaged',&
1763  cmor_long_name= &
1764  'Surface Downward Latent Heat Flux Area Averaged')
1765 
1766  handles%id_sens_ga = register_scalar_field('ocean_model', &
1767  'sens_ga', time, diag, &
1768  long_name='Area averaged downward sensible heat flux', &
1769  units='W m-2', &
1770  cmor_field_name='ave_hfsso', &
1771  cmor_standard_name='surface_downward_sensible_heat_flux_area_averaged',&
1772  cmor_long_name= &
1773  'Surface Downward Sensible Heat Flux Area Averaged')
1774 
1775 
1776  !===============================================================
1777  ! maps of surface salt fluxes, virtual precip fluxes, and adjustments
1778 
1779  handles%id_saltflux = register_diag_field('ocean_model', 'salt_flux', diag%axesT1, time,&
1780  'Net salt flux into ocean at surface (restoring + sea-ice)', &
1781  'kg m-2 s-1',cmor_field_name='sfdsi', &
1782  cmor_standard_name='downward_sea_ice_basal_salt_flux', &
1783  cmor_long_name='Downward Sea Ice Basal Salt Flux')
1784 
1785  handles%id_saltFluxIn = register_diag_field('ocean_model', 'salt_flux_in', diag%axesT1, time, &
1786  'Salt flux into ocean at surface from coupler', 'kg m-2 s-1')
1787 
1788  handles%id_saltFluxAdded = register_diag_field('ocean_model', 'salt_flux_added', &
1789  diag%axesT1,time,'Salt flux into ocean at surface due to restoring or flux adjustment', &
1790  'kg m-2 s-1')
1791 
1792  handles%id_saltFluxGlobalAdj = register_scalar_field('ocean_model', &
1793  'salt_flux_global_restoring_adjustment', time, diag, &
1794  'Adjustment needed to balance net global salt flux into ocean at surface', &
1795  'kg m-2 s-1')
1796 
1797  handles%id_vPrecGlobalAdj = register_scalar_field('ocean_model', &
1798  'vprec_global_adjustment', time, diag, &
1799  'Adjustment needed to adjust net vprec into ocean to zero', &
1800  'kg m-2 s-1')
1801 
1802  handles%id_netFWGlobalAdj = register_scalar_field('ocean_model', &
1803  'net_fresh_water_global_adjustment', time, diag, &
1804  'Adjustment needed to adjust net fresh water into ocean to zero',&
1805  'kg m-2 s-1')
1806 
1807  handles%id_saltFluxGlobalScl = register_scalar_field('ocean_model', &
1808  'salt_flux_global_restoring_scaling', time, diag, &
1809  'Scaling applied to balance net global salt flux into ocean at surface', &
1810  'nondim')
1811 
1812  handles%id_vPrecGlobalScl = register_scalar_field('ocean_model',&
1813  'vprec_global_scaling', time, diag, &
1814  'Scaling applied to adjust net vprec into ocean to zero', &
1815  'nondim')
1816 
1817  handles%id_netFWGlobalScl = register_scalar_field('ocean_model', &
1818  'net_fresh_water_global_scaling', time, diag, &
1819  'Scaling applied to adjust net fresh water into ocean to zero', &
1820  'nondim')
1821 
1822  !===============================================================
1823  ! area integrals of surface salt fluxes
1824 
1825  handles%id_total_saltflux = register_scalar_field('ocean_model', &
1826  'total_salt_flux', time, diag, &
1827  long_name='Area integrated surface salt flux', units='kg', &
1828  cmor_field_name='total_sfdsi', &
1829  cmor_units='kg s-1', &
1830  cmor_standard_name='downward_sea_ice_basal_salt_flux_area_integrated',&
1831  cmor_long_name='Downward Sea Ice Basal Salt Flux Area Integrated')
1832 
1833  handles%id_total_saltFluxIn = register_scalar_field('ocean_model', 'total_salt_Flux_In', &
1834  time, diag, long_name='Area integrated surface salt flux at surface from coupler', units='kg')
1835 
1836  handles%id_total_saltFluxAdded = register_scalar_field('ocean_model', 'total_salt_Flux_Added', &
1837  time, diag, long_name='Area integrated surface salt flux due to restoring or flux adjustment', units='kg')
1838 
1839 
1840 end subroutine register_forcing_type_diags
1841 
1842 !> Accumulate the forcing over time steps, taking input from a mechanical forcing type
1843 !! and a temporary forcing-flux type.
1844 subroutine forcing_accumulate(flux_tmp, forces, fluxes, dt, G, wt2)
1845  type(forcing), intent(in) :: flux_tmp !< A temporary structure with current
1846  !!thermodynamic forcing fields
1847  type(mech_forcing), intent(in) :: forces !< A structure with the driving mechanical forces
1848  type(forcing), intent(inout) :: fluxes !< A structure containing time-averaged
1849  !! thermodynamic forcing fields
1850  real, intent(in) :: dt !< The elapsed time since the last call to this subroutine [s]
1851  type(ocean_grid_type), intent(inout) :: g !< The ocean's grid structure
1852  real, intent(out) :: wt2 !< The relative weight of the new fluxes
1853 
1854  ! This subroutine copies mechancal forcing from flux_tmp to fluxes and
1855  ! stores the time-weighted averages of the various buoyancy fluxes in fluxes,
1856  ! and increments the amount of time over which the buoyancy forcing should be
1857  ! applied, all via a call to fluxes accumulate.
1858 
1859  call fluxes_accumulate(flux_tmp, fluxes, dt, g, wt2, forces)
1860 
1861 end subroutine forcing_accumulate
1862 
1863 !> Accumulate the thermodynamic fluxes over time steps
1864 subroutine fluxes_accumulate(flux_tmp, fluxes, dt, G, wt2, forces)
1865  type(forcing), intent(in) :: flux_tmp !< A temporary structure with current
1866  !! thermodynamic forcing fields
1867  type(forcing), intent(inout) :: fluxes !< A structure containing time-averaged
1868  !! thermodynamic forcing fields
1869  real, intent(in) :: dt !< The elapsed time since the last call to this subroutine [s]
1870  type(ocean_grid_type), intent(inout) :: g !< The ocean's grid structure
1871  real, intent(out) :: wt2 !< The relative weight of the new fluxes
1872  type(mech_forcing), optional, intent(in) :: forces !< A structure with the driving mechanical forces
1873 
1874  ! This subroutine copies mechancal forcing from flux_tmp to fluxes and
1875  ! stores the time-weighted averages of the various buoyancy fluxes in fluxes,
1876  ! and increments the amount of time over which the buoyancy forcing should be
1877  ! applied.
1878 
1879  real :: wt1
1880  integer :: i, j, is, ie, js, je, isq, ieq, jsq, jeq, i0, j0
1881  integer :: isd, ied, jsd, jed, isdb, iedb, jsdb, jedb, isr, ier, jsr, jer
1882  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
1883  isq = g%IscB ; ieq = g%IecB ; jsq = g%JscB ; jeq = g%JecB
1884  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
1885  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
1886 
1887 
1888  if (fluxes%dt_buoy_accum < 0) call mom_error(fatal, "forcing_accumulate: "//&
1889  "fluxes must be initialzed before it can be augmented.")
1890 
1891  ! wt1 is the relative weight of the previous fluxes.
1892  wt1 = fluxes%dt_buoy_accum / (fluxes%dt_buoy_accum + dt)
1893  wt2 = 1.0 - wt1 ! = dt / (fluxes%dt_buoy_accum + dt)
1894  fluxes%dt_buoy_accum = fluxes%dt_buoy_accum + dt
1895 
1896  ! Copy over the pressure fields and accumulate averages of ustar, either from the forcing
1897  ! type or from the temporary fluxes type.
1898  if (present(forces)) then
1899  do j=js,je ; do i=is,ie
1900  fluxes%p_surf(i,j) = forces%p_surf(i,j)
1901  fluxes%p_surf_full(i,j) = forces%p_surf_full(i,j)
1902 
1903  fluxes%ustar(i,j) = wt1*fluxes%ustar(i,j) + wt2*forces%ustar(i,j)
1904  enddo ; enddo
1905  else
1906  do j=js,je ; do i=is,ie
1907  fluxes%p_surf(i,j) = flux_tmp%p_surf(i,j)
1908  fluxes%p_surf_full(i,j) = flux_tmp%p_surf_full(i,j)
1909 
1910  fluxes%ustar(i,j) = wt1*fluxes%ustar(i,j) + wt2*flux_tmp%ustar(i,j)
1911  enddo ; enddo
1912  endif
1913 
1914  ! Average the water, heat, and salt fluxes, and ustar.
1915  do j=js,je ; do i=is,ie
1916 !### Replace the expression for ustar_gustless with this one...
1917 ! fluxes%ustar_gustless(i,j) = wt1*fluxes%ustar_gustless(i,j) + wt2*flux_tmp%ustar_gustless(i,j)
1918  fluxes%ustar_gustless(i,j) = flux_tmp%ustar_gustless(i,j)
1919 
1920  fluxes%evap(i,j) = wt1*fluxes%evap(i,j) + wt2*flux_tmp%evap(i,j)
1921  fluxes%lprec(i,j) = wt1*fluxes%lprec(i,j) + wt2*flux_tmp%lprec(i,j)
1922  fluxes%fprec(i,j) = wt1*fluxes%fprec(i,j) + wt2*flux_tmp%fprec(i,j)
1923  fluxes%vprec(i,j) = wt1*fluxes%vprec(i,j) + wt2*flux_tmp%vprec(i,j)
1924  fluxes%lrunoff(i,j) = wt1*fluxes%lrunoff(i,j) + wt2*flux_tmp%lrunoff(i,j)
1925  fluxes%frunoff(i,j) = wt1*fluxes%frunoff(i,j) + wt2*flux_tmp%frunoff(i,j)
1926  fluxes%seaice_melt(i,j) = wt1*fluxes%seaice_melt(i,j) + wt2*flux_tmp%seaice_melt(i,j)
1927  fluxes%sw(i,j) = wt1*fluxes%sw(i,j) + wt2*flux_tmp%sw(i,j)
1928  fluxes%sw_vis_dir(i,j) = wt1*fluxes%sw_vis_dir(i,j) + wt2*flux_tmp%sw_vis_dir(i,j)
1929  fluxes%sw_vis_dif(i,j) = wt1*fluxes%sw_vis_dif(i,j) + wt2*flux_tmp%sw_vis_dif(i,j)
1930  fluxes%sw_nir_dir(i,j) = wt1*fluxes%sw_nir_dir(i,j) + wt2*flux_tmp%sw_nir_dir(i,j)
1931  fluxes%sw_nir_dif(i,j) = wt1*fluxes%sw_nir_dif(i,j) + wt2*flux_tmp%sw_nir_dif(i,j)
1932  fluxes%lw(i,j) = wt1*fluxes%lw(i,j) + wt2*flux_tmp%lw(i,j)
1933  fluxes%latent(i,j) = wt1*fluxes%latent(i,j) + wt2*flux_tmp%latent(i,j)
1934  fluxes%sens(i,j) = wt1*fluxes%sens(i,j) + wt2*flux_tmp%sens(i,j)
1935 
1936  fluxes%salt_flux(i,j) = wt1*fluxes%salt_flux(i,j) + wt2*flux_tmp%salt_flux(i,j)
1937  enddo ; enddo
1938  if (associated(fluxes%heat_added) .and. associated(flux_tmp%heat_added)) then
1939  do j=js,je ; do i=is,ie
1940  fluxes%heat_added(i,j) = wt1*fluxes%heat_added(i,j) + wt2*flux_tmp%heat_added(i,j)
1941  enddo ; enddo
1942  endif
1943  ! These might always be associated, in which case they can be combined?
1944  if (associated(fluxes%heat_content_cond) .and. associated(flux_tmp%heat_content_cond)) then
1945  do j=js,je ; do i=is,ie
1946  fluxes%heat_content_cond(i,j) = wt1*fluxes%heat_content_cond(i,j) + wt2*flux_tmp%heat_content_cond(i,j)
1947  enddo ; enddo
1948  endif
1949  if (associated(fluxes%heat_content_lprec) .and. associated(flux_tmp%heat_content_lprec)) then
1950  do j=js,je ; do i=is,ie
1951  fluxes%heat_content_lprec(i,j) = wt1*fluxes%heat_content_lprec(i,j) + wt2*flux_tmp%heat_content_lprec(i,j)
1952  enddo ; enddo
1953  endif
1954  if (associated(fluxes%heat_content_fprec) .and. associated(flux_tmp%heat_content_fprec)) then
1955  do j=js,je ; do i=is,ie
1956  fluxes%heat_content_fprec(i,j) = wt1*fluxes%heat_content_fprec(i,j) + wt2*flux_tmp%heat_content_fprec(i,j)
1957  enddo ; enddo
1958  endif
1959  if (associated(fluxes%heat_content_icemelt) .and. associated(flux_tmp%heat_content_icemelt)) then
1960  do j=js,je ; do i=is,ie
1961  fluxes%heat_content_icemelt(i,j) = wt1*fluxes%heat_content_icemelt(i,j) + wt2*flux_tmp%heat_content_icemelt(i,j)
1962  enddo ; enddo
1963  endif
1964  if (associated(fluxes%heat_content_vprec) .and. associated(flux_tmp%heat_content_vprec)) then
1965  do j=js,je ; do i=is,ie
1966  fluxes%heat_content_vprec(i,j) = wt1*fluxes%heat_content_vprec(i,j) + wt2*flux_tmp%heat_content_vprec(i,j)
1967  enddo ; enddo
1968  endif
1969  if (associated(fluxes%heat_content_lrunoff) .and. associated(flux_tmp%heat_content_lrunoff)) then
1970  do j=js,je ; do i=is,ie
1971  fluxes%heat_content_lrunoff(i,j) = wt1*fluxes%heat_content_lrunoff(i,j) + wt2*flux_tmp%heat_content_lrunoff(i,j)
1972  enddo ; enddo
1973  endif
1974  if (associated(fluxes%heat_content_frunoff) .and. associated(flux_tmp%heat_content_frunoff)) then
1975  do j=js,je ; do i=is,ie
1976  fluxes%heat_content_frunoff(i,j) = wt1*fluxes%heat_content_frunoff(i,j) + wt2*flux_tmp%heat_content_frunoff(i,j)
1977  enddo ; enddo
1978  endif
1979  if (associated(fluxes%heat_content_icemelt) .and. associated(flux_tmp%heat_content_icemelt)) then
1980  do j=js,je ; do i=is,ie
1981  fluxes%heat_content_icemelt(i,j) = wt1*fluxes%heat_content_icemelt(i,j) + wt2*flux_tmp%heat_content_icemelt(i,j)
1982  enddo ; enddo
1983  endif
1984 
1985  if (associated(fluxes%ustar_shelf) .and. associated(flux_tmp%ustar_shelf)) then
1986  do i=isd,ied ; do j=jsd,jed
1987  fluxes%ustar_shelf(i,j) = flux_tmp%ustar_shelf(i,j)
1988  enddo ; enddo
1989  endif
1990  if (associated(fluxes%iceshelf_melt) .and. associated(flux_tmp%iceshelf_melt)) then
1991  do i=isd,ied ; do j=jsd,jed
1992  fluxes%iceshelf_melt(i,j) = flux_tmp%iceshelf_melt(i,j)
1993  enddo ; enddo
1994  endif
1995  if (associated(fluxes%frac_shelf_h) .and. associated(flux_tmp%frac_shelf_h)) then
1996  do i=isd,ied ; do j=jsd,jed
1997  fluxes%frac_shelf_h(i,j) = flux_tmp%frac_shelf_h(i,j)
1998  enddo ; enddo
1999  endif
2000 
2001  if (coupler_type_initialized(fluxes%tr_fluxes) .and. &
2002  coupler_type_initialized(flux_tmp%tr_fluxes)) &
2003  call coupler_type_increment_data(flux_tmp%tr_fluxes, fluxes%tr_fluxes, &
2004  scale_factor=wt2, scale_prev=wt1)
2005 
2006 end subroutine fluxes_accumulate
2007 
2008 !> This subroutine copies the computational domains of common forcing fields
2009 !! from a mech_forcing type to a (thermodynamic) forcing type.
2010 subroutine copy_common_forcing_fields(forces, fluxes, G, skip_pres)
2011  type(mech_forcing), intent(in) :: forces !< A structure with the driving mechanical forces
2012  type(forcing), intent(inout) :: fluxes !< A structure containing thermodynamic forcing fields
2013  type(ocean_grid_type), intent(in) :: g !< grid type
2014  logical, optional, intent(in) :: skip_pres !< If present and true, do not copy pressure fields.
2015 
2016  real :: taux2, tauy2 ! Squared wind stress components [Pa2].
2017  logical :: do_pres
2018  integer :: i, j, is, ie, js, je
2019  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
2020 
2021  do_pres = .true. ; if (present(skip_pres)) do_pres = .not.skip_pres
2022 
2023  if (associated(forces%ustar) .and. associated(fluxes%ustar)) then
2024  do j=js,je ; do i=is,ie
2025  fluxes%ustar(i,j) = forces%ustar(i,j)
2026  enddo ; enddo
2027  endif
2028 
2029  if (do_pres) then
2030  if (associated(forces%p_surf) .and. associated(fluxes%p_surf)) then
2031  do j=js,je ; do i=is,ie
2032  fluxes%p_surf(i,j) = forces%p_surf(i,j)
2033  enddo ; enddo
2034  endif
2035 
2036  if (associated(forces%p_surf_full) .and. associated(fluxes%p_surf_full)) then
2037  do j=js,je ; do i=is,ie
2038  fluxes%p_surf_full(i,j) = forces%p_surf_full(i,j)
2039  enddo ; enddo
2040  endif
2041 
2042  if (associated(forces%p_surf_SSH, forces%p_surf_full)) then
2043  fluxes%p_surf_SSH => fluxes%p_surf_full
2044  elseif (associated(forces%p_surf_SSH, forces%p_surf)) then
2045  fluxes%p_surf_SSH => fluxes%p_surf
2046  endif
2047  endif
2048 
2049 end subroutine copy_common_forcing_fields
2050 
2051 
2052 !> This subroutine calculates certain derived forcing fields based on information
2053 !! from a mech_forcing type and stores them in a (thermodynamic) forcing type.
2054 subroutine set_derived_forcing_fields(forces, fluxes, G, US, Rho0)
2055  type(mech_forcing), intent(in) :: forces !< A structure with the driving mechanical forces
2056  type(forcing), intent(inout) :: fluxes !< A structure containing thermodynamic forcing fields
2057  type(ocean_grid_type), intent(in) :: g !< grid type
2058  type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
2059  real, intent(in) :: rho0 !< A reference density of seawater [kg m-3],
2060  !! as used to calculate ustar.
2061 
2062  real :: taux2, tauy2 ! Squared wind stress components [Pa2].
2063  real :: irho0 ! Inverse of the mean density rescaled to [Z2 m / kg ~> m3 kg-1]
2064  integer :: i, j, is, ie, js, je
2065  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
2066 
2067  irho0 = us%m_to_Z**2 / rho0
2068 
2069  if (associated(forces%taux) .and. associated(forces%tauy) .and. &
2070  associated(fluxes%ustar_gustless)) then
2071  do j=js,je ; do i=is,ie
2072  taux2 = 0.0
2073  if ((g%mask2dCu(i-1,j) + g%mask2dCu(i,j)) > 0) &
2074  taux2 = (g%mask2dCu(i-1,j) * forces%taux(i-1,j)**2 + &
2075  g%mask2dCu(i,j) * forces%taux(i,j)**2) / &
2076  (g%mask2dCu(i-1,j) + g%mask2dCu(i,j))
2077  tauy2 = 0.0
2078  if ((g%mask2dCv(i,j-1) + g%mask2dCv(i,j)) > 0) &
2079  tauy2 = (g%mask2dCv(i,j-1) * forces%tauy(i,j-1)**2 + &
2080  g%mask2dCv(i,j) * forces%tauy(i,j)**2) / &
2081  (g%mask2dCv(i,j-1) + g%mask2dCv(i,j))
2082 
2083  fluxes%ustar_gustless(i,j) = us%m_to_Z*us%T_to_s * sqrt(sqrt(taux2 + tauy2) / rho0)
2084 !### Change to:
2085 ! fluxes%ustar_gustless(i,j) = sqrt(sqrt(taux2 + tauy2) * Irho0)
2086  enddo ; enddo
2087  endif
2088 
2089 end subroutine set_derived_forcing_fields
2090 
2091 
2092 !> This subroutine determines the net mass source to the ocean from
2093 !! a (thermodynamic) forcing type and stores it in a mech_forcing type.
2094 subroutine set_net_mass_forcing(fluxes, forces, G)
2095  type(forcing), intent(in) :: fluxes !< A structure containing thermodynamic forcing fields
2096  type(mech_forcing), intent(inout) :: forces !< A structure with the driving mechanical forces
2097  type(ocean_grid_type), intent(in) :: g !< The ocean grid type
2098 
2099  if (associated(forces%net_mass_src)) &
2100  call get_net_mass_forcing(fluxes, g, forces%net_mass_src)
2101 
2102 end subroutine set_net_mass_forcing
2103 
2104 !> This subroutine calculates determines the net mass source to the ocean from
2105 !! a (thermodynamic) forcing type and stores it in a provided array.
2106 subroutine get_net_mass_forcing(fluxes, G, net_mass_src)
2107  type(forcing), intent(in) :: fluxes !< A structure containing thermodynamic forcing fields
2108  type(ocean_grid_type), intent(in) :: g !< The ocean grid type
2109  real, dimension(SZI_(G),SZJ_(G)), intent(out) :: net_mass_src !< The net mass flux of water into the ocean
2110  !! [kg m-2 s-1].
2111 
2112  integer :: i, j, is, ie, js, je
2113  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
2114 
2115  net_mass_src(:,:) = 0.0
2116  if (associated(fluxes%lprec)) then ; do j=js,je ; do i=is,ie
2117  net_mass_src(i,j) = net_mass_src(i,j) + fluxes%lprec(i,j)
2118  enddo ; enddo ; endif
2119  if (associated(fluxes%fprec)) then ; do j=js,je ; do i=is,ie
2120  net_mass_src(i,j) = net_mass_src(i,j) + fluxes%fprec(i,j)
2121  enddo ; enddo ; endif
2122  if (associated(fluxes%vprec)) then ; do j=js,je ; do i=is,ie
2123  net_mass_src(i,j) = net_mass_src(i,j) + fluxes%vprec(i,j)
2124  enddo ; enddo ; endif
2125  if (associated(fluxes%lrunoff)) then ; do j=js,je ; do i=is,ie
2126  net_mass_src(i,j) = net_mass_src(i,j) + fluxes%lrunoff(i,j)
2127  enddo ; enddo ; endif
2128  if (associated(fluxes%frunoff)) then ; do j=js,je ; do i=is,ie
2129  net_mass_src(i,j) = net_mass_src(i,j) + fluxes%frunoff(i,j)
2130  enddo ; enddo ; endif
2131  if (associated(fluxes%evap)) then ; do j=js,je ; do i=is,ie
2132  net_mass_src(i,j) = net_mass_src(i,j) + fluxes%evap(i,j)
2133  enddo ; enddo ; endif
2134  if (associated(fluxes%seaice_melt)) then ; do j=js,je ; do i=is,ie
2135  net_mass_src(i,j) = net_mass_src(i,j) + fluxes%seaice_melt(i,j)
2136  enddo ; enddo ; endif
2137 
2138 end subroutine get_net_mass_forcing
2139 
2140 !> This subroutine copies the computational domains of common forcing fields
2141 !! from a mech_forcing type to a (thermodynamic) forcing type.
2142 subroutine copy_back_forcing_fields(fluxes, forces, G)
2143  type(forcing), intent(in) :: fluxes !< A structure containing thermodynamic forcing fields
2144  type(mech_forcing), intent(inout) :: forces !< A structure with the driving mechanical forces
2145  type(ocean_grid_type), intent(in) :: g !< grid type
2146 
2147  real :: taux2, tauy2 ! Squared wind stress components [Pa2].
2148  integer :: i, j, is, ie, js, je
2149  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
2150 
2151  if (associated(forces%ustar) .and. associated(fluxes%ustar)) then
2152  do j=js,je ; do i=is,ie
2153  forces%ustar(i,j) = fluxes%ustar(i,j)
2154  enddo ; enddo
2155  endif
2156 
2157 end subroutine copy_back_forcing_fields
2158 
2159 !> Offer mechanical forcing fields for diagnostics for those
2160 !! fields registered as part of register_forcing_type_diags.
2161 subroutine mech_forcing_diags(forces, dt, G, diag, handles)
2162  type(mech_forcing), intent(in) :: forces !< A structure with the driving mechanical forces
2163  real, intent(in) :: dt !< time step
2164  type(ocean_grid_type), intent(in) :: g !< grid type
2165  type(diag_ctrl), intent(in) :: diag !< diagnostic type
2166  type(forcing_diags), intent(inout) :: handles !< diagnostic id for diag_manager
2167 
2168  integer :: i,j,is,ie,js,je
2169 
2170  call cpu_clock_begin(handles%id_clock_forcing)
2171 
2172  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
2173  if (query_averaging_enabled(diag)) then
2174 
2175  if ((handles%id_taux > 0) .and. associated(forces%taux)) &
2176  call post_data(handles%id_taux, forces%taux, diag)
2177 
2178  if ((handles%id_tauy > 0) .and. associated(forces%tauy)) &
2179  call post_data(handles%id_tauy, forces%tauy, diag)
2180 
2181  if ((handles%id_mass_berg > 0) .and. associated(forces%mass_berg)) &
2182  call post_data(handles%id_mass_berg, forces%mass_berg, diag)
2183 
2184  if ((handles%id_area_berg > 0) .and. associated(forces%area_berg)) &
2185  call post_data(handles%id_area_berg, forces%area_berg, diag)
2186 
2187  endif
2188 
2189  call cpu_clock_end(handles%id_clock_forcing)
2190 end subroutine mech_forcing_diags
2191 
2192 
2193 !> Offer buoyancy forcing fields for diagnostics for those
2194 !! fields registered as part of register_forcing_type_diags.
2195 subroutine forcing_diagnostics(fluxes, sfc_state, dt, G, diag, handles)
2196  type(forcing), intent(in) :: fluxes !< A structure containing thermodynamic forcing fields
2197  type(surface), intent(in) :: sfc_state !< A structure containing fields that
2198  !! describe the surface state of the ocean.
2199  real, intent(in) :: dt !< time step
2200  type(ocean_grid_type), intent(in) :: g !< grid type
2201  type(diag_ctrl), intent(in) :: diag !< diagnostic regulator
2202  type(forcing_diags), intent(inout) :: handles !< diagnostic ids
2203 
2204  ! local
2205  real, dimension(SZI_(G),SZJ_(G)) :: res
2206  real :: total_transport ! for diagnosing integrated boundary transport
2207  real :: ave_flux ! for diagnosing averaged boundary flux
2208  real :: c_p ! seawater heat capacity (J/(deg K * kg))
2209  real :: i_dt ! inverse time step
2210  real :: ppt2mks ! conversion between ppt and mks
2211  integer :: i,j,is,ie,js,je
2212 
2213  call cpu_clock_begin(handles%id_clock_forcing)
2214 
2215  c_p = fluxes%C_p
2216  i_dt = 1.0/dt
2217  ppt2mks = 1e-3
2218  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
2219 
2220  if (query_averaging_enabled(diag)) then
2221 
2222  ! post the diagnostics for surface mass fluxes ==================================
2223 
2224  if (handles%id_prcme > 0 .or. handles%id_total_prcme > 0 .or. handles%id_prcme_ga > 0) then
2225  do j=js,je ; do i=is,ie
2226  res(i,j) = 0.0
2227  if (associated(fluxes%lprec)) res(i,j) = res(i,j)+fluxes%lprec(i,j)
2228  if (associated(fluxes%fprec)) res(i,j) = res(i,j)+fluxes%fprec(i,j)
2229  ! fluxes%cond is not needed because it is derived from %evap > 0
2230  if (associated(fluxes%evap)) res(i,j) = res(i,j)+fluxes%evap(i,j)
2231  if (associated(fluxes%lrunoff)) res(i,j) = res(i,j)+fluxes%lrunoff(i,j)
2232  if (associated(fluxes%frunoff)) res(i,j) = res(i,j)+fluxes%frunoff(i,j)
2233  if (associated(fluxes%vprec)) res(i,j) = res(i,j)+fluxes%vprec(i,j)
2234  if (associated(fluxes%seaice_melt)) res(i,j) = res(i,j)+fluxes%seaice_melt(i,j)
2235  enddo ; enddo
2236  if (handles%id_prcme > 0) call post_data(handles%id_prcme, res, diag)
2237  if (handles%id_total_prcme > 0) then
2238  total_transport = global_area_integral(res,g)
2239  call post_data(handles%id_total_prcme, total_transport, diag)
2240  endif
2241  if (handles%id_prcme_ga > 0) then
2242  ave_flux = global_area_mean(res,g)
2243  call post_data(handles%id_prcme_ga, ave_flux, diag)
2244  endif
2245  endif
2246 
2247  if (handles%id_net_massout > 0 .or. handles%id_total_net_massout > 0) then
2248  do j=js,je ; do i=is,ie
2249  res(i,j) = 0.0
2250  if (associated(fluxes%lprec)) then
2251  if (fluxes%lprec(i,j) < 0.0) res(i,j) = res(i,j) + fluxes%lprec(i,j)
2252  endif
2253  if (associated(fluxes%vprec)) then
2254  if (fluxes%vprec(i,j) < 0.0) res(i,j) = res(i,j) + fluxes%vprec(i,j)
2255  endif
2256  if (associated(fluxes%evap)) then
2257  if (fluxes%evap(i,j) < 0.0) res(i,j) = res(i,j) + fluxes%evap(i,j)
2258  endif
2259  if (associated(fluxes%seaice_melt)) then
2260  if (fluxes%seaice_melt(i,j) < 0.0) &
2261  res(i,j) = res(i,j) + fluxes%seaice_melt(i,j)
2262  endif
2263  enddo ; enddo
2264  if (handles%id_net_massout > 0) call post_data(handles%id_net_massout, res, diag)
2265  if (handles%id_total_net_massout > 0) then
2266  total_transport = global_area_integral(res,g)
2267  call post_data(handles%id_total_net_massout, total_transport, diag)
2268  endif
2269  endif
2270 
2271  if (handles%id_massout_flux > 0 .and. associated(fluxes%netMassOut)) &
2272  call post_data(handles%id_massout_flux,fluxes%netMassOut,diag)
2273 
2274  if (handles%id_net_massin > 0 .or. handles%id_total_net_massin > 0) then
2275  do j=js,je ; do i=is,ie
2276  res(i,j) = 0.0
2277 
2278  if (associated(fluxes%fprec)) &
2279  res(i,j) = res(i,j) + fluxes%fprec(i,j)
2280  if (associated(fluxes%lrunoff)) &
2281  res(i,j) = res(i,j) + fluxes%lrunoff(i,j)
2282  if (associated(fluxes%frunoff)) &
2283  res(i,j) = res(i,j) + fluxes%frunoff(i,j)
2284 
2285  if (associated(fluxes%lprec)) then
2286  if (fluxes%lprec(i,j) > 0.0) res(i,j) = res(i,j) + fluxes%lprec(i,j)
2287  endif
2288  if (associated(fluxes%vprec)) then
2289  if (fluxes%vprec(i,j) > 0.0) res(i,j) = res(i,j) + fluxes%vprec(i,j)
2290  endif
2291  ! fluxes%cond is not needed because it is derived from %evap > 0
2292  if (associated(fluxes%evap)) then
2293  if (fluxes%evap(i,j) > 0.0) res(i,j) = res(i,j) + fluxes%evap(i,j)
2294  endif
2295  if (associated(fluxes%seaice_melt)) then
2296  if (fluxes%seaice_melt(i,j) > 0.0) &
2297  res(i,j) = res(i,j) + fluxes%seaice_melt(i,j)
2298  endif
2299  enddo ; enddo
2300  if (handles%id_net_massin > 0) call post_data(handles%id_net_massin, res, diag)
2301  if (handles%id_total_net_massin > 0) then
2302  total_transport = global_area_integral(res,g)
2303  call post_data(handles%id_total_net_massin, total_transport, diag)
2304  endif
2305  endif
2306 
2307  if (handles%id_massin_flux > 0 .and. associated(fluxes%netMassIn)) &
2308  call post_data(handles%id_massin_flux,fluxes%netMassIn,diag)
2309 
2310  if ((handles%id_evap > 0) .and. associated(fluxes%evap)) &
2311  call post_data(handles%id_evap, fluxes%evap, diag)
2312  if ((handles%id_total_evap > 0) .and. associated(fluxes%evap)) then
2313  total_transport = global_area_integral(fluxes%evap,g)
2314  call post_data(handles%id_total_evap, total_transport, diag)
2315  endif
2316  if ((handles%id_evap_ga > 0) .and. associated(fluxes%evap)) then
2317  ave_flux = global_area_mean(fluxes%evap,g)
2318  call post_data(handles%id_evap_ga, ave_flux, diag)
2319  endif
2320 
2321  if (associated(fluxes%lprec) .and. associated(fluxes%fprec)) then
2322  do j=js,je ; do i=is,ie
2323  res(i,j) = fluxes%lprec(i,j) + fluxes%fprec(i,j)
2324  enddo ; enddo
2325  if (handles%id_precip > 0) call post_data(handles%id_precip, res, diag)
2326  if (handles%id_total_precip > 0) then
2327  total_transport = global_area_integral(res,g)
2328  call post_data(handles%id_total_precip, total_transport, diag)
2329  endif
2330  if (handles%id_precip_ga > 0) then
2331  ave_flux = global_area_mean(res,g)
2332  call post_data(handles%id_precip_ga, ave_flux, diag)
2333  endif
2334  endif
2335 
2336  if (associated(fluxes%lprec)) then
2337  if (handles%id_lprec > 0) call post_data(handles%id_lprec, fluxes%lprec, diag)
2338  if (handles%id_total_lprec > 0) then
2339  total_transport = global_area_integral(fluxes%lprec,g)
2340  call post_data(handles%id_total_lprec, total_transport, diag)
2341  endif
2342  if (handles%id_lprec_ga > 0) then
2343  ave_flux = global_area_mean(fluxes%lprec,g)
2344  call post_data(handles%id_lprec_ga, ave_flux, diag)
2345  endif
2346  endif
2347 
2348  if (associated(fluxes%fprec)) then
2349  if (handles%id_fprec > 0) call post_data(handles%id_fprec, fluxes%fprec, diag)
2350  if (handles%id_total_fprec > 0) then
2351  total_transport = global_area_integral(fluxes%fprec,g)
2352  call post_data(handles%id_total_fprec, total_transport, diag)
2353  endif
2354  if (handles%id_fprec_ga > 0) then
2355  ave_flux = global_area_mean(fluxes%fprec,g)
2356  call post_data(handles%id_fprec_ga, ave_flux, diag)
2357  endif
2358  endif
2359 
2360  if (associated(fluxes%vprec)) then
2361  if (handles%id_vprec > 0) call post_data(handles%id_vprec, fluxes%vprec, diag)
2362  if (handles%id_total_vprec > 0) then
2363  total_transport = global_area_integral(fluxes%vprec,g)
2364  call post_data(handles%id_total_vprec, total_transport, diag)
2365  endif
2366  if (handles%id_vprec_ga > 0) then
2367  ave_flux = global_area_mean(fluxes%vprec,g)
2368  call post_data(handles%id_vprec_ga, ave_flux, diag)
2369  endif
2370  endif
2371 
2372  if (associated(fluxes%lrunoff)) then
2373  if (handles%id_lrunoff > 0) call post_data(handles%id_lrunoff, fluxes%lrunoff, diag)
2374  if (handles%id_total_lrunoff > 0) then
2375  total_transport = global_area_integral(fluxes%lrunoff,g)
2376  call post_data(handles%id_total_lrunoff, total_transport, diag)
2377  endif
2378  endif
2379 
2380  if (associated(fluxes%frunoff)) then
2381  if (handles%id_frunoff > 0) call post_data(handles%id_frunoff, fluxes%frunoff, diag)
2382  if (handles%id_total_frunoff > 0) then
2383  total_transport = global_area_integral(fluxes%frunoff,g)
2384  call post_data(handles%id_total_frunoff, total_transport, diag)
2385  endif
2386  endif
2387 
2388  if (associated(fluxes%seaice_melt)) then
2389  if (handles%id_seaice_melt > 0) call post_data(handles%id_seaice_melt, fluxes%seaice_melt, diag)
2390  if (handles%id_total_seaice_melt > 0) then
2391  total_transport = global_area_integral(fluxes%seaice_melt,g)
2392  call post_data(handles%id_total_seaice_melt, total_transport, diag)
2393  endif
2394  endif
2395 
2396  ! post diagnostics for boundary heat fluxes ====================================
2397 
2398  if ((handles%id_heat_content_lrunoff > 0) .and. associated(fluxes%heat_content_lrunoff)) &
2399  call post_data(handles%id_heat_content_lrunoff, fluxes%heat_content_lrunoff, diag)
2400  if ((handles%id_total_heat_content_lrunoff > 0) .and. associated(fluxes%heat_content_lrunoff)) then
2401  total_transport = global_area_integral(fluxes%heat_content_lrunoff,g)
2402  call post_data(handles%id_total_heat_content_lrunoff, total_transport, diag)
2403  endif
2404 
2405  if ((handles%id_heat_content_frunoff > 0) .and. associated(fluxes%heat_content_frunoff)) &
2406  call post_data(handles%id_heat_content_frunoff, fluxes%heat_content_frunoff, diag)
2407  if ((handles%id_total_heat_content_frunoff > 0) .and. associated(fluxes%heat_content_frunoff)) then
2408  total_transport = global_area_integral(fluxes%heat_content_frunoff,g)
2409  call post_data(handles%id_total_heat_content_frunoff, total_transport, diag)
2410  endif
2411 
2412  if ((handles%id_heat_content_lprec > 0) .and. associated(fluxes%heat_content_lprec)) &
2413  call post_data(handles%id_heat_content_lprec, fluxes%heat_content_lprec, diag)
2414  if ((handles%id_total_heat_content_lprec > 0) .and. associated(fluxes%heat_content_lprec)) then
2415  total_transport = global_area_integral(fluxes%heat_content_lprec,g)
2416  call post_data(handles%id_total_heat_content_lprec, total_transport, diag)
2417  endif
2418 
2419  if ((handles%id_heat_content_fprec > 0) .and. associated(fluxes%heat_content_fprec)) &
2420  call post_data(handles%id_heat_content_fprec, fluxes%heat_content_fprec, diag)
2421  if ((handles%id_total_heat_content_fprec > 0) .and. associated(fluxes%heat_content_fprec)) then
2422  total_transport = global_area_integral(fluxes%heat_content_fprec,g)
2423  call post_data(handles%id_total_heat_content_fprec, total_transport, diag)
2424  endif
2425 
2426  if ((handles%id_heat_content_icemelt > 0) .and. associated(fluxes%heat_content_icemelt)) &
2427  call post_data(handles%id_heat_content_icemelt, fluxes%heat_content_icemelt, diag)
2428  if ((handles%id_total_heat_content_icemelt > 0) .and. associated(fluxes%heat_content_icemelt)) then
2429  total_transport = global_area_integral(fluxes%heat_content_icemelt,g)
2430  call post_data(handles%id_total_heat_content_icemelt, total_transport, diag)
2431  endif
2432 
2433  if ((handles%id_heat_content_vprec > 0) .and. associated(fluxes%heat_content_vprec)) &
2434  call post_data(handles%id_heat_content_vprec, fluxes%heat_content_vprec, diag)
2435  if ((handles%id_total_heat_content_vprec > 0) .and. associated(fluxes%heat_content_vprec)) then
2436  total_transport = global_area_integral(fluxes%heat_content_vprec,g)
2437  call post_data(handles%id_total_heat_content_vprec, total_transport, diag)
2438  endif
2439 
2440  if ((handles%id_heat_content_cond > 0) .and. associated(fluxes%heat_content_cond)) &
2441  call post_data(handles%id_heat_content_cond, fluxes%heat_content_cond, diag)
2442  if ((handles%id_total_heat_content_cond > 0) .and. associated(fluxes%heat_content_cond)) then
2443  total_transport = global_area_integral(fluxes%heat_content_cond,g)
2444  call post_data(handles%id_total_heat_content_cond, total_transport, diag)
2445  endif
2446 
2447  if ((handles%id_heat_content_massout > 0) .and. associated(fluxes%heat_content_massout)) &
2448  call post_data(handles%id_heat_content_massout, fluxes%heat_content_massout, diag)
2449  if ((handles%id_total_heat_content_massout > 0) .and. associated(fluxes%heat_content_massout)) then
2450  total_transport = global_area_integral(fluxes%heat_content_massout,g)
2451  call post_data(handles%id_total_heat_content_massout, total_transport, diag)
2452  endif
2453 
2454  if ((handles%id_heat_content_massin > 0) .and. associated(fluxes%heat_content_massin)) &
2455  call post_data(handles%id_heat_content_massin, fluxes%heat_content_massin, diag)
2456  if ((handles%id_total_heat_content_massin > 0) .and. associated(fluxes%heat_content_massin)) then
2457  total_transport = global_area_integral(fluxes%heat_content_massin,g)
2458  call post_data(handles%id_total_heat_content_massin, total_transport, diag)
2459  endif
2460 
2461  if (handles%id_net_heat_coupler > 0 .or. handles%id_total_net_heat_coupler > 0 .or. &
2462  handles%id_net_heat_coupler_ga > 0. ) then
2463  do j=js,je ; do i=is,ie
2464  res(i,j) = 0.0
2465  if (associated(fluxes%LW)) res(i,j) = res(i,j) + fluxes%LW(i,j)
2466  if (associated(fluxes%latent)) res(i,j) = res(i,j) + fluxes%latent(i,j)
2467  if (associated(fluxes%sens)) res(i,j) = res(i,j) + fluxes%sens(i,j)
2468  if (associated(fluxes%SW)) res(i,j) = res(i,j) + fluxes%SW(i,j)
2469  if (associated(fluxes%seaice_melt_heat)) res(i,j) = res(i,j) + fluxes%seaice_melt_heat(i,j)
2470  enddo ; enddo
2471  if (handles%id_net_heat_coupler > 0) call post_data(handles%id_net_heat_coupler, res, diag)
2472  if (handles%id_total_net_heat_coupler > 0) then
2473  total_transport = global_area_integral(res,g)
2474  call post_data(handles%id_total_net_heat_coupler, total_transport, diag)
2475  endif
2476  if (handles%id_net_heat_coupler_ga > 0) then
2477  ave_flux = global_area_mean(res,g)
2478  call post_data(handles%id_net_heat_coupler_ga, ave_flux, diag)
2479  endif
2480  endif
2481 
2482  if (handles%id_net_heat_surface > 0 .or. handles%id_total_net_heat_surface > 0 .or. &
2483  handles%id_net_heat_surface_ga > 0. ) then
2484  do j=js,je ; do i=is,ie
2485  res(i,j) = 0.0
2486  if (associated(fluxes%LW)) res(i,j) = res(i,j) + fluxes%LW(i,j)
2487  if (associated(fluxes%latent)) res(i,j) = res(i,j) + fluxes%latent(i,j)
2488  if (associated(fluxes%sens)) res(i,j) = res(i,j) + fluxes%sens(i,j)
2489  if (associated(fluxes%SW)) res(i,j) = res(i,j) + fluxes%SW(i,j)
2490  if (associated(fluxes%seaice_melt_heat)) res(i,j) = res(i,j) + fluxes%seaice_melt_heat(i,j)
2491  if (associated(sfc_state%frazil)) res(i,j) = res(i,j) + sfc_state%frazil(i,j) * i_dt
2492  !if (associated(sfc_state%TempXpme)) then
2493  ! res(i,j) = res(i,j) + sfc_state%TempXpme(i,j) * fluxes%C_p * I_dt
2494  !else
2495  if (associated(fluxes%heat_content_lrunoff)) res(i,j) = res(i,j) + fluxes%heat_content_lrunoff(i,j)
2496  if (associated(fluxes%heat_content_frunoff)) res(i,j) = res(i,j) + fluxes%heat_content_frunoff(i,j)
2497  if (associated(fluxes%heat_content_lprec)) res(i,j) = res(i,j) + fluxes%heat_content_lprec(i,j)
2498  if (associated(fluxes%heat_content_fprec)) res(i,j) = res(i,j) + fluxes%heat_content_fprec(i,j)
2499  if (associated(fluxes%heat_content_icemelt)) res(i,j) = res(i,j) + fluxes%heat_content_icemelt(i,j)
2500  if (associated(fluxes%heat_content_vprec)) res(i,j) = res(i,j) + fluxes%heat_content_vprec(i,j)
2501  if (associated(fluxes%heat_content_cond)) res(i,j) = res(i,j) + fluxes%heat_content_cond(i,j)
2502  if (associated(fluxes%heat_content_massout)) res(i,j) = res(i,j) + fluxes%heat_content_massout(i,j)
2503  !endif
2504  if (associated(fluxes%heat_added)) res(i,j) = res(i,j) + fluxes%heat_added(i,j)
2505  enddo ; enddo
2506  if (handles%id_net_heat_surface > 0) call post_data(handles%id_net_heat_surface, res, diag)
2507 
2508  if (handles%id_total_net_heat_surface > 0) then
2509  total_transport = global_area_integral(res,g)
2510  call post_data(handles%id_total_net_heat_surface, total_transport, diag)
2511  endif
2512  if (handles%id_net_heat_surface_ga > 0) then
2513  ave_flux = global_area_mean(res,g)
2514  call post_data(handles%id_net_heat_surface_ga, ave_flux, diag)
2515  endif
2516  endif
2517 
2518  if (handles%id_heat_content_surfwater > 0 .or. handles%id_total_heat_content_surfwater > 0) then
2519  do j=js,je ; do i=is,ie
2520  res(i,j) = 0.0
2521  ! if (associated(sfc_state%TempXpme)) then
2522  ! res(i,j) = res(i,j) + sfc_state%TempXpme(i,j) * fluxes%C_p * I_dt
2523  ! else
2524  if (associated(fluxes%heat_content_lrunoff)) res(i,j) = res(i,j) + fluxes%heat_content_lrunoff(i,j)
2525  if (associated(fluxes%heat_content_frunoff)) res(i,j) = res(i,j) + fluxes%heat_content_frunoff(i,j)
2526  if (associated(fluxes%heat_content_lprec)) res(i,j) = res(i,j) + fluxes%heat_content_lprec(i,j)
2527  if (associated(fluxes%heat_content_icemelt)) res(i,j) = res(i,j) + fluxes%heat_content_icemelt(i,j)
2528  if (associated(fluxes%heat_content_fprec)) res(i,j) = res(i,j) + fluxes%heat_content_fprec(i,j)
2529  if (associated(fluxes%heat_content_vprec)) res(i,j) = res(i,j) + fluxes%heat_content_vprec(i,j)
2530  if (associated(fluxes%heat_content_cond)) res(i,j) = res(i,j) + fluxes%heat_content_cond(i,j)
2531  if (associated(fluxes%heat_content_massout)) res(i,j) = res(i,j) + fluxes%heat_content_massout(i,j)
2532  ! endif
2533  enddo ; enddo
2534  if (handles%id_heat_content_surfwater > 0) call post_data(handles%id_heat_content_surfwater, res, diag)
2535  if (handles%id_total_heat_content_surfwater > 0) then
2536  total_transport = global_area_integral(res,g)
2537  call post_data(handles%id_total_heat_content_surfwater, total_transport, diag)
2538  endif
2539  endif
2540 
2541  ! for OMIP, hfrunoffds = heat content of liquid plus frozen runoff
2542  if (handles%id_hfrunoffds > 0) then
2543  do j=js,je ; do i=is,ie
2544  res(i,j) = 0.0
2545  if (associated(fluxes%heat_content_lrunoff)) res(i,j) = res(i,j) + fluxes%heat_content_lrunoff(i,j)
2546  if (associated(fluxes%heat_content_frunoff)) res(i,j) = res(i,j) + fluxes%heat_content_frunoff(i,j)
2547  enddo ; enddo
2548  call post_data(handles%id_hfrunoffds, res, diag)
2549  endif
2550 
2551  ! for OMIP, hfrainds = heat content of lprec + fprec + cond
2552  if (handles%id_hfrainds > 0) then
2553  do j=js,je ; do i=is,ie
2554  res(i,j) = 0.0
2555  if (associated(fluxes%heat_content_lprec)) res(i,j) = res(i,j) + fluxes%heat_content_lprec(i,j)
2556  if (associated(fluxes%heat_content_fprec)) res(i,j) = res(i,j) + fluxes%heat_content_fprec(i,j)
2557  if (associated(fluxes%heat_content_cond)) res(i,j) = res(i,j) + fluxes%heat_content_cond(i,j)
2558  enddo ; enddo
2559  call post_data(handles%id_hfrainds, res, diag)
2560  endif
2561 
2562  if ((handles%id_LwLatSens > 0) .and. associated(fluxes%lw) .and. &
2563  associated(fluxes%latent) .and. associated(fluxes%sens)) then
2564  do j=js,je ; do i=is,ie
2565  res(i,j) = (fluxes%lw(i,j) + fluxes%latent(i,j)) + fluxes%sens(i,j)
2566  enddo ; enddo
2567  call post_data(handles%id_LwLatSens, res, diag)
2568  endif
2569 
2570  if ((handles%id_total_LwLatSens > 0) .and. associated(fluxes%lw) .and. &
2571  associated(fluxes%latent) .and. associated(fluxes%sens)) then
2572  do j=js,je ; do i=is,ie
2573  res(i,j) = (fluxes%lw(i,j) + fluxes%latent(i,j)) + fluxes%sens(i,j)
2574  enddo ; enddo
2575  total_transport = global_area_integral(res,g)
2576  call post_data(handles%id_total_LwLatSens, total_transport, diag)
2577  endif
2578 
2579  if ((handles%id_LwLatSens_ga > 0) .and. associated(fluxes%lw) .and. &
2580  associated(fluxes%latent) .and. associated(fluxes%sens)) then
2581  do j=js,je ; do i=is,ie
2582  res(i,j) = (fluxes%lw(i,j) + fluxes%latent(i,j)) + fluxes%sens(i,j)
2583  enddo ; enddo
2584  ave_flux = global_area_mean(res,g)
2585  call post_data(handles%id_LwLatSens_ga, ave_flux, diag)
2586  endif
2587 
2588  if ((handles%id_sw > 0) .and. associated(fluxes%sw)) then
2589  call post_data(handles%id_sw, fluxes%sw, diag)
2590  endif
2591  if ((handles%id_sw_vis > 0) .and. associated(fluxes%sw_vis_dir) .and. &
2592  associated(fluxes%sw_vis_dif)) then
2593  call post_data(handles%id_sw_vis, fluxes%sw_vis_dir+fluxes%sw_vis_dif, diag)
2594  endif
2595  if ((handles%id_sw_nir > 0) .and. associated(fluxes%sw_nir_dir) .and. &
2596  associated(fluxes%sw_nir_dif)) then
2597  call post_data(handles%id_sw_nir, fluxes%sw_nir_dir+fluxes%sw_nir_dif, diag)
2598  endif
2599  if ((handles%id_total_sw > 0) .and. associated(fluxes%sw)) then
2600  total_transport = global_area_integral(fluxes%sw,g)
2601  call post_data(handles%id_total_sw, total_transport, diag)
2602  endif
2603  if ((handles%id_sw_ga > 0) .and. associated(fluxes%sw)) then
2604  ave_flux = global_area_mean(fluxes%sw,g)
2605  call post_data(handles%id_sw_ga, ave_flux, diag)
2606  endif
2607 
2608  if ((handles%id_lw > 0) .and. associated(fluxes%lw)) then
2609  call post_data(handles%id_lw, fluxes%lw, diag)
2610  endif
2611  if ((handles%id_total_lw > 0) .and. associated(fluxes%lw)) then
2612  total_transport = global_area_integral(fluxes%lw,g)
2613  call post_data(handles%id_total_lw, total_transport, diag)
2614  endif
2615  if ((handles%id_lw_ga > 0) .and. associated(fluxes%lw)) then
2616  ave_flux = global_area_mean(fluxes%lw,g)
2617  call post_data(handles%id_lw_ga, ave_flux, diag)
2618  endif
2619 
2620  if ((handles%id_lat > 0) .and. associated(fluxes%latent)) then
2621  call post_data(handles%id_lat, fluxes%latent, diag)
2622  endif
2623  if ((handles%id_total_lat > 0) .and. associated(fluxes%latent)) then
2624  total_transport = global_area_integral(fluxes%latent,g)
2625  call post_data(handles%id_total_lat, total_transport, diag)
2626  endif
2627  if ((handles%id_lat_ga > 0) .and. associated(fluxes%latent)) then
2628  ave_flux = global_area_mean(fluxes%latent,g)
2629  call post_data(handles%id_lat_ga, ave_flux, diag)
2630  endif
2631 
2632  if ((handles%id_lat_evap > 0) .and. associated(fluxes%latent_evap_diag)) then
2633  call post_data(handles%id_lat_evap, fluxes%latent_evap_diag, diag)
2634  endif
2635  if ((handles%id_total_lat_evap > 0) .and. associated(fluxes%latent_evap_diag)) then
2636  total_transport = global_area_integral(fluxes%latent_evap_diag,g)
2637  call post_data(handles%id_total_lat_evap, total_transport, diag)
2638  endif
2639 
2640  if ((handles%id_lat_fprec > 0) .and. associated(fluxes%latent_fprec_diag)) then
2641  call post_data(handles%id_lat_fprec, fluxes%latent_fprec_diag, diag)
2642  endif
2643  if ((handles%id_total_lat_fprec > 0) .and. associated(fluxes%latent_fprec_diag)) then
2644  total_transport = global_area_integral(fluxes%latent_fprec_diag,g)
2645  call post_data(handles%id_total_lat_fprec, total_transport, diag)
2646  endif
2647 
2648  if ((handles%id_lat_frunoff > 0) .and. associated(fluxes%latent_frunoff_diag)) then
2649  call post_data(handles%id_lat_frunoff, fluxes%latent_frunoff_diag, diag)
2650  endif
2651  if (handles%id_total_lat_frunoff > 0 .and. associated(fluxes%latent_frunoff_diag)) then
2652  total_transport = global_area_integral(fluxes%latent_frunoff_diag,g)
2653  call post_data(handles%id_total_lat_frunoff, total_transport, diag)
2654  endif
2655 
2656  if ((handles%id_sens > 0) .and. associated(fluxes%sens)) then
2657  call post_data(handles%id_sens, fluxes%sens, diag)
2658  endif
2659 
2660  if ((handles%id_seaice_melt_heat > 0) .and. associated(fluxes%seaice_melt_heat)) then
2661  call post_data(handles%id_seaice_melt_heat, fluxes%seaice_melt_heat, diag)
2662  endif
2663 
2664  if ((handles%id_total_seaice_melt_heat > 0) .and. associated(fluxes%seaice_melt_heat)) then
2665  total_transport = global_area_integral(fluxes%seaice_melt_heat,g)
2666  call post_data(handles%id_total_seaice_melt_heat, total_transport, diag)
2667  endif
2668 
2669  if ((handles%id_total_sens > 0) .and. associated(fluxes%sens)) then
2670  total_transport = global_area_integral(fluxes%sens,g)
2671  call post_data(handles%id_total_sens, total_transport, diag)
2672  endif
2673  if ((handles%id_sens_ga > 0) .and. associated(fluxes%sens)) then
2674  ave_flux = global_area_mean(fluxes%sens,g)
2675  call post_data(handles%id_sens_ga, ave_flux, diag)
2676  endif
2677 
2678  if ((handles%id_heat_added > 0) .and. associated(fluxes%heat_added)) then
2679  call post_data(handles%id_heat_added, fluxes%heat_added, diag)
2680  endif
2681 
2682  if ((handles%id_total_heat_added > 0) .and. associated(fluxes%heat_added)) then
2683  total_transport = global_area_integral(fluxes%heat_added,g)
2684  call post_data(handles%id_total_heat_added, total_transport, diag)
2685  endif
2686 
2687 
2688  ! post the diagnostics for boundary salt fluxes ==========================
2689 
2690  if ((handles%id_saltflux > 0) .and. associated(fluxes%salt_flux)) &
2691  call post_data(handles%id_saltflux, fluxes%salt_flux, diag)
2692  if ((handles%id_total_saltflux > 0) .and. associated(fluxes%salt_flux)) then
2693  total_transport = ppt2mks*global_area_integral(fluxes%salt_flux,g)
2694  call post_data(handles%id_total_saltflux, total_transport, diag)
2695  endif
2696 
2697  if ((handles%id_saltFluxAdded > 0) .and. associated(fluxes%salt_flux_added)) &
2698  call post_data(handles%id_saltFluxAdded, fluxes%salt_flux_added, diag)
2699  if ((handles%id_total_saltFluxAdded > 0) .and. associated(fluxes%salt_flux_added)) then
2700  total_transport = ppt2mks*global_area_integral(fluxes%salt_flux_added,g)
2701  call post_data(handles%id_total_saltFluxAdded, total_transport, diag)
2702  endif
2703 
2704  if (handles%id_saltFluxIn > 0 .and. associated(fluxes%salt_flux_in)) &
2705  call post_data(handles%id_saltFluxIn, fluxes%salt_flux_in, diag)
2706  if ((handles%id_total_saltFluxIn > 0) .and. associated(fluxes%salt_flux_in)) then
2707  total_transport = ppt2mks*global_area_integral(fluxes%salt_flux_in,g)
2708  call post_data(handles%id_total_saltFluxIn, total_transport, diag)
2709  endif
2710 
2711  if (handles%id_saltFluxGlobalAdj > 0) &
2712  call post_data(handles%id_saltFluxGlobalAdj, fluxes%saltFluxGlobalAdj, diag)
2713  if (handles%id_vPrecGlobalAdj > 0) &
2714  call post_data(handles%id_vPrecGlobalAdj, fluxes%vPrecGlobalAdj, diag)
2715  if (handles%id_netFWGlobalAdj > 0) &
2716  call post_data(handles%id_netFWGlobalAdj, fluxes%netFWGlobalAdj, diag)
2717  if (handles%id_saltFluxGlobalScl > 0) &
2718  call post_data(handles%id_saltFluxGlobalScl, fluxes%saltFluxGlobalScl, diag)
2719  if (handles%id_vPrecGlobalScl > 0) &
2720  call post_data(handles%id_vPrecGlobalScl, fluxes%vPrecGlobalScl, diag)
2721  if (handles%id_netFWGlobalScl > 0) &
2722  call post_data(handles%id_netFWGlobalScl, fluxes%netFWGlobalScl, diag)
2723 
2724 
2725  ! remaining boundary terms ==================================================
2726 
2727  if ((handles%id_psurf > 0) .and. associated(fluxes%p_surf)) &
2728  call post_data(handles%id_psurf, fluxes%p_surf, diag)
2729 
2730  if ((handles%id_TKE_tidal > 0) .and. associated(fluxes%TKE_tidal)) &
2731  call post_data(handles%id_TKE_tidal, fluxes%TKE_tidal, diag)
2732 
2733  if ((handles%id_buoy > 0) .and. associated(fluxes%buoy)) &
2734  call post_data(handles%id_buoy, fluxes%buoy, diag)
2735 
2736  if ((handles%id_ustar > 0) .and. associated(fluxes%ustar)) &
2737  call post_data(handles%id_ustar, fluxes%ustar, diag)
2738 
2739  if ((handles%id_ustar_berg > 0) .and. associated(fluxes%ustar_berg)) &
2740  call post_data(handles%id_ustar_berg, fluxes%ustar_berg, diag)
2741 
2742  if ((handles%id_frac_ice_cover > 0) .and. associated(fluxes%frac_shelf_h)) &
2743  call post_data(handles%id_frac_ice_cover, fluxes%frac_shelf_h, diag)
2744 
2745  if ((handles%id_ustar_ice_cover > 0) .and. associated(fluxes%ustar_shelf)) &
2746  call post_data(handles%id_ustar_ice_cover, fluxes%ustar_shelf, diag)
2747 
2748  endif ! query_averaging_enabled
2749 
2750  call cpu_clock_end(handles%id_clock_forcing)
2751 end subroutine forcing_diagnostics
2752 
2753 
2754 !> Conditionally allocate fields within the forcing type
2755 subroutine allocate_forcing_type(G, fluxes, water, heat, ustar, press, shelf, iceberg, salt)
2756  type(ocean_grid_type), intent(in) :: g !< Ocean grid structure
2757  type(forcing), intent(inout) :: fluxes !< A structure containing thermodynamic forcing fields
2758  logical, optional, intent(in) :: water !< If present and true, allocate water fluxes
2759  logical, optional, intent(in) :: heat !< If present and true, allocate heat fluxes
2760  logical, optional, intent(in) :: ustar !< If present and true, allocate ustar and related fields
2761  logical, optional, intent(in) :: press !< If present and true, allocate p_surf and related fields
2762  logical, optional, intent(in) :: shelf !< If present and true, allocate fluxes for ice-shelf
2763  logical, optional, intent(in) :: iceberg !< If present and true, allocate fluxes for icebergs
2764  logical, optional, intent(in) :: salt !< If present and true, allocate salt fluxes
2765 
2766  ! Local variables
2767  integer :: isd, ied, jsd, jed, isdb, iedb, jsdb, jedb
2768  logical :: heat_water
2769 
2770  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
2771  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
2772 
2773  call myalloc(fluxes%ustar,isd,ied,jsd,jed, ustar)
2774  call myalloc(fluxes%ustar_gustless,isd,ied,jsd,jed, ustar)
2775 
2776  call myalloc(fluxes%evap,isd,ied,jsd,jed, water)
2777  call myalloc(fluxes%lprec,isd,ied,jsd,jed, water)
2778  call myalloc(fluxes%fprec,isd,ied,jsd,jed, water)
2779  call myalloc(fluxes%vprec,isd,ied,jsd,jed, water)
2780  call myalloc(fluxes%lrunoff,isd,ied,jsd,jed, water)
2781  call myalloc(fluxes%frunoff,isd,ied,jsd,jed, water)
2782  call myalloc(fluxes%seaice_melt,isd,ied,jsd,jed, water)
2783  call myalloc(fluxes%netMassOut,isd,ied,jsd,jed, water)
2784  call myalloc(fluxes%netMassIn,isd,ied,jsd,jed, water)
2785  call myalloc(fluxes%netSalt,isd,ied,jsd,jed, water)
2786  call myalloc(fluxes%seaice_melt_heat,isd,ied,jsd,jed, heat)
2787  call myalloc(fluxes%sw,isd,ied,jsd,jed, heat)
2788  call myalloc(fluxes%lw,isd,ied,jsd,jed, heat)
2789  call myalloc(fluxes%latent,isd,ied,jsd,jed, heat)
2790  call myalloc(fluxes%sens,isd,ied,jsd,jed, heat)
2791  call myalloc(fluxes%latent_evap_diag,isd,ied,jsd,jed, heat)
2792  call myalloc(fluxes%latent_fprec_diag,isd,ied,jsd,jed, heat)
2793  call myalloc(fluxes%latent_frunoff_diag,isd,ied,jsd,jed, heat)
2794 
2795  call myalloc(fluxes%salt_flux,isd,ied,jsd,jed, salt)
2796 
2797  if (present(heat) .and. present(water)) then ; if (heat .and. water) then
2798  call myalloc(fluxes%heat_content_cond,isd,ied,jsd,jed, .true.)
2799  call myalloc(fluxes%heat_content_icemelt,isd,ied,jsd,jed, .true.)
2800  call myalloc(fluxes%heat_content_lprec,isd,ied,jsd,jed, .true.)
2801  call myalloc(fluxes%heat_content_fprec,isd,ied,jsd,jed, .true.)
2802  call myalloc(fluxes%heat_content_vprec,isd,ied,jsd,jed, .true.)
2803  call myalloc(fluxes%heat_content_lrunoff,isd,ied,jsd,jed, .true.)
2804  call myalloc(fluxes%heat_content_frunoff,isd,ied,jsd,jed, .true.)
2805  call myalloc(fluxes%heat_content_massout,isd,ied,jsd,jed, .true.)
2806  call myalloc(fluxes%heat_content_massin,isd,ied,jsd,jed, .true.)
2807  endif ; endif
2808 
2809  call myalloc(fluxes%p_surf,isd,ied,jsd,jed, press)
2810 
2811  call myalloc(fluxes%frac_shelf_h,isd,ied,jsd,jed, shelf)
2812  call myalloc(fluxes%ustar_shelf,isd,ied,jsd,jed, shelf)
2813  call myalloc(fluxes%iceshelf_melt,isd,ied,jsd,jed, shelf)
2814 
2815  !These fields should only on allocated when iceberg area is being passed through the coupler.
2816  call myalloc(fluxes%ustar_berg,isd,ied,jsd,jed, iceberg)
2817  call myalloc(fluxes%area_berg,isd,ied,jsd,jed, iceberg)
2818  call myalloc(fluxes%mass_berg,isd,ied,jsd,jed, iceberg)
2819 
2820 end subroutine allocate_forcing_type
2821 
2822 !> Conditionally allocate fields within the mechanical forcing type
2823 subroutine allocate_mech_forcing(G, forces, stress, ustar, shelf, press, iceberg)
2824  type(ocean_grid_type), intent(in) :: g !< Ocean grid structure
2825  type(mech_forcing), intent(inout) :: forces !< Forcing fields structure
2826 
2827  logical, optional, intent(in) :: stress !< If present and true, allocate taux, tauy
2828  logical, optional, intent(in) :: ustar !< If present and true, allocate ustar and related fields
2829  logical, optional, intent(in) :: shelf !< If present and true, allocate forces for ice-shelf
2830  logical, optional, intent(in) :: press !< If present and true, allocate p_surf and related fields
2831  logical, optional, intent(in) :: iceberg !< If present and true, allocate forces for icebergs
2832 
2833  ! Local variables
2834  integer :: isd, ied, jsd, jed, isdb, iedb, jsdb, jedb
2835  logical :: heat_water
2836 
2837  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
2838  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
2839 
2840  call myalloc(forces%taux,isdb,iedb,jsd,jed, stress)
2841  call myalloc(forces%tauy,isd,ied,jsdb,jedb, stress)
2842 
2843  call myalloc(forces%ustar,isd,ied,jsd,jed, ustar)
2844 
2845  call myalloc(forces%p_surf,isd,ied,jsd,jed, press)
2846  call myalloc(forces%p_surf_full,isd,ied,jsd,jed, press)
2847  call myalloc(forces%net_mass_src,isd,ied,jsd,jed, press)
2848 
2849  call myalloc(forces%rigidity_ice_u,isdb,iedb,jsd,jed, shelf)
2850  call myalloc(forces%rigidity_ice_v,isd,ied,jsdb,jedb, shelf)
2851  call myalloc(forces%frac_shelf_u,isdb,iedb,jsd,jed, shelf)
2852  call myalloc(forces%frac_shelf_v,isd,ied,jsdb,jedb, shelf)
2853 
2854  !These fields should only on allocated when iceberg area is being passed through the coupler.
2855  call myalloc(forces%area_berg,isd,ied,jsd,jed, iceberg)
2856  call myalloc(forces%mass_berg,isd,ied,jsd,jed, iceberg)
2857 
2858 end subroutine allocate_mech_forcing
2859 
2860 !> Allocates and zeroes-out array.
2861 subroutine myalloc(array, is, ie, js, je, flag)
2862  real, dimension(:,:), pointer :: array !< Array to be allocated
2863  integer, intent(in) :: is !< Start i-index
2864  integer, intent(in) :: ie !< End i-index
2865  integer, intent(in) :: js !< Start j-index
2866  integer, intent(in) :: je !< End j-index
2867  logical, optional, intent(in) :: flag !< Flag to indicate to allocate
2868 
2869  if (present(flag)) then ; if (flag) then ; if (.not.associated(array)) then
2870  allocate(array(is:ie,js:je)) ; array(is:ie,js:je) = 0.0
2871  endif ; endif ; endif
2872 end subroutine myalloc
2873 
2874 !> Deallocate the forcing type
2875 subroutine deallocate_forcing_type(fluxes)
2876  type(forcing), intent(inout) :: fluxes !< Forcing fields structure
2877 
2878  if (associated(fluxes%ustar)) deallocate(fluxes%ustar)
2879  if (associated(fluxes%ustar_gustless)) deallocate(fluxes%ustar_gustless)
2880  if (associated(fluxes%buoy)) deallocate(fluxes%buoy)
2881  if (associated(fluxes%sw)) deallocate(fluxes%sw)
2882  if (associated(fluxes%seaice_melt_heat)) deallocate(fluxes%seaice_melt_heat)
2883  if (associated(fluxes%sw_vis_dir)) deallocate(fluxes%sw_vis_dir)
2884  if (associated(fluxes%sw_vis_dif)) deallocate(fluxes%sw_vis_dif)
2885  if (associated(fluxes%sw_nir_dir)) deallocate(fluxes%sw_nir_dir)
2886  if (associated(fluxes%sw_nir_dif)) deallocate(fluxes%sw_nir_dif)
2887  if (associated(fluxes%lw)) deallocate(fluxes%lw)
2888  if (associated(fluxes%latent)) deallocate(fluxes%latent)
2889  if (associated(fluxes%latent_evap_diag)) deallocate(fluxes%latent_evap_diag)
2890  if (associated(fluxes%latent_fprec_diag)) deallocate(fluxes%latent_fprec_diag)
2891  if (associated(fluxes%latent_frunoff_diag)) deallocate(fluxes%latent_frunoff_diag)
2892  if (associated(fluxes%sens)) deallocate(fluxes%sens)
2893  if (associated(fluxes%heat_added)) deallocate(fluxes%heat_added)
2894  if (associated(fluxes%heat_content_lrunoff)) deallocate(fluxes%heat_content_lrunoff)
2895  if (associated(fluxes%heat_content_frunoff)) deallocate(fluxes%heat_content_frunoff)
2896  if (associated(fluxes%heat_content_icemelt)) deallocate(fluxes%heat_content_icemelt)
2897  if (associated(fluxes%heat_content_lprec)) deallocate(fluxes%heat_content_lprec)
2898  if (associated(fluxes%heat_content_fprec)) deallocate(fluxes%heat_content_fprec)
2899  if (associated(fluxes%heat_content_cond)) deallocate(fluxes%heat_content_cond)
2900  if (associated(fluxes%heat_content_massout)) deallocate(fluxes%heat_content_massout)
2901  if (associated(fluxes%heat_content_massin)) deallocate(fluxes%heat_content_massin)
2902  if (associated(fluxes%evap)) deallocate(fluxes%evap)
2903  if (associated(fluxes%lprec)) deallocate(fluxes%lprec)
2904  if (associated(fluxes%fprec)) deallocate(fluxes%fprec)
2905  if (associated(fluxes%vprec)) deallocate(fluxes%vprec)
2906  if (associated(fluxes%lrunoff)) deallocate(fluxes%lrunoff)
2907  if (associated(fluxes%frunoff)) deallocate(fluxes%frunoff)
2908  if (associated(fluxes%seaice_melt)) deallocate(fluxes%seaice_melt)
2909  if (associated(fluxes%salt_flux)) deallocate(fluxes%salt_flux)
2910  if (associated(fluxes%p_surf_full)) deallocate(fluxes%p_surf_full)
2911  if (associated(fluxes%p_surf)) deallocate(fluxes%p_surf)
2912  if (associated(fluxes%TKE_tidal)) deallocate(fluxes%TKE_tidal)
2913  if (associated(fluxes%ustar_tidal)) deallocate(fluxes%ustar_tidal)
2914  if (associated(fluxes%ustar_shelf)) deallocate(fluxes%ustar_shelf)
2915  if (associated(fluxes%iceshelf_melt)) deallocate(fluxes%iceshelf_melt)
2916  if (associated(fluxes%frac_shelf_h)) deallocate(fluxes%frac_shelf_h)
2917  if (associated(fluxes%ustar_berg)) deallocate(fluxes%ustar_berg)
2918  if (associated(fluxes%area_berg)) deallocate(fluxes%area_berg)
2919  if (associated(fluxes%mass_berg)) deallocate(fluxes%mass_berg)
2920 
2921  call coupler_type_destructor(fluxes%tr_fluxes)
2922 
2923 end subroutine deallocate_forcing_type
2924 
2925 
2926 !> Deallocate the mechanical forcing type
2927 subroutine deallocate_mech_forcing(forces)
2928  type(mech_forcing), intent(inout) :: forces !< Forcing fields structure
2929 
2930  if (associated(forces%taux)) deallocate(forces%taux)
2931  if (associated(forces%tauy)) deallocate(forces%tauy)
2932  if (associated(forces%ustar)) deallocate(forces%ustar)
2933  if (associated(forces%p_surf)) deallocate(forces%p_surf)
2934  if (associated(forces%p_surf_full)) deallocate(forces%p_surf_full)
2935  if (associated(forces%net_mass_src)) deallocate(forces%net_mass_src)
2936  if (associated(forces%rigidity_ice_u)) deallocate(forces%rigidity_ice_u)
2937  if (associated(forces%rigidity_ice_v)) deallocate(forces%rigidity_ice_v)
2938  if (associated(forces%frac_shelf_u)) deallocate(forces%frac_shelf_u)
2939  if (associated(forces%frac_shelf_v)) deallocate(forces%frac_shelf_v)
2940  if (associated(forces%area_berg)) deallocate(forces%area_berg)
2941  if (associated(forces%mass_berg)) deallocate(forces%mass_berg)
2942 
2943 end subroutine deallocate_mech_forcing
2944 
2945 
2946 !> \namespace mom_forcing_type
2947 !!
2948 !! \section section_fluxes Boundary fluxes
2949 !!
2950 !! The ocean is a forced-dissipative system. Forcing occurs at the
2951 !! boundaries, and this module mediates the various forcing terms
2952 !! from momentum, heat, salt, and mass. Boundary fluxes from other
2953 !! tracers are treated by coupling to biogeochemical models. We
2954 !! here present elements of how MOM6 assumes boundary fluxes are
2955 !! passed into the ocean.
2956 !!
2957 !! Note that all fluxes are positive into the ocean. For surface
2958 !! boundary fluxes, that means fluxes are positive downward.
2959 !! For example, a positive shortwave flux warms the ocean.
2960 !!
2961 !! \subsection subsection_momentum_fluxes Surface boundary momentum fluxes
2962 !!
2963 !! The ocean surface exchanges momentum with the overlying atmosphere,
2964 !! sea ice, and land ice. The momentum is exchanged as a horizontal
2965 !! stress (Newtons per squared meter: N/m2) imposed on the upper ocean
2966 !! grid cell.
2967 !!
2968 !! \subsection subsection_mass_fluxes Surface boundary mass fluxes
2969 !!
2970 !! The ocean gains or loses mass through evaporation, precipitation,
2971 !! sea ice melt/form, and and river runoff. Positive mass fluxes
2972 !! add mass to the liquid ocean. The boundary mass flux units are
2973 !! (kilogram per square meter per sec: kg/(m2/sec)).
2974 !!
2975 !! * Evaporation field can in fact represent a
2976 !! mass loss (evaporation) or mass gain (condensation in foggy areas).
2977 !! * sea ice formation leads to mass moving from the liquid ocean to the
2978 !! ice model, and melt adds liquid to the ocean.
2979 !! * Precipitation can be liquid or frozen (snow). Furthermore, in
2980 !! some versions of the GFDL coupler, precipitation can be negative.
2981 !! The reason is that the ice model combines precipitation with
2982 !! ice melt and ice formation. This limitation of the ice model
2983 !! diagnostics should be overcome future versions.
2984 !! * River runoff can be liquid or frozen. Frozen runoff is often
2985 !! associated with calving land-ice and/or ice bergs.
2986 !!
2987 !! \subsection subsection_salt_fluxes Surface boundary salt fluxes
2988 !!
2989 !! Over most of the ocean, there is no exchange of salt with the
2990 !! atmosphere. However, the liquid ocean exchanges salt with sea ice.
2991 !! When ice forms, it extracts salt from ice pockets and discharges the
2992 !! salt into the liquid ocean. The salt concentration of sea ice
2993 !! is therefore much lower (around 5ppt) than liquid seawater
2994 !! (around 30-35ppt in high latitudes).
2995 !!
2996 !! For ocean-ice models run with a prescribed atmosphere, such as
2997 !! in the CORE/OMMIP simulations, it is necessary to employ a surface
2998 !! restoring term to the k=1 salinity equation, thus imposing a salt
2999 !! flux onto the ocean even outside of sea ice regimes. This salt
3000 !! flux is non-physical, and represents a limitation of the ocean-ice
3001 !! models run without an interactive atmosphere. Sometimes this salt
3002 !! flux is converted to an implied fresh water flux. However, doing
3003 !! so generally leads to changes in the sea level, unless a global
3004 !! normalization is provided to zero-out the net water flux.
3005 !! As a complement, for models with a restoring salt flux, one may
3006 !! choose to zero-out the net salt entering the ocean. There are
3007 !! pros/cons of each approach.
3008 !!
3009 !!
3010 !! \subsection subsection_heat_fluxes Surface boundary heat fluxes
3011 !!
3012 !! There are many terms that contribute to boundary-related heating
3013 !! of the k=1 surface model grid cell. We here outline details of
3014 !! this heat, with each term having units W/m2.
3015 !!
3016 !! The net flux of heat crossing ocean surface is stored in the diagnostic
3017 !! array "hfds". This array is computed as
3018 !! \f[
3019 !! \mbox{hfds = shortwave + longwave + latent + sensible + mass transfer + frazil + restore + flux adjustments}
3020 !! \f]
3021 !!
3022 !! * shortwave (SW) = shortwave radiation (always warms ocean)
3023 !! * longwave (LW) = longwave radiation (generally cools ocean)
3024 !! * latent (LAT) = turbulent latent heat loss due to evaporation
3025 !! (liquid to vapor) or melt (snow to liquid); generally
3026 !! cools the ocean
3027 !! * sensible (SENS) = turbulent heat transfer due to differences in
3028 !! air-sea or ice-sea temperature
3029 !! * mass transfer (MASS) = heat transfer due to heat content of mass (e.g., E-P+R)
3030 !! transferred across ocean surface; computed relative
3031 !! to 0 Celsius
3032 !! * frazil (FRAZ) = heat transferred to form frazil sea ice
3033 !! (positive heating of liquid ocean)
3034 !! * restore (RES) = heat from surface damping sometimes imposed
3035 !! in non-coupled model simulations .
3036 !! * restore (flux adjustments) = heat from surface flux adjustment.
3037 !!
3038 !! \subsubsection subsubsection_SW Treatment of shortwave
3039 !!
3040 !! The shortwave field itself is split into two pieces:
3041 !!
3042 !! * shortwave = penetrative SW + non-penetrative SW
3043 !! * non-penetrative = non-downwelling shortwave; portion of SW
3044 !! totally absorbed in the k=1 cell.
3045 !! The non-penetrative SW is combined with
3046 !! LW+LAT+SENS+seaice_melt_heat in net_heat inside routine
3047 !! extractFluxes1d. Notably, for many cases,
3048 !! non-penetrative SW = 0.
3049 !! * penetrative = that portion of shortwave penetrating below
3050 !! a tiny surface layer. This is the downwelling
3051 !! shortwave. Penetrative SW participates in
3052 !! the penetrative SW heating of k=1,nz cells,
3053 !! with the amount of penetration dependent on
3054 !! optical properties.
3055 !!
3056 !! \subsubsection subsubsection_bdy_heating Convergence of heat into the k=1 cell
3057 !!
3058 !! The convergence of boundary-related heat into surface grid cell is
3059 !! given by the difference in the net heat entering the top of the k=1
3060 !! cell and the penetrative SW leaving the bottom of the cell.
3061 !! \f{eqnarray*}{
3062 !! Q(k=1) &=& \mbox{hfds} - \mbox{pen_SW(leaving bottom of k=1)}
3063 !! \\ &=& \mbox{nonpen_SW} + (\mbox{pen_SW(enter k=1)}-\mbox{pen_SW(leave k=1)})
3064 !! + \mbox{LW+LAT+SENS+MASS+FRAZ+RES}
3065 !! \\ &=& \mbox{nonpen_SW}+ \mbox{LW+LAT+SENS+MASS+FRAZ+RES}
3066 !! + [\mbox{pen_SW(enter k=1)} - \mbox{pen_SW(leave k=1)}]
3067 !! \f}
3068 !! The convergence of the penetrative shortwave flux is given by
3069 !! \f$ \mbox{pen_SW (enter k)}-\mbox{pen_SW (leave k)}\f$. This term
3070 !! appears for all cells k=1,nz. It is diagnosed as "rsdoabsorb" inside module
3071 !! MOM6/src/parameterizations/vertical/MOM_diabatic_aux.F90
3072 !!
3073 
3074 end module mom_forcing_type
mom_forcing_type::mech_forcing
Structure that contains pointers to the mechanical forcing at the surface used to drive the liquid oc...
Definition: MOM_forcing_type.F90:185
mom_variables::surface
Pointers to various fields which may be used describe the surface state of MOM, and which will be ret...
Definition: MOM_variables.F90:38
mom_spatial_means
Functions and routines to take area, volume, mass-weighted, layerwise, zonal or meridional means.
Definition: MOM_spatial_means.F90:2
mom_verticalgrid
Provides a transparent vertical ocean grid type and supporting routines.
Definition: MOM_verticalGrid.F90:2
mom_file_parser::log_version
An overloaded interface to log version information about modules.
Definition: MOM_file_parser.F90:109
mom_diag_mediator
The subroutines here provide convenient wrappers to the fms diag_manager interfaces with additional d...
Definition: MOM_diag_mediator.F90:3
mom_variables::thermo_var_ptrs
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
Definition: MOM_variables.F90:82
mom_eos
Provides subroutines for quantities specific to the equation of state.
Definition: MOM_EOS.F90:2
mom_file_parser::param_file_type
A structure that can be parsed to read and document run-time parameters.
Definition: MOM_file_parser.F90:54
mom_file_parser::get_param
An overloaded interface to read and log the values of various types of parameters.
Definition: MOM_file_parser.F90:102
mom_unit_scaling::unit_scale_type
Describes various unit conversion factors.
Definition: MOM_unit_scaling.F90:14
mom_diag_mediator::post_data
Make a diagnostic available for averaging or output.
Definition: MOM_diag_mediator.F90:70
mom_forcing_type
This module implements boundary forcing for MOM6.
Definition: MOM_forcing_type.F90:2
mom_verticalgrid::verticalgrid_type
Describes the vertical ocean grid, including unit conversion factors.
Definition: MOM_verticalGrid.F90:24
mom_variables
Provides transparent structures with groups of MOM6 variables and supporting routines.
Definition: MOM_variables.F90:2
mom_cpu_clock
Wraps the MPP cpu clock functions.
Definition: MOM_cpu_clock.F90:2
mom_file_parser
The MOM6 facility to parse input files for runtime parameters.
Definition: MOM_file_parser.F90:2
mom_eos::calculate_density_derivs
Calculate the derivatives of density with temperature and salinity from T, S, and P.
Definition: MOM_EOS.F90:70
mom_opacity::optics_type
This type is used to store information about ocean optical properties.
Definition: MOM_opacity.F90:25
mom_grid
Provides the ocean grid type.
Definition: MOM_grid.F90:2
mom_unit_scaling
Provides a transparent unit rescaling type to facilitate dimensional consistency testing.
Definition: MOM_unit_scaling.F90:2
mom_forcing_type::forcing
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
Definition: MOM_forcing_type.F90:49
mom_debugging
Provides checksumming functions for debugging.
Definition: MOM_debugging.F90:7
mom_forcing_type::forcing_diags
Structure that defines the id handles for the forcing type.
Definition: MOM_forcing_type.F90:235
mom_file_parser::log_param
An overloaded interface to log the values of various types of parameters.
Definition: MOM_file_parser.F90:96
mom_opacity
Routines used to calculate the opacity of the ocean.
Definition: MOM_opacity.F90:2
mom_error_handler
Routines for error handling and I/O management.
Definition: MOM_error_handler.F90:2
mom_grid::ocean_grid_type
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:25
mom_diag_mediator::diag_ctrl
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
Definition: MOM_diag_mediator.F90:239