MOM_generic_tracer.F90
1! This file is part of MOM6, the Modular Ocean Model version 6.
2! See the LICENSE file for licensing information.
3! SPDX-License-Identifier: Apache-2.0
4
5!> Drives the generic version of tracers TOPAZ and CFC and other GFDL BGC components
6module mom_generic_tracer
7
8#include <MOM_memory.h>
9
10! The following macro is usually defined in <fms_platform.h> but since MOM6 should not directly
11! include files from FMS we replicate the macro lines here:
12#ifdef NO_F2000
13#define _ALLOCATED associated
14#else
15#define _ALLOCATED allocated
16#endif
17
18! ### These imports should not reach into FMS directly ###
19
20use mom_ale_sponge, only : ale_sponge_cs
21use mom_coms, only : efp_type, real_to_efp
22use mom_diag_mediator, only : diag_ctrl
23use mom_error_handler, only : mom_error, fatal
24use mom_file_parser, only : param_file_type
25use mom_forcing_type, only : forcing, optics_type
26use mom_grid, only : ocean_grid_type
27use mom_hor_index, only : hor_index_type
28use mom_open_boundary, only : ocean_obc_type
29use mom_restart, only : mom_restart_cs
30use mom_sponge, only : sponge_cs
31use mom_time_manager, only : time_type
32use mom_tracer_registry, only : tracer_registry_type
33use mom_unit_scaling, only : unit_scale_type
34use mom_variables, only : surface, thermo_var_ptrs
35use mom_verticalgrid, only : verticalgrid_type
36
37implicit none ; private
38
39!> A state hidden in module data that is very much not allowed in MOM6
40! ### This needs to be fixed
41logical :: g_registered = .false.
42
45public end_mom_generic_tracer, mom_generic_tracer_get
46public mom_generic_tracer_stock
47public mom_generic_flux_init
48public mom_generic_tracer_min_max
49public mom_generic_tracer_fluxes_accumulate
50public register_mom_generic_tracer_segments
51
52!> Control structure for generic tracers
53type, public :: mom_generic_tracer_cs ; private
54 character(len = 200) :: ic_file !< The file in which the generic tracer initial values can
55 !! be found, or an empty string for internal initialization.
56 logical :: z_ic_file !< If true, the generic_tracer IC_file is in Z-space. The default is false.
57 real :: tracer_ic_val = 0.0 !< The initial value assigned to tracers, in
58 !! concentration units [conc]
59 real :: tracer_land_val = -1.0 !< The values of tracers used where land is masked out, in
60 !! concentration units [conc]
61 logical :: tracers_may_reinit !< If true, tracers may go through the
62 !! initialization code if they are not found in the restart files.
63
64 type(diag_ctrl), pointer :: diag => null() !< A structure that is used to
65 !! regulate the timing of diagnostic output.
66 type(mom_restart_cs), pointer :: restart_csp => null() !< Restart control structure
67 type(ocean_obc_type), pointer :: obc => null() !<open boundary condition type
68 !> Pointer to the first element of the linked list of generic tracers.
69 !type(g_tracer_type), pointer :: g_tracer_list => NULL()
70
71end type mom_generic_tracer_cs
72
73contains
74
75!> Initializes the generic tracer packages and adds their tracers to the list
76!! Adds the tracers in the list of generic tracers to the set of MOM tracers (i.e., MOM-register them)
77!! Register these tracers for restart
78function register_mom_generic_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)
79!subroutine register_MOM_generic_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)
80 type(hor_index_type), intent(in) :: hi !< Horizontal index ranges
81 type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
82 type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
83 type(mom_generic_tracer_cs), pointer :: cs !< Pointer to the control structure for this module
84 type(tracer_registry_type), pointer :: tr_reg !< Pointer to the control structure for the tracer
85 !! advection and diffusion module.
86 type(mom_restart_cs), target, intent(inout) :: restart_cs !< MOM restart control struct
87
88 logical :: register_mom_generic_tracer
89
90 register_mom_generic_tracer = .false.
91
92 call mom_error(fatal, "register_MOM_generic_tracer should not be called with the stub code "// &
93 "in MOM6/config_src/external, as it does nothing. Recompile using the full MOM_generic_tracer package.")
94
95end function register_mom_generic_tracer
96
97!> Register OBC segments for generic tracers
98subroutine register_mom_generic_tracer_segments(CS, GV, OBC, tr_Reg, param_file)
99 type(mom_generic_tracer_cs), pointer :: cs !< Pointer to the control structure for this module.
100 type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
101 type(ocean_obc_type), pointer :: obc !< This open boundary condition type specifies whether,
102 !! where, and what open boundary conditions are used.
103 type(tracer_registry_type), pointer :: tr_reg !< Pointer to the control structure for the tracer
104 !! advection and diffusion module.
105 type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
106
107end subroutine register_mom_generic_tracer_segments
108
109!> Initialize phase II: Initialize required variables for generic tracers
110!! There are some steps of initialization that cannot be done in register_MOM_generic_tracer
111!! This is the place and time to do them:
112!! Set the grid mask and initial time for all generic tracers.
113!! Diag_register them.
114!! Z_diag_register them.
115!!
116!! This subroutine initializes the NTR tracer fields in tr(:,:,:,:)
117!! and it sets up the tracer output.
118subroutine initialize_mom_generic_tracer(restart, day, G, GV, US, h, tv, param_file, diag, OBC, &
119 CS, sponge_CSp, ALE_sponge_CSp)
120 logical, intent(in) :: restart !< .true. if the fields have already been
121 !! read from a restart file.
122 type(time_type), target, intent(in) :: day !< Time of the start of the run.
123 type(ocean_grid_type), intent(inout) :: g !< The ocean's grid structure
124 type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
125 type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
126 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
127 type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various thermodynamic
128 !! variables
129 type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time parameters
130 type(diag_ctrl), target, intent(in) :: diag !< Regulates diagnostic output.
131 type(ocean_obc_type), pointer :: obc !< This open boundary condition type specifies whether,
132 !! where, and what open boundary conditions are used.
133 type(mom_generic_tracer_cs), pointer :: cs !< Pointer to the control structure for this module.
134 type(sponge_cs), pointer :: sponge_csp !< Pointer to the control structure for the sponges.
135 type(ale_sponge_cs), pointer :: ale_sponge_csp !< Pointer to the control structure for the
136 !! ALE sponges.
137
138end subroutine initialize_mom_generic_tracer
139
140!> Column physics for generic tracers.
141!! Get the coupler values for generic tracers that exchange with atmosphere
142!! Update generic tracer concentration fields from sources and sinks.
143!! Vertically diffuse generic tracer concentration fields.
144!! Update generic tracers from bottom and their bottom reservoir.
145!!
146!! This subroutine applies diapycnal diffusion and any other column
147!! tracer physics or chemistry to the tracers from this file.
148!! CFCs are relatively simple, as they are passive tracers. with only a surface
149!! flux as a source.
150subroutine mom_generic_tracer_column_physics(h_old, h_new, ea, eb, fluxes, Hml, dt, G, GV, US, CS, tv, optics, &
151 evap_CFL_limit, minimum_forcing_depth)
152 type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure
153 type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
154 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
155 intent(in) :: h_old !< Layer thickness before entrainment [H ~> m or kg m-2].
156 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
157 intent(in) :: h_new !< Layer thickness after entrainment [H ~> m or kg m-2].
158 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
159 intent(in) :: ea !< The amount of fluid entrained from the layer
160 !! above during this call [H ~> m or kg m-2].
161 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
162 intent(in) :: eb !< The amount of fluid entrained from the layer
163 !! below during this call [H ~> m or kg m-2].
164 type(forcing), intent(in) :: fluxes !< A structure containing pointers to thermodynamic
165 !! and tracer forcing fields.
166 real, dimension(SZI_(G),SZJ_(G)), intent(in) :: hml !< Mixed layer depth [Z ~> m]
167 real, intent(in) :: dt !< The amount of time covered by this call [T ~> s]
168 type(unit_scale_type), intent(in) :: us !< A dimensional unit scaling type
169 type(mom_generic_tracer_cs), pointer :: cs !< Pointer to the control structure for this module.
170 type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various thermodynamic variables
171 type(optics_type), intent(in) :: optics !< The structure containing optical properties.
172 real, optional, intent(in) :: evap_cfl_limit !< Limit on the fraction of the water that can
173 !! be fluxed out of the top layer in a timestep [nondim]
174 ! Stored previously in diabatic CS.
175 real, optional, intent(in) :: minimum_forcing_depth !< The smallest depth over which fluxes
176 !! can be applied [H ~> m or kg m-2]
177 ! Stored previously in diabatic CS.
178
179end subroutine mom_generic_tracer_column_physics
180
181!> This subroutine calculates mass-weighted integral on the PE either
182!! of all available tracer concentrations, or of a tracer that is
183!! being requested specifically, returning the number of stocks it has
184!! calculated. If the stock_index is present, only the stock corresponding
185!! to that coded index is returned.
186function mom_generic_tracer_stock(h, stocks, G, GV, CS, names, units, stock_index)
187 type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure
188 type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
189 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
190 type(efp_type), dimension(:), intent(out) :: stocks !< The mass-weighted integrated amount of each
191 !! tracer, in kg times concentration units [kg conc]
192 type(mom_generic_tracer_cs), pointer :: cs !< Pointer to the control structure for this module.
193 character(len=*), dimension(:), intent(out) :: names !< The names of the stocks calculated.
194 character(len=*), dimension(:), intent(out) :: units !< The units of the stocks calculated.
195 integer, optional, intent(in) :: stock_index !< The coded index of a specific stock
196 !! being sought.
197 integer :: mom_generic_tracer_stock !< Return value, the
198 !! number of stocks calculated here.
199
200 integer :: m
201 mom_generic_tracer_stock = 0
202
203 ! These should never be used, but they are set to avoid compile-time warnings
204 do m=1,size(names) ; names(m) = "" ; enddo
205 do m=1,size(units) ; units(m) = "" ; enddo
206 do m=1,size(stocks) ; stocks(m) = real_to_efp(0.0) ; enddo
207
208end function mom_generic_tracer_stock
209
210!> This subroutine finds the global min and max of either of all available
211!! tracer concentrations, or of a tracer that is being requested specifically,
212!! returning the number of tracers it has evaluated.
213!! It also optionally returns the locations of the extrema.
214function mom_generic_tracer_min_max(ind_start, got_minmax, gmin, gmax, G, CS, names, units, &
215 xgmin, ygmin, zgmin, xgmax, ygmax, zgmax)
216 integer, intent(in) :: ind_start !< The index of the tracer to start with
217 logical, dimension(:), intent(out) :: got_minmax !< Indicates whether the global min and
218 !! max are found for each tracer
219 real, dimension(:), intent(out) :: gmin !< Global minimum of each tracer [conc]
220 real, dimension(:), intent(out) :: gmax !< Global maximum of each tracer [conc]
221 type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure
222 type(mom_generic_tracer_cs), pointer :: cs !< Pointer to the control structure for this module.
223 character(len=*), dimension(:), intent(out) :: names !< The names of the stocks calculated.
224 character(len=*), dimension(:), intent(out) :: units !< The units of the stocks calculated.
225 real, dimension(:), optional, intent(out) :: xgmin !< The x-position of the global minimum in the
226 !! units of G%geoLonT, often [degrees_E] or [km] or [m]
227 real, dimension(:), optional, intent(out) :: ygmin !< The y-position of the global minimum in the
228 !! units of G%geoLatT, often [degrees_N] or [km] or [m]
229 real, dimension(:), optional, intent(out) :: zgmin !< The z-position of the global minimum [layer]
230 real, dimension(:), optional, intent(out) :: xgmax !< The x-position of the global maximum in the
231 !! units of G%geoLonT, often [degrees_E] or [km] or [m]
232 real, dimension(:), optional, intent(out) :: ygmax !< The y-position of the global maximum in the
233 !! units of G%geoLatT, often [degrees_N] or [km] or [m]
234 real, dimension(:), optional, intent(out) :: zgmax !< The z-position of the global maximum [layer]
235 integer :: mom_generic_tracer_min_max !< Return value, the
236 !! number of tracers done here.
237
238 integer :: m
239
240 mom_generic_tracer_min_max = 0
241
242 ! These should never be used, but they are set to avoid compile-time warnings. Note that the minimum values
243 ! are delibarately set to be larger than the maximum values.
244 got_minmax(:) = .false.
245 gmax(:) = -huge(gmax)
246 gmin(:) = huge(gmin)
247 do m=1,size(names) ; names(m) = "" ; enddo
248 do m=1,size(units) ; units(m) = "" ; enddo
249 if (present(xgmin)) xgmin(:) = 0.0
250 if (present(ygmin)) ygmin(:) = 0.0
251 if (present(zgmin)) zgmin(:) = 0.0
252 if (present(xgmax)) xgmax(:) = 0.0
253 if (present(ygmax)) ygmax(:) = 0.0
254 if (present(zgmax)) zgmax(:) = 0.0
255
256end function mom_generic_tracer_min_max
257
258!> This subroutine calculates the surface state and sets coupler values for
259!! those generic tracers that have flux exchange with atmosphere.
260!!
261!! This subroutine sets up the fields that the coupler needs to calculate the
262!! CFC fluxes between the ocean and atmosphere.
263subroutine mom_generic_tracer_surface_state(sfc_state, h, G, GV, CS)
264 type(ocean_grid_type), intent(in) :: g !< The ocean's grid structure
265 type(verticalgrid_type), intent(in) :: gv !< The ocean's vertical grid structure
266 type(surface), intent(inout) :: sfc_state !< A structure containing fields that
267 !! describe the surface state of the ocean.
268 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
269 type(mom_generic_tracer_cs), pointer :: cs !< Pointer to the control structure for this module.
270
271end subroutine mom_generic_tracer_surface_state
272
273!ALL PE subroutine on Ocean! Due to otpm design the fluxes should be initialized like this on ALL PE's!
274subroutine mom_generic_flux_init(verbosity)
275 integer, optional, intent(in) :: verbosity !< A 0-9 integer indicating a level of verbosity.
276
277end subroutine mom_generic_flux_init
278
279subroutine mom_generic_tracer_fluxes_accumulate(flux_tmp, weight)
280 type(forcing), intent(in) :: flux_tmp !< A structure containing pointers to
281 !! thermodynamic and tracer forcing fields.
282 real, intent(in) :: weight !< A weight for accumulating this flux [nondim]
283
284end subroutine mom_generic_tracer_fluxes_accumulate
285
286!> Copy the requested tracer into an array.
287subroutine mom_generic_tracer_get(name,member,array, CS)
288 character(len=*), intent(in) :: name !< Name of requested tracer.
289 character(len=*), intent(in) :: member !< The tracer element to return.
290 real, dimension(:,:,:), intent(out) :: array !< Array filled by this routine, in arbitrary units [A]
291 type(mom_generic_tracer_cs), pointer :: cs !< Pointer to the control structure for this module.
292
293 ! Local variables
294 real, dimension(:,:,:), pointer :: array_ptr ! The tracer in the generic tracer structures, in
295 ! arbitrary units [A]
296 character(len=128), parameter :: sub_name = 'MOM_generic_tracer_get'
297
298 array(:,:,:) = huge(array)
299
300end subroutine mom_generic_tracer_get
301
302!> This subroutine deallocates the memory owned by this module.
303subroutine end_mom_generic_tracer(CS)
304 type(mom_generic_tracer_cs), pointer :: cs !< Pointer to the control structure for this module.
305
306end subroutine end_mom_generic_tracer
307
308!----------------------------------------------------------------
309! <CONTACT EMAIL="Niki.Zadeh@noaa.gov"> Niki Zadeh
310! </CONTACT>
311!
312! <REVIEWER EMAIL="William.Cooke@noaa.gov"> William Cooke
313! </REVIEWER>
314!
315! <OVERVIEW>
316! This module drives the generic version of tracers TOPAZ and CFC
317! </OVERVIEW>
318!----------------------------------------------------------------
319
320end module mom_generic_tracer