PROGRAM KPP_ROOT_Driver

  USE KPP_ROOT_Model
  USE KPP_ROOT_Initialize, ONLY: Initialize

  KPP_REAL :: T, DVAL(NSPEC)
  KPP_REAL :: RSTATE(20)
  INTEGER :: IERR
  INTEGER :: i, tcount, ttot
  CHARACTER(LEN=60), PARAMETER :: &
    brk = "------------------------------------------------------------"

  !~~~> Initialization

  STEPMIN = 0.0d0
  STEPMAX = 0.0d0

  DO i=1,NVAR
    RTOL(i) = 1.0d-4
    ATOL(i) = 1.0d-3
  END DO

  WRITE(*,*) " "
  WRITE(*,*) brk
  WRITE(*,*) "BOXMOX (__BOXMOX_VERSION__) driver"
  WRITE(*,*) brk
  WRITE(*,*) " "

  CALL Initialize()

  WRITE(*,*) brk
  WRITE(*,*) " "

  CALL UpdateEnvironment()

  CALL readInput('InitialConditions.csv', NSPEC, SPC_NAMES, C, &
                  InitialCondition)
  CALL InitSaveData()

  CALL InitFixNOx(NSPEC, SPC_NAMES, C)

  !~~~> Time loop
  T = TSTART
  tcount = 1
  ttot   = NINT((TEND - TSTART) / DT)
  kron: DO WHILE (T < TEND)

    IF (lverbose) THEN
      WRITE(*,*) ""
      WRITE(*,"(1X,A,F8.2,A)") "-------------------- time (s): ", T, &
                               " --------------------"
      WRITE(*,*) ""
    ENDIF

    TIME = T
    CALL GetMass( C, DVAL )
    CALL SaveData()

    CALL UpdateEnvironment()
    CALL UpdateAerosol()
    CALL UpdatePhotolysisRates()

    CALL UpdateKturb()

    CALL readInput('Background.csv', NSPEC, SPC_NAMES, C, Mix, lzero=.TRUE.)
    CALL readInput('Emissions.csv', NSPEC, SPC_NAMES, C, Emission)
    CALL readInput('Deposition.csv', NSPEC, SPC_NAMES, C, Deposition)

    CALL Update_SUN()
    CALL Update_RCONST()

    IF (T == TSTART) WRITE(*,*) " "

    IF ( MOD(tcount * 10, ttot) .EQ. 0 ) THEN
      WRITE(6,991) (T-TSTART)/(TEND-TSTART)*100, T,       &
        ( TRIM(SPC_NAMES(MONITOR(i))),           &
        C(MONITOR(i))/CFACTOR, i=1,NMONITOR )
    ENDIF

    IF (lfix_NOx) THEN
      CALL FixNOx(NSPEC, SPC_NAMES, C)
    ENDIF

    CALL INTEGRATE( TIN = T, TOUT = T+DT, RSTATUS_U = RSTATE, &
      ICNTRL_U = (/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /), &
      IERR_U = IERR )
    T = RSTATE(1)

    tcount = tcount + 1

    IF (IERR < 0) THEN
      WRITE(*,*) " "
      WRITE(*,*) brk
      WRITE(*,*) "BOXMOX integration failed, stopping."
      WRITE(*,*) brk
      WRITE(*,*) " "
      STOP 1
    ENDIF

    IF (T == TSTART .OR. lverbose) THEN
      WRITE(*,*) ""
      WRITE(*,*) brk
      WRITE(*,*) ""
    ENDIF

  END DO kron
  !~~~> End Time loop

  CALL GetMass( C, DVAL )
  WRITE(6,991) (T-TSTART)/(TEND-TSTART)*100, T,     &
    ( TRIM(SPC_NAMES(MONITOR(i))),           &
    C(MONITOR(i))/CFACTOR, i=1,NMONITOR )
  TIME = T
  CALL SaveData()
  CALL CloseSaveData()

  WRITE(*,*) " "
  WRITE(*,*) brk
  WRITE(*,*) "BOXMOX successfully completed."
  WRITE(*,*) brk
  WRITE(*,*) " "

991 FORMAT(F6.1,'%. T=',E9.3,2X,200(A,'=',E11.4,'; '))

END PROGRAM KPP_ROOT_Driver

