!===============================================================================
!
! minmax.F90 - program to calculate eigenmode
!
!-------------------------------------------------------------------------------
!
! Copyright (C) 2007 Yoshifumi Nakamura
!
! This file is part of BQCD -- Berlin Quantum ChromoDynamics program
!
! BQCD is free software: you can redistribute it and/or modify
! it under the terms of the GNU General Public License as published by
! the Free Software Foundation, either version 3 of the License, or
! (at your option) any later version.
!
! BQCD is distributed in the hope that it will be useful,
! but WITHOUT ANY WARRANTY; without even the implied warranty of
! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
! GNU General Public License for more details.
!
! You should have received a copy of the GNU General Public License
! along with BQCD.  If not, see <http://www.gnu.org/licenses/>.
!
!-------------------------------------------------------------------------------
# include "defs.h"

!-------------------------------------------------------------------------------
subroutine minmax(mdmc)
  use module_action
  use module_counter
  use module_function_decl
  use module_switches
  use module_rhmc
  use module_dd
  use module_input
  implicit none

  REAL :: min_ev, max_ev, condi, n_opt
  integer :: mdmc, min_i, max_i, counter1, mid, fid
  integer, save :: count = 0
  logical :: mid_done(size(action%mtilde))
  character(len=6)::tol

  if (.not. switches%measure_minmax) return
  DEBUG2S("Start minmax")

  call init_imp_all(.false.)

  tol = trim(input%solver_rest_cg_ritz)

  count = count + 1
  counter1 = counter%traj

  if (count == 1 .and. my_pe() == 0) then
     write(UREC,110)"T%egnv", "traj", "mid", "type", "min", "max", &
                    "it_min","it_max", "tol  ", "condi", "n_opt"
  endif

  select case (mdmc)
     case (AFTER_HMC)
        do mid = 1, n_mtilde
           call minmax_id(EO_NORMAL, mid, min_ev, max_ev, min_i, max_i)
           condi = max_ev/min_ev
           n_opt = log(condi) * HALF
           if (my_pe() == 0 ) write(UREC,111)" %egnv", counter1, &
              mid, EO_NORMAL, min_ev,max_ev, min_i,max_i, tol, condi, n_opt
        enddo
        if (ddable) then
        do mid = 1, n_mtilde
           call minmax_id(DD_NORMAL, mid, min_ev, max_ev, min_i, max_i)
           condi = max_ev/min_ev
           n_opt = log(condi) * HALF
           if (my_pe() == 0 ) write(UREC,111)" %egnv", counter1, &
              mid, DD_NORMAL, min_ev,max_ev, min_i,max_i, tol, condi, n_opt
        enddo
        do mid = 1, n_mtilde
           call minmax_id(HH_NORMAL, mid, min_ev, max_ev, min_i, max_i)
           condi = max_ev/min_ev
           n_opt = log(condi) * HALF
           if (my_pe() == 0 ) write(UREC,111)" %egnv", counter1, &
              mid, HH_NORMAL, min_ev,max_ev, min_i,max_i, tol, condi, n_opt
        enddo
        endif
     case default
        call die("minmax: unknown case")
  end select
110 format (1x, a, a10, 2a6, 2a18,   2a14, 2x, a6, a13,   a9   )
111 format (1x, a, i10, 2i6, 2g18.8, 2i14, 2x, a6, f13.3, f9.2 )
  DEBUG2S("End minmax")
end

!-------------------------------------------------------------------------------
subroutine minmax_id(ftype, mid, min_ev, max_ev, min_i, max_i)
  implicit none
  integer, intent(in) :: ftype, mid
  REAL, intent(out)   :: min_ev, max_ev
  integer,intent(out) :: min_i, max_i

  call init_quark(mid)
!!  if (ftype == UN_NORMAL .or. ftype == UN_RATIONAL) then
!!     call minmax1_id(       mid, min_ev, max_ev, min_i, max_i) ! vol
!!  else
     call minmax2_id(ftype, mid, min_ev, max_ev, min_i, max_i) ! volh
