!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

module fs_tracer_mod

!BOP
! !MODULE: fs_tracer_mod
!
! !DESCRIPTION:
!
! !REVISION HISTORY:
!  SVN:$Id: fs_tracer_mod.F90 2017-05-26 08:10:00Z cro $
! Fram Starit (FS) tracer, Robert Osinski, 2017-05-26

! !USES:

   use POP_KindsMod
   use POP_IOUnitsMod
   use POP_ErrorMod

   use blocks, only: nx_block, ny_block
   use domain_size, only: max_blocks_clinic, km
   use domain, only: nblocks_clinic
   use exit_mod, only: sigAbort, exit_POP
   use communicate, only: my_task, master_task
   use prognostic, only: tracer_field
   use kinds_mod
   use constants, only: c0, c1, char_blank, delim_fmt
   use io, only: data_set
   use io_types, only: stdout, nml_in, nml_filename
   use io_tools, only: document
   use tavg, only: define_tavg_field, accumulate_tavg_field, accumulate_tavg_now
   use passive_tracer_tools, only: ind_name_pair, tracer_read, &
       rest_read_tracer_block, file_read_tracer_block
   implicit none
   private

! !PUBLIC MEMBER FUNCTIONS:

   public :: fs_tracer_cnt,        &
             fs_tracer_init,              &
             fs_tracer_set_interior,      &
             fs_tracer_reset

!EOP
!BOC

!-----------------------------------------------------------------------
!  module variables required by passive_tracer
!-----------------------------------------------------------------------

   integer(int_kind), parameter :: &
      fs_tracer_cnt = 1

!-----------------------------------------------------------------------
!  relative tracer indices
!-----------------------------------------------------------------------

   integer(int_kind), parameter :: &
      fs_tracer_ind = 1     ! fs_tracer index

!-----------------------------------------------------------------------
!  derived type & parameter for tracer index lookup
!-----------------------------------------------------------------------

   type(ind_name_pair), dimension(fs_tracer_cnt) :: &
      ind_name_table = (/ ind_name_pair(fs_tracer_ind, 'FS_TRACER') /)

!-----------------------------------------------------------------------
!  tavg ids for non-standard tavg variables
!-----------------------------------------------------------------------

   integer (int_kind) :: &
      tavg_FS_TRACER_RESET_TEND       ! tavg id for surface reset tendency of FS_TRACER

!EOC
!*****************************************************************************

contains

!*****************************************************************************
!BOP
! !IROUTINE: fs_tracer_init
! !INTERFACE:

 subroutine fs_tracer_init(init_ts_file_fmt, read_restart_filename, &
                      tracer_d_module, TRACER_MODULE, errorCode)

! !DESCRIPTION:
!  Initialize fs_tracer module. This involves setting metadata, reading
!  the module namelist and setting initial conditions.
!
! !REVISION HISTORY:
!  same as module

! !USES:

   use broadcast, only: broadcast_scalar
   use prognostic, only: curtime, oldtime
   use grid, only: KMT, n_topo_smooth, fill_points

! !INPUT PARAMETERS:

   character (*), intent(in) ::  &
      init_ts_file_fmt,    & ! format (bin or nc) for input file
      read_restart_filename  ! file name for restart file

! !INPUT/OUTPUT PARAMETERS:

   type (tracer_field), dimension(fs_tracer_cnt), intent(inout) :: &
      tracer_d_module   ! descriptors for each tracer

   real(r8), dimension(nx_block,ny_block,km,fs_tracer_cnt,3,max_blocks_clinic), &
      intent(inout) :: TRACER_MODULE

! !OUTPUT PARAMETERS:

   integer (POP_i4), intent(out) :: &
      errorCode            ! returned error code

!EOP
!BOC
!-----------------------------------------------------------------------
!  local variables
!-----------------------------------------------------------------------

   character(*), parameter :: subname = 'fs_tracer_mod:fs_tracer_init'

   character(char_len) :: &
      init_fs_tracer_option,           & ! option for initialization of fs_tracer
      init_fs_tracer_init_file,        & ! filename for option 'file'
      init_fs_tracer_init_file_fmt       ! file format for option 'file'

   logical(log_kind) :: &
      lnml_found             ! Was fs_tracer_nml found ?

   integer(int_kind) :: &
      n,                   & ! index for looping over tracers
      k,                   & ! index for looping over depth levels
      iblock,              & ! index for looping over blocks
      nml_error              ! namelist i/o error flag

!     l,                   & ! index for looping over time levels

   type(tracer_read), dimension(fs_tracer_cnt) :: &
      tracer_init_ext        ! namelist variable for initializing tracers

   namelist /fs_tracer_nml/ &
      init_fs_tracer_option, init_fs_tracer_init_file, tracer_init_ext, &
      init_fs_tracer_init_file_fmt

   character (char_len) ::  &
      fs_tracer_restart_filename  ! modified file name for restart file

