MOM6
pseudo_salt_tracer.F90
1 !> A tracer package that mimics salinity
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
6 use mom_debugging, only : hchksum
7 use mom_diag_mediator, only : post_data, register_diag_field, safe_alloc_ptr
9 use mom_error_handler, only : mom_error, fatal, warning
11 use mom_forcing_type, only : forcing
12 use mom_grid, only : ocean_grid_type
13 use mom_hor_index, only : hor_index_type
14 use mom_io, only : file_exists, read_data, slasher, vardesc, var_desc, query_vardesc
17 use mom_sponge, only : set_up_sponge_field, sponge_cs
18 use mom_time_manager, only : time_type
19 use mom_tracer_registry, only : register_tracer, tracer_registry_type
20 use mom_tracer_diabatic, only : tracer_vertdiff, applytracerboundaryfluxesinout
21 use mom_tracer_z_init, only : tracer_z_init
22 use mom_variables, only : surface
25 
26 use coupler_types_mod, only : coupler_type_set_data, ind_csurf
27 use atmos_ocean_fluxes_mod, only : aof_set_coupler_flux
28 
29 implicit none ; private
30 
31 #include <MOM_memory.h>
32 
33 public register_pseudo_salt_tracer, initialize_pseudo_salt_tracer
34 public pseudo_salt_tracer_column_physics, pseudo_salt_tracer_surface_state
35 public pseudo_salt_stock, pseudo_salt_tracer_end
36 
37 !> The control structure for the pseudo-salt tracer
38 type, public :: pseudo_salt_tracer_cs ; private
39  type(time_type), pointer :: time => null() !< A pointer to the ocean model's clock.
40  type(tracer_registry_type), pointer :: tr_reg => null() !< A pointer to the MOM tracer registry
41  real, pointer :: ps(:,:,:) => null() !< The array of pseudo-salt tracer used in this
42  !! subroutine [ppt}
43  real, pointer :: diff(:,:,:) => null() !< The difference between the pseudo-salt
44  !! tracer and the real salt [ppt].
45  logical :: pseudo_salt_may_reinit = .true. !< Hard coding since this should not matter
46 
47  integer :: id_psd = -1 !< A diagnostic ID
48 
49  type(diag_ctrl), pointer :: diag => null() !< A structure that is used to
50  !! regulate the timing of diagnostic output.
51  type(mom_restart_cs), pointer :: restart_csp => null() !< A pointer to the restart control structure
52 
53  type(vardesc) :: tr_desc !< A description and metadata for the pseudo-salt tracer
54 end type pseudo_salt_tracer_cs
55 
56 contains
57 
58 !> Register the pseudo-salt tracer with MOM6
59 function register_pseudo_salt_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)
60  type(hor_index_type), intent(in) :: hi !< A horizontal index type structure
61  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
62  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
63  type(pseudo_salt_tracer_cs), pointer :: cs !< The control structure returned by a previous
64  !! call to register_pseudo_salt_tracer.
65  type(tracer_registry_type), pointer :: tr_reg !< A pointer that is set to point to the control
66  !! structure for the tracer advection and
67  !! diffusion module
68  type(mom_restart_cs), pointer :: restart_cs !< A pointer to the restart control structure
69 ! This subroutine is used to register tracer fields and subroutines
70 ! to be used with MOM.
71 
72  ! Local variables
73  character(len=40) :: mdl = "pseudo_salt_tracer" ! This module's name.
74  character(len=200) :: inputdir ! The directory where the input files are.
75  character(len=48) :: var_name ! The variable's name.
76  character(len=3) :: name_tag ! String for creating identifying pseudo_salt
77 ! This include declares and sets the variable "version".
78 #include "version_variable.h"
79  real, pointer :: tr_ptr(:,:,:) => null()
80  logical :: register_pseudo_salt_tracer
81  integer :: isd, ied, jsd, jed, nz, i, j
82  isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed ; nz = gv%ke
83 
84  if (associated(cs)) then
85  call mom_error(warning, "register_pseudo_salt_tracer called with an "// &
86  "associated control structure.")
87  return
88  endif
89  allocate(cs)
90 
91  ! Read all relevant parameters and write them to the model log.
92  call log_version(param_file, mdl, version, "")
93 
94  allocate(cs%ps(isd:ied,jsd:jed,nz)) ; cs%ps(:,:,:) = 0.0
95  allocate(cs%diff(isd:ied,jsd:jed,nz)) ; cs%diff(:,:,:) = 0.0
96 
97  cs%tr_desc = var_desc(trim("pseudo_salt"), "psu", &
98  "Pseudo salt passive tracer", caller=mdl)
99 
100  tr_ptr => cs%ps(:,:,:)
101  call query_vardesc(cs%tr_desc, name=var_name, caller="register_pseudo_salt_tracer")
102  ! Register the tracer for horizontal advection, diffusion, and restarts.
103  call register_tracer(tr_ptr, tr_reg, param_file, hi, gv, name="pseudo_salt", &
104  longname="Pseudo salt passive tracer", units="psu", &
105  registry_diags=.true., restart_cs=restart_cs, &
106  mandatory=.not.cs%pseudo_salt_may_reinit)
107 
108  cs%tr_Reg => tr_reg
109  cs%restart_CSp => restart_cs
110  register_pseudo_salt_tracer = .true.
111 
112 end function register_pseudo_salt_tracer
113 
114 !> Initialize the pseudo-salt tracer
115 subroutine initialize_pseudo_salt_tracer(restart, day, G, GV, h, diag, OBC, CS, &
116  sponge_CSp, tv)
117  logical, intent(in) :: restart !< .true. if the fields have already
118  !! been read from a restart file.
119  type(time_type), target, intent(in) :: day !< Time of the start of the run.
120  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure
121  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
122  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
123  intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
124  type(diag_ctrl), target, intent(in) :: diag !< A structure that is used to regulate
125  !! diagnostic output.
126  type(ocean_obc_type), pointer :: obc !< This open boundary condition type specifies
127  !! whether, where, and what open boundary
128  !! conditions are used.
129  type(pseudo_salt_tracer_cs), pointer :: cs !< The control structure returned by a previous
130  !! call to register_pseudo_salt_tracer.
131  type(sponge_cs), pointer :: sponge_csp !< Pointer to the control structure for the sponges.
132  type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various thermodynamic variables
133 ! This subroutine initializes the tracer fields in CS%ps(:,:,:).
134 
135  ! Local variables
136  character(len=16) :: name ! A variable's name in a NetCDF file.
137  character(len=72) :: longname ! The long name of that variable.
138  character(len=48) :: units ! The dimensions of the variable.
139  character(len=48) :: flux_units ! The units for age tracer fluxes, either
140  ! years m3 s-1 or years kg s-1.
141  logical :: ok
142  integer :: i, j, k, is, ie, js, je, isd, ied, jsd, jed, nz
143  integer :: isdb, iedb, jsdb, jedb
144 
145  if (.not.associated(cs)) return
146  if (.not.associated(cs%diff)) return
147 
148  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
149  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
150  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
151 
152  cs%Time => day
153  cs%diag => diag
154  name = "pseudo_salt"
155 
156  call query_vardesc(cs%tr_desc, name=name, caller="initialize_pseudo_salt_tracer")
157  if ((.not.restart) .or. (.not.query_initialized(cs%ps, name, cs%restart_CSp))) then
158  do k=1,nz ; do j=jsd,jed ; do i=isd,ied
159  cs%ps(i,j,k) = tv%S(i,j,k)
160  enddo ; enddo ; enddo
161  endif
162 
163  if (associated(obc)) then
164  ! Steal from updated DOME in the fullness of time.
165  endif
166 
167  cs%id_psd = register_diag_field("ocean_model", "pseudo_salt_diff", cs%diag%axesTL, &
168  day, "Difference between pseudo salt passive tracer and salt tracer", "psu")
169 
170 end subroutine initialize_pseudo_salt_tracer
171 
172 !> Apply sources, sinks and diapycnal diffusion to the tracers in this package.
173 subroutine pseudo_salt_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, GV, CS, tv, debug, &
174  evap_CFL_limit, minimum_forcing_depth)
175  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure
176  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
177  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
178  intent(in) :: h_old !< Layer thickness before entrainment [H ~> m or kg m-2].
179  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
180  intent(in) :: h_new !< Layer thickness after entrainment [H ~> m or kg m-2].
181  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
182  intent(in) :: ea !< an array to which the amount of fluid entrained
183  !! from the layer above during this call will be
184  !! added [H ~> m or kg m-2].
185  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
186  intent(in) :: eb !< an array to which the amount of fluid entrained
187  !! from the layer below during this call will be
188  !! added [H ~> m or kg m-2].
189  type(forcing), intent(in) :: fluxes !< A structure containing pointers to thermodynamic
190  !! and tracer forcing fields. Unused fields have NULL ptrs.
191  real, intent(in) :: dt !< The amount of time covered by this call [s]
192  type(pseudo_salt_tracer_cs), pointer :: cs !< The control structure returned by a previous
193  !! call to register_pseudo_salt_tracer.
194  type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various thermodynamic variables
195  logical, intent(in) :: debug !< If true calculate checksums
196  real, optional, intent(in) :: evap_cfl_limit !< Limit on the fraction of the water that can
197  !! be fluxed out of the top layer in a timestep [nondim]
198  real, optional, intent(in) :: minimum_forcing_depth !< The smallest depth over which
199  !! fluxes can be applied [m]
200 
201 ! This subroutine applies diapycnal diffusion and any other column
202 ! tracer physics or chemistry to the tracers from this file.
203 
204 ! The arguments to this subroutine are redundant in that
205 ! h_new(k) = h_old(k) + ea(k) - eb(k-1) + eb(k) - ea(k+1)
206 
207  ! Local variables
208  real :: year, h_total, scale, htot, ih_limit
209  integer :: secs, days
210  integer :: i, j, k, is, ie, js, je, nz, k_max
211  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: h_work ! Used so that h can be modified
212 
213  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
214 
215  if (.not.associated(cs)) return
216  if (.not.associated(cs%diff)) return
217 
218  if (debug) then
219  call hchksum(tv%S,"salt pre pseudo-salt vertdiff", g%HI)
220  call hchksum(cs%ps,"pseudo_salt pre pseudo-salt vertdiff", g%HI)
221  endif
222 
223  ! This uses applyTracerBoundaryFluxesInOut, usually in ALE mode
224  if (present(evap_cfl_limit) .and. present(minimum_forcing_depth)) then
225  do k=1,nz ; do j=js,je ; do i=is,ie
226  h_work(i,j,k) = h_old(i,j,k)
227  enddo ; enddo ; enddo
228  call applytracerboundaryfluxesinout(g, gv, cs%ps, dt, fluxes, h_work, &
229  evap_cfl_limit, minimum_forcing_depth, out_flux_optional=fluxes%netSalt)
230  call tracer_vertdiff(h_work, ea, eb, dt, cs%ps, g, gv)
231  else
232  call tracer_vertdiff(h_old, ea, eb, dt, cs%ps, g, gv)
233  endif
234 
235  do k=1,nz ; do j=js,je ; do i=is,ie
236  cs%diff(i,j,k) = cs%ps(i,j,k)-tv%S(i,j,k)
237  enddo ; enddo ; enddo
238 
239  if (debug) then
240  call hchksum(tv%S,"salt post pseudo-salt vertdiff", g%HI)
241  call hchksum(cs%ps,"pseudo_salt post pseudo-salt vertdiff", g%HI)
242  endif
243 
244  if (cs%id_psd>0) call post_data(cs%id_psd, cs%diff, cs%diag)
245 
246 end subroutine pseudo_salt_tracer_column_physics
247 
248 
249 !> Calculates the mass-weighted integral of all tracer stocks, returning the number of stocks it has
250 !! calculated. If the stock_index is present, only the stock corresponding to that coded index is returned.
251 function pseudo_salt_stock(h, stocks, G, GV, CS, names, units, stock_index)
252  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure
253  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
254  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
255  real, dimension(:), intent(out) :: stocks !< the mass-weighted integrated amount of each
256  !! tracer, in kg times concentration units [kg conc].
257  type(pseudo_salt_tracer_cs), pointer :: cs !< The control structure returned by a previous
258  !! call to register_pseudo_salt_tracer.
259  character(len=*), dimension(:), intent(out) :: names !< The names of the stocks calculated.
260  character(len=*), dimension(:), intent(out) :: units !< The units of the stocks calculated.
261  integer, optional, intent(in) :: stock_index !< The coded index of a specific stock
262  !! being sought.
263  integer :: pseudo_salt_stock !< Return value: the number of
264  !! stocks calculated here.
265 
266 ! This function calculates the mass-weighted integral of all tracer stocks,
267 ! returning the number of stocks it has calculated. If the stock_index
268 ! is present, only the stock corresponding to that coded index is returned.
269 
270  integer :: i, j, k, is, ie, js, je, nz
271  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
272 
273  pseudo_salt_stock = 0
274  if (.not.associated(cs)) return
275  if (.not.associated(cs%diff)) return
276 
277  if (present(stock_index)) then ; if (stock_index > 0) then
278  ! Check whether this stock is available from this routine.
279 
280  ! No stocks from this routine are being checked yet. Return 0.
281  return
282  endif ; endif
283 
284  call query_vardesc(cs%tr_desc, name=names(1), units=units(1), caller="pseudo_salt_stock")
285  units(1) = trim(units(1))//" kg"
286  stocks(1) = 0.0
287  do k=1,nz ; do j=js,je ; do i=is,ie
288  stocks(1) = stocks(1) + cs%diff(i,j,k) * &
289  (g%mask2dT(i,j) * g%areaT(i,j) * h(i,j,k))
290  enddo ; enddo ; enddo
291  stocks(1) = gv%H_to_kg_m2 * stocks(1)
292 
293  pseudo_salt_stock = 1
294 
295 end function pseudo_salt_stock
296 
297 !> This subroutine extracts the surface fields from this tracer package that
298 !! are to be shared with the atmosphere in coupled configurations.
299 !! This particular tracer package does not report anything back to the coupler.
300 subroutine pseudo_salt_tracer_surface_state(state, h, G, CS)
301  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure.
302  type(surface), intent(inout) :: state !< A structure containing fields that
303  !! describe the surface state of the ocean.
304  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
305  intent(in) :: h !< Layer thickness [H ~> m or kg m-2].
306  type(pseudo_salt_tracer_cs), pointer :: cs !< The control structure returned by a previous
307  !! call to register_pseudo_salt_tracer.
308 
309  ! This particular tracer package does not report anything back to the coupler.
310  ! The code that is here is just a rough guide for packages that would.
311 
312  integer :: m, is, ie, js, je, isd, ied, jsd, jed
313  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
314  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
315 
316  if (.not.associated(cs)) return
317 
318  ! By design, this tracer package does not return any surface states.
319 
320 end subroutine pseudo_salt_tracer_surface_state
321 
322 !> Deallocate memory associated with this tracer package
323 subroutine pseudo_salt_tracer_end(CS)
324  type(pseudo_salt_tracer_cs), pointer :: cs !< The control structure returned by a previous
325  !! call to register_pseudo_salt_tracer.
326  integer :: m
327 
328  if (associated(cs)) then
329  if (associated(cs%ps)) deallocate(cs%ps)
330  if (associated(cs%diff)) deallocate(cs%diff)
331  deallocate(cs)
332  endif
333 end subroutine pseudo_salt_tracer_end
334 
335 !> \namespace pseudo_salt_tracer
336 !!
337 !! By Andrew Shao, 2016
338 !!
339 !! This file contains the routines necessary to model a passive
340 !! tracer that uses the same boundary fluxes as salinity. At the
341 !! beginning of the run, salt is set to the same as tv%S. Any
342 !! deviations between this salt-like tracer and tv%S signifies a
343 !! difference between how active and passive tracers are treated.
344 
345 end module pseudo_salt_tracer
mom_time_manager
Wraps the FMS time manager functions.
Definition: MOM_time_manager.F90:2
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_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
atmos_ocean_fluxes_mod
A dummy version of atmos_ocean_fluxes_mod module for use when the vastly larger FMS package is not ne...
Definition: atmos_ocean_fluxes.F90:3
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_tracer_registry
This module contains the tracer_registry_type and the subroutines that handle registration of tracers...
Definition: MOM_tracer_registry.F90:5
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_hor_index
Defines the horizontal index type (hor_index_type) used for providing index ranges.
Definition: MOM_hor_index.F90:2
pseudo_salt_tracer
A tracer package that mimics salinity.
Definition: pseudo_salt_tracer.F90:2
mom_io
This module contains I/O framework code.
Definition: MOM_io.F90:2
mom_restart::mom_restart_cs
A restart registry and the control structure for restarts.
Definition: MOM_restart.F90:72
mom_tracer_z_init
Used to initialize tracers from a depth- (or z*-) space file.
Definition: MOM_tracer_Z_init.F90:2
mom_tracer_diabatic
This module contains routines that implement physical fluxes of tracers (e.g. due to surface fluxes o...
Definition: MOM_tracer_diabatic.F90:4
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_restart
The MOM6 facility for reading and writing restart files, and querying what has been read.
Definition: MOM_restart.F90:2
mom_variables
Provides transparent structures with groups of MOM6 variables and supporting routines.
Definition: MOM_variables.F90:2
mom_open_boundary
Controls where open boundary conditions are applied.
Definition: MOM_open_boundary.F90:2
mom_file_parser
The MOM6 facility to parse input files for runtime parameters.
Definition: MOM_file_parser.F90:2
mom_sponge
Implements sponge regions in isopycnal mode.
Definition: MOM_sponge.F90:2
mom_tracer_registry::tracer_registry_type
Type to carry basic tracer information.
Definition: MOM_tracer_registry.F90:122
mom_hor_index::hor_index_type
Container for horizontal index ranges for data, computational and global domains.
Definition: MOM_hor_index.F90:15
mom_grid
Provides the ocean grid type.
Definition: MOM_grid.F90:2
mom_open_boundary::ocean_obc_type
Open-boundary data.
Definition: MOM_open_boundary.F90:186
mom_sponge::sponge_cs
This control structure holds memory and parameters for the MOM_sponge module.
Definition: MOM_sponge.F90:40
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_io::vardesc
Type for describing a variable, typically a tracer.
Definition: MOM_io.F90:53
mom_io::file_exists
Indicate whether a file exists, perhaps with domain decomposition.
Definition: MOM_io.F90:68
pseudo_salt_tracer::pseudo_salt_tracer_cs
The control structure for the pseudo-salt tracer.
Definition: pseudo_salt_tracer.F90:38
mom_file_parser::log_param
An overloaded interface to log the values of various types of parameters.
Definition: MOM_file_parser.F90:96
mom_restart::query_initialized
Indicate whether a field has been read from a restart file.
Definition: MOM_restart.F90:116
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