program casscf
  implicit none
  BEGIN_DOC
! Optimize MOs and CI coefficients of the CAS
  END_DOC
  
  double precision, allocatable  :: pt2(:), norm_pert(:), H_pert_diag(:)
  integer(bit_kind), allocatable  :: generators_bitmask_save(:,:,:,:) 

  integer                        :: degree, N_generators_bitmask_save, N_det_ci
  double precision               :: E_old, E_CI
  double precision               :: selection_criterion_save, selection_criterion_min_save
  
  integer                        :: N_det_old
  integer                        :: i, j, k, l
  integer                        :: i_bit, j_bit, i_int, j_int
  integer(bit_kind), allocatable :: bit_tmp(:), cas_bm(:)
  character*(64) :: label

  allocate( pt2(N_states), norm_pert(N_states),H_pert_diag(N_states) )
  allocate( generators_bitmask_save(N_int,2,6,N_generators_bitmask) )
  allocate( bit_tmp(N_int), cas_bm(N_int) )

  PROVIDE N_det_cas
  N_det_old = 0
  pt2 = 1.d0
  E_CI = 1.d0
  E_old = 0.d0
  diag_algorithm = "Lapack"
  selection_criterion_save = selection_criterion
  selection_criterion_min_save = selection_criterion_min


  cas_bm = 0_bit_kind
  do i=1,N_cas_bitmask
    do j=1,N_int
      cas_bm(j) = ior(cas_bm(j), cas_bitmask(j,1,i))
      cas_bm(j) = ior(cas_bm(j), cas_bitmask(j,2,i))
    enddo
  enddo

  ! Save CAS-SD bitmask
  generators_bitmask_save = generators_bitmask
  N_generators_bitmask_save = N_generators_bitmask

  ! Set the CAS bitmask 
  do i=1,6
    generators_bitmask(:,:,i,:) = cas_bitmask
  enddo
  N_generators_bitmask = N_cas_bitmask
  SOFT_TOUCH generators_bitmask N_generators_bitmask


  ! If the number of dets already in the file is larger than the requested
  ! number of determinants, truncate the wf
  if (N_det > N_det_max) then
    call diagonalize_CI
    call save_wavefunction
    psi_det = psi_det_sorted
    psi_coef = psi_coef_sorted
    N_det = N_det_max
    soft_touch N_det psi_det psi_coef
    call diagonalize_CI
    call save_wavefunction
    print *,  'N_det    = ', N_det
    print *,  'N_states = ', N_states
    print *,  'PT2      = ', pt2
    print *,  'E        = ', CI_energy
    print *,  'E+PT2    = ', CI_energy+pt2
    print *,  '-----'
  endif

  ! Start MCSCF iteration

  ! CAS-CI
  ! ------

  E_old = E_CI

  ! Reset the selection criterion
  selection_criterion     = selection_criterion_save
  selection_criterion_min = selection_criterion_min_save
  SOFT_TOUCH selection_criterion_min selection_criterion selection_criterion_factor

  ! Set the CAS bitmask 
  do i=1,6
    generators_bitmask(:,:,i,:) = cas_bitmask
  enddo
  N_generators_bitmask = N_cas_bitmask
  SOFT_TOUCH generators_bitmask N_generators_bitmask

  do while (N_det < N_det_max.and.maxval(abs(pt2(1:N_states))) > pt2_max)
    N_det_old = N_det
    call H_apply_CAS_SD_selected_no_skip(pt2, norm_pert, H_pert_diag,  N_states)

    PROVIDE  psi_coef
    PROVIDE  psi_det
    PROVIDE  psi_det_sorted

    if (N_det > N_det_max) then
      psi_det = psi_det_sorted
      psi_coef = psi_coef_sorted
      N_det = N_det_max
      soft_touch N_det psi_det psi_coef
    endif
    call diagonalize_CI
    call save_wavefunction
    print *,  '======'
    print *,  'CAS-CI'
    print *,  '======'
    print *,  ''
    print *,  'N_det      = ', N_det
    print *,  'N_states   = ', N_states
    print *,  'PT2        = ', pt2
    print *,  'E(CAS)     = ', CI_energy
    print *,  'E(CAS)+PT2 = ', CI_energy+pt2
    print *,  '-----'
    print *,  ''
    E_CI = sum(CI_energy(1:N_states)+pt2(1:N_states))/dble(N_states)

    call ezfio_set_casscf_energy(CI_energy(1))
    if (N_det == N_det_old) then
      exit
    endif

  enddo

  ! Super-CI
  ! --------

  selection_criterion_min = 1.d-12
  selection_criterion     = 1.d-12

  ! Set the CAS bitmask
  generators_bitmask = generators_bitmask_save
  N_generators_bitmask = N_generators_bitmask_save
  SOFT_TOUCH generators_bitmask N_generators_bitmask selection_criterion selection_criterion_min selection_criterion_factor

  N_det_ci = N_det

  call H_apply_CAS_SD_selected(pt2, norm_pert, H_pert_diag,  N_states)
  

  do i=1,mo_tot_num
   i_int = ishft(i-1,-bit_kind_shift)+1
   i_bit = j-ishft(i_int-1,bit_kind_shift)-1
   bit_tmp(:) = 0_bit_kind
   bit_tmp(i_int) = ibset(0_bit_kind,i_bit)
   if (iand(bit_tmp(i_int), cas_bm(i_int)) == 0_bit_kind) then
     ! Not a CAS MO
     cycle
   endif

   do j=1,mo_tot_num
     if (j == i) then
       cycle
     endif
     j_int = ishft(j-1,-bit_kind_shift)+1
     j_bit = j-ishft(j_int-1,bit_kind_shift)-1
     bit_tmp(:) = 0_bit_kind
     bit_tmp(j_int) = ibset(0_bit_kind,j_bit)
     if (iand(bit_tmp(j_int), cas_bm(j_int)) == 0_bit_kind) then
       ! Not a CAS MO
       cycle
     endif
     ! Now, both i and j are MOs of the CAS. De-couple them in the DM
     one_body_dm_mo(i,j) = 0.d0
   enddo

  enddo

  SOFT_TOUCH one_body_dm_mo

  double precision               :: mx, ov
  double precision, allocatable  :: mo_coef_old(:,:)
  integer, allocatable           :: iorder(:)
  logical, allocatable           :: selected(:)
  allocate( mo_coef_old(size(mo_coef,1), size(mo_coef,2)), iorder(mo_tot_num), selected(mo_tot_num) )
  mo_coef_old = mo_coef
  label = "Canonical"
  call mo_as_eigvectors_of_mo_matrix(one_body_dm_mo,size(one_body_dm_mo,1),size(one_body_dm_mo,2),label,-1)
  selected = .False.
  do j=1,mo_tot_num
   mx = -1.d0
   iorder(j) = j
   do i=1,mo_tot_num
    if (selected(i)) then
      cycle
    endif
    ov = 0.d0
    do l=1,ao_num
     do k=1,ao_num
      ov = ov + mo_coef_old(k,j) * ao_overlap(k,l) * mo_coef(l,i)
     enddo
    enddo
    ov= dabs(ov)
    if (ov > mx) then
      mx = ov
      iorder(j) = i
    endif
   enddo
   selected( iorder(j) ) = .True.
  enddo
  mo_coef_old = mo_coef
  do i=1,mo_tot_num
    mo_coef(:,i) = mo_coef_old(:,iorder(i))
  enddo

  call save_mos

  call write_double(6,E_CI,"Energy(CAS)")

  deallocate( mo_coef_old )
  deallocate( pt2, norm_pert,H_pert_diag )
  deallocate( generators_bitmask_save )
  deallocate( bit_tmp, cas_bm, iorder )
end
