MOM6
dyed_obc_tracer.F90
1 !> This tracer package dyes flow through open boundaries
3 
4 ! This file is part of MOM6. See LICENSE.md for the license.
5 
7 use mom_error_handler, only : mom_error, fatal, warning
9 use mom_forcing_type, only : forcing
10 use mom_hor_index, only : hor_index_type
11 use mom_grid, only : ocean_grid_type
12 use mom_io, only : file_exists, mom_read_data, slasher, vardesc, var_desc, query_vardesc
14 use mom_restart, only : mom_restart_cs
15 use mom_time_manager, only : time_type
16 use mom_tracer_registry, only : register_tracer, tracer_registry_type
17 use mom_tracer_diabatic, only : tracer_vertdiff, applytracerboundaryfluxesinout
18 use mom_variables, only : surface
20 
21 use coupler_types_mod, only : coupler_type_set_data, ind_csurf
22 use atmos_ocean_fluxes_mod, only : aof_set_coupler_flux
23 
24 implicit none ; private
25 
26 #include <MOM_memory.h>
27 
28 public register_dyed_obc_tracer, initialize_dyed_obc_tracer
29 public dyed_obc_tracer_column_physics, dyed_obc_tracer_end
30 
31 !> The control structure for the dyed_obc tracer package
32 type, public :: dyed_obc_tracer_cs ; private
33  integer :: ntr !< The number of tracers that are actually used.
34  logical :: coupled_tracers = .false. !< These tracers are not offered to the coupler.
35  character(len=200) :: tracer_ic_file !< The full path to the IC file, or " " to initialize internally.
36  type(time_type), pointer :: time => null() !< A pointer to the ocean model's clock.
37  type(tracer_registry_type), pointer :: tr_reg => null() !< A pointer to the tracer registry
38  real, pointer :: tr(:,:,:,:) => null() !< The array of tracers used in this subroutine, in g m-3?
39 
40  integer, allocatable, dimension(:) :: ind_tr !< Indices returned by aof_set_coupler_flux if it is used and the
41  !! surface tracer concentrations are to be provided to the coupler.
42 
43  type(diag_ctrl), pointer :: diag => null() !< A structure that is used to
44  !! regulate the timing of diagnostic output.
45  type(mom_restart_cs), pointer :: restart_csp => null() !< A pointer to the restart control structure
46 
47  type(vardesc), allocatable :: tr_desc(:) !< Descriptions and metadata for the tracers
48 end type dyed_obc_tracer_cs
49 
50 contains
51 
52 !> Register tracer fields and subroutines to be used with MOM.
53 function register_dyed_obc_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)
54  type(hor_index_type), intent(in) :: hi !< A horizontal index type structure.
55  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
56  type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
57  type(dyed_obc_tracer_cs), pointer :: cs !< A pointer that is set to point to the
58  !! control structure for this module
59  type(tracer_registry_type), pointer :: tr_reg !< A pointer to the tracer registry.
60  type(mom_restart_cs), pointer :: restart_cs !< A pointer to the restart control structure.
61 
62 ! Local variables
63  character(len=80) :: name, longname
64 ! This include declares and sets the variable "version".
65 #include "version_variable.h"
66  character(len=40) :: mdl = "dyed_obc_tracer" ! This module's name.
67  character(len=200) :: inputdir
68  character(len=48) :: flux_units ! The units for tracer fluxes, usually
69  ! kg(tracer) kg(water)-1 m3 s-1 or kg(tracer) s-1.
70  real, pointer :: tr_ptr(:,:,:) => null()
71  logical :: register_dyed_obc_tracer
72  integer :: isd, ied, jsd, jed, nz, m
73  isd = hi%isd ; ied = hi%ied ; jsd = hi%jsd ; jed = hi%jed ; nz = gv%ke
74 
75  if (associated(cs)) then
76  call mom_error(warning, "dyed_obc_register_tracer called with an "// &
77  "associated control structure.")
78  return
79  endif
80  allocate(cs)
81 
82  ! Read all relevant parameters and write them to the model log.
83  call log_version(param_file, mdl, version, "")
84  call get_param(param_file, mdl, "NUM_DYE_TRACERS", cs%ntr, &
85  "The number of dye tracers in this run. Each tracer "//&
86  "should have a separate boundary segment.", default=0)
87  allocate(cs%ind_tr(cs%ntr))
88  allocate(cs%tr_desc(cs%ntr))
89 
90  call get_param(param_file, mdl, "dyed_obc_TRACER_IC_FILE", cs%tracer_IC_file, &
91  "The name of a file from which to read the initial "//&
92  "conditions for the dyed_obc tracers, or blank to initialize "//&
93  "them internally.", default=" ")
94  if (len_trim(cs%tracer_IC_file) >= 1) then
95  call get_param(param_file, mdl, "INPUTDIR", inputdir, default=".")
96  inputdir = slasher(inputdir)
97  cs%tracer_IC_file = trim(inputdir)//trim(cs%tracer_IC_file)
98  call log_param(param_file, mdl, "INPUTDIR/dyed_obc_TRACER_IC_FILE", &
99  cs%tracer_IC_file)
100  endif
101 
102  allocate(cs%tr(isd:ied,jsd:jed,nz,cs%ntr)) ; cs%tr(:,:,:,:) = 0.0
103 
104  do m=1,cs%ntr
105  write(name,'("dye_",I2.2)') m
106  write(longname,'("Concentration of dyed_obc Tracer ",I2.2)') m
107  cs%tr_desc(m) = var_desc(name, units="kg kg-1", longname=longname, caller=mdl)
108  if (gv%Boussinesq) then ; flux_units = "kg kg-1 m3 s-1"
109  else ; flux_units = "kg s-1" ; endif
110 
111  ! This is needed to force the compiler not to do a copy in the registration
112  ! calls. Curses on the designers and implementers of Fortran90.
113  tr_ptr => cs%tr(:,:,:,m)
114  ! Register the tracer for horizontal advection, diffusion, and restarts.
115  call register_tracer(tr_ptr, tr_reg, param_file, hi, gv, &
116  name=name, longname=longname, units="kg kg-1", &
117  registry_diags=.true., flux_units=flux_units, &
118  restart_cs=restart_cs)
119 
120  ! Set coupled_tracers to be true (hard-coded above) to provide the surface
121  ! values to the coupler (if any). This is meta-code and its arguments will
122  ! currently (deliberately) give fatal errors if it is used.
123  if (cs%coupled_tracers) &
124  cs%ind_tr(m) = aof_set_coupler_flux(trim(name)//'_flux', &
125  flux_type=' ', implementation=' ', caller="register_dyed_obc_tracer")
126  enddo
127 
128  cs%tr_Reg => tr_reg
129  cs%restart_CSp => restart_cs
130  register_dyed_obc_tracer = .true.
131 end function register_dyed_obc_tracer
132 
133 !> Initializes the CS%ntr tracer fields in tr(:,:,:,:) and sets up the tracer output.
134 subroutine initialize_dyed_obc_tracer(restart, day, G, GV, h, diag, OBC, CS)
135  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure
136  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
137  logical, intent(in) :: restart !< .true. if the fields have already
138  !! been read from a restart file.
139  type(time_type), target, intent(in) :: day !< Time of the start of the run.
140  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
141  type(diag_ctrl), target, intent(in) :: diag !< Structure used to regulate diagnostic output.
142  type(ocean_obc_type), pointer :: obc !< Structure specifying open boundary options.
143  type(dyed_obc_tracer_cs), pointer :: cs !< The control structure returned by a previous
144  !! call to dyed_obc_register_tracer.
145 
146 ! Local variables
147  real, allocatable :: temp(:,:,:)
148  real, pointer, dimension(:,:,:) :: &
149  obc_tr1_u => null(), & ! These arrays should be allocated and set to
150  obc_tr1_v => null() ! specify the values of tracer 1 that should come
151  ! in through u- and v- points through the open
152  ! boundary conditions, in the same units as tr.
153  character(len=24) :: name ! A variable's name in a NetCDF file.
154  character(len=72) :: longname ! The long name of that variable.
155  character(len=48) :: units ! The dimensions of the variable.
156  character(len=48) :: flux_units ! The units for tracer fluxes, usually
157  ! kg(tracer) kg(water)-1 m3 s-1 or kg(tracer) s-1.
158  real, pointer :: tr_ptr(:,:,:) => null()
159  real :: h_neglect ! A thickness that is so small it is usually lost
160  ! in roundoff and can be neglected [H ~> m or kg m-2].
161  real :: e(szk_(g)+1), e_top, e_bot, d_tr
162  integer :: i, j, k, is, ie, js, je, isd, ied, jsd, jed, nz, m
163  integer :: isdb, iedb, jsdb, jedb
164 
165  if (.not.associated(cs)) return
166  if (cs%ntr < 1) return
167  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
168  isd = g%isd ; ied = g%ied ; jsd = g%jsd ; jed = g%jed
169  isdb = g%IsdB ; iedb = g%IedB ; jsdb = g%JsdB ; jedb = g%JedB
170  h_neglect = gv%H_subroundoff
171 
172  cs%Time => day
173  cs%diag => diag
174 
175  if (.not.restart) then
176  if (len_trim(cs%tracer_IC_file) >= 1) then
177  ! Read the tracer concentrations from a netcdf file.
178  if (.not.file_exists(cs%tracer_IC_file, g%Domain)) &
179  call mom_error(fatal, "dyed_obc_initialize_tracer: Unable to open "// &
180  cs%tracer_IC_file)
181  do m=1,cs%ntr
182  call query_vardesc(cs%tr_desc(m), name, caller="initialize_dyed_obc_tracer")
183  call mom_read_data(cs%tracer_IC_file, trim(name), cs%tr(:,:,:,m), g%Domain)
184  enddo
185  else
186  do m=1,cs%ntr
187  do k=1,nz ; do j=js,je ; do i=is,ie
188  cs%tr(i,j,k,m) = 0.0
189  enddo ; enddo ; enddo
190  enddo
191  endif
192  endif ! restart
193 
194 end subroutine initialize_dyed_obc_tracer
195 
196 !> This subroutine applies diapycnal diffusion and any other column
197 !! tracer physics or chemistry to the tracers from this file.
198 !! This is a simple example of a set of advected passive tracers.
199 !!
200 !! The arguments to this subroutine are redundant in that
201 !! h_new(k) = h_old(k) + ea(k) - eb(k-1) + eb(k) - ea(k+1)
202 subroutine dyed_obc_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, GV, CS, &
203  evap_CFL_limit, minimum_forcing_depth)
204  type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure
205  type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
206  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
207  intent(in) :: h_old !< Layer thickness before entrainment [H ~> m or kg m-2].
208  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
209  intent(in) :: h_new !< Layer thickness after entrainment [H ~> m or kg m-2].
210  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
211  intent(in) :: ea !< an array to which the amount of fluid entrained
212  !! from the layer above during this call will be
213  !! added [H ~> m or kg m-2].
214  real, dimension(SZI_(G),SZJ_(G),SZK_(G)), &
215  intent(in) :: eb !< an array to which the amount of fluid entrained
216  !! from the layer below during this call will be
217  !! added [H ~> m or kg m-2].
218  type(forcing), intent(in) :: fluxes !< A structure containing pointers to thermodynamic
219  !! and tracer forcing fields. Unused fields have NULL ptrs.
220  real, intent(in) :: dt !< The amount of time covered by this call [s]
221  type(dyed_obc_tracer_cs), pointer :: cs !< The control structure returned by a previous
222  !! call to dyed_obc_register_tracer.
223  real, optional, intent(in) :: evap_cfl_limit !< Limit on the fraction of the water that can
224  !! be fluxed out of the top layer in a timestep [nondim]
225  real, optional, intent(in) :: minimum_forcing_depth !< The smallest depth over which
226  !! fluxes can be applied [m]
227 
228 ! Local variables
229  real :: b1(szi_(g)) ! b1 and c1 are variables used by the
230  real :: c1(szi_(g),szk_(g)) ! tridiagonal solver.
231  real, dimension(SZI_(G),SZJ_(G),SZK_(G)) :: h_work ! Used so that h can be modified
232  integer :: i, j, k, is, ie, js, je, nz, m
233  is = g%isc ; ie = g%iec ; js = g%jsc ; je = g%jec ; nz = gv%ke
234 
235  if (.not.associated(cs)) return
236  if (cs%ntr < 1) return
237 
238  if (present(evap_cfl_limit) .and. present(minimum_forcing_depth)) then
239  do m=1,cs%ntr
240  do k=1,nz ;do j=js,je ; do i=is,ie
241  h_work(i,j,k) = h_old(i,j,k)
242  enddo ; enddo ; enddo
243  call applytracerboundaryfluxesinout(g, gv, cs%tr(:,:,:,m) , dt, fluxes, h_work, &
244  evap_cfl_limit, minimum_forcing_depth)
245  if (nz > 1) call tracer_vertdiff(h_work, ea, eb, dt, cs%tr(:,:,:,m), g, gv)
246  enddo
247  else
248  do m=1,cs%ntr
249  if (nz > 1) call tracer_vertdiff(h_old, ea, eb, dt, cs%tr(:,:,:,m), g, gv)
250  enddo
251  endif
252 
253 end subroutine dyed_obc_tracer_column_physics
254 
255 !> Clean up memory allocations, if any.
256 subroutine dyed_obc_tracer_end(CS)
257  type(dyed_obc_tracer_cs), pointer :: cs !< The control structure returned by a previous
258  !! call to dyed_obc_register_tracer.
259  integer :: m
260 
261  if (associated(cs)) then
262  if (associated(cs%tr)) deallocate(cs%tr)
263 
264  deallocate(cs)
265  endif
266 end subroutine dyed_obc_tracer_end
267 
268 !> \namespace dyed_obc_tracer
269 !!
270 !! By Kate Hedstrom, 2017, copied from DOME tracers and also
271 !! dye_example.
272 !!
273 !! This file contains an example of the code that is needed to set
274 !! up and use a set of dynamically passive tracers. These tracers
275 !! dye the inflowing water, one per open boundary segment.
276 !!
277 !! A single subroutine is called from within each file to register
278 !! each of the tracers for reinitialization and advection and to
279 !! register the subroutine that initializes the tracers and set up
280 !! their output and the subroutine that does any tracer physics or
281 !! chemistry along with diapycnal mixing (included here because some
282 !! tracers may float or swim vertically or dye diapycnal processes).
283 
284 end module dyed_obc_tracer
mom_time_manager
Wraps the FMS time manager functions.
Definition: MOM_time_manager.F90:2
mom_variables::surface
Pointers to various fields which may be used describe the surface state of MOM, and which will be ret...
Definition: MOM_variables.F90:38
dyed_obc_tracer
This tracer package dyes flow through open boundaries.
Definition: dyed_obc_tracer.F90:2
mom_verticalgrid
Provides a transparent vertical ocean grid type and supporting routines.
Definition: MOM_verticalGrid.F90:2
mom_file_parser::log_version
An overloaded interface to log version information about modules.
Definition: MOM_file_parser.F90:109
atmos_ocean_fluxes_mod
A dummy version of atmos_ocean_fluxes_mod module for use when the vastly larger FMS package is not ne...
Definition: atmos_ocean_fluxes.F90:3
mom_diag_mediator
The subroutines here provide convenient wrappers to the fms diag_manager interfaces with additional d...
Definition: MOM_diag_mediator.F90:3
dyed_obc_tracer::dyed_obc_tracer_cs
The control structure for the dyed_obc tracer package.
Definition: dyed_obc_tracer.F90:32
mom_tracer_registry
This module contains the tracer_registry_type and the subroutines that handle registration of tracers...
Definition: MOM_tracer_registry.F90:5
mom_file_parser::param_file_type
A structure that can be parsed to read and document run-time parameters.
Definition: MOM_file_parser.F90:54
mom_file_parser::get_param
An overloaded interface to read and log the values of various types of parameters.
Definition: MOM_file_parser.F90:102
mom_hor_index
Defines the horizontal index type (hor_index_type) used for providing index ranges.
Definition: MOM_hor_index.F90:2
mom_io
This module contains I/O framework code.
Definition: MOM_io.F90:2
mom_restart::mom_restart_cs
A restart registry and the control structure for restarts.
Definition: MOM_restart.F90:72
mom_tracer_diabatic
This module contains routines that implement physical fluxes of tracers (e.g. due to surface fluxes o...
Definition: MOM_tracer_diabatic.F90:4
mom_forcing_type
This module implements boundary forcing for MOM6.
Definition: MOM_forcing_type.F90:2
mom_verticalgrid::verticalgrid_type
Describes the vertical ocean grid, including unit conversion factors.
Definition: MOM_verticalGrid.F90:24
mom_restart
The MOM6 facility for reading and writing restart files, and querying what has been read.
Definition: MOM_restart.F90:2
mom_variables
Provides transparent structures with groups of MOM6 variables and supporting routines.
Definition: MOM_variables.F90:2
mom_io::mom_read_data
Read a data field from a file.
Definition: MOM_io.F90:74
mom_open_boundary
Controls where open boundary conditions are applied.
Definition: MOM_open_boundary.F90:2
mom_file_parser
The MOM6 facility to parse input files for runtime parameters.
Definition: MOM_file_parser.F90:2
mom_tracer_registry::tracer_registry_type
Type to carry basic tracer information.
Definition: MOM_tracer_registry.F90:122
mom_hor_index::hor_index_type
Container for horizontal index ranges for data, computational and global domains.
Definition: MOM_hor_index.F90:15
mom_grid
Provides the ocean grid type.
Definition: MOM_grid.F90:2
mom_open_boundary::ocean_obc_type
Open-boundary data.
Definition: MOM_open_boundary.F90:186
mom_forcing_type::forcing
Structure that contains pointers to the boundary forcing used to drive the liquid ocean simulated by ...
Definition: MOM_forcing_type.F90:49
mom_io::vardesc
Type for describing a variable, typically a tracer.
Definition: MOM_io.F90:53
mom_io::file_exists
Indicate whether a file exists, perhaps with domain decomposition.
Definition: MOM_io.F90:68
mom_file_parser::log_param
An overloaded interface to log the values of various types of parameters.
Definition: MOM_file_parser.F90:96
mom_error_handler
Routines for error handling and I/O management.
Definition: MOM_error_handler.F90:2
mom_grid::ocean_grid_type
Ocean grid type. See mom_grid for details.
Definition: MOM_grid.F90:25
mom_diag_mediator::diag_ctrl
The following data type a list of diagnostic fields an their variants, as well as variables that cont...
Definition: MOM_diag_mediator.F90:239