!-----------------------------------------------------------------------
!  initialize tracer_d values
!-----------------------------------------------------------------------

   errorCode = POP_Success

   tracer_d_module(fs_tracer_ind)%short_name = 'FS_TRACER'
   tracer_d_module(fs_tracer_ind)%long_name  = 'FS Water Tracer'
   tracer_d_module(fs_tracer_ind)%units      = '%'
   tracer_d_module(fs_tracer_ind)%tend_units = '%/s'
   tracer_d_module(fs_tracer_ind)%flux_units = '%/ cm^2 s'

!-----------------------------------------------------------------------
!  default namelist settings
!-----------------------------------------------------------------------

   init_fs_tracer_option = 'unknown'
   init_fs_tracer_init_file = 'unknown'
   init_fs_tracer_init_file_fmt = 'bin'

   do n = 1,fs_tracer_cnt
      tracer_init_ext(n)%mod_varname  = 'unknown'
      tracer_init_ext(n)%filename     = 'unknown'
      tracer_init_ext(n)%file_varname = 'unknown'
      tracer_init_ext(n)%scale_factor = c1
      tracer_init_ext(n)%default_val  = c0
      tracer_init_ext(n)%file_fmt     = 'bin'
   end do

   if (my_task == master_task) then
      open (nml_in, file=nml_filename, status='old',iostat=nml_error)
      if (nml_error /= 0) then  
         nml_error = -1
      else
         nml_error =  1      
      endif
      do while (nml_error > 0)
         read(nml_in, nml=fs_tracer_nml,iostat=nml_error)
      end do
      if (nml_error == 0) close(nml_in)
   endif

   call broadcast_scalar(nml_error, master_task)
   if (nml_error /= 0) then
      call document(subname, 'fs_tracer_nml not found')
      call exit_POP(sigAbort, 'stopping in ' /&
                           &/ subname)
   endif

!-----------------------------------------------------------------------
!  broadcast all namelist variables
!-----------------------------------------------------------------------

   call broadcast_scalar(init_fs_tracer_option , master_task)
   call broadcast_scalar(init_fs_tracer_init_file, master_task)
   call broadcast_scalar(init_fs_tracer_init_file_fmt, master_task)

   do n = 1,fs_tracer_cnt
      call broadcast_scalar(tracer_init_ext(n)%mod_varname, master_task)
      call broadcast_scalar(tracer_init_ext(n)%filename, master_task)
      call broadcast_scalar(tracer_init_ext(n)%file_varname, master_task)
      call broadcast_scalar(tracer_init_ext(n)%scale_factor, master_task)
      call broadcast_scalar(tracer_init_ext(n)%default_val, master_task)
      call broadcast_scalar(tracer_init_ext(n)%file_fmt, master_task)
   end do

!-----------------------------------------------------------------------
!  initialize tracers
!-----------------------------------------------------------------------

   select case (init_fs_tracer_option)

   case ('ccsm_startup', 'zero', 'ccsm_startup_spunup')
      TRACER_MODULE = c0
      if (my_task == master_task) then
          write(stdout,delim_fmt)
          write(stdout,*) ' Initial 3-d Fram Strait WATER (fs_tracer) set to all zeros' 
          write(stdout,delim_fmt)
          call POP_IOUnitsFlush(POP_stdout) ; call POP_IOUnitsFlush(stdout)
      endif
       
   case ('restart', 'ccsm_continue', 'ccsm_branch', 'ccsm_hybrid' )

      fs_tracer_restart_filename = char_blank

      if (init_fs_tracer_init_file == 'same_as_TS') then
         if (read_restart_filename == 'undefined') then
            call document(subname, 'no restart file to read fs_tracer from')
            call exit_POP(sigAbort, 'stopping in ' /&
                                 &/ subname)
         endif
         fs_tracer_restart_filename = read_restart_filename
         init_fs_tracer_init_file_fmt = init_ts_file_fmt

      else  ! do not read from TS restart file

         fs_tracer_restart_filename = trim(init_fs_tracer_init_file)

      endif

      call rest_read_tracer_block(init_fs_tracer_init_file_fmt, &
                                  fs_tracer_restart_filename,   &
                                  tracer_d_module,         &
                                  TRACER_MODULE)

   case ('file')
      call document(subname, 'fs_tracer being read from separate file')

      call file_read_tracer_block(init_fs_tracer_init_file_fmt, &
                                  init_fs_tracer_init_file,     &
                                  tracer_d_module,         &
                                  ind_name_table,          &
                                  tracer_init_ext,         &
                                  TRACER_MODULE)
 
      if (n_topo_smooth > 0) then
         do k=1,km
            call fill_points(k,TRACER_MODULE(:,:,k,1,curtime,:), errorCode)

            if (errorCode /= POP_Success) then
               call POP_ErrorSet(errorCode, &
                  'fs_tracer_init: error in fill_points for tracer 1')
               return
            endif
         enddo
      endif

   case default
      call document(subname, 'unknown init_fs_tracer_option = ', init_fs_tracer_option)
      call exit_POP(sigAbort, 'stopping in ' /&
                           &/ subname)

   end select

