MOM6
pseudo_salt_tracer.F90
Go to the documentation of this file.
2 !***********************************************************************
3 !* GNU General Public License *
4 !* This file is a part of MOM. *
5 !* *
6 !* MOM is free software; you can redistribute it and/or modify it and *
7 !* are expected to follow the terms of the GNU General Public License *
8 !* as published by the Free Software Foundation; either version 2 of *
9 !* the License, or (at your option) any later version. *
10 !* *
11 !* MOM is distributed in the hope that it will be useful, but WITHOUT *
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
13 !* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public *
14 !* License for more details. *
15 !* *
16 !* For the full text of the GNU General Public License, *
17 !* write to: Free Software Foundation, Inc., *
18 !* 675 Mass Ave, Cambridge, MA 02139, USA. *
19 !* or see: http://www.gnu.org/licenses/gpl.html *
20 !***********************************************************************
21 
22 !********+*********+*********+*********+*********+*********+*********+**
23 !* *
24 !* By Andrew Shao, 2016 *
25 !* *
26 !* This file contains the routines necessary to model a passive *
27 !* tracer that uses the same boundary fluxes as salinity. At the *
28 !* beginning of the run, salt is set to the same as tv%S. Any *
29 !* deviations between this salt-like tracer and tv%S signifies a *
30 !* difference between how active and passive tracers are treated. *
31 !* A single subroutine is called from within each file to register *
32 !* each of the tracers for reinitialization and advection and to *
33 !* register the subroutine that initializes the tracers and set up *
34 !* their output and the subroutine that does any tracer physics or *
35 !* chemistry along with diapycnal mixing (included here because some *
36 !* tracers may float or swim vertically or dye diapycnal processes). *
37 !* *
38 !* *
39 !* Macros written all in capital letters are defined in MOM_memory.h. *
40 !* *
41 !* A small fragment of the grid is shown below: *
42 !* *
43 !* j+1 x ^ x ^ x At x: q *
44 !* j+1 > o > o > At ^: v *
45 !* j x ^ x ^ x At >: u *
46 !* j > o > o > At o: h, tr *
47 !* j-1 x ^ x ^ x *
48 !* i-1 i i+1 At x & ^: *
49 !* i i+1 At > & o: *
50 !* *
51 !* The boundaries always run through q grid points (x). *
52 !* *
53 !********+*********+*********+*********+*********+*********+*********+**
54 
55 use mom_debugging, only : hchksum
56 use mom_diag_mediator, only : post_data, register_diag_field, safe_alloc_ptr
57 use mom_diag_mediator, only : diag_ctrl
59 use mom_error_handler, only : mom_error, fatal, warning
61 use mom_forcing_type, only : forcing
62 use mom_grid, only : ocean_grid_type
63 use mom_hor_index, only : hor_index_type
64 use mom_io, only : file_exists, read_data, slasher, vardesc, var_desc, query_vardesc
68 use mom_time_manager, only : time_type, get_time
73 use mom_variables, only : surface
76 use coupler_util, only : set_coupler_values, ind_csurf
78 
79 implicit none ; private
80 
81 #include <MOM_memory.h>
82 
86 
87 ! NTR_MAX is the maximum number of tracers in this module.
88 integer, parameter :: ntr_max = 1
89 
90 type p3d
91  real, dimension(:,:,:), pointer :: p => null()
92 end type p3d
93 
94 type, public :: pseudo_salt_tracer_cs ; private
95  integer :: ntr=ntr_max ! The number of tracers that are actually used.
96  logical :: coupled_tracers = .false. ! These tracers are not offered to the
97  ! coupler.
98  type(time_type), pointer :: time ! A pointer to the ocean model's clock.
99  type(tracer_registry_type), pointer :: tr_reg => null()
100  real, pointer :: tr(:,:,:,:) => null() ! The array of tracers used in this
101  ! subroutine, in g m-3?
102  real, pointer :: diff(:,:,:,:) => null() ! The array of tracers used in this
103  ! subroutine, in g m-3?
104  type(p3d), dimension(NTR_MAX) :: &
105  tr_adx, &! Tracer zonal advective fluxes in g m-3 m3 s-1.An Error Has Occurred
106 
107 
108  tr_ady, &! Tracer meridional advective fluxes in g m-3 m3 s-1.
109  tr_dfx, &! Tracer zonal diffusive fluxes in g m-3 m3 s-1.
110  tr_dfy ! Tracer meridional diffusive fluxes in g m-3 m3 s-1.
111  logical :: mask_tracers ! If true, pseudo_salt is masked out in massless layers.
112  logical :: pseudo_salt_may_reinit = .true. ! Hard coding since this should not matter
113  integer, dimension(NTR_MAX) :: &
114  ind_tr, & ! Indices returned by aof_set_coupler_flux if it is used and the
115  ! surface tracer concentrations are to be provided to the coupler.
116  id_tracer = -1, id_tr_adx = -1, id_tr_ady = -1, &
117  id_tr_dfx = -1, id_tr_dfy = -1
118  real, dimension(NTR_MAX) :: land_val = -1.0
119 
120  type(diag_ctrl), pointer :: diag ! A structure that is used to regulate the
121  ! timing of diagnostic output.
122  type(mom_restart_cs), pointer :: restart_csp => null()
123 
124  type(vardesc) :: tr_desc(ntr_max)
125 end type pseudo_salt_tracer_cs
126 
127 contains
128 
129 function register_pseudo_salt_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)
130  type(hor_index_type), intent(in) :: HI
131  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure
132  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
133  type(pseudo_salt_tracer_cs), pointer :: CS
134  type(tracer_registry_type), pointer :: tr_Reg
135  type(mom_restart_cs), pointer :: restart_CS
136 ! This subroutine is used to register tracer fields and subroutines
137 ! to be used with MOM.
138 ! Arguments: HI - A horizontal index type structure.
139 ! (in) GV - The ocean's vertical grid structure.
140 ! (in) param_file - A structure indicating the open file to parse for
141 ! model parameter values.
142 ! (in/out) CS - A pointer that is set to point to the control structure
143 ! for this module
144 ! (in/out) tr_Reg - A pointer that is set to point to the control structure
145 ! for the tracer advection and diffusion module.
146 ! (in) restart_CS - A pointer to the restart control structure.
147 
148 ! This include declares and sets the variable "version".
149 #include "version_variable.h"
150  character(len=40) :: mdl = "pseudo_salt_tracer" ! This module's name.
151  character(len=200) :: inputdir ! The directory where the input files are.
152  character(len=48) :: var_name ! The variable's name.
153  character(len=3) :: name_tag ! String for creating identifying pseudo_salt
154  real, pointer :: tr_ptr(:,:,:) => null()
155  logical :: register_pseudo_salt_tracer
156  integer :: isd, ied, jsd, jed, nz, m, i, j
157  isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed ; nz = gv%ke
158 
159  if (associated(cs)) then
160  call mom_error(warning, "register_pseudo_salt_tracer called with an "// &
161  "associated control structure.")
162  return
163  endif
164  allocate(cs)
165 
166  ! Read all relevant parameters and write them to the model log.
167  call log_version(param_file, mdl, version, "")
168 
169  cs%ntr = ntr_max
170  allocate(cs%tr(isd:ied,jsd:jed,nz,cs%ntr)) ; cs%tr(:,:,:,:) = 0.0
171  allocate(cs%diff(isd:ied,jsd:jed,nz,cs%ntr)) ; cs%diff(:,:,:,:) = 0.0
172 
173  do m=1,cs%ntr
174  ! This is needed to force the compiler not to do a copy in the registration
175  ! calls. Curses on the designers and implementers of Fortran90.
176  cs%tr_desc(m) = var_desc(trim("pseudo_salt_diff"), "kg", &
177  "Difference between pseudo salt passive tracer and salt tracer", caller=mdl)
178  tr_ptr => cs%tr(:,:,:,m)
179  call query_vardesc(cs%tr_desc(m), name=var_name, caller="register_pseudo_salt_tracer")
180  ! Register the tracer for the restart file.
181  call register_restart_field(tr_ptr, cs%tr_desc(m), &
182  .not. cs%pseudo_salt_may_reinit, restart_cs)
183  ! Register the tracer for horizontal advection & diffusion.
184  call register_tracer(tr_ptr, cs%tr_desc(m), param_file, hi, gv, tr_reg, &
185  tr_desc_ptr=cs%tr_desc(m))
186 
187  ! Set coupled_tracers to be true (hard-coded above) to provide the surface
188  ! values to the coupler (if any). This is meta-code and its arguments will
189  ! currently (deliberately) give fatal errors if it is used.
190  if (cs%coupled_tracers) &
191  cs%ind_tr(m) = aof_set_coupler_flux(trim(var_name)//'_flux', &
192  flux_type=' ', implementation=' ', caller="register_pseudo_salt_tracer")
193  enddo
194 
195  cs%tr_Reg => tr_reg
196  cs%restart_CSp => restart_cs
197  register_pseudo_salt_tracer = .true.
198 
199 end function register_pseudo_salt_tracer
200 
201 subroutine initialize_pseudo_salt_tracer(restart, day, G, GV, h, diag, OBC, CS, &
202  sponge_CSp, diag_to_Z_CSp, tv)
203  logical, intent(in) :: restart
204  type(time_type), target, intent(in) :: day
205  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
206  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure
207  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thicknesses, in H (usually m or kg m-2)
208  type(diag_ctrl), target, intent(in) :: diag
209  type(ocean_obc_type), pointer :: OBC
210  type(pseudo_salt_tracer_cs), pointer :: CS
211  type(sponge_cs), pointer :: sponge_CSp
212  type(diag_to_z_cs), pointer :: diag_to_Z_CSp
213  type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various thermodynamic variables
214 ! This subroutine initializes the CS%ntr tracer fields in tr(:,:,:,:)
215 ! and it sets up the tracer output.
216 
217 ! Arguments: restart - .true. if the fields have already been read from
218 ! a restart file.
219 ! (in) day - Time of the start of the run.
220 ! (in) G - The ocean's grid structure.
221 ! (in) GV - The ocean's vertical grid structure.
222 ! (in) h - Layer thickness, in m or kg m-2.
223 ! (in) diag - A structure that is used to regulate diagnostic output.
224 ! (in) OBC - This open boundary condition type specifies whether, where,
225 ! and what open boundary conditions are used.
226 ! (in/out) CS - The control structure returned by a previous call to
227 ! register_pseudo_salt_tracer.
228 ! (in/out) sponge_CSp - A pointer to the control structure for the sponges, if
229 ! they are in use. Otherwise this may be unassociated.
230 ! (in/out) diag_to_Z_Csp - A pointer to the control structure for diagnostics
231 ! in depth space.
232  character(len=16) :: name ! A variable's name in a NetCDF file.
233  character(len=72) :: longname ! The long name of that variable.
234  character(len=48) :: units ! The dimensions of the variable.
235  character(len=48) :: flux_units ! The units for age tracer fluxes, either
236  ! years m3 s-1 or years kg s-1.
237  logical :: OK
238  integer :: i, j, k, is, ie, js, je, isd, ied, jsd, jed, nz, m
239  integer :: IsdB, IedB, JsdB, JedB
240 
241  if (.not.associated(cs)) return
242  if (cs%ntr < 1) return
243  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
244  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
245  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
246 
247  cs%Time => day
248  cs%diag => diag
249  name = "pseudo_salt"
250 
251  do m=1,cs%ntr
252  call query_vardesc(cs%tr_desc(m), name=name, caller="initialize_pseudo_salt_tracer")
253  if ((.not.restart) .or. (.not. &
254  query_initialized(cs%tr(:,:,:,m), name, cs%restart_CSp))) then
255  do k=1,nz ; do j=jsd,jed ; do i=isd,ied
256  cs%tr(i,j,k,m) = tv%S(i,j,k)
257  enddo ; enddo ; enddo
258  endif
259  enddo ! Tracer loop
260 
261  if (associated(obc)) then
262  ! All tracers but the first have 0 concentration in their inflows. As this
263  ! is the default value, the following calls are unnecessary.
264  ! do m=1,CS%ntr
265  ! call add_tracer_OBC_values(trim(CS%tr_desc(m)%name), CS%tr_Reg, 0.0)
266  ! enddo
267  endif
268 
269  ! This needs to be changed if the units of tracer are changed above.
270  if (gv%Boussinesq) then ; flux_units = "g salt/(m^2 s)"
271  else ; flux_units = "g salt/(m^2 s)" ; endif
272 
273  do m=1,cs%ntr
274  ! Register the tracer for the restart file.
275  call query_vardesc(cs%tr_desc(m), name, units=units, longname=longname, &
276  caller="initialize_pseudo_salt_tracer")
277  cs%id_tracer(m) = register_diag_field("ocean_model", trim(name), cs%diag%axesTL, &
278  day, trim(longname) , trim(units))
279  cs%id_tr_adx(m) = register_diag_field("ocean_model", trim(name)//"_adx", &
280  cs%diag%axesCuL, day, trim(longname)//" advective zonal flux" , &
281  trim(flux_units))
282  cs%id_tr_ady(m) = register_diag_field("ocean_model", trim(name)//"_ady", &
283  cs%diag%axesCvL, day, trim(longname)//" advective meridional flux" , &
284  trim(flux_units))
285  cs%id_tr_dfx(m) = register_diag_field("ocean_model", trim(name)//"_dfx", &
286  cs%diag%axesCuL, day, trim(longname)//" diffusive zonal flux" , &
287  trim(flux_units))
288  cs%id_tr_dfy(m) = register_diag_field("ocean_model", trim(name)//"_dfy", &
289  cs%diag%axesCvL, day, trim(longname)//" diffusive zonal flux" , &
290  trim(flux_units))
291  if (cs%id_tr_adx(m) > 0) call safe_alloc_ptr(cs%tr_adx(m)%p,isdb,iedb,jsd,jed,nz)
292  if (cs%id_tr_ady(m) > 0) call safe_alloc_ptr(cs%tr_ady(m)%p,isd,ied,jsdb,jedb,nz)
293  if (cs%id_tr_dfx(m) > 0) call safe_alloc_ptr(cs%tr_dfx(m)%p,isdb,iedb,jsd,jed,nz)
294  if (cs%id_tr_dfy(m) > 0) call safe_alloc_ptr(cs%tr_dfy(m)%p,isd,ied,jsdb,jedb,nz)
295 
296 ! Register the tracer for horizontal advection & diffusion.
297  if ((cs%id_tr_adx(m) > 0) .or. (cs%id_tr_ady(m) > 0) .or. &
298  (cs%id_tr_dfx(m) > 0) .or. (cs%id_tr_dfy(m) > 0)) &
299  call add_tracer_diagnostics(name, cs%tr_Reg, cs%tr_adx(m)%p, &
300  cs%tr_ady(m)%p,cs%tr_dfx(m)%p,cs%tr_dfy(m)%p)
301 
302  call register_z_tracer(cs%tr(:,:,:,m), trim(name), longname, units, &
303  day, g, diag_to_z_csp)
304  enddo
305 
306 end subroutine initialize_pseudo_salt_tracer
307 
308 subroutine pseudo_salt_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, GV, CS, tv, debug, &
309  evap_CFL_limit, minimum_forcing_depth)
310  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
311  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure
312  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h_old, h_new, ea, eb
313  type(forcing), intent(in) :: fluxes
314  real, intent(in) :: dt !< The amount of time covered by this call, in s
315  type(pseudo_salt_tracer_cs), pointer :: CS
316  type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various thermodynamic variables
317  logical, intent(in) :: debug
318  real, optional,intent(in) :: evap_CFL_limit
319  real, optional,intent(in) :: minimum_forcing_depth
320 
321 ! This subroutine applies diapycnal diffusion and any other column
322 ! tracer physics or chemistry to the tracers from this file.
323 ! This is a simple example of a set of advected passive tracers.
324 
325 ! Arguments: h_old - Layer thickness before entrainment, in m or kg m-2.
326 ! (in) h_new - Layer thickness after entrainment, in m or kg m-2.
327 ! (in) ea - an array to which the amount of fluid entrained
328 ! from the layer above during this call will be
329 ! added, in m or kg m-2.
330 ! (in) eb - an array to which the amount of fluid entrained
331 ! from the layer below during this call will be
332 ! added, in m or kg m-2.
333 ! (in) fluxes - A structure containing pointers to any possible
334 ! forcing fields. Unused fields have NULL ptrs.
335 ! (in) dt - The amount of time covered by this call, in s.
336 ! (in) G - The ocean's grid structure.
337 ! (in) GV - The ocean's vertical grid structure.
338 ! (in) CS - The control structure returned by a previous call to
339 ! register_pseudo_salt_tracer.
340 ! (in) tv - Thermodynamic structure with T and S
341 ! (in) evap_CFL_limit - Limits how much water can be fluxed out of the top layer
342 ! Stored previously in diabatic CS.
343 ! (in) minimum_forcing_depth - The smallest depth over which fluxes can be applied
344 ! Stored previously in diabatic CS.
345 ! (in) debug - Calculates checksums
346 !
347 ! The arguments to this subroutine are redundant in that
348 ! h_new[k] = h_old[k] + ea[k] - eb[k-1] + eb[k] - ea[k+1]
349 
350  real :: Isecs_per_year = 1.0 / (365.0*86400.0)
351  real :: year, h_total, scale, htot, Ih_limit
352  integer :: secs, days
353  integer :: i, j, k, is, ie, js, je, nz, m, k_max
354  real, allocatable :: local_tr(:,:,:)
355  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: h_work ! Used so that h can be modified
356  real, dimension(:,:), pointer :: net_salt
357 
358  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
359  net_salt=>fluxes%netSalt
360 
361  if (.not.associated(cs)) return
362  if (cs%ntr < 1) return
363 
364  if (debug) then
365  call hchksum(tv%S,"salt pre pseudo-salt vertdiff", g%HI)
366  call hchksum(cs%tr(:,:,:,1),"pseudo_salt pre pseudo-salt vertdiff", g%HI)
367  endif
368 
369  ! This uses applyTracerBoundaryFluxesInOut, usually in ALE mode
370  if (present(evap_cfl_limit) .and. present(minimum_forcing_depth)) then
371  do k=1,nz ;do j=js,je ; do i=is,ie
372  h_work(i,j,k) = h_old(i,j,k)
373  enddo ; enddo ; enddo;
374  call applytracerboundaryfluxesinout(g, gv, cs%tr(:,:,:,1), dt, fluxes, h_work, &
375  evap_cfl_limit, minimum_forcing_depth, out_flux_optional=net_salt)
376  call tracer_vertdiff(h_work, ea, eb, dt, cs%tr(:,:,:,1), g, gv)
377  else
378  call tracer_vertdiff(h_work, ea, eb, dt, cs%tr(:,:,:,1), g, gv)
379  endif
380 
381  do k=1,nz ; do j=js,je ; do i=is,ie
382  cs%diff(i,j,k,1) = cs%tr(i,j,k,1)-tv%S(i,j,k)
383  enddo ; enddo ; enddo
384 
385  if(debug) then
386  call hchksum(tv%S,"salt post pseudo-salt vertdiff", g%HI)
387  call hchksum(cs%tr(:,:,:,1),"pseudo_salt post pseudo-salt vertdiff", g%HI)
388  endif
389 
390  allocate(local_tr(g%isd:g%ied,g%jsd:g%jed,nz))
391  do m=1,1
392  if (cs%id_tracer(m)>0) then
393  if (cs%mask_tracers) then
394  do k=1,nz ; do j=js,je ; do i=is,ie
395  if (h_new(i,j,k) < 1.1*gv%Angstrom) then
396  local_tr(i,j,k) = cs%land_val(m)
397  else
398  local_tr(i,j,k) = cs%diff(i,j,k,m)
399  endif
400  enddo ; enddo ; enddo
401  else
402  do k=1,nz ; do j=js,je ; do i=is,ie
403  local_tr(i,j,k) = cs%tr(i,j,k,m)-tv%S(i,j,k)
404  enddo ; enddo ; enddo
405  endif ! CS%mask_tracers
406  call post_data(cs%id_tracer(m),local_tr,cs%diag)
407  endif ! CS%id_tracer(m)>0
408  if (cs%id_tr_adx(m)>0) &
409  call post_data(cs%id_tr_adx(m),cs%tr_adx(m)%p(:,:,:),cs%diag)
410  if (cs%id_tr_ady(m)>0) &
411  call post_data(cs%id_tr_ady(m),cs%tr_ady(m)%p(:,:,:),cs%diag)
412  if (cs%id_tr_dfx(m)>0) &
413  call post_data(cs%id_tr_dfx(m),cs%tr_dfx(m)%p(:,:,:),cs%diag)
414  if (cs%id_tr_dfy(m)>0) &
415  call post_data(cs%id_tr_dfy(m),cs%tr_dfy(m)%p(:,:,:),cs%diag)
416  enddo
417  deallocate(local_tr)
418 
420 
421 function pseudo_salt_stock(h, stocks, G, GV, CS, names, units, stock_index)
422  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
423  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure
424  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thicknesses, in H (usually m or kg m-2)
425  real, dimension(:), intent(out) :: stocks
426  type(pseudo_salt_tracer_cs), pointer :: CS
427  character(len=*), dimension(:), intent(out) :: names
428  character(len=*), dimension(:), intent(out) :: units
429  integer, optional, intent(in) :: stock_index
430  integer :: pseudo_salt_stock
431 ! This function calculates the mass-weighted integral of all tracer stocks,
432 ! returning the number of stocks it has calculated. If the stock_index
433 ! is present, only the stock corresponding to that coded index is returned.
434 
435 ! Arguments: h - Layer thickness, in m or kg m-2.
436 ! (out) stocks - the mass-weighted integrated amount of each tracer,
437 ! in kg times concentration units.
438 ! (in) G - The ocean's grid structure.
439 ! (in) GV - The ocean's vertical grid structure.
440 ! (in) CS - The control structure returned by a previous call to
441 ! register_pseudo_salt_tracer.
442 ! (out) names - the names of the stocks calculated.
443 ! (out) units - the units of the stocks calculated.
444 ! (in,opt) stock_index - the coded index of a specific stock being sought.
445 ! Return value: the number of stocks calculated here.
446 
447  integer :: i, j, k, is, ie, js, je, nz, m
448  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
449 
450  pseudo_salt_stock = 0
451  if (.not.associated(cs)) return
452  if (cs%ntr < 1) return
453 
454  if (present(stock_index)) then ; if (stock_index > 0) then
455  ! Check whether this stock is available from this routine.
456 
457  ! No stocks from this routine are being checked yet. Return 0.
458  return
459  endif ; endif
460 
461  do m=1,1
462  call query_vardesc(cs%tr_desc(m), name=names(m), units=units(m), caller="pseudo_salt_stock")
463  units(m) = trim(units(m))//" kg"
464  stocks(m) = 0.0
465  do k=1,nz ; do j=js,je ; do i=is,ie
466  stocks(m) = stocks(m) + cs%diff(i,j,k,m) * &
467  (g%mask2dT(i,j) * g%areaT(i,j) * h(i,j,k))
468  enddo ; enddo ; enddo
469  stocks(m) = gv%H_to_kg_m2 * stocks(m)
470  enddo
471 
472  pseudo_salt_stock = cs%ntr
473 
474 end function pseudo_salt_stock
475 
476 subroutine pseudo_salt_tracer_surface_state(state, h, G, CS)
477  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
478  type(surface), intent(inout) :: state
479  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thicknesses, in H (usually m or kg m-2)
480  type(pseudo_salt_tracer_cs), pointer :: CS
481 ! This particular tracer package does not report anything back to the coupler.
482 ! The code that is here is just a rough guide for packages that would.
483 ! Arguments: state - A structure containing fields that describe the
484 ! surface state of the ocean.
485 ! (in) h - Layer thickness, in m or kg m-2.
486 ! (in) G - The ocean's grid structure.
487 ! (in) CS - The control structure returned by a previous call to
488 ! register_pseudo_salt_tracer.
489  integer :: m, is, ie, js, je
490  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
491 
492  if (.not.associated(cs)) return
493 
494  if (cs%coupled_tracers) then
495  do m=1,cs%ntr
496  ! This call loads the surface vlues into the appropriate array in the
497  ! coupler-type structure.
498  call set_coupler_values(cs%tr(:,:,1,m), state%tr_fields, cs%ind_tr(m), &
499  ind_csurf, is, ie, js, je)
500  enddo
501  endif
502 
504 
505 subroutine pseudo_salt_tracer_end(CS)
506  type(pseudo_salt_tracer_cs), pointer :: CS
507  integer :: m
508 
509  if (associated(cs)) then
510  if (associated(cs%tr)) deallocate(cs%tr)
511  if (associated(cs%tr)) deallocate(cs%diff)
512  do m=1,cs%ntr
513  if (associated(cs%tr_adx(m)%p)) deallocate(cs%tr_adx(m)%p)
514  if (associated(cs%tr_ady(m)%p)) deallocate(cs%tr_ady(m)%p)
515  if (associated(cs%tr_dfx(m)%p)) deallocate(cs%tr_dfx(m)%p)
516  if (associated(cs%tr_dfy(m)%p)) deallocate(cs%tr_dfy(m)%p)
517  enddo
518 
519  deallocate(cs)
520  endif
521 end subroutine pseudo_salt_tracer_end
522 
523 end module pseudo_salt_tracer
integer function, public pseudo_salt_stock(h, stocks, G, GV, CS, names, units, stock_index)
The following structure contains pointers to various fields which may be used describe the surface st...
type(vardesc) function, public var_desc(name, units, longname, hor_grid, z_grid, t_grid, cmor_field_name, cmor_units, conversion, caller)
Returns a vardesc type whose elements have been filled with the provided fields. The argument name is...
Definition: MOM_io.F90:585
subroutine, public pseudo_salt_tracer_end(CS)
This module implements boundary forcing for MOM6.
integer function, public aof_set_coupler_flux(name, flux_type, implementation, atm_tr_index, param, flag, ice_restart_file, ocean_restart_file, units, caller)
logical function, public tracer_z_init(tr, h, filename, tr_name, G, missing_val, land_val)
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:19
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
Provides the ocean grid type.
Definition: MOM_grid.F90:2
subroutine, public pseudo_salt_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, GV, CS, tv, debug, evap_CFL_limit, minimum_forcing_depth)
This module contains I/O framework code.
Definition: MOM_io.F90:2
Defines the horizontal index type (hor_index_type) used for providing index ranges.
Container for horizontal index ranges for data, computational and global domains. ...
subroutine, public initialize_pseudo_salt_tracer(restart, day, G, GV, h, diag, OBC, CS, sponge_CSp, diag_to_Z_CSp, tv)
subroutine, public register_tracer(tr1, tr_desc, param_file, HI, GV, Reg, tr_desc_ptr, ad_x, ad_y, df_x, df_y, OBC_inflow, OBC_in_u, OBC_in_v, ad_2d_x, ad_2d_y, df_2d_x, df_2d_y, advection_xy)
This subroutine registers a tracer to be advected and laterally diffused.
This module contains the tracer_registry_type and the subroutines that handle registration of tracers...
subroutine, public pseudo_salt_tracer_surface_state(state, h, G, CS)
subroutine, public applytracerboundaryfluxesinout(G, GV, Tr, dt, fluxes, h, evap_CFL_limit, minimum_forcing_depth, in_flux_optional, out_flux_optional, update_h_opt)
This routine is modeled after applyBoundaryFluxesInOut in MOM_diabatic_aux.F90 NOTE: Please note that...
subroutine, public set_up_sponge_field(sp_val, f_ptr, G, nlay, CS, sp_val_i_mean)
Definition: MOM_sponge.F90:271
Type to carry basic tracer information.
integer, parameter ntr_max
This module contains routines that implement physical fluxes of tracers (e.g. due to surface fluxes o...
subroutine, public register_z_tracer(tr_ptr, name, long_name, units, Time, G, CS, standard_name, cmor_field_name, cmor_long_name, cmor_units, cmor_standard_name)
This subroutine registers a tracer to be output in depth space.
subroutine, public add_tracer_obc_values(name, Reg, OBC_inflow, OBC_in_u, OBC_in_v)
This subroutine adds open boundary condition concentrations for a tracer that has previously been reg...
subroutine, public add_tracer_diagnostics(name, Reg, ad_x, ad_y, df_x, df_y, ad_2d_x, ad_2d_y, df_2d_x, df_2d_y, advection_xy)
This subroutine adds diagnostic arrays for a tracer that has previously been registered by a call to ...
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
subroutine, public set_coupler_values(array_in, BC_struc, BC_index, BC_element, is, ie, js, je, conversion)
Type for describing a variable, typically a tracer.
Definition: MOM_io.F90:51
subroutine, public tracer_vertdiff(h_old, ea, eb, dt, tr, G, GV, sfc_flux, btm_flux, btm_reservoir, sink_rate, convert_flux_in)
This subroutine solves a tridiagonal equation for the final tracer concentrations after the dual-entr...
The thermo_var_ptrs structure contains pointers to an assortment of thermodynamic fields that may be ...
subroutine, public query_vardesc(vd, name, units, longname, hor_grid, z_grid, t_grid, cmor_field_name, cmor_units, conversion, caller)
This routine queries vardesc.
Definition: MOM_io.F90:664
Controls where open boundary conditions are applied.
integer function, public register_diag_field(module_name, field_name, axes, init_time, long_name, units, missing_value, range, mask_variant, standard_name, verbose, do_not_log, err_msg, interp_method, tile_count, cmor_field_name, cmor_long_name, cmor_units, cmor_standard_name, cell_methods, x_cell_method, y_cell_method, v_cell_method, conversion, v_extensive)
Returns the "diag_mediator" handle for a group (native, CMOR, z-coord, ...) of diagnostics derived fr...
subroutine, public mom_error(level, message, all_print)
logical function, public register_pseudo_salt_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)