MOM6
user_tracer_example Module Reference

Detailed Description

A sample tracer package that has striped initial conditions.

Original by Robert Hallberg, 2002

This file contains an example of the code that is needed to set up and use a set (in this case one) of dynamically passive tracers.

A single subroutine is called from within each file to register each of the tracers for reinitialization and advection and to register the subroutine that initializes the tracers and set up their output and the subroutine that does any tracer physics or chemistry along with diapycnal mixing (included here because some tracers may float or swim vertically or dye diapycnal processes).

Data Types

type  user_tracer_example_cs
 The control structure for the USER_tracer_example module. More...
 

Functions/Subroutines

logical function, public user_register_tracer_example (HI, GV, param_file, CS, tr_Reg, restart_CS)
 This subroutine is used to register tracer fields and subroutines to be used with MOM. More...
 
subroutine, public user_initialize_tracer (restart, day, G, GV, h, diag, OBC, CS, sponge_CSp)
 This subroutine initializes the NTR tracer fields in tr(:,:,:,:) and it sets up the tracer output. More...
 
subroutine, public tracer_column_physics (h_old, h_new, ea, eb, fluxes, dt, G, GV, CS)
 This subroutine applies diapycnal diffusion and any other column tracer physics or chemistry to the tracers from this file. This is a simple example of a set of advected passive tracers. The arguments to this subroutine are redundant in that h_new(k) = h_old(k) + ea(k) - eb(k-1) + eb(k) - ea(k+1) More...
 
integer function, public user_tracer_stock (h, stocks, G, GV, CS, names, units, stock_index)
 This function calculates the mass-weighted integral of all tracer stocks, returning the number of stocks it has calculated. If the stock_index is present, only the stock corresponding to that coded index is returned. More...
 
subroutine, public user_tracer_surface_state (state, h, G, CS)
 This subroutine extracts the surface fields from this tracer package that are to be shared with the atmosphere in coupled configurations. More...
 
subroutine, public user_tracer_example_end (CS)
 Clean up allocated memory at the end. More...
 

Variables

integer, parameter ntr = 1
 The number of tracers in this module.
 

Function/Subroutine Documentation

◆ tracer_column_physics()

subroutine, public user_tracer_example::tracer_column_physics ( real, dimension( g %isd: g %ied, g %jsd: g %jed, g %ke), intent(in)  h_old,
real, dimension( g %isd: g %ied, g %jsd: g %jed, g %ke), intent(in)  h_new,
real, dimension( g %isd: g %ied, g %jsd: g %jed, g %ke), intent(in)  ea,
real, dimension( g %isd: g %ied, g %jsd: g %jed, g %ke), intent(in)  eb,
type(forcing), intent(in)  fluxes,
real, intent(in)  dt,
type(ocean_grid_type), intent(in)  G,
type(verticalgrid_type), intent(in)  GV,
type(user_tracer_example_cs), pointer  CS 
)

This subroutine applies diapycnal diffusion and any other column tracer physics or chemistry to the tracers from this file. This is a simple example of a set of advected passive tracers. The arguments to this subroutine are redundant in that h_new(k) = h_old(k) + ea(k) - eb(k-1) + eb(k) - ea(k+1)

Parameters
[in]gThe ocean's grid structure
[in]gvThe ocean's vertical grid structure
[in]h_oldLayer thickness before entrainment [H ~> m or kg m-2].
[in]h_newLayer thickness after entrainment [H ~> m or kg m-2].
[in]eaan array to which the amount of fluid entrained
[in]eban array to which the amount of fluid entrained
[in]fluxesA structure containing pointers to thermodynamic and tracer forcing fields. Unused fields have NULL ptrs.
[in]dtThe amount of time covered by this call [s]
csThe control structure returned by a previous call to USER_register_tracer_example.

Definition at line 263 of file tracer_example.F90.

