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 | |
| 6 | module MOM_tracer_flow_control | |
| 7 | ||
| 8 | use MOM_coms, only : EFP_type, assignment(=), EFP_to_real, real_to_EFP, EFP_sum_across_PEs | |
| 9 | use MOM_diag_mediator, only : time_type, diag_ctrl | |
| 10 | use MOM_error_handler, only : MOM_error, FATAL, WARNING | |
| 11 | use MOM_file_parser, only : get_param, log_version, param_file_type, close_param_file | |
| 12 | use MOM_forcing_type, only : forcing, optics_type | |
| 13 | use MOM_get_input, only : Get_MOM_input | |
| 14 | use MOM_grid, only : ocean_grid_type | |
| 15 | use MOM_hor_index, only : hor_index_type | |
| 16 | use MOM_interface_heights, only : convert_MLD_to_ML_thickness | |
| 17 | use MOM_CVMix_KPP, only : KPP_CS | |
| 18 | use MOM_open_boundary, only : ocean_OBC_type | |
| 19 | use MOM_restart, only : MOM_restart_CS | |
| 20 | use MOM_sponge, only : sponge_CS | |
| 21 | use MOM_ALE_sponge, only : ALE_sponge_CS | |
| 22 | use MOM_tracer_registry, only : tracer_registry_type | |
| 23 | use MOM_unit_scaling, only : unit_scale_type | |
| 24 | use MOM_variables, only : surface, thermo_var_ptrs | |
| 25 | use MOM_verticalGrid, only : verticalGrid_type | |
| 26 | #include <MOM_memory.h> | |
| 27 | ||
| 28 | ! Add references to other user-provide tracer modules here. | |
| 29 | use USER_tracer_example, only : tracer_column_physics, USER_initialize_tracer, USER_tracer_stock | |
| 30 | use USER_tracer_example, only : USER_register_tracer_example, USER_tracer_surface_state | |
| 31 | use USER_tracer_example, only : USER_tracer_example_end, USER_tracer_example_CS | |
| 32 | use DOME_tracer, only : register_DOME_tracer, initialize_DOME_tracer | |
| 33 | use DOME_tracer, only : DOME_tracer_column_physics, DOME_tracer_surface_state | |
| 34 | use DOME_tracer, only : DOME_tracer_end, DOME_tracer_CS | |
| 35 | use ISOMIP_tracer, only : register_ISOMIP_tracer, initialize_ISOMIP_tracer | |
| 36 | use ISOMIP_tracer, only : ISOMIP_tracer_column_physics, ISOMIP_tracer_surface_state | |
| 37 | use ISOMIP_tracer, only : ISOMIP_tracer_end, ISOMIP_tracer_CS | |
| 38 | use RGC_tracer, only : register_RGC_tracer, initialize_RGC_tracer | |
| 39 | use RGC_tracer, only : RGC_tracer_column_physics | |
| 40 | use RGC_tracer, only : RGC_tracer_end, RGC_tracer_CS | |
| 41 | use ideal_age_example, only : register_ideal_age_tracer, initialize_ideal_age_tracer | |
| 42 | use ideal_age_example, only : ideal_age_tracer_column_physics, ideal_age_tracer_surface_state | |
| 43 | use ideal_age_example, only : ideal_age_stock, ideal_age_example_end, ideal_age_tracer_CS | |
| 44 | use MARBL_tracers, only : register_MARBL_tracers, initialize_MARBL_tracers | |
| 45 | use MARBL_tracers, only : MARBL_tracers_column_physics, MARBL_tracers_set_forcing | |
| 46 | use MARBL_tracers, only : MARBL_tracers_surface_state, MARBL_tracers_get | |
| 47 | use MARBL_tracers, only : MARBL_tracers_stock, MARBL_tracers_end, MARBL_tracers_CS | |
| 48 | use regional_dyes, only : register_dye_tracer, initialize_dye_tracer | |
| 49 | use regional_dyes, only : dye_tracer_column_physics, dye_tracer_surface_state | |
| 50 | use regional_dyes, only : dye_stock, regional_dyes_end, dye_tracer_CS | |
| 51 | use MOM_OCMIP2_CFC, only : register_OCMIP2_CFC, initialize_OCMIP2_CFC, flux_init_OCMIP2_CFC | |
| 52 | use MOM_OCMIP2_CFC, only : OCMIP2_CFC_column_physics, OCMIP2_CFC_surface_state | |
| 53 | use MOM_OCMIP2_CFC, only : OCMIP2_CFC_stock, OCMIP2_CFC_end, OCMIP2_CFC_CS | |
| 54 | use MOM_CFC_cap, only : register_CFC_cap, initialize_CFC_cap | |
| 55 | use MOM_CFC_cap, only : CFC_cap_column_physics, CFC_cap_set_forcing | |
| 56 | use MOM_CFC_cap, only : CFC_cap_stock, CFC_cap_end, CFC_cap_CS | |
| 57 | use oil_tracer, only : register_oil_tracer, initialize_oil_tracer | |
| 58 | use oil_tracer, only : oil_tracer_column_physics, oil_tracer_surface_state | |
| 59 | use oil_tracer, only : oil_stock, oil_tracer_end, oil_tracer_CS | |
| 60 | use advection_test_tracer, only : register_advection_test_tracer, initialize_advection_test_tracer | |
| 61 | use advection_test_tracer, only : advection_test_tracer_column_physics, advection_test_tracer_surface_state | |
| 62 | use advection_test_tracer, only : advection_test_stock, advection_test_tracer_end, advection_test_tracer_CS | |
| 63 | use dyed_obc_tracer, only : register_dyed_obc_tracer, initialize_dyed_obc_tracer | |
| 64 | use dyed_obc_tracer, only : dyed_obc_tracer_column_physics | |
| 65 | use dyed_obc_tracer, only : dyed_obc_tracer_end, dyed_obc_tracer_CS | |
| 66 | use MOM_generic_tracer, only : register_MOM_generic_tracer, initialize_MOM_generic_tracer | |
| 67 | use MOM_generic_tracer, only : MOM_generic_tracer_column_physics, MOM_generic_tracer_surface_state | |
| 68 | use MOM_generic_tracer, only : end_MOM_generic_tracer, MOM_generic_tracer_get, MOM_generic_flux_init | |
| 69 | use MOM_generic_tracer, only : MOM_generic_tracer_stock, MOM_generic_tracer_min_max, MOM_generic_tracer_CS | |
| 70 | use MOM_generic_tracer, only : register_MOM_generic_tracer_segments | |
| 71 | use pseudo_salt_tracer, only : register_pseudo_salt_tracer, initialize_pseudo_salt_tracer | |
| 72 | use pseudo_salt_tracer, only : pseudo_salt_tracer_column_physics, pseudo_salt_tracer_surface_state | |
| 73 | use pseudo_salt_tracer, only : pseudo_salt_stock, pseudo_salt_tracer_end, pseudo_salt_tracer_CS | |
| 74 | use boundary_impulse_tracer, only : register_boundary_impulse_tracer, initialize_boundary_impulse_tracer | |
| 75 | use boundary_impulse_tracer, only : boundary_impulse_tracer_column_physics, boundary_impulse_tracer_surface_state | |
| 76 | use boundary_impulse_tracer, only : boundary_impulse_stock, boundary_impulse_tracer_end | |
| 77 | use boundary_impulse_tracer, only : boundary_impulse_tracer_CS | |
| 78 | use nw2_tracers, only : nw2_tracers_CS, register_nw2_tracers, nw2_tracer_column_physics | |
| 79 | use nw2_tracers, only : initialize_nw2_tracers, nw2_tracers_end | |
| 80 | ||
| 81 | implicit none ; private | |
| 82 | ||
| 83 | public call_tracer_register, tracer_flow_control_init, call_tracer_set_forcing | |
| 84 | public call_tracer_column_fns, call_tracer_surface_state, call_tracer_stocks | |
| 85 | public call_tracer_flux_init, get_chl_from_model, tracer_flow_control_end | |
| 86 | public call_tracer_register_obc_segments | |
| 87 | ||
| 88 | !> The control structure for orchestrating the calling of tracer packages | |
| 89 | type, 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 | !>@} | |
| 125 | end type tracer_flow_control_CS | |
| 126 | ||
| 127 | contains | |
| 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 | |
| 136 | 0 | subroutine call_tracer_flux_init(verbosity) |
| 137 | integer, optional, intent(in) :: verbosity !< A 0-9 integer indicating a level of verbosity. | |
| 138 | ||
| 139 | 0 | 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. | |
| 145 | 0 | call get_MOM_Input(param_file, check_params=.false.) |
| 146 | ||
| 147 | call get_param(param_file, mdl, "USE_OCMIP2_CFC", use_OCMIP_CFCs, & | |
| 148 | 0 | default=.false., do_not_log=.true.) |
| 149 | call get_param(param_file, mdl, "USE_generic_tracer", use_MOM_generic_tracer,& | |
| 150 | 0 | default=.false., do_not_log=.true.) |
| 151 | 0 | call close_param_file(param_file, quiet_close=.true.) |
| 152 | ||
| 153 | 0 | if (use_OCMIP_CFCs) call flux_init_OCMIP2_CFC(verbosity=verbosity) |
| 154 | 0 | if (use_MOM_generic_tracer) then |
| 155 | 0 | call MOM_generic_flux_init(verbosity=verbosity) |
| 156 | endif | |
| 157 | ||
| 158 | 0 | end 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. | |
| 165 | 1 | subroutine 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 | ||
| 183 | 1 | if (associated(CS)) then |
| 184 | call MOM_error(WARNING, "call_tracer_register called with an associated "// & | |
| 185 | 0 | "control structure.") |
| 186 | 0 | return |
| 187 | 1 | else ; allocate(CS) ; endif |
| 188 | ||
| 189 | ! Read all relevant parameters and write them to the model log. | |
| 190 | 1 | 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.", & | |
| 193 | 1 | 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.", & | |
| 196 | 1 | 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.", & | |
| 199 | 1 | 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.", & | |
| 202 | 1 | 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.", & | |
| 205 | 1 | default=.false.) |
| 206 | call get_param(param_file, mdl, "USE_MARBL_TRACERS", CS%use_marbl_tracers, & | |
| 207 | "If true, use the MARBL tracer package.", & | |
| 208 | 1 | 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.", & | |
| 211 | 1 | default=.false.) |
| 212 | call get_param(param_file, mdl, "USE_OIL_TRACER", CS%use_oil, & | |
| 213 | "If true, use the oil_tracer tracer package.", & | |
| 214 | 1 | 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.", & | |
| 217 | 1 | 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.", & | |
| 220 | 1 | 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.", & | |
| 223 | 1 | 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.", & | |
| 227 | 1 | 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.", & | |
| 230 | 1 | 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.", & | |
| 233 | 1 | 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.", & | |
| 236 | 1 | default=.false.) |
| 237 | call get_param(param_file, mdl, "USE_NW2_TRACERS", CS%use_nw2_tracers, & | |
| 238 | "If true, use the NeverWorld2 tracers.", & | |
| 239 | 1 | 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. | |
| 244 | 1 | 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, & | |
| 246 | 0 | tr_Reg, restart_CS) |
| 247 | 1 | if (CS%use_DOME_tracer) CS%use_DOME_tracer = & |
| 248 | register_DOME_tracer(G, GV, US, param_file, CS%DOME_tracer_CSp, & | |
| 249 | 0 | tr_Reg, restart_CS) |
| 250 | 1 | if (CS%use_ISOMIP_tracer) CS%use_ISOMIP_tracer = & |
| 251 | register_ISOMIP_tracer(G%HI, GV, param_file, CS%ISOMIP_tracer_CSp, & | |
| 252 | 0 | tr_Reg, restart_CS) |
| 253 | 1 | if (CS%use_RGC_tracer) CS%use_RGC_tracer = & |
| 254 | register_RGC_tracer(G, GV, param_file, CS%RGC_tracer_CSp, & | |
| 255 | 0 | tr_Reg, restart_CS) |
| 256 | 1 | if (CS%use_ideal_age) CS%use_ideal_age = & |
| 257 | register_ideal_age_tracer(G%HI, GV, param_file, CS%ideal_age_tracer_CSp, & | |
| 258 | 1 | tr_Reg, restart_CS) |
| 259 | 1 | if (CS%use_MARBL_tracers) CS%use_MARBL_tracers = & |
| 260 | register_MARBL_tracers(G%HI, GV, US, param_file, CS%MARBL_tracers_CSp, & | |
| 261 | 0 | tr_Reg, restart_CS, CS%get_chl_from_MARBL) |
| 262 | 1 | if (CS%use_regional_dyes) CS%use_regional_dyes = & |
| 263 | register_dye_tracer(G%HI, GV, US, param_file, CS%dye_tracer_CSp, & | |
| 264 | 0 | tr_Reg, restart_CS) |
| 265 | 1 | if (CS%use_oil) CS%use_oil = & |
| 266 | register_oil_tracer(G%HI, GV, US, param_file, CS%oil_tracer_CSp, & | |
| 267 | 0 | tr_Reg, restart_CS) |
| 268 | 1 | 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, & | |
| 270 | 0 | tr_Reg, restart_CS) |
| 271 | 1 | if (CS%use_OCMIP2_CFC) CS%use_OCMIP2_CFC = & |
| 272 | register_OCMIP2_CFC(G%HI, GV, param_file, CS%OCMIP2_CFC_CSp, & | |
| 273 | 0 | tr_Reg, restart_CS) |
| 274 | 1 | if (CS%use_CFC_cap) CS%use_CFC_cap = & |
| 275 | register_CFC_cap(G%HI, GV, param_file, CS%CFC_cap_CSp, & | |
| 276 | 0 | tr_Reg, restart_CS) |
| 277 | 1 | 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, & | |
| 279 | 0 | tr_Reg, restart_CS) |
| 280 | 1 | 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, & | |
| 282 | 0 | tr_Reg, restart_CS) |
| 283 | 1 | 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, & | |
| 285 | 0 | tr_Reg, restart_CS) |
| 286 | 1 | 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, & | |
| 288 | 0 | tr_Reg, restart_CS) |
| 289 | 1 | if (CS%use_nw2_tracers) CS%use_nw2_tracers = & |
| 290 | 0 | register_nw2_tracers(G%HI, GV, US, param_file, CS%nw2_tracers_CSp, tr_Reg, restart_CS) |
| 291 | ||
| 292 | end subroutine call_tracer_register | |
| 293 | ||
| 294 | !> This subroutine calls all registered tracer initialization | |
| 295 | !! subroutines. | |
| 296 | 1 | subroutine 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 | ||
| 327 | 1 | if (.not. associated(CS)) call MOM_error(FATAL, "tracer_flow_control_init: "// & |
| 328 | 0 | "Module must be initialized via call_tracer_register before it is used.") |
| 329 | ||
| 330 | ! Add other user-provided calls here. | |
| 331 | 1 | if (CS%use_USER_tracer_example) & |
| 332 | call USER_initialize_tracer(restart, day, G, GV, US, h, diag, OBC, CS%USER_tracer_example_CSp, & | |
| 333 | 0 | sponge_CSp) |
| 334 | 1 | if (CS%use_DOME_tracer) & |
| 335 | call initialize_DOME_tracer(restart, day, G, GV, US, h, diag, OBC, CS%DOME_tracer_CSp, & | |
| 336 | 0 | sponge_CSp, tv) |
| 337 | 1 | if (CS%use_ISOMIP_tracer) & |
| 338 | call initialize_ISOMIP_tracer(restart, day, G, GV, h, diag, OBC, CS%ISOMIP_tracer_CSp, & | |
| 339 | 0 | ALE_sponge_CSp) |
| 340 | 1 | if (CS%use_RGC_tracer) & |
| 341 | call initialize_RGC_tracer(restart, day, G, GV, h, diag, OBC, CS%RGC_tracer_CSp, & | |
| 342 | 0 | sponge_CSp, ALE_sponge_CSp) |
| 343 | 1 | if (CS%use_ideal_age) & |
| 344 | call initialize_ideal_age_tracer(restart, day, G, GV, US, h, diag, OBC, CS%ideal_age_tracer_CSp, & | |
| 345 | 1 | sponge_CSp) |
| 346 | 1 | if (CS%use_MARBL_tracers) & |
| 347 | call initialize_MARBL_tracers(restart, day, G, GV, US, h, param_file, diag, OBC, CS%MARBL_tracers_CSp, & | |
| 348 | 0 | sponge_CSp) |
| 349 | 1 | if (CS%use_regional_dyes) & |
| 350 | 0 | call initialize_dye_tracer(restart, day, G, GV, US, h, diag, OBC, CS%dye_tracer_CSp, sponge_CSp, tv) |
| 351 | 1 | if (CS%use_oil) & |
| 352 | 0 | call initialize_oil_tracer(restart, day, G, GV, US, h, diag, OBC, CS%oil_tracer_CSp, sponge_CSp) |
| 353 | 1 | if (CS%use_advection_test_tracer) & |
| 354 | call initialize_advection_test_tracer(restart, day, G, GV, h, diag, OBC, CS%advection_test_tracer_CSp, & | |
| 355 | 0 | sponge_CSp) |
| 356 | 1 | if (CS%use_OCMIP2_CFC) & |
| 357 | 0 | call initialize_OCMIP2_CFC(restart, day, G, GV, US, h, diag, OBC, CS%OCMIP2_CFC_CSp, sponge_CSp) |
| 358 | 1 | if (CS%use_CFC_cap) & |
| 359 | 0 | call initialize_CFC_cap(restart, day, G, GV, US, h, diag, OBC, CS%CFC_cap_CSp) |
| 360 | ||
| 361 | 1 | if (CS%use_MOM_generic_tracer) & |
| 362 | call initialize_MOM_generic_tracer(restart, day, G, GV, US, h, tv, param_file, diag, OBC, & | |
| 363 | 0 | CS%MOM_generic_tracer_CSp, sponge_CSp, ALE_sponge_CSp) |
| 364 | 1 | 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, & | |
| 366 | 0 | sponge_CSp, tv) |
| 367 | 1 | 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, & | |
| 369 | 0 | sponge_CSp, tv) |
| 370 | 1 | if (CS%use_dyed_obc_tracer) & |
| 371 | 0 | call initialize_dyed_obc_tracer(restart, day, G, GV, h, diag, OBC, CS%dyed_obc_tracer_CSp) |
| 372 | 1 | if (CS%use_nw2_tracers) & |
| 373 | 0 | call initialize_nw2_tracers(restart, day, G, GV, US, h, tv, diag, CS%nw2_tracers_CSp) |
| 374 | ||
| 375 | 1 | end 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 | |
| 379 | 0 | subroutine 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 | ||
| 393 | 0 | if (CS%use_MOM_generic_tracer) & |
| 394 | 0 | call register_MOM_generic_tracer_segments(CS%MOM_generic_tracer_CSp, GV, OBC, tr_Reg, param_file) |
| 395 | ||
| 396 | 0 | end subroutine call_tracer_register_obc_segments |
| 397 | ||
| 398 | !> This subroutine extracts the chlorophyll concentrations from the model state, if possible | |
| 399 | 0 | subroutine 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 | ||
| 408 | 0 | if (CS%get_chl_from_MARBL) then |
| 409 | 0 | call MARBL_tracers_get('Chl', G, GV, Chl_array, CS%MARBL_tracers_CSp) |
| 410 | 0 | elseif (CS%use_MOM_generic_tracer) then |
| 411 | 0 | 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"// & | |
| 415 | 0 | "CS%use_MOM_generic_tracer is false and no other viable options are on.") |
| 416 | endif | |
| 417 | ||
| 418 | 0 | end 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. | |
| 422 | 12 | subroutine 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 | ||
| 439 | 12 | if (.not. associated(CS)) call MOM_error(FATAL, "call_tracer_set_forcing: "// & |
| 440 | 0 | "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) | |
| 444 | 12 | if (CS%use_CFC_cap) & |
| 445 | call CFC_cap_set_forcing(sfc_state, fluxes, day_start, day_interval, G, US, Rho0, & | |
| 446 | 0 | CS%CFC_cap_CSp) |
| 447 | ||
| 448 | 12 | if (CS%use_MARBL_tracers) & |
| 449 | 0 | call MARBL_tracers_set_forcing(day_start, G, CS%MARBL_tracers_CSp) |
| 450 | ||
| 451 | 12 | end subroutine call_tracer_set_forcing |
| 452 | ||
| 453 | !> This subroutine calls all registered tracer column physics subroutines. | |
| 454 | 12 | subroutine call_tracer_column_fns(h_old, h_new, ea, eb, fluxes, mld, dt, G, GV, US, tv, optics, CS, & |
| 455 | 12 | 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 | |
| 493 | 24 | real :: Hbl(SZI_(G),SZJ_(G)) !< Boundary layer thickness [H ~> m or kg m-2] |
| 494 | logical :: use_h_BL | |
| 495 | ||
| 496 | 12 | if (.not. associated(CS)) call MOM_error(FATAL, "call_tracer_column_fns: "// & |
| 497 | 0 | "Module must be initialized via call_tracer_register before it is used.") |
| 498 | ||
| 499 | ! Use the applyTracerBoundaryFluxesInOut to handle surface fluxes | |
| 500 | 12 | if (present(evap_CFL_limit) .and. present(minimum_forcing_depth)) then |
| 501 | ! Add calls to tracer column functions here. | |
| 502 | 12 | if (CS%use_USER_tracer_example) & |
| 503 | call tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & | |
| 504 | 0 | G, GV, US, CS%USER_tracer_example_CSp) |
| 505 | 12 | 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, & | |
| 509 | 0 | minimum_forcing_depth=minimum_forcing_depth) |
| 510 | 12 | 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, & | |
| 514 | 0 | minimum_forcing_depth=minimum_forcing_depth) |
| 515 | 12 | 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, & | |
| 519 | 0 | minimum_forcing_depth=minimum_forcing_depth) |
| 520 | 12 | if (CS%use_ideal_age) then |
| 521 | 12 | use_h_BL = .false. ; if (present(h_BL)) use_h_BL = associated(h_BL) |
| 522 | 12 | if (present(h_BL)) then |
| 523 | 105276 | Hbl(:,:) = h_BL(:,:) |
| 524 | else ! This option is here mostly to support the offline tracers. | |
| 525 | 0 | 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, & | |
| 530 | 12 | minimum_forcing_depth=minimum_forcing_depth, Hbl=Hbl) |
| 531 | endif | |
| 532 | 12 | 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, & | |
| 538 | 0 | minimum_forcing_depth=minimum_forcing_depth) |
| 539 | 12 | 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, & | |
| 543 | 0 | minimum_forcing_depth=minimum_forcing_depth) |
| 544 | 12 | 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, & | |
| 548 | 0 | minimum_forcing_depth=minimum_forcing_depth) |
| 549 | ||
| 550 | 12 | 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, & | |
| 554 | 0 | minimum_forcing_depth=minimum_forcing_depth) |
| 555 | 12 | 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, & | |
| 559 | 0 | minimum_forcing_depth=minimum_forcing_depth) |
| 560 | 12 | 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, & | |
| 566 | 0 | minimum_forcing_depth=minimum_forcing_depth) |
| 567 | 12 | if (CS%use_MOM_generic_tracer) then |
| 568 | 0 | 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 "//& | |
| 570 | 0 | "[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, & | |
| 574 | 0 | minimum_forcing_depth=minimum_forcing_depth) |
| 575 | endif | |
| 576 | 12 | 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, & | |
| 583 | 0 | minimum_forcing_depth=minimum_forcing_depth) |
| 584 | 12 | 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, & | |
| 588 | 0 | minimum_forcing_depth=minimum_forcing_depth) |
| 589 | 12 | 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, & | |
| 593 | 0 | minimum_forcing_depth=minimum_forcing_depth) |
| 594 | 12 | 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, & | |
| 598 | 0 | minimum_forcing_depth=minimum_forcing_depth) |
| 599 | else ! Apply tracer surface fluxes using ea on the first layer | |
| 600 | 0 | if (CS%use_USER_tracer_example) & |
| 601 | call tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & | |
| 602 | 0 | G, GV, US, CS%USER_tracer_example_CSp) |
| 603 | 0 | if (CS%use_DOME_tracer) & |
| 604 | call DOME_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & | |
| 605 | 0 | G, GV, US, CS%DOME_tracer_CSp) |
| 606 | 0 | if (CS%use_ISOMIP_tracer) & |
| 607 | call ISOMIP_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & | |
| 608 | 0 | G, GV, US, CS%ISOMIP_tracer_CSp) |
| 609 | 0 | if (CS%use_RGC_tracer) & |
| 610 | call RGC_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & | |
| 611 | 0 | G, GV, US, CS%RGC_tracer_CSp) |
| 612 | 0 | if (CS%use_ideal_age) then |
| 613 | 0 | use_h_BL = .false. ; if (present(h_BL)) use_h_BL = associated(h_BL) |
| 614 | 0 | if (present(h_BL)) then |
| 615 | 0 | Hbl(:,:) = h_BL(:,:) |
| 616 | else ! This option is here mostly to support the offline tracers. | |
| 617 | 0 | 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, & | |
| 620 | 0 | G, GV, US, CS%ideal_age_tracer_CSp, Hbl=Hbl) |
| 621 | endif | |
| 622 | 0 | 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, & | |
| 626 | 0 | nonLocalTrans=nonLocalTrans) |
| 627 | 0 | if (CS%use_regional_dyes) & |
| 628 | call dye_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & | |
| 629 | 0 | G, GV, US, tv, CS%dye_tracer_CSp) |
| 630 | 0 | if (CS%use_oil) & |
| 631 | call oil_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & | |
| 632 | 0 | G, GV, US, CS%oil_tracer_CSp, tv) |
| 633 | 0 | if (CS%use_advection_test_tracer) & |
| 634 | call advection_test_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & | |
| 635 | 0 | G, GV, US, CS%advection_test_tracer_CSp) |
| 636 | 0 | if (CS%use_OCMIP2_CFC) & |
| 637 | call OCMIP2_CFC_column_physics(h_old, h_new, ea, eb, fluxes, dt, & | |
| 638 | 0 | G, GV, US, CS%OCMIP2_CFC_CSp) |
| 639 | 0 | 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, & | |
| 643 | 0 | nonLocalTrans=nonLocalTrans) |
| 644 | 0 | if (CS%use_MOM_generic_tracer) then |
| 645 | 0 | 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 "//& | |
| 647 | 0 | "[QRZT]_RESCALE_POWER parameters to 0.") |
| 648 | call MOM_generic_tracer_column_physics(h_old, h_new, ea, eb, fluxes, mld, dt, & | |
| 649 | 0 | G, GV, US, CS%MOM_generic_tracer_CSp, tv, optics) |
| 650 | endif | |
| 651 | 0 | 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, & | |
| 656 | 0 | nonLocalTrans=nonLocalTrans) |
| 657 | 0 | if (CS%use_boundary_impulse_tracer) & |
| 658 | call boundary_impulse_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & | |
| 659 | 0 | G, GV, US, CS%boundary_impulse_tracer_CSp, tv, debug) |
| 660 | 0 | if (CS%use_dyed_obc_tracer) & |
| 661 | call dyed_obc_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & | |
| 662 | 0 | G, GV, US, CS%dyed_obc_tracer_CSp) |
| 663 | 0 | if (CS%use_nw2_tracers) call nw2_tracer_column_physics(h_old, h_new, ea, eb, fluxes, dt, & |
| 664 | 0 | G, GV, US, tv, CS%nw2_tracers_CSp) |
| 665 | endif | |
| 666 | ||
| 667 | 12 | end 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. | |
| 671 | 3 | subroutine call_tracer_stocks(h, stock_values, G, GV, US, CS, stock_names, stock_units, & |
| 672 | 3 | num_stocks, stock_index, got_min_max, global_min, global_max, & |
| 673 | 3 | 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 | ||
| 719 | 3 | if (.not. associated(CS)) call MOM_error(FATAL, "call_tracer_stocks: "// & |
| 720 | 0 | "Module must be initialized via call_tracer_register before it is used.") |
| 721 | ||
| 722 | 3 | index = -1 ; if (present(stock_index)) index = stock_index |
| 723 | 3 | ns_tot = 0 |
| 724 | 3 | max_ns = size(stock_values) |
| 725 | 3 | if (present(stock_names)) max_ns = min(max_ns,size(stock_names)) |
| 726 | 3 | if (present(stock_units)) max_ns = min(max_ns,size(stock_units)) |
| 727 | ||
| 728 | ! Add other user-provided calls here. | |
| 729 | 3 | if (CS%use_USER_tracer_example) then |
| 730 | ns = USER_tracer_stock(h, values_EFP, G, GV, CS%USER_tracer_example_CSp, & | |
| 731 | 0 | names, units, stock_index) |
| 732 | call store_stocks("tracer_example", ns, names, units, values_EFP, index, stock_val_EFP, & | |
| 733 | 0 | 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 | |
| 742 | 3 | if (CS%use_ideal_age) then |
| 743 | ns = ideal_age_stock(h, values_EFP, G, GV, CS%ideal_age_tracer_CSp, & | |
| 744 | 3 | names, units, stock_index) |
| 745 | call store_stocks("ideal_age_example", ns, names, units, values_EFP, index, stock_val_EFP, & | |
| 746 | 3 | set_pkg_name, max_ns, ns_tot, stock_names, stock_units) |
| 747 | endif | |
| 748 | 3 | if (CS%use_MARBL_tracers) then |
| 749 | ns = MARBL_tracers_stock(h, values_EFP, G, GV, CS%MARBL_tracers_CSp, & | |
| 750 | 0 | names, units, stock_index) |
| 751 | call store_stocks("MARBL_tracers", ns, names, units, values_EFP, index, stock_val_EFP, & | |
| 752 | 0 | set_pkg_name, max_ns, ns_tot, stock_names, stock_units) |
| 753 | endif | |
| 754 | 3 | if (CS%use_regional_dyes) then |
| 755 | 0 | 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, & | |
| 757 | 0 | set_pkg_name, max_ns, ns_tot, stock_names, stock_units) |
| 758 | endif | |
| 759 | 3 | if (CS%use_oil) then |
| 760 | 0 | 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, & | |
| 762 | 0 | set_pkg_name, max_ns, ns_tot, stock_names, stock_units) |
| 763 | endif | |
| 764 | 3 | if (CS%use_OCMIP2_CFC) then |
| 765 | 0 | 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, & | |
| 767 | 0 | set_pkg_name, max_ns, ns_tot, stock_names, stock_units) |
| 768 | endif | |
| 769 | ||
| 770 | 3 | if (CS%use_CFC_cap) then |
| 771 | 0 | 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, & | |
| 773 | 0 | set_pkg_name, max_ns, ns_tot, stock_names, stock_units) |
| 774 | endif | |
| 775 | ||
| 776 | 3 | if (CS%use_advection_test_tracer) then |
| 777 | ns = advection_test_stock( h, values_EFP, G, GV, CS%advection_test_tracer_CSp, & | |
| 778 | 0 | 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, & | |
| 781 | 0 | set_pkg_name, max_ns, ns_tot, stock_names, stock_units) |
| 782 | endif | |
| 783 | ||
| 784 | 3 | if (CS%use_MOM_generic_tracer) then |
| 785 | ns = MOM_generic_tracer_stock(h, values_EFP, G, GV, CS%MOM_generic_tracer_CSp, & | |
| 786 | 0 | names, units, stock_index) |
| 787 | call store_stocks("MOM_generic_tracer", ns, names, units, values_EFP, index, stock_val_EFP, & | |
| 788 | 0 | set_pkg_name, max_ns, ns_tot, stock_names, stock_units) |
| 789 | 0 | nn=ns_tot-ns+1 |
| 790 | 0 | 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, & | |
| 793 | 0 | xgmin, ygmin, zgmin, xgmax, ygmax, zgmax) |
| 794 | ||
| 795 | endif | |
| 796 | 3 | if (CS%use_pseudo_salt_tracer) then |
| 797 | ns = pseudo_salt_stock(h, values_EFP, G, GV, CS%pseudo_salt_tracer_CSp, & | |
| 798 | 0 | names, units, stock_index) |
| 799 | call store_stocks("pseudo_salt_tracer", ns, names, units, values_EFP, index, stock_val_EFP, & | |
| 800 | 0 | set_pkg_name, max_ns, ns_tot, stock_names, stock_units) |
| 801 | endif | |
| 802 | ||
| 803 | 3 | if (CS%use_boundary_impulse_tracer) then |
| 804 | ns = boundary_impulse_stock(h, values_EFP, G, GV, CS%boundary_impulse_tracer_CSp, & | |
| 805 | 0 | names, units, stock_index) |
| 806 | call store_stocks("boundary_impulse_tracer", ns, names, units, values_EFP, index, stock_val_EFP, & | |
| 807 | 0 | set_pkg_name, max_ns, ns_tot, stock_names, stock_units) |
| 808 | endif | |
| 809 | ||
| 810 | ! Sum the various quantities across all the processors. | |
| 811 | 3 | if (ns_tot > 0) then |
| 812 | 3 | call EFP_sum_across_PEs(stock_val_EFP, ns_tot) |
| 813 | 6 | do n=1,ns_tot ; stock_values(n) = EFP_to_real(stock_val_EFP(n)) ; enddo |
| 814 | else | |
| 815 | 0 | stock_values(1) = 0.0 |
| 816 | endif | |
| 817 | ||
| 818 | 3 | if (present(num_stocks)) num_stocks = ns_tot |
| 819 | ||
| 820 | 3 | end subroutine call_tracer_stocks |
| 821 | ||
| 822 | !> This routine stores the stocks and does error handling for call_tracer_stocks. | |
| 823 | 9 | subroutine store_stocks(pkg_name, ns, names, units, values, index, stock_values, & |
| 824 | 6 | 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 | ||
| 852 | 3 | if ((index > 0) .and. (ns > 0)) then |
| 853 | 0 | write(ind_text,'(I0)') index |
| 854 | 0 | 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 "//& | |
| 857 | 0 | "for specific stock index "//trim(ind_text)//".") |
| 858 | 0 | 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 "//& | |
| 861 | 0 | "specific stock index "//trim(ind_text)//".") |
| 862 | else | |
| 863 | 0 | set_pkg_name = pkg_name |
| 864 | endif | |
| 865 | endif | |
| 866 | ||
| 867 | 3 | if (ns_tot+ns > max_ns) then |
| 868 | 0 | 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)//& | |
| 871 | 0 | "of the smallest value, name, or units array.") |
| 872 | endif | |
| 873 | ||
| 874 | 6 | do n=1,ns |
| 875 | 3 | stock_values(ns_tot+n) = values(n) |
| 876 | 3 | if (present(stock_names)) stock_names(ns_tot+n) = names(n) |
| 877 | 6 | if (present(stock_units)) stock_units(ns_tot+n) = units(n) |
| 878 | enddo | |
| 879 | 3 | ns_tot = ns_tot + ns |
| 880 | ||
| 881 | 3 | end 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. | |
| 885 | 13 | subroutine 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 | ||
| 896 | 13 | if (.not. associated(CS)) call MOM_error(FATAL, "call_tracer_surface_state: "// & |
| 897 | 0 | "Module must be initialized via call_tracer_register before it is used.") |
| 898 | ||
| 899 | ! Add other user-provided calls here. | |
| 900 | 13 | if (CS%use_USER_tracer_example) & |
| 901 | 0 | call USER_tracer_surface_state(sfc_state, h, G, GV, CS%USER_tracer_example_CSp) |
| 902 | 13 | if (CS%use_DOME_tracer) & |
| 903 | 0 | call DOME_tracer_surface_state(sfc_state, h, G, GV, CS%DOME_tracer_CSp) |
| 904 | 13 | if (CS%use_ISOMIP_tracer) & |
| 905 | 0 | call ISOMIP_tracer_surface_state(sfc_state, h, G, GV, CS%ISOMIP_tracer_CSp) |
| 906 | 13 | if (CS%use_ideal_age) & |
| 907 | 13 | call ideal_age_tracer_surface_state(sfc_state, h, G, GV, CS%ideal_age_tracer_CSp) |
| 908 | 13 | if (CS%use_MARBL_tracers) & |
| 909 | 0 | call MARBL_tracers_surface_state(sfc_state, G, US, CS%MARBL_tracers_CSp) |
| 910 | 13 | if (CS%use_regional_dyes) & |
| 911 | 0 | call dye_tracer_surface_state(sfc_state, h, G, GV, CS%dye_tracer_CSp) |
| 912 | 13 | if (CS%use_oil) & |
| 913 | 0 | call oil_tracer_surface_state(sfc_state, h, G, GV, CS%oil_tracer_CSp) |
| 914 | 13 | if (CS%use_advection_test_tracer) & |
| 915 | 0 | call advection_test_tracer_surface_state(sfc_state, h, G, GV, CS%advection_test_tracer_CSp) |
| 916 | 13 | if (CS%use_OCMIP2_CFC) & |
| 917 | 0 | call OCMIP2_CFC_surface_state(sfc_state, h, G, GV, US, CS%OCMIP2_CFC_CSp) |
| 918 | 13 | if (CS%use_MOM_generic_tracer) & |
| 919 | 0 | call MOM_generic_tracer_surface_state(sfc_state, h, G, GV, CS%MOM_generic_tracer_CSp) |
| 920 | ||
| 921 | 13 | end subroutine call_tracer_surface_state |
| 922 | ||
| 923 | 1 | subroutine 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 | ||
| 927 | 1 | if (CS%use_USER_tracer_example) & |
| 928 | 0 | call USER_tracer_example_end(CS%USER_tracer_example_CSp) |
| 929 | 1 | if (CS%use_DOME_tracer) call DOME_tracer_end(CS%DOME_tracer_CSp) |
| 930 | 1 | if (CS%use_ISOMIP_tracer) call ISOMIP_tracer_end(CS%ISOMIP_tracer_CSp) |
| 931 | 1 | if (CS%use_RGC_tracer) call RGC_tracer_end(CS%RGC_tracer_CSp) |
| 932 | 1 | if (CS%use_ideal_age) call ideal_age_example_end(CS%ideal_age_tracer_CSp) |
| 933 | 1 | if (CS%use_MARBL_tracers) call MARBL_tracers_end(CS%MARBL_tracers_CSp) |
| 934 | 1 | if (CS%use_regional_dyes) call regional_dyes_end(CS%dye_tracer_CSp) |
| 935 | 1 | if (CS%use_oil) call oil_tracer_end(CS%oil_tracer_CSp) |
| 936 | 1 | if (CS%use_advection_test_tracer) call advection_test_tracer_end(CS%advection_test_tracer_CSp) |
| 937 | 1 | if (CS%use_OCMIP2_CFC) call OCMIP2_CFC_end(CS%OCMIP2_CFC_CSp) |
| 938 | 1 | if (CS%use_CFC_cap) call CFC_cap_end(CS%CFC_cap_CSp) |
| 939 | 1 | if (CS%use_MOM_generic_tracer) call end_MOM_generic_tracer(CS%MOM_generic_tracer_CSp) |
| 940 | 1 | if (CS%use_pseudo_salt_tracer) call pseudo_salt_tracer_end(CS%pseudo_salt_tracer_CSp) |
| 941 | 1 | if (CS%use_boundary_impulse_tracer) call boundary_impulse_tracer_end(CS%boundary_impulse_tracer_CSp) |
| 942 | 1 | if (CS%use_dyed_obc_tracer) call dyed_obc_tracer_end(CS%dyed_obc_tracer_CSp) |
| 943 | 1 | if (CS%use_nw2_tracers) call nw2_tracers_end(CS%nw2_tracers_CSp) |
| 944 | ||
| 945 | 1 | if (associated(CS)) deallocate(CS) |
| 946 | 1 | end 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 | !! | |
| 957 | 0 | end module MOM_tracer_flow_control |