!======================================================================
! This is an interface for 3 test tracers: tr1,tr2,tr3
!
! This uses the tracers_suite module to initialize 
!   mixing ratios, fluxes and calculate tendencies.
!   Details of calling tree below. All of the detailed information about the
!  tracers should be store in the suite file, including the number & names of tracers. 
!
! Author B. Eaton
! History  D. Bundy, June 2003 modified to the format of physics interface
!        
!
!---------------------------------------------------------------
!
!  ------------  calling tree --------------
!  Register the tracers as advected fields, pass names to model
!  initindx.F90:			call tracers_register()
!
!  Initialize the tracer mixing ratio field
!  inidat.F90:read_inidat
!  	-> tracers.F90: tracers_init_cnst 
!  		-> tracers_suite.F90:init_cnst_tr
!
!  Initialize data set, things that need to be done at the beginning of a 
!  run (whether restart or initial)
!  inti.F90
!  	-> tracers.F90: tracers_init
!  		-> tracers_suite.F90:init_tr
!  		-> addfld/add default for surface flux (SF)
!
!  Timestepping:
!  advnce.F90
!  	-> tracers_timestep_init
!  		-> tracers_suite.F90:timestep_init_tr
!
!  tphysac.F90
!  	-> tracers_timestep_tend
!  		-> tracers_suite.F90:flux_tr
!  		-> tracers_suite.F90:tend_tr
!
!======================================================================

#include <misc.h>
#include <params.h>


module tracers 8,1

  use shr_kind_mod, only: r8 => shr_kind_r8

  implicit none
  private
  save

! Public interfaces
  public tracers_register                  ! register constituent
  public tracers_implements_cnst           ! true if named constituent is implemented by this package
  public tracers_init_cnst                 ! initialize constituent field
  public tracers_init                      ! initialize history fields, datasets
  public tracers_timestep_tend             ! calculate tendencies
  public tracers_timestep_init             ! interpolate dataset for constituent each timestep
  public set_state_pdry                          ! calculate dry air masses in state variable
  public set_wet_to_dry                         ! calculate dry air masses in state variable
  public set_dry_to_wet

! Data from namelist variables
  logical, public :: tracers_flag  = .false.     ! true => turn on test tracer code, namelist variable

! Private module data

  integer :: ixtrct=-999                             ! index of 1st constituent
  logical :: debug = .false.
  
contains
!======================================================================

subroutine tracers_register 1,5
!----------------------------------------------------------------------- 
!
! Purpose: register advected tracers. Called by initindx.F90
!  The registration lets the model know what the tracer names are
!  and returns the index number ixtrct for the constituent array
! 
! Author: D. Bundy
!-----------------------------------------------------------------------

   use physconst,    only: mwdry, cpair
   use constituents, only: cnst_add, advected
   use tracers_suite, only: get_tracer_name, trac_ncnst
   
   implicit none
!---------------------------Local workspace-----------------------------
   integer :: mm,m                                 ! dummy
   character(len=8) :: name   ! constituent name
   real(r8) minc

!-----------------------------------------------------------------------
   if ( tracers_flag ) then 
      minc = 0        ! min mixing ratio (normal setting)
      minc = -1.e36   ! min mixing ratio (disable qneg3)
      
      do m = 1,trac_ncnst 
         name = get_tracer_name(m)  ! get name from suite file
         
         ! add constituent name to list of advected, save index number ixtrct
         call cnst_add(name, advected, mwdry, cpair, minc, mm, &  
              readiv=.false.,mixtype='dry')
         if ( m .eq. 1 ) ixtrct = mm  ! save index number of first tracer
         
      end do
   end if

end subroutine tracers_register
!======================================================================


function tracers_implements_cnst(name),2
!----------------------------------------------------------------------- 
! 
! Purpose: return true if specified constituent is implemented by this package
! 
! Author: B. Eaton
! 
!-----------------------------------------------------------------------

  use tracers_suite, only: trac_ncnst, get_tracer_name
  
  implicit none
!-----------------------------Arguments---------------------------------
  
  character(len=*), intent(in) :: name   ! constituent name
  logical :: tracers_implements_cnst        ! return value
!---------------------------Local workspace-----------------------------
   integer :: m