263  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
264  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure
265  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
266  intent(in) :: h_old !< Layer thickness before entrainment [H ~> m or kg m-2].
267  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
268  intent(in) :: h_new !< Layer thickness after entrainment [H ~> m or kg m-2].
269  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
270  intent(in) :: ea !< an array to which the amount of fluid entrained
271  !! from the layer above during this call will be
272  !! added [H ~> m or kg m-2].
273  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
274  intent(in) :: eb !< an array to which the amount of fluid entrained
275  !! from the layer below during this call will be
276  !! added [H ~> m or kg m-2].
277  type(forcing), intent(in) :: fluxes !< A structure containing pointers to thermodynamic
278  !! and tracer forcing fields. Unused fields have NULL ptrs.
279  real, intent(in) :: dt !< The amount of time covered by this call [s]
280  type(USER_tracer_example_CS), pointer :: CS !< The control structure returned by a previous
281  !! call to USER_register_tracer_example.
282 
283 ! Local variables
284  real :: hold0(SZI_(G)) ! The original topmost layer thickness,
285  ! with surface mass fluxes added back, m.
286  real :: b1(SZI_(G)) ! b1 and c1 are variables used by the
287  real :: c1(SZI_(G),SZK_(G)) ! tridiagonal solver.
288  real :: d1(SZI_(G)) ! d1=1-c1 is used by the tridiagonal solver.
289  real :: h_neglect ! A thickness that is so small it is usually lost
290  ! in roundoff and can be neglected [H ~> m or kg m-2].
291  real :: b_denom_1 ! The first term in the denominator of b1 [H ~> m or kg m-2].
292  integer :: i, j, k, is, ie, js, je, nz, m
293 
294 ! The following array (trdc) determines the behavior of the tracer
295 ! diapycnal advection. The first element is 1 if tracers are
296 ! passively advected. The second and third are the concentrations
297 ! to which downwelling and upwelling water are set, respectively.
298 ! For most (normal) tracers, the appropriate vales are {1,0,0}.
299 
300  real :: trdc(3)
301 ! Uncomment the following line to dye both upwelling and downwelling.
302 ! data trdc / 0.0,1.0,1.0 /
303 ! Uncomment the following line to dye downwelling.
304 ! data trdc / 0.0,1.0,0.0 /
305 ! Uncomment the following line to dye upwelling.
306 ! data trdc / 0.0,0.0,1.0 /
307 ! Uncomment the following line for tracer concentrations to be set
308 ! to zero in any diapycnal motions.
309 ! data trdc / 0.0,0.0,0.0 /
310 ! Uncomment the following line for most "physical" tracers, which
311 ! are advected diapycnally in the usual manner.
312  data trdc / 1.0,0.0,0.0 /
313  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
314 
315  if (.not.associated(cs)) return
316  h_neglect = gv%H_subroundoff
317 
318  do j=js,je
319  do i=is,ie
320 ! The following line is appropriate for quantities like salinity
321 ! that are left behind by evaporation, and any surface fluxes would
322 ! be explicitly included in the flux structure.
323  hold0(i) = h_old(i,j,1)
324 ! The following line is appropriate for quantities like temperature
325 ! that can be assumed to have the same concentration in evaporation
326 ! as they had in the water. The explicit surface fluxes here would
327 ! reflect differences in concentration from the ambient water, not
328 ! the absolute fluxes.
329  ! hold0(i) = h_old(i,j,1) + ea(i,j,1)
330  b_denom_1 = h_old(i,j,1) + ea(i,j,1) + h_neglect
331  b1(i) = 1.0 / (b_denom_1 + eb(i,j,1))
332 ! d1(i) = b_denom_1 * b1(i)
333  d1(i) = trdc(1) * (b_denom_1 * b1(i)) + (1.0 - trdc(1))
334  do m=1,ntr
335  cs%tr(i,j,1,m) = b1(i)*(hold0(i)*cs%tr(i,j,1,m) + trdc(3)*eb(i,j,1))
336  ! Add any surface tracer fluxes to the preceding line.
337  enddo
338  enddo
339  do k=2,nz ; do i=is,ie
340  c1(i,k) = trdc(1) * eb(i,j,k-1) * b1(i)
341  b_denom_1 = h_old(i,j,k) + d1(i)*ea(i,j,k) + h_neglect
342  b1(i) = 1.0 / (b_denom_1 + eb(i,j,k))
343  d1(i) = trdc(1) * (b_denom_1 * b1(i)) + (1.0 - trdc(1))
344  do m=1,ntr
345  cs%tr(i,j,k,m) = b1(i) * (h_old(i,j,k)*cs%tr(i,j,k,m) + &
346  ea(i,j,k)*(trdc(1)*cs%tr(i,j,k-1,m)+trdc(2)) + &
347  eb(i,j,k)*trdc(3))
348  enddo
349  enddo ; enddo
350  do m=1,ntr ; do k=nz-1,1,-1 ; do i=is,ie
351  cs%tr(i,j,k,m) = cs%tr(i,j,k,m) + c1(i,k+1)*cs%tr(i,j,k+1,m)
352  enddo ; enddo ; enddo
353  enddo
354 

