!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! !!
!! 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
!
!
! call generic_tracer_init(isc,iec,jsc,jec,isd,ied,jsd,jed,nk,ntau,axes,grid_tmask,init_time)
!
!
! 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.
!
!
! call generic_tracer_coupler_get(IOB_struc)
!
!
! 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.
!
!
! call generic_tracer_source(Temp,Salt,rho_dzt,dzt,hblt_depth,ilb,jlb,tau,dtts,&
! grid_dat,sw_pen,opacity,river,neutralrho,grid_yt)
!
!
!
! 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.
!
!
! call generic_tracer_update_from_bottom(dt, tau, model_time)
!
!
! 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.
!
!
! call generic_tracer_vertdiff_G(h_old, ea, eb, dt, Rho_0,tau)
!
!
!
!
!
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
!
!
!
!
!
!
!
!
! call
!
!
!
!
!
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.
!
!
! call generic_tracer_coupler_set(IOB_struc, ST,SS,rho,ilb,jlb,tau)
!
!
! 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
!
!
! call
!
!
! 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.
!
!
! call generic_tracer_end
!
!
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.
!
!
! call generic_tracer_get_list(list)
!
!
! 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