Easy answer first: I'm sorry for the formatted code. I've copy/pasted
directly from the VSCode and it went like this. It was not on purpose, just
a lack of attention to detail.

Now regarding the irreps, notice that you are describing the characters of
the representations, and not the matrices. I agree that if all we want is
to identify the irreps that describe each band, it is sufficient to look at
the characters / trace, and that's what the sym_band.f90 routine already
does.

These traces are invariant under unitary transformations (change of basis),
but the full matrix representation DΓ(S) for S in G is not. In other words,
let's call A a 2x2 matrix representation of the C3(z) operator under a
certain basis set {ψ0, ψ1}, which transforms as some irrep Γ. If U is an
unitary transformation that gives a new basis (within the same subspace)
denoted {ϕ1, ϕ2} = U ⋅ {ψ0, ψ1}, then under this new basis the matrix
representation of C3(z) becomes B = U.A.U†, which is also a rep of the same
irrep Γ, same traces.

I need the full matrices DΓ(S), and not just the characters / trace,
because I need to make sure that numerical wave-functions from QE match the
representations I'll use later in a separate python code. Is it clear now?
So I'm editing this routine to get what I need.

Regarding the bug, don't worry. One of the QE devs has already replied to
me. It is indeed a bug in the D_3h classes that was unnoticed because both
s_v and s_h classes have characters  equal to zero in the double group, so
it does not affect the identification of the irreps. I'll try some
suggestions he sent me to fix this.

But if you want to reproduce this, simply run bands.x for graphene (full
relativistic) or any other D_3h material and use the sym_band.f90 file
attached here. But notice that in this code I'm printing a bunch of stuff
to stdout for testing purposes. The relevant section for this bug is
between lines 870--876.

Best,
--
Gerson J. Ferreira
Prof. Dr. @ InFis - UFU
----------------------------------------------
gjferreira.wordpress.com
Institute of Physics
Federal University of Uberlândia, Brazil
----------------------------------------------


On Mon, Mar 7, 2022 at 12:14 AM Hongyi Zhao <hongyi.z...@gmail.com> wrote:

> On Mon, Mar 7, 2022 at 10:00 AM Gerson J. Ferreira
> <gersonjferre...@ufu.br> wrote:
> >
> > Thanks for the answer and the links. But if I understand correctly,
> these codes only give us the irreps, and I need the specific representation
> matrices calculated from the QE wave-functions. The best way to get these
> seem to be editing this routine.
>
> Let us discuss this in more detail. An irreps is short for irreducible
> representation [1], which is a component of a character table [2]: a
> two-dimensional table whose rows correspond to irreducible
> representations. The specific representation matrices calculated from
> the QE wave-functions should also can be derived from the character
> table.
>
> So, I still don't quite understand what you mean above. Any more
> hints/explanations/comments will be greatly appreciated.
>
> [1] https://en.wikipedia.org/wiki/Irreducible_representation
> [2] https://en.wikipedia.org/wiki/Character_table
>
> > I've found my mistake, and a bug (I'll report for the developers as
> well). My mistake was that I was not using the "which_irr_so(iclass)" to
> identify the class. I was assuming that "iclass" would already list the
> classes in the correct order.
> >
> > Now, the bug is that "which_ir_so" is returning the class 9 two times
> here, but one of these should be 6 instead. This can be checked with the
> following code
> >
> > PRINT *, "======================================================"
> > PRINT *, "which_ir_so:", (which_irr_so(iclass), iclass=1, nclass)
> > PRINT *, "classes:", (name_class_so(iclass), iclass=1, nclass)
> > DO irap=1,nrap
> > PRINT *, ">>", (char_mat_so(irap, which_irr_so(iclass)), iclass=1,
> nclass)
> > ENDDO
> > PRINT *, "======================================================"
>
> I want to know how you can make the above code display black
> background color in this email.
>
> > Which prints
> >
> > which_ir_so(iclass):           1           5           3           9
>        9           7           2           4           8
> > classes: E    -E   2C3  -2C3  3C2' s_h 2S3  -2S3  3s_v
> >
> > So, the classes are ordered as {E, 3C2', 2C3, 3s_v, 3s_v, 2S3, -E, -2C3,
> -2S3}
> >
> > Notice that 3s_v appears twice, and s_h does not appear in the list.
>
> What's your patched code? Could you please show the detailed steps to
> reproduce the above example?
>
> Best,
> Hongyi
>
>
!
! Copyright (C) 2006-2007 Quantum ESPRESSO group
! 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 .
!
!
!-----------------------------------------------------------------------
SUBROUTINE sym_band(filband, spin_component, firstk, lastk)
  !-----------------------------------------------------------------------
  !
  USE kinds,                ONLY : DP
  USE ions_base,            ONLY : nat, ityp, ntyp => nsp
  USE cell_base,            ONLY : at, bg, ibrav
  USE constants,            ONLY : rytoev
  USE fft_base,             ONLY : dfftp
  USE gvect,                ONLY : ngm, g
  USE lsda_mod,             ONLY : nspin
  USE wvfct,                ONLY : et, nbnd, npwx
  USE klist,                ONLY : xk, nks, nkstot, ngk, igk_k
  USE io_files,             ONLY : nwordwfc, iunwfc
  USE symm_base,            ONLY : s, nsym, ft, t_rev, invs, sname
  USE rap_point_group,      ONLY : code_group, nclass, nelem, elem, which_irr, &
       char_mat, name_rap, name_class, gname, ir_ram
  USE rap_point_group_so,   ONLY : nrap, nelem_so, elem_so, has_e, &
       which_irr_so, char_mat_so, name_rap_so, &
       name_class_so, d_spin, name_class_so1
  USE rap_point_group_is,   ONLY : nsym_is, sr_is, ft_is, gname_is, &
       sname_is, code_group_is
  USE uspp,                 ONLY : nkb, vkb
  USE noncollin_module,     ONLY : noncolin, domag
  USE wavefunctions, ONLY : evc
  USE io_global,            ONLY : ionode, ionode_id, stdout
  USE mp,                   ONLY : mp_bcast
  USE mp_images,            ONLY : intra_image_comm
  USE uspp_init,            ONLY : init_us_2
  !
  IMPLICIT NONE
  !
  INTEGER :: ik, i, j, irot, iclass, ig, ibnd
  INTEGER :: npw, spin_component, nks1, nks2, firstk, lastk
  INTEGER :: nks1tot, nks2tot
  INTEGER :: iunout, igroup, irap, dim_rap, ios
  INTEGER :: sk(3,3,48), gk(3,48), sk_is(3,3,48), &
       gk_is(3,48), invs_is(48), t_revk(48), invsk(48), nsymk, isym, ipol, jpol
  REAL(dp) :: ftk(3,48)
  LOGICAL :: is_complex, is_complex_so, is_symmorphic, search_sym
  LOGICAL, ALLOCATABLE :: high_symmetry(:)
  REAL(DP), PARAMETER :: accuracy=1.d-4
  COMPLEX(DP) :: d_spink(2,2,48), d_spin_is(2,2,48)
  COMPLEX(DP),ALLOCATABLE :: times(:,:,:)
  REAL(DP) :: dxk(3), dkmod, dkmod_save, modk1, modk2, k1(3), k2(3), ps
  INTEGER, ALLOCATABLE :: rap_et(:,:), code_group_k(:)
  INTEGER, ALLOCATABLE :: ngroup(:), istart(:,:)
  CHARACTER(len=11) :: group_name
  CHARACTER(len=45) :: snamek(48)
  CHARACTER (len=256) :: filband, namefile
  !
  IF (spin_component/=1.and.nspin/=2) &
       CALL errore('sym_band','incorrect spin_component',1)
  IF (spin_component<1.or.spin_component>2) &
       CALL errore('sym_band','incorrect lsda spin_component',1)

  ALLOCATE(rap_et(nbnd,nkstot))
  ALLOCATE(code_group_k(nkstot))
  ALLOCATE(times(nbnd,24,nkstot))
  ALLOCATE(ngroup(nkstot))
  ALLOCATE(istart(nbnd+1,nkstot))
  ALLOCATE(high_symmetry(nkstot))

  code_group_k=0
  rap_et=-1
  times=(0.0_DP,0.0_DP)
  CALL find_nks1nks2(firstk,lastk,nks1tot,nks1,nks2tot,nks2,spin_component)

  ios=0
  IF ( ionode ) THEN
     iunout=58
     namefile=trim(filband)//".rap"
     OPEN (unit = iunout, file = namefile, status = 'unknown', form = &
          'formatted', iostat = ios)
     REWIND (iunout)
  ENDIF

  CALL mp_bcast ( ios, ionode_id, intra_image_comm )
  IF ( ios /= 0) CALL errore ('sym_band', 'Opening filband file', abs (ios) )

  DO ik = nks1, nks2
     !
     npw = ngk(ik)
     CALL init_us_2 (npw, igk_k(1,ik), xk (1, ik), vkb)
     !
     !   read eigenfunctions
     !
     CALL davcio (evc, 2*nwordwfc, iunwfc, ik, - 1)
     !
     ! Find the small group of k
     !
     CALL smallgk (xk(1,ik), at, bg, s, ft, t_rev, sname, nsym, sk, &
          ftk, gk, t_revk, invsk, snamek, nsymk)
     !
     !  character of the irreducible representations
     !
     CALL find_info_group(nsymk,sk,t_revk,ftk,d_spink,gk,snamek,&
          sk_is,d_spin_is,gk_is,invs_is,is_symmorphic,search_sym)
     code_group_k(ik)=code_group
     !
     IF (.not.search_sym) THEN
        rap_et(:,ik)=-1
        GOTO 100
     ENDIF
     !
     !  Find the symmetry of each state
     !
     IF (noncolin) THEN
        IF (domag) THEN
           CALL find_band_sym_so(ik,evc,et(1,ik),nsym_is, &
                sk_is,ft_is,d_spin_is,gk_is,invs_is,&
                rap_et(1,ik),times(1,1,ik), &
                ngroup(ik),istart(1,ik),accuracy)
        ELSE
           CALL find_band_sym_so(ik,evc,et(1,ik),nsymk,sk,ftk,d_spink,&
                gk,invsk,rap_et(1,ik),times(1,1,ik),ngroup(ik),&
                istart(1,ik),accuracy)
        ENDIF
     ELSE
        CALL find_band_sym (ik,evc, et(1,ik), nsymk, sk, ftk, gk, invsk, &
             rap_et(1,ik), times(1,1,ik), ngroup(ik),&
             istart(1,ik),accuracy)
     ENDIF