◆ user_initialize_tracer()

subroutine, public user_tracer_example::user_initialize_tracer ( logical, intent(in)  restart,
type(time_type), intent(in), target  day,
type(ocean_grid_type), intent(in)  G,
type(verticalgrid_type), intent(in)  GV,
real, dimension(szi_(g),szj_(g),szk_(g)), intent(in)  h,
type(diag_ctrl), intent(in), target  diag,
type(ocean_obc_type), pointer  OBC,
type(user_tracer_example_cs), pointer  CS,
type(sponge_cs), pointer  sponge_CSp 
)

This subroutine initializes the NTR tracer fields in tr(:,:,:,:) and it sets up the tracer output.

Parameters
[in]restart.true. if the fields have already been read from a restart file.
[in]dayTime of the start of the run.
[in]gThe ocean's grid structure
[in]gvThe ocean's vertical grid structure
[in]hLayer thicknesses [H ~> m or kg m-2]
[in]diagA structure that is used to regulate diagnostic output.
obcThis open boundary condition type specifies whether, where, and what open boundary conditions are used.
csThe control structure returned by a previous call to USER_register_tracer_example.
sponge_cspA pointer to the control structure for the sponges, if they are in use.

Definition at line 140 of file tracer_example.F90.

140  logical, intent(in) :: restart !< .true. if the fields have already
141  !! been read from a restart file.
142  type(time_type), target, intent(in) :: day !< Time of the start of the run.
143  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
144  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure
145  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
146  intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
147  type(diag_ctrl), target, intent(in) :: diag !< A structure that is used to regulate
148  !! diagnostic output.
149  type(ocean_OBC_type), pointer :: OBC !< This open boundary condition type specifies
150  !! whether, where, and what open boundary
151  !! conditions are used.
152  type(USER_tracer_example_CS), pointer :: CS !< The control structure returned by a previous
153  !! call to USER_register_tracer_example.
154  type(sponge_CS), pointer :: sponge_CSp !< A pointer to the control structure
155  !! for the sponges, if they are in use.
156 
157 ! Local variables
158  real, allocatable :: temp(:,:,:)
159  character(len=32) :: name ! A variable's name in a NetCDF file.
160  character(len=72) :: longname ! The long name of that variable.
161  character(len=48) :: units ! The dimensions of the variable.
162  character(len=48) :: flux_units ! The units for tracer fluxes, usually
163  ! kg(tracer) kg(water)-1 m3 s-1 or kg(tracer) s-1.
164  real, pointer :: tr_ptr(:,:,:) => null()
165  real :: PI ! 3.1415926... calculated as 4*atan(1)
166  real :: tr_y ! Initial zonally uniform tracer concentrations.
167  real :: dist2 ! The distance squared from a line [m2].
168  integer :: i, j, k, is, ie, js, je, isd, ied, jsd, jed, nz, m
169  integer :: IsdB, IedB, JsdB, JedB, lntr
170 
171  if (.not.associated(cs)) return
172  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
173  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
174  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
175 
176  lntr = ntr ! Avoids compile-time warning when NTR<2
177  cs%Time => day
178  cs%diag => diag
179 
180  if (.not.restart) then
181  if (len_trim(cs%tracer_IC_file) >= 1) then
182 ! Read the tracer concentrations from a netcdf file.
183  if (.not.file_exists(cs%tracer_IC_file, g%Domain)) &
184  call mom_error(fatal, "USER_initialize_tracer: Unable to open "// &
185  cs%tracer_IC_file)
186  do m=1,ntr
187  call query_vardesc(cs%tr_desc(m), name, caller="USER_initialize_tracer")
188  call mom_read_data(cs%tracer_IC_file, trim(name), cs%tr(:,:,:,m), g%Domain)
189  enddo
190  else
191  do m=1,ntr
192  do k=1,nz ; do j=js,je ; do i=is,ie
193  cs%tr(i,j,k,m) = 1.0e-20 ! This could just as well be 0.
194  enddo ; enddo ; enddo
195  enddo
196 
197 ! This sets a stripe of tracer across the basin.
198  pi = 4.0*atan(1.0)
199  do j=js,je
200  dist2 = (g%Rad_Earth * pi / 180.0)**2 * &
201  (g%geoLatT(i,j) - 40.0) * (g%geoLatT(i,j) - 40.0)
202  tr_y = 0.5*exp(-dist2/(1.0e5*1.0e5))
203 
204  do k=1,nz ; do i=is,ie
205 ! This adds the stripes of tracer to every layer.
206  cs%tr(i,j,k,1) = cs%tr(i,j,k,1) + tr_y
207  enddo ; enddo
208  enddo
209  endif
210  endif ! restart
211 
212  if ( cs%use_sponge ) then
213 ! If sponges are used, this example damps tracers in sponges in the
214 ! northern half of the domain to 1 and tracers in the southern half
215 ! to 0. For any tracers that are not damped in the sponge, the call
216 ! to set_up_sponge_field can simply be omitted.
217  if (.not.associated(sponge_csp)) &
218  call mom_error(fatal, "USER_initialize_tracer: "// &
219  "The pointer to sponge_CSp must be associated if SPONGE is defined.")
220 
221  allocate(temp(g%isd:g%ied,g%jsd:g%jed,nz))
222  do k=1,nz ; do j=js,je ; do i=is,ie
223  if (g%geoLatT(i,j) > 700.0 .and. (k > nz/2)) then
224  temp(i,j,k) = 1.0
225  else
226  temp(i,j,k) = 0.0
227  endif
228  enddo ; enddo ; enddo
229 
230 ! do m=1,NTR
231  do m=1,1
232  ! This is needed to force the compiler not to do a copy in the sponge
233  ! calls. Curses on the designers and implementers of Fortran90.
234  tr_ptr => cs%tr(:,:,:,m)
235  call set_up_sponge_field(temp, tr_ptr, g, nz, sponge_csp)
236  enddo
237  deallocate(temp)
238  endif
239 
240  if (associated(obc)) then
241  call query_vardesc(cs%tr_desc(1), name, caller="USER_initialize_tracer")
242  if (obc%specified_v_BCs_exist_globally) then
243  ! Steal from updated DOME in the fullness of time.
244  else
245  ! Steal from updated DOME in the fullness of time.
246  endif
247  ! All tracers but the first have 0 concentration in their inflows. As this
248  ! is the default value, the following calls are unnecessary.
249  do m=2,lntr
250  call query_vardesc(cs%tr_desc(m), name, caller="USER_initialize_tracer")
251  ! Steal from updated DOME in the fullness of time.
252  enddo
253  endif
254 

