module CNMRespMod

  !-----------------------------------------------------------------------
  ! !DESCRIPTION:
  ! Module holding maintenance respiration routines for coupled carbon
  ! nitrogen code.
  !
  ! !USES:
  use shr_kind_mod           , only : r8 => shr_kind_r8
  use shr_const_mod          , only : SHR_CONST_TKFRZ
  use clm_varpar             , only : nlevgrnd
  use clm_varcon             , only : spval
  use decompMod              , only : bounds_type
  use abortutils             , only : endrun
  use shr_log_mod            , only : errMsg => shr_log_errMsg
  use pftconMod              , only : npcropmin, pftcon
  use SoilStateType          , only : soilstate_type
  use CanopyStateType        , only : canopystate_type
  use TemperatureType        , only : temperature_type
  use PhotosynthesisMod      , only : photosyns_type
  use CNVegcarbonfluxType    , only : cnveg_carbonflux_type
  use CNVegnitrogenstateType , only : cnveg_nitrogenstate_type
  use CNSharedParamsMod      , only : CNParamsShareInst
  use PatchType              , only : patch                
  !
  implicit none
  private
  !
  ! !PUBLIC MEMBER FUNCTIONS:
  public :: CNMRespReadNML       ! Read in namelist (CALL FIRST!)
  public :: readParams           ! Read in parameters from file
  public :: CNMResp              ! Apply maintenance respiration

  type, private :: params_type
     real(r8) :: br      = spval ! base rate for maintenance respiration (gC/gN/s)
     real(r8) :: br_root = spval ! base rate for maintenance respiration for roots (gC/gN/s)
  end type params_type

  type(params_type), private :: params_inst

  character(len=*), parameter, private :: sourcefile = &
       __FILE__
  !-----------------------------------------------------------------------

