! @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ !
! @@                                                                @@ !
! @@       PROGRAM  ASCOT 2014.440 (ver.4.53)                       @@ !
! @@     "Abinitio Simulation Code for Quantum Transport"           @@ !
! @@                                                                @@ !
! @@                                                                @@ !
! @@  AUTHOR(S): Hisashi KONDO (Univ. Tokyo)                        @@ !
! @@             Naoki WATANABE (Mizuho I.R.)                       @@ !
! @@             Nobutaka NISHIKAWA (Mizuho I.R.)                   @@ !
! @@                                                09/May/2014     @@ !
! @@                                                                @@ !
! @@  Contact address: Phase System Consortium                      @@ !
! @@                                                                @@ !
! @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ !

subroutine selfenergy_l( descCC, descCL, descLL, w,iw_do,px,py,ispin,kt )
  use hamiltonian_sgf
  use hamiltonian_c
  use gf_se_c
  use constant
  use condition_ini
  use scf_negf
  use ac_mpi_module

  implicit none
  type(MPI_MatDesc), intent(in) :: descLL, descCL, descCC
  integer, intent(in) :: iw_do,ispin,kt
  integer, intent(in) :: px,py
  complex(8), intent(in) :: w

  integer :: ier
  integer :: i, j
  complex(8), allocatable :: amat_temp1(:,:),amat_temp2(:,:)
  complex(8), allocatable :: amat_temp3(:,:),amat_temp4(:,:)
  complex(8), allocatable :: amat_temp5(:,:)

  complex(8) :: trace

  allocate(amat_temp1(descCL%nrow,descCL%scol:descCL%ecol),stat=ier)
  allocate(amat_temp2(descLL%nrow,descLL%scol:descLL%ecol),stat=ier)
  allocate(amat_temp4(descCL%nrow,descCL%scol:descCL%ecol),stat=ier)
  if( ier /= 0 ) then
     write(6,*) 'error allocate: selfenergy_l'
     stop
  end if

  call surf_gf_l(descLL,w,amat_temp2,px,py,ispin)

  if( gra_onoff /= 'off' ) then
     call MPI__ZLATRA_ASCOT( descLL, amat_temp2, trace )
     call cal_print_text11(iw_do,trace,ispin,kt)
  end if

  call alo_hami_c1(descCL)

  if( ham_model_ini == 'input' .or. ham_model_ini == 'scf_accel') then
     call set_hami_c_ll_input(descCL,descLL,ispin)
  else
     call set_hami_c_ll(descCL,px,py)
  end if

  amat_temp1(:,:) = w*scl_mat(:,:) - hcl_mat(:,:) 
  amat_temp4(:,:) = dconjg(w)*scl_mat(:,:) - hcl_mat(:,:) 

  call unset_hami_c1

  allocate(amat_temp3(descCL%nrow,descCL%scol:descCL%ecol),stat=ier)
  allocate(amat_temp5(descCC%nrow,descCC%scol:descCC%ecol),stat=ier)

  call MPI__ZGEMM2_ASCOT( 'N', 'N', descCL, descLL, descCL, &
       C1, amat_temp1, amat_temp2, C0, amat_temp3 )
  call MPI__ZGEMM2_ASCOT( 'N', 'C', descCL, descCL, descCC, &
       C1, amat_temp3, amat_temp4, C0, amat_temp5 )

  se_l_mat_per(:,:,px,py) = amat_temp5(:,:) 

  deallocate(amat_temp1,amat_temp2,amat_temp3,amat_temp4,amat_temp5,stat=ier)
  if( ier /= 0 ) then
     write(6,*) 'error deallocate: selfenergy_l'
     stop
  end if

  return
end subroutine selfenergy_l
subroutine surf_gf_l(descLL,w,amat_temp2,kx,ky,ispin)

  use condition_ini
  use surface_green_function
  use hamiltonian_sgf
  use hamiltonian_e
  use ac_mpi_module

  implicit none
  type(MPI_MatDesc), intent(in) :: descLL
  complex(8), intent(in) :: w
  complex(8), intent(out) :: amat_temp2(descLL%nrow,descLL%scol:descLL%ecol)
  integer, intent(in) :: kx,ky,ispin

  integer :: i, j

  mat_max=mat_max_ll

  call set_condition_l
  call set_hamiltonian_l(descLL,kx,ky,ispin)

  if( sgf_method_ini == 'transfer' ) then
     call alo_surface_gf_transefer(descLL)
  else
     if( sgf_method_ini == 'direct' ) then
        call alo_surface_gf_direct(descLL)
     else
        write(6,*) 'error - sgf_method_l'
     end if
  end if

  if( sgf_method_ini == 'transfer' ) then
     call su_gf_trans(descLL,iteration_max_ini,eps_ini, &
          h00_mat,h01_mat,h10_mat,s00_mat,s01_mat,s10_mat,w) 
  else
     if( sgf_method_ini == 'direct' ) then
        call su_gf_direct(descLL,iteration_max_ini,eps_ini, &
             h00_mat,h01_mat,h10_mat,s00_mat,s01_mat,s10_mat,w) 
     end if
  end if

  amat_temp2(:,:) = gr00(:,:)

  if( sgf_method_ini == 'transfer' ) then
     call unset_surface_gf_transefer
  else
     if( sgf_method_ini == 'direct' ) then
        call unset_surface_gf_direct
     end if
  end if

  call unset_hamiltonian
  call unset_condition_l

  return
end subroutine surf_gf_l