100  CONTINUE
  ENDDO

#ifdef __MPI
  !
  !  Only the symmetry of a set of k points is calculated by this
  !  processor with pool. Here we collect the results into ionode
  !
  CALL ipoolrecover(code_group_k,1,nkstot,nks)
  CALL ipoolrecover(rap_et,nbnd,nkstot,nks)
  CALL poolrecover(times,2*24*nbnd,nkstot,nks)
  CALL ipoolrecover(ngroup,1,nkstot,nks)
  CALL ipoolrecover(istart,nbnd+1,nkstot,nks)
#endif
  IF (ionode) THEN
     high_symmetry = .FALSE.
     DO ik=nks1tot,nks2tot
        IF ( ik==nks1tot .OR. ik==nks2tot ) THEN
           high_symmetry(ik) = .TRUE.
        ELSE
           k1(:) = xk(:,ik) - xk(:,ik-1)
           k2(:) = xk(:,ik+1) - xk(:,ik)
           modk1=sqrt( k1(1)*k1(1) + k1(2)*k1(2) + k1(3)*k1(3) )
           modk2=sqrt( k2(1)*k2(1) + k2(2)*k2(2) + k2(3)*k2(3) )
           IF (modk1 <1.d-6 .OR. modk2 < 1.d-6) CYCLE
           ps = ( k1(1)*k2(1) + k1(2)*k2(2) + k1(3)*k2(3) ) / &
                modk1 / modk2
           high_symmetry(ik) = (ABS(ps-1.d0) >1.0d-4)
!
!  The gamma point is a high symmetry point
!
           IF (xk(1,ik)**2+xk(2,ik)**2+xk(3,ik)**2 < 1.0d-9) &
                             high_symmetry(ik)=.TRUE.
        END IF
     END DO
!
     DO ik=nks1tot, nks2tot
        CALL smallgk (xk(1,ik), at, bg, s, ft, t_rev, sname, &
             nsym, sk, ftk, gk, t_revk, invsk, snamek, nsymk)
        CALL find_info_group(nsymk,sk,t_revk,ftk,d_spink,gk,snamek,&
             sk_is,d_spin_is,gk_is,invs_is,is_symmorphic,search_sym)
        IF (code_group_k(ik) /= code_group) &
             CALL errore('sym_band','problem with code_group',1)
        WRITE(stdout, '(/,1x,74("*"))')
        WRITE(stdout, '(/,20x,"xk=(",2(f10.5,","),f10.5,"  )")') &
             xk(1,ik), xk(2,ik), xk(3,ik)
        IF (.not.search_sym) THEN
           WRITE(stdout,'(/,5x,"zone border point and non-symmorphic group ")')
           WRITE(stdout,'(5x,"symmetry decomposition not available")')
           WRITE(stdout, '(/,1x,74("*"))')
        ENDIF
        IF (ik == nks1tot) THEN
           WRITE (iunout, '(" &plot_rap nbnd_rap=",i4,", nks_rap=",i4," /")') &
                nbnd, nks2tot-nks1tot+1
           IF (search_sym) CALL write_group_info(.true.)
           dxk(:) = xk(:,nks1tot+1) - xk(:,nks1tot)
           dkmod_save = sqrt( dxk(1)**2 + dxk(2)**2 + dxk(3)**2 )
        ELSE
           IF (code_group_k(ik)/=code_group_k(ik-1).and.search_sym) &
                CALL write_group_info(.true.)
!
!    When the symmetry changes the point must be considered a high
!    symmetry point. If the previous point was also high_symmetry, there
!    are two possibilities. The two points are distant and in this case
!    both of them must be considered high symmetry. If they are close only
!    the first point is a high symmetry point. First compute the distance
!
           dxk(:) = xk(:,ik) - xk(:,ik-1)
           dkmod= sqrt( dxk(1)**2 + dxk(2)**2 + dxk(3)**2 )
           IF (dkmod < 1.D-6) THEN
              !
              !   In this case is_high_sym does not change because the point
              !   is the same
              high_symmetry(ik)=high_symmetry(ik-1)
              !
           ELSE IF (dkmod < 5.0_DP * dkmod_save) THEN
!
!    In this case the two points are considered close
!
              IF ( .NOT. high_symmetry(ik-1) ) &
                 high_symmetry(ik)= ((code_group_k(ik)/=code_group_k(ik-1)) &
                                   .OR. high_symmetry(ik) ) 
              IF (dkmod > 1.d-3) dkmod_save=dkmod
           ELSE