!-----------------------------------------------------------------------

   tracers_implements_cnst = .false.
   if ( tracers_flag ) then 
      do m = 1, trac_ncnst
         if (name == get_tracer_name(m)) then
            tracers_implements_cnst = .true.
            return
         end if
      end do
   end if
end function tracers_implements_cnst

!===============================================================================

subroutine tracers_init_cnst(name, q) 4,4

!----------------------------------------------------------------------- 
!
! Purpose: initialize test tracers mixing ratio fields 
!  This subroutine is called at the beginning of an initial run ONLY
!
!-----------------------------------------------------------------------

  use pmgrid,     only: plon, plev, plat
  use tracers_suite,   only: init_cnst_tr, trac_ncnst, get_tracer_name

  implicit none

  character(len=*), intent(in) :: name
  real(r8), intent(out), dimension(plon,plev,plat) :: q    ! kg tracer/kg dry air

! Local
  integer m
  if ( tracers_flag ) then 
     do m = 1, trac_ncnst
        if (name ==  get_tracer_name(m))  then
           call init_cnst_tr(m,q)
        endif
     end do
  end if

end subroutine tracers_init_cnst

!===============================================================================

subroutine tracers_init 1,4

!----------------------------------------------------------------------- 
!
! Purpose: declare history variables, initialize data sets
!  This subroutine is called at the beginning of an initial or restart run
!
!-----------------------------------------------------------------------

  use tracers_suite,   only: init_tr, trac_ncnst
  use history,    only: addfld, add_default, phys_decomp
  use pmgrid,     only:  plev, plat

  implicit none

! Local
  integer m

  if ( tracers_flag ) then     
     

     ! this is where we would do addfld calls
     ! add surface flux and tendency fields. The tracer mixing ratios are added in history.F90
     
     ! initialize datasets, etc, needed for constituents.
     call init_tr  
  endif
     
end subroutine tracers_init

!======================================================================


subroutine tracers_timestep_init 1,2
!----------------------------------------------------------------------- 
!
! Purpose: At the beginning of a timestep, there are some things to do
! that just the masterproc should do. This currently just interpolates
! the emissions boundary data set to the current time step.
!
!-----------------------------------------------------------------------

  use tracers_suite, only: timestep_init_tr

  if ( tracers_flag ) then 
     
     call timestep_init_tr
     
     if (debug) write(6,*)'tracers_timestep_init done'
  endif

end subroutine tracers_timestep_init

!======================================================================


subroutine tracers_timestep_tend(state, ptend, cflx, landfrac, deltat) 1,9

!----------------------------------------------------------------------- 
!
! Purpose: During the timestep, compute test tracer mixing ratio 
! tendencies and surface fluxes.
! 
! Author: D. Bundy
!-----------------------------------------------------------------------

  use physics_types, only: physics_state, physics_ptend, physics_ptend_init
  use ppgrid,        only: pcols, pver
  use constituents,  only: ppcnst, sflxnam
  use tracers_suite, only: flux_tr,tend_tr,trac_ncnst
  use history,    only: outfld

  implicit none

  ! Arguments
   type(physics_state), intent(in)  :: state          ! state variables
   type(physics_ptend), intent(out) :: ptend          ! package tendencies
   real(r8),            intent(in)  :: deltat         ! timestep
   real(r8),            intent(in)  :: landfrac(pcols) ! Land fraction
   real(r8), intent(inout) :: cflx(pcols,ppcnst) ! Surface constituent flux (kg/m^2/s)

! Local variables
   integer  :: m               ! tracer number (internal)