contains

  !-----------------------------------------------------------------------
  subroutine CNMRespReadNML( NLFilename )
    !
    ! !DESCRIPTION:
    ! Read the namelist for CNMResp (MUST BE CALLED BEFORE readParams!!!)
    !
    ! !USES:
    use fileutils      , only : getavu, relavu, opnfil
    use shr_nl_mod     , only : shr_nl_find_group_name
    use spmdMod        , only : masterproc, mpicom
    use shr_mpi_mod    , only : shr_mpi_bcast
    use clm_varctl     , only : iulog
    !
    ! !ARGUMENTS:
    character(len=*), intent(in) :: NLFilename ! Namelist filename
    !
    ! !LOCAL VARIABLES:
    integer :: ierr                 ! error code
    integer :: unitn                ! unit for namelist file

    character(len=*), parameter :: subname = 'CNMRespReadNML'
    character(len=*), parameter :: nmlname = 'cnmresp_inparm'
    real(r8) :: br_root = spval ! base rate for maintenance respiration for roots (gC/gN/s)
    !-----------------------------------------------------------------------

    namelist /cnmresp_inparm/ br_root

    ! Initialize options to default values, in case they are not specified in
    ! the namelist

    if (masterproc) then
       unitn = getavu()
       write(iulog,*) 'Read in '//nmlname//'  namelist'
       call opnfil (NLFilename, unitn, 'F')
       call shr_nl_find_group_name(unitn, nmlname, status=ierr)
       if (ierr == 0) then
          read(unitn, nml=cnmresp_inparm, iostat=ierr)
          if (ierr /= 0) then
             call endrun(msg="ERROR reading "//nmlname//"namelist"//errmsg(sourcefile, __LINE__))
          end if
       else
          call endrun(msg="ERROR finding "//nmlname//"namelist"//errmsg(sourcefile, __LINE__))
       end if
       call relavu( unitn )
    end if

    call shr_mpi_bcast (br_root, mpicom)

    params_inst%br_root = br_root

    if (masterproc) then
       write(iulog,*) ' '
       write(iulog,*) nmlname//' settings:'
       write(iulog,nml=cnmresp_inparm)
       write(iulog,*) ' '
    end if

  end subroutine CNMRespReadNML
  !-----------------------------------------------------------------------

  !-----------------------------------------------------------------------
  subroutine readParams ( ncid )
    !
    ! !DESCRIPTION:
    ! Read parameters (call AFTER CNMRespReadNML!)
    !
    ! !USES:
    use ncdio_pio , only : file_desc_t,ncd_io
    !
    ! !ARGUMENTS:
    implicit none
    type(file_desc_t),intent(inout) :: ncid   ! pio netCDF file id
    !
    ! !LOCAL VARIABLES:
    character(len=32)  :: subname = 'CNMRespParamsType'
    character(len=100) :: errCode = '-Error reading in parameters file:'
    logical            :: readv ! has variable been read in or not
    real(r8)           :: tempr ! temporary to read in constant
    character(len=100) :: tString ! temp. var for reading
    !-----------------------------------------------------------------------

    tString='br_mr'
    call ncd_io(varname=trim(tString),data=tempr, flag='read', ncid=ncid, readvar=readv)
    if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__))
    params_inst%br=tempr

    if ( params_inst%br_root == spval ) then
       params_inst%br_root = params_inst%br
    end if

  end subroutine readParams

  !-----------------------------------------------------------------------
  ! FIX(SPM,032414) this shouldn't even be called with fates on.
  !
  subroutine CNMResp(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, &
       canopystate_inst, soilstate_inst, temperature_inst, photosyns_inst, &
       cnveg_carbonflux_inst, cnveg_nitrogenstate_inst)
    !
    ! !DESCRIPTION:
    !
    ! !ARGUMENTS:
    use clm_varcon  , only : tfrz
    
    type(bounds_type)              , intent(in)    :: bounds          
    integer                        , intent(in)    :: num_soilc       ! number of soil points in column filter
    integer                        , intent(in)    :: filter_soilc(:) ! column filter for soil points
    integer                        , intent(in)    :: num_soilp       ! number of soil points in patch filter
    integer                        , intent(in)    :: filter_soilp(:) ! patch filter for soil points
    type(canopystate_type)         , intent(in)    :: canopystate_inst
    type(soilstate_type)           , intent(in)    :: soilstate_inst
    type(temperature_type)         , intent(in)    :: temperature_inst
    type(photosyns_type)           , intent(in)    :: photosyns_inst
    type(cnveg_carbonflux_type)    , intent(inout) :: cnveg_carbonflux_inst
    type(cnveg_nitrogenstate_type) , intent(in)    :: cnveg_nitrogenstate_inst
    !
    ! !LOCAL VARIABLES:
    integer :: c,p,j   ! indices
    integer :: fp      ! soil filter patch index
    integer :: fc      ! soil filter column index
    real(r8):: br      ! base rate (gC/gN/s)
    real(r8):: br_root ! root base rate (gC/gN/s)
    real(r8):: q10     ! temperature dependence

    real(r8):: tc      ! temperature correction, 2m air temp (unitless)
    real(r8):: tcsoi(bounds%begc:bounds%endc,nlevgrnd) ! temperature correction by soil layer (unitless)
    !-----------------------------------------------------------------------

    associate(                                                            &    
         ivt            =>    patch%itype                                 , & ! Input:  [integer  (:)   ]  patch vegetation type                                

         woody          =>    pftcon%woody                              , & ! Input:  binary flag for woody lifeform (1=woody, 0=not woody)

         frac_veg_nosno =>    canopystate_inst%frac_veg_nosno_patch     , & ! Input:  [integer  (:)   ]  fraction of vegetation not covered by snow (0 OR 1) [-]
         laisun         =>    canopystate_inst%laisun_patch             , & ! Input:  [real(r8) (:)   ]  sunlit projected leaf area index                  
         laisha         =>    canopystate_inst%laisha_patch             , & ! Input:  [real(r8) (:)   ]  shaded projected leaf area index                  

         crootfr        =>    soilstate_inst%crootfr_patch              , & ! Input:  [real(r8) (:,:) ]  fraction of roots for carbon in each soil layer  (nlevgrnd)

         t_soisno       =>    temperature_inst%t_soisno_col             , & ! Input:  [real(r8) (:,:) ]  soil temperature (Kelvin)  (-nlevsno+1:nlevgrnd)
         t_ref2m        =>    temperature_inst%t_ref2m_patch            , & ! Input:  [real(r8) (:)   ]  2 m height surface air temperature (Kelvin)       

         t10            => temperature_inst%t_a10_patch                 , & ! Input:  [real(r8) (:)   ]  10-day running mean of the 2 m temperature (K)
 
         lmrsun         =>    photosyns_inst%lmrsun_patch               , & ! Input:  [real(r8) (:)   ]  sunlit leaf maintenance respiration rate (umol CO2/m**2/s)
         lmrsha         =>    photosyns_inst%lmrsha_patch               , & ! Input:  [real(r8) (:)   ]  shaded leaf maintenance respiration rate (umol CO2/m**2/s)
         rootstem_acc   =>    photosyns_inst%rootstem_acc               , & ! Input:  [logical        ]  root and stem acclimation switch

         frootn         =>    cnveg_nitrogenstate_inst%frootn_patch     , & ! Input:  [real(r8) (:)   ]  (gN/m2) fine root N                               
         livestemn      =>    cnveg_nitrogenstate_inst%livestemn_patch  , & ! Input:  [real(r8) (:)   ]  (gN/m2) live stem N                               
         livecrootn     =>    cnveg_nitrogenstate_inst%livecrootn_patch , & ! Input:  [real(r8) (:)   ]  (gN/m2) live coarse root N                        
         grainn         =>    cnveg_nitrogenstate_inst%grainn_patch     , & ! Input:  [real(r8) (:)   ]  (kgN/m2) grain N

         leaf_mr        =>    cnveg_carbonflux_inst%leaf_mr_patch       , & ! Output: [real(r8) (:)   ]                                                    
         froot_mr       =>    cnveg_carbonflux_inst%froot_mr_patch      , & ! Output: [real(r8) (:)   ]                                                    
         livestem_mr    =>    cnveg_carbonflux_inst%livestem_mr_patch   , & ! Output: [real(r8) (:)   ]                                                    
         livecroot_mr   =>    cnveg_carbonflux_inst%livecroot_mr_patch  , & ! Output: [real(r8) (:)   ]                                                    
         grain_mr       =>    cnveg_carbonflux_inst%grain_mr_patch        & ! Output: [real(r8) (:)   ]                                                    

         )

      ! base rate for maintenance respiration is from:
      ! M. Ryan, 1991. Effects of climate change on plant respiration.
      ! Ecological Applications, 1(2), 157-167.
      ! Original expression is br = 0.0106 molC/(molN h)
      ! Conversion by molecular weights of C and N gives 2.525e-6 gC/(gN s)
      ! set constants
      br      = params_inst%br
      br_root = params_inst%br_root
     
      ! Peter Thornton: 3/13/09 
      ! Q10 was originally set to 2.0, an arbitrary choice, but reduced to 1.5 as part of the tuning
      ! to improve seasonal cycle of atmospheric CO2 concentration in global
      ! simulatoins
      Q10 = CNParamsShareInst%Q10

      ! column loop to calculate temperature factors in each soil layer
      do j=1,nlevgrnd
         do fc = 1, num_soilc
            c = filter_soilc(fc)

            ! calculate temperature corrections for each soil layer, for use in
            ! estimating fine root maintenance respiration with depth
            tcsoi(c,j) = Q10**((t_soisno(c,j)-SHR_CONST_TKFRZ - 20.0_r8)/10.0_r8)
         end do
      end do

      ! patch loop for leaves and live wood
      do fp = 1, num_soilp
         p = filter_soilp(fp)

         ! calculate maintenance respiration fluxes in
         ! gC/m2/s for each of the live plant tissues.
         ! Leaf and live wood MR

         tc = Q10**((t_ref2m(p)-SHR_CONST_TKFRZ - 20.0_r8)/10.0_r8)
         
         !RF: acclimation of root and stem respiration fluxes
         ! n.b. we do not yet know if this is defensible scientifically (awaiting data analysis)
         ! turning this on will increase R and decrease productivity in boreal forests, A LOT. :)

         if(rootstem_acc)then 
           br      = br      * 10._r8**(-0.00794_r8*((t10(p)-tfrz)-25._r8))
           br_root = br_root * 10._r8**(-0.00794_r8*((t10(p)-tfrz)-25._r8))
         end if

         if (frac_veg_nosno(p) == 1) then

            leaf_mr(p) = lmrsun(p) * laisun(p) * 12.011e-6_r8 + &
                         lmrsha(p) * laisha(p) * 12.011e-6_r8

         else !nosno

            leaf_mr(p) = 0._r8

         end if

         if (woody(ivt(p)) == 1) then
            livestem_mr(p) = livestemn(p)*br*tc
            livecroot_mr(p) = livecrootn(p)*br_root*tc
         else if (ivt(p) >= npcropmin) then
            livestem_mr(p) = livestemn(p)*br*tc
            grain_mr(p) = grainn(p)*br*tc
         end if
      end do

      ! soil and patch loop for fine root

      do j = 1,nlevgrnd
         do fp = 1,num_soilp
            p = filter_soilp(fp)
            c = patch%column(p)

            ! Fine root MR
            ! crootfr(j) sums to 1.0 over all soil layers, and
            ! describes the fraction of root mass for carbon that is in each
            ! layer.  This is used with the layer temperature correction
            ! to estimate the total fine root maintenance respiration as a
            ! function of temperature and N content.
            if(rootstem_acc)then
               br_root = br_root * 10._r8**(-0.00794_r8*((t10(p)-tfrz)-25._r8))
            end if
            froot_mr(p) = froot_mr(p) + frootn(p)*br_root*tcsoi(c,j)*crootfr(p,j)
            
         end do
      end do

    end associate

  end subroutine CNMResp

end module CNMRespMod
