#include <misc.h>
#include <preproc.h>

module controlMod

!-----------------------------------------------------------------------
!BOP
!
! !MODULE: controlMod
!
! !DESCRIPTION:
! Module which initializes run control variables. The following possible
! namelist variables are set default values and possibly read in on startup
!
! === model time =======================
!
!    o dtime      = integer model time step (s)
!    o vicrst_interval = integer VIC model restart time step (s)

! === input data ===
!
!    o finidat         = 256 character initial conditions file name
!    o fsurdat         = 256 character surface data file name
!    o flndtopo        = 256 character land topography file name
!    o fatmgrid        = 256 character atmosphere grid data file name
!    o fatmlndfrc      = 256 character landfrac (on atm grid) file name
!    o fatmtopo        = 256 character atmosphere topography file name (on atm grid)
!    o flndtopo        = 256 character land topography file name
!    o fndepdat        = 254 character nitrogen deposition data file name (netCDF)
!    o fndepdyn        = 254 character nitrogen deposition data file name (netCDF) changing dynamically in time
!    o fpftcon         = 256 character data file with PFT physiological constants
!    o fpftdyn         = 256 character data file with PFT physiological constants changing dynamically in time
!    o frivinp_rtm     = 256 character input data file for rtm
!    o furbinp         = 256 character input data file for urban input
!    o nrevsn          = 256 character restart file name for use with branch run
!
! === history and restart files ===
!
!    o outnc_large_files = true if want to create output netCDF files in 64-bit large file format
!    o hist_empty_htapes = true if do not want ANY output fields on files by default
!    o hist_avgflag_pertape = averaging flag to use by default for all fields on a file series
!    o hist_ndens    = integer, can have value of 1 (nc_double) or 2 (nf_float)
!    o hist_dov2xy   = true if want grid-average history field (false = vector)
!    o hist_nhtfrq   = integer history interval (+ = iterations,  - = hours, 0=monthly ave)
!    o hist_mfilt    = integer number of time samples per history file
!    o hist_fincl1   = 10 character name of fields for first  auxillary history file
!    o hist_fincl2   = 10 character name of fields for second auxillary history file
!    o hist_fincl3   = 10 character name of fields for first  auxillary history file
!    o hist_fincl4   = 10 character name of fields for second auxillary history file
!    o hist_fincl5   = 10 character name of fields for first  auxillary history file
!    o hist_fincl6   = 10 character name of fields for second auxillary history file
!    o hist_fexcl1   = 8  character name of fields for first  auxillary history file
!    o hist_fexcl2   = 8  character name of fields for second auxillary history file
!    o hist_fexcl3   = 8  character name of fields for first  auxillary history file
!    o hist_fexcl4   = 8  character name of fields for second auxillary history file
!    o hist_fexcl5   = 8  character name of fields for first  auxillary history file
!    o hist_fexcl6   = 8  character name of fields for second auxillary history file
!    o hist_crtinic  = 8  character frequency to generate initial dataset
!                         ['6-HOURLY','DAILY','MONTHLY','YEARLY','NONE']
!    o rest_flag     = logical, turns off restart file writing [.TRUE., .FALSE.]
!
! === Parallel history writing options (experiemental, and mostly to due with PIO)
!
!    o hist_pioflag           = logical true if want to turn on hist with pio                    [.FALSE., .TRUE.]
!    o ncd_lowmem2d           = logical true if want to turn on low memory 2d writes in clm hist [.TRUE., .FALSE.]
!    o ncd_pio_def            = logical true if want default pio use setting                     [.FALSE., .TRUE.]
!    o ncd_pio_UseRearranger  = logical true if want to use MCT as Rearranger                    [.TRUE., .FALSE.]
!    o ncd_pio_UseBoxRearr    = logical true if want to use box as Rearranger                    [.FALSE., .TRUE.]
!    o ncd_pio_SerialCDF      = logical true if want to write with pio serial netcdf mode        [.FALSE., .TRUE.]
!    o ncd_pio_IODOF_rootonly = logical true if want to write history in pio from root only      [.FALSE., .TRUE.]
!    o ncd_pio_DebugLevel     = integer pio debug level
!    o ncd_pio_num_iotasks    = integer number of iotasks to use for PIO
!
! === Biogeochem=CASA =======
!    o lnpp        = 1=gpp*gppfact,2=fn(lgrow)*gppfact
!    o lalloc      = 0=fixed allocation, 1=dynamic allocation
!    o q10         = temperature dependence
!    o spunup      = 0=no, 1=yes (used with nsrest/=1 only)
!    o fcpool      = Carbon Pool initial state filename
!
! === Decomposition   =======
!
!    o clump_pproc = clumps per processor
!    o nsegspc     = number of segments per clump for decomposition
!
! === model physics ===
!
!    o irad         = integer solar radiation frequency (+ = iteration. - = hour)
!    o wrtdia       = true if want output written
!    o co2_ppmv     = CO2 volume mixing ratio
!    o pertlim      = perturbation limit
!    o create_crop_landunit = logical on if to create crop as separate landunits
!    o co2_type     = type of CO2 feedback, choices are constant, prognostic or diagnostic
!
! === rtm control variables ===
!
!    o rtm_nsteps  = if > 1, average rtm over rtm_nsteps time steps
!
! !USES:
  use shr_kind_mod , only : r8 => shr_kind_r8, SHR_KIND_CL
  use clm_varpar   , only : maxpatch_pft
  use clm_varctl   , only : dtime, caseid, ctitle, nsrest, brnch_retain_casename, hostname, model_version=>version,    &
                            iulog, hist_crtinic, outnc_large_files, finidat,                                    &
			    fsurdat, fvicsoil, fvicveg, fvicsnow, fveglib,finitdata, fatmgrid, flakegrid, fatmlndfrc,     &
                            fatmtopo, flndtopo, fndepdat, fndepdyn, fpftdyn, fpftcon, nrevsn, frivinp_rtm,      &
                            create_crop_landunit, allocate_all_vegpfts, outstream_freqs, outstream_modes, outstream_interval, &
                            NUM_OUTSTRMS, MAX_OUTSTRMS, NONE, ESTEP, HOURLY, DAILY, MONTHLY, AVRG, INST, ON, OFF, &
                            co2_type, irad, wrtdia, co2_ppmv, rtm_nsteps, nsegspc, pertlim,       &
                            hist_pioflag, ncd_lowmem2d, ncd_pio_def, ncd_pio_UseRearranger, username,           &
                            ncd_pio_UseBoxRearr, ncd_pio_SerialCDF, ncd_pio_IODOF_rootonly, ncd_pio_DebugLevel, &
                            ncd_pio_num_iotasks
  use spmdMod      , only : masterproc
  use decompMod    , only : clump_pproc
  use histFileMod  , only : max_tapes, max_namlen, &
                            hist_empty_htapes, hist_dov2xy, &
                            hist_avgflag_pertape, hist_type1d_pertape, &
                            hist_nhtfrq, hist_ndens, hist_mfilt, &
                            hist_fincl1, hist_fincl2, hist_fincl3, &
                            hist_fincl4, hist_fincl5, hist_fincl6, &
                            hist_fexcl1, hist_fexcl2, hist_fexcl3, &
                            hist_fexcl4, hist_fexcl5, hist_fexcl6
  use restFileMod  , only : rest_flag
  use shr_const_mod, only : SHR_CONST_CDAY
  use abortutils   , only : endrun
  use UrbanInputMod, only : furbinp
