MOM6
oil_tracer Module Reference

Detailed Description

A tracer package to mimic dissolved oil.

By Alistair Adcroft and Robert Hallberg, 2010 *

In the midst of the Deepwater Horizon oil spill, it became evident that models were needed to predict the long-term fate of dissolved oil in the open ocean. This tracer packages mimics the transport, dilution and decay of dissolved oil plumes in the ocean.

This tracer package was central to the simulations used by Adcroft et al., GRL 2010, to prove that the Deepwater Horizon spill was an important regional event, with implications for dissolved oxygen levels in the Gulf of Mexico, but not one that would directly impact the East Coast of the U.S.

Data Types

type  oil_tracer_cs
 The control structure for the oil tracer package. More...
 

Functions/Subroutines

logical function, public register_oil_tracer (HI, GV, US, param_file, CS, tr_Reg, restart_CS)
 Register oil tracer fields and subroutines to be used with MOM. More...
 
subroutine, public initialize_oil_tracer (restart, day, G, GV, US, h, diag, OBC, CS, sponge_CSp)
 Initialize the oil tracers and set up tracer output. More...
 
subroutine, public oil_tracer_column_physics (h_old, h_new, ea, eb, fluxes, dt, G, GV, US, CS, tv, evap_CFL_limit, minimum_forcing_depth)
 Apply sources, sinks, diapycnal mixing and rising motions to the oil tracers. More...
 
integer function, public oil_stock (h, stocks, G, GV, CS, names, units, stock_index)
 Calculate the mass-weighted integral of the oil 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 oil_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. This particular tracer package does not report anything back to the coupler. More...
 
subroutine, public oil_tracer_end (CS)
 Deallocate memory associated with this tracer package. More...
 

Variables

integer, parameter ntr_max = 20
 the maximum number of tracers in this module. More...
 

Function/Subroutine Documentation

◆ initialize_oil_tracer()

subroutine, public oil_tracer::initialize_oil_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,
type(unit_scale_type), intent(in)  US,
real, dimension( g %isd: g %ied, g %jsd: g %jed, g %ke), intent(in)  h,
type(diag_ctrl), intent(in), target  diag,
type(ocean_obc_type), pointer  OBC,
type(oil_tracer_cs), pointer  CS,
type(sponge_cs), pointer  sponge_CSp 
)