!
!    Points are distant. They are all high symmetry
!
              high_symmetry(ik) = .TRUE.
           ENDIF
        ENDIF
        WRITE (iunout, '(10x,3f10.6,l5)') xk(1,ik),xk(2,ik),xk(3,ik), &
             high_symmetry(ik)
        WRITE (iunout, '(10i8)') (rap_et(ibnd,ik), ibnd=1,nbnd)
        IF (.not.search_sym) CYCLE
        IF (noncolin) THEN
           IF (domag) THEN
              WRITE(stdout,'(/,5x,"Band symmetry, ",a11," [",a11, &
                   & "] magnetic double point group,")') gname, gname_is
              WRITE(stdout,'(5x,"using ",a11,/)') gname_is
           ELSE
              WRITE(stdout,'(/,5x,"Band symmetry, ",a11,&
                   & " double point group:",/)') gname
           ENDIF
        ELSE
           WRITE(stdout,'(/,5x,"Band symmetry, ",a11," point group:",/)') &
                group_name(code_group_k(ik))
        ENDIF

        DO igroup=1,ngroup(ik)
           dim_rap=istart(igroup+1,ik)-istart(igroup,ik)
           DO irap=1,nclass
              IF (noncolin) THEN
                 IF ((abs(nint(dble(times(igroup,irap,ik)))-  &
                      dble(times(igroup,irap,ik))) > accuracy).or. &
                      (abs(aimag(times(igroup,irap,ik))) > accuracy) ) THEN
                    WRITE(stdout,'(5x,"e(",i3," -",i3,") = ",f12.5,2x,&
                         &"eV",3x,i3,3x, "-->   ?")') &
                         istart(igroup,ik), istart(igroup+1,ik)-1, &
                         et(istart(igroup,ik),ik)*rytoev, dim_rap
                    exit
                 ELSEIF (abs(times(igroup,irap,ik)) > accuracy) THEN
                    IF (abs(nint(dble(times(igroup,irap,ik))-1.d0)) < &
                         accuracy) THEN
                       WRITE(stdout,'(5x, "e(",i3," -",i3,") = ",&
                            &f12.5,2x,"eV",3x,i3,3x,"--> ",a15)') &
                            istart(igroup,ik), istart(igroup+1,ik)-1, &
                            et(istart(igroup,ik),ik)*rytoev, &
                            dim_rap, name_rap_so(irap)
                    ELSE
                       WRITE(stdout,'(5x,"e(",i3," -",i3,") = ",&
                            &f12.5,2x,"eV",3x,i3,3x,"--> ",i3," ",a15)') &
                            istart(igroup,ik), istart(igroup+1,ik)-1, &
                            et(istart(igroup,ik),ik)*rytoev, dim_rap, &
                            nint(dble(times(igroup,irap,ik))), name_rap_so(irap)
                    ENDIF
                 ENDIF
              ELSE
                 IF ((abs(nint(dble(times(igroup,irap,ik)))-  &
                      dble(times(igroup,irap,ik))) > accuracy).or. &
                      (abs(aimag(times(igroup,irap,ik))) > accuracy) ) THEN
                    WRITE(stdout,'(5x,"e(",i3," -",i3,") = ",f12.5,2x,&
                         &"eV",3x,i3,3x, "-->   ?")') &
                         istart(igroup,ik), istart(igroup+1,ik)-1, &
                         et(istart(igroup,ik),ik)*rytoev, dim_rap
                    exit
                 ELSEIF (abs(times(igroup,irap,ik)) > accuracy) THEN
                    IF (abs(nint(dble(times(igroup,irap,ik))-1.d0)) < &
                         accuracy) THEN
                       WRITE(stdout,'(5x, "e(",i3," -",i3,") = ",&
                            &f12.5,2x,"eV",3x,i3,3x,"--> ",a15)') &
                            istart(igroup,ik), istart(igroup+1,ik)-1, &
                            et(istart(igroup,ik),ik)*rytoev, &
                            dim_rap, name_rap(irap)
                    ELSE
                       WRITE(stdout,'(5x,"e(",i3," -",i3,") = ",&
                            &f12.5,2x,"eV",3x,i3,3x,"--> ",i3," ",a15)') &
                            istart(igroup,ik), istart(igroup+1,ik)-1, &
                            et(istart(igroup,ik),ik)*rytoev, dim_rap, &
                            nint(dble(times(igroup,irap,ik))), name_rap(irap)
                    ENDIF
                 ENDIF
              ENDIF
           ENDDO
        ENDDO
        WRITE( stdout, '(/,1x,74("*"))')
     ENDDO
     CLOSE(iunout)
  ENDIF

  !
  DEALLOCATE(times)
  DEALLOCATE(code_group_k)
  DEALLOCATE(rap_et)
  DEALLOCATE(ngroup)
  DEALLOCATE(istart)
  DEALLOCATE(high_symmetry)
  !
  RETURN
END SUBROUTINE sym_band
!
SUBROUTINE find_band_sym (ik,evc,et,nsym,s,ft,gk,invs,rap_et,times,ngroup,&
                          istart,accuracy)
  !
  !   This subroutine finds the irreducible representations which give
  !   the transformation properties of the wavefunctions.
  !   Presently it does NOT work at zone border if the space group of
  !   the crystal has fractionary translations (non-symmorphic space groups).
  !
  !
  USE io_global,       ONLY : stdout
  USE kinds,           ONLY : DP
  USE constants,       ONLY : rytoev
  USE rap_point_group, ONLY : code_group, nclass, nelem, elem, which_irr, &
       char_mat, name_rap, name_class, gname
  USE gvect,           ONLY : ngm
  USE wvfct,           ONLY : nbnd, npwx
  USE klist,           ONLY : ngk, igk_k
  USE uspp,            ONLY : vkb, nkb, okvan
  USE becmod,          ONLY : bec_type, becp, calbec, &
       allocate_bec_type, deallocate_bec_type
  USE fft_base,        ONLY : dfftp
  USE fft_interfaces,  ONLY : invfft
  USE mp_bands,        ONLY : intra_bgrp_comm
  USE mp,              ONLY : mp_sum

  IMPLICIT NONE

  INTEGER, INTENT(in) :: ik
  REAL(DP), INTENT(in) :: accuracy

  INTEGER ::                  &
       nsym,             &
       rap_et(nbnd),     &
       gk(3,48),         &
       s(3,3,48),        &
       invs(48),         &
       ngroup,           &  ! number of different frequencies groups
       istart(nbnd+1)

  REAL(DP) ::             &
       ft(3,48),          &
       et(nbnd)

  COMPLEX(DP) ::  &
       times(nbnd,24), &
       evc(npwx, nbnd)

  REAL(DP), PARAMETER :: eps=1.d-5

  INTEGER ::         &
       ibnd,jbnd, &
       igroup,    &
       dim_rap,   &
       irot,      &
       irap,      &
       iclass,    &
       shift,     &
       na, i, j, ig, dimen, nrxx, npw
  INTEGER :: s_scaled(3,3,nsym), ftau(3,nsym)

  REAL(DP), ALLOCATABLE ::  w1(:)
  COMPLEX(DP), ALLOCATABLE ::  evcr(:,:), trace(:,:), psic(:,:), matrep(:,:,:,:)
  !
  !    Divide the bands on the basis of the band degeneracy.
  !
  nrxx=dfftp%nnr
  ALLOCATE(w1(nbnd))
  ALLOCATE(evcr(npwx,nbnd))
  ALLOCATE(psic(nrxx,nbnd))
  ALLOCATE(trace(48,nbnd))
  ALLOCATE(matrep(48,nbnd,10,10))
  IF (okvan) CALL allocate_bec_type ( nkb, nbnd, becp )

  rap_et=-1
  w1=et*rytoev

  ngroup=1
  istart(ngroup)=1
  DO ibnd=2,nbnd
     IF (abs(w1(ibnd)-w1(ibnd-1)) > 0.0001d0) THEN
        ngroup=ngroup+1
        istart(ngroup)=ibnd
     ENDIF
  ENDDO
  istart(ngroup+1)=nbnd+1
