!
! Copyright (C) 2016  Quantum ESPRESSO Foundation
! This file is distributed under the terms of the
! GNU General Public License. See the file `License'
! in the root directory of the present distribution,
! or http://www.gnu.org/copyleft/gpl.txt .
!
! Author: Mitsuaki Kawamura, U. Tokyo
!----------------------------------------------------------------------------
MODULE elph_tetra_mod
  !--------------------------------------------------------------------------
  !
  IMPLICIT NONE
  !
  PRIVATE
  !
  LOGICAL,SAVE :: &
  &  lshift_q = .false., &
  &  in_alpha2f = .FALSE.
  !
  INTEGER,SAVE :: elph_tetra = 0 ! switch to output electron-phonon matrix
  !
  PUBLIC elph_tetra, lshift_q, in_alpha2f, &
  &      elph_tetra_lambda, elph_tetra_gamma
  !
  CONTAINS
 !
!----------------------------------------------------------------------------
SUBROUTINE elph_tetra_lambda()
  !--------------------------------------------------------------------------
  !
  ! This routine computes the electron-phonon matrix
  ! in the irreducible Brillouin zone and
  ! expand that to whole BZ.
  !
  USE ener, ONLY : ef
  USE constants, ONLY : pi, ry_to_cmm1, ry_to_ghz, rytoev
  USE kinds, ONLY : dp
  USE mp, ONLY : mp_sum, mp_bcast
  USE mp_pools, ONLY : inter_pool_comm
  USE mp_images, ONLY : me_image, nproc_image, intra_image_comm
  USE io_global, ONLY : stdout, ionode, ionode_id
  USE cell_base, ONLY : at, bg
  USE ions_base, ONLY : nat
  USE symm_base, ONLY : s, irt, nsym, invs
  USE klist,  ONLY: nks, nkstot
  USE wvfct, ONLY: et, nbnd
  USE qpoint, ONLY : xq, nksq, ikks
  USE dynmat, ONLY : dyn, w2
  USE el_phon, ONLY : el_ph_mat, elph_nbnd_min, elph_nbnd_max, done_elph, gamma_disp, el_ph_nsigma
  USE control_lr,  ONLY : lgamma
  USE control_ph, ONLY : current_iq, qplot, xmldyn
  USE modes, ONLY : u, nirr
  USE lr_symm_base, ONLY : minus_q, nsymq, rtau, irotmq
  USE lsda_mod,   ONLY : nspin
  USE ktetra,     ONLY : ntetra, tetra, opt_tetra_dos_t
  USE output, ONLY : fildyn
  USE io_files, ONLY : create_directory
  !
  IMPLICIT NONE
  !
  REAL(DP), PARAMETER :: eps = 20_dp/ry_to_cmm1 ! eps = 20 cm^-1, in Ry
  INTEGER :: iq, ipert, jpert, nu, iuelph, nbnd_fs, ntpp, rest, &
  &          tfst, tlst, ios, irr
  REAL(dp) :: dosef(2), lambda(3 * nat), gamma, phase_space
  COMPLEX(dp) :: el_ph_sum (3*nat,3*nat)
  !
  REAL(dp),ALLOCATABLE :: wght(:,:,:), et_col(:,:)
  !
  character(len=80) :: filelph
  INTEGER, EXTERNAL :: find_free_unit
  CHARACTER(LEN=6) :: int_to_char
  !
  ! Used to generate a2fq2r
  !
  integer :: nq, isq (48), imq, isig
  ! nq :  degeneracy of the star of q
  ! isq: index of q in the star of a given sym.op.
  ! imq: index of -q in the star of q (0 if not present)
  real(DP) :: sxq (3, 48)
  ! list of vectors in the star of q
  COMPLEX(DP) :: dyn22(3*nat,3*nat)
  CHARACTER(LEN=256) :: elph_dir
  LOGICAL  :: exst, xmldyn_save
  !  
  DO irr=1,nirr
     IF (.NOT.done_elph(irr)) RETURN
  ENDDO
  !
  ! Work Sharing
  !
  ntpp = ntetra / nproc_image
  rest = MOD(ntetra, nproc_image)
  IF(me_image < rest) THEN
     tfst = (ntpp + 1) *  me_image + 1
     tlst = (ntpp + 1) * (me_image + 1)
  ELSE
     tfst = ntpp *  me_image + 1  + rest
     tlst = ntpp * (me_image + 1) + rest
  END IF
  !
  IF(lgamma) THEN
     iq = 0
  ELSE
     iq = 1
  END IF
  !
  nbnd_fs = elph_nbnd_max - elph_nbnd_min + 1
  !
  WRITE(stdout,'(a)') ""
  WRITE(stdout,'(a,i10)') "     [elph_tetra]   Lowest band which contains FS : ", elph_nbnd_min
  WRITE(stdout,'(a,i10)') "     [elph_tetra]  Highest band which contains FS : ", elph_nbnd_max
  WRITE(stdout,'(a,i10)') "     [elph_tetra]    # of bands which contains FS : ", nbnd_fs
  !
  ! Collect eigval
  !
  ALLOCATE(wght(nbnd_fs,nbnd_fs,nkstot), et_col(nbnd, nkstot))
  !
  CALL poolcollect(nbnd, nks, et, nkstot, et_col)
  !
  IF(lgamma) THEN
     !
     wght(1:nbnd_fs,1:nbnd_fs,1:nkstot) = 0.0_dp
     phase_space = 0.0_dp
     !
     WRITE(stdout,'(a)') "     ##############  Please Chack  ##############"
     WRITE(stdout,'(a)') "       \lambda_{q \nu} is singular at q = \Gamma"
     WRITE(stdout,'(a)') "       You should use shifted q grid            "
     WRITE(stdout,'(a)') "     ############################################"
     !
  ELSE
     !
     CALL elph_tetra_delta1(nbnd_fs,iq,tfst,tlst,et_col,wght)
     phase_space = SUM(wght(1:nbnd_fs,1:nbnd_fs,1:nkstot))
     CALL poolscatter( nbnd_fs*nbnd_fs, nkstot, wght, nks, wght)
     CALL elph_tetra_average_weight(1,nbnd_fs,wght)
     !
  END IF
  !
  DO jpert = 1, 3 * nat
     DO ipert = 1, 3 * nat
        !
        el_ph_sum (ipert, jpert) = SUM(wght( 1:nbnd_fs, 1:nbnd_fs, ikks(1:nksq)) &
        & *       el_ph_mat(elph_nbnd_min:elph_nbnd_max, elph_nbnd_min:elph_nbnd_max, 1:nksq, jpert) &
        & * CONJG(el_ph_mat(elph_nbnd_min:elph_nbnd_max, elph_nbnd_min:elph_nbnd_max, 1:nksq, ipert)) )
     END DO
  END DO
  !
  CALL mp_sum(el_ph_sum, inter_pool_comm)
  !
  CALL symdyn_munu_new (el_ph_sum, u, xq, s, invs, rtau, irt,  at, bg, nsymq, nat, irotmq, minus_q)
  !
  dosef(1:2) = 0.0_dp
  CALL opt_tetra_dos_t (et_col, nspin, nbnd, nkstot, ef, dosef)
  !
  dosef(1:2) = 0.5_dp * dosef(1:2)
  !
  DO nu = 1, 3 * nat
     !
     lambda(nu) = 0.0_dp
     DO ipert = 1, 3 * nat
        DO jpert = 1, 3 * nat
           lambda(nu) = lambda(nu) &
           & + REAL(CONJG(dyn(jpert, nu)) * el_ph_sum(jpert, ipert) * dyn(ipert, nu), dp)
        END DO
     END DO
     !
     IF(w2(nu) >= 0.0_dp) THEN
        lambda(nu) = lambda(nu) / (2.0_dp * w2(nu) * SUM(dosef(1:2)))
     ELSE
        lambda(nu) = 0.0_dp
     END IF
     !
  END DO
  !
  ! Output
  !
  filelph=TRIM(fildyn)//'.elph.'//TRIM(int_to_char(current_iq))
  !
  ! parallel case: only first node writes
  IF ( ionode ) THEN
     !
     iuelph = find_free_unit()
     OPEN (unit = iuelph, file = TRIM(filelph), status = 'unknown', err = &
          100, iostat = ios)
     REWIND (iuelph)
  ELSE
     iuelph = 0
     !
  END IF
100 CONTINUE
  CALL mp_bcast(ios,ionode_id,intra_image_comm)
  CALL errore ('elph_tetra_lambda', 'opening file '//filelph, ABS (ios) )
  !
  IF (ionode) THEN
     WRITE (iuelph, '(3f15.8,i8)') xq, 3 * nat
     WRITE (iuelph, '(6e14.6)') (w2 (nu) , nu = 1, 3 * nat)
  ENDIF
  WRITE (stdout, *)
  WRITE (stdout, 9000)
  WRITE (stdout, 9005) SUM(dosef(1:2)), ef * rytoev
  WRITE (stdout, 9006) phase_space
  !
  IF (ionode) THEN
     WRITE (iuelph, 9000)
     WRITE (iuelph, 9005) SUM(dosef(1:2)), ef * rytoev
  ENDIF
  !
  DO nu = 1, 3 * nat
     !
     gamma = lambda(nu) * pi * w2(nu) * SUM(dosef(1:2))
     !
     WRITE (stdout, 9010) nu, lambda(nu), gamma * ry_to_gHz
     IF (ionode) WRITE (iuelph, 9010) nu, lambda(nu), gamma * ry_to_gHz
     IF (qplot) gamma_disp(nu,1,current_iq) = gamma * ry_to_gHz
     !
  END DO
  !
9000 FORMAT(5x,'Tetrahedron method')
9005 FORMAT(5x,'DOS =',f10.6,' states/spin/Ry/Unit Cell at Ef=', &
          &       f10.6,' eV')
9006 FORMAT(5x,'double delta at Ef =',f10.6)
9010 FORMAT(5x,'lambda(',i5,')=',f8.4,'   gamma=',f8.2,' GHz')
  !
  IF (ionode) CLOSE (unit = iuelph)
  !
  !    Prepare interface to q2r and matdyn
  !
  elph_dir='elph_dir/'
  IF (ionode) INQUIRE(file=TRIM(elph_dir), EXIST=exst)
  CALL mp_bcast(exst, ionode_id, intra_image_comm) 
  IF (.NOT.exst) CALL create_directory( elph_dir )
  !
  call star_q (xq, at, bg, nsym, s, invs, nq, sxq, isq, imq, .TRUE. )
  !
  DO isig = 1, el_ph_nsigma !=nsig in elphsum
     filelph = TRIM(elph_dir)//'a2Fq2r.'// TRIM(int_to_char(50 + isig)) &
                                  //'.'//TRIM(int_to_char(current_iq))
     IF (ionode) THEN
        iuelph = find_free_unit()
        OPEN(iuelph, file=filelph, STATUS = 'unknown', FORM = 'formatted', &
                     iostat=ios)
     ELSE
        !
        ! this node doesn't write: unit 6 is redirected to /dev/null
        !
        iuelph =6
     END IF
     CALL mp_bcast(ios, ionode_id, intra_image_comm)
     IF (ios /= 0) CALL errore('elph_tetra_lambda','opening output file '// TRIM(filelph),1)
     dyn22(1:3*nat,1:3*nat) = el_ph_sum(1:3*nat,1:3*nat)
     WRITE(iuelph,*) 0.0_dp, ef, SUM(dosef(1:2))
     IF ( imq == 0 ) THEN
        write(iuelph,*) 2*nq
     ELSE
        write(iuelph,*) nq
     ENDIF
     xmldyn_save=xmldyn
     xmldyn=.FALSE.
     CALL q2qstar_ph (dyn22, at, bg, nat, nsym, s, invs, &
          irt, rtau, nq, sxq, isq, imq, iuelph)
     xmldyn=xmldyn_save
     IF (ionode) CLOSE( UNIT = iuelph, STATUS = 'KEEP' )
  END DO
  !
  DEALLOCATE(wght, et_col)
  !
END SUBROUTINE elph_tetra_lambda
!
!-----------------------------------------------------------------------
SUBROUTINE elph_tetra_delta1(nbnd_fs,iq,tfst,tlst,et_col,wght)
  !---------------------------------------------------------------------
  !
  ! This routine computed the weight for the double-delta function.
  !
  USE kinds, ONLY : dp
  USE mp, ONLY : mp_sum
  USE mp_images, ONLY : intra_image_comm
  USE el_phon, ONLY : elph_nbnd_min
  USE ener,   ONLY : ef
  USE wvfct, ONLY: nbnd
  USE klist,  ONLY: nkstot
  USE lsda_mod,   ONLY : nspin
  USE ktetra, ONLY : tetra, ntetra, nntetra, wlsm
  !
  INTEGER,INTENT(IN) :: nbnd_fs, iq, tfst, tlst
  REAL(dp),INTENT(IN) :: et_col(nbnd, nkstot)
  REAL(dp),INTENT(OUT) :: wght(nbnd_fs, nbnd_fs, nkstot)
  !
  INTEGER :: nspin_lsda, ns, nk, nt, ii, jj, ibnd, itetra(4), ik
  REAL(dp) :: ei0(4,nbnd_fs), ej0(4,nbnd_fs), e(4), a(4,4), V, tsmall(4,4), &
  &           ej1(3,nbnd_fs), w0(nbnd_fs,nbnd_fs,4), w1(nbnd_fs,3)
  !
  wght(1:nbnd_fs,1:nbnd_fs,1:nkstot) = 0.0_dp
  !
  IF ( nspin == 2 ) THEN
     nspin_lsda = 2
  ELSE
     nspin_lsda = 1
  END IF
  !
  DO ns = 1, nspin_lsda
     !
     ! nk is used to select k-points with up (ns=1) or down (ns=2) spin
     !
     IF (ns == 1) THEN
        nk = 0
     ELSE
        nk = nkstot / 2
     END IF
     !
     DO nt = tfst, tlst
        !
        ei0(1:4, 1:nbnd_fs) = 0.0_dp
        ej0(1:4, 1:nbnd_fs) = 0.0_dp
        DO ii = 1, nntetra
           !
           ik = tetra(ii, nt) + nk
           DO ibnd = 1, nbnd_fs
              ei0(1:4, ibnd) = ei0(1:4, ibnd) &
              &             + wlsm(1:4,ii) * (et_col(ibnd + elph_nbnd_min - 1, ik)    - ef)
              ej0(1:4, ibnd) = ej0(1:4, ibnd) &
              &             + wlsm(1:4,ii) * (et_col(ibnd + elph_nbnd_min - 1, ik+iq) - ef)
           END DO
           !
        END DO
        !
        w0(1:nbnd_fs,1:nbnd_fs,1:4) = 0.0_dp
        !
        DO ibnd = 1, nbnd_fs
           !
           itetra(1) = 0
           e(1:4) = ei0(1:4, ibnd)
           call hpsort (4, e, itetra)
           !
           DO ii = 1, 4
              a(1:4,ii) = (0.0_dp - e(ii)) / (e(1:4) - e(ii))
           END DO
           !
           IF(e(1) < 0.0_dp .AND. 0.0_dp <= e(2)) THEN
              !
              ! A
              !
              !V = 3.0_dp * a(2,1) * a(3,1) * a(4,1) / (0.0_dp - e(1))
              V = 3.0_dp * a(2,1) * a(3,1)           / (e(4) - e(1))
              !
              tsmall(1, 1:4) = (/a(1,2), a(2,1), 0.0_dp, 0.0_dp/)
              tsmall(2, 1:4) = (/a(1,3), 0.0_dp, a(3,1), 0.0_dp/)
              tsmall(3, 1:4) = (/a(1,4), 0.0_dp, 0.0_dp, a(4,1)/)
              !
              ej1(1:3,1:nbnd_fs) = MATMUL(tsmall(1:3,1:4), ej0(itetra(1:4), 1:nbnd_fs))
              !
              CALL elph_tetra_delta2(nbnd_fs,ej1,w1)
              !
              w0(1:nbnd_fs,ibnd,itetra(1:4)) = w0(1:nbnd_fs,ibnd,itetra(1:4)) &
              &           + V * MATMUL(w1(1:nbnd_fs,1:3), tsmall(1:3,1:4))
              !
           ELSE IF( e(2) < 0.0_dp .AND. 0.0_dp <= e(3)) THEN
              !
              ! B - 1
              !
              !V = 3.0_dp * a(3,1) * a(4,1) * a(2,4) / (0.0_dp - e(1))
              V = 3.0_dp           * a(4,1) * a(2,4) / (e(3) - e(1))
              !
              tsmall(1, 1:4) = (/a(1,3), 0.0_dp, a(3,1), 0.0_dp/)
              tsmall(2, 1:4) = (/a(1,4), 0.0_dp, 0.0_dp, a(4,1)/)
              tsmall(3, 1:4) = (/0.0_dp, a(2,4), 0.0_dp, a(4,2)/)
              !
              ej1(1:3,1:nbnd_fs) = MATMUL(tsmall(1:3,1:4), ej0(itetra(1:4), 1:nbnd_fs))
              !
              CALL elph_tetra_delta2(nbnd_fs,ej1,w1)
              !
              w0(1:nbnd_fs,ibnd,itetra(1:4)) = w0(1:nbnd_fs,ibnd,itetra(1:4)) &
              &           + V * MATMUL(w1(1:nbnd_fs,1:3), tsmall(1:3,1:4))
              !
              ! B - 2
              !
              !V = 3.0_dp * a(2,3) * a(3,1) * a(4,2) / (0.0_dp - e(1))
              V = 3.0_dp * a(2,3)           * a(4,2) / (e(3) - e(1))
              !
              tsmall(1, 1:4) = (/a(1,3), 0.0_dp, a(3,1), 0.0_dp/)
              tsmall(2, 1:4) = (/0.0_dp, a(2,3), a(3,2), 0.0_dp/)
              tsmall(3, 1:4) = (/0.0_dp, a(2,4), 0.0_dp, a(4,2)/)
              !
              ej1(1:3,1:nbnd_fs) = MATMUL(tsmall(1:3,1:4), ej0(itetra(1:4), 1:nbnd_fs))
              !
              CALL elph_tetra_delta2(nbnd_fs,ej1,w1)
              !
              w0(1:nbnd_fs,ibnd,itetra(1:4)) = w0(1:nbnd_fs,ibnd,itetra(1:4)) &
              &           + V * MATMUL(w1(1:nbnd_fs,1:3), tsmall(1:3,1:4))
              !
           ELSE IF(e(3) < 0.0_dp .AND. 0.0_dp < e(4)) THEN
              !
              ! C
              !
              !V = 3.0_dp * a(1,4) * a(2,4) * a(3,4) / (e(4) - 0.0_dp)
              V = 3.0_dp * a(1,4) * a(2,4)           / (e(4) - e(3))
              !
              tsmall(1, 1:4) = (/a(1,4), 0.0_dp, 0.0_dp, a(4,1)/)
              tsmall(2, 1:4) = (/0.0_dp, a(2,4), 0.0_dp, a(4,2)/)
              tsmall(3, 1:4) = (/0.0_dp, 0.0_dp, a(3,4), a(4,3)/)
              !
              ej1(1:3,1:nbnd_fs) = MATMUL(tsmall(1:3,1:4), ej0(itetra(1:4), 1:nbnd_fs))
              !
              CALL elph_tetra_delta2(nbnd_fs,ej1,w1)
              !
              w0(1:nbnd_fs,ibnd,itetra(1:4)) = w0(1:nbnd_fs,ibnd,itetra(1:4)) &
              &           + V * MATMUL(w1(1:nbnd_fs,1:3), tsmall(1:3,1:4))
              !
           END IF
           !
        END DO
        !
        DO ii = 1, nntetra
           !
           ik = tetra(ii, nt) + nk
           DO jj = 1, 4
              wght(1:nbnd_fs,1:nbnd_fs,ik) = wght(1:nbnd_fs,1:nbnd_fs,ik) &
              &             + wlsm(jj,ii) * w0(1:nbnd_fs, 1:nbnd_fs, jj)
           END DO
           !
        END DO ! ii
        !
     END DO ! nt
     !
  END DO ! ns
  !
  wght(1:nbnd_fs,1:nbnd_fs,1:nkstot) = wght(1:nbnd_fs,1:nbnd_fs,1:nkstot) &
       / REAL(ntetra, dp)
  IF(nspin == 1) wght(1:nbnd_fs,1:nbnd_fs,1:nkstot) = 2.0_dp * &
                     wght(1:nbnd_fs,1:nbnd_fs,1:nkstot)
  !
  CALL mp_sum(wght, intra_image_comm)
  !
END SUBROUTINE elph_tetra_delta1
!
!-------------------------------------------------------------------------------
SUBROUTINE elph_tetra_delta2(nbnd_fs,ej0,w)
  !-----------------------------------------------------------------------------
  !
  ! 2nd step of tetrahedra method.
  !
  USE kinds, ONLY : dp
  !
  INTEGER,INTENT(IN) :: nbnd_fs
  REAL(dp),INTENT(IN) :: ej0(3,nbnd_fs)
  REAL(dp),INTENT(OUT) :: w(nbnd_fs,3)
  !
  INTEGER :: ibnd, itetra(3), ii
  REAL(dp) :: e(3), a(3,3), V
  !
  w(1:nbnd_fs, 1:3) = 0.0_dp
  !
  DO ibnd = 1, nbnd_fs
     !
     IF(MAXVAL(ABS(ej0(1:3,ibnd))) < 1e-10_dp) &
     & CALL errore("elph_tetra_delta2", "Nesting occurs.", ibnd)
     !
     itetra(1) = 0
     e(1:3) = ej0(1:3,ibnd)
     call hpsort (3, e, itetra)
     !
     DO ii = 1, 3
        a(1:3,ii) = (0.0_dp - e(ii)) / (e(1:3) - e(ii))
     END DO
     !
     IF((e(1) < 0.0_dp .AND. 0.0_dp <= e(2)) .OR. (e(1) <= 0.0_dp .AND. 0.0_dp < e(2))) THEN
        !
        !V = a(2,1) * a(3,1) / (0.0_dp - e(1)) 
        V = a(2,1)           / (e(3) - e(1)) 
        !
        w(ibnd,itetra(1)) = V * (a(1,2) + a(1,3))
        w(ibnd,itetra(2)) = V * a(2,1)
        w(ibnd,itetra(3)) = V * a(3,1)
        !
     ELSE IF((e(2) <= 0.0_dp .AND. 0.0_dp < e(3)) .OR. (e(2) < 0.0_dp .AND. 0.0_dp <= e(3))) THEN
        !
        !V = a(1,3) * a(2,3) / (e(3) - 0.0_dp) 
        V = a(1,3)           / (e(3) - e(2)) 
        !
        w(ibnd,itetra(1)) = V * a(1,3)
        w(ibnd,itetra(2)) = V * a(2,3)
        w(ibnd,itetra(3)) = V * (a(3,1) + a(3,2))
        !
     END IF
     !
  END DO ! ib
  !
END SUBROUTINE elph_tetra_delta2
!
!----------------------------------------------------------------------------
SUBROUTINE elph_tetra_gamma()
  !--------------------------------------------------------------------------
  !
  ! This routine computes the electron-phonon matrix
  ! in the irreducible Brillouin zone and
  ! expand that to whole BZ.
  !
  USE ener, ONLY : ef
  USE constants, ONLY : pi, ry_to_cmm1, ry_to_ghz, rytoev, amu_ry
  USE kinds, ONLY : dp
  USE mp, ONLY : mp_sum, mp_bcast
  USE mp_pools, ONLY : inter_pool_comm
  USE io_global, ONLY : stdout, ionode, ionode_id
  USE cell_base, ONLY : at, bg
  USE ions_base, ONLY : nat
  USE symm_base, ONLY : s, irt, nsym, invs
  USE klist,  ONLY: nks, nkstot
  USE wvfct, ONLY: et, nbnd
  USE qpoint, ONLY : xq, nksq, ikks
  USE dynmat, ONLY : dyn, w2
  USE el_phon, ONLY : el_ph_mat, elph_nbnd_min, elph_nbnd_max, done_elph, gamma_disp, el_ph_nsigma
  USE control_lr,  ONLY : lgamma
  USE control_ph, ONLY : current_iq, qplot, xmldyn
  USE modes, ONLY : u, nirr
  USE lr_symm_base, ONLY : minus_q, nsymq, rtau, irotmq
  USE lsda_mod,   ONLY : nspin
  USE ktetra,     ONLY : ntetra, tetra, opt_tetra_dos_t
  USE mp_images, ONLY : me_image, nproc_image, intra_image_comm
  USE output, ONLY : fildyn
  USE io_files, ONLY : create_directory
  USE ions_base, ONLY : ityp, amass
  !
  IMPLICIT NONE
  !
  REAL(DP), PARAMETER :: eps = 20_dp/ry_to_cmm1 ! eps = 20 cm^-1, in Ry
  INTEGER :: ipert, jpert, iuelph, nu, nbnd_fs, iq, ntpp, rest, &
  &          tfst, tlst, ios, irr
  REAL(dp) :: dosef(2), lambda(3 * nat), gamma, phase_space(3*nat)
  COMPLEX(dp) :: el_ph_sum (3*nat,3*nat,3*nat)
  !
  REAL(dp),ALLOCATABLE :: wght(:,:,:,:), et_col(:,:)
  !
  character(len=80) :: filelph
  INTEGER, EXTERNAL :: find_free_unit
  CHARACTER(LEN=6) :: int_to_char
  !
  ! Used to generate a2fq2r
  !
  integer :: nq, isq (48), imq, isig
  ! nq :  degeneracy of the star of q
  ! isq: index of q in the star of a given sym.op.
  ! imq: index of -q in the star of q (0 if not present)
  real(DP) :: sxq (3, 48)
  ! list of vectors in the star of q
  COMPLEX(DP) :: dyn22(3*nat,3*nat)
  CHARACTER(LEN=256) :: elph_dir
  LOGICAL  :: exst, xmldyn_save
  !
  DO irr=1,nirr
     IF (.NOT.done_elph(irr)) RETURN
  ENDDO
  !
  ! Work Sharing
  !
  ntpp = ntetra / nproc_image
  rest = MOD(ntetra, nproc_image)
  IF(me_image < rest) THEN
     tfst = (ntpp + 1) *  me_image + 1
     tlst = (ntpp + 1) * (me_image + 1)
  ELSE
     tfst = ntpp *  me_image + 1  + rest
     tlst = ntpp * (me_image + 1) + rest
  END IF
  !
  IF(lgamma) THEN
     iq = 0
  ELSE
     iq = 1
  END IF
  !
  nbnd_fs = elph_nbnd_max - elph_nbnd_min + 1
  !
  WRITE(stdout,'(a)') ""
  WRITE(stdout,'(a,i10)') "     [elph_tetra]   Lowest band which contains FS : ", elph_nbnd_min
  WRITE(stdout,'(a,i10)') "     [elph_tetra]  Highest band which contains FS : ", elph_nbnd_max
  WRITE(stdout,'(a,i10)') "     [elph_tetra]    # of bands which contains FS : ", nbnd_fs
  !
  ! Collect eigval
  !
  ALLOCATE(wght(3 * nat,nbnd_fs,nbnd_fs,nkstot), et_col(nbnd, nkstot))
  !
  CALL poolcollect(nbnd, nks, et, nkstot, et_col)
  !
  CALL elph_tetra_step1(nbnd_fs,iq,tfst,tlst,et_col,wght)
  DO nu = 1, 3* nat
     IF(w2(nu) > 0.0_dp) THEN
        phase_space(nu) = SUM(wght(nu,1:nbnd_fs,1:nbnd_fs,1:nkstot)) / (REAL(3 * nat, dp) * SQRT(w2(nu)))
     ELSE
        phase_space(nu) = 0.0_dp
        wght(nu,1:nbnd_fs,1:nbnd_fs,1:nkstot) = 0.0_dp
     END IF
  END DO
  CALL poolscatter( 3*nat*nbnd_fs*nbnd_fs, nkstot, wght, nks, wght)
  CALL elph_tetra_average_weight(3 * nat,nbnd_fs,wght)
  !
  DO jpert = 1, 3 * nat
     DO ipert = 1, 3 * nat
        DO nu = 1, 3 * nat
           el_ph_sum(ipert, jpert, nu) = SUM(wght(nu, 1:nbnd_fs, 1:nbnd_fs, ikks(1:nksq)) &
           &  * CONJG( el_ph_mat(elph_nbnd_min:elph_nbnd_max, elph_nbnd_min:elph_nbnd_max, 1:nksq, ipert)) &
           &         * el_ph_mat(elph_nbnd_min:elph_nbnd_max, elph_nbnd_min:elph_nbnd_max, 1:nksq, jpert)  )
        END DO
     END DO
  END DO
  !
  CALL mp_sum(el_ph_sum, inter_pool_comm)
  !
  DO nu = 1, 3 * nat
     CALL symdyn_munu_new (el_ph_sum(1:3 * nat,1:3 * nat, nu), u, xq, s, invs, &
     &                     rtau, irt,  at, bg, nsymq, nat, irotmq, minus_q)
  END DO
  !
  dosef(1:2) = 0.0_dp
  CALL opt_tetra_dos_t (et_col, nspin, nbnd, nkstot, ef, dosef)
  !
  dosef(1:2) = 0.5_dp * dosef(1:2)
  !
  DO nu = 1, 3 * nat
     !
     lambda(nu) = 0.0_dp
     !
     DO ipert = 1, 3 * nat
        DO jpert = 1, 3 * nat
           lambda(nu) = lambda(nu) &
           &  + REAL(CONJG(dyn(jpert,nu)) * el_ph_sum(jpert,ipert,nu) * dyn(ipert,nu), dp)
        END DO
     END DO
     !
     IF(w2(nu) >= 0.0_dp) THEN
        lambda(nu) = lambda(nu) / (2.0_dp * w2(nu) * SQRT(w2(nu)) * SUM(dosef(1:2)))
     ELSE
        lambda(nu) = 0.0_dp
     END IF
     !
  END DO
  !
  ! Output
  !
  filelph=TRIM(fildyn)//'.elph.'//TRIM(int_to_char(current_iq))
  !
  ! parallel case: only first node writes
  IF ( ionode ) THEN
     !
     iuelph = find_free_unit()
     OPEN (unit = iuelph, file = TRIM(filelph), status = 'unknown', err = &
          100, iostat = ios)
     REWIND (iuelph)
  ELSE
     iuelph = 0
     !
  END IF
100 CONTINUE
  CALL mp_bcast(ios,ionode_id,intra_image_comm)
  CALL errore ('elph_tetra_gamma', 'opening file '//filelph, ABS (ios) )
  !
  IF (ionode) THEN
     WRITE (iuelph, '(3f15.8,i8)') xq, 3 * nat
     WRITE (iuelph, '(6e14.6)') (w2 (nu) , nu = 1, 3 * nat)
  ENDIF
  WRITE (stdout, *)
  WRITE (stdout, 9000)
  WRITE (stdout, 9005) SUM(dosef(1:2)), ef * rytoev
  WRITE (stdout, 9006) phase_space
  !
  IF (ionode) THEN
     WRITE (iuelph, 9000)
     WRITE (iuelph, 9005) SUM(dosef(1:2)), ef * rytoev
  ENDIF
  !
  DO nu = 1, 3 * nat
     !
     gamma = lambda(nu) * pi * w2(nu) * SUM(dosef(1:2))
     !
     WRITE (stdout, 9010) nu, lambda(nu), gamma * ry_to_gHz
     IF (ionode) WRITE (iuelph, 9010) nu, lambda(nu), gamma * ry_to_gHz
     IF (qplot) gamma_disp(nu,1,current_iq) = gamma * ry_to_gHz
     !
  END DO
  !
9000 FORMAT(5x,'Tetrahedron method')
9005 FORMAT(5x,'DOS =',f10.6,' states/spin/Ry/Unit Cell at Ef=', &
          &       f10.6,' eV')
9006 FORMAT(5x,'double delta at Ef =',f10.6)
9010 FORMAT(5x,'lambda(',i5,')=',f8.4,'   gamma=',f8.2,' GHz')
  !
  IF (ionode) CLOSE (unit = iuelph)
  !
  !    Prepare interface to q2r and matdyn
  !
  elph_dir='elph_dir/'
  IF (ionode) INQUIRE(file=TRIM(elph_dir), EXIST=exst)
  CALL mp_bcast(exst, ionode_id, intra_image_comm) 
  IF (.NOT.exst) CALL create_directory( elph_dir )
  !
  call star_q (xq, at, bg, nsym, s, invs, nq, sxq, isq, imq, .TRUE. )
  !
  DO isig = 1, el_ph_nsigma !=nsig in elphsum
     filelph = TRIM(elph_dir)//'a2Fq2r.'// TRIM(int_to_char(50 + isig)) &
                                  //'.'//TRIM(int_to_char(current_iq))
     IF (ionode) THEN
        iuelph = find_free_unit()
        OPEN(iuelph, file=filelph, STATUS = 'unknown', FORM = 'formatted', &
                     iostat=ios)
     ELSE
        !
        ! this node doesn't write: unit 6 is redirected to /dev/null
        !
        iuelph =6
     END IF
     CALL mp_bcast(ios, ionode_id, intra_image_comm)
     IF (ios /= 0) CALL errore('elph_tetra_lambda','opening output file '// TRIM(filelph),1)
     DO ipert = 1, 3 * nat
        DO jpert = 1, 3 * nat
           dyn22(jpert,ipert) = 2.0_dp * SUM(dosef(1:2)) &
           &  * amu_ry**2 * amass(ityp((ipert+2)/3)) * amass(ityp((jpert+2)/3)) &
           &  * SUM(lambda(1:3*nat) * w2(1:3*nat) * dyn(jpert, 1:3*nat) * CONJG(dyn(ipert, 1:3*nat)))
        END DO
     END DO
     WRITE(iuelph,*) 0.0_dp, ef, SUM(dosef(1:2))
     IF ( imq == 0 ) THEN
        write(iuelph,*) 2*nq
     ELSE
        write(iuelph,*) nq
     ENDIF
     xmldyn_save=xmldyn
     xmldyn=.FALSE.
     CALL q2qstar_ph (dyn22, at, bg, nat, nsym, s, invs, &
          irt, rtau, nq, sxq, isq, imq, iuelph)
     xmldyn=xmldyn_save
     IF (ionode) CLOSE( UNIT = iuelph, STATUS = 'KEEP' )
  END DO
  !
  DEALLOCATE(wght, et_col)
  !
END SUBROUTINE elph_tetra_gamma
!
!-----------------------------------------------------------------------
SUBROUTINE elph_tetra_step1(nbnd_fs,iq,tfst,tlst,et_col,wght)
  !---------------------------------------------------------------------
  !
  ! This routine computed the weight for the double-delta function.
  !
  USE kinds, ONLY : dp
  USE mp, ONLY : mp_sum
  USE mp_images, ONLY : intra_image_comm
  USE ions_base, ONLY : nat
  USE el_phon, ONLY : elph_nbnd_min
  USE ener,   ONLY : ef
  USE wvfct, ONLY: nbnd
  USE klist,  ONLY: nkstot
  USE lsda_mod,   ONLY : nspin
  USE ktetra, ONLY : ntetra, tetra, nntetra, wlsm
  !
  INTEGER,INTENT(IN) :: nbnd_fs, iq, tfst, tlst
  REAL(dp),INTENT(IN) :: et_col(nbnd, nkstot)
  REAL(dp),INTENT(OUT) :: wght(3 * nat, nbnd_fs, nbnd_fs, nkstot)
  !
  INTEGER :: nt, nspin_lsda, ns, nk, ibnd, ii, jj, itetra(4), ik
  REAL(dp) :: e(4), a(4,4), tsmall(4,4), V, thr = 1e-10_dp, ei0(4,nbnd_fs), ej0(4,nbnd_fs), &
  &           ei1(4), ej1(4,nbnd_fs), w0(3*nat,nbnd_fs,nbnd_fs,4), w1(3*nat,nbnd_fs,4)
  !
  wght(1:3 * nat,1:nbnd_fs,1:nbnd_fs,1:nkstot) = 0.0_dp
  !
  IF ( nspin == 2 ) THEN
     nspin_lsda = 2
  ELSE
     nspin_lsda = 1
  END IF
  !
  DO ns = 1, nspin_lsda
     !
     ! nk is used to select k-points with up (ns=1) or down (ns=2) spin
     !
     IF (ns == 1) THEN
        nk = 0
     ELSE
        nk = nkstot / 2
     END IF
     !
     DO nt = tfst, tlst
        !
        ei0(1:4, 1:nbnd_fs) = 0.0_dp
        ej0(1:4, 1:nbnd_fs) = 0.0_dp
        DO ii = 1, nntetra
           !
           ik = tetra(ii, nt) + nk
           DO ibnd = 1, nbnd_fs
              ei0(1:4, ibnd) = ei0(1:4, ibnd) + wlsm(1:4,ii) * (et_col(ibnd + elph_nbnd_min - 1, ik)    - ef)
              ej0(1:4, ibnd) = ej0(1:4, ibnd) + wlsm(1:4,ii) * (et_col(ibnd + elph_nbnd_min - 1, ik+iq) - ef)
           END DO
           !
        END DO
        !
        w0(1:3 * nat,1:nbnd_fs,1:nbnd_fs,1:4) = 0.0_dp
        !
        DO ibnd = 1, nbnd_fs
           !
           itetra(1) = 0
           e(1:4) = ei0(1:4, ibnd)
           call hpsort (4, e, itetra)
           !
           DO ii = 1, 4
              a(1:4,ii) = (0.0_dp - e(ii) ) / (e(1:4) - e(ii) )
           END DO
           !
           IF( e(1) <= 0.0_dp .AND. 0.0_dp < e(2) ) THEN
              !
              ! A - 1
              !
              V = a(2,1) * a(3,1) * a(4,1)
              !
              IF(V > thr) THEN
                 !
                 tsmall(1, 1:4) = (/1.0_dp, 0.0_dp, 0.0_dp, 0.0_dp/)
                 tsmall(2, 1:4) = (/a(1,2), a(2,1), 0.0_dp, 0.0_dp/)
                 tsmall(3, 1:4) = (/a(1,3), 0.0_dp, a(3,1), 0.0_dp/)
                 tsmall(4, 1:4) = (/a(1,4), 0.0_dp, 0.0_dp, a(4,1)/)
                 !
                 ei1(1:4) = MATMUL(tsmall(1:4,1:4), e(1:4))
                 ej1(1:4,1:nbnd_fs) = MATMUL(tsmall(1:4,1:4), ej0(itetra(1:4), 1:nbnd_fs))
                 !
                 CALL elph_tetra_step2(nbnd_fs,ei1,ej1,w1)
                 !
                 DO ii = 1, 3 * nat
                    w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) = w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) &
                    &           + V * MATMUL(w1(ii,1:nbnd_fs,1:4), tsmall(1:4,1:4))
                 END DO
                 !
              END IF
              !
           ELSE IF( e(2) <= 0.0_dp .AND. 0.0_dp < e(3)) THEN
              !
              ! B - 1
              !
              V = a(3,1) * a(4,1) * a(2,4)
              !
              IF(V > thr) THEN
                 !
                 tsmall(1, 1:4) = (/1.0_dp, 0.0_dp, 0.0_dp, 0.0_dp/)
                 tsmall(2, 1:4) = (/a(1,3), 0.0_dp, a(3,1), 0.0_dp/)
                 tsmall(3, 1:4) = (/a(1,4), 0.0_dp, 0.0_dp, a(4,1)/)
                 tsmall(4, 1:4) = (/0.0_dp, a(2,4), 0.0_dp, a(4,2)/)
                 !
                 ei1(1:4) = MATMUL(tsmall(1:4,1:4), e(1:4))
                 ej1(1:4,1:nbnd_fs) = MATMUL(tsmall(1:4,1:4), ej0(itetra(1:4), 1:nbnd_fs))
                 !
                 CALL elph_tetra_step2(nbnd_fs,ei1,ej1,w1)
                 !
                 DO ii = 1, 3 * nat
                    w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) = w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) &
                    &           + V * MATMUL(w1(ii,1:nbnd_fs,1:4), tsmall(1:4,1:4))
                 END DO
                 !
              END IF
              !
              ! B - 2
              !
              V = a(3,2) * a(4,2)
              !
              IF(V > thr) THEN
                 !
                 tsmall(1, 1:4) = (/1.0_dp, 0.0_dp, 0.0_dp, 0.0_dp/)
                 tsmall(2, 1:4) = (/0.0_dp, 1.0_dp, 0.0_dp, 0.0_dp/)
                 tsmall(3, 1:4) = (/0.0_dp, a(2,3), a(3,2), 0.0_dp/)
                 tsmall(4, 1:4) = (/0.0_dp, a(2,4), 0.0_dp, a(4,2)/)
                 !
                 ei1(1:4) = MATMUL(tsmall(1:4,1:4), e(1:4))
                 ej1(1:4,1:nbnd_fs) = MATMUL(tsmall(1:4,1:4), ej0(itetra(1:4), 1:nbnd_fs))
                 !
                 CALL elph_tetra_step2(nbnd_fs,ei1,ej1,w1)
                 !
                 DO ii = 1, 3 * nat
                    w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) = w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) &
                    &           + V * MATMUL(w1(ii,1:nbnd_fs,1:4), tsmall(1:4,1:4))
                 END DO
                 !
              END IF
              !
              ! B - 3
              !
              V = a(2,3) * a(3,1) * a(4,2)
              !
              IF(V > thr) THEN
                 !
                 tsmall(1, 1:4) = (/1.0_dp, 0.0_dp, 0.0_dp, 0.0_dp/)
                 tsmall(2, 1:4) = (/a(1,3), 0.0_dp, a(3,1), 0.0_dp/)
                 tsmall(3, 1:4) = (/0.0_dp, a(2,3), a(3,2), 0.0_dp/)
                 tsmall(4, 1:4) = (/0.0_dp, a(2,4), 0.0_dp, a(4,2)/)
                 !
                 ei1(1:4) = MATMUL(tsmall(1:4,1:4), e(1:4))
                 ej1(1:4,1:nbnd_fs) = MATMUL(tsmall(1:4,1:4), ej0(itetra(1:4), 1:nbnd_fs))
                 !
                 CALL elph_tetra_step2(nbnd_fs,ei1,ej1,w1)
                 !
                 DO ii = 1, 3 * nat
                    w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) = w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) &
                    &           + V * MATMUL(w1(ii,1:nbnd_fs,1:4), tsmall(1:4,1:4))
                 END DO
                 !
              END IF
              !
           ELSE IF( e(3) <= 0.0_dp .AND. 0.0_dp < e(4)) THEN
              !
              ! C - 1
              !
              V = a(4,3)
              !
              IF(V > thr) THEN
                 !
                 tsmall(1, 1:4) = (/1.0_dp, 0.0_dp, 0.0_dp, 0.0_dp/)
                 tsmall(2, 1:4) = (/0.0_dp, 1.0_dp, 0.0_dp, 0.0_dp/)
                 tsmall(3, 1:4) = (/0.0_dp, 0.0_dp, 1.0_dp, 0.0_dp/)
                 tsmall(4, 1:4) = (/0.0_dp, 0.0_dp, a(3,4), a(4,3)/)
                 !
                 ei1(1:4) = MATMUL(tsmall(1:4,1:4), e(1:4))
                 ej1(1:4,1:nbnd_fs) = MATMUL(tsmall(1:4,1:4), ej0(itetra(1:4), 1:nbnd_fs))
                 !
                 CALL elph_tetra_step2(nbnd_fs,ei1,ej1,w1)
                 !
                 DO ii = 1, 3 * nat
                    w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) = w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) &
                    &           + V * MATMUL(w1(ii,1:nbnd_fs,1:4), tsmall(1:4,1:4))
                 END DO
                 !
              END IF
              !
              ! C - 2
              !
              V = a(3,4) * a(4,2)
              !
              IF(V > thr) THEN
                 !
                 tsmall(1, 1:4) = (/1.0_dp, 0.0_dp, 0.0_dp, 0.0_dp/)
                 tsmall(2, 1:4) = (/0.0_dp, 1.0_dp, 0.0_dp, 0.0_dp/)
                 tsmall(3, 1:4) = (/0.0_dp, a(2,4), 0.0_dp, a(4,2)/)
                 tsmall(4, 1:4) = (/0.0_dp, 0.0_dp, a(3,4), a(4,3)/)
                 !
                 ei1(1:4) = MATMUL(tsmall(1:4,1:4), e(1:4))
                 ej1(1:4,1:nbnd_fs) = MATMUL(tsmall(1:4,1:4), ej0(itetra(1:4), 1:nbnd_fs))
                 !
                 CALL elph_tetra_step2(nbnd_fs,ei1,ej1,w1)
                 !
                 DO ii = 1, 3 * nat
                    w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) = w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) &
                    &           + V * MATMUL(w1(ii,1:nbnd_fs,1:4), tsmall(1:4,1:4))
                 END DO
                 !
              END IF
              !
              ! C - 3
              !
              V = a(3,4) * a(2,4) * a(4,1)
              !
              IF(V > thr) THEN
                 !
                 tsmall(1, 1:4) = (/1.0_dp, 0.0_dp, 0.0_dp, 0.0_dp/)
                 tsmall(2, 1:4) = (/a(1,4), 0.0_dp, 0.0_dp, a(4,1)/)
                 tsmall(3, 1:4) = (/0.0_dp, a(2,4), 0.0_dp, a(4,2)/)
                 tsmall(4, 1:4) = (/0.0_dp, 0.0_dp, a(3,4), a(4,3)/)
                 !
                 ei1(1:4) = MATMUL(tsmall(1:4,1:4), e(1:4))
                 ej1(1:4,1:nbnd_fs) = MATMUL(tsmall(1:4,1:4), ej0(itetra(1:4), 1:nbnd_fs))
                 !
                 CALL elph_tetra_step2(nbnd_fs,ei1,ej1,w1)
                 !
                 DO ii = 1, 3 * nat
                    w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) = w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) &
                    &           + V * MATMUL(w1(ii,1:nbnd_fs,1:4), tsmall(1:4,1:4))
                 END DO
                 !
              END IF
              !
           ELSE IF( e(4) <= 0.0_dp ) THEN
              !
              ! D - 1
              !
              ei1(1:4) = MATMUL(tsmall(1:4,1:4), e(1:4))
              ej1(1:4,1:nbnd_fs) = MATMUL(tsmall(1:4,1:4), ej0(itetra(1:4), 1:nbnd_fs))
              !
              CALL elph_tetra_step2(nbnd_fs,ei1,ej1,w1)
              !
              DO ii = 1, 3 * nat
                 w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) = w0(ii,1:nbnd_fs,ibnd,itetra(1:4)) &
                 &           + MATMUL(w1(ii,1:nbnd_fs,1:4), tsmall(1:4,1:4))
              END DO
              !
           END IF
           !
        END DO ! ibnd
        !
        DO ii = 1, nntetra
           !
           ik = tetra(ii, nt) + nk
           !
           DO jj = 1, 4
              wght(1:3 * nat,1:nbnd_fs,1:nbnd_fs,ik) = wght(1:3 * nat,1:nbnd_fs,1:nbnd_fs,ik) &
              &           + wlsm(jj,ii) * w0(1:3 * nat,1:nbnd_fs,1:nbnd_fs,jj)
           END DO
           !
        END DO ! ii
        !
     END DO ! nt
     !
  END DO ! ns
  !
  wght(1:3 * nat,1:nbnd_fs,1:nbnd_fs,1:nkstot) = wght(1:3 * nat,1:nbnd_fs,1:nbnd_fs,1:nkstot) / REAL(ntetra, dp)
  IF(nspin == 1) wght(1:3 * nat,1:nbnd_fs,1:nbnd_fs,1:nkstot) = wght(1:3 * nat,1:nbnd_fs,1:nbnd_fs,1:nkstot) * 2.0_dp
  !
  CALL mp_sum(wght, intra_image_comm)
  !
END SUBROUTINE elph_tetra_step1
!
!------------------------------------------------------------------------------------------------
SUBROUTINE elph_tetra_step2(nbnd_fs,ei0,ej0,w)
  !------------------------------------------------------------------------------------------------
  !
  ! This routine compute the second step function in the gamma
  !
  USE kinds, ONLY : dp
  USE ions_base, ONLY : nat
  !
  INTEGER,INTENT(IN) :: nbnd_fs
  REAL(dp),INTENT(IN) :: ei0(4), ej0(4,nbnd_fs)
  REAL(dp),INTENT(OUT) :: w(3*nat,nbnd_fs,4)
  !
  INTEGER :: ibnd, itetra(4), ii
  REAL(dp) :: e(4), a(4,4), de(4), w1(3*nat,4), tsmall(4,4), V, thr = 1e-8_dp
  !
  w(1:3*nat,1:nbnd_fs,1:4) = 0.0_dp
  !
  DO ibnd = 1, nbnd_fs
     !
     e(1:4) = ej0(1:4,ibnd)
     itetra(1) = 0
     call hpsort (4, e, itetra)
     !
     DO ii = 1, 4
        a(1:4,ii) = (0.0_dp - e(ii) ) / (e(1:4) - e(ii))
     END DO
     !
     IF(0.0_dp <= e(1)) THEN
        !
        ! A - 1
        !
        de(1:4) = e(1:4) - ei0(itetra(1:4))
        !
        CALL elph_tetra_delta3(nbnd_fs,de,w1)
        !
        w(1:3*nat,ibnd,itetra(1:4)) = w(1:3*nat,ibnd,itetra(1:4)) + w1(1:3*nat,1:4)
        !
     ELSE IF((e(1) < 0.0_dp .AND. 0.0_dp <= e(2)) .OR. (e(1) <= 0.0_dp .AND. 0.0_dp < e(2))) THEN
        !
        ! B - 1
        !
        V = a(1,2)
        !
        IF(V > thr) THEN
           !
           tsmall(1, 1:4) = (/a(1,2), a(2,1), 0.0_dp, 0.0_dp/)
           tsmall(2, 1:4) = (/0.0_dp, 1.0_dp, 0.0_dp, 0.0_dp/)
           tsmall(3, 1:4) = (/0.0_dp, 0.0_dp, 1.0_dp, 0.0_dp/)
           tsmall(4, 1:4) = (/0.0_dp, 0.0_dp, 0.0_dp, 1.0_dp/)
           !
           de(1:4) = MATMUL(tsmall(1:4,1:4), e(1:4) - ei0(itetra(1:4)))
           !
           CALL elph_tetra_delta3(nbnd_fs,de,w1)
           !
           w(1:3*nat,ibnd,itetra(1:4)) = w(1:3*nat,ibnd,itetra(1:4)) &
           &                   + V * MATMUL(w1(1:3*nat,1:4), tsmall(1:4,1:4))
           !       
        END IF
        !
        ! B - 2
        !
        V = a(1,3) * a(2,1)
        !
        IF(V > thr) THEN
           !
           tsmall(1, 1:4) = (/a(1,2), a(2,1), 0.0_dp, 0.0_dp/)
           tsmall(2, 1:4) = (/a(1,3), 0.0_dp, a(3,1), 0.0_dp/)
           tsmall(3, 1:4) = (/0.0_dp, 0.0_dp, 1.0_dp, 0.0_dp/)
           tsmall(4, 1:4) = (/0.0_dp, 0.0_dp, 0.0_dp, 1.0_dp/)
           !
           de(1:4) = MATMUL(tsmall(1:4,1:4), e(1:4) - ei0(itetra(1:4)))
           !
           CALL elph_tetra_delta3(nbnd_fs,de,w1)
           !
           w(1:3*nat,ibnd,itetra(1:4)) = w(1:3*nat,ibnd,itetra(1:4)) &
           &                   + V * MATMUL(w1(1:3*nat,1:4), tsmall(1:4,1:4))
           !
        END IF
        !
        ! B - 3
        !
        V = a(1,4) * a(2,1) * a(3,1)
        !
        IF(V > thr) THEN
           !
           tsmall(1, 1:4) = (/a(1,2), a(2,1), 0.0_dp, 0.0_dp/)
           tsmall(2, 1:4) = (/a(1,3), 0.0_dp, a(3,1), 0.0_dp/)
           tsmall(3, 1:4) = (/a(1,4), 0.0_dp, 0.0_dp, a(4,1)/)
           tsmall(4, 1:4) = (/0.0_dp, 0.0_dp, 0.0_dp, 1.0_dp/)
           !
           de(1:4) = MATMUL(tsmall(1:4,1:4), e(1:4) - ei0(itetra(1:4)))
           !
           CALL elph_tetra_delta3(nbnd_fs,de,w1)
           !
           w(1:3*nat,ibnd,itetra(1:4)) = w(1:3*nat,ibnd,itetra(1:4)) &
           &                   + V * MATMUL(w1(1:3*nat,1:4), tsmall(1:4,1:4))
           !       
        END IF
        !          
     ELSE IF((e(2) < 0.0_dp .AND. 0.0_dp <= e(3)) .OR. (e(2) <= 0.0_dp .AND. 0.0_dp < e(3))) THEN
        !          
        ! C - 1
        !
        V = a(2,4) * a(1,4) * a(3,1)
        !
        IF(V > thr) THEN
           !
           tsmall(1, 1:4) = (/a(1,3), 0.0_dp, a(3,1), 0.0_dp/)
           tsmall(2, 1:4) = (/a(1,4), 0.0_dp, 0.0_dp, a(4,1)/)
           tsmall(3, 1:4) = (/0.0_dp, a(2,4), 0.0_dp, a(4,2)/)
           tsmall(4, 1:4) = (/0.0_dp, 0.0_dp, 0.0_dp, 1.0_dp/)
           !
           de(1:4) = MATMUL(tsmall(1:4,1:4), e(1:4) - ei0(itetra(1:4)))
           !
           CALL elph_tetra_delta3(nbnd_fs,de,w1)
           !
           w(1:3*nat,ibnd,itetra(1:4)) = w(1:3*nat,ibnd,itetra(1:4)) &
           &                   + V * MATMUL(w1(1:3*nat,1:4), tsmall(1:4,1:4))
           !      
        END IF
        !
        ! C - 2
        !
        V = a(1,3) * a(2,3)
        !
        IF(V > thr) THEN
           !
           tsmall(1, 1:4) = (/a(1,3), 0.0_dp, a(3,1), 0.0_dp/)
           tsmall(2, 1:4) = (/0.0_dp, a(2,3), a(3,2), 0.0_dp/)
           tsmall(3, 1:4) = (/0.0_dp, 0.0_dp, 1.0_dp, 0.0_dp/)
           tsmall(4, 1:4) = (/0.0_dp, 0.0_dp, 0.0_dp, 1.0_dp/)
           !
           de(1:4) = MATMUL(tsmall(1:4,1:4), e(1:4) - ei0(itetra(1:4)))
           !
           CALL elph_tetra_delta3(nbnd_fs,de,w1)
           !
           w(1:3*nat,ibnd,itetra(1:4)) = w(1:3*nat,ibnd,itetra(1:4)) &
           &                   + V * MATMUL(w1(1:3*nat,1:4), tsmall(1:4,1:4))
           !
        END IF
        !
        ! C - 3
        ! 
        V = a(1,3) * a(2,4) * a(3,2)
        !
        IF(V > thr) THEN
           !
           tsmall(1, 1:4) = (/a(1,3), 0.0_dp, a(3,1), 0.0_dp/)
           tsmall(2, 1:4) = (/0.0_dp, a(2,3), a(3,2), 0.0_dp/)
           tsmall(3, 1:4) = (/0.0_dp, a(2,4), 0.0_dp, a(4,2)/)
           tsmall(4, 1:4) = (/0.0_dp, 0.0_dp, 0.0_dp, 1.0_dp/)
           !
           de(1:4) = MATMUL(tsmall(1:4,1:4), e(1:4) - ei0(itetra(1:4)))
           !
           CALL elph_tetra_delta3(nbnd_fs,de,w1)
           !
           w(1:3*nat,ibnd,itetra(1:4)) = w(1:3*nat,ibnd,itetra(1:4)) &
           &                   + V * MATMUL(w1(1:3*nat,1:4), tsmall(1:4,1:4))
           !
        END IF
        !          
     ELSE IF((e(3) < 0.0_dp .AND. 0.0_dp <= e(4)) .OR. (e(3) <= 0.0_dp .AND. 0.0_dp < e(4))) THEN
        !
        ! D - 1
        !
        V = a(3,4) * a(2,4) * a(1,4) 
        !          
        IF(V > thr) THEN
           !
           tsmall(1, 1:4) = (/a(1,4), 0.0_dp, 0.0_dp, a(4,1)/)
           tsmall(2, 1:4) = (/0.0_dp, a(2,4), 0.0_dp, a(4,2)/)
           tsmall(3, 1:4) = (/0.0_dp, 0.0_dp, a(3,4), a(4,3)/)
           tsmall(4, 1:4) = (/0.0_dp, 0.0_dp, 0.0_dp, 1.0_dp/)
           !
           de(1:4) = MATMUL(tsmall(1:4,1:4), e(1:4) - ei0(itetra(1:4)))
           !
           CALL elph_tetra_delta3(nbnd_fs,de,w1)
           !
           w(1:3*nat,ibnd,itetra(1:4)) = w(1:3*nat,ibnd,itetra(1:4)) &
           &                   + V * MATMUL(w1(1:3*nat,1:4), tsmall(1:4,1:4))
           !        
        END IF
        !
     END IF
     !
  END DO
  !
END SUBROUTINE elph_tetra_step2
!
!-------------------------------------------------------------------------------------------
SUBROUTINE elph_tetra_delta3(nbnd_fs,de,w)
  !-------------------------------------------------------------------------------------------
  !
  USE ions_base, ONLY : nat
  USE dynmat, ONLY : w2
  USE kinds, ONLY : dp
  !
  INTEGER,INTENT(IN) :: nbnd_fs
  REAL(dp),INTENT(IN) :: de(4)
  REAL(dp),INTENT(INOUT) :: w(3 * nat,4)
  !
  INTEGER :: nu, ii, itetra(4)
  REAL(dp) :: a(4,4), e(4), V, e0(3 * nat)
  !
  e0(1:3 * nat) = SQRT(ABS(w2(1:3 * nat)))
  !
  e(1:4) = de(1:4)
  itetra(1) = 0
  call hpsort (4, e, itetra)
  !
  w(1:3*nat,1:4) = 0.0_dp
  !
  DO nu = 1, 3 * nat
     !
     DO ii = 1, 4
        a(1:4,ii) = (e0(nu) - e(ii)) / (e(1:4) - e(ii))
     END DO
     !
     IF(e(1) < e0(nu) .AND. e0(nu) <= e(2)) THEN
        !
        V = a(2,1) * a(3,1) * a(4,1) / (e0(nu) - e(1) )
        w(nu,itetra(1)) = a(1,2) + a(1,3) + a(1,4)
        w(nu,itetra(2:4)) = a(2:4,1)
        w(nu,1:4) = w(nu,1:4) * V
        !
     ELSE IF(e(2) < e0(nu) .AND. e0(nu) <= e(3)) THEN
        !
        V = a(2,3) * a(3,1) + a(3,2) * a(2,4)
        w(nu,itetra(1)) = a(1,4) * V + a(1,3) * a(3,1) * a(2,3)
        w(nu,itetra(2)) = a(2,3) * V + a(2,4) * a(2,4) * a(3,2)
        w(nu,itetra(3)) = a(3,2) * V + a(3,1) * a(3,1) * a(2,3)
        w(nu,itetra(4)) = a(4,1) * V + a(4,2) * a(2,4) * a(3,2)
        V  = 1.0_dp / ( e(4) - e(1) )
        w(nu,1:4) = w(nu,1:4) * V
        !
     ELSE IF(e(3) < e0(nu) .AND. e0(nu) < e(4)) THEN
        !
        V = a(1,4) * a(2,4) * a(3,4) / ( e(4) - e0(nu) )
        w(nu,itetra(1:3))  = a(1:3,4)
        w(nu,itetra(4))  = a(4,1) + a(4,2) + a(4,3)
        w(nu,1:4) = w(nu,1:4) * V
        !
     END IF
     !
  END DO ! nu
  !
END SUBROUTINE elph_tetra_delta3
!
!--------------------------------------------------------------------------
SUBROUTINE elph_tetra_average_weight(nmode,nbnd_fs,wght)
  !--------------------------------------------------------------------------
  !
  ! Average weights of degenerated states
  !
  USE kinds, ONLY : dp
  USE wvfct, ONLY : et
  USE klist, ONLY : nks
  USE qpoint,ONLY : nksq, ikks, ikqs
  USE el_phon, ONLY : elph_nbnd_min
  !
  IMPLICIT NONE
  !
  INTEGER,INTENT(IN) :: nmode, nbnd_fs
  REAL(dp),INTENT(INOUT) :: wght(nmode,nbnd_fs,nbnd_fs,nks)
  !
  INTEGER :: ibnd, jbnd, kbnd, ik
  REAL(dp) :: wght2(nmode,nbnd_fs)
  !
  DO ik = 1, nksq
     !
     DO ibnd = 1, nbnd_fs
        !
        wght2(1:nmode,1:nbnd_fs) = wght(1:nmode,1:nbnd_fs,ibnd,ikks(ik))
        !
        DO jbnd = ibnd + 1, nbnd_fs
           !
           IF(ABS(et(ibnd - 1 + elph_nbnd_min,ikks(ik)) - et(jbnd - 1 + elph_nbnd_min,ikks(ik))) < 1e-6_dp) THEN
              wght2(1:nmode,1:nbnd_fs) = wght2(1:nmode,1:nbnd_fs) + wght(1:nmode,1:nbnd_fs,jbnd,ikks(ik))
           ELSE
              !
              DO kbnd = ibnd, jbnd - 1
                 wght(1:nmode,1:nbnd_fs,kbnd,ikks(ik)) = wght2(1:nmode,1:nbnd_fs) / real(jbnd - ibnd, dp)
              END DO
              !
              EXIT
           END IF
           !
        END DO
        !
        wght2(1:nmode,1:nbnd_fs) = wght(1:nmode,ibnd,1:nbnd_fs,ikks(ik))
        !
        DO jbnd = ibnd + 1, nbnd_fs
           !
           IF(ABS(et(ibnd - 1 + elph_nbnd_min,ikqs(ik)) - et(jbnd - 1 + elph_nbnd_min,ikqs(ik))) < 1e-6_dp) THEN
              wght2(1:nmode,1:nbnd_fs) = wght2(1:nmode,1:nbnd_fs) + wght(1:nmode,jbnd,1:nbnd_fs,ikks(ik))
           ELSE
              !
              DO kbnd = ibnd, jbnd - 1
                 wght(1:nmode,kbnd,1:nbnd_fs,ikks(ik)) = wght2(1:nmode,1:nbnd_fs) / real(jbnd - ibnd, dp)
              END DO
              !
              EXIT
           END IF
           !
        END DO
        !
     END DO
  END DO
  !
END SUBROUTINE elph_tetra_average_weight
!
END MODULE elph_tetra_mod