Initialize the oil tracers and set up 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]usA dimensional unit scaling type
[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 register_oil_tracer.
sponge_cspPointer to the control structure for the sponges.

Definition at line 206 of file oil_tracer.F90.

206  logical, intent(in) :: restart !< .true. if the fields have already
207  !! been read from a restart file.
208  type(time_type), target, intent(in) :: day !< Time of the start of the run.
209  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
210  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure
211  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
212  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
213  intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
214  type(diag_ctrl), target, intent(in) :: diag !< A structure that is used to regulate
215  !! diagnostic output.
216  type(ocean_OBC_type), pointer :: OBC !< This open boundary condition type specifies
217  !! whether, where, and what open boundary
218  !! conditions are used.
219  type(oil_tracer_CS), pointer :: CS !< The control structure returned by a previous
220  !! call to register_oil_tracer.
221  type(sponge_CS), pointer :: sponge_CSp !< Pointer to the control structure for the sponges.
222 
223  ! Local variables
224  character(len=16) :: name ! A variable's name in a NetCDF file.
225  character(len=72) :: longname ! The long name of that variable.
226  character(len=48) :: units ! The dimensions of the variable.
227  character(len=48) :: flux_units ! The units for age tracer fluxes, either
228  ! years m3 s-1 or years kg s-1.
229  logical :: OK
230  integer :: i, j, k, is, ie, js, je, isd, ied, jsd, jed, nz, m
231  integer :: IsdB, IedB, JsdB, JedB
232 
233  if (.not.associated(cs)) return
234  if (cs%ntr < 1) return
235  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
236  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
237  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
238 
239  ! Establish location of source
240  do j=g%jsdB+1,g%jed ; do i=g%isdB+1,g%ied
241  ! This test for i,j index is specific to a lat/lon (non-rotated grid).
242  ! and needs to be generalized to work properly on the tri-polar grid.
243  if (cs%oil_source_longitude<g%geoLonBu(i,j) .and. &
244  cs%oil_source_longitude>=g%geoLonBu(i-1,j) .and. &
245  cs%oil_source_latitude<g%geoLatBu(i,j) .and. &
246  cs%oil_source_latitude>=g%geoLatBu(i,j-1) ) then
247  cs%oil_source_i=i
248  cs%oil_source_j=j
249  endif
250  enddo ; enddo
251 
252  cs%Time => day
253  cs%diag => diag
254 
255  do m=1,cs%ntr
256  call query_vardesc(cs%tr_desc(m), name=name, caller="initialize_oil_tracer")
257  if ((.not.restart) .or. (cs%oil_may_reinit .and. .not. &
258  query_initialized(cs%tr(:,:,:,m), name, cs%restart_CSp))) then
259 
260  if (len_trim(cs%IC_file) > 0) then
261  ! Read the tracer concentrations from a netcdf file.
262  if (.not.file_exists(cs%IC_file, g%Domain)) &
263  call mom_error(fatal, "initialize_oil_tracer: "// &
264  "Unable to open "//cs%IC_file)
265 
266  if (cs%Z_IC_file) then
267  ok = tracer_z_init(cs%tr(:,:,:,m), h, cs%IC_file, name, &
268  g, us, -1e34, 0.0) ! CS%land_val(m))
269  if (.not.ok) then
270  ok = tracer_z_init(cs%tr(:,:,:,m), h, cs%IC_file, &
271  trim(name), g, us, -1e34, 0.0) ! CS%land_val(m))
272  if (.not.ok) call mom_error(fatal,"initialize_oil_tracer: "//&
273  "Unable to read "//trim(name)//" from "//&
274  trim(cs%IC_file)//".")
275  endif
276  else
277  call mom_read_data(cs%IC_file, trim(name), cs%tr(:,:,:,m), g%Domain)
278  endif
279  else
280  do k=1,nz ; do j=js,je ; do i=is,ie
281  if (g%mask2dT(i,j) < 0.5) then
282  cs%tr(i,j,k,m) = cs%land_val(m)
283  else
284  cs%tr(i,j,k,m) = cs%IC_val(m)
285  endif
286  enddo ; enddo ; enddo
287  endif
288 
289  endif ! restart
290  enddo ! Tracer loop
291 
292  if (associated(obc)) then
293  ! Put something here...
294  endif
295 

References mom_error_handler::mom_error(), mom_io::query_vardesc(), and mom_tracer_z_init::tracer_z_init().

Here is the call graph for this function:

◆ oil_stock()

integer function, public oil_tracer::oil_stock ( real, dimension(szi_(g),szj_(g),szk_(g)), intent(in)  h,
real, dimension(:), intent(out)  stocks,
type(ocean_grid_type), intent(in)  G,
type(verticalgrid_type), intent(in)  GV,
type(oil_tracer_cs), pointer  CS,
character(len=*), dimension(:), intent(out)  names,
character(len=*), dimension(:), intent(out)  units,
integer, intent(in), optional  stock_index 
)

Calculate the mass-weighted integral of the oil 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_oil_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
The number of stocks calculated here.

Definition at line 408 of file oil_tracer.F90.

408  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
409  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure
410  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
411  real, dimension(:), intent(out) :: stocks !< the mass-weighted integrated amount of each
412  !! tracer, in kg times concentration units [kg conc].
413  type(oil_tracer_CS), pointer :: CS !< The control structure returned by a previous
414  !! call to register_oil_tracer.
415  character(len=*), dimension(:), intent(out) :: names !< the names of the stocks calculated.
416  character(len=*), dimension(:), intent(out) :: units !< the units of the stocks calculated.
417  integer, optional, intent(in) :: stock_index !< the coded index of a specific stock
418  !! being sought.
419  integer :: oil_stock !< The number of stocks calculated here.
420 
421 ! This function calculates the mass-weighted integral of all tracer stocks,
422 ! returning the number of stocks it has calculated. If the stock_index
423 ! is present, only the stock corresponding to that coded index is returned.
424 
425  ! Local variables
426  integer :: i, j, k, is, ie, js, je, nz, m
427  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
428 
429  oil_stock = 0
430  if (.not.associated(cs)) return
431  if (cs%ntr < 1) return
432 
433  if (present(stock_index)) then ; if (stock_index > 0) then
434  ! Check whether this stock is available from this routine.
435 
436  ! No stocks from this routine are being checked yet. Return 0.
437  return
438  endif ; endif
439 
440  do m=1,cs%ntr
441  call query_vardesc(cs%tr_desc(m), name=names(m), units=units(m), caller="oil_stock")
442  units(m) = trim(units(m))//" kg"
443  stocks(m) = 0.0
444  do k=1,nz ; do j=js,je ; do i=is,ie
445  stocks(m) = stocks(m) + cs%tr(i,j,k,m) * &
446  (g%mask2dT(i,j) * g%US%L_to_m**2*g%areaT(i,j) * h(i,j,k))
447  enddo ; enddo ; enddo
448  stocks(m) = gv%H_to_kg_m2 * stocks(m)
449  enddo
450  oil_stock = cs%ntr
451 

References mom_io::query_vardesc().

Referenced by mom_tracer_flow_control::call_tracer_stocks().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ oil_tracer_column_physics()

subroutine, public oil_tracer::oil_tracer_column_physics ( real, dimension(szi_(g),szj_(g),szk_(g)), intent(in)  h_old,
real, dimension(szi_(g),szj_(g),szk_(g)), intent(in)  h_new,
real, dimension(szi_(g),szj_(g),szk_(g)), intent(in)  ea,
real, dimension(szi_(g),szj_(g),szk_(g)), 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(unit_scale_type), intent(in)  US,
type(oil_tracer_cs), pointer  CS,
type(thermo_var_ptrs), intent(in)  tv,
real, intent(in), optional  evap_CFL_limit,
real, intent(in), optional  minimum_forcing_depth 
)

Apply sources, sinks, diapycnal mixing and rising motions to the oil tracers.

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 [T ~> s]
[in]usA dimensional unit scaling type
csThe control structure returned by a previous call to register_oil_tracer.
[in]tvA structure pointing to various thermodynamic variables
[in]evap_cfl_limitLimit on the fraction of the water that can be fluxed out of the top layer in a timestep [nondim]
[in]minimum_forcing_depthThe smallest depth over which fluxes can be applied [H ~> m or kg m-2]

Definition at line 301 of file oil_tracer.F90.

301  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure
302  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure
303  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
304  intent(in) :: h_old !< Layer thickness before entrainment [H ~> m or kg m-2].
305  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
306  intent(in) :: h_new !< Layer thickness after entrainment [H ~> m or kg m-2].
307  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
308  intent(in) :: ea !< an array to which the amount of fluid entrained
309  !! from the layer above during this call will be
310  !! added [H ~> m or kg m-2].
311  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
312  intent(in) :: eb !< an array to which the amount of fluid entrained
313  !! from the layer below during this call will be
314  !! added [H ~> m or kg m-2].
315  type(forcing), intent(in) :: fluxes !< A structure containing pointers to thermodynamic
316  !! and tracer forcing fields. Unused fields have NULL ptrs.
317  real, intent(in) :: dt !< The amount of time covered by this call [T ~> s]
318  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
319  type(oil_tracer_CS), pointer :: CS !< The control structure returned by a previous
320  !! call to register_oil_tracer.
321  type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various thermodynamic variables
322  real, optional, intent(in) :: evap_CFL_limit !< Limit on the fraction of the water that can
323  !! be fluxed out of the top layer in a timestep [nondim]
324  real, optional, intent(in) :: minimum_forcing_depth !< The smallest depth over which
325  !! fluxes can be applied [H ~> m or kg m-2]
326 ! This subroutine applies diapycnal diffusion and any other column
327 ! tracer physics or chemistry to the tracers from this file.
328 ! This is a simple example of a set of advected passive tracers.
329 
330 ! The arguments to this subroutine are redundant in that
331 ! h_new(k) = h_old(k) + ea(k) - eb(k-1) + eb(k) - ea(k+1)
332 
333  ! Local variables
334  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: h_work ! Used so that h can be modified
335  real :: Isecs_per_year = 1.0 / (365.0*86400.0)
336  real :: year, h_total, ldecay
337  integer :: i, j, k, is, ie, js, je, nz, m, k_max
338  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
339 
340  if (.not.associated(cs)) return
341  if (cs%ntr < 1) return
342 
343  if (present(evap_cfl_limit) .and. present(minimum_forcing_depth)) then
344  do m=1,cs%ntr
345  do k=1,nz ;do j=js,je ; do i=is,ie
346  h_work(i,j,k) = h_old(i,j,k)
347  enddo ; enddo ; enddo
348  call applytracerboundaryfluxesinout(g, gv, cs%tr(:,:,:,m), dt, fluxes, h_work, &
349  evap_cfl_limit, minimum_forcing_depth)
350  call tracer_vertdiff(h_work, ea, eb, dt, cs%tr(:,:,:,m), g, gv)
351  enddo
352  else
353  do m=1,cs%ntr
354  call tracer_vertdiff(h_old, ea, eb, dt, cs%tr(:,:,:,m), g, gv)
355  enddo
356  endif
357 
358  year = time_type_to_real(cs%Time) * isecs_per_year
359 
360  ! Decay tracer (limit decay rate to 1/dt - just in case)
361  do m=2,cs%ntr
362  do k=1,nz ; do j=js,je ; do i=is,ie
363  !CS%tr(i,j,k,m) = CS%tr(i,j,k,m) - dt*CS%oil_decay_rate(m)*CS%tr(i,j,k,m) ! Simple
364  !CS%tr(i,j,k,m) = CS%tr(i,j,k,m) - min(dt*CS%oil_decay_rate(m),1.)*CS%tr(i,j,k,m) ! Safer
365  if (cs%oil_decay_rate(m)>0.) then
366  cs%tr(i,j,k,m) = g%mask2dT(i,j)*max(1. - dt*cs%oil_decay_rate(m),0.)*cs%tr(i,j,k,m) ! Safest
367  elseif (cs%oil_decay_rate(m)<0.) then
368  ldecay = 12.*(3.0**(-(tv%T(i,j,k)-20.)/10.)) ! Timescale [days]
369  ldecay = 1. / (86400.*us%s_to_T * ldecay) ! Rate [T-1 ~> s-1]
370  cs%tr(i,j,k,m) = g%mask2dT(i,j)*max(1. - dt*ldecay,0.)*cs%tr(i,j,k,m)
371  endif
372  enddo ; enddo ; enddo
373  enddo
374 
375  ! Add oil at the source location
376  if (year>=cs%oil_start_year .and. year<=cs%oil_end_year .and. &
377  cs%oil_source_i>-999 .and. cs%oil_source_j>-999) then
378  i=cs%oil_source_i ; j=cs%oil_source_j
379  k_max=nz ; h_total=0.
380  do k=nz, 2, -1
381  h_total = h_total + h_new(i,j,k)
382  if (h_total<10.) k_max=k-1 ! Find bottom most interface that is 10 m above bottom
383  enddo
384  do m=1,cs%ntr
385  k=cs%oil_source_k(m)
386  if (k>0) then
387  k=min(k,k_max) ! Only insert k or first layer with interface 10 m above bottom
388  cs%tr(i,j,k,m) = cs%tr(i,j,k,m) + cs%oil_source_rate*dt / &
389  ((h_new(i,j,k)+gv%H_subroundoff) * g%US%L_to_m**2*g%areaT(i,j) )
390  elseif (k<0) then
391  h_total=gv%H_subroundoff
392  do k=1, nz
393  h_total = h_total + h_new(i,j,k)
394  enddo
395  do k=1, nz
396  cs%tr(i,j,k,m) = cs%tr(i,j,k,m) + cs%oil_source_rate*dt/(h_total &
397  * g%US%L_to_m**2*g%areaT(i,j) )
398  enddo
399  endif
400  enddo
401  endif
402 

References mom_tracer_diabatic::applytracerboundaryfluxesinout(), and mom_tracer_diabatic::tracer_vertdiff().

Here is the call graph for this function:

◆ oil_tracer_end()

subroutine, public oil_tracer::oil_tracer_end ( type(oil_tracer_cs), pointer  CS)

Deallocate memory associated with this tracer package.

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

Definition at line 489 of file oil_tracer.F90.

489  type(oil_tracer_CS), pointer :: CS !< The control structure returned by a previous
490  !! call to register_oil_tracer.
491  integer :: m
492 
493  if (associated(cs)) then
494  if (associated(cs%tr)) deallocate(cs%tr)
495  deallocate(cs)
496  endif

◆ oil_tracer_surface_state()

subroutine, public oil_tracer::oil_tracer_surface_state ( type(surface), intent(inout)  state,
real, dimension( g %isd: g %ied, g %jsd: g %jed, g %ke), intent(in)  h,
type(ocean_grid_type), intent(in)  G,
type(oil_tracer_cs), pointer  CS 
)

This subroutine extracts the surface fields from this tracer package that are to be shared with the atmosphere in coupled configurations. This particular tracer package does not report anything back to the coupler.

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

Definition at line 458 of file oil_tracer.F90.

458  type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
459  type(surface), intent(inout) :: state !< A structure containing fields that
460  !! describe the surface state of the ocean.
461  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
462  intent(in) :: h !< Layer thickness [H ~> m or kg m-2].
463  type(oil_tracer_CS), pointer :: CS !< The control structure returned by a previous
464  !! call to register_oil_tracer.
465 
466  ! This particular tracer package does not report anything back to the coupler.
467  ! The code that is here is just a rough guide for packages that would.
468 
469  integer :: m, is, ie, js, je, isd, ied, jsd, jed
470  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec
471  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
472 
473  if (.not.associated(cs)) return
474 
475  if (cs%coupled_tracers) then
476  do m=1,cs%ntr
477  ! This call loads the surface values into the appropriate array in the
478  ! coupler-type structure.
479  call coupler_type_set_data(cs%tr(:,:,1,m), cs%ind_tr(m), ind_csurf, &
480  state%tr_fields, idim=(/isd, is, ie, ied/), &
481  jdim=(/jsd, js, je, jed/) )
482  enddo
483  endif
484 

◆ register_oil_tracer()

logical function, public oil_tracer::register_oil_tracer ( type(hor_index_type), intent(in)  HI,
type(verticalgrid_type), intent(in)  GV,
type(unit_scale_type), intent(in)  US,
type(param_file_type), intent(in)  param_file,
type(oil_tracer_cs), pointer  CS,
type(tracer_registry_type), pointer  tr_Reg,
type(mom_restart_cs), pointer  restart_CS 
)

Register oil tracer fields and subroutines to be used with MOM.

Parameters
[in]hiA horizontal index type structure
[in]gvThe ocean's vertical grid structure
[in]usA dimensional unit scaling type
[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 78 of file oil_tracer.F90.

78  type(hor_index_type), intent(in) :: HI !< A horizontal index type structure
79  type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure
80  type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
81  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
82  type(oil_tracer_CS), pointer :: CS !< A pointer that is set to point to the control
83  !! structure for this module
84  type(tracer_registry_type), pointer :: tr_Reg !< A pointer that is set to point to the control
85  !! structure for the tracer advection and
86  !! diffusion module
87  type(MOM_restart_CS), pointer :: restart_CS !< A pointer to the restart control structure
88 
89  ! Local variables
90  character(len=40) :: mdl = "oil_tracer" ! This module's name.
91 ! This include declares and sets the variable "version".
92 #include "version_variable.h"
93  character(len=200) :: inputdir ! The directory where the input files are.
94  character(len=48) :: var_name ! The variable's name.
95  character(len=3) :: name_tag ! String for creating identifying oils
96  character(len=48) :: flux_units ! The units for tracer fluxes, here
97  ! kg(oil) s-1 or kg(oil) m-3 kg(water) s-1.
98  real, pointer :: tr_ptr(:,:,:) => null()
99  logical :: register_oil_tracer
100  integer :: isd, ied, jsd, jed, nz, m, i, j
101  isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed ; nz = gv%ke
102 
103  if (associated(cs)) then
104  call mom_error(warning, "register_oil_tracer called with an "// &
105  "associated control structure.")
106  return
107  endif
108  allocate(cs)
109 
110  ! Read all relevant parameters and write them to the model log.
111  call log_version(param_file, mdl, version, "")
112  call get_param(param_file, mdl, "OIL_IC_FILE", cs%IC_file, &
113  "The file in which the oil tracer initial values can be "//&
114  "found, or an empty string for internal initialization.", &
115  default=" ")
116  if ((len_trim(cs%IC_file) > 0) .and. (scan(cs%IC_file,'/') == 0)) then
117  ! Add the directory if CS%IC_file is not already a complete path.
118  call get_param(param_file, mdl, "INPUTDIR", inputdir, default=".")
119  cs%IC_file = trim(slasher(inputdir))//trim(cs%IC_file)
120  call log_param(param_file, mdl, "INPUTDIR/CFC_IC_FILE", cs%IC_file)
121  endif
122  call get_param(param_file, mdl, "OIL_IC_FILE_IS_Z", cs%Z_IC_file, &
123  "If true, OIL_IC_FILE is in depth space, not layer space", &
124  default=.false.)
125 
126  call get_param(param_file, mdl, "OIL_MAY_REINIT", cs%oil_may_reinit, &
127  "If true, oil tracers may go through the initialization "//&
128  "code if they are not found in the restart files. "//&
129  "Otherwise it is a fatal error if the oil tracers are not "//&
130  "found in the restart files of a restarted run.", &
131  default=.false.)
132  call get_param(param_file, mdl, "OIL_SOURCE_LONGITUDE", cs%oil_source_longitude, &
133  "The geographic longitude of the oil source.", units="degrees E", &
134  fail_if_missing=.true.)
135  call get_param(param_file, mdl, "OIL_SOURCE_LATITUDE", cs%oil_source_latitude, &
136  "The geographic latitude of the oil source.", units="degrees N", &
137  fail_if_missing=.true.)
138  call get_param(param_file, mdl, "OIL_SOURCE_LAYER", cs%oil_source_k, &
139  "The layer into which the oil is introduced, or a "//&
140  "negative number for a vertically uniform source, "//&
141  "or 0 not to use this tracer.", units="Layer", default=0)
142  call get_param(param_file, mdl, "OIL_SOURCE_RATE", cs%oil_source_rate, &
143  "The rate of oil injection.", units="kg s-1", scale=us%T_to_s, default=1.0)
144  call get_param(param_file, mdl, "OIL_DECAY_DAYS", cs%oil_decay_days, &
145  "The decay timescale in days (if positive), or no decay "//&
146  "if 0, or use the temperature dependent decay rate of "//&
147  "Adcroft et al. (GRL, 2010) if negative.", units="days", &
148  default=0.0)
149  call get_param(param_file, mdl, "OIL_DATED_START_YEAR", cs%oil_start_year, &
150  "The time at which the oil source starts", units="years", &
151  default=0.0)
152  call get_param(param_file, mdl, "OIL_DATED_END_YEAR", cs%oil_end_year, &
153  "The time at which the oil source ends", units="years", &
154  default=1.0e99)
155 
156  cs%ntr = 0
157  cs%oil_decay_rate(:) = 0.
158  do m=1,ntr_max
159  if (cs%oil_source_k(m)/=0) then
160  write(name_tag(1:3),'("_",I2.2)') m
161  cs%ntr = cs%ntr + 1
162  cs%tr_desc(m) = var_desc("oil"//trim(name_tag), "kg m-3", "Oil Tracer", caller=mdl)
163  cs%IC_val(m) = 0.0
164  if (cs%oil_decay_days(m)>0.) then
165  cs%oil_decay_rate(m) = 1. / (86400.0*us%s_to_T * cs%oil_decay_days(m))
166  elseif (cs%oil_decay_days(m)<0.) then
167  cs%oil_decay_rate(m) = -1.
168  endif
169  endif
170  enddo
171  call log_param(param_file, mdl, "OIL_DECAY_RATE", us%s_to_T*cs%oil_decay_rate(1:cs%ntr))
172 
173  ! This needs to be changed if the units of tracer are changed above.
174  if (gv%Boussinesq) then ; flux_units = "kg s-1"
175  else ; flux_units = "kg m-3 kg s-1" ; endif
176 
177  allocate(cs%tr(isd:ied,jsd:jed,nz,cs%ntr)) ; cs%tr(:,:,:,:) = 0.0
178 
179  do m=1,cs%ntr
180  ! This is needed to force the compiler not to do a copy in the registration
181  ! calls. Curses on the designers and implementers of Fortran90.
182  tr_ptr => cs%tr(:,:,:,m)
183  call query_vardesc(cs%tr_desc(m), name=var_name, caller="register_oil_tracer")
184  ! Register the tracer for horizontal advection, diffusion, and restarts.
185  call register_tracer(tr_ptr, tr_reg, param_file, hi, gv, tr_desc=cs%tr_desc(m), &
186  registry_diags=.true., flux_units=flux_units, restart_cs=restart_cs, &
187  mandatory=.not.cs%oil_may_reinit)
188 
189  ! Set coupled_tracers to be true (hard-coded above) to provide the surface
190  ! values to the coupler (if any). This is meta-code and its arguments will
191  ! currently (deliberately) give fatal errors if it is used.
192  if (cs%coupled_tracers) &
193  cs%ind_tr(m) = aof_set_coupler_flux(trim(var_name)//'_flux', &
194  flux_type=' ', implementation=' ', caller="register_oil_tracer")
195  enddo
196 
197  cs%tr_Reg => tr_reg
198  cs%restart_CSp => restart_cs
199  register_oil_tracer = .true.
200 

References atmos_ocean_fluxes_mod::aof_set_coupler_flux(), mom_error_handler::mom_error(), ntr_max, mom_io::query_vardesc(), mom_tracer_registry::register_tracer(), and mom_io::var_desc().

Here is the call graph for this function:

Variable Documentation

◆ ntr_max

integer, parameter oil_tracer::ntr_max = 20
private

the maximum number of tracers in this module.

Definition at line 35 of file oil_tracer.F90.

35 integer, parameter :: NTR_MAX = 20 !< the maximum number of tracers in this module.

Referenced by register_oil_tracer().