!
!   bring all the bands in real space
!
  npw = ngk(ik)
  psic=(0.0_DP,0.0_DP)
  DO ibnd=1,nbnd
     psic(dfftp%nl(igk_k(1:npw,ik)),ibnd) = evc(1:npw,ibnd)
     CALL invfft ('Rho', psic(:,ibnd), dfftp)
  ENDDO
  !
  !  scale sym.ops. and fractional translations with FFT grids
  !
  CALL scale_sym_ops (nsym, s, ft, dfftp%nr1, dfftp%nr2, dfftp%nr3, s_scaled, ftau)
  !
  !  Find the character of one symmetry operation per class
  !
  DO iclass=1,nclass
     irot=elem(1,iclass)
     !
     !   Rotate all the bands together.
     !   NB: rotate_psi assume that s is in the small group of k. It does not
     !       rotate the k point.
     !
     !
     IF (irot==1) THEN
        evcr=evc
     ELSE
        CALL rotate_all_psi(ik, psic, evcr, s_scaled(1,1,invs(irot)), &
                               ftau(1,invs(irot)), gk(1,invs(irot)))
     ENDIF
     !
     !   and apply S if necessary
     !
     IF ( okvan ) THEN
        CALL calbec( npw, vkb, evcr, becp )
        CALL s_psi( npwx, npw, nbnd, evcr, evcr )
     ENDIF
     !
     !  Compute the trace of the representation for each group of bands
     !
     DO igroup=1,ngroup
        dim_rap=istart(igroup+1)-istart(igroup)
        trace(iclass,igroup)=(0.d0,0.d0)
        DO i=1,dim_rap
           ibnd=istart(igroup)+i-1
           trace(iclass,igroup)=trace(iclass,igroup) + &
                DOT_PRODUCT (evc(1:npw,ibnd),evcr(1:npw,ibnd))
        ENDDO
        !      write(6,*) igroup, iclass, trace(iclass,igroup)
     ENDDO

     !
     ! Compute the representation matrices for each group of bands
     !
     DO igroup=1,ngroup
        dim_rap=istart(igroup+1)-istart(igroup)
        DO i=1,dim_rap
           DO j=1,dim_rap
              ibnd=istart(igroup)+i-1
              jbnd=istart(igroup)+j-1
              matrep(iclass,igroup,i,j) = DOT_PRODUCT (evc(1:npw,ibnd),evcr(1:npw,jbnd))
           ENDDO
        ENDDO
     ENDDO
   
  ENDDO
  !
  CALL mp_sum( trace, intra_bgrp_comm )

  !DO iclass=1,nclass
  !   write(6,'(i5,3(2f11.8,1x))') iclass,trace(iclass,4),trace(iclass,5), &
  !                                       trace(iclass,6)
  !ENDDO

  !
  !  And now use the character table to identify the symmetry representation
  !  of each group of bands
  !
  !WRITE(stdout,'(/,5x,"Band symmetry, ",a11," point group:",/)') gname

  DO igroup=1,ngroup
     dim_rap=istart(igroup+1)-istart(igroup)
     shift=0
     DO irap=1,nclass
        times(igroup,irap)=(0.d0,0.d0)
        DO iclass=1,nclass
           times(igroup,irap)=times(igroup,irap) &
                +trace(iclass,igroup)*CONJG(char_mat(irap,which_irr(iclass)))&
                *nelem(iclass)
        ENDDO
        times(igroup,irap)=times(igroup,irap)/nsym
        IF ((abs(nint(dble(times(igroup,irap)))-dble(times(igroup,irap))) &
             > accuracy).or. (abs(aimag(times(igroup,irap))) > eps) ) THEN
           !            WRITE(stdout,'(5x,"e(",i3," -",i3,") = ",f12.5,2x,"eV",3x,i3,3x,&
           !                      & "-->   ?")') &
           !              istart(igroup), istart(igroup+1)-1, w1(istart(igroup)), dim_rap
           ibnd=istart(igroup)
           IF (rap_et(ibnd)==-1) THEN
              DO i=1,dim_rap
                 ibnd=istart(igroup)+i-1
                 rap_et(ibnd)=0
              ENDDO
           ENDIF
           GOTO 300
        ELSEIF (abs(times(igroup,irap)) > accuracy) THEN
           ibnd=istart(igroup)+shift
           dimen=nint(dble(char_mat(irap,1)))
           IF (rap_et(ibnd)==-1) THEN
              DO i=1,dimen*nint(dble(times(igroup,irap)))
                 ibnd=istart(igroup)+shift+i-1
                 rap_et(ibnd)=irap
              ENDDO
              shift=shift+dimen*nint(dble(times(igroup,irap)))
           ENDIF
           !         IF (ABS(NINT(DBLE(times))-1.d0) < 1.d-4) THEN
           !            WRITE(stdout,'(5x, "e(",i3," -",i3,") = ",f12.5,2x,"eV",3x,i3,&
           !                      & 3x,"--> ",a15)') &
           !              istart(igroup), istart(igroup+1)-1, w1(istart(igroup)), &
           !                              dim_rap, name_rap(irap)
           !         ELSE
           !            WRITE(stdout,'(5x,"e(",i3," -",i3,") = ",f12.5,2x,"eV",3x,i3,3x,&
           !                      & "--> ",i3," ",a15)') &
           !              istart(igroup), istart(igroup+1)-1, &
           !              w1(istart(igroup)), dim_rap, NINT(DBLE(times)), name_rap(irap)
           !         END IF
        ENDIF
     ENDDO
300  CONTINUE
  ENDDO
  !WRITE( stdout, '(/,1x,74("*"))')

  DEALLOCATE(matrep)
  DEALLOCATE(trace)
  DEALLOCATE(w1)
  DEALLOCATE(evcr)
  DEALLOCATE(psic)
  IF (okvan) CALL deallocate_bec_type (becp)

  RETURN
END SUBROUTINE find_band_sym


SUBROUTINE rotate_all_psi(ik,psic,evcr,s,ftau,gk)

  USE kinds,     ONLY : DP
  USE constants, ONLY : tpi
  USE gvect,     ONLY : ngm
  USE wvfct,     ONLY : nbnd, npwx
  USE klist,     ONLY : ngk, igk_k
  USE fft_base,  ONLY : dfftp
  USE scatter_mod,  ONLY : cgather_sym_many, cscatter_sym_many
  USE fft_interfaces, ONLY : fwfft, invfft
  USE mp_bands,  ONLY : intra_bgrp_comm
  USE mp,        ONLY : mp_sum

  IMPLICIT NONE

  INTEGER, INTENT(IN) :: ik
  INTEGER :: s(3,3), ftau(3), gk(3)

  COMPLEX(DP), ALLOCATABLE :: psir(:)
  COMPLEX(DP) :: psic(dfftp%nnr,nbnd), evcr(npwx,nbnd)
  COMPLEX(DP) :: phase
  REAL(DP) :: arg
  INTEGER :: i, j, k, ri, rj, rk, ir, rir, ipol, ibnd
  INTEGER :: nr1, nr2, nr3, nr1x, nr2x, nr3x, nrxx, npw
  LOGICAL :: zone_border
  INTEGER :: start_band, last_band, my_nbnd_proc
  INTEGER :: start_band_proc(dfftp%nproc), nbnd_proc(dfftp%nproc)

#if defined  (__MPI)
  !
  COMPLEX (DP), ALLOCATABLE :: psir_collect(:)
  COMPLEX (DP), ALLOCATABLE :: psic_collect(:,:)
  !
#endif
  !
  nr1=dfftp%nr1
  nr2=dfftp%nr2
  nr3=dfftp%nr3
  nr1x=dfftp%nr1x
  nr2x=dfftp%nr2x
  nr3x=dfftp%nr3x
  nrxx=dfftp%nnr
  npw = ngk(ik)
  !
  ALLOCATE(psir(nrxx))
  !
  zone_border=(gk(1)/=0.OR.gk(2)/=0.OR.gk(3)/=0)
  !
  evcr=  (0.0_DP, 0.0_DP)
  !
