!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! !! !! GNU General Public License !! !! !! !! This file is part of the Flexible Modeling System (FMS). !! !! !! !! FMS is free software; you can redistribute it and/or modify !! !! it and are expected to follow the terms of the GNU General Public !! !! License as published by the Free Software Foundation. !! !! !! !! FMS is distributed in the hope that it will be useful, !! !! but WITHOUT ANY WARRANTY; without even the implied warranty of !! !! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !! !! GNU General Public License for more details. !! !! !! !! You should have received a copy of the GNU General Public License !! !! along with FMS; if not, write to: !! !! Free Software Foundation, Inc. !! !! 59 Temple Place, Suite 330 !! !! Boston, MA 02111-1307 USA !! !! or see: !! !! http://www.gnu.org/licenses/gpl.txt !! !! !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !---------------------------------------------------------------- ! Niki Zadeh ! ! ! William Cooke ! ! ! ! This module provides the main interfaces between Ocean models and ! generic tracers. ! ! ! Generic Tracers are designed to be used by both GFDL Ocean models, GOLD and MOM. ! This module provides the main interfaces for using generic tracers. ! Generic Tracers are contained in separate modules according to their ! chemical/physical similarity (currently generic_TOPAZ and generic_CFC) ! This module acts as a router for these various tracer modules and ! routes the subroutine calls to the appropriate tracer module. ! It also maintains a (linked) list of all generic tracers created in ! the experiment. This list acts as the "state" of generic tracers and ! contains all the information for all such tracers. This module provides ! a subroutine to query its state at any time. ! ! ! http://cobweb.gfdl.noaa.gov/~nnz/MITeam_GUTS_022708.pdf ! ! ! http://cobweb.gfdl.noaa.gov/~nnz/wiki/doku.php?id=genericunifiedtracers ! ! !---------------------------------------------------------------- module generic_tracer use fms_mod, only: open_namelist_file, close_file, check_nml_error use field_manager_mod, only: fm_string_len use mpp_mod, only : mpp_error, NOTE, WARNING, FATAL, stdout, stdlog use time_manager_mod, only : time_type use coupler_types_mod, only : coupler_2d_bc_type use g_tracer_utils, only : g_tracer_type, g_tracer_init use g_tracer_utils, only : g_tracer_get_common, g_tracer_set_common, g_tracer_is_prog use g_tracer_utils, only : g_tracer_coupler_set,g_tracer_coupler_get, g_tracer_register_diag use g_tracer_utils, only : g_tracer_vertdiff_M, g_tracer_vertdiff_G, g_tracer_get_next use generic_CFC, only : generic_CFC_register use generic_CFC, only : generic_CFC_init, generic_CFC_update_from_source,generic_CFC_update_from_coupler use generic_CFC, only : generic_CFC_set_boundary_values, generic_CFC_end, do_generic_CFC use generic_TOPAZ, only : generic_TOPAZ_register use generic_TOPAZ, only : generic_TOPAZ_init, generic_TOPAZ_update_from_source,generic_TOPAZ_register_diag use generic_TOPAZ, only : generic_TOPAZ_update_from_bottom,generic_TOPAZ_update_from_coupler use generic_TOPAZ, only : generic_TOPAZ_set_boundary_values, generic_TOPAZ_end, do_generic_TOPAZ use generic_BLING, only : generic_BLING_register use generic_BLING, only : generic_BLING_init, generic_BLING_update_from_source,generic_BLING_register_diag use generic_BLING, only : generic_BLING_update_from_bottom,generic_BLING_update_from_coupler use generic_BLING, only : generic_BLING_set_boundary_values, generic_BLING_end, do_generic_BLING implicit none ; private character(len=fm_string_len), parameter :: mod_name = 'generic_tracer' character(len=fm_string_len), parameter :: package_name = 'generic_tracer' public generic_tracer_register public generic_tracer_init public generic_tracer_register_diag public generic_tracer_source public generic_tracer_update_from_bottom public generic_tracer_coupler_get public generic_tracer_coupler_set public generic_tracer_coupler_zero public generic_tracer_end public generic_tracer_get_list public do_generic_tracer public generic_tracer_vertdiff_G public generic_tracer_vertdiff_M !Linked Lists of all prog and diag tracers in this module !Ensure these pointers are "save"d between the calls type(g_tracer_type), save, pointer :: tracer_list => NULL() logical, save :: do_generic_tracer = .false. namelist /generic_tracer_nml/ do_generic_tracer, do_generic_CFC, do_generic_TOPAZ, do_generic_BLING contains subroutine generic_tracer_register integer :: ioun, io_status, ierr character(len=fm_string_len), parameter :: sub_name = 'generic_tracer_register' ! provide for namelist over-ride of defaults ioun = open_namelist_file() read (ioun, generic_tracer_nml,iostat=io_status) write (stdout(),'(/)') write (stdout(), generic_tracer_nml) write (stdlog(), generic_tracer_nml) ierr = check_nml_error(io_status,'generic_tracer_nml') call close_file (ioun) if(do_generic_CFC) & call generic_CFC_register(tracer_list) if(do_generic_TOPAZ) & call generic_TOPAZ_register(tracer_list) if(do_generic_BLING) & call generic_BLING_register(tracer_list) end subroutine generic_tracer_register ! ! ! Initialize generic tracers ! ! ! Reads the namelist generic_tracer_nml to find the requested tracer packages ! Sets the common properties to be used by ALL generic tracers: isc,iec,jsc,jec,isd,ied,jsd,jed,nk,ntau,axes,grid_tmask,init_time ! Initialize each requested generic tracer package by calling their init routine ! ! ! ! Domain boundaries, ! ntau: number of time steps retained in the concentration field ! axes(3): diag axes ! ! ! ! ! ! Initiation time ! ! ! Grid mask ! ! subroutine generic_tracer_init(isc,iec,jsc,jec,isd,ied,jsd,jed,nk,ntau,axes,grid_tmask,grid_kmt,init_time) integer, intent(in) :: isc,iec,jsc,jec,isd,ied,jsd,jed,nk,ntau,axes(3) type(time_type), intent(in) :: init_time real, dimension(:,:,:),target, intent(in) :: grid_tmask integer, dimension(:,:) , intent(in) :: grid_kmt type(g_tracer_type), pointer :: g_tracer,g_tracer_next integer :: ioun, io_status, ierr character(len=fm_string_len), parameter :: sub_name = 'generic_tracer_init' ! provide for namelist over-ride of defaults ioun = open_namelist_file() read (ioun, generic_tracer_nml,iostat=io_status) write (stdout(),'(/)') write (stdout(), generic_tracer_nml) write (stdlog(), generic_tracer_nml) ierr = check_nml_error(io_status,'generic_tracer_nml') call close_file (ioun) call g_tracer_set_common(isc,iec,jsc,jec,isd,ied,jsd,jed,nk,ntau,axes,grid_tmask,grid_kmt,init_time) !Allocate and initialize all registered generic tracers if(do_generic_CFC .or. do_generic_TOPAZ .or. do_generic_BLING) then g_tracer => tracer_list !Go through the list of tracers do call g_tracer_init(g_tracer) !traverse the linked list till hit NULL call g_tracer_get_next(g_tracer, g_tracer_next) if(.NOT. associated(g_tracer_next)) exit g_tracer=>g_tracer_next enddo endif !Initilalize specific tracers if(do_generic_CFC) & call generic_CFC_init(tracer_list) if(do_generic_TOPAZ) & call generic_TOPAZ_init(tracer_list) if(do_generic_BLING) & call generic_BLING_init(tracer_list) end subroutine generic_tracer_init subroutine generic_tracer_register_diag character(len=fm_string_len), parameter :: sub_name = 'generic_tracer_register_diag' type(g_tracer_type), pointer :: g_tracer,g_tracer_next !Diagnostics register for the fields common to All generic tracers if(do_generic_CFC .or. do_generic_TOPAZ .or. do_generic_BLING) then g_tracer => tracer_list !Go through the list of tracers do call g_tracer_register_diag(g_tracer) !traverse the linked list till hit NULL call g_tracer_get_next(g_tracer, g_tracer_next) if(.NOT. associated(g_tracer_next)) exit g_tracer=>g_tracer_next enddo endif !Diagnostics register for fields particular to each tracer module if(do_generic_TOPAZ) call generic_TOPAZ_register_diag() if(do_generic_BLING) call generic_BLING_register_diag() end subroutine generic_tracer_register_diag ! ! ! Get coupler values ! ! ! Calls the corresponding generic_X_update_from_coupler routine for each package X. ! ! ! ! Ice Ocean Boundary flux structure ! ! subroutine generic_tracer_coupler_get(IOB_struc) type(coupler_2d_bc_type), intent(in) :: IOB_struc character(len=fm_string_len), parameter :: sub_name = 'generic_tracer_coupler_get' !All generic tracers !Update tracer boundary values (%stf and %triver) from coupler fluxes foreach tracer in the prog_tracer_list call g_tracer_coupler_get(tracer_list,IOB_struc) !Specific tracers ! if(do_generic_CFC) call generic_CFC_update_from_coupler(tracer_list) !Nothing to do if(do_generic_TOPAZ) call generic_TOPAZ_update_from_coupler(tracer_list) if(do_generic_BLING) call generic_BLING_update_from_coupler(tracer_list) end subroutine generic_tracer_coupler_get ! ! ! Update the tracers from sources/sinks ! ! ! Calls the corresponding generic_X_update_from_source routine for each package X. ! ! ! ! ! Lower bounds of x and y extents of input arrays on data domain ! ! ! Ocean temperature ! ! ! Ocean salinity ! ! ! Ocean layer thickness (meters) ! ! ! Ocean opacity ! ! ! Shortwave peneteration ! ! ! ! ! ! Grid area ! ! ! Time step index of %field ! ! ! Time step increment ! ! subroutine generic_tracer_source(Temp,Salt,rho_dzt,dzt,hblt_depth,ilb,jlb,tau,dtts,& grid_dat,model_time,nbands,max_wavelength_band,sw_pen_band,opacity_band) real, dimension(ilb:,jlb:,:), intent(in) :: Temp,Salt,rho_dzt,dzt real, dimension(ilb:,jlb:), intent(in) :: hblt_depth integer, intent(in) :: ilb,jlb,tau real, intent(in) :: dtts real, dimension(ilb:,jlb:), intent(in) :: grid_dat type(time_type), intent(in) :: model_time integer, intent(in) :: nbands real, dimension(:), intent(in) :: max_wavelength_band real, dimension(:,ilb:,jlb:), intent(in) :: sw_pen_band real, dimension(:,ilb:,jlb:,:), intent(in) :: opacity_band character(len=fm_string_len), parameter :: sub_name = 'generic_tracer_update_from_source' ! if(do_generic_CFC) call generic_CFC_update_from_source(tracer_list) !Nothing to do for CFC if(do_generic_TOPAZ) call generic_TOPAZ_update_from_source(tracer_list,Temp,Salt,rho_dzt,dzt,& hblt_depth,ilb,jlb,tau,dtts,grid_dat,model_time,& nbands,max_wavelength_band,sw_pen_band,opacity_band) if(do_generic_BLING) call generic_BLING_update_from_source(tracer_list,Temp,Salt,rho_dzt,dzt,& hblt_depth,ilb,jlb,tau,dtts,grid_dat,model_time,& nbands,max_wavelength_band,sw_pen_band,opacity_band) return end subroutine generic_tracer_source ! ! ! Update the tracers from bottom fluxes ! ! ! Calls the corresponding generic_X_update_from_bottom routine for each package X. ! ! ! ! Time step increment ! ! ! Time step index used for the concentration field ! ! subroutine generic_tracer_update_from_bottom(dt, tau, model_time) real, intent(in) :: dt integer, intent(in) ::tau type(time_type), intent(in) :: model_time character(len=fm_string_len), parameter :: sub_name = 'generic_tracer_update_from_bottom' ! if(do_generic_CFC) call generic_CFC_update_from_bottom(tracer_list)!Nothing to do for CFC if(do_generic_TOPAZ) call generic_TOPAZ_update_from_bottom(tracer_list,dt, tau, model_time) if(do_generic_BLING) call generic_BLING_update_from_bottom(tracer_list,dt, tau) return end subroutine generic_tracer_update_from_bottom ! ! ! Vertically diffuse all generic tracers for GOLD ocean ! ! ! This subroutine use a tridiagonal solver to update the values ! of concentration field from vertical diffusion. ! The implicit vertdiff for these tracers should be disabled in the Ocean model. ! ! ! ! ! ! subroutine generic_tracer_vertdiff_G(h_old, ea, eb, dt, kg_m2_to_H, m_to_H, tau) real, dimension(:,:,:), intent(in) :: h_old, ea, eb real, intent(in) :: dt, kg_m2_to_H, m_to_H integer, intent(in) :: tau type(g_tracer_type), pointer :: g_tracer,g_tracer_next !nnz: Should I loop here or inside the sub g_tracer_vertdiff ? if(do_generic_CFC .or. do_generic_TOPAZ .or. do_generic_BLING) then g_tracer => tracer_list !Go through the list of tracers do if(g_tracer_is_prog(g_tracer)) & call g_tracer_vertdiff_G(g_tracer,h_old, ea, eb, dt, kg_m2_to_H, m_to_H, tau) !traverse the linked list till hit NULL call g_tracer_get_next(g_tracer, g_tracer_next) if(.NOT. associated(g_tracer_next)) exit g_tracer=>g_tracer_next enddo endif end subroutine generic_tracer_vertdiff_G ! ! ! ! ! ! ! ! ! ! ! ! subroutine generic_tracer_vertdiff_M(dh, dhw, diff_cbt, dt, Rho_0,tau) real, dimension(:,:,:), intent(in) :: dh, dhw, diff_cbt real, intent(in) :: dt,Rho_0 integer, intent(in) :: tau type(g_tracer_type), pointer :: g_tracer,g_tracer_next !nnz: Should I loop here or inside the sub g_tracer_vertdiff ? if(do_generic_CFC .or. do_generic_TOPAZ .or. do_generic_BLING) then g_tracer => tracer_list !Go through the list of tracers do if(g_tracer_is_prog(g_tracer)) & call g_tracer_vertdiff_M(g_tracer,dh, dhw, diff_cbt, dt, Rho_0,tau) !traverse the linked list till hit NULL call g_tracer_get_next(g_tracer, g_tracer_next) if(.NOT. associated(g_tracer_next)) exit g_tracer=>g_tracer_next enddo endif end subroutine generic_tracer_vertdiff_M ! ! ! Set the coupler values for each generic tracer ! ! ! Calls the corresponding generic_X_set_boundary_values routine for each package X. ! ! ! ! Ice Ocean Boundary flux structure ! ! ! Lower bounds of x and y extents of input arrays on data domain ! ! ! Sea Surface Temperature ! ! ! Sea Surface Salinity ! ! ! Ocean density ! ! ! Time step index of %field ! ! subroutine generic_tracer_coupler_set(IOB_struc, ST,SS,rho,ilb,jlb,tau) type(coupler_2d_bc_type), intent(inout) :: IOB_struc integer, intent(in) :: ilb,jlb,tau real, dimension(ilb:,jlb:), intent(in) :: ST,SS real, dimension(ilb:,jlb:,:,:), intent(in) :: rho character(len=fm_string_len), parameter :: sub_name = 'generic_tracer_coupler_set' !Set coupler fluxes from tracer boundary values (%stf and %triver)for each tracer in the prog_tracer_list !User must identify these tracers (not all tracers in module need to set coupler) !User must provide the calculations for these boundary values. if(do_generic_CFC) & call generic_CFC_set_boundary_values(tracer_list,ST,SS,rho,ilb,jlb,tau) if(do_generic_TOPAZ) & call generic_TOPAZ_set_boundary_values(tracer_list,ST,SS,rho,ilb,jlb,tau) if(do_generic_BLING) & call generic_BLING_set_boundary_values(tracer_list,ST,SS,rho,ilb,jlb,tau) ! !Set coupler fluxes from tracer boundary values (%alpha and %csurf) !for each tracer in the tracer_list that has been marked by the user routine above ! if(do_generic_CFC .or. do_generic_TOPAZ .or. do_generic_BLING) call g_tracer_coupler_set(tracer_list,IOB_struc) end subroutine generic_tracer_coupler_set ! ! ! Zero out the coupler values for each tracer ! ! ! Set the coupler arrays for ALL generic tracers to 0 ! ! ! ! Ice Ocean Boundary flux structure ! ! subroutine generic_tracer_coupler_zero(IOB_struc) type(coupler_2d_bc_type), intent(inout) :: IOB_struc !Generic tracer coupler values are not accumulative. No need to set them to zero ! call g_tracer_coupler_set(tracer_list,IOB_struc,value=0.0) end subroutine generic_tracer_coupler_zero ! ! ! End this module by calling the corresponding generic_X_end for each package X. ! ! ! subroutine generic_tracer_end character(len=fm_string_len), parameter :: sub_name = 'generic_tracer_end' if(do_generic_CFC) call generic_CFC_end if(do_generic_TOPAZ) call generic_TOPAZ_end if(do_generic_BLING) call generic_BLING_end end subroutine generic_tracer_end ! ! ! Get a pointer to the head of the generic tracers list ! ! ! The (linked) list of all generic tracers acts as the "state" ! of the generic tracers. This routine provides a way to get ! this state at any time. ! ! ! ! Pointer to head of the linked list ! ! subroutine generic_tracer_get_list(list) type(g_tracer_type), pointer :: list list => tracer_list end subroutine generic_tracer_get_list end module generic_tracer