!-----------------------------------------------------------------------
!  apply land mask to tracers
!-----------------------------------------------------------------------

   do iblock=1,nblocks_clinic
      do n = 1,fs_tracer_cnt
         do k = 1,km
            where (k > KMT(:,:,iblock))
               TRACER_MODULE(:,:,k,n,curtime,iblock) = c0
               TRACER_MODULE(:,:,k,n,oldtime,iblock) = c0
            end where
         end do
      end do
   enddo

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

   call define_tavg_field(tavg_FS_TRACER_RESET_TEND, 'FS_TRACER_RESET_TEND',2,  &
                          long_name='surface reset tendency of FS_TRACER', &
                          units='years/s', grid_loc='2110',           &
                          coordinates='TLONG TLAT time')

!-----------------------------------------------------------------------
!EOC

 end subroutine fs_tracer_init

!***********************************************************************
!BOP
! !IROUTINE: fs_tracer_set_interior
! !INTERFACE:

 subroutine fs_tracer_set_interior(k, DTRACER_MODULE)

! !DESCRIPTION:
!  set interior source/sink term for FS water tracer
!
! !REVISION HISTORY:
!  same as module

! !USES:

   use time_management, only: seconds_in_year
! !INPUT PARAMETERS:

   integer(int_kind), intent(in) :: &
      k                   ! vertical level index

! !OUTPUT PARAMETERS:

   real(r8), dimension(nx_block,ny_block,fs_tracer_cnt), intent(out) :: &
      DTRACER_MODULE      ! computed source/sink term

!EOP
!BOC

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

!cro    if (k > 1) then
!cro       DTRACER_MODULE = c1 / seconds_in_year
!cro    else
          DTRACER_MODULE = c0 
!cro    endif


!-----------------------------------------------------------------------
!EOC

 end subroutine fs_tracer_set_interior

!***********************************************************************
!BOP
! !IROUTINE: fs_tracer_reset
! !INTERFACE:

 subroutine fs_tracer_reset(TRACER_MODULE, bid)

! !DESCRIPTION:
!  reset (mask, water masses or surface) value for fs_tracer tracer
!
! !REVISION HISTORY:
!  same as module

! !USES:

   use time_management, only: mix_pass, c2dtt
   use prognostic, only: PSURF, newtime
   use constants, only: grav
   use grid, only: dz
   use forcing_fields, only: TRACERS_MASK2 !cro
   use prognostic, only:curtime,TRACER     !cro 

! !INPUT PARAMETERS:

   integer(int_kind), intent(in) :: bid
   integer(int_kind)  :: k  !cro
                         ! vertical level index

! !INPUT/OUTPUT PARAMETERS:

   real(r8), dimension(nx_block,ny_block,km,fs_tracer_cnt), intent(inout) :: &
      TRACER_MODULE      ! fs_tracer tracer

!EOP
!BOC
!-----------------------------------------------------------------------
!  local variables
!-----------------------------------------------------------------------

   real (r8), dimension(nx_block,ny_block) :: WORK

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

   if (mix_pass /= 1) then
      if (accumulate_tavg_now(tavg_FS_TRACER_RESET_TEND)) then
            WORK = -TRACER_MODULE(:,:,1,1) / c2dtt(1)
            WORK = WORK * (c1 + PSURF(:,:,newtime,bid)/grav/dz(1))
            call accumulate_tavg_field(WORK,tavg_FS_TRACER_RESET_TEND,bid,1)
      endif
   endif

!cro   TRACER_MODULE(:,:,1,:) = c0 !set at level 1 (surface)
  do k=1,km
!     where (TRACERS_MASK2 .gt. 0)  TRACER_MODULE(:,:,k,:) = TRACERS_MASK2 !set value 1
      where (TRACER(:,:,k,1,curtime,:) .gt. -100.0 .and. & !temperature low
             TRACER(:,:,k,1,curtime,:) .lt.  100.0 .and. & !temperature high
             TRACER(:,:,k,2,curtime,:) .gt. -100.0 .and. & !salinity low (0.035)
             TRACER(:,:,k,2,curtime,:) .lt.  100.0 .and. & !salinity high
              TRACERS_MASK2 .gt. 0) 
       TRACER_MODULE(:,:,k,:) = TRACERS_MASK2
      end where 
  enddo
   where (TRACER_MODULE .gt. 1) TRACER_MODULE = c1  !get rid of values > 1
    where (TRACER_MODULE .lt. 0) TRACER_MODULE = c0 !get rid of vasues < 0

!-----------------------------------------------------------------------
!EOC

 end subroutine fs_tracer_reset

!***********************************************************************

end module fs_tracer_mod

!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