#if defined  (__MPI)

  call divide (intra_bgrp_comm, nbnd, start_band, last_band)
  start_band_proc=0
  start_band_proc(dfftp%mype+1)=start_band
  nbnd_proc=0
  my_nbnd_proc=last_band-start_band+1
  nbnd_proc(dfftp%mype+1)=my_nbnd_proc
  CALL mp_sum(start_band_proc, intra_bgrp_comm)
  CALL mp_sum(nbnd_proc, intra_bgrp_comm)
  !
  ALLOCATE (psic_collect(nr1x*nr2x*nr3x, my_nbnd_proc))
  ALLOCATE (psir_collect(nr1x*nr2x*nr3x))
  !
  CALL cgather_sym_many( dfftp, psic, psic_collect, nbnd, nbnd_proc, start_band_proc)
  !
  DO ibnd = 1, my_nbnd_proc
     psir_collect=(0.d0,0.d0)
     !
     IF (zone_border) THEN
        DO k = 1, nr3
          DO j = 1, nr2
             DO i = 1, nr1
              CALL rotate_grid_point (s, ftau, i, j, k, nr1, nr2, nr3, ri, rj, rk )
              ir=i+(j-1)*nr1x+(k-1)*nr1x*nr2x
              rir=ri+(rj-1)*nr1x+(rk-1)*nr1x*nr2x
              arg=tpi*( (gk(1)*(i-1))/dble(nr1)+(gk(2)*(j-1))/dble(nr2)+ &
                   (gk(3)*(k-1))/dble(nr3) )
              phase=cmplx(cos(arg),sin(arg),kind=DP)
              psir_collect(ir)=psic_collect(rir,ibnd)*phase
             ENDDO
          ENDDO
       ENDDO
     ELSE
        DO k = 1, nr3
           DO j = 1, nr2
              DO i = 1, nr1
                 CALL rotate_grid_point (s, ftau, i, j, k, nr1, nr2, nr3, ri, rj, rk )
                 ir=i+(j-1)*nr1x+(k-1)*nr1x*nr2x
                 rir=ri+(rj-1)*nr1x+(rk-1)*nr1x*nr2x
                 psir_collect(ir)=psic_collect(rir, ibnd)
              ENDDO
           ENDDO
        ENDDO
     ENDIF
     psic_collect(:,ibnd)=psir_collect(:)
  ENDDO
  !
  DO ibnd=1, nbnd
     CALL cscatter_sym_many( dfftp, psic_collect, psir, ibnd, nbnd, &
                                                 nbnd_proc, start_band_proc )
     !
     CALL fwfft ('Rho', psir, dfftp)
     !
     evcr(1:npw,ibnd) = psir(dfftp%nl(igk_k(1:npw,ik)))
  END DO
  DEALLOCATE (psic_collect)
  DEALLOCATE (psir_collect)
  !
#else
  psir=(0.d0,0.d0)
  DO ibnd=1,nbnd
     IF (zone_border) THEN
        DO k = 1, nr3
           DO j = 1, nr2
              DO i = 1, nr1
                 CALL rotate_grid_point (s, ftau, i, j, k, nr1, nr2, nr3, ri, rj, rk )
                 ir=i+(j-1)*nr1x+(k-1)*nr1x*nr2x
                 rir=ri+(rj-1)*nr1x+(rk-1)*nr1x*nr2x
                 arg=tpi*( (gk(1)*(i-1))/dble(nr1)+(gk(2)*(j-1))/dble(nr2)+ &
                    (gk(3)*(k-1))/dble(nr3) )
                 phase=cmplx(cos(arg),sin(arg),kind=DP)
                 psir(ir)=psic(rir,ibnd)*phase
              ENDDO
           ENDDO
        ENDDO
     ELSE
        DO k = 1, nr3
           DO j = 1, nr2
              DO i = 1, nr1
                 CALL rotate_grid_point (s, ftau, i, j, k, nr1, nr2, nr3, ri, rj, rk )
                 ir=i+(j-1)*nr1x+(k-1)*nr1x*nr2x
                 rir=ri+(rj-1)*nr1x+(rk-1)*nr1x*nr2x
                 psir(ir)=psic(rir,ibnd)
              ENDDO
           ENDDO
        ENDDO
     ENDIF
     CALL fwfft ('Rho', psir, dfftp)
     !
     evcr(1:npw,ibnd) = psir(dfftp%nl(igk_k(1:npw,ik)))
  ENDDO
  !
#endif
  !
  DEALLOCATE(psir)
  !
  RETURN
END SUBROUTINE rotate_all_psi

SUBROUTINE find_band_sym_so (ik,evc,et,nsym,s,ft,d_spin,gk, &
     invs,rap_et,times,ngroup,istart,accuracy)

  !
  !   This subroutine finds the irreducible representations of the
  !   double group which give the transformation properties of the
  !   spinor wavefunctions evc.
  !   Presently it does NOT work at zone border if the space group of
  !   the crystal has fractionary translations (non-symmorphic space groups).
  !
  !
  USE io_global,          ONLY : stdout
  USE kinds,              ONLY : DP
  USE constants,          ONLY : rytoev
  USE fft_base,           ONLY : dfftp
  USE rap_point_group,    ONLY : code_group, nclass, gname
  USE rap_point_group_so, ONLY : nrap, nelem_so, elem_so, has_e, which_irr_so, &
       char_mat_so, name_rap_so, name_class_so,      &
       name_class_so1
  USE rap_point_group_is, ONLY : gname_is
  USE gvect,              ONLY : ngm
  USE wvfct,              ONLY : nbnd, npwx
  USE klist,              ONLY : ngk
  USE uspp,               ONLY : vkb, nkb, okvan
  USE noncollin_module,   ONLY : npol
  USE becmod,             ONLY : bec_type, becp, calbec, allocate_bec_type, deallocate_bec_type
  USE mp_bands,           ONLY : intra_bgrp_comm
  USE mp,                 ONLY : mp_sum

  IMPLICIT NONE

  INTEGER, INTENT(in) :: ik
  REAL(DP), INTENT(in) :: accuracy

  INTEGER ::                  &
       nsym,             &
       ngroup,           &
       istart(nbnd+1),   &
       rap_et(nbnd),     &
       gk(3,48),         &
       invs(48),         &
       s(3,3,48)

  REAL(DP) ::            &
       ft(3,48),         &
       et(nbnd)

  COMPLEX(DP) ::  &
       times(nbnd,24), &
       d_spin(2,2,48), &
       evc(npwx*npol, nbnd)

  REAL(DP), PARAMETER :: eps=1.d-5

  INTEGER :: s_scaled(3,3,nsym), ftau(3,nsym)
  INTEGER ::         &
       ibnd,jbnd, &
       igroup,    &
       dim_rap,   &  ! counters
       irot,      &
       irap,      &
       shift,     &
       iclass,    &
       na, i, j, ig, ipol, jpol, jrap, dimen, npw

  REAL(DP), ALLOCATABLE ::  w1(:)      ! list of energy eigenvalues in eV
  COMPLEX(DP), ALLOCATABLE ::  evcr(:,:), & ! the rotated of each wave function
       trace(:,:), &   ! the trace of the symmetry matrix
       matrep(:,:,:,:) ! the representation matrix
  ! within a given group
  !
  !    Divide the bands on the basis of the band degeneracy.
  !
  ALLOCATE(w1(nbnd))
  ALLOCATE(evcr(npwx*npol,nbnd))
  ALLOCATE(trace(48,nbnd))
  ALLOCATE(matrep(48,nbnd,10,10))
  IF (okvan) CALL allocate_bec_type ( nkb, nbnd, becp )

  rap_et=-1
  w1=et*rytoev
  !
  !  divide the energies in groups of degenerate eigenvalues. Two eigenvalues
  !  are assumed to be degenerate if their difference is less than 0.0001 eV.
  !
  ngroup=1
  istart(ngroup)=1
  DO ibnd=2,nbnd
     IF (abs(w1(ibnd)-w1(ibnd-1)) > 0.0001d0) THEN
        ngroup=ngroup+1
        istart(ngroup)=ibnd
     ENDIF
  ENDDO
  istart(ngroup+1)=nbnd+1
  !
  !  scale sym.ops. and fractional translations with FFT grid
  !
  CALL scale_sym_ops (nsym, s, ft, dfftp%nr1, dfftp%nr2, dfftp%nr3, s_scaled, ftau)

  trace=(0.d0,0.d0)
  matrep=(0.d0,0.d0)
  DO iclass=1,nclass
     irot=elem_so(1,iclass)
     !
     !   Rotate all the bands together.
     !   NB: rotate_psi assumes that s is in the small group of k. It does not
     !       rotate the k point.
     !
     CALL rotate_all_psi_so(ik, evc, evcr, s_scaled(1,1,invs(irot)),        &
           ftau(1,invs(irot)),d_spin(1,1,irot),has_e(1,iclass),gk(1,invs(irot)))
     !
     !   and apply S in the US case.
     !
     npw = ngk(ik)
     IF ( okvan ) THEN
        CALL calbec( npw, vkb, evcr, becp )
        CALL s_psi( npwx, npw, nbnd, evcr, evcr )
     ENDIF
     !
     !  Compute the trace of the representation for each group of bands
     !
     DO igroup=1,ngroup
        dim_rap=istart(igroup+1)-istart(igroup)
        DO i=1,dim_rap
           ibnd=istart(igroup)+i-1
           trace(iclass,igroup)=trace(iclass,igroup) +            &
                DOT_PRODUCT (evc(:,ibnd),evcr(:,ibnd))
        ENDDO
        !      write(6,*) igroup, iclass, dim_rap, trace(iclass,igroup)
     ENDDO

     !
     ! Compute the representation matrices for each group of bands
     !
     DO igroup=1,ngroup
      dim_rap=istart(igroup+1)-istart(igroup)
      DO i=1,dim_rap
         DO j=1,dim_rap
            ibnd=istart(igroup)+i-1
            jbnd=istart(igroup)+j-1
            matrep(iclass,igroup,i,j) = DOT_PRODUCT (evc(:,ibnd),evcr(:,jbnd))
         ENDDO
      ENDDO
   ENDDO
  ENDDO

  CALL mp_sum(matrep,intra_bgrp_comm)
  CALL mp_sum(trace,intra_bgrp_comm)
  
  DO iclass=1,nclass
   PRINT *, '******************************************************************************'
   DO igroup=1,ngroup
      dim_rap=istart(igroup+1)-istart(igroup)
      PRINT *, 'Bands, dim: e(', istart(igroup), ',', istart(igroup+1)-1, ')', dim_rap
      PRINT *, 'Class:', name_class_so(which_irr_so(iclass))
      PRINT *, 'Trace:', trace(iclass,igroup)
      DO i=1,dim_rap
         WRITE (*, '("matrix:", 100f15.8)') (matrep(iclass,igroup,i,j), j=1,dim_rap)
      ENDDO
   ENDDO
  ENDDO
  
  !