◆ user_register_tracer_example()

logical function, public user_tracer_example::user_register_tracer_example ( type(hor_index_type), intent(in)  HI,
type(verticalgrid_type), intent(in)  GV,
type(param_file_type), intent(in)  param_file,
type(user_tracer_example_cs), pointer  CS,
type(tracer_registry_type), pointer  tr_Reg,
type(mom_restart_cs), pointer  restart_CS 
)

This subroutine is used to register tracer fields and subroutines to be used with MOM.

Parameters
[in]hiA horizontal index type structure
[in]gvThe ocean's vertical grid structure
[in]param_fileA structure to parse for run-time parameters
csA pointer that is set to point to the control structure for this module
tr_regA pointer that is set to point to the control structure for the tracer advection and diffusion module
restart_csA pointer to the restart control structure

Definition at line 56 of file tracer_example.F90.

56  type(hor_index_type), intent(in) :: HI !< A horizontal index type structure
57  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure
58  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
59  type(USER_tracer_example_CS), pointer :: CS !< A pointer that is set to point to the control
60  !! structure for this module
61  type(tracer_registry_type), pointer :: tr_Reg !< A pointer that is set to point to the control
62  !! structure for the tracer advection and
63  !! diffusion module
64  type(MOM_restart_CS), pointer :: restart_CS !< A pointer to the restart control structure
65 
66 ! Local variables
67  character(len=80) :: name, longname
68 ! This include declares and sets the variable "version".
69 #include "version_variable.h"
70  character(len=40) :: mdl = "tracer_example" ! This module's name.
71  character(len=200) :: inputdir
72  character(len=48) :: flux_units ! The units for tracer fluxes, usually
73  ! kg(tracer) kg(water)-1 m3 s-1 or kg(tracer) s-1.
74  real, pointer :: tr_ptr(:,:,:) => null()
75  logical :: USER_register_tracer_example
76  integer :: isd, ied, jsd, jed, nz, m
77  isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed ; nz = gv%ke
78 
79  if (associated(cs)) then
80  call mom_error(warning, "USER_register_tracer_example called with an "// &
81  "associated control structure.")
82  return
83  endif
84  allocate(cs)
85 
86  ! Read all relevant parameters and write them to the model log.
87  call log_version(param_file, mdl, version, "")
88  call get_param(param_file, mdl, "TRACER_EXAMPLE_IC_FILE", cs%tracer_IC_file, &
89  "The name of a file from which to read the initial "//&
90  "conditions for the DOME tracers, or blank to initialize "//&
91  "them internally.", default=" ")
92  if (len_trim(cs%tracer_IC_file) >= 1) then
93  call get_param(param_file, mdl, "INPUTDIR", inputdir, default=".")
94  cs%tracer_IC_file = trim(slasher(inputdir))//trim(cs%tracer_IC_file)
95  call log_param(param_file, mdl, "INPUTDIR/TRACER_EXAMPLE_IC_FILE", &
96  cs%tracer_IC_file)
97  endif
98  call get_param(param_file, mdl, "SPONGE", cs%use_sponge, &
99  "If true, sponges may be applied anywhere in the domain. "//&
100  "The exact location and properties of those sponges are "//&
101  "specified from MOM_initialization.F90.", default=.false.)
102 
103  allocate(cs%tr(isd:ied,jsd:jed,nz,ntr)) ; cs%tr(:,:,:,:) = 0.0
104 
105  do m=1,ntr
106  if (m < 10) then ; write(name,'("tr",I1.1)') m
107  else ; write(name,'("tr",I2.2)') m ; endif
108  write(longname,'("Concentration of Tracer ",I2.2)') m
109  cs%tr_desc(m) = var_desc(name, units="kg kg-1", longname=longname, caller=mdl)
110 
111  ! This needs to be changed if the units of tracer are changed above.
112  if (gv%Boussinesq) then ; flux_units = "kg kg-1 m3 s-1"
113  else ; flux_units = "kg s-1" ; endif
114 
115  ! This is needed to force the compiler not to do a copy in the registration
116  ! calls. Curses on the designers and implementers of Fortran90.
117  tr_ptr => cs%tr(:,:,:,m)
118  ! Register the tracer for horizontal advection, diffusion, and restarts.
119  call register_tracer(tr_ptr, tr_reg, param_file, hi, gv, &
120  name=name, longname=longname, units="kg kg-1", &
121  registry_diags=.true., flux_units=flux_units, &
122  restart_cs=restart_cs)
123 
124  ! Set coupled_tracers to be true (hard-coded above) to provide the surface
125  ! values to the coupler (if any). This is meta-code and its arguments will
126  ! currently (deliberately) give fatal errors if it is used.
127  if (cs%coupled_tracers) &
128  cs%ind_tr(m) = aof_set_coupler_flux(trim(name)//'_flux', &
129  flux_type=' ', implementation=' ', caller="USER_register_tracer_example")
130  enddo
131 
132  cs%tr_Reg => tr_reg
133  user_register_tracer_example = .true.

