MOM6
MOM_variables.F90
1 !> Provides transparent structures with groups of MOM6 variables and supporting routines
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
7 use mom_domains, only : mom_domain_type, get_domain_extent, group_pass_type
8 use mom_debugging, only : hchksum
9 use mom_error_handler, only : mom_error, fatal
10 use mom_grid, only : ocean_grid_type
11 use mom_eos, only : eos_type
12 
13 use coupler_types_mod, only : coupler_1d_bc_type, coupler_2d_bc_type
14 use coupler_types_mod, only : coupler_type_spawn, coupler_type_destructor
15 use coupler_types_mod, only : coupler_type_initialized
16 
17 implicit none ; private
18 
19 #include <MOM_memory.h>
20 
21 public allocate_surface_state, deallocate_surface_state, mom_thermovar_chksum
22 public ocean_grid_type, alloc_bt_cont_type, dealloc_bt_cont_type
23 public rotate_surface_state
24 
25 ! A note on unit descriptions in comments: MOM6 uses units that can be rescaled for dimensional
26 ! consistency testing. These are noted in comments with units like Z, H, L, and T, along with
27 ! their mks counterparts with notation like "a velocity [Z T-1 ~> m s-1]". If the units
28 ! vary with the Boussinesq approximation, the Boussinesq variant is given first.
29 
30 !> A structure for creating arrays of pointers to 3D arrays
31 type, public :: p3d
32  real, dimension(:,:,:), pointer :: p => null() !< A pointer to a 3D array
33 end type p3d
34 !> A structure for creating arrays of pointers to 2D arrays
35 type, public :: p2d
36  real, dimension(:,:), pointer :: p => null() !< A pointer to a 2D array
37 end type p2d
38 
39 !> Pointers to various fields which may be used describe the surface state of MOM, and which
40 !! will be returned to a the calling program
41 type, public :: surface
42  real, allocatable, dimension(:,:) :: &
43  sst, & !< The sea surface temperature [degC].
44  sss, & !< The sea surface salinity [ppt ~> psu or gSalt/kg].
45  sfc_density, & !< The mixed layer density [R ~> kg m-3].
46  hml, & !< The mixed layer depth [Z ~> m].
47  u, & !< The mixed layer zonal velocity [L T-1 ~> m s-1].
48  v, & !< The mixed layer meridional velocity [L T-1 ~> m s-1].
49  sea_lev, & !< The sea level [Z ~> m]. If a reduced surface gravity is
50  !! used, that is compensated for in sea_lev.
51  frazil, & !< The energy needed to heat the ocean column to the freezing point during
52  !! the call to step_MOM [Q R Z ~> J m-2].
53  melt_potential, & !< Instantaneous amount of heat that can be used to melt sea ice [Q R Z ~> J m-2].
54  !! This is computed w.r.t. surface freezing temperature.
55  ocean_mass, & !< The total mass of the ocean [R Z ~> kg m-2].
56  ocean_heat, & !< The total heat content of the ocean in [degC R Z ~> degC kg m-2].
57  ocean_salt, & !< The total salt content of the ocean in [kgSalt kg-1 R Z ~> kgSalt m-2].
58  taux_shelf, & !< The zonal stresses on the ocean under shelves [R L Z T-2 ~> Pa].
59  tauy_shelf, & !< The meridional stresses on the ocean under shelves [R L Z T-2 ~> Pa].
60  tempxpme, & !< The net inflow of water into the ocean times the temperature at which this
61  !! inflow occurs during the call to step_MOM [degC R Z ~> degC kg m-2].
62  salt_deficit, & !< The salt needed to maintain the ocean column above a minimum
63  !! salinity over the call to step_MOM [kgSalt kg-1 R Z ~> kgSalt m-2].
64  internal_heat !< Any internal or geothermal heat sources that are applied to the ocean
65  !! integrated over the call to step_MOM [degC R Z ~> degC kg m-2].
66  logical :: t_is_cont = .false. !< If true, the temperature variable SST is actually the
67  !! conservative temperature in [degC].
68  logical :: s_is_abss = .false. !< If true, the salinity variable SSS is actually the
69  !! absolute salinity in [g/kg].
70  type(coupler_2d_bc_type) :: tr_fields !< A structure that may contain an
71  !! array of named fields describing tracer-related quantities.
72  !### NOTE: ALL OF THE ARRAYS IN TR_FIELDS USE THE COUPLER'S INDEXING CONVENTION AND HAVE NO
73  !### HALOS! THIS IS DONE TO CONFORM TO THE TREATMENT IN MOM4, BUT I DON'T LIKE IT! -RWH
74  logical :: arrays_allocated = .false. !< A flag that indicates whether the surface type
75  !! has had its memory allocated.
76 end type surface
77 
78 !> Pointers to an assortment of thermodynamic fields that may be available, including
79 !! potential temperature, salinity, heat capacity, and the equation of state control structure.
80 type, public :: thermo_var_ptrs
81  ! If allocated, the following variables have nz layers.
82  real, pointer :: t(:,:,:) => null() !< Potential temperature [degC].
83  real, pointer :: s(:,:,:) => null() !< Salinity [PSU] or [gSalt/kg], generically [ppt].
84  real, pointer :: p_surf(:,:) => null() !< Ocean surface pressure used in equation of state
85  !! calculations [R L2 T-2 ~> Pa]
86  type(eos_type), pointer :: eqn_of_state => null() !< Type that indicates the
87  !! equation of state to use.
88  real :: p_ref !< The coordinate-density reference pressure [R L2 T-2 ~> Pa].
89  !! This is the pressure used to calculate Rml from
90  !! T and S when eqn_of_state is associated.
91  real :: c_p !< The heat capacity of seawater [Q degC-1 ~> J degC-1 kg-1].
92  !! When conservative temperature is used, this is
93  !! constant and exactly 3991.86795711963 J degC-1 kg-1.
94  logical :: t_is_cont = .false. !< If true, the temperature variable tv%T is
95  !! actually the conservative temperature [degC].
96  logical :: s_is_abss = .false. !< If true, the salinity variable tv%S is
97  !! actually the absolute salinity in units of [gSalt/kg].
98  real :: min_salinity = 0.01 !< The minimum value of salinity when BOUND_SALINITY=True [ppt].
99  !! The default is 0.01 for backward compatibility but should be 0.
100  ! These arrays are accumulated fluxes for communication with other components.
101  real, dimension(:,:), pointer :: frazil => null()
102  !< The energy needed to heat the ocean column to the
103  !! freezing point since calculate_surface_state was2
104  !! last called [Q Z R ~> J m-2].
105  real, dimension(:,:), pointer :: salt_deficit => null()
106  !< The salt needed to maintain the ocean column
107  !! at a minimum salinity of MIN_SALINITY since the last time
108  !! that calculate_surface_state was called, [ppt R Z ~> gSalt m-2].
109  real, dimension(:,:), pointer :: tempxpme => null()
110  !< The net inflow of water into the ocean times the
111  !! temperature at which this inflow occurs since the
112  !! last call to calculate_surface_state [degC R Z ~> degC kg m-2].
113  !! This should be prescribed in the forcing fields, but
114  !! as it often is not, this is a useful heat budget diagnostic.
115  real, dimension(:,:), pointer :: internal_heat => null()
116  !< Any internal or geothermal heat sources that
117  !! have been applied to the ocean since the last call to
118  !! calculate_surface_state [degC R Z ~> degC kg m-2].
119  ! The following variables are most normally not used but when they are they
120  ! will be either set by parameterizations or prognostic.
121  real, pointer :: vart(:,:,:) => null() !< SGS variance of potential temperature [degC2].
122  real, pointer :: vars(:,:,:) => null() !< SGS variance of salinity [ppt2].
123  real, pointer :: covarts(:,:,:) => null() !< SGS covariance of salinity and potential
124  !! temperature [degC ppt].
125 end type thermo_var_ptrs
126 
127 !> Pointers to all of the prognostic variables allocated in MOM_variables.F90 and MOM.F90.
128 !!
129 !! It is useful for sending these variables for diagnostics, and in preparation for ensembles
130 !! later on. All variables have the same names as the local (public) variables
131 !! they refer to in MOM.F90.
132 type, public :: ocean_internal_state
133  real, pointer, dimension(:,:,:) :: &
134  t => null(), & !< Pointer to the temperature state variable [degC]
135  s => null(), & !< Pointer to the salinity state variable [ppt ~> PSU or g/kg]
136  u => null(), & !< Pointer to the zonal velocity [L T-1 ~> m s-1]
137  v => null(), & !< Pointer to the meridional velocity [L T-1 ~> m s-1]
138  h => null() !< Pointer to the layer thicknesses [H ~> m or kg m-2]
139  real, pointer, dimension(:,:,:) :: &
140  uh => null(), & !< Pointer to zonal transports [H L2 T-1 ~> m3 s-1 or kg s-1]
141  vh => null() !< Pointer to meridional transports [H L2 T-1 ~> m3 s-1 or kg s-1]
142  real, pointer, dimension(:,:,:) :: &
143  cau => null(), & !< Pointer to the zonal Coriolis and Advective acceleration [L T-2 ~> m s-2]
144  cav => null(), & !< Pointer to the meridional Coriolis and Advective acceleration [L T-2 ~> m s-2]
145  pfu => null(), & !< Pointer to the zonal Pressure force acceleration [L T-2 ~> m s-2]
146  pfv => null(), & !< Pointer to the meridional Pressure force acceleration [L T-2 ~> m s-2]
147  diffu => null(), & !< Pointer to the zonal acceleration due to lateral viscosity [L T-2 ~> m s-2]
148  diffv => null(), & !< Pointer to the meridional acceleration due to lateral viscosity [L T-2 ~> m s-2]
149  pbce => null(), & !< Pointer to the baroclinic pressure force dependency on free surface movement
150  !! [L2 T-2 H-1 ~> m s-2 or m4 kg-1 s-2]
151  u_accel_bt => null(), & !< Pointer to the zonal barotropic-solver acceleration [L T-2 ~> m s-2]
152  v_accel_bt => null() !< Pointer to the meridional barotropic-solver acceleration [L T-2 ~> m s-2]
153  real, pointer, dimension(:,:,:) :: &
154  u_av => null(), & !< Pointer to zonal velocity averaged over the timestep [L T-1 ~> m s-1]
155  v_av => null(), & !< Pointer to meridional velocity averaged over the timestep [L T-1 ~> m s-1]
156  u_prev => null(), & !< Pointer to zonal velocity at the end of the last timestep [L T-1 ~> m s-1]
157  v_prev => null() !< Pointer to meridional velocity at the end of the last timestep [L T-1 ~> m s-1]
158 end type ocean_internal_state
159 
160 !> Pointers to arrays with accelerations, which can later be used for derived diagnostics, like energy balances.
161 type, public :: accel_diag_ptrs
162 
163  ! Each of the following fields has nz layers.
164  real, pointer, dimension(:,:,:) :: &
165  diffu => null(), & !< Zonal acceleration due to along isopycnal viscosity [L T-2 ~> m s-2]
166  diffv => null(), & !< Meridional acceleration due to along isopycnal viscosity [L T-2 ~> m s-2]
167  cau => null(), & !< Zonal Coriolis and momentum advection accelerations [L T-2 ~> m s-2]
168  cav => null(), & !< Meridional Coriolis and momentum advection accelerations [L T-2 ~> m s-2]
169  pfu => null(), & !< Zonal acceleration due to pressure forces [L T-2 ~> m s-2]
170  pfv => null(), & !< Meridional acceleration due to pressure forces [L T-2 ~> m s-2]
171  du_dt_visc => null(), &!< Zonal acceleration due to vertical viscosity [L T-2 ~> m s-2]
172  dv_dt_visc => null(), &!< Meridional acceleration due to vertical viscosity [L T-2 ~> m s-2]
173  du_dt_dia => null(), & !< Zonal acceleration due to diapycnal mixing [L T-2 ~> m s-2]
174  dv_dt_dia => null() !< Meridional acceleration due to diapycnal mixing [L T-2 ~> m s-2]
175  real, pointer, dimension(:,:,:) :: du_other => null()
176  !< Zonal velocity changes due to any other processes that are
177  !! not due to any explicit accelerations [L T-1 ~> m s-1].
178  real, pointer, dimension(:,:,:) :: dv_other => null()
179  !< Meridional velocity changes due to any other processes that are
180  !! not due to any explicit accelerations [L T-1 ~> m s-1].
181 
182  ! These accelerations are sub-terms included in the accelerations above.
183  real, pointer :: gradkeu(:,:,:) => null() !< gradKEu = - d/dx(u2) [L T-2 ~> m s-2]
184  real, pointer :: gradkev(:,:,:) => null() !< gradKEv = - d/dy(u2) [L T-2 ~> m s-2]
185  real, pointer :: rv_x_v(:,:,:) => null() !< rv_x_v = rv * v at u [L T-2 ~> m s-2]
186  real, pointer :: rv_x_u(:,:,:) => null() !< rv_x_u = rv * u at v [L T-2 ~> m s-2]
187 
188  real, pointer :: diag_hfrac_u(:,:,:) => null() !< Fractional layer thickness at u points
189  real, pointer :: diag_hfrac_v(:,:,:) => null() !< Fractional layer thickness at v points
190 end type accel_diag_ptrs
191 
192 !> Pointers to arrays with transports, which can later be used for derived diagnostics, like energy balances.
193 type, public :: cont_diag_ptrs
194 
195 ! Each of the following fields has nz layers.
196  real, pointer, dimension(:,:,:) :: &
197  uh => null(), & !< Resolved zonal layer thickness fluxes, [H L2 T-1 ~> m3 s-1 or kg s-1]
198  vh => null(), & !< Resolved meridional layer thickness fluxes, [H L2 T-1 ~> m3 s-1 or kg s-1]
199  uhgm => null(), & !< Isopycnal height diffusion induced zonal volume fluxes [H L2 T-1 ~> m3 s-1 or kg s-1]
200  vhgm => null() !< Isopycnal height diffusion induced meridional volume fluxes [H L2 T-1 ~> m3 s-1 or kg s-1]
201 
202 ! Each of the following fields is found at nz+1 interfaces.
203  real, pointer :: diapyc_vel(:,:,:) => null() !< The net diapycnal velocity [H s-1 ~> m s-1 or kg m-2 s-1]
204 
205 end type cont_diag_ptrs
206 
207 !> Vertical viscosities, drag coefficients, and related fields.
208 type, public :: vertvisc_type
209  real :: prandtl_turb !< The Prandtl number for the turbulent diffusion
210  !! that is captured in Kd_shear [nondim].
211  real, pointer, dimension(:,:) :: &
212  bbl_thick_u => null(), & !< The bottom boundary layer thickness at the u-points [Z ~> m].
213  bbl_thick_v => null(), & !< The bottom boundary layer thickness at the v-points [Z ~> m].
214  kv_bbl_u => null(), & !< The bottom boundary layer viscosity at the u-points [Z2 T-1 ~> m2 s-1].
215  kv_bbl_v => null(), & !< The bottom boundary layer viscosity at the v-points [Z2 T-1 ~> m2 s-1].
216  ustar_bbl => null() !< The turbulence velocity in the bottom boundary layer at h points [Z T-1 ~> m s-1].
217  real, pointer, dimension(:,:) :: tke_bbl => null()
218  !< A term related to the bottom boundary layer source of turbulent kinetic
219  !! energy, currently in [Z3 T-3 ~> m3 s-3], but may at some time be changed
220  !! to [R Z3 T-3 ~> W m-2].
221  real, pointer, dimension(:,:) :: &
222  taux_shelf => null(), & !< The zonal stresses on the ocean under shelves [R Z L T-2 ~> Pa].
223  tauy_shelf => null() !< The meridional stresses on the ocean under shelves [R Z L T-2 ~> Pa].
224  real, pointer, dimension(:,:) :: tbl_thick_shelf_u => null()
225  !< Thickness of the viscous top boundary layer under ice shelves at u-points [Z ~> m].
226  real, pointer, dimension(:,:) :: tbl_thick_shelf_v => null()
227  !< Thickness of the viscous top boundary layer under ice shelves at v-points [Z ~> m].
228  real, pointer, dimension(:,:) :: kv_tbl_shelf_u => null()
229  !< Viscosity in the viscous top boundary layer under ice shelves at u-points [Z2 T-1 ~> m2 s-1].
230  real, pointer, dimension(:,:) :: kv_tbl_shelf_v => null()
231  !< Viscosity in the viscous top boundary layer under ice shelves at v-points [Z2 T-1 ~> m2 s-1].
232  real, pointer, dimension(:,:) :: nkml_visc_u => null()
233  !< The number of layers in the viscous surface mixed layer at u-points [nondim].
234  !! This is not an integer because there may be fractional layers, and it is stored in
235  !! terms of layers, not depth, to facilitate the movement of the viscous boundary layer
236  !! with the flow.
237  real, pointer, dimension(:,:) :: nkml_visc_v => null()
238  !< The number of layers in the viscous surface mixed layer at v-points [nondim].
239  real, pointer, dimension(:,:) :: &
240  mld => null() !< Instantaneous active mixing layer depth [Z ~> m].
241  real, pointer, dimension(:,:,:) :: &
242  ray_u => null(), & !< The Rayleigh drag velocity to be applied to each layer at u-points [Z T-1 ~> m s-1].
243  ray_v => null() !< The Rayleigh drag velocity to be applied to each layer at v-points [Z T-1 ~> m s-1].
244  real, pointer, dimension(:,:,:) :: kd_extra_t => null()
245  !< The extra diffusivity of temperature due to double diffusion relative to the
246  !! diffusivity of density [Z2 T-1 ~> m2 s-1].
247  real, pointer, dimension(:,:,:) :: kd_extra_s => null()
248  !< The extra diffusivity of salinity due to double diffusion relative to the
249  !! diffusivity of density [Z2 T-1 ~> m2 s-1].
250  ! One of Kd_extra_T and Kd_extra_S is always 0. Kd_extra_S is positive for salt fingering;
251  ! Kd_extra_T is positive for double diffusive convection. They are only allocated if
252  ! DOUBLE_DIFFUSION is true.
253  real, pointer, dimension(:,:,:) :: kd_shear => null()
254  !< The shear-driven turbulent diapycnal diffusivity at the interfaces between layers
255  !! in tracer columns [Z2 T-1 ~> m2 s-1].
256  real, pointer, dimension(:,:,:) :: kv_shear => null()
257  !< The shear-driven turbulent vertical viscosity at the interfaces between layers
258  !! in tracer columns [Z2 T-1 ~> m2 s-1].
259  real, pointer, dimension(:,:,:) :: kv_shear_bu => null()
260  !< The shear-driven turbulent vertical viscosity at the interfaces between layers in
261  !! corner columns [Z2 T-1 ~> m2 s-1].
262  real, pointer, dimension(:,:,:) :: kv_slow => null()
263  !< The turbulent vertical viscosity component due to "slow" processes (e.g., tidal,
264  !! background, convection etc) [Z2 T-1 ~> m2 s-1].
265  real, pointer, dimension(:,:,:) :: tke_turb => null()
266  !< The turbulent kinetic energy per unit mass at the interfaces [Z2 T-2 ~> m2 s-2].
267  !! This may be at the tracer or corner points
268 end type vertvisc_type
269 
270 !> Container for information about the summed layer transports
271 !! and how they will vary as the barotropic velocity is changed.
272 type, public :: bt_cont_type
273  real, allocatable :: fa_u_ee(:,:) !< The effective open face area for zonal barotropic transport
274  !! drawing from locations far to the east [H L ~> m2 or kg m-1].
275  real, allocatable :: fa_u_e0(:,:) !< The effective open face area for zonal barotropic transport
276  !! drawing from nearby to the east [H L ~> m2 or kg m-1].
277  real, allocatable :: fa_u_w0(:,:) !< The effective open face area for zonal barotropic transport
278  !! drawing from nearby to the west [H L ~> m2 or kg m-1].
279  real, allocatable :: fa_u_ww(:,:) !< The effective open face area for zonal barotropic transport
280  !! drawing from locations far to the west [H L ~> m2 or kg m-1].
281  real, allocatable :: ubt_ww(:,:) !< uBT_WW is the barotropic velocity [L T-1 ~> m s-1], beyond which the marginal
282  !! open face area is FA_u_WW. uBT_WW must be non-negative.
283  real, allocatable :: ubt_ee(:,:) !< uBT_EE is a barotropic velocity [L T-1 ~> m s-1], beyond which the marginal
284  !! open face area is FA_u_EE. uBT_EE must be non-positive.
285  real, allocatable :: fa_v_nn(:,:) !< The effective open face area for meridional barotropic transport
286  !! drawing from locations far to the north [H L ~> m2 or kg m-1].
287  real, allocatable :: fa_v_n0(:,:) !< The effective open face area for meridional barotropic transport
288  !! drawing from nearby to the north [H L ~> m2 or kg m-1].
289  real, allocatable :: fa_v_s0(:,:) !< The effective open face area for meridional barotropic transport
290  !! drawing from nearby to the south [H L ~> m2 or kg m-1].
291  real, allocatable :: fa_v_ss(:,:) !< The effective open face area for meridional barotropic transport
292  !! drawing from locations far to the south [H L ~> m2 or kg m-1].
293  real, allocatable :: vbt_ss(:,:) !< vBT_SS is the barotropic velocity, [L T-1 ~> m s-1], beyond which the marginal
294  !! open face area is FA_v_SS. vBT_SS must be non-negative.
295  real, allocatable :: vbt_nn(:,:) !< vBT_NN is the barotropic velocity, [L T-1 ~> m s-1], beyond which the marginal
296  !! open face area is FA_v_NN. vBT_NN must be non-positive.
297  real, allocatable :: h_u(:,:,:) !< An effective thickness at zonal faces [H ~> m or kg m-2].
298  real, allocatable :: h_v(:,:,:) !< An effective thickness at meridional faces [H ~> m or kg m-2].
299  type(group_pass_type) :: pass_polarity_bt !< Structure for polarity group halo updates
300  type(group_pass_type) :: pass_fa_uv !< Structure for face area group halo updates
301 end type bt_cont_type
302 
303 contains
304 
305 !> Allocates the fields for the surface (return) properties of
306 !! the ocean model. Unused fields are unallocated.
307 subroutine allocate_surface_state(sfc_state, G, use_temperature, do_integrals, &
308  gas_fields_ocn, use_meltpot, use_iceshelves, omit_frazil)
309  type(ocean_grid_type), intent(in) :: G !< ocean grid structure
310  type(surface), intent(inout) :: sfc_state !< ocean surface state type to be allocated.
311  logical, optional, intent(in) :: use_temperature !< If true, allocate the space for thermodynamic variables.
312  logical, optional, intent(in) :: do_integrals !< If true, allocate the space for vertically
313  !! integrated fields.
314  type(coupler_1d_bc_type), &
315  optional, intent(in) :: gas_fields_ocn !< If present, this type describes the ocean
316  !! ocean and surface-ice fields that will participate
317  !! in the calculation of additional gas or other
318  !! tracer fluxes, and can be used to spawn related
319  !! internal variables in the ice model.
320  logical, optional, intent(in) :: use_meltpot !< If true, allocate the space for melt potential
321  logical, optional, intent(in) :: use_iceshelves !< If true, allocate the space for the stresses
322  !! under ice shelves.
323  logical, optional, intent(in) :: omit_frazil !< If present and false, do not allocate the space to
324  !! pass frazil fluxes to the coupler
325 
326  ! local variables
327  logical :: use_temp, alloc_integ, use_melt_potential, alloc_iceshelves, alloc_frazil
328  integer :: is, ie, js, je, isd, ied, jsd, jed
329  integer :: isdB, iedB, jsdB, jedB
330 
331  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
332  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
333  isdb = g%isdB ; iedb = g%iedB; jsdb = g%jsdB ; jedb = g%jedB
334 
335  use_temp = .true. ; if (present(use_temperature)) use_temp = use_temperature
336  alloc_integ = .true. ; if (present(do_integrals)) alloc_integ = do_integrals
337  use_melt_potential = .false. ; if (present(use_meltpot)) use_melt_potential = use_meltpot
338  alloc_iceshelves = .false. ; if (present(use_iceshelves)) alloc_iceshelves = use_iceshelves
339  alloc_frazil = .true. ; if (present(omit_frazil)) alloc_frazil = .not.omit_frazil
340 
341  if (sfc_state%arrays_allocated) return
342 
343  if (use_temp) then
344  allocate(sfc_state%SST(isd:ied,jsd:jed)) ; sfc_state%SST(:,:) = 0.0
345  allocate(sfc_state%SSS(isd:ied,jsd:jed)) ; sfc_state%SSS(:,:) = 0.0
346  else
347  allocate(sfc_state%sfc_density(isd:ied,jsd:jed)) ; sfc_state%sfc_density(:,:) = 0.0
348  endif
349  if (use_temp .and. alloc_frazil) then
350  allocate(sfc_state%frazil(isd:ied,jsd:jed)) ; sfc_state%frazil(:,:) = 0.0
351  endif
352  allocate(sfc_state%sea_lev(isd:ied,jsd:jed)) ; sfc_state%sea_lev(:,:) = 0.0
353  allocate(sfc_state%Hml(isd:ied,jsd:jed)) ; sfc_state%Hml(:,:) = 0.0
354  allocate(sfc_state%u(isdb:iedb,jsd:jed)) ; sfc_state%u(:,:) = 0.0
355  allocate(sfc_state%v(isd:ied,jsdb:jedb)) ; sfc_state%v(:,:) = 0.0
356 
357  if (use_melt_potential) then
358  allocate(sfc_state%melt_potential(isd:ied,jsd:jed)) ; sfc_state%melt_potential(:,:) = 0.0
359  endif
360 
361  if (alloc_integ) then
362  ! Allocate structures for the vertically integrated ocean_mass, ocean_heat, and ocean_salt.
363  allocate(sfc_state%ocean_mass(isd:ied,jsd:jed)) ; sfc_state%ocean_mass(:,:) = 0.0
364  if (use_temp) then
365  allocate(sfc_state%ocean_heat(isd:ied,jsd:jed)) ; sfc_state%ocean_heat(:,:) = 0.0
366  allocate(sfc_state%ocean_salt(isd:ied,jsd:jed)) ; sfc_state%ocean_salt(:,:) = 0.0
367  allocate(sfc_state%TempxPmE(isd:ied,jsd:jed)) ; sfc_state%TempxPmE(:,:) = 0.0
368  allocate(sfc_state%salt_deficit(isd:ied,jsd:jed)) ; sfc_state%salt_deficit(:,:) = 0.0
369  allocate(sfc_state%internal_heat(isd:ied,jsd:jed)) ; sfc_state%internal_heat(:,:) = 0.0
370  endif
371  endif
372 
373  if (alloc_iceshelves) then
374  allocate(sfc_state%taux_shelf(isdb:iedb,jsd:jed)) ; sfc_state%taux_shelf(:,:) = 0.0
375  allocate(sfc_state%tauy_shelf(isd:ied,jsdb:jedb)) ; sfc_state%tauy_shelf(:,:) = 0.0
376  endif
377 
378  if (present(gas_fields_ocn)) &
379  call coupler_type_spawn(gas_fields_ocn, sfc_state%tr_fields, &
380  (/is,is,ie,ie/), (/js,js,je,je/), as_needed=.true.)
381 
382  sfc_state%arrays_allocated = .true.
383 
384 end subroutine allocate_surface_state
385 
386 !> Deallocates the elements of a surface state type.
387 subroutine deallocate_surface_state(sfc_state)
388  type(surface), intent(inout) :: sfc_state !< ocean surface state type to be deallocated here.
389 
390  if (.not.sfc_state%arrays_allocated) return
391 
392  if (allocated(sfc_state%melt_potential)) deallocate(sfc_state%melt_potential)
393  if (allocated(sfc_state%SST)) deallocate(sfc_state%SST)
394  if (allocated(sfc_state%SSS)) deallocate(sfc_state%SSS)
395  if (allocated(sfc_state%sfc_density)) deallocate(sfc_state%sfc_density)
396  if (allocated(sfc_state%sea_lev)) deallocate(sfc_state%sea_lev)
397  if (allocated(sfc_state%Hml)) deallocate(sfc_state%Hml)
398  if (allocated(sfc_state%u)) deallocate(sfc_state%u)
399  if (allocated(sfc_state%v)) deallocate(sfc_state%v)
400  if (allocated(sfc_state%ocean_mass)) deallocate(sfc_state%ocean_mass)
401  if (allocated(sfc_state%ocean_heat)) deallocate(sfc_state%ocean_heat)
402  if (allocated(sfc_state%ocean_salt)) deallocate(sfc_state%ocean_salt)
403  if (allocated(sfc_state%salt_deficit)) deallocate(sfc_state%salt_deficit)
404 
405  call coupler_type_destructor(sfc_state%tr_fields)
406 
407  sfc_state%arrays_allocated = .false.
408 
409 end subroutine deallocate_surface_state
410 
411 !> Rotate the surface state fields from the input to the model indices.
412 subroutine rotate_surface_state(sfc_state_in, G_in, sfc_state, G, turns)
413  type(surface), intent(in) :: sfc_state_in
414  type(ocean_grid_type), intent(in) :: G_in
415  type(surface), intent(inout) :: sfc_state
416  type(ocean_grid_type), intent(in) :: G
417  integer, intent(in) :: turns
418 
419  logical :: use_temperature, do_integrals, use_melt_potential, use_iceshelves
420 
421  ! NOTE: Many of these are weak tests, since only one is checked
422  use_temperature = allocated(sfc_state_in%SST) &
423  .and. allocated(sfc_state_in%SSS)
424  use_melt_potential = allocated(sfc_state_in%melt_potential)
425  do_integrals = allocated(sfc_state_in%ocean_mass)
426  use_iceshelves = allocated(sfc_state_in%taux_shelf) &
427  .and. allocated(sfc_state_in%tauy_shelf)
428 
429  if (.not. sfc_state%arrays_allocated) then
430  call allocate_surface_state(sfc_state, g, &
431  use_temperature=use_temperature, &
432  do_integrals=do_integrals, &
433  use_meltpot=use_melt_potential, &
434  use_iceshelves=use_iceshelves &
435  )
436  sfc_state%arrays_allocated = .true.
437  endif
438 
439  if (use_temperature) then
440  call rotate_array(sfc_state_in%SST, turns, sfc_state%SST)
441  call rotate_array(sfc_state_in%SSS, turns, sfc_state%SSS)
442  else
443  call rotate_array(sfc_state_in%sfc_density, turns, sfc_state%sfc_density)
444  endif
445 
446  call rotate_array(sfc_state_in%Hml, turns, sfc_state%Hml)
447  call rotate_vector(sfc_state_in%u, sfc_state_in%v, turns, &
448  sfc_state%u, sfc_state%v)
449  call rotate_array(sfc_state_in%sea_lev, turns, sfc_state%sea_lev)
450 
451  if (use_melt_potential) then
452  call rotate_array(sfc_state_in%melt_potential, turns, sfc_state%melt_potential)
453  endif
454 
455  if (do_integrals) then
456  call rotate_array(sfc_state_in%ocean_mass, turns, sfc_state%ocean_mass)
457  if (use_temperature) then
458  call rotate_array(sfc_state_in%ocean_heat, turns, sfc_state%ocean_heat)
459  call rotate_array(sfc_state_in%ocean_salt, turns, sfc_state%ocean_salt)
460  call rotate_array(sfc_state_in%SSS, turns, sfc_state%TempxPmE)
461  call rotate_array(sfc_state_in%salt_deficit, turns, sfc_state%salt_deficit)
462  call rotate_array(sfc_state_in%internal_heat, turns, sfc_state%internal_heat)
463  endif
464  endif
465 
466  if (use_iceshelves) then
467  call rotate_vector(sfc_state_in%taux_shelf, sfc_state_in%tauy_shelf, turns, &
468  sfc_state%taux_shelf, sfc_state%tauy_shelf)
469  endif
470 
471  if (use_temperature .and. allocated(sfc_state_in%frazil)) &
472  call rotate_array(sfc_state_in%frazil, turns, sfc_state%frazil)
473 
474  ! Scalar transfers
475  sfc_state%T_is_conT = sfc_state_in%T_is_conT
476  sfc_state%S_is_absS = sfc_state_in%S_is_absS
477 
478  ! TODO: tracer field rotation
479  if (coupler_type_initialized(sfc_state_in%tr_fields)) &
480  call mom_error(fatal, "Rotation of surface state tracers is not yet " &
481  // "implemented.")
482 end subroutine rotate_surface_state
483 
484 !> Allocates the arrays contained within a BT_cont_type and initializes them to 0.
485 subroutine alloc_bt_cont_type(BT_cont, G, alloc_faces)
486  type(bt_cont_type), pointer :: BT_cont !< The BT_cont_type whose elements will be allocated
487  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
488  logical, optional, intent(in) :: alloc_faces !< If present and true, allocate
489  !! memory for effective face thicknesses.
490 
491  integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB
492  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
493  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
494 
495  if (associated(bt_cont)) call mom_error(fatal, &
496  "alloc_BT_cont_type called with an associated BT_cont_type pointer.")
497 
498  allocate(bt_cont)
499  allocate(bt_cont%FA_u_WW(isdb:iedb,jsd:jed)) ; bt_cont%FA_u_WW(:,:) = 0.0
500  allocate(bt_cont%FA_u_W0(isdb:iedb,jsd:jed)) ; bt_cont%FA_u_W0(:,:) = 0.0
501  allocate(bt_cont%FA_u_E0(isdb:iedb,jsd:jed)) ; bt_cont%FA_u_E0(:,:) = 0.0
502  allocate(bt_cont%FA_u_EE(isdb:iedb,jsd:jed)) ; bt_cont%FA_u_EE(:,:) = 0.0
503  allocate(bt_cont%uBT_WW(isdb:iedb,jsd:jed)) ; bt_cont%uBT_WW(:,:) = 0.0
504  allocate(bt_cont%uBT_EE(isdb:iedb,jsd:jed)) ; bt_cont%uBT_EE(:,:) = 0.0
505 
506  allocate(bt_cont%FA_v_SS(isd:ied,jsdb:jedb)) ; bt_cont%FA_v_SS(:,:) = 0.0
507  allocate(bt_cont%FA_v_S0(isd:ied,jsdb:jedb)) ; bt_cont%FA_v_S0(:,:) = 0.0
508  allocate(bt_cont%FA_v_N0(isd:ied,jsdb:jedb)) ; bt_cont%FA_v_N0(:,:) = 0.0
509  allocate(bt_cont%FA_v_NN(isd:ied,jsdb:jedb)) ; bt_cont%FA_v_NN(:,:) = 0.0
510  allocate(bt_cont%vBT_SS(isd:ied,jsdb:jedb)) ; bt_cont%vBT_SS(:,:) = 0.0
511  allocate(bt_cont%vBT_NN(isd:ied,jsdb:jedb)) ; bt_cont%vBT_NN(:,:) = 0.0
512 
513  if (present(alloc_faces)) then ; if (alloc_faces) then
514  allocate(bt_cont%h_u(isdb:iedb,jsd:jed,1:g%ke)) ; bt_cont%h_u(:,:,:) = 0.0
515  allocate(bt_cont%h_v(isd:ied,jsdb:jedb,1:g%ke)) ; bt_cont%h_v(:,:,:) = 0.0
516  endif ; endif
517 
518 end subroutine alloc_bt_cont_type
519 
520 !> Deallocates the arrays contained within a BT_cont_type.
521 subroutine dealloc_bt_cont_type(BT_cont)
522  type(bt_cont_type), pointer :: BT_cont !< The BT_cont_type whose elements will be deallocated.
523 
524  if (.not.associated(bt_cont)) return
525 
526  deallocate(bt_cont%FA_u_WW) ; deallocate(bt_cont%FA_u_W0)
527  deallocate(bt_cont%FA_u_E0) ; deallocate(bt_cont%FA_u_EE)
528  deallocate(bt_cont%uBT_WW) ; deallocate(bt_cont%uBT_EE)
529 
530  deallocate(bt_cont%FA_v_SS) ; deallocate(bt_cont%FA_v_S0)
531  deallocate(bt_cont%FA_v_N0) ; deallocate(bt_cont%FA_v_NN)
532  deallocate(bt_cont%vBT_SS) ; deallocate(bt_cont%vBT_NN)
533 
534  if (allocated(bt_cont%h_u)) deallocate(bt_cont%h_u)
535  if (allocated(bt_cont%h_v)) deallocate(bt_cont%h_v)
536 
537  deallocate(bt_cont)
538 
539 end subroutine dealloc_bt_cont_type
540 
541 !> Diagnostic checksums on various elements of a thermo_var_ptrs type for debugging.
542 subroutine mom_thermovar_chksum(mesg, tv, G)
543  character(len=*), intent(in) :: mesg !< A message that appears in the checksum lines
544  type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various thermodynamic variables
545  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
546 
547  ! Note that for the chksum calls to be useful for reproducing across PE
548  ! counts, there must be no redundant points, so all variables use is..ie
549  ! and js...je as their extent.
550  if (associated(tv%T)) &
551  call hchksum(tv%T, mesg//" tv%T", g%HI)
552  if (associated(tv%S)) &
553  call hchksum(tv%S, mesg//" tv%S", g%HI)
554  if (associated(tv%frazil)) &
555  call hchksum(tv%frazil, mesg//" tv%frazil", g%HI, scale=g%US%Q_to_J_kg*g%US%RZ_to_kg_m2)
556  if (associated(tv%salt_deficit)) &
557  call hchksum(tv%salt_deficit, mesg//" tv%salt_deficit", g%HI, scale=g%US%RZ_to_kg_m2)
558  if (associated(tv%TempxPmE)) &
559  call hchksum(tv%TempxPmE, mesg//" tv%TempxPmE", g%HI, scale=g%US%RZ_to_kg_m2)
560 end subroutine mom_thermovar_chksum
561 
562 end module mom_variables
Pointers to various fields which may be used describe the surface state of MOM, and which will be ret...
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:26
Provides the ocean grid type.
Definition: MOM_grid.F90:2
Rotate an array pair representing the components of a vector. Rotation is applied across the first an...
Vertical viscosities, drag coefficients, and related fields.
Pointers to arrays with accelerations, which can later be used for derived diagnostics, like energy balances.
A structure for creating arrays of pointers to 2D arrays.
Container for information about the summed layer transports and how they will vary as the barotropic ...
Module for supporting the rotation of a field&#39;s index map. The implementation of each angle is descri...
Describes the decomposed MOM domain and has routines for communications across PEs.
Definition: MOM_domains.F90:2
Pointers to arrays with transports, which can later be used for derived diagnostics, like energy balances.
Routines for error handling and I/O management.
Pointers to all of the prognostic variables allocated in MOM_variables.F90 and MOM.F90.
Provides subroutines for quantities specific to the equation of state.
Definition: MOM_EOS.F90:2
Rotate the elements of an array to the rotated set of indices. Rotation is applied across the first a...
The MOM_domain_type contains information about the domain decompositoin.
Pointers to an assortment of thermodynamic fields that may be available, including potential temperat...
Provides transparent structures with groups of MOM6 variables and supporting routines.
Provides checksumming functions for debugging.
A control structure for the equation of state.
Definition: MOM_EOS.F90:108
A structure for creating arrays of pointers to 3D arrays.