!  DO iclass=1,nclass
!     write(6,'(i5,3(2f11.8,1x))') iclass,trace(iclass,1),trace(iclass,2), &
!                                         trace(iclass,3)
!  ENDDO
  !
  !  And now use the character table to identify the symmetry representation
  !  of each group of bands
  !
  !IF (domag) THEN
  !   WRITE(stdout,'(/,5x,"Band symmetry, ",a11," [",a11, &
  !          & "] magnetic double point group,")') gname, gname_is
  !   WRITE(stdout,'(5x,"using ",a11,/)') gname_is
  !ELSE
  !   WRITE(stdout,'(/,5x,"Band symmetry, ",a11," double point group:",/)') gname
  !ENDIF


  PRINT *, "======================================================"
  PRINT *, "which_ir_so:", (which_irr_so(iclass), iclass=1, nclass)
  PRINT *, "classes:", (name_class_so(iclass), iclass=1, nclass)
  DO irap=1,nrap
   PRINT *, ">>", (char_mat_so(irap, which_irr_so(iclass)), iclass=1, nclass)
  ENDDO
  PRINT *, "======================================================"

  DO igroup=1,ngroup
     dim_rap=istart(igroup+1)-istart(igroup)
     shift=0
     DO irap=1,nrap
        times(igroup,irap)=(0.d0,0.d0)
        DO iclass=1,nclass
           times(igroup,irap)=times(igroup,irap) &
                +trace(iclass,igroup)*CONJG(char_mat_so(irap, &
                which_irr_so(iclass)))*DBLE(nelem_so(iclass))
        ENDDO
        times(igroup,irap)=times(igroup,irap)/2/nsym
        PRINT *, "Times:", igroup, name_rap_so(irap), times(igroup, irap)

        IF ((abs(nint(dble(times(igroup,irap)))-dble(times(igroup,irap)))&
             > accuracy).or. (abs(aimag(times(igroup,irap))) > accuracy) ) THEN
           !            WRITE(stdout,'(5x,"e(",i3," -",i3,") = ",f12.5,2x,"eV",3x,i3,3x,&
           !                      & "-->   ?")') &
           !              istart(igroup), istart(igroup+1)-1, w1(istart(igroup)), dim_rap
           ibnd=istart(igroup)
           IF (rap_et(ibnd)==-1) THEN
              DO i=1,dim_rap
                 ibnd=istart(igroup)+i-1
                 rap_et(ibnd)=0
              ENDDO
           ENDIF
           GOTO 300
        ENDIF
        IF (abs(times(igroup,irap)) > accuracy) THEN
           dimen=nint(dble(char_mat_so(irap,1)))
           ibnd=istart(igroup) + shift
           IF (rap_et(ibnd)==-1) THEN
              DO i=1,dimen*nint(dble(times(igroup,irap)))
                 ibnd=istart(igroup)+shift+i-1
                 rap_et(ibnd)=irap
              ENDDO
              shift=shift+dimen*nint(dble(times(igroup,irap)))
           ENDIF
           !         IF (ABS(NINT(DBLE(times))-1.d0) < 1.d-4) THEN
           !            WRITE(stdout,'(5x, "e(",i3," -",i3,") = ",f12.5,2x,"eV",3x,i3,3x,&
           !                      & "--> ",a15)') &
           !              istart(igroup), istart(igroup+1)-1, w1(istart(igroup)), &
           !                             dim_rap, name_rap_so(irap)
           !         ELSE
           !            WRITE(stdout,'(5x,"e(",i3," -",i3,") = ",f12.5,2x,"eV",3x,i3,&
           !                      & 3x,"--> ",i3," ",a15)') &
           !              istart(igroup), istart(igroup+1)-1, &
           !              w1(istart(igroup)), dim_rap, NINT(DBLE(times)), name_rap_so(irap)
           !         END IF
        ENDIF
     ENDDO
300  CONTINUE
  ENDDO
  !WRITE( stdout, '(/,1x,74("*"))')

  DEALLOCATE(matrep)
  DEALLOCATE(trace)
  DEALLOCATE(w1)
  DEALLOCATE(evcr)
  IF (okvan) CALL deallocate_bec_type ( becp )
  RETURN
END SUBROUTINE find_band_sym_so

SUBROUTINE rotate_all_psi_so(ik,evc_nc,evcr,s,ftau,d_spin,has_e,gk)
  !
  !  This subroutine rotates a spinor wavefunction according to the symmetry
  !  s. d_spin contains the 2x2 rotation matrix in the spin space.
  !  has_e=-1 means that also a 360 degrees rotation is applied in spin space.
  !
  USE kinds,     ONLY : DP
  USE constants, ONLY : tpi
  USE fft_base,  ONLY : dfftp
  USE scatter_mod,  ONLY : cgather_sym_many, cscatter_sym_many
  USE fft_interfaces, ONLY : fwfft, invfft
  USE gvect,     ONLY : ngm
  USE wvfct,     ONLY : nbnd, npwx
  USE klist,     ONLY : ngk, igk_k
  USE noncollin_module, ONLY : npol
  USE mp_bands,  ONLY : intra_bgrp_comm
  USE mp,        ONLY : mp_sum

  IMPLICIT NONE

  INTEGER, INTENT(in) :: ik
  INTEGER :: s(3,3), ftau(3), gk(3), has_e
  COMPLEX(DP) :: evc_nc(npwx,2,nbnd), evcr(npwx,2,nbnd), d_spin(2,2)

  COMPLEX(DP), ALLOCATABLE :: psic(:,:), psir(:), evcr_save(:,:,:)
  COMPLEX(DP) :: phase
  REAL(DP) :: arg
  INTEGER :: i, j, k, ri, rj, rk, ir, rir, ipol, jpol, ibnd
  INTEGER :: nr1, nr2, nr3, nr1x, nr2x, nr3x, nrxx, npw
  LOGICAL :: zone_border
  INTEGER :: start_band, last_band, my_nbnd_proc
  INTEGER :: start_band_proc(dfftp%nproc), nbnd_proc(dfftp%nproc)
  !
#if defined  (__MPI)
  !
  COMPLEX (DP), ALLOCATABLE :: psir_collect(:)
  COMPLEX (DP), ALLOCATABLE :: psic_collect(:,:)
  !
#endif

  nr1=dfftp%nr1
  nr2=dfftp%nr2
  nr3=dfftp%nr3
  nr1x=dfftp%nr1x
  nr2x=dfftp%nr2x
  nr3x=dfftp%nr3x
  nrxx=dfftp%nnr

