diff --git a/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 b/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 index 808e6d44d9..e58c2796c8 100644 --- a/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 +++ b/config_src/drivers/nuopc_cap/mom_ocean_model_nuopc.F90 @@ -41,7 +41,7 @@ module MOM_ocean_model_nuopc use MOM_time_manager, only : operator(/=), operator(<=), operator(>=) use MOM_time_manager, only : operator(<), real_to_time_type, time_type_to_real use MOM_interpolate, only : time_interp_external_init -use MOM_tracer_flow_control, only : call_tracer_flux_init +use MOM_tracer_flow_control, only : tracer_flow_control_CS, call_tracer_flux_init, call_tracer_set_forcing use MOM_unit_scaling, only : unit_scale_type use MOM_variables, only : surface use MOM_verticalGrid, only : verticalGrid_type @@ -210,6 +210,8 @@ module MOM_ocean_model_nuopc type(marine_ice_CS), pointer :: & marine_ice_CSp => NULL() !< A pointer to the control structure for the !! marine ice effects module. + type(tracer_flow_control_CS), pointer :: & + tracer_flow_CSp => NULL() !< A pointer to the tracer flow control structure type(wave_parameters_CS), pointer, public :: & Waves => NULL() !< A pointer to the surface wave control structure type(surface_forcing_CS), pointer :: & @@ -255,7 +257,6 @@ subroutine ocean_model_init(Ocean_sfc, OS, Time_init, Time_in, gas_fields_ocn, i !! min(HFrz, OBLD), where OBLD is the boundary layer depth. !! If HFrz <= 0 (default), melt potential will not be computed. logical :: use_melt_pot !< If true, allocate melt_potential array - logical :: use_CFC !< If true, allocated arrays for surface CFCs. ! This include declares and sets the variable "version". @@ -283,7 +284,8 @@ subroutine ocean_model_init(Ocean_sfc, OS, Time_init, Time_in, gas_fields_ocn, i call initialize_MOM(OS%Time, Time_init, param_file, OS%dirs, OS%MOM_CSp, & OS%restart_CSp, Time_in, offline_tracer_mode=OS%offline_tracer_mode, & input_restart_file=input_restart_file, & - diag_ptr=OS%diag, count_calls=.true., waves_CSp=OS%Waves) + diag_ptr=OS%diag, count_calls=.true., tracer_flow_CSp=OS%tracer_flow_CSp, & + waves_CSp=OS%Waves) call get_MOM_state_elements(OS%MOM_CSp, G=OS%grid, GV=OS%GV, US=OS%US, C_p=OS%C_p, & C_p_scaled=OS%fluxes%C_p, use_temp=use_temperature) @@ -375,8 +377,6 @@ subroutine ocean_model_init(Ocean_sfc, OS, Time_init, Time_in, gas_fields_ocn, i use_melt_pot=.false. endif - call get_param(param_file, mdl, "USE_CFC_CAP", use_CFC, & - default=.false., do_not_log=.true.) call get_param(param_file, mdl, "USE_WAVES", OS%Use_Waves, & "If true, enables surface wave modules.", default=.false.) @@ -384,7 +384,7 @@ subroutine ocean_model_init(Ocean_sfc, OS, Time_init, Time_in, gas_fields_ocn, i ! vertical integrals, since the related 3-d sums are not negligible in cost. call allocate_surface_state(OS%sfc_state, OS%grid, use_temperature, & do_integrals=.true., gas_fields_ocn=gas_fields_ocn, & - use_meltpot=use_melt_pot, use_cfcs=use_CFC) + use_meltpot=use_melt_pot) call surface_forcing_init(Time_in, OS%grid, OS%US, param_file, OS%diag, & OS%forcing_CSp, OS%restore_salinity, OS%restore_temp, OS%use_waves) @@ -610,6 +610,11 @@ subroutine update_ocean_model(Ice_ocean_boundary, OS, Ocean_sfc, & call finish_MOM_initialization(OS%Time, OS%dirs, OS%MOM_CSp, OS%restart_CSp) endif + if (do_thermo) & + call call_tracer_set_forcing(OS%sfc_state, OS%fluxes, OS%Time, & + real_to_time_type(dt_coupling), OS%grid, OS%US, OS%GV%Rho0, & + OS%tracer_flow_CSp) + call disable_averaging(OS%diag) Master_time = OS%Time ; Time1 = OS%Time diff --git a/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 b/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 index 27324efa56..30c54e6c4f 100644 --- a/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 +++ b/config_src/drivers/nuopc_cap/mom_surface_forcing_nuopc.F90 @@ -26,7 +26,6 @@ module MOM_surface_forcing_nuopc use MOM_grid, only : ocean_grid_type use MOM_interpolate, only : init_external_field, time_interp_external use MOM_interpolate, only : time_interp_external_init -use MOM_CFC_cap, only : CFC_cap_fluxes use MOM_io, only : slasher, write_version_number, MOM_read_data use MOM_io, only : stdout use MOM_restart, only : register_restart_field, restart_init, MOM_restart_CS @@ -129,7 +128,6 @@ module MOM_surface_forcing_nuopc type(diag_ctrl), pointer :: diag !< structure to regulate diagnostic output timing character(len=200) :: inputdir !< directory where NetCDF input files are - character(len=200) :: CFC_BC_file !< filename with cfc11 and cfc12 data character(len=200) :: salt_restore_file !< filename for salt restoring data character(len=30) :: salt_restore_var_name !< name of surface salinity in salt_restore_file logical :: mask_srestore !< if true, apply a 2-dimensional mask to the surface @@ -146,11 +144,6 @@ module MOM_surface_forcing_nuopc real, pointer, dimension(:,:) :: trestore_mask => NULL() !< mask for SST restoring integer :: id_srestore = -1 !< id number for time_interp_external. integer :: id_trestore = -1 !< id number for time_interp_external. - integer :: CFC_BC_year_offset = 0 !< offset to add to model time to get time value used in CFC_BC_file - integer :: id_cfc11_atm_nh = -1 !< id number for time_interp_external. - integer :: id_cfc11_atm_sh = -1 !< id number for time_interp_external. - integer :: id_cfc12_atm_nh = -1 !< id number for time_interp_external. - integer :: id_cfc12_atm_sh = -1 !< id number for time_interp_external. ! Diagnostics handles type(forcing_diags), public :: handles @@ -593,13 +586,6 @@ subroutine convert_IOB_to_fluxes(IOB, fluxes, index_bounds, Time, valid_time, G, fluxes%accumulate_p_surf = .true. ! Multiple components may contribute to surface pressure. endif - ! CFCs - if (CS%use_CFC) then - call CFC_cap_fluxes(fluxes, sfc_state, G, US, CS%Rho0, Time, CS%CFC_BC_year_offset, & - CS%id_cfc11_atm_nh, CS%id_cfc11_atm_sh, & - CS%id_cfc12_atm_nh, CS%id_cfc12_atm_sh) - endif - if (associated(IOB%salt_flux)) then do j=js,je ; do i=is,ie fluxes%salt_flux(i,j) = G%mask2dT(i,j)*(fluxes%salt_flux(i,j) + kg_m2_s_conversion*IOB%salt_flux(i-i0,j-j0)) @@ -1117,13 +1103,7 @@ subroutine surface_forcing_init(Time, G, US, param_file, diag, CS, restore_salt, character(len=48) :: stagger character(len=48) :: flnam character(len=240) :: basin_file - character(len=30) :: cfc11_nh_var_name ! name of cfc11 nh in CFC_BC_file - character(len=30) :: cfc11_sh_var_name ! name of cfc11 sh in CFC_BC_file - character(len=30) :: cfc12_nh_var_name ! name of cfc12 nh in CFC_BC_file - character(len=30) :: cfc12_sh_var_name ! name of cfc12 sh in CFC_BC_file integer :: i, j, isd, ied, jsd, jed - integer :: CFC_BC_data_year ! specific year in CFC BC data calendar - integer :: CFC_BC_model_year ! model year corresponding to CFC_BC_data_year isd = G%isd ; ied = G%ied ; jsd = G%jsd ; jed = G%jed @@ -1419,42 +1399,6 @@ subroutine surface_forcing_init(Time, G, US, param_file, diag, CS, restore_salt, endif endif ; endif - ! Do not log these params here since they are logged in the CFC cap module - if (CS%use_CFC) then - call get_param(param_file, mdl, "CFC_BC_FILE", CS%CFC_BC_file, & - "The file in which the CFC-11 and CFC-12 atm concentrations can be "//& - "found (units must be parts per trillion).", default=" ", do_not_log=.true.) - if (len_trim(CS%CFC_BC_file) == 0) then - call MOM_error(FATAL, "CFC_BC_FILE must be specified if USE_CFC_CAP=.true.") - endif - if (scan(CS%CFC_BC_file, '/') == 0) then - ! Add the directory if CFC_BC_file is not already a complete path. - CS%CFC_BC_file = trim(CS%inputdir)//trim(CS%CFC_BC_file) - endif - call get_param(param_file, mdl, "CFC_BC_DATA_YEAR", CFC_BC_data_year, & - "Specific year in CFC_BC_FILE data calendar", default=2000, do_not_log=.true.) - call get_param(param_file, mdl, "CFC_BC_MODEL_YEAR", CFC_BC_model_year, & - "Model year corresponding to CFC_BC_MODEL_YEAR", default=2000, do_not_log=.true.) - CS%CFC_BC_year_offset = CFC_BC_data_year - CFC_BC_model_year - call get_param(param_file, mdl, "CFC11_NH_VARIABLE", cfc11_nh_var_name, & - "Variable name of NH CFC-11 atm mole fraction in CFC_BC_FILE.", & - default="cfc11_nh", do_not_log=.true.) - call get_param(param_file, mdl, "CFC11_SH_VARIABLE", cfc11_sh_var_name, & - "Variable name of SH CFC-11 atm mole fraction in CFC_BC_FILE.", & - default="cfc11_sh", do_not_log=.true.) - call get_param(param_file, mdl, "CFC12_NH_VARIABLE", cfc12_nh_var_name, & - "Variable name of NH CFC-12 atm mole fraction in CFC_BC_FILE.", & - default="cfc12_nh", do_not_log=.true.) - call get_param(param_file, mdl, "CFC12_SH_VARIABLE", cfc12_sh_var_name, & - "Variable name of SH CFC-12 atm mole fraction in CFC_BC_FILE.", & - default="cfc12_sh", do_not_log=.true.) - - CS%id_cfc11_atm_nh = init_external_field(CS%CFC_BC_file, cfc11_nh_var_name) - CS%id_cfc11_atm_sh = init_external_field(CS%CFC_BC_file, cfc11_sh_var_name) - CS%id_cfc12_atm_nh = init_external_field(CS%CFC_BC_file, cfc12_nh_var_name) - CS%id_cfc12_atm_sh = init_external_field(CS%CFC_BC_file, cfc12_sh_var_name) - endif - ! Set up any restart fields associated with the forcing. call restart_init(param_file, CS%restart_CSp, "MOM_forcing.res") call restart_init_end(CS%restart_CSp) diff --git a/config_src/drivers/solo_driver/MOM_surface_forcing.F90 b/config_src/drivers/solo_driver/MOM_surface_forcing.F90 index c1e125be83..1d72dc8eb6 100644 --- a/config_src/drivers/solo_driver/MOM_surface_forcing.F90 +++ b/config_src/drivers/solo_driver/MOM_surface_forcing.F90 @@ -345,7 +345,8 @@ subroutine set_forcing(sfc_state, forces, fluxes, day_start, day_interval, G, US endif if (associated(CS%tracer_flow_CSp)) then - call call_tracer_set_forcing(sfc_state, fluxes, day_start, day_interval, G, CS%tracer_flow_CSp) + call call_tracer_set_forcing(sfc_state, fluxes, day_start, day_interval, G, US, CS%Rho0, & + CS%tracer_flow_CSp) endif ! Allow for user-written code to alter the fluxes after all the above diff --git a/src/core/MOM_forcing_type.F90 b/src/core/MOM_forcing_type.F90 index 4365dd6296..e7fc638e15 100644 --- a/src/core/MOM_forcing_type.F90 +++ b/src/core/MOM_forcing_type.F90 @@ -191,10 +191,8 @@ module MOM_forcing_type real :: C_p !< heat capacity of seawater [Q C-1 ~> J kg-1 degC-1]. !! C_p is is the same value as in thermovar_ptrs_type. - ! CFC-related arrays needed in the MOM_CFC_cap module + ! arrays needed in the some tracer modules, e.g., MOM_CFC_cap real, pointer, dimension(:,:) :: & - cfc11_flux => NULL(), & !< flux of cfc_11 into the ocean [CU R Z T-1 ~> mol m-2 s-1] - cfc12_flux => NULL(), & !< flux of cfc_12 into the ocean [CU R Z T-1 ~> mol m-2 s-1] ice_fraction => NULL(), & !< fraction of sea ice coverage at h-cells, from 0 to 1 [nondim]. u10_sqr => NULL() !< wind magnitude at 10 m squared [L2 T-2 ~> m2 s-2] @@ -364,9 +362,7 @@ module MOM_forcing_type integer :: id_TKE_tidal = -1 integer :: id_buoy = -1 - ! cfc-related diagnostics handles - integer :: id_cfc11 = -1 - integer :: id_cfc12 = -1 + ! tracer surface flux related diagnostics handles integer :: id_ice_fraction = -1 integer :: id_u10_sqr = -1 @@ -1129,10 +1125,6 @@ subroutine MOM_forcing_chksum(mesg, fluxes, G, US, haloshift) call hchksum(fluxes%u10_sqr, mesg//" fluxes%u10_sqr", G%HI, haloshift=hshift, scale=US%L_to_m**2*US%s_to_T**2) if (associated(fluxes%ice_fraction)) & call hchksum(fluxes%ice_fraction, mesg//" fluxes%ice_fraction", G%HI, haloshift=hshift) - if (associated(fluxes%cfc11_flux)) & - call hchksum(fluxes%cfc11_flux, mesg//" fluxes%cfc11_flux", G%HI, haloshift=hshift, scale=US%RZ_T_to_kg_m2s) - if (associated(fluxes%cfc12_flux)) & - call hchksum(fluxes%cfc12_flux, mesg//" fluxes%cfc12_flux", G%HI, haloshift=hshift, scale=US%RZ_T_to_kg_m2s) if (associated(fluxes%salt_flux)) & call hchksum(fluxes%salt_flux, mesg//" fluxes%salt_flux", G%HI, haloshift=hshift, scale=US%RZ_T_to_kg_m2s) if (associated(fluxes%TKE_tidal)) & @@ -1340,26 +1332,9 @@ subroutine register_forcing_type_diags(Time, diag, US, use_temperature, handles, endif endif - ! units for cfc11_flux and cfc12_flux are [Conc R Z T-1 ~> mol m-2 s-1] ! See: - ! http://clipc-services.ceda.ac.uk/dreq/u/0940cbee6105037e4b7aa5579004f124.html - ! http://clipc-services.ceda.ac.uk/dreq/u/e9e21426e4810d0bb2d3dddb24dbf4dc.html if (present(use_cfcs)) then if (use_cfcs) then - handles%id_cfc11 = register_diag_field('ocean_model', 'cfc11_flux', diag%axesT1, Time, & - 'Gas exchange flux of CFC11 into the ocean ', & - 'mol m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & - cmor_field_name='fgcfc11', & - cmor_long_name='Surface Downward CFC11 Flux', & - cmor_standard_name='surface_downward_cfc11_flux') - - handles%id_cfc12 = register_diag_field('ocean_model', 'cfc12_flux', diag%axesT1, Time, & - 'Gas exchange flux of CFC12 into the ocean ', & - 'mol m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & - cmor_field_name='fgcfc12', & - cmor_long_name='Surface Downward CFC12 Flux', & - cmor_standard_name='surface_downward_cfc12_flux') - handles%id_ice_fraction = register_diag_field('ocean_model', 'ice_fraction', diag%axesT1, Time, & 'Fraction of cell area covered by sea ice', 'm2 m-2') @@ -2921,13 +2896,7 @@ subroutine forcing_diagnostics(fluxes_in, sfc_state, G_in, US, time_end, diag, h if (handles%id_netFWGlobalScl > 0) & call post_data(handles%id_netFWGlobalScl, fluxes%netFWGlobalScl, diag) - ! post diagnostics related to cfcs ==================================== - - if ((handles%id_cfc11 > 0) .and. associated(fluxes%cfc11_flux)) & - call post_data(handles%id_cfc11, fluxes%cfc11_flux, diag) - - if ((handles%id_cfc11 > 0) .and. associated(fluxes%cfc12_flux)) & - call post_data(handles%id_cfc12, fluxes%cfc12_flux, diag) + ! post diagnostics related to tracer surface fluxes ======================== if ((handles%id_ice_fraction > 0) .and. associated(fluxes%ice_fraction)) & call post_data(handles%id_ice_fraction, fluxes%ice_fraction, diag) @@ -2989,7 +2958,8 @@ subroutine allocate_forcing_by_group(G, fluxes, water, heat, ustar, press, & logical, optional, intent(in) :: salt !< If present and true, allocate salt fluxes logical, optional, intent(in) :: fix_accum_bug !< If present and true, avoid using a bug in !! accumulation of ustar_gustless - logical, optional, intent(in) :: cfc !< If present and true, allocate cfc fluxes + logical, optional, intent(in) :: cfc !< If present and true, allocate fields needed + !! for cfc surface fluxes logical, optional, intent(in) :: waves !< If present and true, allocate wave fields logical, optional, intent(in) :: shelf_sfc_accumulation !< If present and true, and shelf is true, !! then allocate surface flux deposition from the atmosphere @@ -3064,8 +3034,6 @@ subroutine allocate_forcing_by_group(G, fluxes, water, heat, ustar, press, & call myAlloc(fluxes%mass_berg,isd,ied,jsd,jed, iceberg) !These fields should only on allocated when USE_CFC_CAP is activated. - call myAlloc(fluxes%cfc11_flux,isd,ied,jsd,jed, cfc) - call myAlloc(fluxes%cfc12_flux,isd,ied,jsd,jed, cfc) call myAlloc(fluxes%ice_fraction,isd,ied,jsd,jed, cfc) call myAlloc(fluxes%u10_sqr,isd,ied,jsd,jed, cfc) @@ -3322,8 +3290,6 @@ subroutine deallocate_forcing_type(fluxes) if (associated(fluxes%mass_berg)) deallocate(fluxes%mass_berg) if (associated(fluxes%ice_fraction)) deallocate(fluxes%ice_fraction) if (associated(fluxes%u10_sqr)) deallocate(fluxes%u10_sqr) - if (associated(fluxes%cfc11_flux)) deallocate(fluxes%cfc11_flux) - if (associated(fluxes%cfc12_flux)) deallocate(fluxes%cfc12_flux) call coupler_type_destructor(fluxes%tr_fluxes) diff --git a/src/core/MOM_variables.F90 b/src/core/MOM_variables.F90 index 8279afa954..b586d09a09 100644 --- a/src/core/MOM_variables.F90 +++ b/src/core/MOM_variables.F90 @@ -44,8 +44,6 @@ module MOM_variables SST, & !< The sea surface temperature [C ~> degC]. SSS, & !< The sea surface salinity [S ~> psu or gSalt/kg]. sfc_density, & !< The mixed layer density [R ~> kg m-3]. - sfc_cfc11, & !< Sea surface concentration of CFC11 [mol kg-1]. - sfc_cfc12, & !< Sea surface concentration of CFC12 [mol kg-1]. Hml, & !< The mixed layer depth [Z ~> m]. u, & !< The mixed layer zonal velocity [L T-1 ~> m s-1]. v, & !< The mixed layer meridional velocity [L T-1 ~> m s-1]. @@ -328,7 +326,7 @@ module MOM_variables !! the ocean model. Unused fields are unallocated. subroutine allocate_surface_state(sfc_state, G, use_temperature, do_integrals, & gas_fields_ocn, use_meltpot, use_iceshelves, & - omit_frazil, use_cfcs) + omit_frazil) type(ocean_grid_type), intent(in) :: G !< ocean grid structure type(surface), intent(inout) :: sfc_state !< ocean surface state type to be allocated. logical, optional, intent(in) :: use_temperature !< If true, allocate the space for thermodynamic variables. @@ -341,14 +339,13 @@ subroutine allocate_surface_state(sfc_state, G, use_temperature, do_integrals, & !! tracer fluxes, and can be used to spawn related !! internal variables in the ice model. logical, optional, intent(in) :: use_meltpot !< If true, allocate the space for melt potential - logical, optional, intent(in) :: use_cfcs !< If true, allocate the space for cfcs logical, optional, intent(in) :: use_iceshelves !< If true, allocate the space for the stresses !! under ice shelves. logical, optional, intent(in) :: omit_frazil !< If present and false, do not allocate the space to !! pass frazil fluxes to the coupler ! local variables - logical :: use_temp, alloc_integ, use_melt_potential, alloc_iceshelves, alloc_frazil, alloc_cfcs + logical :: use_temp, alloc_integ, use_melt_potential, alloc_iceshelves, alloc_frazil integer :: is, ie, js, je, isd, ied, jsd, jed integer :: isdB, iedB, jsdB, jedB @@ -359,7 +356,6 @@ subroutine allocate_surface_state(sfc_state, G, use_temperature, do_integrals, & use_temp = .true. ; if (present(use_temperature)) use_temp = use_temperature alloc_integ = .true. ; if (present(do_integrals)) alloc_integ = do_integrals use_melt_potential = .false. ; if (present(use_meltpot)) use_melt_potential = use_meltpot - alloc_cfcs = .false. ; if (present(use_cfcs)) alloc_cfcs = use_cfcs alloc_iceshelves = .false. ; if (present(use_iceshelves)) alloc_iceshelves = use_iceshelves alloc_frazil = .true. ; if (present(omit_frazil)) alloc_frazil = .not.omit_frazil @@ -383,11 +379,6 @@ subroutine allocate_surface_state(sfc_state, G, use_temperature, do_integrals, & allocate(sfc_state%melt_potential(isd:ied,jsd:jed), source=0.0) endif - if (alloc_cfcs) then - allocate(sfc_state%sfc_cfc11(isd:ied,jsd:jed), source=0.0) - allocate(sfc_state%sfc_cfc12(isd:ied,jsd:jed), source=0.0) - endif - if (alloc_integ) then ! Allocate structures for the vertically integrated ocean_mass, ocean_heat, and ocean_salt. allocate(sfc_state%ocean_mass(isd:ied,jsd:jed), source=0.0) @@ -427,8 +418,6 @@ subroutine deallocate_surface_state(sfc_state) if (allocated(sfc_state%ocean_mass)) deallocate(sfc_state%ocean_mass) if (allocated(sfc_state%ocean_heat)) deallocate(sfc_state%ocean_heat) if (allocated(sfc_state%ocean_salt)) deallocate(sfc_state%ocean_salt) - if (allocated(sfc_state%sfc_cfc11)) deallocate(sfc_state%sfc_cfc11) - if (allocated(sfc_state%sfc_cfc12)) deallocate(sfc_state%sfc_cfc12) call coupler_type_destructor(sfc_state%tr_fields) sfc_state%arrays_allocated = .false. diff --git a/src/tracer/MOM_CFC_cap.F90 b/src/tracer/MOM_CFC_cap.F90 index 427ea1ed9a..4364dac0fd 100644 --- a/src/tracer/MOM_CFC_cap.F90 +++ b/src/tracer/MOM_CFC_cap.F90 @@ -5,6 +5,7 @@ module MOM_CFC_cap ! This file is part of MOM6. See LICENSE.md for the license. use MOM_coms, only : EFP_type +use MOM_debugging, only : hchksum use MOM_diag_mediator, only : diag_ctrl, register_diag_field, post_data use MOM_error_handler, only : MOM_error, FATAL, WARNING use MOM_file_parser, only : get_param, log_param, log_version, param_file_type @@ -25,7 +26,7 @@ module MOM_CFC_cap use MOM_tracer_diabatic, only : tracer_vertdiff, applyTracerBoundaryFluxesInOut use MOM_tracer_Z_init, only : tracer_Z_init use MOM_unit_scaling, only : unit_scale_type -use MOM_variables, only : surface +use MOM_variables, only : surface, thermo_var_ptrs use MOM_verticalGrid, only : verticalGrid_type implicit none ; private @@ -33,24 +34,29 @@ module MOM_CFC_cap #include public register_CFC_cap, initialize_CFC_cap, CFC_cap_unit_tests -public CFC_cap_column_physics, CFC_cap_surface_state, CFC_cap_fluxes +public CFC_cap_column_physics, CFC_cap_set_forcing public CFC_cap_stock, CFC_cap_end integer, parameter :: NTR = 2 !< the number of tracers in this module. -!> Contains the concentration array, a pointer to Tr in Tr_reg, and some metadata for a single CFC tracer +!> Contains the concentration array, surface flux, a pointer to Tr in Tr_reg, +!! and some metadata for a single CFC tracer type, private :: CFC_tracer_data - type(vardesc) :: desc !< A set of metadata for the tracer - real :: IC_val = 0.0 !< The initial value assigned to the tracer [mol kg-1]. - real :: land_val = -1.0 !< The value of the tracer used where land is masked out [mol kg-1]. - character(len=32) :: name !< Tracer variable name - integer :: id_cmor !< Diagnostic ID - real, pointer, dimension(:,:,:) :: conc !< The tracer concentration [mol kg-1]. - type(tracer_type), pointer :: tr_ptr !< pointer to tracer inside Tr_reg - end type CFC_tracer_data + type(vardesc) :: desc !< A set of metadata for the tracer + real :: IC_val = 0.0 !< The initial value assigned to the tracer [mol kg-1]. + real :: land_val = -1.0 !< The value of the tracer used where land is + !! masked out [mol kg-1]. + character(len=32) :: name !< Tracer variable name + integer :: id_cmor = -1 !< Diagnostic id + integer :: id_sfc_flux = -1 !< Surface flux id + real, pointer, dimension(:,:,:) :: conc !< The tracer concentration [mol kg-1]. + real, pointer, dimension(:,:) :: sfc_flux !< Surface flux [CU R Z T-1 ~> mol m-2 s-1] + type(tracer_type), pointer :: tr_ptr !< pointer to tracer inside Tr_reg +end type CFC_tracer_data !> The control structure for the CFC_cap tracer package type, public :: CFC_cap_CS ; private + logical :: debug !< If true, write verbose checksums for debugging purposes. character(len=200) :: IC_file !< The file in which the CFC initial values can !! be found, or an empty string for internal initilaization. logical :: Z_IC_file !< If true, the IC_file is in Z-space. The default is false. @@ -62,7 +68,12 @@ module MOM_CFC_cap !! the timing of diagnostic output. type(MOM_restart_CS), pointer :: restart_CSp => NULL() !< Model restart control structure - type(CFC_tracer_data), dimension(2) :: CFC_data !< per-tracer parameters / metadata + type(CFC_tracer_data), dimension(NTR) :: CFC_data !< per-tracer parameters / metadata + integer :: CFC_BC_year_offset = 0 !< offset to add to model time to get time value used in CFC_BC_file + integer :: id_cfc11_atm_nh = -1 !< id number for time_interp_external. + integer :: id_cfc11_atm_sh = -1 !< id number for time_interp_external. + integer :: id_cfc12_atm_nh = -1 !< id number for time_interp_external. + integer :: id_cfc12_atm_sh = -1 !< id number for time_interp_external. end type CFC_cap_CS contains @@ -81,15 +92,17 @@ function register_CFC_cap(HI, GV, param_file, CS, tr_Reg, restart_CS) ! Local variables character(len=40) :: mdl = "MOM_CFC_cap" ! This module's name. - character(len=200) :: inputdir ! The directory where NetCDF input files are. ! This include declares and sets the variable "version". # include "version_variable.h" + character(len=200) :: inputdir ! The directory where NetCDF input files are. real, dimension(:,:,:), pointer :: tr_ptr => NULL() - character(len=200) :: dummy ! Dummy variable to store params that need to be logged here. - integer :: dummy_int ! Dummy variable to store params that need to be logged here. + character(len=200) :: CFC_BC_file ! filename with cfc11 and cfc12 data + character(len=30) :: CFC_BC_var_name ! varname of field in CFC_BC_file character :: m2char logical :: register_CFC_cap integer :: isd, ied, jsd, jed, nz, m + integer :: CFC_BC_data_year ! specific year in CFC BC data calendar + integer :: CFC_BC_model_year ! model year corresponding to CFC_BC_data_year isd = HI%isd ; ied = HI%ied ; jsd = HI%jsd ; jed = HI%jed ; nz = GV%ke @@ -101,6 +114,9 @@ function register_CFC_cap(HI, GV, param_file, CS, tr_Reg, restart_CS) ! Read all relevant parameters and write them to the model log. call log_version(param_file, mdl, version, "") + call get_param(param_file, mdl, "DEBUG", CS%debug, & + "If true, write out verbose debugging data.", & + default=.false., debuggingParam=.true.) call get_param(param_file, mdl, "CFC_IC_FILE", CS%IC_file, & "The file in which the CFC initial values can be "//& "found, or an empty string for internal initialization.", & @@ -120,7 +136,7 @@ function register_CFC_cap(HI, GV, param_file, CS, tr_Reg, restart_CS) "if they are not found in the restart files. Otherwise "//& "it is a fatal error if tracers are not found in the "//& "restart files of a restarted run.", default=.false.) - do m=1,2 + do m=1,NTR write(m2char, "(I1)") m call get_param(param_file, mdl, "CFC1"//m2char//"_IC_VAL", CS%CFC_data(m)%IC_val, & "Value that CFC_1"//m2char//" is set to when it is not read from a file.", & @@ -129,41 +145,49 @@ function register_CFC_cap(HI, GV, param_file, CS, tr_Reg, restart_CS) ! the following params are not used in this module. Instead, they are used in ! the cap but are logged here to keep all the CFC cap params together. - call get_param(param_file, mdl, "CFC_BC_FILE", dummy, & + call get_param(param_file, mdl, "CFC_BC_FILE", CFC_BC_file, & "The file in which the CFC-11 and CFC-12 atm concentrations can be "//& "found (units must be parts per trillion).", default=" ") - if (len_trim(dummy) == 0) then + if (len_trim(CFC_BC_file) == 0) then call MOM_error(FATAL, "CFC_BC_FILE must be specified if USE_CFC_CAP=.true.") endif - if (scan(dummy, '/') == 0) then - ! Add the directory if dummy is not already a complete path. + if (scan(CFC_BC_file, '/') == 0) then + ! Add the directory if CFC_BC_file is not already a complete path. call get_param(param_file, mdl, "INPUTDIR", inputdir, default=".") - dummy = trim(slasher(inputdir))//trim(dummy) - call log_param(param_file, mdl, "INPUTDIR/CFC_BC_FILE", dummy, & + CFC_BC_file = trim(slasher(inputdir))//trim(CFC_BC_file) + call log_param(param_file, mdl, "INPUTDIR/CFC_BC_FILE", CFC_BC_file, & "full path of CFC_BC_FILE") endif - if (len_trim(dummy) > 0) then - call get_param(param_file, mdl, "CFC_BC_DATA_YEAR", dummy_int, & + + call get_param(param_file, mdl, "CFC_BC_DATA_YEAR", CFC_BC_data_year, & "Specific year in CFC_BC_FILE data calendar", default=2000) - call get_param(param_file, mdl, "CFC_BC_MODEL_YEAR", dummy_int, & + call get_param(param_file, mdl, "CFC_BC_MODEL_YEAR", CFC_BC_model_year, & "Model year corresponding to CFC_BC_MODEL_YEAR", default=2000) - call get_param(param_file, mdl, "CFC11_NH_VARIABLE", dummy, & - "Variable name of NH CFC-11 atm mole fraction in CFC_BC_FILE.", & - default="cfc11_nh") - call get_param(param_file, mdl, "CFC11_SH_VARIABLE", dummy, & - "Variable name of SH CFC-11 atm mole fraction in CFC_BC_FILE.", & - default="cfc11_sh") - call get_param(param_file, mdl, "CFC12_NH_VARIABLE", dummy, & - "Variable name of NH CFC-12 atm mole fraction in CFC_BC_FILE.", & - default="cfc12_nh") - call get_param(param_file, mdl, "CFC12_SH_VARIABLE", dummy, & - "Variable name of SH CFC-12 atm mole fraction in CFC_BC_FILE.", & - default="cfc12_sh") - endif + CS%CFC_BC_year_offset = CFC_BC_data_year - CFC_BC_model_year + + call get_param(param_file, mdl, "CFC11_NH_VARIABLE", CFC_BC_var_name, & + "Variable name of NH CFC-11 atm mole fraction in CFC_BC_FILE.", & + default="cfc11_nh") + CS%id_cfc11_atm_nh = init_external_field(CFC_BC_file, CFC_BC_var_name) + + call get_param(param_file, mdl, "CFC11_SH_VARIABLE", CFC_BC_var_name, & + "Variable name of SH CFC-11 atm mole fraction in CFC_BC_FILE.", & + default="cfc11_sh") + CS%id_cfc11_atm_sh = init_external_field(CFC_BC_file, CFC_BC_var_name) + + call get_param(param_file, mdl, "CFC12_NH_VARIABLE", CFC_BC_var_name, & + "Variable name of NH CFC-12 atm mole fraction in CFC_BC_FILE.", & + default="cfc12_nh") + CS%id_cfc12_atm_nh = init_external_field(CFC_BC_file, CFC_BC_var_name) + + call get_param(param_file, mdl, "CFC12_SH_VARIABLE", CFC_BC_var_name, & + "Variable name of SH CFC-12 atm mole fraction in CFC_BC_FILE.", & + default="cfc12_sh") + CS%id_cfc12_atm_sh = init_external_field(CFC_BC_file, CFC_BC_var_name) ! The following vardesc types contain a package of metadata about each tracer, ! including, the name; units; longname; and grid information. - do m=1,2 + do m=1,NTR write(m2char, "(I1)") m write(CS%CFC_data(m)%name, "(2A)") "CFC_1", m2char CS%CFC_data(m)%desc = var_desc(CS%CFC_data(m)%name, & @@ -172,6 +196,7 @@ function register_CFC_cap(HI, GV, param_file, CS, tr_Reg, restart_CS) caller=mdl) allocate(CS%CFC_data(m)%conc(isd:ied,jsd:jed,nz), source=0.0) + allocate(CS%CFC_data(m)%sfc_flux(isd:ied,jsd:jed), source=0.0) ! This pointer assignment is needed to force the compiler not to do a copy in ! the registration calls. Curses on the designers and implementers of F90. @@ -216,7 +241,7 @@ subroutine initialize_CFC_cap(restart, day, G, GV, US, h, diag, OBC, CS) CS%Time => day CS%diag => diag - do m=1,2 + do m=1,NTR if (.not.restart .or. (CS%tracers_may_reinit .and. & .not.query_initialized(CS%CFC_data(m)%conc, CS%CFC_data(m)%name, CS%restart_CSp))) then call init_tracer_CFC(h, CS%CFC_data(m)%conc, CS%CFC_data(m)%name, CS%CFC_data(m)%land_val, & @@ -225,11 +250,23 @@ subroutine initialize_CFC_cap(restart, day, G, GV, US, h, diag, OBC, CS) endif ! cmor diagnostics + ! units for cfc11_flux and cfc12_flux are [Conc R Z T-1 ~> mol m-2 s-1] ! CFC11 cmor conventions: http://clipc-services.ceda.ac.uk/dreq/u/42625c97b8fe75124a345962c4430982.html + ! http://clipc-services.ceda.ac.uk/dreq/u/0940cbee6105037e4b7aa5579004f124.html ! CFC12 cmor conventions: http://clipc-services.ceda.ac.uk/dreq/u/3ab8e10027d7014f18f9391890369235.html + ! http://clipc-services.ceda.ac.uk/dreq/u/e9e21426e4810d0bb2d3dddb24dbf4dc.html write(m2char, "(I1)") m - CS%CFC_data(m)%id_cmor = register_diag_field('ocean_model', 'cfc1'//m2char, diag%axesTL, day, & - 'Mole Concentration of CFC1'//m2char//' in Sea Water', 'mol m-3') + CS%CFC_data(m)%id_cmor = register_diag_field('ocean_model', & + 'cfc1'//m2char, diag%axesTL, day, & + 'Mole Concentration of CFC1'//m2char//' in Sea Water', 'mol m-3') + + CS%CFC_data(m)%id_sfc_flux = register_diag_field('ocean_model', & + 'cfc1'//m2char//'_flux', diag%axesT1, day, & + 'Gas exchange flux of CFC1'//m2char//' into the ocean ', & + 'mol m-2 s-1', conversion=US%RZ_T_to_kg_m2s, & + cmor_field_name='fgcfc1'//m2char, & + cmor_long_name='Surface Downward CFC1'//m2char//' Flux', & + cmor_standard_name='surface_downward_cfc1'//m2char//'_flux') enddo @@ -323,7 +360,7 @@ subroutine CFC_cap_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, GV, US, C ! Local variables real, dimension(SZI_(G),SZJ_(G),SZK_(GV)) :: h_work ! Used so that h can be modified [H ~> m or kg m-2] real :: flux_scale - integer :: i, j, k, is, ie, js, je, nz + integer :: i, j, k, is, ie, js, je, nz, m is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke @@ -334,43 +371,43 @@ subroutine CFC_cap_column_physics(h_old, h_new, ea, eb, fluxes, dt, G, GV, US, C if (associated(KPP_CSp) .and. present(nonLocalTrans)) then flux_scale = GV%Z_to_H / GV%rho0 - call KPP_NonLocalTransport(KPP_CSp, G, GV, h_old, nonLocalTrans, fluxes%cfc11_flux(:,:), dt, CS%diag, & - CS%CFC_data(1)%tr_ptr, CS%CFC_data(1)%conc(:,:,:), & - flux_scale=flux_scale) - call KPP_NonLocalTransport(KPP_CSp, G, GV, h_old, nonLocalTrans, fluxes%cfc12_flux(:,:), dt, CS%diag, & - CS%CFC_data(2)%tr_ptr, CS%CFC_data(2)%conc(:,:,:), & - flux_scale=flux_scale) + do m=1,NTR + call KPP_NonLocalTransport(KPP_CSp, G, GV, h_old, nonLocalTrans, & + CS%CFC_data(m)%sfc_flux(:,:), dt, CS%diag, & + CS%CFC_data(m)%tr_ptr, CS%CFC_data(m)%conc(:,:,:), & + flux_scale=flux_scale) + enddo endif endif ! Use a tridiagonal solver to determine the concentrations after the ! surface source is applied and diapycnal advection and diffusion occurs. if (present(evap_CFL_limit) .and. present(minimum_forcing_depth)) then - do k=1,nz ;do j=js,je ; do i=is,ie - h_work(i,j,k) = h_old(i,j,k) - enddo ; enddo ; enddo - call applyTracerBoundaryFluxesInOut(G, GV, CS%CFC_data(1)%conc, dt, fluxes, h_work, & - evap_CFL_limit, minimum_forcing_depth) - call tracer_vertdiff(h_work, ea, eb, dt, CS%CFC_data(1)%conc, G, GV, sfc_flux=fluxes%cfc11_flux) - - do k=1,nz ;do j=js,je ; do i=is,ie - h_work(i,j,k) = h_old(i,j,k) - enddo ; enddo ; enddo - call applyTracerBoundaryFluxesInOut(G, GV, CS%CFC_data(2)%conc, dt, fluxes, h_work, & - evap_CFL_limit, minimum_forcing_depth) - call tracer_vertdiff(h_work, ea, eb, dt, CS%CFC_data(2)%conc, G, GV, sfc_flux=fluxes%cfc12_flux) + do m=1,NTR + do k=1,nz ;do j=js,je ; do i=is,ie + h_work(i,j,k) = h_old(i,j,k) + enddo ; enddo ; enddo + call applyTracerBoundaryFluxesInOut(G, GV, CS%CFC_data(m)%conc, dt, fluxes, h_work, & + evap_CFL_limit, minimum_forcing_depth) + call tracer_vertdiff(h_work, ea, eb, dt, CS%CFC_data(m)%conc, G, GV, & + sfc_flux=CS%CFC_data(m)%sfc_flux) + enddo else - call tracer_vertdiff(h_old, ea, eb, dt, CS%CFC_data(1)%conc, G, GV, sfc_flux=fluxes%cfc11_flux) - call tracer_vertdiff(h_old, ea, eb, dt, CS%CFC_data(2)%conc, G, GV, sfc_flux=fluxes%cfc12_flux) + do m=1,NTR + call tracer_vertdiff(h_old, ea, eb, dt, CS%CFC_data(m)%conc, G, GV, & + sfc_flux=CS%CFC_data(m)%sfc_flux) + enddo endif ! If needed, write out any desired diagnostics from tracer sources & sinks here. - if (CS%CFC_data(1)%id_cmor > 0) call post_data(CS%CFC_data(1)%id_cmor, & - (GV%Rho0*US%R_to_kg_m3)*CS%CFC_data(1)%conc, & - CS%diag) - if (CS%CFC_data(2)%id_cmor > 0) call post_data(CS%CFC_data(2)%id_cmor, & - (GV%Rho0*US%R_to_kg_m3)*CS%CFC_data(2)%conc, & - CS%diag) + do m=1,NTR + if (CS%CFC_data(m)%id_cmor > 0) & + call post_data(CS%CFC_data(m)%id_cmor, & + (GV%Rho0*US%R_to_kg_m3)*CS%CFC_data(m)%conc, CS%diag) + + if (CS%CFC_data(m)%id_sfc_flux > 0) & + call post_data(CS%CFC_data(m)%id_sfc_flux, CS%CFC_data(m)%sfc_flux, CS%diag) + enddo end subroutine CFC_cap_column_physics @@ -409,58 +446,32 @@ function CFC_cap_stock(h, stocks, G, GV, CS, names, units, stock_index) return endif ; endif - do m=1,2 + do m=1,NTR call query_vardesc(CS%CFC_data(m)%desc, name=names(m), units=units(m), caller="CFC_cap_stock") units(m) = trim(units(m))//" kg" stocks(m) = global_mass_int_EFP(h, G, GV, CS%CFC_data(m)%conc, on_PE_only=.true.) enddo - CFC_cap_stock = 2 + CFC_cap_stock = NTR end function CFC_cap_stock -!> Extracts the ocean surface CFC concentrations and copies them to sfc_state. -subroutine CFC_cap_surface_state(sfc_state, G, CS) - type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure. - type(surface), intent(inout) :: sfc_state !< A structure containing fields that - !! describe the surface state of the ocean. - type(CFC_cap_CS), pointer :: CS!< The control structure returned by a previous - !! call to register_CFC_cap. - - ! Local variables - integer :: i, j, is, ie, js, je - - is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec - - if (.not.associated(CS)) return - - do j=js,je ; do i=is,ie - sfc_state%sfc_cfc11(i,j) = CS%CFC_data(1)%conc(i,j,1) - sfc_state%sfc_cfc12(i,j) = CS%CFC_data(2)%conc(i,j,1) - enddo ; enddo - -end subroutine CFC_cap_surface_state - !> Orchestrates the calculation of the CFC fluxes [mol m-2 s-1], including getting the ATM !! concentration, and calculating the solubility, Schmidt number, and gas exchange. -subroutine CFC_cap_fluxes(fluxes, sfc_state, G, US, Rho0, Time, CFC_BC_year_offset, & - id_cfc11_atm_nh, id_cfc11_atm_sh, id_cfc12_atm_nh, id_cfc12_atm_sh) - type(ocean_grid_type), intent(in ) :: G !< The ocean's grid structure. - type(unit_scale_type), intent(in ) :: US !< A dimensional unit scaling type +subroutine CFC_cap_set_forcing(sfc_state, fluxes, day_start, day_interval, G, US, Rho0, CS) type(surface), intent(in ) :: sfc_state !< A structure containing fields !! that describe the surface state of the ocean. type(forcing), intent(inout) :: fluxes !< A structure containing pointers !! to thermodynamic and tracer forcing fields. Unused fields !! have NULL ptrs. - real, intent(in ) :: Rho0 !< The mean ocean density [R ~> kg m-3] - type(time_type), intent(in ) :: Time !< The time of the fluxes, used for interpolating the - !! CFC's concentration in the atmosphere. - integer, intent(in ) :: CFC_BC_year_offset !< offset to add to model time to get - !! time value used in CFC_BC_file - integer, intent(inout) :: id_cfc11_atm_nh !< id number for time_interp_external. - integer, intent(inout) :: id_cfc11_atm_sh !< id number for time_interp_external. - integer, intent(inout) :: id_cfc12_atm_nh !< id number for time_interp_external. - integer, intent(inout) :: id_cfc12_atm_sh !< id number for time_interp_external. + type(time_type), intent(in) :: day_start !< Start time of the fluxes. + type(time_type), intent(in) :: day_interval !< Length of time over which these + !! fluxes will be applied. + type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure. + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type + real, intent(in) :: Rho0 !< The mean ocean density [R ~> kg m-3] + type(CFC_cap_CS), pointer :: CS !< The control structure returned by a + !! previous call to register_CFC_cap. ! Local variables type(time_type) :: Time_external ! time value used in CFC_BC_file @@ -483,22 +494,23 @@ subroutine CFC_cap_fluxes(fluxes, sfc_state, G, US, Rho0, Time, CFC_BC_year_offs real :: kw_coeff ! A coefficient used to compute the piston velocity [Z T-1 T2 L-2 = Z T L-2 ~> s / m] real, parameter :: pa_to_atm = 9.8692316931427e-6 ! factor for converting from Pa to atm [atm Pa-1]. real :: press_to_atm ! converts from model pressure units to atm [atm T2 R-1 L-2 ~> atm Pa-1] - integer :: i, j, is, ie, js, je + integer :: i, j, is, ie, js, je, m is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec - Time_external = increment_date(Time, years=CFC_BC_year_offset) + ! Time_external = increment_date(day_start + day_interval/2, years=CS%CFC_BC_year_offset) + Time_external = increment_date(day_start, years=CS%CFC_BC_year_offset) ! CFC11 atm mole fraction, convert from ppt (pico mol/mol) to mol/mol - call time_interp_external(id_cfc11_atm_nh, Time_external, cfc11_atm_nh) + call time_interp_external(CS%id_cfc11_atm_nh, Time_external, cfc11_atm_nh) cfc11_atm_nh = cfc11_atm_nh * 1.0e-12 - call time_interp_external(id_cfc11_atm_sh, Time_external, cfc11_atm_sh) + call time_interp_external(CS%id_cfc11_atm_sh, Time_external, cfc11_atm_sh) cfc11_atm_sh = cfc11_atm_sh * 1.0e-12 ! CFC12 atm mole fraction, convert from ppt (pico mol/mol) to mol/mol - call time_interp_external(id_cfc12_atm_nh, Time_external, cfc12_atm_nh) + call time_interp_external(CS%id_cfc12_atm_nh, Time_external, cfc12_atm_nh) cfc12_atm_nh = cfc12_atm_nh * 1.0e-12 - call time_interp_external(id_cfc12_atm_sh, Time_external, cfc12_atm_sh) + call time_interp_external(CS%id_cfc12_atm_sh, Time_external, cfc12_atm_sh) cfc12_atm_sh = cfc12_atm_sh * 1.0e-12 !--------------------------------------------------------------------- @@ -544,14 +556,21 @@ subroutine CFC_cap_fluxes(fluxes, sfc_state, G, US, Rho0, Time, CFC_BC_year_offs ! CFC flux units: CU R Z T-1 = mol kg-1 R Z T-1 ~> mol m-2 s-1 kw(i,j) = kw_wo_sc_no_term(i,j) * sqrt(660.0 / sc_11) cair(i,j) = press_to_atm * alpha_11 * cfc11_atm(i,j) * fluxes%p_surf_full(i,j) - fluxes%cfc11_flux(i,j) = kw(i,j) * (cair(i,j) - sfc_state%sfc_CFC11(i,j)) * Rho0 + CS%CFC_data(1)%sfc_flux(i,j) = kw(i,j) * (cair(i,j) - CS%CFC_data(1)%conc(i,j,1)) * Rho0 kw(i,j) = kw_wo_sc_no_term(i,j) * sqrt(660.0 / sc_12) cair(i,j) = press_to_atm * alpha_12 * cfc12_atm(i,j) * fluxes%p_surf_full(i,j) - fluxes%cfc12_flux(i,j) = kw(i,j) * (cair(i,j) - sfc_state%sfc_CFC12(i,j)) * Rho0 + CS%CFC_data(2)%sfc_flux(i,j) = kw(i,j) * (cair(i,j) - CS%CFC_data(2)%conc(i,j,1)) * Rho0 enddo ; enddo -end subroutine CFC_cap_fluxes + if (CS%debug) then + do m=1,NTR + call hchksum(CS%CFC_data(m)%sfc_flux, trim(CS%CFC_data(m)%name)//" sfc_flux", G%HI, & + scale=US%RZ_T_to_kg_m2s) + enddo + endif + +end subroutine CFC_cap_set_forcing !> Calculates the CFC's solubility function following Warner and Weiss (1985) DSR, vol 32. subroutine get_solubility(alpha_11, alpha_12, ta, sal , mask) @@ -638,8 +657,9 @@ subroutine CFC_cap_end(CS) integer :: m if (associated(CS)) then - do m=1,2 + do m=1,NTR if (associated(CS%CFC_data(m)%conc)) deallocate(CS%CFC_data(m)%conc) + if (associated(CS%CFC_data(m)%sfc_flux)) deallocate(CS%CFC_data(m)%sfc_flux) enddo deallocate(CS) @@ -716,7 +736,7 @@ logical function compare_values(verbose, test_name, calc, ans, limit) write(stdout,10) calc, ans endif -10 format("calc=",f20.16," ans",f20.16) +10 format("calc=",f22.16," ans",f22.16) end function compare_values !> \namespace mom_CFC_cap diff --git a/src/tracer/MOM_tracer_flow_control.F90 b/src/tracer/MOM_tracer_flow_control.F90 index f4794921e3..58bada441f 100644 --- a/src/tracer/MOM_tracer_flow_control.F90 +++ b/src/tracer/MOM_tracer_flow_control.F90 @@ -45,7 +45,7 @@ module MOM_tracer_flow_control use MOM_OCMIP2_CFC, only : OCMIP2_CFC_column_physics, OCMIP2_CFC_surface_state use MOM_OCMIP2_CFC, only : OCMIP2_CFC_stock, OCMIP2_CFC_end, OCMIP2_CFC_CS use MOM_CFC_cap, only : register_CFC_cap, initialize_CFC_cap -use MOM_CFC_cap, only : CFC_cap_column_physics, CFC_cap_surface_state +use MOM_CFC_cap, only : CFC_cap_column_physics, CFC_cap_set_forcing use MOM_CFC_cap, only : CFC_cap_stock, CFC_cap_end, CFC_cap_CS use oil_tracer, only : register_oil_tracer, initialize_oil_tracer use oil_tracer, only : oil_tracer_column_physics, oil_tracer_surface_state @@ -379,7 +379,7 @@ end subroutine get_chl_from_model !> This subroutine calls the individual tracer modules' subroutines to !! specify or read quantities related to their surface forcing. -subroutine call_tracer_set_forcing(sfc_state, fluxes, day_start, day_interval, G, CS) +subroutine call_tracer_set_forcing(sfc_state, fluxes, day_start, day_interval, G, US, Rho0, CS) type(surface), intent(inout) :: sfc_state !< A structure containing fields that !! describe the surface state of the @@ -391,6 +391,8 @@ subroutine call_tracer_set_forcing(sfc_state, fluxes, day_start, day_interval, G type(time_type), intent(in) :: day_interval !< Length of time over which these !! fluxes will be applied. type(ocean_grid_type), intent(in) :: G !< The ocean's grid structure. + type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type + real, intent(in) :: Rho0 !< The mean ocean density [R ~> kg m-3] type(tracer_flow_control_CS), pointer :: CS !< The control structure returned by a !! previous call to call_tracer_register. @@ -399,6 +401,9 @@ subroutine call_tracer_set_forcing(sfc_state, fluxes, day_start, day_interval, G ! if (CS%use_ideal_age) & ! call ideal_age_tracer_set_forcing(sfc_state, fluxes, day_start, day_interval, & ! G, CS%ideal_age_tracer_CSp) + if (CS%use_CFC_cap) & + call CFC_cap_set_forcing(sfc_state, fluxes, day_start, day_interval, G, US, Rho0, & + CS%CFC_cap_CSp) end subroutine call_tracer_set_forcing @@ -821,8 +826,6 @@ subroutine call_tracer_surface_state(sfc_state, h, G, GV, US, CS) call advection_test_tracer_surface_state(sfc_state, h, G, GV, CS%advection_test_tracer_CSp) if (CS%use_OCMIP2_CFC) & call OCMIP2_CFC_surface_state(sfc_state, h, G, GV, US, CS%OCMIP2_CFC_CSp) - if (CS%use_CFC_cap) & - call CFC_cap_surface_state(sfc_state, G, CS%CFC_cap_CSp) if (CS%use_MOM_generic_tracer) & call MOM_generic_tracer_surface_state(sfc_state, h, G, GV, CS%MOM_generic_tracer_CSp) diff --git a/src/tracer/oil_tracer.F90 b/src/tracer/oil_tracer.F90 index 3fc2537caa..aa365b1c6d 100644 --- a/src/tracer/oil_tracer.F90 +++ b/src/tracer/oil_tracer.F90 @@ -113,7 +113,7 @@ function register_oil_tracer(HI, GV, US, param_file, CS, tr_Reg, restart_CS) ! Add the directory if CS%IC_file is not already a complete path. call get_param(param_file, mdl, "INPUTDIR", inputdir, default=".") CS%IC_file = trim(slasher(inputdir))//trim(CS%IC_file) - call log_param(param_file, mdl, "INPUTDIR/CFC_IC_FILE", CS%IC_file) + call log_param(param_file, mdl, "INPUTDIR/OIL_IC_FILE", CS%IC_file) endif call get_param(param_file, mdl, "OIL_IC_FILE_IS_Z", CS%Z_IC_file, & "If true, OIL_IC_FILE is in depth space, not layer space", &