!-----------------------------------------------------------------------

     ! Initialize output tendency structure
     ! Do this even if not going to be used, to clear it and 
     !    pass runtime debug checks 
     call physics_ptend_init(ptend)

  if ( tracers_flag ) then 
     ptend%name  = 'tracers'
     
     do  m = 1,trac_ncnst 
        if (debug) print *,'tracers.F90 calling for tracer ',m
        
        !calculate flux
        call flux_tr(m,state%ncol,state%lchnk, landfrac, cflx(:,ixtrct+m-1))
        
        !calculate tendency
        call tend_tr(m,state%ncol, state%q(:,:,ixtrct+m-1), deltat, ptend%q(:,:,ixtrct+m-1))
        ptend%lq(ixtrct+m-1) = .true.    ! logical flag to update physics tendency
        
        !outfld calls could go here
        call outfld (sflxnam(ixtrct+m-1),cflx(:,ixtrct+m-1),pcols,state%lchnk)
        
        
     end do
     
     if ( debug ) then 
        do  m = 1,trac_ncnst 
           print *,'tracers_timestep_tend ixtrct,m,ixtrct+m-1',ixtrct,m,ixtrct+m-1
           print *,'tracers_timestep_tend min max flux',minval(cflx(:,ixtrct+m-1)),maxval(cflx(:,ixtrct+m-1))
           print *,'tracers_timestep_tend min max tend',minval(ptend%q(:,:,ixtrct+m-1)),maxval(ptend%q(:,:,ixtrct+m-1))
        end do
        write(6,*)'tracers_timestep_tend end'
     endif
  endif


end subroutine tracers_timestep_tend

!======================================================================


subroutine set_state_pdry (state) 2,3

  use physics_types, only: physics_state
  use ppgrid,  only: pcols, pver
  use pmgrid

  implicit none

#include <comhyb.h>

  type(physics_state), intent(inout) :: state
  integer ncol
  integer i, k
  
  ncol = state%ncol

#ifdef METHOD1
  state%psdry(:ncol) = ps0 * hyai(1)
  do k = 1, pver
     state%psdry(:ncol) = state%psdry(:ncol) + state%pdel(:ncol,k)*(1.-state%q(:ncol,k,1))
  end do
  call plevs0(ncol, pcols, pver, state%psdry, &
       state%pintdry, state%pmiddry, state%pdeldry)
#else
  state%psdry(:ncol) = ps0 * hyai(1)
  state%pintdry(:ncol,1) = ps0 * hyai(1)
  do k = 1, pver
     state%pdeldry(:ncol,k) = state%pdel(:ncol,k)*(1.-state%q(:ncol,k,1))
     state%pintdry(:ncol,k+1) = state%pintdry(:ncol,k)+state%pdeldry(:ncol,k)
     state%pmiddry(:ncol,k) = (state%pintdry(:ncol,k+1)+state%pintdry(:ncol,k))/2.
     state%psdry(:ncol) = state%psdry(:ncol) + state%pdeldry(:ncol,k)
  end do
#endif

  state%rpdeldry(:ncol,:) = 1./state%pdeldry(:ncol,:)
  state%lnpmiddry(:ncol,:) = log(state%pmiddry(:ncol,:))
  state%lnpintdry(:ncol,:) = log(state%pintdry(:ncol,:))

end subroutine set_state_pdry 

!======================================================================


subroutine set_wet_to_dry (state) 1,5

  use physics_types, only: physics_state
  use ppgrid,  only: pcols, pver
  use pmgrid
  use constituents,   only: cnst_type
  use constituents,  only: ppcnst

  implicit none

#include <comhyb.h>

  type(physics_state), intent(inout) :: state
  integer ncol
  integer i, k, m
  
  ncol = state%ncol

  do m = 1,ppcnst
     if (cnst_type(m).eq.'dry') then
        state%q(:ncol,:,m) = state%q(:ncol,:,m)*state%pdel(:ncol,:)/state%pdeldry(:ncol,:)
     endif
  end do


end subroutine set_wet_to_dry 

!======================================================================


subroutine set_dry_to_wet (state) 1,5

  use physics_types, only: physics_state
  use ppgrid,  only: pcols, pver
  use pmgrid
  use constituents,  only: cnst_type
  use constituents,  only: ppcnst

  implicit none

#include <comhyb.h>

  type(physics_state), intent(inout) :: state
  integer ncol
  integer i, k, m
  
  ncol = state%ncol

  do m = 1,ppcnst
     if (cnst_type(m).eq.'dry') then
        if ( debug ) write(6,*)'DRBDBG set_dry_to_wet cnst',m
        state%q(:ncol,:,m) = state%q(:ncol,:,m)*state%pdeldry(:ncol,:)/state%pdel(:ncol,:)
     endif
  end do

end subroutine set_dry_to_wet

!======================================================================


end module tracers