#if defined  (__MPI)
  call divide (intra_bgrp_comm, nbnd, start_band, last_band)
  start_band_proc=0
  start_band_proc(dfftp%mype+1)=start_band
  nbnd_proc=0
  my_nbnd_proc=last_band-start_band+1
  nbnd_proc(dfftp%mype+1)=my_nbnd_proc
  CALL mp_sum(start_band_proc, intra_bgrp_comm)
  CALL mp_sum(nbnd_proc, intra_bgrp_comm)
  ALLOCATE (psic_collect(nr1x*nr2x*nr3x,my_nbnd_proc))
  ALLOCATE (psir_collect(nr1x*nr2x*nr3x))
#endif
  !
  ALLOCATE(psic(nrxx,nbnd))
  ALLOCATE(psir(nrxx))
  ALLOCATE(evcr_save(npwx,npol,nbnd))
  !
  zone_border=(gk(1)/=0.or.gk(2)/=0.or.gk(3)/=0)
  !
  npw = ngk(ik)
  evcr_save=(0.0_DP,0.0_DP)
  DO ipol=1,npol
     !
     psic = ( 0.D0, 0.D0 )
     psir = ( 0.D0, 0.D0 )
     !
     DO ibnd=1,nbnd
        psic(dfftp%nl(igk_k(1:npw,ik)),ibnd) = evc_nc(1:npw,ipol,ibnd)
        CALL invfft ('Rho', psic(:,ibnd), dfftp)
     ENDDO
     !
#if defined  (__MPI)
     !
     !
     CALL cgather_sym_many( dfftp, psic, psic_collect, nbnd, nbnd_proc, &
                                                       start_band_proc  )
     !
     psir_collect=(0.d0,0.d0)
     DO ibnd=1,my_nbnd_proc
        !
        IF (zone_border) THEN
           DO k = 1, nr3
              DO j = 1, nr2
                 DO i = 1, nr1
                    CALL rotate_grid_point (s, ftau, i, j, k, nr1, nr2, nr3, ri, rj, rk )
                    ir=i+(j-1)*nr1x+(k-1)*nr1x*nr2x
                    rir=ri+(rj-1)*nr1x+(rk-1)*nr1x*nr2x
                    arg=tpi*( (gk(1)*(i-1))/dble(nr1)+(gk(2)*(j-1))/dble(nr2)+ &
                         (gk(3)*(k-1))/dble(nr3) )
                    phase=cmplx(cos(arg),sin(arg),kind=DP)
                    psir_collect(ir)=psic_collect(rir,ibnd)*phase
                 ENDDO
              ENDDO
           ENDDO
        ELSE
           DO k = 1, nr3
              DO j = 1, nr2
                 DO i = 1, nr1
                    CALL rotate_grid_point (s, ftau, i, j, k, nr1, nr2, nr3, ri, rj, rk )
                    ir=i+(j-1)*nr1x+(k-1)*nr1x*nr2x
                    rir=ri+(rj-1)*nr1x+(rk-1)*nr1x*nr2x
                    psir_collect(ir)=psic_collect(rir,ibnd)
                 ENDDO
              ENDDO
           ENDDO
        ENDIF
        psic_collect(:,ibnd) = psir_collect(:)
     ENDDO
     DO ibnd=1,nbnd
        !
        CALL cscatter_sym_many(dfftp, psic_collect, psir, ibnd, nbnd, nbnd_proc, &
                               start_band_proc)
        CALL fwfft ('Rho', psir, dfftp)
        !
        evcr_save(1:npw,ipol,ibnd) = psir(dfftp%nl(igk_k(1:npw,ik)))
     ENDDO
     !
#else
     DO ibnd=1,nbnd
        IF (zone_border) THEN
           DO k = 1, nr3
              DO j = 1, nr2
                 DO i = 1, nr1
                    CALL rotate_grid_point (s, ftau, i, j, k, nr1, nr2, nr3, ri, rj, rk )
                    ir=i+(j-1)*nr1x+(k-1)*nr1x*nr2x
                    rir=ri+(rj-1)*nr1x+(rk-1)*nr1x*nr2x
                    arg=tpi*( (gk(1)*(i-1))/dble(nr1)+(gk(2)*(j-1))/dble(nr2)+ &
                         (gk(3)*(k-1))/dble(nr3) )
                    phase=cmplx(cos(arg),sin(arg),kind=DP)
                    psir(ir)=psic(rir,ibnd)*phase
                 ENDDO
              ENDDO
           ENDDO
        ELSE
           DO k = 1, nr3
              DO j = 1, nr2
                 DO i = 1, nr1
                    CALL rotate_grid_point (s, ftau, i, j, k, nr1, nr2, nr3, ri, rj, rk )
                    ir=i+(j-1)*nr1x+(k-1)*nr1x*nr2x
                    rir=ri+(rj-1)*nr1x+(rk-1)*nr1x*nr2x
                    psir(ir)=psic(rir,ibnd)
                 ENDDO
              ENDDO
           ENDDO
        ENDIF
        CALL fwfft ('Rho', psir(:), dfftp)
        !
        evcr_save(1:npw,ipol,ibnd) = psir(dfftp%nl(igk_k(1:npw,ik)))
     ENDDO
     !
#endif
     !
     !
  ENDDO

  evcr=(0.d0,0.d0)
  DO ibnd=1,nbnd 
     DO ipol=1,npol
        DO jpol=1,npol
           evcr(:,ipol,ibnd)=evcr(:,ipol,ibnd)+ &
                             d_spin(ipol,jpol)*evcr_save(:,jpol,ibnd)
        ENDDO
     ENDDO
  ENDDO
  IF (has_e==-1) evcr=-evcr
  !
  DEALLOCATE(evcr_save)
  DEALLOCATE(psic)
  DEALLOCATE(psir)
#if defined (__MPI)
  DEALLOCATE (psic_collect)
  DEALLOCATE (psir_collect)
#endif
  RETURN
END SUBROUTINE rotate_all_psi_so

SUBROUTINE find_nks1nks2(firstk,lastk,nks1tot,nks1,nks2tot,nks2,spin_component)
  !
  !  This routine selects the first (nks1) and last (nks2) k point calculated
  !  by the  current pool.
  !
  USE lsda_mod, ONLY : nspin
  USE klist,    ONLY : nks, nkstot
  USE mp_pools, ONLY : my_pool_id, npool, kunit

  IMPLICIT NONE
  INTEGER, INTENT(out) :: nks1tot,nks1,nks2tot,nks2
  INTEGER, INTENT(in) :: firstk, lastk, spin_component
  INTEGER :: nbase, rest

  IF (nspin==1.or.nspin==4) THEN
     nks1tot=max(1,firstk)
     nks2tot=min(nkstot, lastk)
  ELSEIF (nspin==2) THEN
     IF (spin_component == 1) THEN
        nks1tot=max(1,firstk)
        nks2tot=min(nkstot/2,lastk)
     ELSEIF (spin_component==2) THEN
        nks1tot=nkstot/2 + max(1,firstk)
        nks2tot=nkstot/2 + min(nkstot/2,lastk)
     ENDIF
  ENDIF
  IF (nks1tot>nks2tot) CALL errore('findnks1nks2','wrong nks1tot or nks2tot',1)

#ifdef __MPI
  nks  = kunit * ( nkstot / kunit / npool )
  rest = ( nkstot - nks * npool ) / kunit
  IF ( ( my_pool_id + 1 ) <= rest ) nks = nks + kunit
  !
  ! ... calculates nbase = the position in the list of the first point that
  ! ...                    belong to this npool - 1
  !
  nbase = nks * my_pool_id
  IF ( ( my_pool_id + 1 ) > rest ) nbase = nbase + rest * kunit

  nks1=max(1,nks1tot-nbase)
  IF (nks1>nks) nks1=nks+1
  nks2=min(nks,nks2tot-nbase)
  IF (nks2<1) nks2=nks1-1
#else
  nks1=nks1tot
  nks2=nks2tot
#endif

END SUBROUTINE find_nks1nks2

