MOM6
dye_example.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 Robert Hallberg, 2002 *
25 !* *
26 !* This file contains an example of the code that is needed to set *
27 !* up and use a set (in this case two) of dynamically passive tracers *
28 !* for diagnostic purposes. The tracers here are dye tracers which *
29 !* are set to 1 within the geographical region specified. The depth *
30 !* which a tracer is set is determined by calculating the depth from *
31 !* the seafloor upwards through the column. *
32 !* *
33 !* A single subroutine is called from within each file to register *
34 !* each of the tracers for reinitialization and advection and to *
35 !* register the subroutine that initializes the tracers and set up *
36 !* their output and the subroutine that does any tracer physics or *
37 !* chemistry along with diapycnal mixing (included here because some *
38 !* tracers may float or swim vertically or dye diapycnal processes). *
39 !* *
40 !* *
41 !* Macros written all in capital letters are defined in MOM_memory.h. *
42 !* *
43 !* A small fragment of the grid is shown below: *
44 !* *
45 !* j+1 x ^ x ^ x At x: q *
46 !* j+1 > o > o > At ^: v *
47 !* j x ^ x ^ x At >: u *
48 !* j > o > o > At o: h, tr *
49 !* j-1 x ^ x ^ x *
50 !* i-1 i i+1 At x & ^: *
51 !* i i+1 At > & o: *
52 !* *
53 !* The boundaries always run through q grid points (x). *
54 !* *
55 !********+*********+*********+*********+*********+*********+*********+**
56 
57 use mom_diag_mediator, only : post_data, register_diag_field, safe_alloc_ptr
58 use mom_diag_mediator, only : diag_ctrl
60 use mom_error_handler, only : mom_error, fatal, warning
62 use mom_forcing_type, only : forcing
63 use mom_grid, only : ocean_grid_type
64 use mom_hor_index, only : hor_index_type
65 use mom_io, only : file_exists, read_data, slasher, vardesc, var_desc, query_vardesc
69 use mom_time_manager, only : time_type, get_time
74 use mom_variables, only : surface
76 
77 use coupler_util, only : set_coupler_values, ind_csurf
79 
80 implicit none ; private
81 
82 #include <MOM_memory.h>
83 
87 
88 
89 type p3d
90  real, dimension(:,:,:), pointer :: p => null()
91 end type p3d
92 
93 type, public :: dye_tracer_cs ; private
94  integer :: ntr ! The number of tracers that are actually used.
95  logical :: coupled_tracers = .false. ! These tracers are not offered to the
96  ! coupler.
97  real, allocatable, dimension(:) :: dye_source_minlon, & ! Minimum longitude of region dye will be injected.
98  dye_source_maxlon, & ! Maximum longitude of region dye will be injected.
99  dye_source_minlat, & ! Minimum latitude of region dye will be injected.
100  dye_source_maxlat, & ! Maximum latitude of region dye will be injected.
101  dye_source_mindepth, & ! Minimum depth of region dye will be injected (m).
102  dye_source_maxdepth ! Maximum depth of region dye will be injected (m).
103  type(tracer_registry_type), pointer :: tr_reg => null()
104  real, pointer :: tr(:,:,:,:) => null() ! The array of tracers used in this
105  ! subroutine, in g m-3?
106  type(p3d), allocatable, dimension(:) :: &
107  tr_adx, &! Tracer zonal advective fluxes in g m-3 m3 s-1.
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 
112  integer, allocatable, dimension(:) :: &
113  ind_tr, & ! Indices returned by aof_set_coupler_flux if it is used and the
114  ! surface tracer concentrations are to be provided to the coupler.
115  id_tracer, id_tr_adx, id_tr_ady, &
116  id_tr_dfx, id_tr_dfy
117 
118  type(diag_ctrl), pointer :: diag ! A structure that is used to regulate the
119  ! timing of diagnostic output.
120  type(mom_restart_cs), pointer :: restart_csp => null()
121 
122  type(vardesc), allocatable :: tr_desc(:)
123  logical :: tracers_may_reinit = .false. ! hard-coding here (mjh)
124 end type dye_tracer_cs
125 
126 contains
127 
128 function register_dye_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)
129  type(hor_index_type), intent(in) :: HI
130  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure
131  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
132  type(dye_tracer_cs), pointer :: CS
133  type(tracer_registry_type), pointer :: tr_Reg
134  type(mom_restart_cs), pointer :: restart_CS
135 ! This subroutine is used to register tracer fields and subroutines
136 ! to be used with MOM.
137 ! Arguments: HI - A horizontal index type structure.
138 ! (in) param_file - A structure indicating the open file to parse for
139 ! model parameter values.
140 ! (in/out) CS - A pointer that is set to point to the control structure
141 ! for this module
142 ! (in) diag - A structure that is used to regulate diagnostic output.
143 ! (in/out) tr_Reg - A pointer that is set to point to the control structure
144 ! for the tracer advection and diffusion module.
145 ! (in) restart_CS - A pointer to the restart control structure.
146 
147 ! This include declares and sets the variable "version".
148 #include "version_variable.h"
149  character(len=40) :: mdl = "regional_dyes" ! This module's name.
150  character(len=200) :: inputdir ! The directory where the input files are.
151  character(len=48) :: var_name ! The variable's name.
152  character(len=48) :: desc_name ! The variable's descriptor.
153  real, pointer :: tr_ptr(:,:,:) => null()
154  logical :: register_dye_tracer
155  integer :: isd, ied, jsd, jed, nz, m
156  isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed ; nz = gv%ke
157 
158  if (associated(cs)) then
159  call mom_error(warning, "register_dye_tracer called with an "// &
160  "associated control structure.")
161  return
162  endif
163  allocate(cs)
164 
165  ! Read all relevant parameters and write them to the model log.
166  call log_version(param_file, mdl, version, "")
167  call get_param(param_file, mdl, "NUM_DYE_TRACERS", cs%ntr, &
168  "The number of dye tracers in this run. Each tracer \n"//&
169  "should have a separate region.", default=0)
170  allocate(cs%dye_source_minlon(cs%ntr), &
171  cs%dye_source_maxlon(cs%ntr), &
172  cs%dye_source_minlat(cs%ntr), &
173  cs%dye_source_maxlat(cs%ntr), &
174  cs%dye_source_mindepth(cs%ntr), &
175  cs%dye_source_maxdepth(cs%ntr))
176  allocate(cs%tr_adx(cs%ntr), &
177  cs%tr_ady(cs%ntr), &
178  cs%tr_dfx(cs%ntr), &
179  cs%tr_dfy(cs%ntr))
180  allocate(cs%ind_tr(cs%ntr), &
181  cs%id_tracer(cs%ntr), &
182  cs%id_tr_adx(cs%ntr), &
183  cs%id_tr_ady(cs%ntr), &
184  cs%id_tr_dfx(cs%ntr), &
185  cs%id_tr_dfy(cs%ntr))
186  allocate(cs%tr_desc(cs%ntr))
187 
188  cs%id_tracer(:) = -1
189  cs%id_tr_adx(:) = -1
190  cs%id_tr_ady(:) = -1
191  cs%id_tr_dfx(:) = -1
192  cs%id_tr_dfy(:) = -1
193 
194  cs%dye_source_minlon(:) = -1.e30
195  call get_param(param_file, mdl, "DYE_SOURCE_MINLON", cs%dye_source_minlon, &
196  "This is the starting longitude at which we start injecting dyes.", &
197  fail_if_missing=.true.)
198  if (minval(cs%dye_source_minlon(:)) < -1.e29) &
199  call mom_error(fatal, "register_dye_tracer: Not enough values provided for DYE_SOURCE_MINLON ")
200 
201  cs%dye_source_maxlon(:) = -1.e30
202  call get_param(param_file, mdl, "DYE_SOURCE_MAXLON", cs%dye_source_maxlon, &
203  "This is the ending longitude at which we finish injecting dyes.", &
204  fail_if_missing=.true.)
205  if (minval(cs%dye_source_maxlon(:)) < -1.e29) &
206  call mom_error(fatal, "register_dye_tracer: Not enough values provided for DYE_SOURCE_MAXLON ")
207 
208  cs%dye_source_minlat(:) = -1.e30
209  call get_param(param_file, mdl, "DYE_SOURCE_MINLAT", cs%dye_source_minlat, &
210  "This is the starting latitude at which we start injecting dyes.", &
211  fail_if_missing=.true.)
212  if (minval(cs%dye_source_minlat(:)) < -1.e29) &
213  call mom_error(fatal, "register_dye_tracer: Not enough values provided for DYE_SOURCE_MINLAT ")
214 
215  cs%dye_source_maxlat(:) = -1.e30
216  call get_param(param_file, mdl, "DYE_SOURCE_MAXLAT", cs%dye_source_maxlat, &
217  "This is the ending latitude at which we finish injecting dyes.", &
218  fail_if_missing=.true.)
219  if (minval(cs%dye_source_maxlat(:)) < -1.e29) &
220  call mom_error(fatal, "register_dye_tracer: Not enough values provided for DYE_SOURCE_MAXLAT ")
221 
222  cs%dye_source_mindepth(:) = -1.e30
223  call get_param(param_file, mdl, "DYE_SOURCE_MINDEPTH", cs%dye_source_mindepth, &
224  "This is the minumum depth at which we inject dyes.", &
225  fail_if_missing=.true.)
226  if (minval(cs%dye_source_mindepth(:)) < -1.e29) &
227  call mom_error(fatal, "register_dye_tracer: Not enough values provided for DYE_SOURCE_MINDEPTH")
228 
229  cs%dye_source_maxdepth(:) = -1.e30
230  call get_param(param_file, mdl, "DYE_SOURCE_MAXDEPTH", cs%dye_source_maxdepth, &
231  "This is the maximum depth at which we inject dyes.", &
232  fail_if_missing=.true.)
233  if (minval(cs%dye_source_maxdepth(:)) < -1.e29) &
234  call mom_error(fatal, "register_dye_tracer: Not enough values provided for DYE_SOURCE_MAXDEPTH ")
235 
236  do m = 1, cs%ntr
237  write(var_name(:),'(A,I3.3)') "dye",m
238  write(desc_name(:),'(A,I3.3)') "Dye Tracer ",m
239  cs%tr_desc(m) = var_desc(trim(var_name), "conc", trim(desc_name), caller=mdl)
240  enddo
241 
242 
243 
244  allocate(cs%tr(isd:ied,jsd:jed,nz,cs%ntr)) ; cs%tr(:,:,:,:) = 0.0
245 
246  do m=1,cs%ntr
247  ! This is needed to force the compiler not to do a copy in the registration
248  ! calls. Curses on the designers and implementers of Fortran90.
249  tr_ptr => cs%tr(:,:,:,m)
250  call query_vardesc(cs%tr_desc(m), name=var_name, &
251  caller="register_dye_tracer")
252 ! ! Register the tracer for the restart file.
253  call register_restart_field(tr_ptr, cs%tr_desc(m), &
254  .not.cs%tracers_may_reinit, restart_cs)
255  ! Register the tracer for horizontal advection & diffusion.
256  call register_tracer(tr_ptr, cs%tr_desc(m), param_file, hi, gv, tr_reg, &
257  tr_desc_ptr=cs%tr_desc(m))
258 
259  ! Set coupled_tracers to be true (hard-coded above) to provide the surface
260  ! values to the coupler (if any). This is meta-code and its arguments will
261  ! currently (deliberately) give fatal errors if it is used.
262  if (cs%coupled_tracers) &
263  cs%ind_tr(m) = aof_set_coupler_flux(trim(var_name)//'_flux', &
264  flux_type=' ', implementation=' ', caller="register_dye_tracer")
265  enddo
266 
267  cs%tr_Reg => tr_reg
268  cs%restart_CSp => restart_cs
269  register_dye_tracer = .true.
270 end function register_dye_tracer
271 
272 subroutine initialize_dye_tracer(restart, day, G, GV, h, diag, OBC, CS, sponge_CSp, &
273  diag_to_Z_CSp)
274  logical, intent(in) :: restart
275  type(time_type), target, intent(in) :: day
276  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
277  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure
278  real, dimension(NIMEM_,NJMEM_,NKMEM_), intent(in) :: h !< Layer thicknesses, in H (usually m or kg m-2)
279  type(diag_ctrl), target, intent(in) :: diag
280  type(ocean_obc_type), pointer :: OBC
281  type(dye_tracer_cs), pointer :: CS
282  type(sponge_cs), pointer :: sponge_CSp
283  type(diag_to_z_cs), pointer :: diag_to_Z_CSp
284 ! This subroutine initializes the CS%ntr tracer fields in tr(:,:,:,:)
285 ! and it sets up the tracer output.
286 
287 ! Arguments: restart - .true. if the fields have already been read from
288 ! a restart file.
289 ! (in) day - Time of the start of the run.
290 ! (in) G - The ocean's grid structure.
291 ! (in) GV - The ocean's vertical grid structure.
292 ! (in) h - Layer thickness, in m or kg m-2.
293 ! (in) OBC - This open boundary condition type specifies whether, where,
294 ! and what open boundary conditions are used.
295 ! (in/out) CS - The control structure returned by a previous call to
296 ! register_dye_tracer.
297 ! (in/out) sponge_CSp - A pointer to the control structure for the sponges, if
298 ! they are in use. Otherwise this may be unassociated.
299 ! (in/out) diag_to_Z_Csp - A pointer to the control structure for diagnostics
300 ! in depth space.
301  character(len=24) :: name ! A variable's name in a NetCDF file.
302  character(len=72) :: longname ! The long name of that variable.
303  character(len=48) :: units ! The dimensions of the variable.
304  character(len=48) :: flux_units ! The units for age tracer fluxes, either
305  ! years m3 s-1 or years kg s-1.
306  logical :: OK
307  integer :: i, j, k, m
308  real :: z_bot, z_center
309 
310  if (.not.associated(cs)) return
311  if (cs%ntr < 1) return
312 
313  cs%diag => diag
314 
315  ! Establish location of source
316  do m= 1, cs%ntr
317  do j=g%jsd,g%jed ; do i=g%isd,g%ied
318  ! A dye is set dependent on the center of the cell being inside the rectangular box.
319  if (cs%dye_source_minlon(m)<g%geoLonT(i,j) .and. &
320  cs%dye_source_maxlon(m)>=g%geoLonT(i,j) .and. &
321  cs%dye_source_minlat(m)<g%geoLatT(i,j) .and. &
322  cs%dye_source_maxlat(m)>=g%geoLatT(i,j) .and. &
323  g%mask2dT(i,j) > 0.0 ) then
324  z_bot = -g%bathyT(i,j)
325  do k = gv%ke, 1, -1
326  z_center = z_bot + 0.5*h(i,j,k)*gv%H_to_m
327  if ( z_center > -cs%dye_source_maxdepth(m) .and. &
328  z_center < -cs%dye_source_mindepth(m) ) then
329  cs%tr(i,j,k,m) = 1.0
330  endif
331  z_bot = z_bot + h(i,j,k)*gv%H_to_m
332  enddo
333  endif
334  enddo; enddo
335  enddo
336 
337  do m=1,cs%ntr
338  ! Register the tracer for the restart file.
339  call query_vardesc(cs%tr_desc(m), name, units=units, longname=longname, &
340  caller="initialize_dye_tracer")
341  cs%id_tracer(m) = register_diag_field("ocean_model", trim(name), cs%diag%axesTL, &
342  day, trim(longname) , trim(units))
343  cs%id_tr_adx(m) = register_diag_field("ocean_model", trim(name)//"_adx", &
344  cs%diag%axesCuL, day, trim(longname)//" advective zonal flux" , &
345  trim(flux_units))
346  cs%id_tr_ady(m) = register_diag_field("ocean_model", trim(name)//"_ady", &
347  cs%diag%axesCvL, day, trim(longname)//" advective meridional flux" , &
348  trim(flux_units))
349  cs%id_tr_dfx(m) = register_diag_field("ocean_model", trim(name)//"_dfx", &
350  cs%diag%axesCuL, day, trim(longname)//" diffusive zonal flux" , &
351  trim(flux_units))
352  cs%id_tr_dfy(m) = register_diag_field("ocean_model", trim(name)//"_dfy", &
353  cs%diag%axesCvL, day, trim(longname)//" diffusive zonal flux" , &
354  trim(flux_units))
355  if (cs%id_tr_adx(m) > 0) call safe_alloc_ptr(cs%tr_adx(m)%p,g%IsdB,g%IedB,g%jsd,g%jed,gv%ke)
356  if (cs%id_tr_ady(m) > 0) call safe_alloc_ptr(cs%tr_ady(m)%p,g%isd,g%ied,g%JsdB,g%JedB,gv%ke)
357  if (cs%id_tr_dfx(m) > 0) call safe_alloc_ptr(cs%tr_dfx(m)%p,g%IsdB,g%IedB,g%jsd,g%jed,gv%ke)
358  if (cs%id_tr_dfy(m) > 0) call safe_alloc_ptr(cs%tr_dfy(m)%p,g%isd,g%ied,g%JsdB,g%JedB,gv%ke)
359 
360 ! Register the tracer for horizontal advection & diffusion.
361  if ((cs%id_tr_adx(m) > 0) .or. (cs%id_tr_ady(m) > 0) .or. &
362  (cs%id_tr_dfx(m) > 0) .or. (cs%id_tr_dfy(m) > 0)) &
363  call add_tracer_diagnostics(name, cs%tr_Reg, cs%tr_adx(m)%p, &
364  cs%tr_ady(m)%p,cs%tr_dfx(m)%p,cs%tr_dfy(m)%p)
365 
366  call register_z_tracer(cs%tr(:,:,:,m), trim(name), longname, units, &
367  day, g, diag_to_z_csp)
368  enddo
369 
370 end subroutine initialize_dye_tracer
371 
372 subroutine dye_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, GV, CS, &
373  evap_CFL_limit, minimum_forcing_depth)
374  real, dimension(NIMEM_,NJMEM_,NKMEM_), intent(in) :: h_old, h_new, ea, eb
375  type(forcing), intent(in) :: fluxes
376  real, intent(in) :: dt !< The amount of time covered by this call, in s
377  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
378  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure
379  type(dye_tracer_cs), pointer :: CS
380  real, optional,intent(in) :: evap_CFL_limit
381  real, optional,intent(in) :: minimum_forcing_depth
382 ! This subroutine applies diapycnal diffusion and any other column
383 ! tracer physics or chemistry to the tracers from this file.
384 ! This is a simple example of a set of advected passive tracers.
385 
386 ! Arguments: h_old - Layer thickness before entrainment, in m or kg m-2.
387 ! (in) h_new - Layer thickness after entrainment, in m or kg m-2.
388 ! (in) ea - an array to which the amount of fluid entrained
389 ! from the layer above during this call will be
390 ! added, in m or kg m-2.
391 ! (in) eb - an array to which the amount of fluid entrained
392 ! from the layer below during this call will be
393 ! added, in m or kg m-2.
394 ! (in) fluxes - A structure containing pointers to any possible
395 ! forcing fields. Unused fields have NULL ptrs.
396 ! (in) dt - The amount of time covered by this call, in s.
397 ! (in) G - The ocean's grid structure.
398 ! (in) GV - The ocean's vertical grid structure.
399 ! (in) CS - The control structure returned by a previous call to
400 ! register_dye_tracer.
401 !
402 ! The arguments to this subroutine are redundant in that
403 ! h_new[k] = h_old[k] + ea[k] - eb[k-1] + eb[k] - ea[k+1]
404  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: h_work ! Used so that h can be modified
405  real :: sfc_val ! The surface value for the tracers.
406  real :: Isecs_per_year ! The number of seconds in a year.
407  real :: year ! The time in years.
408  integer :: secs, days ! Integer components of the time type.
409  integer :: i, j, k, is, ie, js, je, nz, m
410  real :: z_bot, z_center
411 
412  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
413 
414  if (.not.associated(cs)) return
415  if (cs%ntr < 1) return
416 
417  if (present(evap_cfl_limit) .and. present(minimum_forcing_depth)) then
418  do m=1,cs%ntr
419  do k=1,nz ;do j=js,je ; do i=is,ie
420  h_work(i,j,k) = h_old(i,j,k)
421  enddo ; enddo ; enddo;
422  call applytracerboundaryfluxesinout(g, gv, cs%tr(:,:,:,m) , dt, fluxes, h_work, &
423  evap_cfl_limit, minimum_forcing_depth)
424  call tracer_vertdiff(h_work, ea, eb, dt, cs%tr(:,:,:,m), g, gv)
425  enddo
426  else
427  do m=1,cs%ntr
428  call tracer_vertdiff(h_old, ea, eb, dt, cs%tr(:,:,:,m), g, gv)
429  enddo
430  endif
431 
432  do m=1,cs%ntr
433  do j=g%jsd,g%jed ; do i=g%isd,g%ied
434  ! A dye is set dependent on the center of the cell being inside the rectangular box.
435  if (cs%dye_source_minlon(m)<g%geoLonT(i,j) .and. &
436  cs%dye_source_maxlon(m)>=g%geoLonT(i,j) .and. &
437  cs%dye_source_minlat(m)<g%geoLatT(i,j) .and. &
438  cs%dye_source_maxlat(m)>=g%geoLatT(i,j) .and. &
439  g%mask2dT(i,j) > 0.0 ) then
440  z_bot = -g%bathyT(i,j)
441  do k=nz,1,-1
442  z_center = z_bot + 0.5*h_new(i,j,k)*gv%H_to_m
443  if ( z_center > -cs%dye_source_maxdepth(m) .and. &
444  z_center < -cs%dye_source_mindepth(m) ) then
445  cs%tr(i,j,k,m) = 1.0
446  endif
447  z_bot = z_bot + h_new(i,j,k)*gv%H_to_m
448  enddo
449  endif
450  enddo; enddo
451  enddo
452 
453 
454  do m=1,cs%ntr
455  if (cs%id_tracer(m)>0) &
456  call post_data(cs%id_tracer(m),cs%tr(:,:,:,m),cs%diag)
457  if (cs%id_tr_adx(m)>0) &
458  call post_data(cs%id_tr_adx(m),cs%tr_adx(m)%p(:,:,:),cs%diag)
459  if (cs%id_tr_ady(m)>0) &
460  call post_data(cs%id_tr_ady(m),cs%tr_ady(m)%p(:,:,:),cs%diag)
461  if (cs%id_tr_dfx(m)>0) &
462  call post_data(cs%id_tr_dfx(m),cs%tr_dfx(m)%p(:,:,:),cs%diag)
463  if (cs%id_tr_dfy(m)>0) &
464  call post_data(cs%id_tr_dfy(m),cs%tr_dfy(m)%p(:,:,:),cs%diag)
465  enddo
466 
467 end subroutine dye_tracer_column_physics
468 
469 function dye_stock(h, stocks, G, GV, CS, names, units, stock_index)
470  real, dimension(NIMEM_,NJMEM_,NKMEM_), intent(in) :: h !< Layer thicknesses, in H (usually m or kg m-2)
471  real, dimension(:), intent(out) :: stocks
472  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
473  type(verticalgrid_type), intent(in) :: GV !< The ocean's vertical grid structure
474  type(dye_tracer_cs), pointer :: CS
475  character(len=*), dimension(:), intent(out) :: names
476  character(len=*), dimension(:), intent(out) :: units
477  integer, optional, intent(in) :: stock_index
478  integer :: dye_stock
479 ! This function calculates the mass-weighted integral of all tracer stocks,
480 ! returning the number of stocks it has calculated. If the stock_index
481 ! is present, only the stock corresponding to that coded index is returned.
482 
483 ! Arguments: h - Layer thickness, in m or kg m-2.
484 ! (out) stocks - the mass-weighted integrated amount of each tracer,
485 ! in kg times concentration units.
486 ! (in) G - The ocean's grid structure.
487 ! (in) GV - The ocean's vertical grid structure.
488 ! (in) CS - The control structure returned by a previous call to
489 ! register_dye_tracer.
490 ! (out) names - the names of the stocks calculated.
491 ! (out) units - the units of the stocks calculated.
492 ! (in,opt) stock_index - the coded index of a specific stock being sought.
493 ! Return value: the number of stocks calculated here.
494 
495  integer :: i, j, k, is, ie, js, je, nz, m
496  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
497 
498  dye_stock = 0
499  if (.not.associated(cs)) return
500  if (cs%ntr < 1) return
501 
502  if (present(stock_index)) then ; if (stock_index > 0) then
503  ! Check whether this stock is available from this routine.
504 
505  ! No stocks from this routine are being checked yet. Return 0.
506  return
507  endif ; endif
508 
509  do m=1,cs%ntr
510  call query_vardesc(cs%tr_desc(m), name=names(m), units=units(m), caller="dye_stock")
511  units(m) = trim(units(m))//" kg"
512  stocks(m) = 0.0
513  do k=1,nz ; do j=js,je ; do i=is,ie
514  stocks(m) = stocks(m) + cs%tr(i,j,k,m) * &
515  (g%mask2dT(i,j) * g%areaT(i,j) * h(i,j,k))
516  enddo ; enddo ; enddo
517  stocks(m) = gv%H_to_kg_m2 * stocks(m)
518  enddo
519  dye_stock = cs%ntr
520 
521 end function dye_stock
522 
523 subroutine dye_tracer_surface_state(state, h, G, CS)
524  type(surface), intent(inout) :: state
525  real, dimension(NIMEM_,NJMEM_,NKMEM_), intent(in) :: h !< Layer thicknesses, in H (usually m or kg m-2)
526  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
527  type(dye_tracer_cs), pointer :: CS
528 ! This particular tracer package does not report anything back to the coupler.
529 ! The code that is here is just a rough guide for packages that would.
530 ! Arguments: state - A structure containing fields that describe the
531 ! surface state of the ocean.
532 ! (in) h - Layer thickness, in m or kg m-2.
533 ! (in) G - The ocean's grid structure.
534 ! (in) CS - The control structure returned by a previous call to
535 ! register_dye_tracer.
536  integer :: i, j, m, is, ie, js, je
537  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
538 
539  if (.not.associated(cs)) return
540 
541  if (cs%coupled_tracers) then
542  do m=1,cs%ntr
543  ! This call loads the surface vlues into the appropriate array in the
544  ! coupler-type structure.
545  call set_coupler_values(cs%tr(:,:,1,m), state%tr_fields, cs%ind_tr(m), &
546  ind_csurf, is, ie, js, je)
547  enddo
548  endif
549 
550 end subroutine dye_tracer_surface_state
551 
552 subroutine regional_dyes_end(CS)
553  type(dye_tracer_cs), pointer :: CS
554  integer :: m
555 
556  if (associated(cs)) then
557  if (associated(cs%tr)) deallocate(cs%tr)
558  do m=1,cs%ntr
559  if (associated(cs%tr_adx(m)%p)) deallocate(cs%tr_adx(m)%p)
560  if (associated(cs%tr_ady(m)%p)) deallocate(cs%tr_ady(m)%p)
561  if (associated(cs%tr_dfx(m)%p)) deallocate(cs%tr_dfx(m)%p)
562  if (associated(cs%tr_dfy(m)%p)) deallocate(cs%tr_dfy(m)%p)
563  enddo
564 
565  deallocate(cs)
566  endif
567 end subroutine regional_dyes_end
568 
569 end module regional_dyes
The following structure contains pointers to various fields which may be used describe the surface st...
logical function, public register_dye_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)
subroutine, public regional_dyes_end(CS)
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
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
integer function, public dye_stock(h, stocks, G, GV, CS, names, units, stock_index)
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 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 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.
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...
subroutine, public initialize_dye_tracer(restart, day, G, GV, h, diag, OBC, CS, sponge_CSp, diag_to_Z_CSp)
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.
subroutine, public dye_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, GV, CS, evap_CFL_limit, minimum_forcing_depth)
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)
subroutine, public dye_tracer_surface_state(state, h, G, CS)