◆ user_tracer_example_end()

subroutine, public user_tracer_example::user_tracer_example_end ( type(user_tracer_example_cs), pointer  CS)

Clean up allocated memory at the end.

Parameters
csThe control structure returned by a previous call to register_USER_tracer.

Definition at line 438 of file tracer_example.F90.

438  type(USER_tracer_example_CS), pointer :: CS !< The control structure returned by a previous
439  !! call to register_USER_tracer.
440  integer :: m
441 
442  if (associated(cs)) then
443  if (associated(cs%tr)) deallocate(cs%tr)
444  deallocate(cs)
445  endif

◆ user_tracer_stock()

integer function, public user_tracer_example::user_tracer_stock ( real, dimension( g %isd: g %ied, g %jsd: g %jed, g %ke), intent(in)  h,
real, dimension(:), intent(out)  stocks,
type(ocean_grid_type), intent(in)  G,
type(verticalgrid_type), intent(in)  GV,
type(user_tracer_example_cs), pointer  CS,
character(len=*), dimension(:), intent(out)  names,
character(len=*), dimension(:), intent(out)  units,
integer, intent(in), optional  stock_index 
)

This function calculates the mass-weighted integral of all tracer stocks, returning the number of stocks it has calculated. If the stock_index is present, only the stock corresponding to that coded index is returned.