!!  endif
end

!!!-------------------------------------------------------------------------------
!!subroutine minmax1_id(id, min_ev, max_ev, min_i, max_i)
!!  use module_evec
!!  use module_function_decl
!!  use module_p_interface
!!  implicit none
!!  integer, intent(in) :: id
!!  REAL, intent(out)   :: min_ev, max_ev
!!  integer,intent(out) :: min_i, max_i
!!  integer :: i, ierr
!!
!!  if (neig == 0) then
!!     call stderr2("Warning!!! minmax was called but       ")
!!     call stderr2("Warning!!! measure_minmax == 0 in input")
!!     call stderr2("Warning!!! BQCD assuemes measure_minmax == 1")
!!     neig = 1
!!  endif
!!
!!  if (.not. associated(evech1)) then
!!     allocate(evech1(neig), STAT = ierr)
!!     if (ierr /= 0) then
!!        call stderr2_int("allocation failed", 1, ierr)
!!        call die("minmax1_id: allocation failed evech1")
!!     endif
!!     do i = 1, neig
!!        nullify(evech1(i)%xe)
!!        nullify(evech1(i)%xo)
!!        ALLOCATE_SC_OVERINDEXED(evech1(i)%xe)
!!        ALLOCATE_SC_OVERINDEXED(evech1(i)%xo)
!!     enddo
!!  endif
!!
!!  call cg_ritz_cont1(id, neig, evech1, max_i, 1) !min
!!  max_ev=evech1(1)%eval
!!  if (neig > 1) then
!!     do i=1, neig
!!        if (my_pe() == 0 ) write(UREC,100)" %egn_h", id, i, evech1(i)%eval
!!     enddo
!!  endif
!!
!!  call cg_ritz_cont1(id, neig, evech1, min_i, 0) !min
!!  min_ev=evech1(1)%eval
!!  if (neig > 1) then
!!     do i=1, neig
!!        if (my_pe() == 0 ) write(UREC,100)" %egn_l", id, i, evech1(i)%eval
!!     enddo
!!  endif
!!
!!100 format (1x, a, 2i5, 2g18.8)
!!
!!end

!-------------------------------------------------------------------------------
subroutine minmax2_id(ftype, id, min_ev, max_ev, min_i, max_i)
  use module_evec
  use module_function_decl
  use module_p_interface
  implicit none
  integer, intent(in) :: ftype, id
  REAL, intent(out)   :: min_ev, max_ev
  integer,intent(out) :: min_i, max_i
  integer :: i, ierr

  DEBUG2S("Start: minmax2_id")

  if (neig == 0) then
     call stderr2("Warning!!! minmax was called but       ")
     call stderr2("Warning!!! measure_minmax == 0 in input")
     call stderr2("Warning!!! BQCD assuemes measure_minmax == 1")
     neig = 1
  endif

  if (.not. associated(evech2)) then
     allocate(evech2(neig), STAT = ierr)
     if (ierr /= 0) then
        call stderr2_int("allocation failed", 1, ierr)
        call die("minmax2_id: allocation failed evech2")
     endif
     do i = 1, neig
        nullify(evech2(i)%x)
        ALLOCATE_SC_OVERINDEXED(evech2(i)%x)
     enddo
  endif

  call cg_ritz_cont2(ftype, id, neig, evech2, max_i, 1) !min
  max_ev=evech2(1)%eval
  if (neig > 1) then
     do i=1, neig
        if (my_pe() == 0 ) write(UREC,100)" %egn_h", id, i, evech2(i)%eval
     enddo
  endif

  call cg_ritz_cont2(ftype, id, neig, evech2, min_i, 0) !min
  min_ev=evech2(1)%eval
  if (neig > 1) then
     do i=1, neig
        if (my_pe() == 0 ) write(UREC,100)" %egn_l", id, i, evech2(i)%eval
     enddo
  endif

100 format (1x, a, 2i5, 2g18.8)

  DEBUG2S("End: minmax2_id")
end
!===============================================================================
