module dwr_alg_mod
!  use dual_element_mod
!  use matrix_oper
!  use lapack_oper
!  use main_data
   use elemental_mod
   use target_functional_mod

   implicit none

   type :: DWR_alg_t
      integer :: iter! number of nonlinear Newton steps
      integer :: restart_primal ! set number of iterations of GMRES primal
      integer :: restart_dual ! set number of iterations of GMRES primal
      integer :: iter_lin_primal
      integer :: iter_lin_dual
      real :: C_N, C_A    ! how many time should be alg. error smaller than the space estimate 0.1 - 0.001, C_N nonlinear , C_A linear
      real :: C_Safe    ! safety parameter ~ 0.1
      logical :: linPdone, linDdone, nlDone ! linPrimalProblem is computed exactly enough, similarly for dual and nonlinear criterion
      real :: linTol , nlTol ! actuall stopping criteria for linear and nonlinear problem
!      character(len=20) :: file_error_name
      character(len=20) :: file_error_new
      !character(len=20) :: file_eta_name ! for file containing the etaS for colorMap plots
      character(len=20) :: file_etaS, file_etaD ! for file containing the etaS for colorMap plots

      logical :: fixedIter ! True - no TOL used, always do the given number of iters of the lin solvers !
      logical :: optimal ! TRUE - algorithmic - compute only the estimates, which are truly needed , FALSE - compute all estimates - to compare the decrease

   contains
      procedure :: init => initDWR_alg
      procedure :: update => updateDWR_alg
      !procedure :: writeErrorFile
!      procedure :: updateDWR
!    procedure :: allocDualElems

   end type DWR_alg_t

   contains

    subroutine initDWR_alg( this )
      class(DWR_alg_t), intent(inout) :: this

      integer :: i
      integer :: iFile

      iFile = 47

      this%iter = 0
      this%iter_lin_primal = 0
      this%iter_lin_dual = 0

      ! set here !
      !this%file_error_name = "aDWR_errors"
      !this%file_eta_name = "eta_plot"
      this%file_error_new = "aDWR_nlErrors"

      ! file for color maps
      this%file_etaS = "etaS_plot"
      this%file_etaD = "etaD_plot"

      this%fixedIter = .false. !.true.
      ! fixed number of linear iterations
      ! FOR LINEAR PROBLEMS - newton is used only as a restart for GMRES
      if (this%fixedIter ) then
         print*
         print*, 'FIXED number of iterations - for tables and decrease graphs'
         print*

         this%restart_primal = 20
         this%restart_dual = 20


         ! ratio between nonlin and discr estimates
         ! tolerance given in ini file for nlSolver is used
         this%C_N = state%nlSolver%tol
         ! ratio between lin, nonlin  estimates
         ! tolerance given in ini file for linSolver is used
         this%C_A =  state%linSolver%tol
         this%C_Safe = 1.0 ! 0.5        ! safety parameter

         this%nlTol =  this%C_N ! for primal problem?
         this%linTol = this%C_A * this%C_N ! for dual problem ?

      else
         this%restart_primal = 30
         this%restart_dual = 30
         ! ratio between nonlin and discr estimates
         ! tolerance given in ini file for nlSolver is used
         this%C_N = state%nlSolver%tol
         ! ratio between lin, nonlin  estimates
         ! tolerance given in ini file for linSolver is used
         this%C_A = state%linSolver%tol
         !this%C_A = 0.05       ! ratio between lin, nonlin and discr estimates
         this%C_Safe = 0.5        ! safety parameter
         this%nlTol = this%C_N
         this%linTol = this%C_A * this%C_N
      endif

      this%iter_lin_primal = 0
      this%iter_lin_dual = 0
      this%iter = 0

      write(*,*) '# DWR: algebraic DWR stopping criterion is used. Parameters set in initDWR_alg.'
      !print*, 'restart_primal = ', this%restart_primal
      !print*, 'restart_dual = ', this%restart_dual
      write(*,'(a9,f5.2)') ' # C_N = ' , this%C_N
      ! clear the file_error_name
      !open( iFile, file = this%file_error_name, action="write", status="replace" )
      !close( iFile )
      open( iFile, file = this%file_etaS, action="write", status="replace" )
      close( iFile )
      open( iFile, file = this%file_etaD, action="write", status="replace" )
      close( iFile )

   end subroutine initDWR_alg

   !> called from DWR%update, after each adaptation
   subroutine updateDWR_alg( this )
      class(DWR_alg_t), intent(inout) :: this

      ! not used ?
      this%linPdone = .false.
      this%linDdone = .false.
      this%nlDone = .false.

      this%iter = 0 ! count
      this%iter_lin_primal = 0 ! count
      this%iter_lin_dual = 0 ! count
      ! after adaptation linTol cannot be connected to estimNL from last mesh
      this%linTol = this%nlTol * this%C_A

!      print*, 'linTol = ', this%linTol
!      print*, 'nlTol = ', this%nlTol

      this%iter_lin_primal = 0
      this%iter_lin_dual = 0
      this%iter = 0

   end subroutine


!   ! write one line into the file for errors from state%estim()
!   !> appending after every adaptation
!   subroutine writeErrorFile( this, nelem )
!      class( DWR_alg_t ) :: this
!      integer, intent(in) :: nelem
!!      integer, intent(in) :: iter ! number of the line
!!      integer, intent(in) :: iter_lin_primal !
!!      integer, intent(in) :: iter_lin_dual ! number of the lin. alg. iterations
!      integer :: iFile = 42
!
!      ! ALL NUMBERS NEED to be squarerooted !!!!!!!!!
!
!      open( iFile, file = this%file_error_name , action="write", position="append" )
!        write(iFile,'(i6, i6, i6, i6, 8es14.6)') &
!!         state%space%adapt%adapt_level, &
!         nelem, this%iter , this%iter_lin_primal, this%iter_lin_dual, &
!         sqrt(state%estim( dwrE, 1)) , sqrt(state%estim( dwr_aver, 1)) ,  &
!         sqrt(state%estim( dwrS, 1)) , sqrt(state%estim( dwrS_abs, 1)) , &
!         sqrt(state%estim( dwr_dualS, 1)) , sqrt(state%estim( dwr_dualS_abs, 1)) , &
!         sqrt(state%estim( dwrA, 1)) , sqrt(state%estim( dwr_dualA, 1))
!      close(iFile)
!
!  end subroutine writeErrorFile




end module dwr_alg_mod