Parameters
[in]gThe ocean's grid structure
[in]gvThe ocean's vertical grid structure
[in]hLayer thicknesses [H ~> m or kg m-2]
[out]stocksthe mass-weighted integrated amount of each tracer, in kg times concentration units [kg conc].
csThe control structure returned by a previous call to register_USER_tracer.
[out]namesThe names of the stocks calculated.
[out]unitsThe units of the stocks calculated.
[in]stock_indexThe coded index of a specific stock being sought.
Returns
Return value: the number of stocks calculated here.

Definition at line 361 of file tracer_example.F90.

361  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
362  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure
363  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
364  intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
365  real, dimension(:), intent(out) :: stocks !< the mass-weighted integrated amount of each
366  !! tracer, in kg times concentration units [kg conc].
367  type(USER_tracer_example_CS), pointer :: CS !< The control structure returned by a
368  !! previous call to register_USER_tracer.
369  character(len=*), dimension(:), intent(out) :: names !< The names of the stocks calculated.
370  character(len=*), dimension(:), intent(out) :: units !< The units of the stocks calculated.
371  integer, optional, intent(in) :: stock_index !< The coded index of a specific stock
372  !! being sought.
373  integer :: USER_tracer_stock !< Return value: the number of
374  !! stocks calculated here.
375 
376 ! Local variables
377  integer :: i, j, k, is, ie, js, je, nz, m
378  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
379 
380  user_tracer_stock = 0
381  if (.not.associated(cs)) return
382 
383  if (present(stock_index)) then ; if (stock_index > 0) then
384  ! Check whether this stock is available from this routine.
385 
386  ! No stocks from this routine are being checked yet. Return 0.
387  return
388  endif ; endif
389 
390  do m=1,ntr
391  call query_vardesc(cs%tr_desc(m), name=names(m), units=units(m), caller="USER_tracer_stock")
392  units(m) = trim(units(m))//" kg"
393  stocks(m) = 0.0
394  do k=1,nz ; do j=js,je ; do i=is,ie
395  stocks(m) = stocks(m) + cs%tr(i,j,k,m) * &
396  (g%mask2dT(i,j) * g%areaT(i,j) * h(i,j,k))
397  enddo ; enddo ; enddo
398  stocks(m) = gv%H_to_kg_m2 * stocks(m)
399  enddo
400  user_tracer_stock = ntr
401 

◆ user_tracer_surface_state()

subroutine, public user_tracer_example::user_tracer_surface_state ( type(surface), intent(inout)  state,
real, dimension(szi_(g),szj_(g),szk_(g)), intent(in)  h,
type(ocean_grid_type), intent(in)  G,
type(user_tracer_example_cs), pointer  CS 
)

This subroutine extracts the surface fields from this tracer package that are to be shared with the atmosphere in coupled configurations.

Parameters
[in]gThe ocean's grid structure
[in,out]stateA structure containing fields that describe the surface state of the ocean.
[in]hLayer thicknesses [H ~> m or kg m-2]
csThe control structure returned by a previous call to register_USER_tracer.

Definition at line 407 of file tracer_example.F90.

407  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
408  type(surface), intent(inout) :: state !< A structure containing fields that
409  !! describe the surface state of the ocean.
410  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
411  intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
412  type(USER_tracer_example_CS), pointer :: CS !< The control structure returned by a previous
413  !! call to register_USER_tracer.
414 
415  ! This particular tracer package does not report anything back to the coupler.
416  ! The code that is here is just a rough guide for packages that would.
417 
418  integer :: m, is, ie, js, je, isd, ied, jsd, jed
419  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
420  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
421 
422  if (.not.associated(cs)) return
423 
424  if (cs%coupled_tracers) then
425  do m=1,ntr
426  ! This call loads the surface values into the appropriate array in the
427  ! coupler-type structure.
428  call coupler_type_set_data(cs%tr(:,:,1,m), cs%ind_tr(m), ind_csurf, &
429  state%tr_fields, idim=(/isd, is, ie, ied/), &
430  jdim=(/jsd, js, je, jed/) )
431  enddo
432  endif
433