← back to index

src/tracer/MOM_tracer_flow_control.F90

portedportable, not yet portedexecuted, not portableexecutable, not hit by this run

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!> Orchestrates the registration and calling of tracer packages
6module MOM_tracer_flow_control
7
8use MOM_coms, only : EFP_type, assignment(=), EFP_to_real, real_to_EFP, EFP_sum_across_PEs
9use MOM_diag_mediator, only : time_type, diag_ctrl
10use MOM_error_handler, only : MOM_error, FATAL, WARNING
11use MOM_file_parser, only : get_param, log_version, param_file_type, close_param_file
12use MOM_forcing_type, only : forcing, optics_type
13use MOM_get_input, only : Get_MOM_input
14use MOM_grid, only : ocean_grid_type
15use MOM_hor_index, only : hor_index_type
16use MOM_interface_heights, only : convert_MLD_to_ML_thickness
17use MOM_CVMix_KPP, only : KPP_CS
18use MOM_open_boundary, only : ocean_OBC_type
19use MOM_restart, only : MOM_restart_CS
20use MOM_sponge, only : sponge_CS
21use MOM_ALE_sponge, only : ALE_sponge_CS
22use MOM_tracer_registry, only : tracer_registry_type
23use MOM_unit_scaling, only : unit_scale_type
24use MOM_variables, only : surface, thermo_var_ptrs
25use MOM_verticalGrid, only : verticalGrid_type
26#include <MOM_memory.h>
27
28! Add references to other user-provide tracer modules here.
29use USER_tracer_example, only : tracer_column_physics, USER_initialize_tracer, USER_tracer_stock
30use USER_tracer_example, only : USER_register_tracer_example, USER_tracer_surface_state
31use USER_tracer_example, only : USER_tracer_example_end, USER_tracer_example_CS
32use DOME_tracer, only : register_DOME_tracer, initialize_DOME_tracer
33use DOME_tracer, only : DOME_tracer_column_physics, DOME_tracer_surface_state
34use DOME_tracer, only : DOME_tracer_end, DOME_tracer_CS
35use ISOMIP_tracer, only : register_ISOMIP_tracer, initialize_ISOMIP_tracer
36use ISOMIP_tracer, only : ISOMIP_tracer_column_physics, ISOMIP_tracer_surface_state
37use ISOMIP_tracer, only : ISOMIP_tracer_end, ISOMIP_tracer_CS
38use RGC_tracer, only : register_RGC_tracer, initialize_RGC_tracer
39use RGC_tracer, only : RGC_tracer_column_physics
40use RGC_tracer, only : RGC_tracer_end, RGC_tracer_CS
41use ideal_age_example, only : register_ideal_age_tracer, initialize_ideal_age_tracer
42use ideal_age_example, only : ideal_age_tracer_column_physics, ideal_age_tracer_surface_state
43use ideal_age_example, only : ideal_age_stock, ideal_age_example_end, ideal_age_tracer_CS
44use MARBL_tracers, only : register_MARBL_tracers, initialize_MARBL_tracers
45use MARBL_tracers, only : MARBL_tracers_column_physics, MARBL_tracers_set_forcing
46use MARBL_tracers, only : MARBL_tracers_surface_state, MARBL_tracers_get
47use MARBL_tracers, only : MARBL_tracers_stock, MARBL_tracers_end, MARBL_tracers_CS
48use regional_dyes, only : register_dye_tracer, initialize_dye_tracer
49use regional_dyes, only : dye_tracer_column_physics, dye_tracer_surface_state
50use regional_dyes, only : dye_stock, regional_dyes_end, dye_tracer_CS
51use MOM_OCMIP2_CFC, only : register_OCMIP2_CFC, initialize_OCMIP2_CFC, flux_init_OCMIP2_CFC
52use MOM_OCMIP2_CFC, only : OCMIP2_CFC_column_physics, OCMIP2_CFC_surface_state
53use MOM_OCMIP2_CFC, only : OCMIP2_CFC_stock, OCMIP2_CFC_end, OCMIP2_CFC_CS
54use MOM_CFC_cap, only : register_CFC_cap, initialize_CFC_cap
55use MOM_CFC_cap, only : CFC_cap_column_physics, CFC_cap_set_forcing
56use MOM_CFC_cap, only : CFC_cap_stock, CFC_cap_end, CFC_cap_CS
57use oil_tracer, only : register_oil_tracer, initialize_oil_tracer
58use oil_tracer, only : oil_tracer_column_physics, oil_tracer_surface_state
59use oil_tracer, only : oil_stock, oil_tracer_end, oil_tracer_CS
60use advection_test_tracer, only : register_advection_test_tracer, initialize_advection_test_tracer
61use advection_test_tracer, only : advection_test_tracer_column_physics, advection_test_tracer_surface_state
62use advection_test_tracer, only : advection_test_stock, advection_test_tracer_end, advection_test_tracer_CS
63use dyed_obc_tracer, only : register_dyed_obc_tracer, initialize_dyed_obc_tracer
64use dyed_obc_tracer, only : dyed_obc_tracer_column_physics
65use dyed_obc_tracer, only : dyed_obc_tracer_end, dyed_obc_tracer_CS
66use MOM_generic_tracer, only : register_MOM_generic_tracer, initialize_MOM_generic_tracer
67use MOM_generic_tracer, only : MOM_generic_tracer_column_physics, MOM_generic_tracer_surface_state
68use MOM_generic_tracer, only : end_MOM_generic_tracer, MOM_generic_tracer_get, MOM_generic_flux_init
69use MOM_generic_tracer, only : MOM_generic_tracer_stock, MOM_generic_tracer_min_max, MOM_generic_tracer_CS
70use MOM_generic_tracer, only : register_MOM_generic_tracer_segments
71use pseudo_salt_tracer, only : register_pseudo_salt_tracer, initialize_pseudo_salt_tracer
72use pseudo_salt_tracer, only : pseudo_salt_tracer_column_physics, pseudo_salt_tracer_surface_state
73use pseudo_salt_tracer, only : pseudo_salt_stock, pseudo_salt_tracer_end, pseudo_salt_tracer_CS
74use boundary_impulse_tracer, only : register_boundary_impulse_tracer, initialize_boundary_impulse_tracer
75use boundary_impulse_tracer, only : boundary_impulse_tracer_column_physics, boundary_impulse_tracer_surface_state
76use boundary_impulse_tracer, only : boundary_impulse_stock, boundary_impulse_tracer_end
77use boundary_impulse_tracer, only : boundary_impulse_tracer_CS
78use nw2_tracers, only : nw2_tracers_CS, register_nw2_tracers, nw2_tracer_column_physics
79use nw2_tracers, only : initialize_nw2_tracers, nw2_tracers_end
80
81implicit none ; private
82
83public call_tracer_register, tracer_flow_control_init, call_tracer_set_forcing
84public call_tracer_column_fns, call_tracer_surface_state, call_tracer_stocks
85public call_tracer_flux_init, get_chl_from_model, tracer_flow_control_end
86public call_tracer_register_obc_segments
87
88!> The control structure for orchestrating the calling of tracer packages
89type, public :: tracer_flow_control_CS ; private
90 logical :: use_USER_tracer_example = .false. !< If true, use the USER_tracer_example package
91 logical :: use_DOME_tracer = .false. !< If true, use the DOME_tracer package
92 logical :: use_ISOMIP_tracer = .false. !< If true, use the ISOMPE_tracer package
93 logical :: use_RGC_tracer =.false. !< If true, use the RGC_tracer package
94 logical :: use_ideal_age = .false. !< If true, use the ideal age tracer package
95 logical :: use_MARBL_tracers = .false. !< If true, use the MARBL tracer package
96 logical :: use_regional_dyes = .false. !< If true, use the regional dyes tracer package
97 logical :: use_oil = .false. !< If true, use the oil tracer package
98 logical :: use_advection_test_tracer = .false. !< If true, use the advection_test_tracer package
99 logical :: use_OCMIP2_CFC = .false. !< If true, use the OCMIP2_CFC tracer package
100 logical :: use_CFC_cap = .false. !< If true, use the CFC_cap tracer package
101 logical :: use_MOM_generic_tracer = .false. !< If true, use the MOM_generic_tracer packages
102 logical :: use_pseudo_salt_tracer = .false. !< If true, use the psuedo_salt tracer package
103 logical :: use_boundary_impulse_tracer = .false. !< If true, use the boundary impulse tracer package
104 logical :: use_dyed_obc_tracer = .false. !< If true, use the dyed OBC tracer package
105 logical :: use_nw2_tracers = .false. !< If true, use the NW2 tracer package
106 logical :: get_chl_from_MARBL = .false. !< If true, use the MARBL-provided Chl for shortwave penetration
107 !>@{ Pointers to the control strucures for the tracer packages
108 type(USER_tracer_example_CS), pointer :: USER_tracer_example_CSp => NULL()
109 type(DOME_tracer_CS), pointer :: DOME_tracer_CSp => NULL()
110 type(ISOMIP_tracer_CS), pointer :: ISOMIP_tracer_CSp => NULL()
111 type(RGC_tracer_CS), pointer :: RGC_tracer_CSp => NULL()
112 type(ideal_age_tracer_CS), pointer :: ideal_age_tracer_CSp => NULL()
113 type(MARBL_tracers_CS), pointer :: MARBL_tracers_CSp => NULL()
114 type(dye_tracer_CS), pointer :: dye_tracer_CSp => NULL()
115 type(oil_tracer_CS), pointer :: oil_tracer_CSp => NULL()
116 type(advection_test_tracer_CS), pointer :: advection_test_tracer_CSp => NULL()
117 type(OCMIP2_CFC_CS), pointer :: OCMIP2_CFC_CSp => NULL()
118 type(CFC_cap_CS), pointer :: CFC_cap_CSp => NULL()
119 type(MOM_generic_tracer_CS), pointer :: MOM_generic_tracer_CSp => NULL()
120 type(pseudo_salt_tracer_CS), pointer :: pseudo_salt_tracer_CSp => NULL()
121 type(boundary_impulse_tracer_CS), pointer :: boundary_impulse_tracer_CSp => NULL()
122 type(dyed_obc_tracer_CS), pointer :: dyed_obc_tracer_CSp => NULL()
123 type(nw2_tracers_CS), pointer :: nw2_tracers_CSp => NULL()
124 !>@}
125end type tracer_flow_control_CS
126
127contains
128
129
130!> This subroutine carries out a series of calls to initialize the air-sea
131!! tracer fluxes, but it does not record the generated indicies, and it may
132!! be called _before_ the ocean model has been initialized and may be called
133!! on non-ocean PEs. It is not necessary to call this routine for ocean-only
134!! runs, because the same calls are made again inside of the routines called by
135!! call_tracer_register
1360subroutine call_tracer_flux_init(verbosity)
137 integer, optional, intent(in) :: verbosity !< A 0-9 integer indicating a level of verbosity.
138
1390 type(param_file_type) :: param_file ! A structure to parse for run-time parameters
140 character(len=40) :: mdl = "call_tracer_flux_init" ! This module's name.
141 logical :: use_OCMIP_CFCs, use_MOM_generic_tracer
142
143 ! Determine which tracer routines with tracer fluxes are to be called. Note
144 ! that not every tracer package is required to have a flux_init call.
1450 call get_MOM_Input(param_file, check_params=.false.)
146
147 call get_param(param_file, mdl, "USE_OCMIP2_CFC", use_OCMIP_CFCs, &
1480 default=.false., do_not_log=.true.)
149 call get_param(param_file, mdl, "USE_generic_tracer", use_MOM_generic_tracer,&
1500 default=.false., do_not_log=.true.)
1510 call close_param_file(param_file, quiet_close=.true.)
152
1530 if (use_OCMIP_CFCs) call flux_init_OCMIP2_CFC(verbosity=verbosity)
1540 if (use_MOM_generic_tracer) then
1550 call MOM_generic_flux_init(verbosity=verbosity)
156 endif
157
1580end subroutine call_tracer_flux_init
159
160! The following 5 subroutines and associated definitions provide the machinery to register and call
161! the subroutines that initialize tracers and apply vertical column processes to tracers.
162
163!> This subroutine determines which tracer packages are to be used and does the calls to
164!! register their tracers to be advected, diffused, and read from restarts.
1651subroutine call_tracer_register(G, GV, US, param_file, CS, tr_Reg, restart_CS)
166 type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
167 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
168 type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
169 type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time
170 !! parameters.
171 type(tracer_flow_control_CS), pointer :: CS !< A pointer that is set to point to the
172 !! control structure for this module.
173 type(tracer_registry_type), pointer :: tr_Reg !< A pointer that is set to point to the
174 !! control structure for the tracer
175 !! advection and diffusion module.
176 type(MOM_restart_CS), intent(inout) :: restart_CS !< A pointer to the restart control
177 !! structure.
178
179 ! This include declares and sets the variable "version".
180# include "version_variable.h"
181 character(len=40) :: mdl = "MOM_tracer_flow_control" ! This module's name.
182
1831 if (associated(CS)) then
184 call MOM_error(WARNING, "call_tracer_register called with an associated "// &
1850 "control structure.")
1860 return
1871 else ; allocate(CS) ; endif
188
189 ! Read all relevant parameters and write them to the model log.
1901 call log_version(param_file, mdl, version, "")
191 call get_param(param_file, mdl, "USE_USER_TRACER_EXAMPLE", CS%use_USER_tracer_example, &
192 "If true, use the USER_tracer_example tracer package.", &
1931 default=.false.)
194 call get_param(param_file, mdl, "USE_DOME_TRACER", CS%use_DOME_tracer, &
195 "If true, use the DOME_tracer tracer package.", &
1961 default=.false.)
197 call get_param(param_file, mdl, "USE_ISOMIP_TRACER", CS%use_ISOMIP_tracer, &
198 "If true, use the ISOMIP_tracer tracer package.", &
1991 default=.false.)
200 call get_param(param_file, mdl, "USE_RGC_TRACER", CS%use_RGC_tracer, &
201 "If true, use the RGC_tracer tracer package.", &
2021 default=.false.)
203 call get_param(param_file, mdl, "USE_IDEAL_AGE_TRACER", CS%use_ideal_age, &
204 "If true, use the ideal_age_example tracer package.", &
2051 default=.false.)
206 call get_param(param_file, mdl, "USE_MARBL_TRACERS", CS%use_marbl_tracers, &
207 "If true, use the MARBL tracer package.", &
2081 default=.false.)
209 call get_param(param_file, mdl, "USE_REGIONAL_DYES", CS%use_regional_dyes, &
210 "If true, use the regional_dyes tracer package.", &
2111 default=.false.)
212 call get_param(param_file, mdl, "USE_OIL_TRACER", CS%use_oil, &
213 "If true, use the oil_tracer tracer package.", &
2141 default=.false.)
215 call get_param(param_file, mdl, "USE_ADVECTION_TEST_TRACER", CS%use_advection_test_tracer, &
216 "If true, use the advection_test_tracer tracer package.", &
2171 default=.false.)
218 call get_param(param_file, mdl, "USE_OCMIP2_CFC", CS%use_OCMIP2_CFC, &
219 "If true, use the MOM_OCMIP2_CFC tracer package.", &
2201 default=.false.)
221 call get_param(param_file, mdl, "USE_CFC_CAP", CS%use_CFC_cap, &
222 "If true, use the MOM_CFC_cap tracer package.", &
2231 default=.false.)
224 call get_param(param_file, mdl, "USE_generic_tracer", CS%use_MOM_generic_tracer, &
225 "If true and _USE_GENERIC_TRACER is defined as a "//&
226 "preprocessor macro, use the MOM_generic_tracer packages.", &
2271 default=.false.)
228 call get_param(param_file, mdl, "USE_PSEUDO_SALT_TRACER", CS%use_pseudo_salt_tracer, &
229 "If true, use the pseudo salt tracer, typically run as a diagnostic.", &
2301 default=.false.)
231 call get_param(param_file, mdl, "USE_BOUNDARY_IMPULSE_TRACER", CS%use_boundary_impulse_tracer, &
232 "If true, use the boundary impulse tracer.", &
2331 default=.false.)
234 call get_param(param_file, mdl, "USE_DYED_OBC_TRACER", CS%use_dyed_obc_tracer, &
235 "If true, use the dyed_obc_tracer tracer package.", &
2361 default=.false.)
237 call get_param(param_file, mdl, "USE_NW2_TRACERS", CS%use_nw2_tracers, &
238 "If true, use the NeverWorld2 tracers.", &
2391 default=.false.)
240
241! Add other user-provided calls to register tracers for restarting here. Each
242! tracer package registration call returns a logical false if it cannot be run
243! for some reason. This then overrides the run-time selection from above.
2441 if (CS%use_USER_tracer_example) CS%use_USER_tracer_example = &
245 USER_register_tracer_example(G, GV, US, param_file, CS%USER_tracer_example_CSp, &
2460 tr_Reg, restart_CS)
2471 if (CS%use_DOME_tracer) CS%use_DOME_tracer = &
248 register_DOME_tracer(G, GV, US, param_file, CS%DOME_tracer_CSp, &
2490 tr_Reg, restart_CS)
2501 if (CS%use_ISOMIP_tracer) CS%use_ISOMIP_tracer = &
251 register_ISOMIP_tracer(G%HI, GV, param_file, CS%ISOMIP_tracer_CSp, &
2520 tr_Reg, restart_CS)
2531 if (CS%use_RGC_tracer) CS%use_RGC_tracer = &
254 register_RGC_tracer(G, GV, param_file, CS%RGC_tracer_CSp, &
2550 tr_Reg, restart_CS)
2561 if (CS%use_ideal_age) CS%use_ideal_age = &
257 register_ideal_age_tracer(G%HI, GV, param_file, CS%ideal_age_tracer_CSp, &
2581 tr_Reg, restart_CS)
2591 if (CS%use_MARBL_tracers) CS%use_MARBL_tracers = &
260 register_MARBL_tracers(G%HI, GV, US, param_file, CS%MARBL_tracers_CSp, &
2610 tr_Reg, restart_CS, CS%get_chl_from_MARBL)
2621 if (CS%use_regional_dyes) CS%use_regional_dyes = &
263 register_dye_tracer(G%HI, GV, US, param_file, CS%dye_tracer_CSp, &
2640 tr_Reg, restart_CS)
2651 if (CS%use_oil) CS%use_oil = &
266 register_oil_tracer(G%HI, GV, US, param_file, CS%oil_tracer_CSp, &
2670 tr_Reg, restart_CS)
2681 if (CS%use_advection_test_tracer) CS%use_advection_test_tracer = &
269 register_advection_test_tracer(G, GV, param_file, CS%advection_test_tracer_CSp, &
2700 tr_Reg, restart_CS)
2711 if (CS%use_OCMIP2_CFC) CS%use_OCMIP2_CFC = &
272 register_OCMIP2_CFC(G%HI, GV, param_file, CS%OCMIP2_CFC_CSp, &
2730 tr_Reg, restart_CS)
2741 if (CS%use_CFC_cap) CS%use_CFC_cap = &
275 register_CFC_cap(G%HI, GV, param_file, CS%CFC_cap_CSp, &
2760 tr_Reg, restart_CS)
2771 if (CS%use_MOM_generic_tracer) CS%use_MOM_generic_tracer = &
278 register_MOM_generic_tracer(G%HI, GV, param_file, CS%MOM_generic_tracer_CSp, &
2790 tr_Reg, restart_CS)
2801 if (CS%use_pseudo_salt_tracer) CS%use_pseudo_salt_tracer = &
281 register_pseudo_salt_tracer(G%HI, GV, param_file, CS%pseudo_salt_tracer_CSp, &
2820 tr_Reg, restart_CS)
2831 if (CS%use_boundary_impulse_tracer) CS%use_boundary_impulse_tracer = &
284 register_boundary_impulse_tracer(G%HI, GV, US, param_file, CS%boundary_impulse_tracer_CSp, &
2850 tr_Reg, restart_CS)
2861 if (CS%use_dyed_obc_tracer) CS%use_dyed_obc_tracer = &
287 register_dyed_obc_tracer(G%HI, GV, param_file, CS%dyed_obc_tracer_CSp, &
2880 tr_Reg, restart_CS)
2891 if (CS%use_nw2_tracers) CS%use_nw2_tracers = &
2900 register_nw2_tracers(G%HI, GV, US, param_file, CS%nw2_tracers_CSp, tr_Reg, restart_CS)
291
292end subroutine call_tracer_register
293
294!> This subroutine calls all registered tracer initialization
295!! subroutines.
2961subroutine tracer_flow_control_init(restart, day, G, GV, US, h, param_file, diag, OBC, &
297 CS, sponge_CSp, ALE_sponge_CSp, tv)
298 logical, intent(in) :: restart !< 1 if the fields have already
299 !! been read from a restart file.
300 type(time_type), target, intent(in) :: day !< Time of the start of the run.
301 type(ocean_grid_type), intent(inout) :: G !< The ocean's grid structure.
302 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid
303 !! structure.
304 type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
305 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
306 intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
307 type(param_file_type), intent(in) :: param_file !< A structure to parse for
308 !! run-time parameters
309 type(diag_ctrl), target, intent(in) :: diag !< A structure that is used to
310 !! regulate diagnostic output.
311 type(ocean_OBC_type), pointer :: OBC !< This open boundary condition
312 !! type specifies whether, where,
313 !! and what open boundary
314 !! conditions are used.
315 type(tracer_flow_control_CS), pointer :: CS !< The control structure returned
316 !! by a previous call to
317 !! call_tracer_register.
318 type(sponge_CS), pointer :: sponge_CSp !< A pointer to the control
319 !! structure for the sponges, if they are in use.
320 !! Otherwise this may be unassociated.
321 type(ALE_sponge_CS), pointer :: ALE_sponge_CSp !< A pointer to the control
322 !! structure for the ALE sponges, if they are in use.
323 !! Otherwise this may be unassociated.
324 type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various
325 !! thermodynamic variables
326
3271 if (.not. associated(CS)) call MOM_error(FATAL, "tracer_flow_control_init: "// &
3280 "Module must be initialized via call_tracer_register before it is used.")
329
330! Add other user-provided calls here.
3311 if (CS%use_USER_tracer_example) &
332 call USER_initialize_tracer(restart, day, G, GV, US, h, diag, OBC, CS%USER_tracer_example_CSp, &
3330 sponge_CSp)
3341 if (CS%use_DOME_tracer) &
335 call initialize_DOME_tracer(restart, day, G, GV, US, h, diag, OBC, CS%DOME_tracer_CSp, &
3360 sponge_CSp, tv)
3371 if (CS%use_ISOMIP_tracer) &
338 call initialize_ISOMIP_tracer(restart, day, G, GV, h, diag, OBC, CS%ISOMIP_tracer_CSp, &
3390 ALE_sponge_CSp)
3401 if (CS%use_RGC_tracer) &
341 call initialize_RGC_tracer(restart, day, G, GV, h, diag, OBC, CS%RGC_tracer_CSp, &
3420 sponge_CSp, ALE_sponge_CSp)
3431 if (CS%use_ideal_age) &
344 call initialize_ideal_age_tracer(restart, day, G, GV, US, h, diag, OBC, CS%ideal_age_tracer_CSp, &
3451 sponge_CSp)
3461 if (CS%use_MARBL_tracers) &
347 call initialize_MARBL_tracers(restart, day, G, GV, US, h, param_file, diag, OBC, CS%MARBL_tracers_CSp, &
3480 sponge_CSp)
3491 if (CS%use_regional_dyes) &
3500 call initialize_dye_tracer(restart, day, G, GV, US, h, diag, OBC, CS%dye_tracer_CSp, sponge_CSp, tv)
3511 if (CS%use_oil) &
3520 call initialize_oil_tracer(restart, day, G, GV, US, h, diag, OBC, CS%oil_tracer_CSp, sponge_CSp)
3531 if (CS%use_advection_test_tracer) &
354 call initialize_advection_test_tracer(restart, day, G, GV, h, diag, OBC, CS%advection_test_tracer_CSp, &
3550 sponge_CSp)
3561 if (CS%use_OCMIP2_CFC) &
3570 call initialize_OCMIP2_CFC(restart, day, G, GV, US, h, diag, OBC, CS%OCMIP2_CFC_CSp, sponge_CSp)
3581 if (CS%use_CFC_cap) &
3590 call initialize_CFC_cap(restart, day, G, GV, US, h, diag, OBC, CS%CFC_cap_CSp)
360
3611 if (CS%use_MOM_generic_tracer) &
362 call initialize_MOM_generic_tracer(restart, day, G, GV, US, h, tv, param_file, diag, OBC, &
3630 CS%MOM_generic_tracer_CSp, sponge_CSp, ALE_sponge_CSp)
3641 if (CS%use_pseudo_salt_tracer) &
365 call initialize_pseudo_salt_tracer(restart, day, G, GV, US, h, diag, OBC, CS%pseudo_salt_tracer_CSp, &
3660 sponge_CSp, tv)
3671 if (CS%use_boundary_impulse_tracer) &
368 call initialize_boundary_impulse_tracer(restart, day, G, GV, US, h, diag, OBC, CS%boundary_impulse_tracer_CSp, &
3690 sponge_CSp, tv)
3701 if (CS%use_dyed_obc_tracer) &
3710 call initialize_dyed_obc_tracer(restart, day, G, GV, h, diag, OBC, CS%dyed_obc_tracer_CSp)
3721 if (CS%use_nw2_tracers) &
3730 call initialize_nw2_tracers(restart, day, G, GV, US, h, tv, diag, CS%nw2_tracers_CSp)
374
3751end subroutine tracer_flow_control_init
376
377!> This subroutine calls all registered tracers to register their OBC segments
378!! similar to register_temp_salt_segments for T&S
3790subroutine call_tracer_register_obc_segments(GV, param_file, CS, tr_Reg, OBC)
380 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
381 type(param_file_type), intent(in) :: param_file !< A structure to parse for run-time
382 !! parameters.
383 type(tracer_flow_control_CS), pointer :: CS !< A pointer that is set to point to the
384 !! control structure for this module.
385 type(tracer_registry_type), pointer :: tr_Reg !< A pointer that is set to point to the
386 !! control structure for the tracer
387 !! advection and diffusion module.
388 type(ocean_OBC_type), pointer :: OBC !< This open boundary condition
389 !! type specifies whether, where,
390 !! and what open boundary
391 !! conditions are used.
392
3930 if (CS%use_MOM_generic_tracer) &
3940 call register_MOM_generic_tracer_segments(CS%MOM_generic_tracer_CSp, GV, OBC, tr_Reg, param_file)
395
3960end subroutine call_tracer_register_obc_segments
397
398!> This subroutine extracts the chlorophyll concentrations from the model state, if possible
3990subroutine get_chl_from_model(Chl_array, G, GV, CS)
400 type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
401 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
402 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
403 intent(out) :: Chl_array !< The array in which to store the model's
404 !! Chlorophyll-A concentrations [mg m-3].
405 type(tracer_flow_control_CS), pointer :: CS !< The control structure returned by a
406 !! previous call to call_tracer_register.
407
4080 if (CS%get_chl_from_MARBL) then
4090 call MARBL_tracers_get('Chl', G, GV, Chl_array, CS%MARBL_tracers_CSp)
4100 elseif (CS%use_MOM_generic_tracer) then
4110 call MOM_generic_tracer_get('chl', 'field', Chl_array, CS%MOM_generic_tracer_CSp)
412 else
413 call MOM_error(FATAL, "get_chl_from_model was called in a configuration "// &
414 "that is unable to provide a sensible model-based value.\n"// &
4150 "CS%use_MOM_generic_tracer is false and no other viable options are on.")
416 endif
417
4180end subroutine get_chl_from_model
419
420!> This subroutine calls the individual tracer modules' subroutines to
421!! specify or read quantities related to their surface forcing.
42212subroutine call_tracer_set_forcing(sfc_state, fluxes, day_start, day_interval, G, US, Rho0, CS)
423
424 type(surface), intent(inout) :: sfc_state !< A structure containing fields that
425 !! describe the surface state of the
426 !! ocean.
427 type(forcing), intent(inout) :: fluxes !< A structure containing pointers to any
428 !! possible forcing fields. Unused fields
429 !! have NULL ptrs.
430 type(time_type), intent(in) :: day_start !< Start time of the fluxes.
431 type(time_type), intent(in) :: day_interval !< Length of time over which these
432 !! fluxes will be applied.
433 type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
434 type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
435 real, intent(in) :: Rho0 !< The mean ocean density [R ~> kg m-3]
436 type(tracer_flow_control_CS), pointer :: CS !< The control structure returned by a
437 !! previous call to call_tracer_register.
438
43912 if (.not. associated(CS)) call MOM_error(FATAL, "call_tracer_set_forcing: "// &
4400 "Module must be initialized via call_tracer_register before it is used.")
441! if (CS%use_ideal_age) &
442! call ideal_age_tracer_set_forcing(sfc_state, fluxes, day_start, day_interval, &
443! G, CS%ideal_age_tracer_CSp)
44412 if (CS%use_CFC_cap) &
445 call CFC_cap_set_forcing(sfc_state, fluxes, day_start, day_interval, G, US, Rho0, &
4460 CS%CFC_cap_CSp)
447
44812 if (CS%use_MARBL_tracers) &
4490 call MARBL_tracers_set_forcing(day_start, G, CS%MARBL_tracers_CSp)
450
45112end subroutine call_tracer_set_forcing
452
453!> This subroutine calls all registered tracer column physics subroutines.
45412subroutine call_tracer_column_fns(h_old, h_new, ea, eb, fluxes, mld, dt, G, GV, US, tv, optics, CS, &
45512 debug, KPP_CSp, nonLocalTrans, evap_CFL_limit, minimum_forcing_depth, h_BL)
456 type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
457 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
458 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h_old !< Layer thickness before entrainment
459 !! [H ~> m or kg m-2].
460 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: h_new !< Layer thickness after entrainment
461 !! [H ~> m or kg m-2].
462 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: ea !< an array to which the amount of
463 !! fluid entrained from the layer above during this call
464 !! will be added [H ~> m or kg m-2].
465 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), intent(in) :: eb !< an array to which the amount of
466 !! fluid entrained from the layer below during this call
467 !! will be added [H ~> m or kg m-2].
468 type(forcing), intent(in) :: fluxes !< A structure containing pointers to
469 !! any possible forcing fields.
470 !! Unused fields have NULL ptrs.
471 real, dimension(SZI_(G),SZJ_(G)), intent(in) :: mld !< Mixed layer depth [Z ~> m]
472 real, intent(in) :: dt !< The amount of time covered by this
473 !! call [T ~> s]
474 type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
475 type(thermo_var_ptrs), intent(in) :: tv !< A structure pointing to various
476 !! thermodynamic variables.
477 type(optics_type), pointer :: optics !< The structure containing optical
478 !! properties.
479 type(tracer_flow_control_CS), pointer :: CS !< The control structure returned by
480 !! a previous call to
481 !! call_tracer_register.
482 logical, intent(in) :: debug !< If true calculate checksums
483 type(KPP_CS), optional, pointer :: KPP_CSp !< KPP control structure
484 real, optional, intent(in) :: nonLocalTrans(:,:,:) !< Non-local transport [nondim]
485 real, optional, intent(in) :: evap_CFL_limit !< Limit on the fraction of
486 !! the water that can be fluxed out
487 !! of the top layer in a timestep [nondim]
488 real, optional, intent(in) :: minimum_forcing_depth !< The smallest depth over
489 !! which fluxes can be applied [H ~> m or kg m-2]
490 real, dimension(:,:), optional, pointer :: h_BL !< Thickness of active mixing layer [H ~> m or kg m-2]
491
492 ! Local variables
49324 real :: Hbl(SZI_(G),SZJ_(G)) !< Boundary layer thickness [H ~> m or kg m-2]
494 logical :: use_h_BL
495
49612 if (.not. associated(CS)) call MOM_error(FATAL, "call_tracer_column_fns: "// &
4970 "Module must be initialized via call_tracer_register before it is used.")
498
499 ! Use the applyTracerBoundaryFluxesInOut to handle surface fluxes
50012 if (present(evap_CFL_limit) .and. present(minimum_forcing_depth)) then
501 ! Add calls to tracer column functions here.
50212 if (CS%use_USER_tracer_example) &
503 call tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
5040 G, GV, US, CS%USER_tracer_example_CSp)
50512 if (CS%use_DOME_tracer) &
506 call DOME_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
507 G, GV, US, CS%DOME_tracer_CSp, &
508 evap_CFL_limit=evap_CFL_limit, &
5090 minimum_forcing_depth=minimum_forcing_depth)
51012 if (CS%use_ISOMIP_tracer) &
511 call ISOMIP_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
512 G, GV, US, CS%ISOMIP_tracer_CSp, &
513 evap_CFL_limit=evap_CFL_limit, &
5140 minimum_forcing_depth=minimum_forcing_depth)
51512 if (CS%use_RGC_tracer) &
516 call RGC_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
517 G, GV, US, CS%RGC_tracer_CSp, &
518 evap_CFL_limit=evap_CFL_limit, &
5190 minimum_forcing_depth=minimum_forcing_depth)
52012 if (CS%use_ideal_age) then
52112 use_h_BL = .false. ; if (present(h_BL)) use_h_BL = associated(h_BL)
52212 if (present(h_BL)) then
523105276 Hbl(:,:) = h_BL(:,:)
524 else ! This option is here mostly to support the offline tracers.
5250 call convert_MLD_to_ML_thickness(mld, h_new, Hbl, tv, G, GV)
526 endif
527 call ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
528 G, GV, US, CS%ideal_age_tracer_CSp, &
529 evap_CFL_limit=evap_CFL_limit, &
53012 minimum_forcing_depth=minimum_forcing_depth, Hbl=Hbl)
531 endif
53212 if (CS%use_MARBL_tracers) &
533 call MARBL_tracers_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
534 G, GV, US, CS%MARBL_tracers_CSp, tv, &
535 KPP_CSp=KPP_CSp, &
536 nonLocalTrans=nonLocalTrans, &
537 evap_CFL_limit=evap_CFL_limit, &
5380 minimum_forcing_depth=minimum_forcing_depth)
53912 if (CS%use_regional_dyes) &
540 call dye_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
541 G, GV, US, tv, CS%dye_tracer_CSp, &
542 evap_CFL_limit=evap_CFL_limit, &
5430 minimum_forcing_depth=minimum_forcing_depth)
54412 if (CS%use_oil) &
545 call oil_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
546 G, GV, US, CS%oil_tracer_CSp, tv, &
547 evap_CFL_limit=evap_CFL_limit, &
5480 minimum_forcing_depth=minimum_forcing_depth)
549
55012 if (CS%use_advection_test_tracer) &
551 call advection_test_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
552 G, GV, US, CS%advection_test_tracer_CSp, &
553 evap_CFL_limit=evap_CFL_limit, &
5540 minimum_forcing_depth=minimum_forcing_depth)
55512 if (CS%use_OCMIP2_CFC) &
556 call OCMIP2_CFC_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
557 G, GV, US, CS%OCMIP2_CFC_CSp, &
558 evap_CFL_limit=evap_CFL_limit, &
5590 minimum_forcing_depth=minimum_forcing_depth)
56012 if (CS%use_CFC_cap) &
561 call CFC_cap_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
562 G, GV, US, CS%CFC_cap_CSp, &
563 KPP_CSp=KPP_CSp, &
564 nonLocalTrans=nonLocalTrans, &
565 evap_CFL_limit=evap_CFL_limit, &
5660 minimum_forcing_depth=minimum_forcing_depth)
56712 if (CS%use_MOM_generic_tracer) then
5680 if (US%QRZ_T_to_W_m2 /= 1.0) call MOM_error(FATAL, "MOM_generic_tracer_column_physics "//&
569 "has not been written to permit dimensionsal rescaling. Set all 4 of the "//&
5700 "[QRZT]_RESCALE_POWER parameters to 0.")
571 call MOM_generic_tracer_column_physics(h_old, h_new, ea, eb, fluxes, mld, dt, &
572 G, GV, US, CS%MOM_generic_tracer_CSp, tv, optics, &
573 evap_CFL_limit=evap_CFL_limit, &
5740 minimum_forcing_depth=minimum_forcing_depth)
575 endif
57612 if (CS%use_pseudo_salt_tracer) &
577 call pseudo_salt_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
578 G, GV, US, CS%pseudo_salt_tracer_CSp, tv, &
579 debug, &
580 KPP_CSp=KPP_CSp, &
581 nonLocalTrans=nonLocalTrans, &
582 evap_CFL_limit=evap_CFL_limit, &
5830 minimum_forcing_depth=minimum_forcing_depth)
58412 if (CS%use_boundary_impulse_tracer) &
585 call boundary_impulse_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
586 G, GV, US, CS%boundary_impulse_tracer_CSp, tv, debug, &
587 evap_CFL_limit=evap_CFL_limit, &
5880 minimum_forcing_depth=minimum_forcing_depth)
58912 if (CS%use_dyed_obc_tracer) &
590 call dyed_obc_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
591 G, GV, US, CS%dyed_obc_tracer_CSp, &
592 evap_CFL_limit=evap_CFL_limit, &
5930 minimum_forcing_depth=minimum_forcing_depth)
59412 if (CS%use_nw2_tracers) &
595 call nw2_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
596 G, GV, US, tv, CS%nw2_tracers_CSp, &
597 evap_CFL_limit=evap_CFL_limit, &
5980 minimum_forcing_depth=minimum_forcing_depth)
599 else ! Apply tracer surface fluxes using ea on the first layer
6000 if (CS%use_USER_tracer_example) &
601 call tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
6020 G, GV, US, CS%USER_tracer_example_CSp)
6030 if (CS%use_DOME_tracer) &
604 call DOME_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
6050 G, GV, US, CS%DOME_tracer_CSp)
6060 if (CS%use_ISOMIP_tracer) &
607 call ISOMIP_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
6080 G, GV, US, CS%ISOMIP_tracer_CSp)
6090 if (CS%use_RGC_tracer) &
610 call RGC_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
6110 G, GV, US, CS%RGC_tracer_CSp)
6120 if (CS%use_ideal_age) then
6130 use_h_BL = .false. ; if (present(h_BL)) use_h_BL = associated(h_BL)
6140 if (present(h_BL)) then
6150 Hbl(:,:) = h_BL(:,:)
616 else ! This option is here mostly to support the offline tracers.
6170 call convert_MLD_to_ML_thickness(mld, h_new, Hbl, tv, G, GV)
618 endif
619 call ideal_age_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
6200 G, GV, US, CS%ideal_age_tracer_CSp, Hbl=Hbl)
621 endif
6220 if (CS%use_MARBL_tracers) &
623 call MARBL_tracers_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
624 G, GV, US, CS%MARBL_tracers_CSp, tv, &
625 KPP_CSp=KPP_CSp, &
6260 nonLocalTrans=nonLocalTrans)
6270 if (CS%use_regional_dyes) &
628 call dye_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
6290 G, GV, US, tv, CS%dye_tracer_CSp)
6300 if (CS%use_oil) &
631 call oil_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
6320 G, GV, US, CS%oil_tracer_CSp, tv)
6330 if (CS%use_advection_test_tracer) &
634 call advection_test_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
6350 G, GV, US, CS%advection_test_tracer_CSp)
6360 if (CS%use_OCMIP2_CFC) &
637 call OCMIP2_CFC_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
6380 G, GV, US, CS%OCMIP2_CFC_CSp)
6390 if (CS%use_CFC_cap) &
640 call CFC_cap_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
641 G, GV, US, CS%CFC_cap_CSp, &
642 KPP_CSp=KPP_CSp, &
6430 nonLocalTrans=nonLocalTrans)
6440 if (CS%use_MOM_generic_tracer) then
6450 if (US%QRZ_T_to_W_m2 /= 1.0) call MOM_error(FATAL, "MOM_generic_tracer_column_physics "//&
646 "has not been written to permit dimensionsal rescaling. Set all 4 of the "//&
6470 "[QRZT]_RESCALE_POWER parameters to 0.")
648 call MOM_generic_tracer_column_physics(h_old, h_new, ea, eb, fluxes, mld, dt, &
6490 G, GV, US, CS%MOM_generic_tracer_CSp, tv, optics)
650 endif
6510 if (CS%use_pseudo_salt_tracer) &
652 call pseudo_salt_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
653 G, GV, US, CS%pseudo_salt_tracer_CSp, &
654 tv, debug, &
655 KPP_CSp=KPP_CSp, &
6560 nonLocalTrans=nonLocalTrans)
6570 if (CS%use_boundary_impulse_tracer) &
658 call boundary_impulse_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
6590 G, GV, US, CS%boundary_impulse_tracer_CSp, tv, debug)
6600 if (CS%use_dyed_obc_tracer) &
661 call dyed_obc_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
6620 G, GV, US, CS%dyed_obc_tracer_CSp)
6630 if (CS%use_nw2_tracers) call nw2_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, &
6640 G, GV, US, tv, CS%nw2_tracers_CSp)
665 endif
666
66712end subroutine call_tracer_column_fns
668
669!> This subroutine calls all registered tracer packages to enable them to
670!! add to the surface state returned to the coupler. These routines are optional.
6713subroutine call_tracer_stocks(h, stock_values, G, GV, US, CS, stock_names, stock_units, &
6723 num_stocks, stock_index, got_min_max, global_min, global_max, &
6733 xgmin, ygmin, zgmin, xgmax, ygmax, zgmax)
674 type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
675 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
676 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
677 intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
678 real, dimension(:), intent(out) :: stock_values !< The globally mass-integrated
679 !! amount of a tracer [kg conc].
680 type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
681 type(tracer_flow_control_CS), pointer :: CS !< The control structure returned by a
682 !! previous call to
683 !! call_tracer_register.
684 character(len=*), dimension(:), &
685 optional, intent(out) :: stock_names !< Diagnostic names to use for each stock.
686 character(len=*), dimension(:), &
687 optional, intent(out) :: stock_units !< Units to use in the metadata for each stock.
688 integer, optional, intent(out) :: num_stocks !< The number of tracer stocks being returned.
689 integer, optional, intent(in) :: stock_index !< The integer stock index from
690 !! stocks_constants_mod of the stock to be returned. If this is
691 !! present and greater than 0, only a single stock can be returned.
692 logical, dimension(:), &
693 optional, intent(inout) :: got_min_max !< Indicates whether the global min and
694 !! max are found for each tracer
695 real, dimension(:), optional, intent(out) :: global_min !< The global minimum of each tracer [conc]
696 real, dimension(:), optional, intent(out) :: global_max !< The global maximum of each tracer [conc]
697 real, dimension(:), optional, intent(out) :: xgmin !< The x-position of the global minimum in the
698 !! units of G%geoLonT, often [degrees_E] or [km]
699 real, dimension(:), optional, intent(out) :: ygmin !< The y-position of the global minimum in the
700 !! units of G%geoLatT, often [degrees_N] or [km]
701 real, dimension(:), optional, intent(out) :: zgmin !< The z-position of the global minimum [layer]
702 real, dimension(:), optional, intent(out) :: xgmax !< The x-position of the global maximum in the
703 !! units of G%geoLonT, often [degrees_E] or [km]
704 real, dimension(:), optional, intent(out) :: ygmax !< The y-position of the global maximum in the
705 !! units of G%geoLatT, often [degrees_N] or [km]
706 real, dimension(:), optional, intent(out) :: zgmax !< The z-position of the global maximum [layer]
707
708 ! Local variables
709 character(len=200), dimension(MAX_FIELDS_) :: names, units
710 character(len=200) :: set_pkg_name
711 ! real, dimension(MAX_FIELDS_) :: values ! Globally integrated tracer amounts in a
712 ! new list for each tracer package [kg conc]
713 type(EFP_type), dimension(MAX_FIELDS_) :: values_EFP ! Globally integrated tracer amounts in a
714 ! new list for each tracer package [kg conc]
715 type(EFP_type), dimension(MAX_FIELDS_) :: stock_val_EFP ! Globally integrated tracer amounts in a
716 ! single master list for all tracers [kg conc]
717 integer :: max_ns, ns_tot, ns, index, nn, n
718
7193 if (.not. associated(CS)) call MOM_error(FATAL, "call_tracer_stocks: "// &
7200 "Module must be initialized via call_tracer_register before it is used.")
721
7223 index = -1 ; if (present(stock_index)) index = stock_index
7233 ns_tot = 0
7243 max_ns = size(stock_values)
7253 if (present(stock_names)) max_ns = min(max_ns,size(stock_names))
7263 if (present(stock_units)) max_ns = min(max_ns,size(stock_units))
727
728! Add other user-provided calls here.
7293 if (CS%use_USER_tracer_example) then
730 ns = USER_tracer_stock(h, values_EFP, G, GV, CS%USER_tracer_example_CSp, &
7310 names, units, stock_index)
732 call store_stocks("tracer_example", ns, names, units, values_EFP, index, stock_val_EFP, &
7330 set_pkg_name, max_ns, ns_tot, stock_names, stock_units)
734 endif
735! if (CS%use_DOME_tracer) then
736! ns = DOME_tracer_stock(h, values, G, GV, CS%DOME_tracer_CSp, &
737! names, units, stock_index)
738! do n=1,ns ; values_EFP(n) = real_to_EFP(values(n)) ; enddo
739! call store_stocks("DOME_tracer", ns, names, units, values_EFP, index, stock_val_EFP, &
740! set_pkg_name, max_ns, ns_tot, stock_names, stock_units)
741! endif
7423 if (CS%use_ideal_age) then
743 ns = ideal_age_stock(h, values_EFP, G, GV, CS%ideal_age_tracer_CSp, &
7443 names, units, stock_index)
745 call store_stocks("ideal_age_example", ns, names, units, values_EFP, index, stock_val_EFP, &
7463 set_pkg_name, max_ns, ns_tot, stock_names, stock_units)
747 endif
7483 if (CS%use_MARBL_tracers) then
749 ns = MARBL_tracers_stock(h, values_EFP, G, GV, CS%MARBL_tracers_CSp, &
7500 names, units, stock_index)
751 call store_stocks("MARBL_tracers", ns, names, units, values_EFP, index, stock_val_EFP, &
7520 set_pkg_name, max_ns, ns_tot, stock_names, stock_units)
753 endif
7543 if (CS%use_regional_dyes) then
7550 ns = dye_stock(h, values_EFP, G, GV, CS%dye_tracer_CSp, names, units, stock_index)
756 call store_stocks("regional_dyes", ns, names, units, values_EFP, index, stock_val_EFP, &
7570 set_pkg_name, max_ns, ns_tot, stock_names, stock_units)
758 endif
7593 if (CS%use_oil) then
7600 ns = oil_stock(h, values_EFP, G, GV, CS%oil_tracer_CSp, names, units, stock_index)
761 call store_stocks("oil_tracer", ns, names, units, values_EFP, index, stock_val_EFP, &
7620 set_pkg_name, max_ns, ns_tot, stock_names, stock_units)
763 endif
7643 if (CS%use_OCMIP2_CFC) then
7650 ns = OCMIP2_CFC_stock(h, values_EFP, G, GV, CS%OCMIP2_CFC_CSp, names, units, stock_index)
766 call store_stocks("MOM_OCMIP2_CFC", ns, names, units, values_EFP, index, stock_val_EFP, &
7670 set_pkg_name, max_ns, ns_tot, stock_names, stock_units)
768 endif
769
7703 if (CS%use_CFC_cap) then
7710 ns = CFC_cap_stock(h, values_EFP, G, GV, CS%CFC_cap_CSp, names, units, stock_index)
772 call store_stocks("MOM_CFC_cap", ns, names, units, values_EFP, index, stock_val_EFP, &
7730 set_pkg_name, max_ns, ns_tot, stock_names, stock_units)
774 endif
775
7763 if (CS%use_advection_test_tracer) then
777 ns = advection_test_stock( h, values_EFP, G, GV, CS%advection_test_tracer_CSp, &
7780 names, units, stock_index )
779 ! do n=1,ns ; values_EFP(n) = real_to_EFP(values(n)) ; enddo
780 call store_stocks("advection_test_tracer", ns, names, units, values_EFP, index, stock_val_EFP, &
7810 set_pkg_name, max_ns, ns_tot, stock_names, stock_units)
782 endif
783
7843 if (CS%use_MOM_generic_tracer) then
785 ns = MOM_generic_tracer_stock(h, values_EFP, G, GV, CS%MOM_generic_tracer_CSp, &
7860 names, units, stock_index)
787 call store_stocks("MOM_generic_tracer", ns, names, units, values_EFP, index, stock_val_EFP, &
7880 set_pkg_name, max_ns, ns_tot, stock_names, stock_units)
7890 nn=ns_tot-ns+1
7900 if (present(got_min_max) .and. present(global_min) .and. present(global_max)) &
791 nn = MOM_generic_tracer_min_max(nn, got_min_max, global_min, global_max, &
792 G, CS%MOM_generic_tracer_CSp, names, units, &
7930 xgmin, ygmin, zgmin, xgmax, ygmax, zgmax)
794
795 endif
7963 if (CS%use_pseudo_salt_tracer) then
797 ns = pseudo_salt_stock(h, values_EFP, G, GV, CS%pseudo_salt_tracer_CSp, &
7980 names, units, stock_index)
799 call store_stocks("pseudo_salt_tracer", ns, names, units, values_EFP, index, stock_val_EFP, &
8000 set_pkg_name, max_ns, ns_tot, stock_names, stock_units)
801 endif
802
8033 if (CS%use_boundary_impulse_tracer) then
804 ns = boundary_impulse_stock(h, values_EFP, G, GV, CS%boundary_impulse_tracer_CSp, &
8050 names, units, stock_index)
806 call store_stocks("boundary_impulse_tracer", ns, names, units, values_EFP, index, stock_val_EFP, &
8070 set_pkg_name, max_ns, ns_tot, stock_names, stock_units)
808 endif
809
810 ! Sum the various quantities across all the processors.
8113 if (ns_tot > 0) then
8123 call EFP_sum_across_PEs(stock_val_EFP, ns_tot)
8136 do n=1,ns_tot ; stock_values(n) = EFP_to_real(stock_val_EFP(n)) ; enddo
814 else
8150 stock_values(1) = 0.0
816 endif
817
8183 if (present(num_stocks)) num_stocks = ns_tot
819
8203end subroutine call_tracer_stocks
821
822!> This routine stores the stocks and does error handling for call_tracer_stocks.
8239subroutine store_stocks(pkg_name, ns, names, units, values, index, stock_values, &
8246 set_pkg_name, max_ns, ns_tot, stock_names, stock_units)
825 character(len=*), intent(in) :: pkg_name !< The tracer package name
826 integer, intent(in) :: ns !< The number of stocks associated with this tracer package
827 character(len=*), dimension(:), &
828 intent(in) :: names !< Diagnostic names to use for each stock.
829 character(len=*), dimension(:), &
830 intent(in) :: units !< Units to use in the metadata for each stock.
831 type(EFP_type), dimension(:), &
832 intent(in) :: values !< The values of the tracer stocks [conc kg]
833 integer, intent(in) :: index !< The integer stock index from
834 !! stocks_constants_mod of the stock to be returned. If this is
835 !! present and greater than 0, only a single stock can be returned.
836 type(EFP_type), dimension(:), &
837 intent(inout) :: stock_values !< The master list of stock values [conc kg]
838 character(len=*), intent(inout) :: set_pkg_name !< The name of the last tracer package whose
839 !! stocks were stored for a specific index. This is
840 !! used to trigger an error if there are redundant stocks.
841 integer, intent(in) :: max_ns !< The maximum size of the master stock list
842 integer, intent(inout) :: ns_tot !< The total number of stocks in the master list
843 character(len=*), dimension(:), &
844 optional, intent(inout) :: stock_names !< Diagnostic names to use for each stock in the master list
845 character(len=*), dimension(:), &
846 optional, intent(inout) :: stock_units !< Units to use in the metadata for each stock in the master list
847
848! This routine stores the stocks and does error handling for call_tracer_stocks.
849 character(len=16) :: ind_text, ns_text, max_text
850 integer :: n
851
8523 if ((index > 0) .and. (ns > 0)) then
8530 write(ind_text,'(I0)') index
8540 if (ns > 1) then
855 call MOM_error(FATAL,"Tracer package "//trim(pkg_name)//&
856 " is not permitted to return more than one value when queried "//&
8570 "for specific stock index "//trim(ind_text)//".")
8580 elseif (ns+ns_tot > 1) then
859 call MOM_error(FATAL,"Tracer packages "//trim(pkg_name)//" and "//&
860 trim(set_pkg_name)//" both attempted to set values for "//&
8610 "specific stock index "//trim(ind_text)//".")
862 else
8630 set_pkg_name = pkg_name
864 endif
865 endif
866
8673 if (ns_tot+ns > max_ns) then
8680 write(ns_text,'(I0)') ns_tot+ns ; write(max_text,'(I0)') max_ns
869 call MOM_error(FATAL,"Attempted to return more tracer stock values (at least "//&
870 trim(ns_text)//") than the size "//trim(max_text)//&
8710 "of the smallest value, name, or units array.")
872 endif
873
8746 do n=1,ns
8753 stock_values(ns_tot+n) = values(n)
8763 if (present(stock_names)) stock_names(ns_tot+n) = names(n)
8776 if (present(stock_units)) stock_units(ns_tot+n) = units(n)
878 enddo
8793 ns_tot = ns_tot + ns
880
8813end subroutine store_stocks
882
883!> This subroutine calls all registered tracer packages to enable them to
884!! add to the surface state returned to the coupler. These routines are optional.
88513subroutine call_tracer_surface_state(sfc_state, h, G, GV, US, CS)
886 type(surface), intent(inout) :: sfc_state !< A structure containing fields that
887 !! describe the surface state of the ocean.
888 type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure.
889 type(verticalGrid_type), intent(in) :: GV !< The ocean's vertical grid structure.
890 real, dimension(SZI_(G),SZJ_(G),SZK_(GV)), &
891 intent(in) :: h !< Layer thicknesses [H ~> m or kg m-2]
892 type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
893 type(tracer_flow_control_CS), pointer :: CS !< The control structure returned by a
894 !! previous call to call_tracer_register.
895
89613 if (.not. associated(CS)) call MOM_error(FATAL, "call_tracer_surface_state: "// &
8970 "Module must be initialized via call_tracer_register before it is used.")
898
899! Add other user-provided calls here.
90013 if (CS%use_USER_tracer_example) &
9010 call USER_tracer_surface_state(sfc_state, h, G, GV, CS%USER_tracer_example_CSp)
90213 if (CS%use_DOME_tracer) &
9030 call DOME_tracer_surface_state(sfc_state, h, G, GV, CS%DOME_tracer_CSp)
90413 if (CS%use_ISOMIP_tracer) &
9050 call ISOMIP_tracer_surface_state(sfc_state, h, G, GV, CS%ISOMIP_tracer_CSp)
90613 if (CS%use_ideal_age) &
90713 call ideal_age_tracer_surface_state(sfc_state, h, G, GV, CS%ideal_age_tracer_CSp)
90813 if (CS%use_MARBL_tracers) &
9090 call MARBL_tracers_surface_state(sfc_state, G, US, CS%MARBL_tracers_CSp)
91013 if (CS%use_regional_dyes) &
9110 call dye_tracer_surface_state(sfc_state, h, G, GV, CS%dye_tracer_CSp)
91213 if (CS%use_oil) &
9130 call oil_tracer_surface_state(sfc_state, h, G, GV, CS%oil_tracer_CSp)
91413 if (CS%use_advection_test_tracer) &
9150 call advection_test_tracer_surface_state(sfc_state, h, G, GV, CS%advection_test_tracer_CSp)
91613 if (CS%use_OCMIP2_CFC) &
9170 call OCMIP2_CFC_surface_state(sfc_state, h, G, GV, US, CS%OCMIP2_CFC_CSp)
91813 if (CS%use_MOM_generic_tracer) &
9190 call MOM_generic_tracer_surface_state(sfc_state, h, G, GV, CS%MOM_generic_tracer_CSp)
920
92113end subroutine call_tracer_surface_state
922
9231subroutine tracer_flow_control_end(CS)
924 type(tracer_flow_control_CS), pointer :: CS !< The control structure returned by a
925 !! previous call to call_tracer_register.
926
9271 if (CS%use_USER_tracer_example) &
9280 call USER_tracer_example_end(CS%USER_tracer_example_CSp)
9291 if (CS%use_DOME_tracer) call DOME_tracer_end(CS%DOME_tracer_CSp)
9301 if (CS%use_ISOMIP_tracer) call ISOMIP_tracer_end(CS%ISOMIP_tracer_CSp)
9311 if (CS%use_RGC_tracer) call RGC_tracer_end(CS%RGC_tracer_CSp)
9321 if (CS%use_ideal_age) call ideal_age_example_end(CS%ideal_age_tracer_CSp)
9331 if (CS%use_MARBL_tracers) call MARBL_tracers_end(CS%MARBL_tracers_CSp)
9341 if (CS%use_regional_dyes) call regional_dyes_end(CS%dye_tracer_CSp)
9351 if (CS%use_oil) call oil_tracer_end(CS%oil_tracer_CSp)
9361 if (CS%use_advection_test_tracer) call advection_test_tracer_end(CS%advection_test_tracer_CSp)
9371 if (CS%use_OCMIP2_CFC) call OCMIP2_CFC_end(CS%OCMIP2_CFC_CSp)
9381 if (CS%use_CFC_cap) call CFC_cap_end(CS%CFC_cap_CSp)
9391 if (CS%use_MOM_generic_tracer) call end_MOM_generic_tracer(CS%MOM_generic_tracer_CSp)
9401 if (CS%use_pseudo_salt_tracer) call pseudo_salt_tracer_end(CS%pseudo_salt_tracer_CSp)
9411 if (CS%use_boundary_impulse_tracer) call boundary_impulse_tracer_end(CS%boundary_impulse_tracer_CSp)
9421 if (CS%use_dyed_obc_tracer) call dyed_obc_tracer_end(CS%dyed_obc_tracer_CSp)
9431 if (CS%use_nw2_tracers) call nw2_tracers_end(CS%nw2_tracers_CSp)
944
9451 if (associated(CS)) deallocate(CS)
9461end subroutine tracer_flow_control_end
947
948!> \namespace MOM_tracer_flow_control
949!!
950!! By Will Cooke, April 2003
951!! Edited by Elizabeth Yankovsky, May 2019
952!!
953!! This module contains two subroutines into which calls to other
954!! tracer initialization (call_tracer_init_fns) and column physics
955!! routines (call_tracer_column_fns) can be inserted.
956!!
9570end module MOM_tracer_flow_control