!
! !PUBLIC TYPES:
  implicit none
  save
!
! !PUBLIC MEMBER FUNCTIONS:
  public :: control_setNL ! Set namelist filename
  public :: control_init  ! initial run control information
  public :: control_print ! print run control information
!
!
! !REVISION HISTORY:
! Created by Mariana Vertenstein
!
!EOP
!
! PRIVATE TYPES:
! Namelist variables only used locally
  character(len=  7) :: runtyp(4)                        ! run type
  character(len=SHR_KIND_CL) :: NLFilename = 'lnd.stdin' ! Namelist filename
#if (defined _OPENMP)
   integer, external :: omp_get_max_threads  ! max number of threads that can execute
                                             ! concurrently in a single parallel region
#endif
!-----------------------------------------------------------------------

contains

!------------------------------------------------------------------------
!BOP
!
! !IROUTINE: control_setNL
!
! !INTERFACE:
  subroutine control_setNL( NLfile )

    implicit none
!
! !DESCRIPTION:
! Set the namelist filename to use
!
!
! !ARGUMENTS:
  character(len=*), intent(IN) :: NLFile ! Namelist filename
!
! !REVISION HISTORY:
! Created by Erik Kluzek
!
!EOP
!
! !LOCAL VARIABLES:
    character(len=32) :: subname = 'control_setNL'  ! subroutine name
    logical :: lexist                               ! File exists

    ! Error checking...
    if ( len_trim(NLFile) == 0 )then
       call endrun( subname//' error: nlfilename entered is not set' )
    end if
    inquire (file = trim(NLFile), exist = lexist)
    if ( .not. lexist )then
       call endrun( subname//' error: NLfilename entered does NOT exist:'//trim(NLFile) )
    end if
    if ( len_trim(NLFile) > len(NLFilename) )then
       call endrun( subname//' error: entered NLFile is too long' )
    end if
    ! Set the filename
    NLFilename = NLFile
  end subroutine control_setNL

!------------------------------------------------------------------------
!BOP
!
! !IROUTINE: control_init
!
! !INTERFACE:
  subroutine control_init(start_ymd, start_tod, dt)
!
! !DESCRIPTION:
! Initialize CLM run control information
!
! !USES:
    use clm_time_manager , only : set_timemgr_init, is_perpetual, get_timemgr_defaults
#if (defined CASA)
    use CASAMod          , only : lnpp, lalloc, q10, spunup, fcpool
#endif
    use fileutils        , only : getavu, relavu
    use shr_string_mod   , only : shr_string_getParentDir
    use clm_varctl       , only : clmvarctl_init

    implicit none
!
    include 'netcdf.inc'
!
! !REVISION HISTORY:
! Created by Mariana Vertenstein
!
!EOP
!
! !LOCAL VARIABLES:
    character(len=32)  :: starttype ! infodata start type
    character(len=32)  :: output_frequency ! infodata start type
    character(len=32)  :: output_mode      ! infodata start type
    character(len=32)  :: new_str      ! infodata start type
    integer :: len_str
    integer :: len_new_str
    integer :: i,j,n                ! loop indices
    integer :: ierr                 ! error code
    integer :: unitn                ! unit for namelist file
    integer :: inst_id              ! array index for instantaneous stream frequency 
    integer :: num_freqs            ! number of matching output frequency inputs to be processed 
    integer, dimension(MAX_OUTSTRMS,2) :: out_freq_stats ! 
    character(len=32) :: subname = 'control_init'  ! subroutine name
    integer         , intent(out) :: start_ymd
    integer         , intent(out) :: start_tod
    real(r8)         , intent(out) :: dt

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

    ! ----------------------------------------------------------------------
    ! Namelist Variables
    ! ----------------------------------------------------------------------

    ! clm input datasets

    integer :: dtime, vicrst_interval  ! Integer time-step
    namelist / vic_inparm/ &
	 dtime, output_frequency, output_mode, vicrst_interval	

    namelist /vic_inparm/  &
         finidat, fsurdat, fvicsoil, fvicveg, fvicsnow, fveglib, finitdata, & 
         fatmgrid, & 
         flakegrid, fatmlndfrc, fatmtopo, &
         flndtopo, &
         fpftcon, frivinp_rtm,  furbinp, &
         fpftdyn, fndepdat, fndepdyn, nrevsn

    ! clm history, restart options

    namelist /vic_inparm/  &
         hist_empty_htapes, hist_dov2xy, &
         hist_avgflag_pertape, hist_type1d_pertape, &
         hist_nhtfrq,  hist_ndens, hist_mfilt, &
         hist_fincl1,  hist_fincl2, hist_fincl3, &
         hist_fincl4,  hist_fincl5, hist_fincl6, &
         hist_fexcl1,  hist_fexcl2, hist_fexcl3, &
         hist_fexcl4,  hist_fexcl5, hist_fexcl6, &
         hist_crtinic, rest_flag, outnc_large_files, &
         hist_pioflag, ncd_lowmem2d, ncd_pio_def, &
         ncd_pio_UseRearranger, ncd_pio_UseBoxRearr, ncd_pio_SerialCDF, &
         ncd_pio_IODOF_rootonly, ncd_pio_DebugLevel, ncd_pio_num_iotasks
    
    ! clm bgc info

#if (defined CASA)
    namelist /vic_inparm/  &
         lnpp, lalloc, q10, spunup, fcpool
#endif

#if (defined SEQ_MCT) || (defined SEQ_ESMF)
    namelist /vic_inparm / &
         co2_type
#endif

    ! clm other options

    namelist /vic_inparm/  &
         clump_pproc, irad, wrtdia, rtm_nsteps, pertlim, &
         create_crop_landunit, nsegspc, co2_ppmv

    ! ----------------------------------------------------------------------
    ! Default values
    ! ----------------------------------------------------------------------

    if (masterproc) then
       write(iulog,*) 'Attempting to initialize run control settings'
    endif

    runtyp(0 + 1) = 'initial'
    runtyp(1 + 1) = 'restart'
    runtyp(3 + 1) = 'branch '

#if (defined CASA)
    lnpp = 2
    lalloc = 1
    q10 = 2.0_r8          ! set Q10 to 2.0  03/11/19
    spunup = 0
    fcpool = ' '
#endif

    ! Set clumps per procoessor

    clump_pproc = 1
#if (defined _OPENMP)
    clump_pproc = omp_get_max_threads()
#else
#if (defined UNICOSMP)
#if (defined SSP)
    clump_pproc = 1
#else
    clump_pproc = 1 ! 4 when using CSDs in driver.F90; 1 otherwise
#endif
#endif
#endif

    if (masterproc) then

       ! ----------------------------------------------------------------------
       ! Read namelist from standard input. 
       ! ----------------------------------------------------------------------

       if ( len_trim(NLFilename) == 0  )then
          call endrun( subname//' error: nlfilename not set' )
       end if
       unitn = getavu()
       write(iulog,*) 'Read in vic_inparm namelist from: ', trim(NLFilename)
       open( unitn, file=trim(NLFilename), status='old' )
       ierr = 1
       do while ( ierr /= 0 )
          read(unitn, vic_inparm, iostat=ierr)
          if (ierr < 0) then
             call endrun( subname//' encountered end-of-file on namelist read' )
          endif
       end do
       call relavu( unitn )

       ! ----------------------------------------------------------------------
       ! Consistency checks on input namelist.
       ! ----------------------------------------------------------------------

       call set_timemgr_init( dtime_in=dtime )

#if (defined RTM) || (defined DGVM)
       if (is_perpetual()) then
          write(iulog,*)'RTM or DGVM cannot be defined in perpetual mode'
          call endrun()
       end if
#endif
       if (is_perpetual()) then
          if (finidat == ' ') then
             write(iulog,*)'must specify initial dataset for perpetual mode'
             call endrun()
          end if
       end if

       ! Check that hist_type_1d is not set for primary tape

       if (hist_type1d_pertape(1) /= ' ') then
          write(iulog,*)'CONTROL_INIT error: hist_type1d_pertape can only be set for tapes 2-6'
          call endrun()
       end if

       ! History and restart files

       do i = 1, max_tapes
          if (hist_nhtfrq(i) == 0) then
             hist_mfilt(i) = 1
          else if (hist_nhtfrq(i) < 0) then
             hist_nhtfrq(i) = nint(-hist_nhtfrq(i)*SHR_CONST_CDAY/(24._r8*dtime))
          endif
       end do
       
       !! JCR: start processing output frequencies inputted
       output_frequency = trim(output_frequency)
       output_mode = trim(output_mode)
       !! write(iulog,*) 'JCR: Read output_frequency=', output_frequency, " output_mode=", output_mode

       !! JCR: initialize data to now inputs
       inst_id = MAX_OUTSTRMS + 1
       NUM_OUTSTRMS = 0
       do i = 1 , MAX_OUTSTRMS
          outstream_freqs(i) = OFF
          outstream_modes(i) = NONE 
          outstream_interval(i) = NONE
          
          !! JCR: array that keeps track of output freqs already set to avoid duplicates
          out_freq_stats(i,INST+1) = OFF  ! inst case
          out_freq_stats(i,AVRG+1) = OFF  ! avg case
       enddo

       !! JCR: Remove empty/blank spaces
       len_str = len_trim(output_frequency)
       new_str =""
       len_new_str = 0
       do i = 1, len_str
          if(output_frequency(i:i).ne.' ') then
             len_new_str = len_new_str + 1
             new_str(len_new_str:len_new_str) = output_frequency(i:i)
          endif
       enddo
       output_frequency = new_str

       len_str = len_trim(output_mode)
       new_str =""
       len_new_str = 0
       do i = 1, len_str
          if(output_mode(i:i).ne.' ') then
             len_new_str = len_new_str + 1
             new_str(len_new_str:len_new_str) = output_mode(i:i)
          endif
       enddo
       output_mode = new_str
     
       !! JCR: compute length of string examine
       num_freqs = NUM_OUTSTRMS
       if (len(output_frequency) > len(output_mode)) then
          num_freqs = len(output_mode)
       else 
          num_freqs = len(output_frequency)
       endif
       if (num_freqs >  MAX_OUTSTRMS) num_freqs = MAX_OUTSTRMS
   
       !! JCR: loop through string and get valid non duplicate pairs of frequency outputs
       do i = 1 , num_freqs
          if (output_mode(i:i) == 'a') then
             if (output_frequency(i:i) =='e') then
                if (out_freq_stats(ESTEP, INST+1) == OFF) then 
                   out_freq_stats(ESTEP, INST+1) = ON
                   NUM_OUTSTRMS =  NUM_OUTSTRMS + 1
                   outstream_freqs(i) = ESTEP
                   outstream_modes(i) = INST
                   outstream_interval(i) = dtime
                   inst_id = ESTEP
                endif
             elseif (output_frequency(i:i) == 'h') then
                if (out_freq_stats(HOURLY, AVRG+1) == OFF) then 
                   out_freq_stats(HOURLY, AVRG+1) = ON
                   NUM_OUTSTRMS =  NUM_OUTSTRMS + 1
                   outstream_freqs(i) = HOURLY
                   outstream_modes(i) = AVRG
                   outstream_interval(i) = 3600
                endif
             elseif (output_frequency(i:i) == 'd') then
                if (out_freq_stats(DAILY, AVRG+1) == OFF) then 
                   out_freq_stats(DAILY, AVRG+1) = ON
                   NUM_OUTSTRMS =  NUM_OUTSTRMS + 1
                   outstream_freqs(i) = DAILY
                   outstream_modes(i) = AVRG
                   outstream_interval(i) = 86400
                endif
             elseif (output_frequency(i:i) == 'm') then
                if (out_freq_stats(MONTHLY, AVRG+1) == OFF) then 
                   out_freq_stats(MONTHLY, AVRG+1) = ON
                   NUM_OUTSTRMS =  NUM_OUTSTRMS + 1
                   outstream_freqs(i) = MONTHLY
                   outstream_modes(i) = AVRG
                   outstream_interval(i) = 2592000
                endif
             end if
          elseif (output_mode(i:i) == 'i') then
             if (output_frequency(i:i) =='e') then
                if (out_freq_stats(ESTEP, INST+1) == OFF) then 
                   out_freq_stats(ESTEP, INST+1) = ON
                   NUM_OUTSTRMS =  NUM_OUTSTRMS + 1
                   outstream_freqs(i) = ESTEP
                   outstream_modes(i) = INST
                   outstream_interval(i) = dtime
                   inst_id = ESTEP
                endif
             elseif (output_frequency(i:i) == 'h') then
                if (out_freq_stats(HOURLY, INST+1) == OFF) then 
                   out_freq_stats(HOURLY, INST+1) = ON
                   NUM_OUTSTRMS =  NUM_OUTSTRMS + 1
                   outstream_freqs(i) = HOURLY
                   outstream_modes(i) = INST
                   outstream_interval(i) = 3600
                   if ( inst_id > HOURLY) inst_id = HOURLY
                endif
             elseif (output_frequency(i:i) == 'd') then
                if (out_freq_stats(DAILY, INST+1) == OFF) then 
                   out_freq_stats(DAILY, INST+1) = ON
                   NUM_OUTSTRMS =  NUM_OUTSTRMS + 1
                   outstream_freqs(i) = DAILY
                   outstream_modes(i) = INST
                   outstream_interval(i) = 86400
                   if ( inst_id > DAILY) inst_id = DAILY
                endif
             elseif (output_frequency(i:i) == 'm') then
                if (out_freq_stats(MONTHLY, INST+1) == OFF) then 
                   out_freq_stats(MONTHLY, INST+1) = ON
                   NUM_OUTSTRMS =  NUM_OUTSTRMS + 1
                   outstream_freqs(i) = MONTHLY
                   outstream_modes(i) = INST
                   outstream_interval(i) = 2592000
                   if ( inst_id > MONTHLY) inst_id = MONTHLY
                endif
             endif
          endif
       enddo

       !! JCR: ensure for valid output streams 
       do i = 1 , MAX_OUTSTRMS
          if (outstream_freqs(i) /= OFF) then
             !! JCR: ensure that dtime is greater than interval fequency 
             !! JCR: if not, turn off stream output for that frequency
             if (dtime >  outstream_interval(i)) then
                outstream_freqs(i) = OFF
                outstream_modes(i) = NONE
                outstream_interval(i) = NONE
                NUM_OUTSTRMS = NUM_OUTSTRMS - 1
                !! JCR: If dtime equals stream output frequency, label as instantaneous
             elseif (dtime == outstream_interval(i)) then
                outstream_modes(i) = INST
                if ( inst_id > outstream_freqs(i)) inst_id = outstream_freqs(i)
             endif
          endif
       enddo

       !! JCR: ensure only one smallest instantaneous frequency is outputted  
       if (inst_id  <  (MAX_OUTSTRMS + 1)) then 
          do i = 1 , MAX_OUTSTRMS
             if (outstream_modes(i) == INST) then
                if ( inst_id < outstream_freqs(i)) then
                   outstream_freqs(i) = OFF
                   outstream_modes(i) = NONE
                   outstream_interval(i) = NONE
                   NUM_OUTSTRMS = NUM_OUTSTRMS - 1
                endif
             endif
          enddo
       endif

       !! write(iulog,*) 'JCR: NUM_OUTSTRMS=', NUM_OUTSTRMS
       !! write(iulog,*) 'JCR: MAX_OUTSTRMS=', MAX_OUTSTRMS
       !! write(iulog,*) 'JCR: SET outstream_freqs=', outstream_freqs
       !! write(iulog,*) 'JCR: SET outstream_modes=', outstream_modes
       !! write(iulog,*)

    endif   ! end of if-masterproc if-block

    call clmvarctl_init( masterproc, dtime )

    ! ----------------------------------------------------------------------
    ! Broadcast all control information if appropriate
    ! ----------------------------------------------------------------------

    call control_spmd()
    
    if (masterproc) then
       write(iulog,*) 'Successfully initialized run control settings',dtime
    endif
 
   dt = dtime

  end subroutine control_init


!------------------------------------------------------------------------
!BOP
!
! !IROUTINE: control_spmd
!
! !INTERFACE:
  subroutine control_spmd()
!
! !DESCRIPTION:
! Distribute namelist data all processors. The cpp SPMD definition
! provides for the funnelling of all program i/o through the master
! processor. Processor 0 either reads restart/history data from the
! disk and distributes it to all processors, or collects data from
! all processors and writes it to disk.
!
! !USES:
!
#if (defined CASA)
    use CASAMod,    only : lnpp, lalloc, q10, spunup
#endif
    use spmdMod,    only : mpicom, MPI_CHARACTER, MPI_INTEGER, MPI_LOGICAL, MPI_REAL8
    use clm_varctl, only : dtime, single_column, scmlat, scmlon, rpntfil
!
! !ARGUMENTS:
    implicit none
!
! !REVISION HISTORY:
! Created by Mariana Vertenstein
!
!EOP
!
! !LOCAL VARIABLES:
    integer ier       !error code
!-----------------------------------------------------------------------

    ! run control variables

    call mpi_bcast (caseid,         len(caseid),        MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (ctitle,         len(ctitle),        MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (model_version,  len(model_version), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (hostname,       len(hostname),      MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (username,       len(username),      MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (nsrest,                     1,      MPI_INTEGER  , 0, mpicom, ier)
    call mpi_bcast (outstream_freqs, MAX_OUTSTRMS,      MPI_INTEGER  , 0, mpicom, ier)
    call mpi_bcast (outstream_modes, MAX_OUTSTRMS,      MPI_INTEGER  , 0, mpicom, ier)
    call mpi_bcast (NUM_OUTSTRMS,               1,      MPI_INTEGER  , 0, mpicom, ier)

    call mpi_bcast (dtime,       1, MPI_REAL8,   0, mpicom, ier)

    ! initial file variables

    call mpi_bcast (nrevsn  , len(nrevsn)  , MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (finidat , len(finidat) , MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (fsurdat , len(fsurdat) , MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (fatmgrid, len(fatmgrid), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (flakegrid, len(flakegrid), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (finitdata, len(finitdata), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (fatmlndfrc,len(fatmlndfrc),MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (fatmtopo, len(fatmtopo) ,MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (flndtopo, len(flndtopo) ,MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (fndepdat, len(fndepdat), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (fndepdyn, len(fndepdyn), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (fpftcon , len(fpftcon) , MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (fpftdyn , len(fpftdyn) , MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (furbinp , len(furbinp) , MPI_CHARACTER, 0, mpicom, ier)
#if (defined RTM)
    call mpi_bcast (frivinp_rtm, len(frivinp_rtm), MPI_CHARACTER, 0, mpicom, ier)
#endif

    ! Landunit generation

    call mpi_bcast(create_crop_landunit, 1, MPI_LOGICAL, 0, mpicom, ier)
    call mpi_bcast(allocate_all_vegpfts, 1, MPI_LOGICAL, 0, mpicom, ier)

    ! BGC

    call mpi_bcast (co2_type, len(co2_type), MPI_CHARACTER, 0, mpicom, ier)

    ! physics variables

    call mpi_bcast (irad        , 1, MPI_INTEGER, 0, mpicom, ier)
    call mpi_bcast (rtm_nsteps  , 1, MPI_INTEGER, 0, mpicom, ier)
    call mpi_bcast (nsegspc     , 1, MPI_INTEGER, 0, mpicom, ier)
    call mpi_bcast (wrtdia      , 1, MPI_LOGICAL, 0, mpicom, ier)
    call mpi_bcast (single_column,1, MPI_LOGICAL, 0, mpicom, ier)
    call mpi_bcast (scmlat,       1, MPI_REAL8,   0, mpicom, ier)
    call mpi_bcast (scmlon,       1, MPI_REAL8,   0, mpicom, ier)
    call mpi_bcast (co2_ppmv    , 1, MPI_REAL8,   0, mpicom, ier)
    call mpi_bcast (hist_pioflag, 1, MPI_LOGICAL, 0, mpicom, ier)
    call mpi_bcast (ncd_lowmem2d, 1, MPI_LOGICAL, 0, mpicom, ier)
    call mpi_bcast (ncd_pio_def , 1, MPI_LOGICAL, 0, mpicom, ier)
    call mpi_bcast (ncd_pio_UseRearranger , 1, MPI_LOGICAL, 0, mpicom, ier)
    call mpi_bcast (ncd_pio_UseBoxRearr   , 1, MPI_LOGICAL, 0, mpicom, ier)
    call mpi_bcast (ncd_pio_SerialCDF     , 1, MPI_LOGICAL, 0, mpicom, ier)
    call mpi_bcast (ncd_pio_IODOF_rootonly, 1, MPI_LOGICAL, 0, mpicom, ier)
    call mpi_bcast (ncd_pio_DebugLevel    , 1, MPI_INTEGER, 0, mpicom, ier)
    call mpi_bcast (ncd_pio_num_iotasks   , 1, MPI_INTEGER, 0, mpicom, ier)

    ! history file variables

    call mpi_bcast (outnc_large_files, 1, MPI_LOGICAL, 0, mpicom, ier)
    call mpi_bcast (hist_empty_htapes, 1, MPI_LOGICAL, 0, mpicom, ier)
    call mpi_bcast (hist_dov2xy, size(hist_dov2xy), MPI_LOGICAL, 0, mpicom, ier)
    call mpi_bcast (hist_nhtfrq, size(hist_nhtfrq), MPI_INTEGER, 0, mpicom, ier)
    call mpi_bcast (hist_mfilt, size(hist_mfilt), MPI_INTEGER, 0, mpicom, ier)
    call mpi_bcast (hist_ndens, size(hist_ndens), MPI_INTEGER, 0, mpicom, ier)
    call mpi_bcast (hist_crtinic, len(hist_crtinic), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (hist_avgflag_pertape, size(hist_avgflag_pertape), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (hist_type1d_pertape, max_namlen*size(hist_type1d_pertape), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (hist_fexcl1, max_namlen*size(hist_fexcl1), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (hist_fexcl2, max_namlen*size(hist_fexcl2), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (hist_fexcl3, max_namlen*size(hist_fexcl3), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (hist_fexcl4, max_namlen*size(hist_fexcl4), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (hist_fexcl5, max_namlen*size(hist_fexcl5), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (hist_fexcl6, max_namlen*size(hist_fexcl6), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (hist_fincl1, (max_namlen+2)*size(hist_fincl1), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (hist_fincl2, (max_namlen+2)*size(hist_fincl2), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (hist_fincl3, (max_namlen+2)*size(hist_fincl3), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (hist_fincl4, (max_namlen+2)*size(hist_fincl4), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (hist_fincl5, (max_namlen+2)*size(hist_fincl5), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (hist_fincl6, (max_namlen+2)*size(hist_fincl6), MPI_CHARACTER, 0, mpicom, ier)
    call mpi_bcast (rest_flag, 1, MPI_LOGICAL, 0, mpicom, ier)

    ! restart file variables

    call mpi_bcast (rpntfil, len(rpntfil), MPI_CHARACTER, 0, mpicom, ier)

    ! clump decomposition variables

    call mpi_bcast (clump_pproc, 1, MPI_INTEGER, 0, mpicom, ier)

    ! error growth perturbation limit
    call mpi_bcast (pertlim, 1, MPI_REAL8, 0, mpicom, ier)

#if (defined CASA)
    call mpi_bcast (lnpp  , 1, MPI_INTEGER, 0, mpicom, ier)
    call mpi_bcast (lalloc, 1, MPI_INTEGER, 0, mpicom, ier)
    call mpi_bcast (spunup, 1, MPI_INTEGER, 0, mpicom, ier)
    call mpi_bcast (q10   , 1, MPI_REAL8  , 0, mpicom, ier)
#endif

  end subroutine control_spmd

!------------------------------------------------------------------------
!BOP
!
! !IROUTINE: control_print
!
! !INTERFACE:
  subroutine control_print ()
!
! !DESCRIPTION:
! Write out run control variables
!
! !USES:
!
    use clm_varctl, only : source, rpntdir, rpntfil
! !ARGUMENTS:
    implicit none
!
! !REVISION HISTORY:
! Created by Mariana Vertenstein
!
!EOP
!
! !LOCAL VARIABLES:
    integer i  !loop index
!------------------------------------------------------------------------

    write(iulog,*) 'define run:'
    write(iulog,*) '   source                = ',trim(source)
    write(iulog,*) '   model_version         = ',trim(model_version)
    write(iulog,*) '   run type              = ',runtyp(nsrest+1)
    write(iulog,*) '   case title            = ',trim(ctitle)
    write(iulog,*) '   case name             = ',trim(caseid)
    write(iulog,*) '   username              = ',trim(username)
    write(iulog,*) '   hostname              = ',trim(hostname)
    write(iulog,*) 'input data files:'
    write(iulog,*) '   PFT physiology = ',trim(fpftcon)
    if (fsurdat == ' ') then
       write(iulog,*) '   fsurdat, surface dataset not set'
    else
       write(iulog,*) '   surface data   = ',trim(fsurdat)
    end if
    if (flndtopo == ' ') then
       write(iulog,*) '   flndtopo not set'
    else
       write(iulog,*) '   land topographic data = ',trim(flndtopo)
    end if
    if (fatmgrid == ' ') then
       write(iulog,*) '   fatmgrid not set, using fsurdat'
       fatmgrid = fsurdat
       write(iulog,*) '   atm grid data  = ',trim(fatmgrid)
    else
       write(iulog,*) '   atm grid data  = ',trim(fatmgrid)
    end if
     if (flakegrid == ' ') then
       write(iulog,*) '   flakegrid not set'
     else
       write(iulog,*) '   lake grid data  = ',trim(flakegrid)
    end if

     if (finitdata == ' ') then
       write(iulog,*) '   finitdata not set'
     else
       write(iulog,*) '   init data  = ',trim(finitdata)
    end if


    if (fatmlndfrc == ' ') then
       write(iulog,*) '   fatmlndfrc not set, using fatmgrid'
       fatmlndfrc = fatmgrid
       write(iulog,*) '   land frac data = ',trim(fatmlndfrc)
    else
       write(iulog,*) '   land frac data = ',trim(fatmlndfrc)
    end if
    if (fatmtopo == ' ') then
       write(iulog,*) '   fatmtopo not set'
    else
       write(iulog,*) '   atm topographic data = ',trim(fatmtopo)
    end if
    if (fndepdat == ' ') then
        write(iulog,*) '   NOT using input data for nitrogen deposition'
    else
        write(iulog,*) '   nitrogen deposition data = ',trim(fndepdat)
    endif
    if (fndepdyn == ' ') then
        write(iulog,*) '   NOT using dynamic input data for nitrogen deposition'
    else
        write(iulog,*) '   dynamic nitrogen deposition data = ',trim(fndepdyn)
    endif
    if (nsrest == 0 .and. finidat == ' ') write(iulog,*) '   initial data created by model'
    if (nsrest == 0 .and. finidat /= ' ') write(iulog,*) '   initial data   = ',trim(finidat)
    if (nsrest /= 0) write(iulog,*) '   restart data   = ',trim(nrevsn)
#if (defined SEQ_MCT) || (defined SEQ_ESMF)
    write(iulog,*) '   atmospheric forcing data is from sequential ccsm model'
#endif
#if (defined RTM)
    if (frivinp_rtm /= ' ') write(iulog,*) '   RTM river data       = ',trim(frivinp_rtm)
#endif
    write(iulog,*) 'Restart parameters:'
    write(iulog,*)'   restart pointer file directory     = ',trim(rpntdir)
    write(iulog,*)'   restart pointer file name          = ',trim(rpntfil)
    if ( outnc_large_files ) then
       write(iulog,*)'Large file support for output files is ON'
    end if
    if (hist_crtinic == 'MONTHLY') then
       write(iulog,*)'initial datasets will be written monthly'
    else if (hist_crtinic == 'YEARLY') then
       write(iulog,*)'initial datasets will be written yearly'
    else if (hist_crtinic == 'DAILY') then
       write(iulog,*)'initial datasets will be written daily'
    else if (hist_crtinic == '6-HOURLY') then
       write(iulog,*)'initial datasets will be written 6-hourly'
    else
       write(iulog,*)'initial datasets will not be produced'
    endif
    write(iulog,*) 'model physics parameters:'
#if (defined PERGRO)
    write(iulog,*) '   flag for random perturbation test is set'
#else
    write(iulog,*) '   flag for random perturbation test is not set'
#endif
    write(iulog,*) '   solar radiation frequency (iterations) = ',irad
    write(iulog,*) '   CO2 volume mixing ratio   (umol/mol)   = ', co2_ppmv
#if (defined RTM)
    if (rtm_nsteps > 1) then
       write(iulog,*)'river runoff calculation performed only every ',rtm_nsteps,' nsteps'
    else
       write(iulog,*)'river runoff calculation performed every time step'
    endif
#endif
    if (nsrest == 1) then
       write(iulog,*) 'restart warning:'
       write(iulog,*) '   Namelist not checked for agreement with initial run.'
       write(iulog,*) '   Namelist should not differ except for ending time step and run type'
    end if
    if (nsrest == 3) then
       write(iulog,*) 'branch warning:'
       write(iulog,*) '   Namelist not checked for agreement with initial run.'
       write(iulog,*) '   Surface data set and reference date should not differ from initial run'
    end if
    if ( pertlim /= 0.0_r8 ) &
    write(iulog,*) '   perturbation limit = ',pertlim
    write(iulog,*) '   maxpatch_pft         = ',maxpatch_pft
    write(iulog,*) '   allocate_all_vegpfts = ',allocate_all_vegpfts
    write(iulog,*) '   nsegspc              = ',nsegspc

!tcx for debugging
    write(iulog,*) 'history/PIO parameters:'
    write(iulog,*) '   hist_pioflag           = ', hist_pioflag
    write(iulog,*) '   ncd_lowmem2d           = ', ncd_lowmem2d
    write(iulog,*) '   ncd_pio_def            = ', ncd_pio_def
    write(iulog,*) '   ncd_pio_UseRearranger  = ', ncd_pio_UseRearranger
    write(iulog,*) '   ncd_pio_UseBoxRearr    = ', ncd_pio_UseBoxRearr
    write(iulog,*) '   ncd_pio_SerialCDF      = ', ncd_pio_SerialCDF
    write(iulog,*) '   ncd_pio_IODOF_rootonly = ', ncd_pio_IODOF_rootonly
    write(iulog,*) '   ncd_pio_DebugLevel     = ', ncd_pio_DebugLevel
    write(iulog,*) '   ncd_pio_num_iotasks    = ', ncd_pio_num_iotasks

  end subroutine control_print

end module controlMod
