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_shear => null()
245  !< The shear-driven turbulent diapycnal diffusivity at the interfaces between layers
246  !! in tracer columns [Z2 T-1 ~> m2 s-1].
247  real, pointer, dimension(:,:,:) :: kv_shear => null()
248  !< The shear-driven turbulent vertical viscosity at the interfaces between layers
249  !! in tracer columns [Z2 T-1 ~> m2 s-1].
250  real, pointer, dimension(:,:,:) :: kv_shear_bu => null()
251  !< The shear-driven turbulent vertical viscosity at the interfaces between layers in
252  !! corner columns [Z2 T-1 ~> m2 s-1].
253  real, pointer, dimension(:,:,:) :: kv_slow => null()
254  !< The turbulent vertical viscosity component due to "slow" processes (e.g., tidal,
255  !! background, convection etc) [Z2 T-1 ~> m2 s-1].
256  real, pointer, dimension(:,:,:) :: tke_turb => null()
257  !< The turbulent kinetic energy per unit mass at the interfaces [Z2 T-2 ~> m2 s-2].
258  !! This may be at the tracer or corner points
259 end type vertvisc_type
260 
261 !> Container for information about the summed layer transports
262 !! and how they will vary as the barotropic velocity is changed.
263 type, public :: bt_cont_type
264  real, allocatable :: fa_u_ee(:,:) !< The effective open face area for zonal barotropic transport
265  !! drawing from locations far to the east [H L ~> m2 or kg m-1].
266  real, allocatable :: fa_u_e0(:,:) !< The effective open face area for zonal barotropic transport
267  !! drawing from nearby to the east [H L ~> m2 or kg m-1].
268  real, allocatable :: fa_u_w0(:,:) !< The effective open face area for zonal barotropic transport
269  !! drawing from nearby to the west [H L ~> m2 or kg m-1].
270  real, allocatable :: fa_u_ww(:,:) !< The effective open face area for zonal barotropic transport
271  !! drawing from locations far to the west [H L ~> m2 or kg m-1].
272  real, allocatable :: ubt_ww(:,:) !< uBT_WW is the barotropic velocity [L T-1 ~> m s-1], beyond which the marginal
273  !! open face area is FA_u_WW. uBT_WW must be non-negative.
274  real, allocatable :: ubt_ee(:,:) !< uBT_EE is a barotropic velocity [L T-1 ~> m s-1], beyond which the marginal
275  !! open face area is FA_u_EE. uBT_EE must be non-positive.
276  real, allocatable :: fa_v_nn(:,:) !< The effective open face area for meridional barotropic transport
277  !! drawing from locations far to the north [H L ~> m2 or kg m-1].
278  real, allocatable :: fa_v_n0(:,:) !< The effective open face area for meridional barotropic transport
279  !! drawing from nearby to the north [H L ~> m2 or kg m-1].
280  real, allocatable :: fa_v_s0(:,:) !< The effective open face area for meridional barotropic transport
281  !! drawing from nearby to the south [H L ~> m2 or kg m-1].
282  real, allocatable :: fa_v_ss(:,:) !< The effective open face area for meridional barotropic transport
283  !! drawing from locations far to the south [H L ~> m2 or kg m-1].
284  real, allocatable :: vbt_ss(:,:) !< vBT_SS is the barotropic velocity, [L T-1 ~> m s-1], beyond which the marginal
285  !! open face area is FA_v_SS. vBT_SS must be non-negative.
286  real, allocatable :: vbt_nn(:,:) !< vBT_NN is the barotropic velocity, [L T-1 ~> m s-1], beyond which the marginal
287  !! open face area is FA_v_NN. vBT_NN must be non-positive.
288  real, allocatable :: h_u(:,:,:) !< An effective thickness at zonal faces [H ~> m or kg m-2].
289  real, allocatable :: h_v(:,:,:) !< An effective thickness at meridional faces [H ~> m or kg m-2].
290  type(group_pass_type) :: pass_polarity_bt !< Structure for polarity group halo updates
291  type(group_pass_type) :: pass_fa_uv !< Structure for face area group halo updates
292 end type bt_cont_type
293 
294 contains
295 
296 !> Allocates the fields for the surface (return) properties of
297 !! the ocean model. Unused fields are unallocated.
298 subroutine allocate_surface_state(sfc_state, G, use_temperature, do_integrals, &
299  gas_fields_ocn, use_meltpot, use_iceshelves, omit_frazil)
300  type(ocean_grid_type), intent(in) :: G !< ocean grid structure
301  type(surface), intent(inout) :: sfc_state !< ocean surface state type to be allocated.
302  logical, optional, intent(in) :: use_temperature !< If true, allocate the space for thermodynamic variables.
303  logical, optional, intent(in) :: do_integrals !< If true, allocate the space for vertically
304  !! integrated fields.
305  type(coupler_1d_bc_type), &
306  optional, intent(in) :: gas_fields_ocn !< If present, this type describes the ocean
307  !! ocean and surface-ice fields that will participate
308  !! in the calculation of additional gas or other
309  !! tracer fluxes, and can be used to spawn related
310  !! internal variables in the ice model.
311  logical, optional, intent(in) :: use_meltpot !< If true, allocate the space for melt potential
312  logical, optional, intent(in) :: use_iceshelves !< If true, allocate the space for the stresses
313  !! under ice shelves.
314  logical, optional, intent(in) :: omit_frazil !< If present and false, do not allocate the space to
315  !! pass frazil fluxes to the coupler
316 
317  ! local variables
318  logical :: use_temp, alloc_integ, use_melt_potential, alloc_iceshelves, alloc_frazil
319  integer :: is, ie, js, je, isd, ied, jsd, jed
320  integer :: isdB, iedB, jsdB, jedB
321 
322  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
323  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
324  isdb = g%isdB ; iedb = g%iedB; jsdb = g%jsdB ; jedb = g%jedB
325 
326  use_temp = .true. ; if (present(use_temperature)) use_temp = use_temperature
327  alloc_integ = .true. ; if (present(do_integrals)) alloc_integ = do_integrals
328  use_melt_potential = .false. ; if (present(use_meltpot)) use_melt_potential = use_meltpot
329  alloc_iceshelves = .false. ; if (present(use_iceshelves)) alloc_iceshelves = use_iceshelves
330  alloc_frazil = .true. ; if (present(omit_frazil)) alloc_frazil = .not.omit_frazil
331 
332  if (sfc_state%arrays_allocated) return
333 
334  if (use_temp) then
335  allocate(sfc_state%SST(isd:ied,jsd:jed)) ; sfc_state%SST(:,:) = 0.0
336  allocate(sfc_state%SSS(isd:ied,jsd:jed)) ; sfc_state%SSS(:,:) = 0.0
337  else
338  allocate(sfc_state%sfc_density(isd:ied,jsd:jed)) ; sfc_state%sfc_density(:,:) = 0.0
339  endif
340  if (use_temp .and. alloc_frazil) then
341  allocate(sfc_state%frazil(isd:ied,jsd:jed)) ; sfc_state%frazil(:,:) = 0.0
342  endif
343  allocate(sfc_state%sea_lev(isd:ied,jsd:jed)) ; sfc_state%sea_lev(:,:) = 0.0
344  allocate(sfc_state%Hml(isd:ied,jsd:jed)) ; sfc_state%Hml(:,:) = 0.0
345  allocate(sfc_state%u(isdb:iedb,jsd:jed)) ; sfc_state%u(:,:) = 0.0
346  allocate(sfc_state%v(isd:ied,jsdb:jedb)) ; sfc_state%v(:,:) = 0.0
347 
348  if (use_melt_potential) then
349  allocate(sfc_state%melt_potential(isd:ied,jsd:jed)) ; sfc_state%melt_potential(:,:) = 0.0
350  endif
351 
352  if (alloc_integ) then
353  ! Allocate structures for the vertically integrated ocean_mass, ocean_heat, and ocean_salt.
354  allocate(sfc_state%ocean_mass(isd:ied,jsd:jed)) ; sfc_state%ocean_mass(:,:) = 0.0
355  if (use_temp) then
356  allocate(sfc_state%ocean_heat(isd:ied,jsd:jed)) ; sfc_state%ocean_heat(:,:) = 0.0
357  allocate(sfc_state%ocean_salt(isd:ied,jsd:jed)) ; sfc_state%ocean_salt(:,:) = 0.0
358  allocate(sfc_state%TempxPmE(isd:ied,jsd:jed)) ; sfc_state%TempxPmE(:,:) = 0.0
359  allocate(sfc_state%salt_deficit(isd:ied,jsd:jed)) ; sfc_state%salt_deficit(:,:) = 0.0
360  allocate(sfc_state%internal_heat(isd:ied,jsd:jed)) ; sfc_state%internal_heat(:,:) = 0.0
361  endif
362  endif
363 
364  if (alloc_iceshelves) then
365  allocate(sfc_state%taux_shelf(isdb:iedb,jsd:jed)) ; sfc_state%taux_shelf(:,:) = 0.0
366  allocate(sfc_state%tauy_shelf(isd:ied,jsdb:jedb)) ; sfc_state%tauy_shelf(:,:) = 0.0
367  endif
368 
369  if (present(gas_fields_ocn)) &
370  call coupler_type_spawn(gas_fields_ocn, sfc_state%tr_fields, &
371  (/is,is,ie,ie/), (/js,js,je,je/), as_needed=.true.)
372 
373  sfc_state%arrays_allocated = .true.
374 
375 end subroutine allocate_surface_state
376 
377 !> Deallocates the elements of a surface state type.
378 subroutine deallocate_surface_state(sfc_state)
379  type(surface), intent(inout) :: sfc_state !< ocean surface state type to be deallocated here.
380 
381  if (.not.sfc_state%arrays_allocated) return
382 
383  if (allocated(sfc_state%melt_potential)) deallocate(sfc_state%melt_potential)
384  if (allocated(sfc_state%SST)) deallocate(sfc_state%SST)
385  if (allocated(sfc_state%SSS)) deallocate(sfc_state%SSS)
386  if (allocated(sfc_state%sfc_density)) deallocate(sfc_state%sfc_density)
387  if (allocated(sfc_state%sea_lev)) deallocate(sfc_state%sea_lev)
388  if (allocated(sfc_state%Hml)) deallocate(sfc_state%Hml)
389  if (allocated(sfc_state%u)) deallocate(sfc_state%u)
390  if (allocated(sfc_state%v)) deallocate(sfc_state%v)
391  if (allocated(sfc_state%ocean_mass)) deallocate(sfc_state%ocean_mass)
392  if (allocated(sfc_state%ocean_heat)) deallocate(sfc_state%ocean_heat)
393  if (allocated(sfc_state%ocean_salt)) deallocate(sfc_state%ocean_salt)
394  if (allocated(sfc_state%salt_deficit)) deallocate(sfc_state%salt_deficit)
395 
396  call coupler_type_destructor(sfc_state%tr_fields)
397 
398  sfc_state%arrays_allocated = .false.
399 
400 end subroutine deallocate_surface_state
401 
402 !> Rotate the surface state fields from the input to the model indices.
403 subroutine rotate_surface_state(sfc_state_in, G_in, sfc_state, G, turns)
404  type(surface), intent(in) :: sfc_state_in
405  type(ocean_grid_type), intent(in) :: G_in
406  type(surface), intent(inout) :: sfc_state
407  type(ocean_grid_type), intent(in) :: G
408  integer, intent(in) :: turns
409 
410  logical :: use_temperature, do_integrals, use_melt_potential, use_iceshelves
411 
412  ! NOTE: Many of these are weak tests, since only one is checked
413  use_temperature = allocated(sfc_state_in%SST) &
414  .and. allocated(sfc_state_in%SSS)
415  use_melt_potential = allocated(sfc_state_in%melt_potential)
416  do_integrals = allocated(sfc_state_in%ocean_mass)
417  use_iceshelves = allocated(sfc_state_in%taux_shelf) &
418  .and. allocated(sfc_state_in%tauy_shelf)
419 
420  if (.not. sfc_state%arrays_allocated) then
421  call allocate_surface_state(sfc_state, g, &
422  use_temperature=use_temperature, &
423  do_integrals=do_integrals, &
424  use_meltpot=use_melt_potential, &
425  use_iceshelves=use_iceshelves &
426  )
427  sfc_state%arrays_allocated = .true.
428  endif
429 
430  if (use_temperature) then
431  call rotate_array(sfc_state_in%SST, turns, sfc_state%SST)
432  call rotate_array(sfc_state_in%SSS, turns, sfc_state%SSS)
433  else
434  call rotate_array(sfc_state_in%sfc_density, turns, sfc_state%sfc_density)
435  endif
436 
437  call rotate_array(sfc_state_in%Hml, turns, sfc_state%Hml)
438  call rotate_vector(sfc_state_in%u, sfc_state_in%v, turns, &
439  sfc_state%u, sfc_state%v)
440  call rotate_array(sfc_state_in%sea_lev, turns, sfc_state%sea_lev)
441 
442  if (use_melt_potential) then
443  call rotate_array(sfc_state_in%melt_potential, turns, sfc_state%melt_potential)
444  endif
445 
446  if (do_integrals) then
447  call rotate_array(sfc_state_in%ocean_mass, turns, sfc_state%ocean_mass)
448  if (use_temperature) then
449  call rotate_array(sfc_state_in%ocean_heat, turns, sfc_state%ocean_heat)
450  call rotate_array(sfc_state_in%ocean_salt, turns, sfc_state%ocean_salt)
451  call rotate_array(sfc_state_in%SSS, turns, sfc_state%TempxPmE)
452  call rotate_array(sfc_state_in%salt_deficit, turns, sfc_state%salt_deficit)
453  call rotate_array(sfc_state_in%internal_heat, turns, sfc_state%internal_heat)
454  endif
455  endif
456 
457  if (use_iceshelves) then
458  call rotate_vector(sfc_state_in%taux_shelf, sfc_state_in%tauy_shelf, turns, &
459  sfc_state%taux_shelf, sfc_state%tauy_shelf)
460  endif
461 
462  if (use_temperature .and. allocated(sfc_state_in%frazil)) &
463  call rotate_array(sfc_state_in%frazil, turns, sfc_state%frazil)
464 
465  ! Scalar transfers
466  sfc_state%T_is_conT = sfc_state_in%T_is_conT
467  sfc_state%S_is_absS = sfc_state_in%S_is_absS
468 
469  ! TODO: tracer field rotation
470  if (coupler_type_initialized(sfc_state_in%tr_fields)) &
471  call mom_error(fatal, "Rotation of surface state tracers is not yet " &
472  // "implemented.")
473 end subroutine rotate_surface_state
474 
475 !> Allocates the arrays contained within a BT_cont_type and initializes them to 0.
476 subroutine alloc_bt_cont_type(BT_cont, G, alloc_faces)
477  type(bt_cont_type), pointer :: BT_cont !< The BT_cont_type whose elements will be allocated
478  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
479  logical, optional, intent(in) :: alloc_faces !< If present and true, allocate
480  !! memory for effective face thicknesses.
481 
482  integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB
483  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
484  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
485 
486  if (associated(bt_cont)) call mom_error(fatal, &
487  "alloc_BT_cont_type called with an associated BT_cont_type pointer.")
488 
489  allocate(bt_cont)
490  allocate(bt_cont%FA_u_WW(isdb:iedb,jsd:jed)) ; bt_cont%FA_u_WW(:,:) = 0.0
491  allocate(bt_cont%FA_u_W0(isdb:iedb,jsd:jed)) ; bt_cont%FA_u_W0(:,:) = 0.0
492  allocate(bt_cont%FA_u_E0(isdb:iedb,jsd:jed)) ; bt_cont%FA_u_E0(:,:) = 0.0
493  allocate(bt_cont%FA_u_EE(isdb:iedb,jsd:jed)) ; bt_cont%FA_u_EE(:,:) = 0.0
494  allocate(bt_cont%uBT_WW(isdb:iedb,jsd:jed)) ; bt_cont%uBT_WW(:,:) = 0.0
495  allocate(bt_cont%uBT_EE(isdb:iedb,jsd:jed)) ; bt_cont%uBT_EE(:,:) = 0.0
496 
497  allocate(bt_cont%FA_v_SS(isd:ied,jsdb:jedb)) ; bt_cont%FA_v_SS(:,:) = 0.0
498  allocate(bt_cont%FA_v_S0(isd:ied,jsdb:jedb)) ; bt_cont%FA_v_S0(:,:) = 0.0
499  allocate(bt_cont%FA_v_N0(isd:ied,jsdb:jedb)) ; bt_cont%FA_v_N0(:,:) = 0.0
500  allocate(bt_cont%FA_v_NN(isd:ied,jsdb:jedb)) ; bt_cont%FA_v_NN(:,:) = 0.0
501  allocate(bt_cont%vBT_SS(isd:ied,jsdb:jedb)) ; bt_cont%vBT_SS(:,:) = 0.0
502  allocate(bt_cont%vBT_NN(isd:ied,jsdb:jedb)) ; bt_cont%vBT_NN(:,:) = 0.0
503 
504  if (present(alloc_faces)) then ; if (alloc_faces) then
505  allocate(bt_cont%h_u(isdb:iedb,jsd:jed,1:g%ke)) ; bt_cont%h_u(:,:,:) = 0.0
506  allocate(bt_cont%h_v(isd:ied,jsdb:jedb,1:g%ke)) ; bt_cont%h_v(:,:,:) = 0.0
507  endif ; endif
508 
509 end subroutine alloc_bt_cont_type
510 
511 !> Deallocates the arrays contained within a BT_cont_type.
512 subroutine dealloc_bt_cont_type(BT_cont)
513  type(bt_cont_type), pointer :: BT_cont !< The BT_cont_type whose elements will be deallocated.
514 
515  if (.not.associated(bt_cont)) return
516 
517  deallocate(bt_cont%FA_u_WW) ; deallocate(bt_cont%FA_u_W0)
518  deallocate(bt_cont%FA_u_E0) ; deallocate(bt_cont%FA_u_EE)
519  deallocate(bt_cont%uBT_WW) ; deallocate(bt_cont%uBT_EE)
520 
521  deallocate(bt_cont%FA_v_SS) ; deallocate(bt_cont%FA_v_S0)
522  deallocate(bt_cont%FA_v_N0) ; deallocate(bt_cont%FA_v_NN)
523  deallocate(bt_cont%vBT_SS) ; deallocate(bt_cont%vBT_NN)
524 
525  if (allocated(bt_cont%h_u)) deallocate(bt_cont%h_u)
526  if (allocated(bt_cont%h_v)) deallocate(bt_cont%h_v)
527 
528  deallocate(bt_cont)
529 
530 end subroutine dealloc_bt_cont_type
531 
532 !> Diagnostic checksums on various elements of a thermo_var_ptrs type for debugging.
533 subroutine mom_thermovar_chksum(mesg, tv, G)
534  character(len=*), intent(in) :: mesg !< A message that appears in the checksum lines
535  type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various thermodynamic variables
536  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
537 
538  ! Note that for the chksum calls to be useful for reproducing across PE
539  ! counts, there must be no redundant points, so all variables use is..ie
540  ! and js...je as their extent.
541  if (associated(tv%T)) &
542  call hchksum(tv%T, mesg//" tv%T", g%HI)
543  if (associated(tv%S)) &
544  call hchksum(tv%S, mesg//" tv%S", g%HI)
545  if (associated(tv%frazil)) &
546  call hchksum(tv%frazil, mesg//" tv%frazil", g%HI, scale=g%US%Q_to_J_kg*g%US%RZ_to_kg_m2)
547  if (associated(tv%salt_deficit)) &
548  call hchksum(tv%salt_deficit, mesg//" tv%salt_deficit", g%HI, scale=g%US%RZ_to_kg_m2)
549  if (associated(tv%TempxPmE)) &
550  call hchksum(tv%TempxPmE, mesg//" tv%TempxPmE", g%HI, scale=g%US%RZ_to_kg_m2)
551 end subroutine mom_thermovar_chksum
552 
553 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.