quantum-espresso/Modules/wyckoff.f90

322 lines
8.2 KiB
Fortran

MODULE wyckoff
USE kinds, ONLY : DP
USE space_group, ONLY : sym_brav, find_equivalent_tau
IMPLICIT NONE
INTEGER :: nattot
REAL(DP), ALLOCATABLE :: tautot(:,:), extfortot(:,:)
INTEGER, ALLOCATABLE :: ityptot(:), if_postot(:,:)
SAVE
PRIVATE
PUBLIC sup_spacegroup, clean_spacegroup, nattot, tautot, ityptot, extfortot, &
if_postot
CONTAINS
SUBROUTINE sup_spacegroup(tau,ityp,extfor,if_pos,space_group_number,not_eq,&
uniqueb,rhombohedral,choice,ibrav)
INTEGER, INTENT(IN) :: space_group_number, choice
LOGICAL, INTENT (IN) :: uniqueb, rhombohedral
INTEGER, INTENT (INOUT) :: not_eq
INTEGER, INTENT(OUT) :: ibrav
REAL(DP), DIMENSION(:,:), ALLOCATABLE, INTENT(IN) :: tau, extfor
INTEGER, DIMENSION(:), ALLOCATABLE, INTENT(IN) :: ityp
INTEGER, DIMENSION(:,:), ALLOCATABLE, INTENT(IN) :: if_pos
INTEGER :: i,k,l,n,sym_n
INTEGER,DIMENSION(:),allocatable :: msym_n
character(LEN=1) :: unique
REAL(DP), DIMENSION(:,:), ALLOCATABLE :: inco
REAL(DP), DIMENSION(:,:,:), ALLOCATABLE :: outco
ALLOCATE(inco(3,not_eq))
ALLOCATE(msym_n(not_eq))
inco=tau
!conv from uniqueb,rhombohedral,choice to unique
unique='1'
IF ((uniqueb).or.(.not.rhombohedral).or.(choice==2)) then
unique='2'
END IF
!select ibrav and number of symmetries
CALL sym_brav(space_group_number,sym_n,ibrav)
do i=1,not_eq
msym_n(i)=sym_n
end do
IF (((ibrav==12).or.(ibrav==13)).and.(unique=='2')) ibrav=-ibrav
ALLOCATE(outco(3,sym_n,not_eq))
!make symmetries, convert coordinates, esclusion
DO i=1,not_eq
CALL find_equivalent_tau(space_group_number, inco, outco,i,unique)
END DO
call ccord(outco,sym_n,not_eq,ibrav,unique)
CALL zerone(sym_n,not_eq, outco)
CALL esclusion(sym_n,not_eq,outco,msym_n)
nattot=SUM(msym_n)
ALLOCATE(tautot(3,nattot))
ALLOCATE(ityptot(nattot))
ALLOCATE(extfortot(3,nattot))
ALLOCATE(if_postot(3,nattot))
!conversione tra outco e tau
l=0
DO i=1,not_eq
IF (i/=1) THEN
l=l+msym_n(i-1)
END IF
!
DO k=1,msym_n(i)
tautot(1,k+l)=outco(1,k,i)
tautot(2,k+l)=outco(2,k,i)
tautot(3,k+l)=outco(3,k,i)
ityptot(k+l) = ityp(i)
if_postot(:,k+l) = if_pos(:,i)
extfortot(:,k+l) = extfor(:,i)
END DO
END DO
DEALLOCATE(inco)
DEALLOCATE(outco)
DEALLOCATE(msym_n)
RETURN
END SUBROUTINE sup_spacegroup
SUBROUTINE clean_spacegroup
DEALLOCATE(tautot)
DEALLOCATE(ityptot)
DEALLOCATE(extfortot)
DEALLOCATE(if_postot)
RETURN
END SUBROUTINE clean_spacegroup
SUBROUTINE ccord(outco,sym_n,not_eq,ibrav,unique)
IMPLICIT NONE
REAL(DP), DIMENSION(:,:,:), INTENT(INOUT) :: outco
INTEGER, INTENT(in) :: ibrav,sym_n,not_eq
CHARACTER, INTENT(in) :: unique
INTEGER :: i,k
REAL(DP) :: tmpx, tmpy, tmpz
Cambio: SELECT CASE (ibrav)
CASE (2) !fcc
DO k=1,not_eq
DO i=1,sym_n
tmpx=outco(1,i,k)
tmpy=outco(2,i,k)
tmpz=outco(3,i,k)
outco(1,i,k)=-tmpx-tmpy+tmpz
outco(2,i,k)=tmpx+tmpy+tmpz
outco(3,i,k)=-tmpx-tmpz+tmpy
END DO
END DO
CASE (3) !bcc
DO k=1,not_eq
DO i=1,sym_n
tmpx=outco(1,i,k)
tmpy=outco(2,i,k)
tmpz=outco(3,i,k)
outco(1,i,k)=tmpx+tmpz
outco(2,i,k)=tmpy-tmpx
outco(3,i,k)=tmpz-tmpy
END DO
END DO
CASE (5) !Only for trigonal
IF (unique=='2') THEN
DO k=1,not_eq
DO i=1,sym_n
tmpx=outco(1,i,k)
tmpy=outco(2,i,k)
tmpz=outco(3,i,k)
!
! Original signs (corresponding to reverse trigonal axes)
!
! outco(1,i,k)=tmpx-tmpy+tmpz
! outco(2,i,k)=tmpy+tmpz
! outco(3,i,k)=tmpz-tmpx
!
! Corrected signs (correspond to obverse trigonal axes as in ITA)
!
outco(1,i,k)=tmpx-tmpy-tmpz
outco(2,i,k)=tmpy-tmpz
outco(3,i,k)=-tmpz-tmpx
END DO
END DO
END IF
CASE (7) !Body Centred Tetragonal
DO k=1,not_eq
DO i=1,sym_n
tmpx=outco(1,i,k)
tmpy=outco(2,i,k)
tmpz=outco(3,i,k)
outco(1,i,k)=tmpx-tmpy
outco(2,i,k)=tmpy+tmpz
outco(3,i,k)=tmpz-tmpx
END DO
END DO
CASE (9) !Base Centrata ORTHORHOMBIC C
DO k=1,not_eq
DO i=1,sym_n
tmpx=outco(1,i,k)
tmpy=outco(2,i,k)
tmpz=outco(3,i,k)
outco(1,i,k)=tmpx+tmpy
outco(2,i,k)=tmpy-tmpx
outco(3,i,k)=tmpz
END DO
END DO
CASE (91) !Base Centrata ORTHORHOMBIC A
DO k=1,not_eq
DO i=1,sym_n
tmpx=outco(1,i,k)
tmpy=outco(2,i,k)
tmpz=outco(3,i,k)
outco(1,i,k)=tmpx
outco(2,i,k)=tmpy+tmpz
outco(3,i,k)=tmpy-tmpz
END DO
END DO
CASE (10) !Tutte le faccie centrate ORTHORHOMBIC
DO k=1,not_eq
DO i=1,sym_n
tmpx=outco(1,i,k)
tmpy=outco(2,i,k)
tmpz=outco(3,i,k)
outco(1,i,k)=tmpx-tmpy+tmpz
outco(2,i,k)=tmpx+tmpy-tmpz
outco(3,i,k)=-tmpx+tmpy+tmpz
END DO
END DO
CASE (11) !Corpo Centrato ORTHORHOMBIC
DO k=1,not_eq
DO i=1,sym_n
tmpx=outco(1,i,k)
tmpy=outco(2,i,k)
tmpz=outco(3,i,k)
outco(1,i,k)=tmpx+tmpz
outco(2,i,k)=tmpy-tmpx
outco(3,i,k)=tmpz-tmpy
END DO
END DO
CASE (13) !Centrato C unique MONOCLINO
DO k=1,not_eq
DO i=1,sym_n
tmpx=outco(1,i,k)
tmpz=outco(3,i,k)
outco(1,i,k)=tmpx-tmpz
outco(3,i,k)=tmpz+tmpx
END DO
END DO
CASE (-13) !Centrato B unique MONOCLINO
DO k=1,not_eq
DO i=1,sym_n
tmpx=outco(1,i,k)
tmpy=outco(2,i,k)
outco(1,i,k)=tmpx+tmpy
outco(2,i,k)=tmpy-tmpx
END DO
END DO
END SELECT cambio
END SUBROUTINE ccord
!Translation in order to have 0<=x,y,z<=1
SUBROUTINE zerone(sym_n,not_eq, outco)
IMPLICIT NONE
INTEGER, INTENT(in) :: sym_n,not_eq
REAL(DP), DIMENSION(:,:,:), INTENT(INOUT) :: outco
INTEGER :: i,j, k
DO k=1,not_eq
DO i=1, sym_n
DO j=1,3
!
! bring everything to the -0.5:+0.5 interval
!
outco(j,i,k)=outco(j,i,k)-NINT(outco(j,i,k))
!
! bring everything to positive values
!
IF ( outco(j,i,k) < 0.0_dp ) &
outco(j,i,k)=outco(j,i,k) + 1.0_dp
END DO
END DO
END DO
END SUBROUTINE zerone
SUBROUTINE esclusion(sym_n,not_eq,outco,msym_n)
IMPLICIT NONE
REAL(DP), DIMENSION(:,:,:), INTENT(INOUT) :: outco
INTEGER, DIMENSION (:), INTENT(INOUT) :: msym_n
INTEGER, INTENT(in) :: not_eq, sym_n
INTEGER :: i,l,k,j
REAL(DP), DIMENSION(:,:,:),allocatable :: temp
REAL(DP):: diff(3)
REAL(dp), PARAMETER :: eps6=1.0D-6
LOGICAL :: bol
ALLOCATE(temp(3,sym_n,not_eq))
DO k=1,not_eq
l=0
DO j=1,sym_n
bol=.false.
DO i=j+1,sym_n
diff(:) = outco(:,j,k)-outco(:,i,k)
diff(:) = diff(:) - NINT (diff(:))
IF ( ( ABS(diff(1)) < eps6 ) .AND. &
( ABS(diff(2)) < eps6 ) .AND. &
( ABS(diff(3)) < eps6 ) ) THEN
bol = .true.
ENDIF
END DO
IF (.not.bol) THEN
l=l+1
temp(:,l,k)=outco(:,j,k)
END IF
END DO
msym_n(k)=l
END DO
outco=temp
DEALLOCATE(temp)
RETURN
END SUBROUTINE esclusion
END MODULE wyckoff