PROGRAM KPP_ROOT_ADJ_Driver

  USE KPP_ROOT_Model
  USE KPP_ROOT_Initialize, ONLY: Initialize

  KPP_REAL :: T, DVAL(NSPEC)
  INTEGER :: i, ii

  CHARACTER(LEN=60), PARAMETER :: &
    brk = "------------------------------------------------------------"

  !~~>  NADJ = Number of functionals for which sensitivities are computed
  !     Note: the setting below is for sensitivities of all final concentrations;
  !           the setting may have to be changed for other applications
  INTEGER, PARAMETER :: NADJ = NVAR
  KPP_REAL, DIMENSION(NVAR,NADJ) :: Y_adj, ATOL_adj, RTOL_adj

  !~~>  Control (in) and status (out) arguments for the integration
  KPP_REAL, DIMENSION(20) :: RCNTRL, RSTATUS
  INTEGER,       DIMENSION(20) :: ICNTRL, ISTATUS

  STEPMIN = 0.0d0
  STEPMAX = 0.0d0

  !~~~> Tolerances for calculating concentrations
  DO i=1,NVAR
    RTOL(i) = 1.0d-4
    ATOL(i) = 1.0d-3
  END DO

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

  !~~~> Tolerances for calculating adjoints
  !     are used for controlling adjoint truncation error
  !     and for solving the linear adjoint equations by iterations
  !     Note: Adjoints typically span many orders of magnitude
  !           and a careful tuning of ATOL_adj may be necessary
  DO ii=1,NADJ
    DO i=1,NVAR
      RTOL_adj(i,ii) = 1.0d-4
      ATOL_adj(i,ii) = 1.0d-10
    END DO
  END DO

  CALL Initialize()

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

  CALL UpdateEnvironment()

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

  !~~~>  The adjoint values at the final time
  Y_adj(1:NVAR,1:NADJ) = 0.0d0
  DO ii=1,NADJ
    Y_adj(ii,ii) = 1.0d0
  END DO

  !~~~> Default control options
  ICNTRL(1:20) = 0
  RCNTRL(1:20) = 0.0d0

  !~~~> Begin adjoint integration

  TIME = TSTART

    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()

  CALL INTEGRATE_ADJ( NADJ, VAR, Y_adj, TSTART, TEND,       &
    ATOL_adj, RTOL_adj,              &
    ICNTRL, RCNTRL, ISTATUS, RSTATUS )

  !~~~> End adjoint intergration ~~~~~~~~~~
  OPEN(20, FILE='KPP_ROOT.adjoint')

  !~~~> The entire matrix of sensitivities
  WRITE(20,996) (TRIM(SPC_NAMES(i)), i=1,NVAR )
  DO ii=1,NADJ
    WRITE(20,997) TRIM(SPC_NAMES(ii)),( Y_adj(i,ii), i=1,NVAR )
  END DO

996 FORMAT('spc ',1000(2X,A24))
997 FORMAT('d/d ',A24,1000(2X,E24.16E3))

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

END PROGRAM KPP_ROOT_ADJ_Driver

