#!/usr/bin/env python
#in app_nameNlayer write three files
#CMakeLists.txt
#app_nameBGCReactionsType.F90
#app_namePlantSoilBGCType.F90

def MakeNlayer(sfarm_dir, app_name):
    print "create file "+sfarm_dir+'/'+app_name+'/'+app_name+'Nlayer'+"/CMakeLists.txt"
    fcmake=open(sfarm_dir+'/'+app_name+'/'+app_name+'Nlayer'+"/CMakeLists.txt","w")
    fcmake.write("set("+app_name.upper()+"NLAYER_SOURCES\n")
    fcmake.write("  "+app_name+"BGCReactionsType.F90\n")
    fcmake.write("  "+app_name+"PlantSoilBGCType.F90\n")
    fcmake.write(")\n")
    fcmake.write("\n")
    fcmake.write("include_directories(${CMAKE_BINARY_DIR}/src/betr/betr_util)\n")
    fcmake.write("include_directories(${CMAKE_BINARY_DIR}/src/betr/betr_math)\n")
    fcmake.write("include_directories(${CMAKE_BINARY_DIR}/src/betr/betr_bgc)\n")
    fcmake.write("include_directories(${CMAKE_BINARY_DIR}/src/betr/betr_grid)\n")
    fcmake.write("include_directories(${CMAKE_BINARY_DIR}/src/betr/betr_dtype)\n")
    fcmake.write("include_directories(${CMAKE_BINARY_DIR}/src/betr/betr_core)\n")
    fcmake.write("include_directories(${CMAKE_BINARY_DIR}/src/Applications/soil-farm/bgcfarm_util)\n")
    fcmake.write("include_directories(${CMAKE_BINARY_DIR}/src/Applications/soil-farm/"+app_name+"/"+app_name+"Para)\n")
    fcmake.write("include_directories(${CMAKE_BINARY_DIR}/src/Applications/soil-farm/"+app_name+"/"+app_name+"1layer)\n")
    fcmake.write("include(add_betr_library)\n")
    fcmake.write("add_betr_library("+app_name+"Nlayer ${"+app_name.upper()+"NLAYER_SOURCES})\n")

    fcmake.write("set(BETR_LIBRARIES "+app_name+"Nlayer;${BETR_LIBRARIES} PARENT_SCOPE)\n")
    fcmake.write("set(BETR_LIBRARIES "+app_name+"Nlayer;${BETR_LIBRARIES})\n")

#X#add_subdirectory(tests)

    fcmake.write('if (NOT CMAKE_INSTALL_PREFIX STREQUAL "INSTALL_DISABLED")\n')
    fcmake.write("  install(TARGETS "+app_name+"Nlayer DESTINATION lib)\n")
    fcmake.write("  file(GLOB HEADERS *.h)\n")
    fcmake.write("  install(FILES ${HEADERS} DESTINATION include/soil-farm/"+app_name+"/"+app_name+"Nlayer)\n")
    fcmake.write("endif()\n")
    fcmake.close()