SUBROUTINE find_info_group(nsym,s,t_rev,ft,d_spink,gk,sname,  &
     s_is,d_spin_is,gk_is, invs_is,is_symmorphic,search_sym)
  !
  ! This routine receives as input a point group and sets the corresponding
  ! variables for the description of the classes and of the irreducible
  ! representations. It sets also the group name and code.
  ! In the magnetic case it selects the invariat subgroup.
  !
  USE kinds,                ONLY : DP
  USE cell_base,            ONLY : at, bg
  USE fft_base,             ONLY : dfftp
  USE noncollin_module,     ONLY : noncolin, domag
  USE rap_point_group,      ONLY : code_group, nclass, nelem, elem, which_irr, &
       char_mat, name_rap, name_class, gname, ir_ram
  USE rap_point_group_so,   ONLY : nrap, nelem_so, elem_so, has_e, &
       which_irr_so, char_mat_so, name_rap_so, &
       name_class_so, d_spin, name_class_so1
  USE rap_point_group_is,   ONLY : nsym_is, sr_is, ft_is, gname_is, &
       sname_is, code_group_is

  IMPLICIT NONE

  INTEGER, INTENT(in) :: nsym,        & ! dimension of the group
       s(3,3,48),   & ! rotation matrices
       t_rev(48),   & ! if time reversal is need
       gk(3,48)
  REAL(dp), INTENT(IN) :: ft(3,48)! fractionary translation

  INTEGER, INTENT(out) :: s_is(3,3,48),   & ! rotation matrices
       gk_is(3,48), invs_is(48)

  COMPLEX(DP),INTENT(out)   :: d_spink(2,2,48),  & ! rotation in spin space
       d_spin_is(2,2,48)   ! rotation in spin space

  LOGICAL, INTENT(out) :: is_symmorphic, &  ! true if the gruop is symmorphic
       search_sym        ! true if gk

  CHARACTER(len=45), INTENT(in) :: sname(48)

  REAL(DP) :: sr(3,3,48)
  INTEGER :: isym, jsym, ss(3,3)
  LOGICAL :: found


  is_symmorphic=.true.
  search_sym=.true.

  DO isym=1,nsym
     is_symmorphic=( is_symmorphic.and.(ft(1,isym)==0.d0).and.  &
          (ft(2,isym)==0.d0).and.  &
          (ft(3,isym)==0.d0) )
  ENDDO

  IF (.NOT.is_symmorphic) THEN

     DO isym=1,nsym
        DO jsym=1,nsym
           search_sym=search_sym.AND.(ABS(gk(1,isym)*ft(1,jsym)+ &
                     gk(2,isym)*ft(2,jsym)+gk(3,isym)*ft(3,jsym))<1.D-8) 
        ENDDO
     ENDDO
  ENDIF
  !
  !  Set the group name, divide it in classes and set the irreducible
  !  representations
  !
  nsym_is=0
  DO isym=1,nsym
     CALL s_axis_to_cart (s(1,1,isym), sr(1,1,isym), at, bg)
     IF (noncolin) THEN
        !
        !  In the noncollinear magnetic case finds the invariant subgroup of the point
        !  group of k. Presently we use only this subgroup to classify the levels.
        !
        IF (domag) THEN
           IF (t_rev(isym)==0) THEN
              nsym_is=nsym_is+1
              CALL s_axis_to_cart (s(1,1,isym), sr_is(1,1,nsym_is), at, bg)
              CALL find_u(sr_is(1,1,nsym_is),d_spin_is(1,1,nsym_is))
              s_is(:,:,nsym_is)=s(:,:,isym)
              gk_is(:,nsym_is)=gk(:,isym)
              ft_is(:,nsym_is)=ft(:,isym)
              sname_is(nsym_is)=sname(isym)
           ENDIF
        ELSE
           CALL find_u(sr(1,1,isym),d_spink(1,1,isym))
        ENDIF
     ENDIF
  ENDDO

  IF (noncolin.AND.domag) THEN
!
!   find the inverse of each element
!
     DO isym = 1, nsym_is
        found = .FALSE.
        DO jsym = 1, nsym_is
           !
           ss = MATMUL (s_is(:,:,jsym),s_is(:,:,isym))
           ! s(:,:,1) is the identity
           IF ( ALL ( s_is(:,:,1) == ss(:,:) ) ) THEN
              invs_is (isym) = jsym
              found = .TRUE.
           ENDIF
        END DO
        IF ( .NOT.found) CALL errore ('find_info_group', ' Not a group', 1)
     ENDDO
!
!   Recheck if we can compute the representations. The group is now smaller
!
     is_symmorphic=.TRUE.
     search_sym=.TRUE.

     DO isym=1,nsym_is
        is_symmorphic=( is_symmorphic.AND.(ft_is(1,isym)==0.d0).AND.  &
                                          (ft_is(2,isym)==0.d0).AND.  &
                                          (ft_is(3,isym)==0.d0) )
     ENDDO
     IF (.NOT.is_symmorphic) THEN
        DO isym=1,nsym_is
           DO jsym=1,nsym_is
              search_sym=search_sym.AND.(ABS(gk_is(1,isym)*ft_is(1,jsym)+ &
                                             gk_is(2,isym)*ft_is(2,jsym)+     &
                                             gk_is(3,isym)*ft_is(3,jsym))<1.D-8) 
           ENDDO
        ENDDO
     ENDIF
  END IF
  !
  !  Set the group name, divide it in classes and set the irreducible
  !
  CALL find_group(nsym,sr,gname,code_group)
  IF (noncolin) THEN
     IF (domag) THEN
        CALL find_group(nsym_is,sr_is,gname_is,code_group_is)
        CALL set_irr_rap_so(code_group_is,nclass,nrap,char_mat_so, &
             name_rap_so,name_class_so,name_class_so1)
        CALL divide_class_so(code_group_is,nsym_is,sr_is,d_spin_is,&
             has_e,nclass,nelem_so,elem_so,which_irr_so)
     ELSE
        CALL set_irr_rap_so(code_group,nclass,nrap,char_mat_so, &
             name_rap_so,name_class_so,name_class_so1)
        CALL divide_class_so(code_group,nsym,sr,d_spink, &
             has_e,nclass,nelem_so,elem_so,which_irr_so)
     ENDIF
  ELSE
     CALL set_irr_rap(code_group,nclass,char_mat,name_rap,name_class,ir_ram)
     CALL divide_class(code_group,nsym,sr,nclass,nelem,elem,which_irr)
  ENDIF

  RETURN
END SUBROUTINE find_info_group
!
! Copyright (C) 2001 PWSCF group
! 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 .
!
!
!----------------------------------------------------------------------
SUBROUTINE s_axis_to_cart (s, sr, at, bg)
  !----------------------------------------------------------------------
  !
  !     This routine transform a symmetry matrix expressed in the
  !     basis of the crystal axis in the cartesian basis.
  !
  !     last revised 3 may 1995 by A. Dal Corso
  !
  !
  USE kinds
  IMPLICIT NONE
  !
  !     first the input parameters
  !
  INTEGER :: s (3, 3)
  ! input: matrix in crystal axis
  real(DP) :: sr (3, 3), at (3, 3), bg (3, 3)
  ! output: matrix in cartesian axis
  ! input: direct lattice vectors
  ! input: reciprocal lattice vectors
  !
  !     here the local variable
  !

  INTEGER :: apol, bpol, kpol, lpol
  !
  !     counters on polarizations
  !
  DO apol = 1, 3
     DO bpol = 1, 3
        sr (apol, bpol) = 0.d0
        DO kpol = 1, 3
           DO lpol = 1, 3
              sr (apol, bpol) = sr (apol, bpol) + at (apol, kpol) * &
                   dble ( s (lpol, kpol) ) * bg (bpol, lpol)
           ENDDO
        ENDDO
     ENDDO
  ENDDO
  RETURN
END SUBROUTINE s_axis_to_cart


_______________________________________________
The Quantum ESPRESSO community stands by the Ukrainian
people and expresses its concerns about the devastating
effects that the Russian military offensive has on their
country and on the free and peaceful scientific, cultural,
and economic cooperation amongst peoples
_______________________________________________
Quantum ESPRESSO is supported by MaX (www.max-centre.eu)
users mailing list users@lists.quantum-espresso.org
https://lists.quantum-espresso.org/mailman/listinfo/users

Reply via email to