#app_nameBGCReactionsType.F90
    print "create file "+sfarm_dir+'/'+app_name+'/'+app_name+'Nlayer/'+app_name+"BGCReactionsType.F90"
    ff90=open(sfarm_dir+'/'+app_name+'/'+app_name+'Nlayer/'+app_name+"BGCReactionsType.F90","w")
    ff90.write("module "+app_name+"BGCReactionsType\n")
    import datetime
    ff90.write('#include "bshr_assert.h"\n')
    ff90.write("!\n")
    ff90.write("! !DESCRIPTION:\n")
    ff90.write("! This is an example generated from AppMaker for use in betr\n")
    ff90.write("!\n")
    ff90.write("! HISTORY:\n")
    ff90.write("! Created by Jinyun Tang, "+datetime.date.today().strftime("%B %d, %Y")+"\n")
    ff90.write("! !USES:\n")
    ff90.write("  use bshr_log_mod             , only : errMsg => shr_log_errMsg\n")
    ff90.write("  use bshr_kind_mod            , only : r8 => shr_kind_r8\n")
    ff90.write("  use BeTR_decompMod           , only : bounds_type  => betr_bounds_type\n")
    ff90.write("  use BGCReactionsMod          , only : bgc_reaction_type\n")
    ff90.write("  use tracer_varcon            , only : bndcond_as_conc, bndcond_as_flux\n")
    ff90.write("  use BeTR_biogeophysInputType , only : betr_biogeophys_input_type\n")
    ff90.write("  use BetrStatusType           , only : betr_status_type\n")
    ff90.write("  use "+app_name+"ParaType            , only : "+app_name+"_para\n")
    ff90.write("  use "+app_name+"BGCIndexType        , only : "+app_name+"_bgc_index_type\n")
    ff90.write("  use "+app_name+"BGCType             , only : "+app_name+"_bgc_type\n")
    ff90.write("  use JarBgcForcType           , only : JarBGC_forc_type\n")
    ff90.write("implicit none\n")
    ff90.write("\n")
    ff90.write("  private\n")

    ff90.write("  character(len=*), parameter :: mod_filename = &\n")
    ff90.write("    __FILE__\n")

    ff90.write("  public :: "+app_name+"_bgc_reaction_type\n")

    ff90.write("  type, extends(bgc_reaction_type) :: &\n")
    ff90.write("    "+app_name+"_bgc_reaction_type\n")
    ff90.write("  private\n")
    ff90.write("    type("+app_name+"_bgc_type), pointer :: "+app_name+"_bgc(:,:)\n")
    ff90.write("    type(JarBGC_forc_type), pointer :: "+app_name+"_forc(:,:)\n")
    ff90.write("    type("+app_name+"_bgc_index_type) :: "+app_name+"_bgc_index\n")
    ff90.write("    logical :: use_c13\n")
    ff90.write("    logical :: use_c14\n")
    ff90.write("    logical :: nop_limit\n")
    ff90.write("    logical :: non_limit\n")
    ff90.write("    integer :: nactpft               ! number of active pfts\n")
    ff90.write("  contains\n")
    ff90.write("    procedure :: Init_betrbgc                          ! initialize betr bgc\n")
    ff90.write("    procedure :: set_boundary_conditions               ! set top/bottom boundary conditions for various tracers\n")
    ff90.write("    procedure :: calc_bgc_reaction                     ! doing bgc calculation\n")
    ff90.write("    procedure :: init_boundary_condition_type          ! initialize type of top boundary conditions\n")
    ff90.write("    procedure :: do_tracer_equilibration               ! do equilibrium tracer chemistry\n")
    ff90.write("    procedure :: InitCold                              ! do cold initialization\n")
    ff90.write("    procedure :: retrieve_biogeoflux           !\n")
    ff90.write("    procedure :: set_kinetics_par\n")
    ff90.write("    procedure :: retrieve_lnd2atm\n")
    ff90.write("    procedure :: readParams                   ! read in parameters\n")
    ff90.write("    procedure :: retrieve_biostates\n")
    ff90.write("    procedure :: debug_info\n")
    ff90.write("    procedure :: set_bgc_spinup\n")
    ff90.write("    procedure :: UpdateParas\n")
    ff90.write("    procedure :: init_iP_prof\n")
    ff90.write("    procedure, private :: set_tracer\n")
    ff90.write("    procedure, private :: InitAllocate\n")
    ff90.write("    procedure, private :: retrieve_output\n")
    ff90.write("    procedure, private :: set_bgc_forc\n")
    ff90.write("  end type "+app_name+"_bgc_reaction_type\n")
    ff90.write("\n")
    ff90.write("  interface "+app_name+"_bgc_reaction_type\n")
    ff90.write("    module procedure constructor\n")
    ff90.write("  end interface "+app_name+"_bgc_reaction_type\n")
    ff90.write("\n")
    ff90.write("contains\n")
    ff90.write("!-------------------------------------------------------------------------------\n")
    ff90.write("  type("+app_name+"_bgc_reaction_type) function constructor()\n")
    ff90.write("  !\n")
    ff90.write("  ! !DESCRIPTION:\n")
    ff90.write("  ! create an object of type "+app_name+"_bgc_reaction_type.\n")
    ff90.write("\n")
    ff90.write("  type("+app_name+"_bgc_reaction_type), allocatable :: bgc\n")
    ff90.write("  allocate(bgc)\n")
    ff90.write("  constructor = bgc\n")
    ff90.write("  end function constructor\n")
    ff90.write("!-------------------------------------------------------------------------------\n")
    ff90.write("  subroutine UpdateParas(this, bounds, lbj, ubj, bstatus)\n")
    ff90.write("  implicit none\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type)         , intent(inout)    :: this\n")
    ff90.write("  type(bounds_type)                    , intent(in)    :: bounds\n")
    ff90.write("  integer                              , intent(in)    :: lbj, ubj        ! lower and upper bounds, make sure they are > 0\n")
    ff90.write("  type(betr_status_type)               , intent(out)   :: bstatus\n")
    ff90.write("  integer :: c, j\n")
    ff90.write("\n")
    ff90.write("  if (this%dummy_compiler_warning) continue\n")
    ff90.write("  call bstatus%reset()\n")
    ff90.write('  !do nothing\n')
    ff90.write("  end subroutine UpdateParas\n")
    ff90.write("!----------------------------------------------------------------------\n")
    ff90.write("  subroutine init_iP_prof(this, bounds, lbj, ubj, biophysforc, tracers, tracerstate_vars)\n")
    ff90.write("  !\n")
    ff90.write("  !DESCRIPTION\n")
    ff90.write("  ! set up initial inorganic P profile\n")
    ff90.write("  use tracer_varcon, only : patomw\n")
    ff90.write("  use tracerstatetype        , only : tracerstate_type\n")
    ff90.write("  use BeTRTracerType         , only : betrtracer_type\n")
    ff90.write("  implicit none\n")
    ff90.write("  ! !ARGUMENTS:\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type)         , intent(inout)    :: this\n")
    ff90.write("  type(bounds_type)                        , intent(in) :: bounds\n")
    ff90.write("  integer                                  , intent(in) :: lbj, ubj\n")
    ff90.write("  type(betr_biogeophys_input_type)        , intent(inout) :: biophysforc\n")
    ff90.write("  type(BeTRtracer_type)                    , intent(inout) :: tracers\n")
    ff90.write("  type(tracerstate_type)                   , intent(inout) :: tracerstate_vars\n")
    ff90.write("\n")
    ff90.write("  if (this%dummy_compiler_warning) continue\n")
    ff90.write("  if (bounds%begc > 0) continue\n")
    ff90.write("\n")
    ff90.write("  end subroutine init_iP_prof\n")
    ff90.write("!----------------------------------------------------------------------\n")
    ff90.write("  subroutine set_kinetics_par(this, lbj, ubj, nactpft, plantNutkinetics, tracercoeff_vars)\n")
    ff90.write("  !\n")
    ff90.write("  !DESCRIPTION\n")
    ff90.write("  !set up kinetic parameters needed by the model\n")
    ff90.write("  use PlantNutKineticsMod, only : PlantNutKinetics_type\n")
    ff90.write("  use tracercoeffType          , only : tracercoeff_type\n")
    ff90.write("  ! !ARGUMENTS:\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type)         , intent(inout)    :: this\n")
    ff90.write("  class(PlantNutKinetics_type), intent(in) :: plantNutkinetics\n")
    ff90.write("  type(tracercoeff_type), intent(inout) :: tracercoeff_vars\n")
    ff90.write("  integer, intent(in) :: lbj, ubj\n")
    ff90.write("  integer, intent(in) :: nactpft\n")
    ff90.write("  integer :: c_l, p, j\n")
    ff90.write("  !in the following, only one column is assumed for the bgc\n")
    ff90.write("  c_l = 1\n")
    ff90.write("  this%nactpft = nactpft\n")
    ff90.write("  do j = lbj, ubj\n")
    ff90.write("    !effective p competing decomposers\n")
    ff90.write("  enddo\n")
    ff90.write("  end subroutine set_kinetics_par\n")
    ff90.write("!-------------------------------------------------------------------------------\n")
    ff90.write("  subroutine init_boundary_condition_type(this, bounds, betrtracer_vars, tracerboundarycond_vars )\n")
    ff90.write("  !\n")
    ff90.write("  ! !DESCRIPTION:\n")
    ff90.write("  ! initialize boundary condition types\n")
    ff90.write("  !\n")
    ff90.write("  ! !USES:\n")
    ff90.write("  use BeTRTracerType        , only : betrtracer_type\n")
    ff90.write("  use TracerBoundaryCondType, only : tracerboundarycond_type\n")
    ff90.write("  use tracer_varcon         , only : bndcond_as_conc, bndcond_as_flux\n")
    ff90.write("  use BeTRTracerType        , only : betrtracer_type\n")
    ff90.write("  ! !ARGUMENTS:\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type), intent(inout) :: this\n")
    ff90.write("  type(BeTRtracer_type),             intent(in) :: betrtracer_vars\n")
    ff90.write("  type(bounds_type),                 intent(in) :: bounds\n")
    ff90.write("  type(tracerboundarycond_type),     intent(in) :: tracerboundarycond_vars\n")
    ff90.write("  ! !LOCAL VARIABLES:\n")
    ff90.write(" \n")
    ff90.write("  ! remove compiler warnings for unused dummy args\n")
    ff90.write("  if (this%dummy_compiler_warning) continue\n")
    ff90.write("  if (bounds%begc > 0) continue\n")
    ff90.write("  if (len(betrtracer_vars%betr_simname) > 0) continue\n")
    ff90.write("  tracerboundarycond_vars%topbc_type(:) = bndcond_as_conc\n")
    ff90.write("  !when bottom BC is not given, it is specified as constant flux\n")
    ff90.write("  !X!tracerboundarycond_vars%botbc_type(:) = bndcond_as_flux\n")
    ff90.write("  end subroutine init_boundary_condition_type\n")
    ff90.write("!-------------------------------------------------------------------------------\n")
    ff90.write("\n")
    ff90.write("subroutine set_bgc_spinup(this, bounds, lbj, ubj, biophysforc, &\n")
    ff90.write("  tracers, tracerstate_vars)\n")
    ff90.write("  use tracerstatetype        , only : tracerstate_type\n")
    ff90.write("  use BeTRTracerType         , only : betrtracer_type\n")
    ff90.write("  use BeTR_decompMod         , only : betr_bounds_type\n")
    ff90.write("\n")
    ff90.write("  implicit none\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type), intent(inout)    :: this\n")
    ff90.write("  type(betr_bounds_type)                  , intent(in) :: bounds\n")
    ff90.write("  integer                                 , intent(in) :: lbj, ubj\n")
    ff90.write("  type(betr_biogeophys_input_type)        , intent(inout) :: biophysforc\n")
    ff90.write("  type(BeTRtracer_type)                   , intent(inout) :: tracers\n")
    ff90.write("  type(tracerstate_type)                  , intent(inout) :: tracerstate_vars\n")
    ff90.write("\n")
    ff90.write("  if (this%dummy_compiler_warning) continue\n")
    ff90.write("  if (bounds%begc > 0) continue\n")
    ff90.write("  end subroutine set_bgc_spinup\n")
    ff90.write("!-------------------------------------------------------------------------------\n")
    ff90.write("  subroutine InitAllocate(this, bounds, lbj, ubj, bstatus)\n")
    ff90.write("  !\n")
    ff90.write("  !!DESCRIPTION\n")
    ff90.write("  !allocate memory\n")
    ff90.write("  use betr_varcon                      , only : betr_maxpatch_pft\n")
    ff90.write("  implicit none\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type), intent(inout)    :: this\n")
    ff90.write("  type(betr_status_type)           , intent(out)   :: bstatus\n")
    ff90.write("  type(bounds_type)                , intent(in)    :: bounds\n")
    ff90.write("  integer                          , intent(in)    :: lbj, ubj\n")
    ff90.write("  integer :: j, c\n")
    ff90.write("  logical :: batch_mode\n")
    ff90.write("  batch_mode =.false.\n")
    ff90.write("  this%nactpft = 0\n")
    ff90.write("\n")
    ff90.write("  call this%"+app_name+"_bgc_index%Init()\n")
    ff90.write("  !create the models\n")
    ff90.write("  allocate(this%"+app_name+"_bgc(bounds%begc:bounds%endc,lbj:ubj))\n")
    ff90.write("  !create model specific forcing data structure\n")
    ff90.write("  allocate(this%"+app_name+"_forc(bounds%begc:bounds%endc,lbj:ubj))\n")
    ff90.write("  !initialize\n")
    ff90.write("  do j = lbj, ubj\n")
    ff90.write("    do c = bounds%begc, bounds%endc\n")
    ff90.write("      call this%"+app_name+"_bgc(c,j)%Init(batch_mode, bstatus)\n")
    ff90.write("      if(bstatus%check_status())return\n")
    ff90.write("      call this%"+app_name+"_forc(c,j)%Init(this%"+app_name+"_bgc_index%nstvars)\n")
    ff90.write("    enddo\n")
    ff90.write("  enddo\n")
    ff90.write("  end subroutine InitAllocate\n")
    ff90.write("!-------------------------------------------------------------------------------\n")
    ff90.write("  subroutine Init_betrbgc(this, bounds, lbj, ubj, betrtracer_vars, namelist_buffer, bstatus)\n")
    ff90.write("!\n")
    ff90.write("! DESCRIPTION:\n")
    ff90.write("! initialize the betrbgc\n")
    ff90.write("!\n")
    ff90.write("! !USES:\n")
    ff90.write("  use BeTRTracerType , only : betrtracer_type\n")
    ff90.write("  use BetrStatusType , only : betr_status_type\n")
    ff90.write("  use gbetrType      , only : gbetr_type\n")
    ff90.write("  implicit none\n")
    ff90.write("  ! !ARGUMENTS:\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type), intent(inout)    :: this\n")
    ff90.write("  type(bounds_type)                , intent(in)    :: bounds\n")
    ff90.write("  integer                          , intent(in)    :: lbj, ubj\n")
    ff90.write("  type(BeTRtracer_type )           , intent(inout) :: betrtracer_vars\n")
    ff90.write("  character(len=*)                 , intent(in)    :: namelist_buffer\n")
    ff90.write("  type(betr_status_type)           , intent(out)   :: bstatus\n")
    ff90.write("  !LOCAL VARIABLES\n")
    ff90.write("  character(len=*), parameter                      :: subname ='Init_betrbgc'\n")
    ff90.write("  call bstatus%reset()\n")
    ff90.write("  ! remove compiler warnings for unused dummy args\n")
    ff90.write("  if (this%dummy_compiler_warning)           continue\n")
    ff90.write("  if (bounds%begc > 0)                       continue\n")
    ff90.write("  if (ubj > lbj)                             continue\n")
    ff90.write("  if (len(betrtracer_vars%betr_simname) > 0) continue\n")
    ff90.write("  call this%InitAllocate(bounds, lbj, ubj, bstatus)\n")
    ff90.write("  if(bstatus%check_status())return\n")

    ff90.write("  call this%set_tracer(betrtracer_vars, bstatus)\n")
    ff90.write("  end subroutine Init_betrbgc\n")
    ff90.write("!-------------------------------------------------------------------------------\n")
    ff90.write("  subroutine set_tracer(this, betrtracer_vars, bstatus)\n")
    ff90.write("  use BeTRTracerType  , only : betrtracer_type\n")
    ff90.write("  use MathfuncMod     , only : addone\n")
    ff90.write("  implicit none\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type), intent(inout)    :: this\n")
    ff90.write("  type(BeTRtracer_type )           , intent(inout) :: betrtracer_vars\n")
    ff90.write("  type(betr_status_type)           , intent(out)   :: bstatus\n")
    ff90.write("  !LOCAL VARIABLES\n")
    ff90.write("  integer :: itemp_gwm\n")
    ff90.write("  integer :: itemp_g\n")
    ff90.write("  integer :: itemp_s\n")
    ff90.write("  integer :: itemp_gwm_grp\n")
    ff90.write("  integer :: dum, itemp\n")
    ff90.write("  integer :: itemp_grp, itemp_v, itemp_vgrp, itemp_trc, itemp_ads, itemp_ads_grp\n")
    ff90.write("  integer :: litr_cnt, wood_cnt, Bm_cnt, trcid, itemp_mem, ngroupmems\n")
    ff90.write("\n")

    ff90.write("  itemp_gwm     = 0\n")
    ff90.write("  itemp_g       = 0\n")
    ff90.write("  itemp_s       = 0\n")
    ff90.write("  itemp_gwm_grp = 0\n")
    ff90.write("  itemp_ads_grp =0!counter for sorptive groups\n")
    ff90.write("  itemp_ads=0     !counter for sorptive tracers\n")
    ff90.write("  !volatile tracers\n")
    ff90.write("  itemp = 0; itemp_trc=0\n")
    ff90.write("  call betrtracer_vars%add_tracer_group(trc_grp_cnt=addone(itemp),  mem = 1, &\n")
    ff90.write("    trc_cnt = itemp_trc, trc_grp=betrtracer_vars%id_trc_no3x, &\n")
    ff90.write("    trc_grp_beg=betrtracer_vars%id_trc_beg_no3x, &\n")
    ff90.write("    trc_grp_end=betrtracer_vars%id_trc_end_no3x, &\n")
    ff90.write("    is_trc_gw=.true., is_trc_volatile = .false.)\n")
    ff90.write("\n")
    ff90.write("  betrtracer_vars%nmem_max               = 1\n")
    ff90.write("\n")
    ff90.write("  call betrtracer_vars%Init()\n")
    ff90.write("\n")
    ff90.write("  itemp_grp = 0    !group id\n")
    ff90.write("  itemp_v = 0      !volatile id\n")
    ff90.write("  itemp_vgrp = 0   !volatile group\n")
    ff90.write("\n")
    ff90.write("  call betrtracer_vars%set_tracer(bstatus=bstatus,trc_id = betrtracer_vars%id_trc_no3x, &\n")
    ff90.write("    trc_name='NO3x', is_trc_mobile=.true., is_trc_advective = .true., &\n")
    ff90.write("    trc_group_id = betrtracer_vars%id_trc_no3x, trc_group_mem = 1, is_trc_volatile=.false., &\n")
    ff90.write("    trc_vtrans_scal=1._r8)\n")
    ff90.write("  if(bstatus%check_status())return\n")
    ff90.write("  end subroutine set_tracer\n")
    ff90.write("!-------------------------------------------------------------------------------\n")
    ff90.write("  subroutine set_boundary_conditions(this, bounds, num_soilc, filter_soilc, dz_top, betrtracer_vars, &\n")
    ff90.write("   biophysforc, biogeo_flux, tracercoeff_vars, tracerboundarycond_vars, betr_status)\n")
    ff90.write("  !\n")
    ff90.write("  ! !DESCRIPTION:\n")
    ff90.write("  ! set up boundary conditions for tracer movement\n")
    ff90.write("  !\n")
    ff90.write("  ! !USES:\n")
    ff90.write("  use betr_ctrl              , only : iulog  => biulog\n")
    ff90.write("  use TracerBoundaryCondType , only : tracerboundarycond_type\n")
    ff90.write("  use bshr_log_mod           , only : errMsg => shr_log_errMsg\n")
    ff90.write("  use BeTRTracerType         , only : betrtracer_type\n")
    ff90.write("  use betr_varcon            , only : rgas => brgas\n")
    ff90.write("  use BeTR_biogeoFluxType    , only : betr_biogeo_flux_type\n")
    ff90.write("  use BetrStatusType         , only : betr_status_type\n")
    ff90.write("  use UnitConvertMod          , only : ppm2molv\n")
    ff90.write("  use TracerCoeffType        , only : tracercoeff_type\n")
    ff90.write("  implicit none\n")
    ff90.write("  ! !ARGUMENTS:\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type) , intent(inout)    :: this        !\n")
    ff90.write("  type(bounds_type)                 , intent(in)    :: bounds             !\n")
    ff90.write("  integer                           , intent(in)    :: num_soilc                  ! number of columns in column filter_soilc\n")
    ff90.write("  integer                           , intent(in)    :: filter_soilc(:)            ! column filter_soilc\n")
    ff90.write("  type(betrtracer_type)             , intent(in)    :: betrtracer_vars            !\n")
    ff90.write("  real(r8)                          , intent(in)    :: dz_top(bounds%begc: )      !\n")
    ff90.write("  type(betr_biogeophys_input_type)  , intent(in)    :: biophysforc\n")
    ff90.write("  type(betr_biogeo_flux_type)       , intent(in)    :: biogeo_flux\n")
    ff90.write("  type(tracercoeff_type)             , intent(in)   :: tracercoeff_vars\n")
    ff90.write("  type(tracerboundarycond_type)     , intent(inout) :: tracerboundarycond_vars !\n")
    ff90.write("  type(betr_status_type)            , intent(out)   :: betr_status\n")
    ff90.write("\n")
    ff90.write("  ! !LOCAL VARIABLES:\n")
    ff90.write("  integer            :: fc, c\n")
    ff90.write("  character(len=255) :: subname = 'set_boundary_conditions'\n")
    ff90.write("  real(r8) :: irt   !the inverse of R*T\n")
    ff90.write("\n")
    ff90.write("  call betr_status%reset()\n")
    ff90.write("  SHR_ASSERT_ALL((ubound(dz_top)  == (/bounds%endc/)),   errMsg(mod_filename,__LINE__), betr_status)\n")
    ff90.write("\n")
    ff90.write("  ! remove compiler warnings for unused dummy args\n")
    ff90.write("  if (this%dummy_compiler_warning)      continue\n")
    ff90.write("  if (size(biogeo_flux%qflx_adv_col)>0) continue\n")
    ff90.write("\n")
    ff90.write("  associate(                                                          &\n")
    ff90.write("    forc_pbot            => biophysforc%forc_pbot_downscaled_col    , &\n")
    ff90.write("    forc_tbot            => biophysforc%forc_t_downscaled_col       , &\n")
    ff90.write("    groupid              => betrtracer_vars%groupid                   &\n")
    ff90.write("  )\n")
    ff90.write("  do fc = 1, num_soilc\n")
    ff90.write("    c = filter_soilc(fc)\n")
    ff90.write("    tracerboundarycond_vars%tracer_gwdif_concflux_top_col(c,1:2,betrtracer_vars%id_trc_no3x)  = 0._r8       !mol m-3, contant boundary condition, as concentration\n")
    ff90.write("    tracerboundarycond_vars%bot_concflux_col(c,1,:)                                          = 0._r8       !zero flux boundary condition for diffusion\n")
    ff90.write("    !set value for specific groups\n")
    ff90.write("    tracerboundarycond_vars%condc_toplay_col(c,groupid(betrtracer_vars%id_trc_no3x))          = 0._r8       !m/s surface conductance\n")
    ff90.write("  enddo\n")
    ff90.write("\n")
    ff90.write("    end associate\n")
    ff90.write("  end subroutine set_boundary_conditions\n")
    ff90.write("!-------------------------------------------------------------------------------\n")
    ff90.write("  subroutine calc_bgc_reaction(this, bounds, col, lbj, ubj, num_soilc, filter_soilc,               &\n")
    ff90.write("    num_soilp,filter_soilp, jtops, dtime, betrtracer_vars, tracercoeff_vars,  biophysforc, &\n")
    ff90.write("    tracerstate_vars, tracerflux_vars, tracerboundarycond_vars, plant_soilbgc, &\n")
    ff90.write("    biogeo_flux,  betr_status)\n")
    ff90.write("  !\n")
    ff90.write("  ! !DESCRIPTION:\n")
    ff90.write("  ! do bgc reaction\n")
    ff90.write("  !\n")
    ff90.write("  ! !USES:\n")
    ff90.write("  use TracerBoundaryCondType , only : tracerboundarycond_type\n")
    ff90.write("  use tracerfluxType         , only : tracerflux_type\n")
    ff90.write("  use tracerstatetype        , only : tracerstate_type\n")
    ff90.write("  use tracercoeffType        , only : tracercoeff_type\n")
    ff90.write("  use BetrTracerType         , only : betrtracer_type\n")
    ff90.write("  use PlantSoilBGCMod        , only : plant_soilbgc_type\n")
    ff90.write("  use BetrStatusType         , only : betr_status_type\n")
    ff90.write("  use betr_columnType        , only : betr_column_type\n")
    ff90.write("  use BeTR_biogeoFluxType    , only : betr_biogeo_flux_type\n")
    ff90.write("  use BeTR_biogeoStateType   , only : betr_biogeo_state_type\n")
    ff90.write("  implicit none\n")
    ff90.write("  !ARGUMENTS\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type) , intent(inout) :: this !\n")
    ff90.write("  type(bounds_type)                 , intent(in)    :: bounds      ! bounds\n")
    ff90.write("  type(betr_column_type)            , intent(in)    :: col\n")
    ff90.write("  integer                           , intent(in)    :: num_soilc    ! number of columns in column filter\n")
    ff90.write("  integer                           , intent(in)    :: filter_soilc(:)    ! column filter\n")
    ff90.write("  integer                           , intent(in)    :: num_soilp\n")
    ff90.write("  integer                           , intent(in)    :: filter_soilp(:)\n")
    ff90.write("  integer                           , intent(in)    :: jtops( : )  ! top index of each column\n")
    ff90.write("  integer                           , intent(in)    :: lbj, ubj    ! lower and upper bounds, make sure they are > 0\n")
    ff90.write("  real(r8)                          , intent(in)    :: dtime                       ! model time step\n")
    ff90.write("  type(betrtracer_type)             , intent(in)    :: betrtracer_vars             ! betr configuration information\n")
    ff90.write("  type(betr_biogeophys_input_type)  , intent(inout) :: biophysforc\n")
    ff90.write("  type(tracercoeff_type)            , intent(inout) :: tracercoeff_vars\n")
    ff90.write("  type(tracerstate_type)            , intent(inout) :: tracerstate_vars\n")
    ff90.write("  type(tracerflux_type)             , intent(inout) :: tracerflux_vars\n")
    ff90.write("  type(tracerboundarycond_type)     , intent(inout) :: tracerboundarycond_vars !\n")
    ff90.write("  class(plant_soilbgc_type)         , intent(inout) :: plant_soilbgc\n")
    ff90.write("  type(betr_biogeo_flux_type)       , intent(inout) :: biogeo_flux\n")
    ff90.write("  type(betr_status_type)            , intent(out)   :: betr_status\n")
    ff90.write("  character(len=*)                 , parameter     :: subname ='calc_bgc_reaction'\n")
    ff90.write("\n")
    ff90.write("  integer :: c, fc, j\n")
    ff90.write("  character(len=5) :: laystr\n")
    ff90.write("  logical :: is_surflit  !surface litter layer?\n")
    ff90.write("  integer :: nstates\n")
    ff90.write("  real(r8), allocatable :: ystates0(:)\n")
    ff90.write("  real(r8), allocatable :: ystatesf(:)\n")
    ff90.write("\n")
    ff90.write("  associate(                                                                      &\n")
    ff90.write("    tracer_mobile_phase            => tracerstate_vars%tracer_conc_mobile_col  ,  &\n")
    ff90.write("    tracer_flx_netpro_vr           => tracerflux_vars%tracer_flx_netpro_vr_col    &\n")
    ff90.write("  )\n")
    ff90.write("\n")
    ff90.write("  call betr_status%reset()\n")
    ff90.write("\n")
    ff90.write("  nstates = this%"+app_name+"_bgc_index%nstvars\n")
    ff90.write("  allocate(ystates0(nstates))\n")
    ff90.write("  allocate(ystatesf(nstates))\n")
    ff90.write("\n")
    ff90.write("  call this%set_bgc_forc(bounds, col, lbj, ubj, jtops, num_soilc, filter_soilc, &\n")
    ff90.write("    biophysforc, plant_soilbgc, betrtracer_vars, tracercoeff_vars, tracerstate_vars,betr_status)\n")
    ff90.write("\n")
    ff90.write("  do j = lbj, ubj\n")
    ff90.write("    do fc = 1, num_soilc\n")
    ff90.write("      c = filter_soilc(fc)\n")
    ff90.write("      if(j<jtops(c))cycle\n")
    ff90.write("      is_surflit=(j<=0)\n")
    ff90.write("      !do bgc reaction\n")
    ff90.write("      call this%"+app_name+"_bgc(c,j)%runbgc(is_surflit, dtime, this%"+app_name+"_forc(c,j), nstates, ystates0, ystatesf, betr_status)\n")
    ff90.write("      if(betr_status%check_status())then\n")
    ff90.write("        write(laystr,'(I2.2)')j\n")
    ff90.write("        betr_status%msg=trim(betr_status%msg)//' lay '//trim(laystr)\n")
    ff90.write("        return\n")
    ff90.write("      endif\n")
    ff90.write("\n")
    ff90.write("      call this%retrieve_output(c, j, nstates, ystates0, ystatesf, dtime, betrtracer_vars, tracerflux_vars,&\n")
    ff90.write("        tracerstate_vars, plant_soilbgc, biogeo_flux)\n")
    ff90.write("\n")
    ff90.write("    enddo\n")
    ff90.write("  enddo\n")
    ff90.write("\n")
    ff90.write("  !update phase change coefficients for tracers involved in sorptive reactions\n")
    ff90.write("  deallocate(ystates0)\n")
    ff90.write("  deallocate(ystatesf)\n")
    ff90.write("  end associate\n")
    ff90.write("  end subroutine calc_bgc_reaction\n")
    ff90.write("  !-------------------------------------------------------------------------------\n")
    ff90.write("  subroutine do_tracer_equilibration(this, bounds, lbj, ubj, jtops, num_soilc, filter_soilc, &\n")
    ff90.write("    betrtracer_vars, tracercoeff_vars, tracerstate_vars, betr_status)\n")
    ff90.write("  !\n")
    ff90.write("  ! DESCRIPTION:\n")
    ff90.write("  ! requilibrate tracers that has solid and mobile phases\n")
    ff90.write("  ! using the theory of mass action.\n")
    ff90.write("  !\n")
    ff90.write("  ! !USES:\n")
    ff90.write("  !\n")
    ff90.write("  use tracerstatetype , only : tracerstate_type\n")
    ff90.write("  use tracercoeffType , only : tracercoeff_type\n")
    ff90.write("  use BeTRTracerType  , only : betrtracer_type\n")
    ff90.write("  use BetrStatusType  , only : betr_status_type\n")
    ff90.write("  implicit none\n")
    ff90.write("  ! !ARGUMENTS:\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type) , intent(inout)    :: this\n")
    ff90.write("  type(bounds_type)                 , intent(in)    :: bounds\n")
    ff90.write("  integer                           , intent(in)    :: lbj, ubj\n")
    ff90.write("  integer                           , intent(in)    :: jtops(bounds%begc: )        ! top label of each column\n")
    ff90.write("  integer                           , intent(in)    :: num_soilc\n")
    ff90.write("  integer                           , intent(in)    :: filter_soilc(:)\n")
    ff90.write("  type(betrtracer_type)             , intent(in)    :: betrtracer_vars\n")
    ff90.write("  type(tracercoeff_type)            , intent(in)    :: tracercoeff_vars\n")
    ff90.write("  type(tracerstate_type)            , intent(inout) :: tracerstate_vars\n")
    ff90.write("  type(betr_status_type)            , intent(out)   :: betr_status\n")
    ff90.write("  !local variables\n")
    ff90.write("  character(len=255) :: subname = 'do_tracer_equilibration'\n")
    ff90.write("  call betr_status%reset()\n")
    ff90.write("  SHR_ASSERT_ALL((ubound(jtops) == (/bounds%endc/)), errMsg(mod_filename,__LINE__), betr_status)\n")
    ff90.write("\n")
    ff90.write("  ! remove compiler warnings for unused dummy args\n")
    ff90.write("  if (this%dummy_compiler_warning)                          continue\n")
    ff90.write("  if (bounds%begc > 0)                                      continue\n")
    ff90.write("  if (ubj > lbj)                                            continue\n")
    ff90.write("  if (size(jtops) > 0)                                      continue\n")
    ff90.write("  if (num_soilc > 0)                                        continue\n")
    ff90.write("  if (size(filter_soilc) > 0)                               continue\n")
    ff90.write("  if (len(betrtracer_vars%betr_simname) > 0)                continue\n")
    ff90.write("  if (size(tracerstate_vars%tracer_conc_surfwater_col) > 0) continue\n")
    ff90.write("  !continue on the simulation type, an implementation of aqueous chemistry will be\n")
    ff90.write("  !employed to separate out the adsorbed phase\n")
    ff90.write("  !It should be noted that this formulation excludes the use of linear isotherm, which\n")
    ff90.write("  !can be integrated through the retardation factor\n")
    ff90.write("  end subroutine do_tracer_equilibration\n")
    ff90.write("!-----------------------------------------------------------------------\n")
    ff90.write("  subroutine InitCold(this, bounds, col, betrtracer_vars, biophysforc, tracerstate_vars)\n")
    ff90.write("  !\n")
    ff90.write("  ! !DESCRIPTION:\n")
    ff90.write("  ! do cold initialization\n")
    ff90.write("  !\n")
    ff90.write("  ! !USES:\n")
    ff90.write("  use BeTRTracerType      , only : BeTRTracer_Type\n")
    ff90.write("  use tracerstatetype     , only : tracerstate_type\n")
    ff90.write("  use betr_varcon         , only : spval => bspval, ispval => bispval\n")
    ff90.write("  use BeTR_landvarconType , only : landvarcon  => betr_landvarcon\n")
    ff90.write("  use betr_columnType     , only : betr_column_type\n")
    ff90.write("  implicit none\n")
    ff90.write("  ! !ARGUMENTS:\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type) , intent(inout)    :: this\n")
    ff90.write("  type(bounds_type)                 , intent(in)    :: bounds\n")
    ff90.write("  type(betr_column_type)            , intent(in)    :: col\n")
    ff90.write("  type(BeTRTracer_Type)             , intent(in)    :: betrtracer_vars\n")
    ff90.write("  type(betr_biogeophys_input_type)  , intent(in)    :: biophysforc\n")
    ff90.write("  type(tracerstate_type)            , intent(inout) :: tracerstate_vars\n")
    ff90.write("  !\n")
    ff90.write("  ! !LOCAL VARIABLES:\n")
    ff90.write("  integer :: p, c, l, k, j\n")
    ff90.write("  integer :: fc       ! filter_soilc index\n")
    ff90.write("  integer :: begc, endc\n")
    ff90.write("  integer :: begg, endg\n")
    ff90.write("  integer :: trcid\n")
    ff90.write("  begc = bounds%begc; endc= bounds%endc\n")
    ff90.write("  begg = bounds%begg; endg= bounds%endg\n")
    ff90.write("\n")
    ff90.write("  do c = bounds%begc, bounds%endc\n")
    ff90.write("    !dual phase tracers\n")
    ff90.write("    tracerstate_vars%tracer_conc_mobile_col(c,:, :)          = 0._r8\n")
    ff90.write("    tracerstate_vars%tracer_conc_surfwater_col(c,:)          = 0._r8\n")
    ff90.write("    tracerstate_vars%tracer_conc_aquifer_col(c,:)            = 0._r8\n")
    ff90.write("    tracerstate_vars%tracer_conc_grndwater_col(c,:)          = 0._r8\n")
    ff90.write("    if(betrtracer_vars%nsolid_equil_tracers>0)then\n")
    ff90.write("      tracerstate_vars%tracer_conc_solid_equil_col(c, :, :) = 0._r8\n")
    ff90.write("    endif\n")
    ff90.write("    tracerstate_vars%tracer_soi_molarmass_col(c,:)          = 0._r8\n")
    ff90.write("    !initialize microbial biomass\n")
    ff90.write("  enddo\n")
    ff90.write("  end subroutine InitCold\n")
    ff90.write("!-----------------------------------------------------------------------\n")
    ff90.write("  subroutine readParams(this, name_list_buffer, betrtracer_vars)\n")
    ff90.write("  !\n")
    ff90.write("  ! !DESCRIPTION:\n")
    ff90.write("  ! read in module specific parameters\n")
    ff90.write("  !\n")
    ff90.write("  ! !USES:\n")
    ff90.write("  use BeTRTracerType , only : BeTRTracer_Type\n")
    ff90.write("  implicit none\n")
    ff90.write("  ! !ARGUMENTS:\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type) , intent(inout)    :: this\n")
    ff90.write("  type(BeTRTracer_Type)             , intent(inout) :: betrtracer_vars\n")
    ff90.write("  character(len=*)                  , intent(in)  :: name_list_buffer\n")
    ff90.write("  ! remove compiler warnings for unused dummy args\n")
    ff90.write("  if (this%dummy_compiler_warning)           continue\n")
    ff90.write("  if (len(betrtracer_vars%betr_simname) > 0) continue\n")
    ff90.write("\n")
    ff90.write("  !do nothing here\n")
    ff90.write("  end subroutine readParams\n")
    ff90.write("!-------------------------------------------------------------------------------\n")
    ff90.write("  subroutine retrieve_biogeoflux(this, num_soilc, filter_soilc, tracerflux_vars, &\n")
    ff90.write("    betrtracer_vars, biogeo_flux)\n")
    ff90.write("  !\n")
    ff90.write("  ! DESCRIPTION\n")
    ff90.write("  ! retrieve fluxes after bgc update\n")
    ff90.write("  ! USES\n")
    ff90.write("  use tracerfluxType           , only : tracerflux_type\n")
    ff90.write("  use BeTR_decompMod           , only : betr_bounds_type\n")
    ff90.write("  use BeTRTracerType           , only : BeTRTracer_Type\n")
    ff90.write("  use BeTR_biogeoFluxType      , only : betr_biogeo_flux_type\n")
    ff90.write("  implicit none\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type) , intent(inout) :: this    !\n")
    ff90.write("  integer                          , intent(in)    :: num_soilc   ! number of columns in column filter\n")
    ff90.write("  integer                          , intent(in)    :: filter_soilc(:)             ! column filter\n")
    ff90.write("  type(betrtracer_type)            , intent(in)    :: betrtracer_vars             ! betr configuration information\n")
    ff90.write("  type(tracerflux_type)            , intent(in)    :: tracerflux_vars\n")
    ff90.write("  type(betr_biogeo_flux_type)      , intent(inout) :: biogeo_flux\n")

    ff90.write("  ! remove compiler warnings for unused dummy args\n")
    ff90.write("  if (this%dummy_compiler_warning)                          continue\n")
    ff90.write("  if (num_soilc > 0)                                        continue\n")
    ff90.write("  if (size(filter_soilc) > 0)                               continue\n")
    ff90.write("  if (len(betrtracer_vars%betr_simname) > 0)                continue\n")
    ff90.write("  if (size(tracerflux_vars%tracer_flx_top_soil_col) > 0)    continue\n")
    ff90.write("  end subroutine retrieve_biogeoflux\n")
    ff90.write("!----------------------------------------------------------------------\n")
    ff90.write("  subroutine retrieve_lnd2atm(this, bounds, num_soilc, filter_soilc, tracerflux_vars, &\n")
    ff90.write("    betrtracer_vars, biogeo_flux)\n")
    ff90.write("  !\n")
    ff90.write("  ! DESCRIPTION\n")
    ff90.write("  ! retrieve fluxes from land to atmosphere\n")
    ff90.write("  ! USES\n")
    ff90.write("  use tracerfluxType           , only : tracerflux_type\n")
    ff90.write("  use BeTR_decompMod           , only : betr_bounds_type\n")
    ff90.write("  use BeTRTracerType           , only : BeTRTracer_Type\n")
    ff90.write("  use BeTR_biogeoFluxType      , only : betr_biogeo_flux_type\n")
    ff90.write("  implicit none\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type) , intent(inout) :: this     !\n")
    ff90.write("  type(betr_bounds_type)           , intent(in)    :: bounds     ! bounds\n")
    ff90.write("  integer                          , intent(in)    :: num_soilc   ! number of columns in column filter\n")
    ff90.write("  integer                          , intent(in)    :: filter_soilc(:)             ! column filter\n")
    ff90.write("  type(betrtracer_type)            , intent(in)    :: betrtracer_vars             ! betr configuration information\n")
    ff90.write("  type(tracerflux_type)            , intent(in)    :: tracerflux_vars\n")
    ff90.write("  type(betr_biogeo_flux_type)      , intent(inout) :: biogeo_flux\n")
    ff90.write("  if (this%dummy_compiler_warning) continue\n")
    ff90.write("  if (bounds%begc > 0)             continue\n")
    ff90.write("\n")
    ff90.write("  end subroutine retrieve_lnd2atm\n")
    ff90.write("!-------------------------------------------------------------------------------\n")
    ff90.write("  subroutine debug_info(this, bounds, num_soilc, filter_soilc, dzsoi, betrtracer_vars, tracerstate_vars, header, betr_status)\n")
    ff90.write("  !\n")
    ff90.write("  ! DESCRIPTION\n")
    ff90.write("  ! write debug information\n")
    ff90.write("  ! USES\n")
    ff90.write("  use BeTRTracerType           , only : BeTRTracer_Type\n")
    ff90.write("  use tracerstatetype          , only : tracerstate_type\n")
    ff90.write("  use BeTR_decompMod           , only : betr_bounds_type\n")
    ff90.write("  ! !ARGUMENTS:\n")
    ff90.write("  implicit none\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type) , intent(inout) :: this      !\n")
    ff90.write("  type(betr_bounds_type)               , intent(in) :: bounds    ! bounds\n")
    ff90.write("  integer                              , intent(in) :: num_soilc  ! number of columns in column filter\n")
    ff90.write("  integer                              , intent(in) :: filter_soilc(:)    ! column filter\n")
    ff90.write("  real(r8)                             , intent(in) :: dzsoi(bounds%begc: ,bounds%lbj: )\n")
    ff90.write("  type(betrtracer_type)                , intent(in) :: betrtracer_vars   ! betr configuration information\n")
    ff90.write("  type(tracerstate_type)               , intent(in) :: tracerstate_vars\n")
    ff90.write("  character(len=*)                     , intent(in) :: header\n")
    ff90.write("  type(betr_status_type)               , intent(out):: betr_status\n")
    ff90.write("  call betr_status%reset()\n")
    ff90.write("  SHR_ASSERT_ALL((ubound(dzsoi)  == (/bounds%endc, bounds%ubj/)),   errMsg(mod_filename,__LINE__), betr_status)\n")
    ff90.write("\n")
    ff90.write("  if (this%dummy_compiler_warning) continue\n")
    ff90.write("  end subroutine debug_info\n")
    ff90.write("!----------------------------------------------------------------------\n")
    ff90.write("  subroutine retrieve_biostates(this, bounds, lbj, ubj, jtops,num_soilc, filter_soilc, &\n")
    ff90.write("    betrtracer_vars, tracerstate_vars, biogeo_state, betr_status)\n")
    ff90.write("  !\n")
    ff90.write("  ! DESCRIPTION\n")
    ff90.write("  !retrieve state variables for lsm mass balance check\n")
    ff90.write("  ! USES\n")
    ff90.write("  use tracer_varcon, only : catomw, natomw, patomw, c13atomw, c14atomw\n")
    ff90.write("  use BeTR_decompMod           , only : betr_bounds_type\n")
    ff90.write("  use BeTRTracerType           , only : BeTRTracer_Type\n")
    ff90.write("  use tracerstatetype          , only : tracerstate_type\n")
    ff90.write("  use BeTR_biogeoStateType     , only : betr_biogeo_state_type\n")
    ff90.write("  implicit none\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type) , intent(inout) :: this           !\n")
    ff90.write("  type(betr_bounds_type)               , intent(in)  :: bounds            ! bounds\n")
    ff90.write("  integer                              , intent(in) :: lbj, ubj\n")
    ff90.write("  integer                              , intent(in) :: jtops(bounds%begc: )\n")
    ff90.write("  integer                              , intent(in)    :: num_soilc   ! number of columns in column filter\n")
    ff90.write("  integer                              , intent(in)    :: filter_soilc(:)    ! column filter\n")
    ff90.write("  type(betrtracer_type)                , intent(in) :: betrtracer_vars       ! betr configuration information\n")
    ff90.write("  type(tracerstate_type)               , intent(inout) :: tracerstate_vars\n")
    ff90.write("  type(betr_biogeo_state_type)         , intent(inout) :: biogeo_state\n")
    ff90.write("  type(betr_status_type)               , intent(out):: betr_status\n")
    ff90.write("  !local variables\n")
    ff90.write("  integer :: nelm\n")
    ff90.write("  integer :: c_loc, c13_loc, c14_loc\n")
    ff90.write("  integer :: c, fc, j, kk\n")
    ff90.write("\n")
    ff90.write("  call betr_status%reset()\n")
    ff90.write("  SHR_ASSERT_ALL((ubound(jtops)  == (/bounds%endc/)),   errMsg(mod_filename,__LINE__), betr_status)\n")
    ff90.write("\n")
    ff90.write("  nelm =this%"+app_name+"_bgc_index%nelms\n")
    ff90.write("  do j = lbj, ubj\n")
    ff90.write("    do fc = 1, num_soilc\n")
    ff90.write("      c = filter_soilc(fc)\n")
    ff90.write("      if(j<jtops(c))cycle\n")
    ff90.write("    enddo\n")
    ff90.write("  enddo\n")
    ff90.write("  end subroutine retrieve_biostates\n")
    ff90.write("!------------------------------------------------------------------------------\n")
    ff90.write("  subroutine retrieve_output(this, c, j, nstates, ystates0, ystatesf, dtime, betrtracer_vars, tracerflux_vars,&\n")
    ff90.write("    tracerstate_vars, plant_soilbgc, biogeo_flux)\n")
    ff90.write("  !DESCRIPTION\n")
    ff90.write("  !retrieve flux and state variables after evolving the bgc calculation\n")
    ff90.write("  !\n")
    ff90.write("  !USES\n")
    ff90.write("  use BetrTracerType           , only : betrtracer_type\n")
    ff90.write("  use BeTR_biogeoFluxType      , only : betr_biogeo_flux_type\n")
    ff90.write("  use tracerfluxType           , only : tracerflux_type\n")
    ff90.write("  use tracerstatetype          , only : tracerstate_type\n")
    ff90.write("  use betr_ctrl                , only : betr_spinup_state\n")
    ff90.write("  use PlantSoilBGCMod          , only : plant_soilbgc_type\n")
    ff90.write("  use "+app_name+"PlantSoilBGCType    , only : "+app_name+"_plant_soilbgc_type\n")
    ff90.write("  use tracer_varcon            , only : catomw, natomw, patomw, fix_ip\n")
    ff90.write("  implicit none\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type) , intent(inout)    :: this\n")
    ff90.write("  integer                              , intent(in) :: c, j\n")
    ff90.write("  integer                              , intent(in) :: nstates\n")
    ff90.write("  real(r8)                             , intent(in) :: ystates0(nstates)\n")
    ff90.write("  real(r8)                             , intent(inout) :: ystatesf(nstates)\n")
    ff90.write("  real(r8)                             , intent(in) :: dtime\n")
    ff90.write("  type(betrtracer_type)                , intent(in) :: betrtracer_vars    ! betr configuration information\n")
    ff90.write("  type(tracerstate_type)               , intent(inout) :: tracerstate_vars\n")
    ff90.write("  type(tracerflux_type)                , intent(inout) :: tracerflux_vars\n")
    ff90.write("  class(plant_soilbgc_type)            , intent(inout) :: plant_soilbgc\n")
    ff90.write("  type(betr_biogeo_flux_type)          , intent(inout) :: biogeo_flux\n")
    ff90.write("\n")
    ff90.write("  !local variables\n")
    ff90.write("  integer :: k, k1, k2, jj, p\n")
    ff90.write("  integer :: trcid\n")
    ff90.write("\n")
    ff90.write("  end subroutine retrieve_output\n")
    ff90.write("!------------------------------------------------------------------------------\n")
    ff90.write("  subroutine set_bgc_forc(this, bounds, col, lbj, ubj, jtops, num_soilc, filter_soilc, &\n")
    ff90.write("    biophysforc, plant_soilbgc, betrtracer_vars, tracercoeff_vars, tracerstate_vars, betr_status)\n")
    ff90.write("  !\n")
    ff90.write("  !DESCRIPTION\n")
    ff90.write("  use BeTR_biogeophysInputType , only : betr_biogeophys_input_type\n")
    ff90.write("  use PlantSoilBGCMod          , only : plant_soilbgc_type\n")
    ff90.write("  use tracerstatetype          , only : tracerstate_type\n")
    ff90.write("  use betr_decompMod           , only : betr_bounds_type\n")
    ff90.write("  use tracercoeffType          , only : tracercoeff_type\n")
    ff90.write("  use betr_columnType          , only : betr_column_type\n")
    ff90.write("  use BetrTracerType           , only : betrtracer_type\n")
    ff90.write("  use "+app_name+"PlantSoilBGCType    , only : "+app_name+"_plant_soilbgc_type\n")
    ff90.write("  use MathfuncMod              , only : fpmax\n")
    ff90.write("  use betr_varcon              , only : grav => bgrav\n")
    ff90.write("  implicit none\n")
    ff90.write("  class("+app_name+"_bgc_reaction_type) , intent(inout) :: this    !\n")
    ff90.write("  type(bounds_type)                    , intent(in) :: bounds     ! bounds\n")
    ff90.write("  type(betr_column_type)               , intent(in) :: col\n")
    ff90.write("  integer                              , intent(in) :: jtops(bounds%begc: ) ! top index of each column\n")
    ff90.write("  integer                              , intent(in) :: lbj, ubj       ! lower and upper bounds, make sure they are > 0\n")
    ff90.write("  integer                              , intent(in) :: num_soilc       ! number of columns in column filter\n")
    ff90.write("  integer                              , intent(in) :: filter_soilc(:) ! column filter\n")
    ff90.write("  type(betr_biogeophys_input_type)     , intent(in) :: biophysforc\n")
    ff90.write("  class(plant_soilbgc_type)            , intent(in) :: plant_soilbgc\n")
    ff90.write("  type(betrtracer_type)                , intent(in) :: betrtracer_vars     ! betr configuration information\n")
    ff90.write("  type(tracerstate_type)               , intent(in) :: tracerstate_vars\n")
    ff90.write("  type(tracercoeff_type)               , intent(in) :: tracercoeff_vars\n")
    ff90.write("  type(betr_status_type)               , intent(out)   :: betr_status\n")
    ff90.write("\n")
    ff90.write("  integer :: j, fc, c\n")
    ff90.write("  integer :: k1, k2\n")
    ff90.write("  real(r8), parameter :: tiny_cval =1.e-16_r8\n")
    ff90.write("\n")

    ff90.write("  call betr_status%reset()\n")
    ff90.write("  SHR_ASSERT_ALL((ubound(jtops) == (/bounds%endc/)), errMsg(mod_filename,__LINE__),betr_status)\n")
    ff90.write("\n")
    ff90.write("  do j = lbj, ubj\n")
    ff90.write("    do fc = 1, num_soilc\n")
    ff90.write("      c = filter_soilc(fc)\n")
    ff90.write("      if(j<jtops(c))cycle\n")
    ff90.write("    enddo\n")
    ff90.write("  enddo\n")
    ff90.write("  end subroutine set_bgc_forc\n")
    ff90.write("!------------------------------------------------------------------------------\n")
    ff90.write("end module "+app_name+"BGCReactionsType\n")
    ff90.close()
    print "create file "+sfarm_dir+'/'+app_name+'/'+app_name+'Nlayer/'+app_name+"PlantSoilBGCType.F90"
    ff90=open(sfarm_dir+'/'+app_name+'/'+app_name+'Nlayer/'+app_name+"PlantSoilBGCType.F90","w")
    ff90.write("module "+app_name+"PlantSoilBGCType\n")
    ff90.write("  !\n")
    ff90.write("  !DESCRIPTION\n")
    ff90.write("  ! mock interface for plant soil bgc coupling\n")
    ff90.write('#include "bshr_assert.h"\n')
    ff90.write("  !USES\n")
    ff90.write("  use PlantSoilBGCMod , only : plant_soilbgc_type\n")
    ff90.write("  use betr_decompMod  , only : bounds_type => betr_bounds_type\n")
    ff90.write("  use bshr_log_mod    , only : errMsg => shr_log_errMsg\n")
    ff90.write("  implicit none\n")
    ff90.write("\n")
    ff90.write("  private\n")
    ff90.write("  character(len=*), private, parameter :: mod_filename = &\n")
    ff90.write("    __FILE__\n")
    ff90.write("  public :: "+app_name+"_plant_soilbgc_type\n")
    ff90.write("\n")
    ff90.write("  type, extends(plant_soilbgc_type) :: &\n")
    ff90.write("    "+app_name+"_plant_soilbgc_type\n")
    ff90.write("    private\n")
    ff90.write("  contains\n")
    ff90.write("    procedure :: Init_plant_soilbgc\n")
    ff90.write("    procedure :: plant_soilbgc_summary\n")
    ff90.write("    procedure :: integrate_vr_flux\n")
    ff90.write("    procedure :: lsm_betr_plant_soilbgc_recv\n")
    ff90.write("    procedure :: lsm_betr_plant_soilbgc_send\n")
    ff90.write("  end type "+app_name+"_plant_soilbgc_type\n")
    ff90.write("\n")
    ff90.write("  interface "+app_name+"_plant_soilbgc_type\n")
    ff90.write("    module procedure constructor\n")
    ff90.write("  end interface "+app_name+"_plant_soilbgc_type\n")
    ff90.write("\n")
    ff90.write("  contains\n")
    ff90.write("!-------------------------------------------------------------------------------\n")
    ff90.write("  type("+app_name+"_plant_soilbgc_type) function constructor()\n")
    ff90.write("  !\n")
    ff90.write("  ! !DESCRIPTION:\n")
    ff90.write("  ! create an object of type "+app_name+"_plant_soilbgc_type.\n")
    ff90.write("  ! Right now it is purposely empty\n")
    ff90.write("  type("+app_name+"_plant_soilbgc_type), allocatable :: plants\n")
    ff90.write("  allocate(plants)\n")
    ff90.write("  constructor = plants\n")
    ff90.write("  end function constructor\n")
    ff90.write("!-------------------------------------------------------------------------------\n")
    ff90.write("  subroutine Init_plant_soilbgc(this, bounds, lbj, ubj, namelist_buffer)\n")
    ff90.write("  !\n")
    ff90.write("  ! !DESCRIPTION:\n")
    ff90.write("  ! template for init_betrbgc\n")
    ff90.write("  !\n")
    ff90.write("  ! !USES:\n")
    ff90.write("  use gbetrType      , only : gbetr_type\n")
    ff90.write("  implicit none\n")
    ff90.write("  ! !ARGUMENTS:\n")
    ff90.write("  class("+app_name+"_plant_soilbgc_type) , intent(inout) :: this\n")
    ff90.write("  type(bounds_type)                  , intent(in) :: bounds\n")
    ff90.write("  integer                            , intent(in) :: lbj, ubj\n")
    ff90.write("  character(len=*)                   , intent(in) :: namelist_buffer\n")
    ff90.write("\n")
    ff90.write("  ! remove compiler warnings for unused dummy args\n")
    ff90.write("  if (this%dummy_compiler_warning) continue\n")
    ff90.write("  if (bounds%begc > 0)             continue\n")
    ff90.write("  if (lbj > 0)                     continue\n")
    ff90.write("  if (ubj > 0)                     continue\n")
    ff90.write("\n")
    ff90.write("  end subroutine Init_plant_soilbgc\n")
    ff90.write("!----------------------------------------------------------------------\n")
    ff90.write("  subroutine plant_soilbgc_summary(this,bounds, lbj, ubj, pft, numf, &\n")
    ff90.write("    filter, dtime, dz, betrtracer_vars, tracerflux_vars, biogeo_flux, betr_status)\n")
    ff90.write("  !DESCRIPTION\n")
    ff90.write("  !summarize bgc coupling flux variables\n")
    ff90.write("  ! !USES:\n")
    ff90.write("  use BeTRTracerType , only : BeTRtracer_type\n")
    ff90.write("  use tracerfluxType , only : tracerflux_type\n")
    ff90.write("  use bshr_kind_mod  , only : r8 => shr_kind_r8\n")
    ff90.write("  use BetrStatusType , only : betr_status_type\n")
    ff90.write("  use BeTR_PatchType , only : betr_patch_type\n")
    ff90.write("  use BeTR_biogeoFluxType  , only : betr_biogeo_flux_type\n")
    ff90.write("  implicit none\n")
    ff90.write("  ! !ARGUMENTS:\n")
    ff90.write("  class("+app_name+"_plant_soilbgc_type) , intent(inout) :: this\n")
    ff90.write("  type(bounds_type)                  , intent(in) :: bounds\n")
    ff90.write("  integer                            , intent(in) :: lbj, ubj\n")
    ff90.write("  type(betr_patch_type)              , intent(in) :: pft\n")
    ff90.write("  integer                            , intent(in) :: numf\n")
    ff90.write("  integer                            , intent(in) :: filter(:)\n")
    ff90.write("  real(r8)                           , intent(in) :: dtime\n")
    ff90.write("  real(r8)                           , intent(in) :: dz(bounds%begc: ,1: )\n")
    ff90.write("  type(BeTRtracer_type )             , intent(in) :: betrtracer_vars\n")
    ff90.write("  type(tracerflux_type)              , intent(in) :: tracerflux_vars\n")
    ff90.write("  type(betr_biogeo_flux_type)        , intent(inout) :: biogeo_flux\n")
    ff90.write("  type(betr_status_type)             , intent(out):: betr_status\n")
    ff90.write("\n")
    ff90.write("  call betr_status%reset()\n")
    ff90.write("  SHR_ASSERT_ALL((ubound(dz)==(/bounds%endc,ubj/)), errMsg(mod_filename,__LINE__), betr_status)\n")
    ff90.write("\n")
    ff90.write("  ! remove compiler warnings for unused dummy args\n")
    ff90.write("  if (this%dummy_compiler_warning)                       continue\n")
    ff90.write("  if (bounds%begc > 0)                                   continue\n")
    ff90.write("  if (numf > 0)                                          continue\n")
    ff90.write("  if (size(filter) > 0)                                  continue\n")
    ff90.write("  if (lbj > 0)                                           continue\n")
    ff90.write("  if (ubj > 0)                                           continue\n")
    ff90.write("  if (size(dz) > 0)                                      continue\n")
    ff90.write("  if (len(betrtracer_vars%betr_simname) > 0)             continue\n")
    ff90.write("  if (size(tracerflux_vars%tracer_flx_top_soil_col) > 0) continue\n")
    ff90.write("\n")
    ff90.write("  end subroutine plant_soilbgc_summary\n")
    ff90.write("!----------------------------------------------------------------------\n")
    ff90.write("  subroutine integrate_vr_flux(this, bounds, numf, filter)\n")

    ff90.write("  implicit none\n")
    ff90.write("  ! !ARGUMENTS:\n")
    ff90.write("  class("+app_name+"_plant_soilbgc_type) , intent(inout) :: this\n")
    ff90.write("  type(bounds_type)                  , intent(in) :: bounds\n")
    ff90.write("  integer                            , intent(in) :: numf\n")
    ff90.write("  integer                            , intent(in) :: filter(:)\n")
    ff90.write("\n")
    ff90.write("  ! remove compiler warnings for unused dummy args\n")
    ff90.write("  if (this%dummy_compiler_warning) continue\n")
    ff90.write("  if (bounds%begc > 0)             continue\n")
    ff90.write("  if (numf > 0)                    continue\n")
    ff90.write("  if (size(filter) > 0)            continue\n")
    ff90.write("\n")
    ff90.write("  end subroutine integrate_vr_flux\n")
    ff90.write("!----------------------------------------------------------------------\n")
    ff90.write("  subroutine lsm_betr_plant_soilbgc_recv(this, bounds, numf, filter, betr_pft, biogeo_fluxes)\n")
    ff90.write("\n")
    ff90.write("  !DESCRIPTION\n")
    ff90.write("  !return plant nutrient yield\n")
    ff90.write("  !\n")
    ff90.write("  !USES\n")
    ff90.write("  use BeTR_biogeoFluxType, only : betr_biogeo_flux_type\n")
    ff90.write("  use BeTR_PatchType, only : betr_patch_type\n")
    ff90.write("  implicit none\n")
    ff90.write("  ! !ARGUMENTS:\n")
    ff90.write("  class("+app_name+"_plant_soilbgc_type) , intent(inout)    :: this\n")
    ff90.write("  type(bounds_type)                  , intent(in)    :: bounds\n")
    ff90.write("  integer                            , intent(in)    :: numf\n")
    ff90.write("  integer                            , intent(in)    :: filter(:)\n")
    ff90.write("  type(betr_patch_type) , intent(in) :: betr_pft\n")
    ff90.write("  type(betr_biogeo_flux_type)        , intent(inout) :: biogeo_fluxes\n")
    ff90.write("\n")
    ff90.write("  ! remove compiler warnings for unused dummy args\n")
    ff90.write("  if (this%dummy_compiler_warning)        continue\n")
    ff90.write("  if (bounds%begc > 0)                    continue\n")
    ff90.write("  if (numf > 0)                           continue\n")
    ff90.write("  if (size(filter) > 0)                   continue\n")
    ff90.write("  if (size(biogeo_fluxes%qflx_adv_col)>0) continue\n")
    ff90.write("  end subroutine lsm_betr_plant_soilbgc_recv\n")
    ff90.write("!----------------------------------------------------------------------\n")
    ff90.write("  subroutine lsm_betr_plant_soilbgc_send(this, bounds, numf, filter,  &\n")
    ff90.write("    betr_pft, biogeo_forc, biogeo_states, biogeo_fluxes)\n")
    ff90.write("  !\n")
    ff90.write("  !DESCRIPTION\n")
    ff90.write("  ! initialize feedback variables for plant soil bgc interactions\n")
    ff90.write("  !\n")
    ff90.write("  !USES\n")
    ff90.write("  use BeTR_biogeoStateType , only : betr_biogeo_state_type\n")
    ff90.write("  use BeTR_biogeoFluxType  , only : betr_biogeo_flux_type\n")
    ff90.write("  use BeTR_decompMod       , only : betr_bounds_type\n")
    ff90.write("  use BeTR_biogeophysInputType , only : betr_biogeophys_input_type\n")
    ff90.write("  use BeTR_PatchType, only : betr_patch_type\n")
    ff90.write("  ! !ARGUMENTS:\n")
    ff90.write("  class("+app_name+"_plant_soilbgc_type) , intent(inout) :: this\n")
    ff90.write("  type(betr_bounds_type)             , intent(in) :: bounds\n")
    ff90.write("  integer                            , intent(in) :: numf\n")
    ff90.write("  integer                            , intent(in) :: filter(:)\n")
    ff90.write("  type(betr_patch_type)              , intent(in) :: betr_pft\n")
    ff90.write("  type(betr_biogeophys_input_type), intent(in):: biogeo_forc\n")
    ff90.write("  type(betr_biogeo_state_type)       , intent(in) :: biogeo_states\n")
    ff90.write("  type(betr_biogeo_flux_type)        , intent(in) :: biogeo_fluxes\n")
    ff90.write("\n")
    ff90.write("  ! remove compiler warnings for unused dummy args\n")
    ff90.write("  if (this%dummy_compiler_warning)       continue\n")
    ff90.write("  if (bounds%begc > 0)                   continue\n")
    ff90.write("  if (numf > 0)                          continue\n")
    ff90.write("  if (size(filter) > 0)                  continue\n")
    ff90.write("  if (size(biogeo_states%zwts_col)>0)    continue\n")
    ff90.write("  if(size(biogeo_fluxes%qflx_adv_col)>0) continue\n")
    ff90.write("\n")
    ff90.write("  end subroutine lsm_betr_plant_soilbgc_send\n")
    ff90.write("end module "+app_name+"PlantSoilBGCType\n")
    ff90.close()
