Infrastructure for Kpoint symmetries (#3482)

This commit is contained in:
Juerg Hutter 2024-06-18 09:37:39 +02:00 committed by GitHub
parent a391c5a87d
commit 17f893d634
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 3860 additions and 120 deletions

View file

@ -304,6 +304,7 @@ list(
kpoint_methods.F
kpoint_transitional.F
kpoint_types.F
kpsym.F
libgrpp_integrals.F
libint_2c_3c.F
libint_wrapper.F
@ -492,6 +493,7 @@ list(
qs_atomic_block.F
qs_band_structure.F
qs_basis_gradient.F
qs_basis_rotation_methods.F
qs_block_davidson_types.F
qs_cdft_methods.F
qs_cdft_opt_types.F

View file

@ -46,16 +46,15 @@ MODULE orbital_transformation_matrices
TYPE(orbtramat_type), DIMENSION(:), POINTER :: orbtramat => NULL()
TYPE orbrotmat_type
REAL(KIND=dp), DIMENSION(:, :), POINTER :: mat => NULL()
END TYPE orbrotmat_type
INTEGER, SAVE :: current_maxl = -1
! Public variables
PUBLIC :: orbtramat
! Public subroutines
PUBLIC :: deallocate_spherical_harmonics, &
init_spherical_harmonics
PUBLIC :: orbrotmat_type, calculate_rotmat, release_rotmat
PUBLIC :: deallocate_spherical_harmonics, init_spherical_harmonics
CONTAINS
@ -307,6 +306,274 @@ CONTAINS
END SUBROUTINE init_spherical_harmonics
! **************************************************************************************************
!> \brief Calculate rotation matrices for spherical harmonics up to value l
!> Joseph Ivanic and Klaus Ruedenberg
!> Rotation Matrices for Real Spherical Harmonics. Direct Determination by Recursion
!> J. Phys. Chem. 1996, 100, 6342-6347
!> \param orbrotmat ...
!> \param rotmat ...
!> \param lval ...
! **************************************************************************************************
SUBROUTINE calculate_rotmat(orbrotmat, rotmat, lval)
TYPE(orbrotmat_type), DIMENSION(:), POINTER :: orbrotmat
REAL(KIND=dp), DIMENSION(3, 3) :: rotmat
INTEGER, INTENT(IN) :: lval
INTEGER :: l, m1, m2, ns
REAL(KIND=dp) :: s3, u, uf, v, vf, w, wf
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: r
REAL(KIND=dp), DIMENSION(-1:1, -1:1) :: r1
REAL(KIND=dp), DIMENSION(-2:2, -2:2) :: r2
REAL(KIND=dp), DIMENSION(3, 3) :: t
MARK_USED(rotmat)
CALL release_rotmat(orbrotmat)
ALLOCATE (orbrotmat(0:lval))
DO l = 0, lval
ns = nso(l)
ALLOCATE (orbrotmat(l)%mat(ns, ns))
END DO
IF (lval >= 0) THEN
orbrotmat(0)%mat = 1.0_dp
END IF
IF (lval >= 1) THEN
t(1, 1:3) = rotmat(2, 1:3)
t(2, 1:3) = rotmat(3, 1:3)
t(3, 1:3) = rotmat(1, 1:3)
r1(-1:1, -1) = t(1:3, 2)
r1(-1:1, 0) = t(1:3, 3)
r1(-1:1, 1) = t(1:3, 1)
orbrotmat(1)%mat(1:3, 1:3) = r1(-1:1, -1:1)
END IF
IF (lval >= 2) THEN
s3 = SQRT(3.0_dp)
! Table 4
r2(0, 0) = (3.0_dp*r1(0, 0)**2 - 1.0_dp)*0.5_dp
r2(0, 1) = s3*r1(0, 1)*r1(0, 0)
r2(0, -1) = s3*r1(0, -1)*r1(0, 0)
r2(0, -2) = s3*(r1(0, 1)**2 - r1(0, -1)**2)*0.5_dp
r2(0, -2) = s3*r1(0, 1)*r1(0, -1)
!
r2(1, 0) = s3*r1(1, 0)*r1(0, 0)
r2(1, 1) = r1(1, 1)*r1(0, 0) + r1(1, 0)*r1(0, 1)
r2(1, -1) = r1(1, -1)*r1(0, 0) + r1(1, 0)*r1(0, -1)
r2(1, 2) = r1(1, 1)*r1(0, 1) - r1(1, -1)*r1(0, -1)
r2(1, -2) = r1(1, 1)*r1(0, -1) + r1(1, -1)*r1(0, 1)
!
r2(-1, 0) = s3*r1(-1, 0)*r1(0, 0)
r2(-1, 1) = r1(-1, 1)*r1(0, 0) + r1(-1, 0)*r1(0, 1)
r2(-1, -1) = r1(-1, -1)*r1(0, 0) + r1(-1, 0)*r1(0, -1)
r2(-1, 2) = r1(-1, 1)*r1(0, 1) - r1(-1, -1)*r1(0, -1)
r2(-1, -2) = r1(-1, 1)*r1(0, -1) + r1(-1, -1)*r1(0, 1)
!
r2(2, 0) = s3*(r1(1, 0)**2 - r1(-1, 0)**2)*0.5_dp
r2(2, 1) = r1(1, 1)*r1(1, 0) - r1(-1, 1)*r1(-1, 0)
r2(2, -1) = r1(1, -1)*r1(1, 0) - r1(-1, -1)*r1(-1, 0)
r2(2, 2) = (r1(1, 1)**2 - r1(1, -1)**2 - r1(-1, 1)**2 + r1(-1, -1)**2)*0.5_dp
r2(2, -2) = r1(1, 1)*r1(1, -1) - r1(-1, 1)*r1(-1, -1)
!
r2(-2, 0) = s3*r1(1, 0)*r1(-1, 0)
r2(2, 1) = r1(1, 1)*r1(-1, 0) + r1(1, 0)*r1(-1, 1)
r2(2, -1) = r1(1, -1)*r1(-1, 0) + r1(1, 0)*r1(-1, -1)
r2(2, 2) = r1(1, 1)*r1(-1, 1) - r1(1, -1)*r1(-1, -1)
r2(2, -2) = r1(1, 1)*r1(-1, -1) + r1(1, -1)*r1(-1, 1)
!
orbrotmat(2)%mat(1:5, 1:5) = r2(-2:2, -2:2)
END IF
IF (lval >= 3) THEN
! General recursion
ALLOCATE (r(0:lval, -lval:lval, -lval:lval))
r = 0.0_dp
r(0, 0, 0) = 1.0_dp
r(1, -1:1, -1:1) = r1(-1:1, -1:1)
r(2, -2:2, -2:2) = r2(-2:2, -2:2)
DO l = 3, lval
DO m1 = -l, l
DO m2 = -l, l
u = u_func(l, m1, m2)
v = v_func(l, m1, m2)
w = w_func(l, m1, m2)
CALL r_recursion(l, m1, m2, r1, r, lval, uf, vf, wf)
r(l, m1, m2) = u*uf + v*vf + w*wf
END DO
END DO
END DO
DO l = 3, lval
ns = nso(l)
orbrotmat(l)%mat(1:ns, 1:ns) = r(l, -l:l, -l:l)
END DO
DEALLOCATE (r)
END IF
END SUBROUTINE calculate_rotmat
! **************************************************************************************************
!> \brief ...
!> \param l ...
!> \param ma ...
!> \param mb ...
!> \return ...
! **************************************************************************************************
FUNCTION u_func(l, ma, mb) RESULT(u)
INTEGER :: l, ma, mb
REAL(KIND=dp) :: u
IF (ABS(mb) == l) THEN
u = REAL((l + ma)*(l - ma), KIND=dp)/REAL(2*l*(2*l - 1), KIND=dp)
u = SQRT(u)
ELSE IF (ABS(mb) < l) THEN
u = REAL((l + ma)*(l - ma), KIND=dp)/REAL((l + mb)*(l - mb), KIND=dp)
u = SQRT(u)
ELSE
CPABORT("Illegal m value")
END IF
END FUNCTION u_func
! **************************************************************************************************
!> \brief ...
!> \param l ...
!> \param ma ...
!> \param mb ...
!> \return ...
! **************************************************************************************************
FUNCTION v_func(l, ma, mb) RESULT(v)
INTEGER :: l, ma, mb
REAL(KIND=dp) :: v
INTEGER :: a1, a2, dm0
dm0 = 0
IF (ma == 0) dm0 = 1
IF (ABS(mb) == l) THEN
a1 = (1 + dm0)*(l + ABS(ma) - 1)*(l + ABS(ma))
a2 = 2*l*(2*l - 1)
ELSE IF (ABS(mb) < l) THEN
a1 = (1 + dm0)*(l + ABS(ma) - 1)*(l + ABS(ma))
a2 = (l + mb)*(l - mb)
ELSE
CPABORT("Illegal m value")
END IF
v = 0.5_dp*SQRT(REAL(a1, KIND=dp)/REAL(a2, KIND=dp))*REAL(1 - 2*dm0, KIND=dp)
END FUNCTION v_func
! **************************************************************************************************
!> \brief ...
!> \param l ...
!> \param ma ...
!> \param mb ...
!> \return ...
! **************************************************************************************************
FUNCTION w_func(l, ma, mb) RESULT(w)
INTEGER :: l, ma, mb
REAL(KIND=dp) :: w
INTEGER :: a1, a2, dm0
dm0 = 0
IF (ma == 0) dm0 = 1
IF (ABS(mb) == l) THEN
a1 = (l - ABS(ma) - 1)*(l - ABS(ma))
a2 = 2*l*(2*l - 1)
ELSE IF (ABS(mb) < l) THEN
a1 = (l - ABS(ma) - 1)*(l - ABS(ma))
a2 = (l + mb)*(l - mb)
ELSE
CPABORT("Illegal m value")
END IF
w = -0.5_dp*SQRT(REAL(a1, KIND=dp)/REAL(a2, KIND=dp))*REAL(1 - dm0, KIND=dp)
END FUNCTION w_func
! **************************************************************************************************
!> \brief ...
!> \param i ...
!> \param l ...
!> \param mu ...
!> \param m ...
!> \param r1 ...
!> \param r ...
!> \param lr ...
!> \return ...
! **************************************************************************************************
FUNCTION p_func(i, l, mu, m, r1, r, lr) RESULT(p)
INTEGER :: i, l, mu, m
REAL(KIND=dp), DIMENSION(-1:1, -1:1) :: r1
INTEGER :: lr
REAL(KIND=dp), DIMENSION(0:lr, -lr:lr, -lr:lr) :: r
REAL(KIND=dp) :: p
IF (m == l) THEN
p = r1(i, 1)*r(l - 1, mu, m) - r1(i, -1)*r(l - 1, mu, -m)
ELSE IF (m == -l) THEN
p = r1(i, 1)*r(l - 1, mu, m) + r1(i, -1)*r(l - 1, mu, -m)
ELSE IF (ABS(m) < l) THEN
p = r1(i, 0)*r(l - 1, mu, m)
ELSE
CPABORT("Illegal m value")
END IF
END FUNCTION p_func
! **************************************************************************************************
!> \brief ...
!> \param l ...
!> \param ma ...
!> \param mb ...
!> \param r1 ...
!> \param r ...
!> \param lr ...
!> \param u ...
!> \param v ...
!> \param w ...
! **************************************************************************************************
SUBROUTINE r_recursion(l, ma, mb, r1, r, lr, u, v, w)
INTEGER :: l, ma, mb
REAL(KIND=dp), DIMENSION(-1:1, -1:1) :: r1
INTEGER :: lr
REAL(KIND=dp), DIMENSION(0:lr, -lr:lr, -lr:lr) :: r
REAL(KIND=dp) :: u, v, w
REAL(KIND=dp) :: dd
IF (ma == 0) THEN
u = p_func(0, l, 0, mb, r1, r, lr)
v = p_func(1, l, 1, mb, r1, r, lr) + p_func(-1, l, -1, mb, r1, r, lr)
w = 0.0_dp
ELSE IF (ma > 0) THEN
dd = 1.0_dp
IF (ma == 1) dd = 1.0_dp
u = p_func(0, l, ma, mb, r1, r, lr)
v = p_func(1, l, ma - 1, mb, r1, r, lr)*SQRT(1.0_dp + dd) - p_func(-1, l, -ma + 1, mb, r1, r, lr)*(1.0_dp - dd)
w = p_func(1, l, ma + 1, mb, r1, r, lr) + p_func(-1, l, -1 - ma, mb, r1, r, lr)
ELSE IF (ma < 0) THEN
dd = 1.0_dp
IF (ma == -1) dd = 1.0_dp
u = p_func(0, l, ma, mb, r1, r, lr)
v = p_func(1, l, ma + 1, mb, r1, r, lr)*(1.0_dp - dd) + p_func(-1, l, -ma - 1, mb, r1, r, lr)*SQRT(1.0_dp + dd)
w = p_func(1, l, ma - 1, mb, r1, r, lr) - p_func(-1, l, -ma + 1, mb, r1, r, lr)
END IF
END SUBROUTINE
! **************************************************************************************************
!> \brief Release rotation matrices
!> \param orbrotmat ...
! **************************************************************************************************
SUBROUTINE release_rotmat(orbrotmat)
TYPE(orbrotmat_type), DIMENSION(:), POINTER :: orbrotmat
INTEGER :: i
IF (ASSOCIATED(orbrotmat)) THEN
DO i = LBOUND(orbrotmat, 1), UBOUND(orbrotmat, 1)
IF (ASSOCIATED(orbrotmat(i)%mat)) DEALLOCATE (orbrotmat(i)%mat)
END DO
DEALLOCATE (orbrotmat)
END IF
END SUBROUTINE release_rotmat
! **************************************************************************************************
!> \brief Print a matrix to the logical unit "lunit".
!> \param matrix ...

View file

@ -14,17 +14,23 @@ MODULE cryssym
USE bibliography, ONLY: Togo2018,&
cite_reference
USE kinds, ONLY: dp
USE spglib_f08, ONLY: &
spg_get_international, spg_get_ir_reciprocal_mesh, spg_get_major_version, &
spg_get_micro_version, spg_get_minor_version, spg_get_multiplicity, spg_get_pointgroup, &
spg_get_schoenflies, spg_get_symmetry
USE kpsym, ONLY: group1s,&
k290s
USE spglib_f08, ONLY: spg_get_international,&
spg_get_major_version,&
spg_get_micro_version,&
spg_get_minor_version,&
spg_get_multiplicity,&
spg_get_pointgroup,&
spg_get_schoenflies,&
spg_get_symmetry
USE string_utilities, ONLY: strip_control_codes
#include "./base/base_uses.f90"
IMPLICIT NONE
PRIVATE
PUBLIC :: csym_type, release_csym_type, print_crys_symmetry, print_kp_symmetry
PUBLIC :: crys_sym_gen, kpoint_gen, apply_rotation_coord
PUBLIC :: crys_sym_gen, kpoint_gen
CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cryssym'
@ -60,6 +66,12 @@ MODULE cryssym
INTEGER :: n_operations = 0
INTEGER, DIMENSION(:, :, :), ALLOCATABLE :: rotations
REAL(KIND=dp), DIMENSION(:, :), ALLOCATABLE :: translations
!K290
REAL(KIND=dp), DIMENSION(3, 3, 48) :: rt = 0.0_dp
REAL(KIND=dp), DIMENSION(3, 48) :: vt = 0.0_dp
INTEGER, ALLOCATABLE, DIMENSION(:, :) :: f0
INTEGER :: nrtot = 0
INTEGER, DIMENSION(48) :: ibrot = 1
END TYPE csym_type
CONTAINS
@ -98,6 +110,9 @@ CONTAINS
IF (ALLOCATED(csym%kpop)) THEN
DEALLOCATE (csym%kpop)
END IF
IF (ALLOCATED(csym%f0)) THEN
DEALLOCATE (csym%f0)
END IF
END SUBROUTINE release_csym_type
@ -214,14 +229,11 @@ CONTAINS
CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_gen'
INTEGER :: handle, i, ik, is_shift(3), &
is_time_reversal, j, nkp, nkpts
INTEGER, ALLOCATABLE, DIMENSION(:) :: iwkp, xptr
INTEGER, ALLOCATABLE, DIMENSION(:, :) :: ixkp
INTEGER :: handle, i, ik, j, nkp, nkpts
INTEGER, ALLOCATABLE, DIMENSION(:) :: kpop, xptr
LOGICAL :: fullmesh
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: wkp
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: xkp
REAL(KIND=dp), DIMENSION(3) :: rxkp
CALL timeset(routineN, handle)
@ -247,7 +259,7 @@ CONTAINS
csym%mesh(1:3) = nk(1:3)
nkpts = nk(1)*nk(2)*nk(3)
ALLOCATE (xkp(3, nkpts), wkp(nkpts))
ALLOCATE (xkp(3, nkpts), wkp(nkpts), kpop(nkpts))
! kp: link
ALLOCATE (csym%kplink(2, nkpts))
csym%kplink = 0
@ -274,20 +286,10 @@ CONTAINS
CALL cp_abort(__LOCATION__, "MacDonald shifted k-point meshes are only "// &
"possible without symmetrization.")
END IF
ALLOCATE (ixkp(3, nkpts), iwkp(nkpts))
is_shift(1:3) = MOD(nk(1:3) + 1, 2)
is_time_reversal = 1
nkp = spg_get_ir_reciprocal_mesh(ixkp, iwkp, nk, is_shift, is_time_reversal, &
TRANSPOSE(csym%hmat), csym%scoord, csym%atype, &
csym%nat, csym%delta)
wkp = 0.0_dp
DO i = 1, nkpts
xkp(:, i) = REAL(is_shift + 2*ixkp(:, i), KIND=dp)/REAL(2*nk(:), KIND=dp)
j = iwkp(i) + 1
wkp(j) = wkp(j) + 1.0_dp
END DO
csym%kplink(1, 1:nkpts) = iwkp(1:nkpts) + 1
DEALLOCATE (ixkp, iwkp)
CALL full_grid_gen(nk, xkp, wkp, shift)
CALL kp_symmetry(csym, xkp, wkp, kpop)
END IF
ELSE
! no symmetry library is available
@ -343,24 +345,9 @@ CONTAINS
ALLOCATE (csym%kpop(nkpts))
IF (csym%symlib .AND. csym%istriz == 1 .AND. .NOT. fullmesh) THEN
! atomic symmetry operations possible
csym%kpop(1:nkpts) = kpop(1:nkpts)
DO ik = 1, nkpts
IF (wkp(ik) > 0.0_dp) THEN
csym%kpop(ik) = 1
ELSE
csym%kpop(ik) = 0
j = csym%kplink(2, ik)
DO i = 1, csym%n_operations
IF (SUM(ABS(csym%translations(:, i))) > 1.e-10_dp) CYCLE
rxkp(1:3) = kp_apply_operation(csym%xkpoint(1:3, j), csym%rotations(:, :, i))
rxkp(1:3) = ABS(xkp(1:3, ik) - rxkp(1:3))
rxkp(1:3) = rxkp(1:3) - REAL(NINT(rxkp(1:3)), KIND=dp)
IF (ALL((rxkp(1:3)) < 1.e-12_dp)) THEN
csym%kpop(ik) = i
EXIT
END IF
END DO
CPASSERT(csym%kpop(ik) /= 0)
END IF
CPASSERT(csym%kpop(ik) /= 0)
END DO
ELSE
! only time reversal symmetry
@ -373,7 +360,7 @@ CONTAINS
END DO
END IF
DEALLOCATE (xkp, wkp)
DEALLOCATE (xkp, wkp, kpop)
CALL timestop(handle)
@ -381,6 +368,128 @@ CONTAINS
! **************************************************************************************************
!> \brief ...
!> \param csym ...
!> \param xkp ...
!> \param wkp ...
!> \param kpop ...
! **************************************************************************************************
SUBROUTINE kp_symmetry(csym, xkp, wkp, kpop)
TYPE(csym_type) :: csym
REAL(KIND=dp), DIMENSION(:, :) :: xkp
REAL(KIND=dp), DIMENSION(:) :: wkp
INTEGER, DIMENSION(:) :: kpop
INTEGER :: i, ihc, ihg, ik, indpg, iou, iq1, iq2, &
iq3, istriz, isy, itoj, j, kr, li, lr, &
nat, nc, nhash, nkm, nkp, nkpoint, &
nsp, ntvec
INTEGER, ALLOCATABLE, DIMENSION(:) :: includ, isc, list, lwght, ty
INTEGER, ALLOCATABLE, DIMENSION(:, :) :: f0, lrot
INTEGER, DIMENSION(48) :: ib
REAL(KIND=dp) :: alat
REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: rlist, rx, tvec, wvkl, xkapa
REAL(KIND=dp), DIMENSION(3) :: a1, a2, a3, b1, b2, b3, origin, rr, wvk0
REAL(KIND=dp), DIMENSION(3, 3) :: hmat, strain
REAL(KIND=dp), DIMENSION(3, 3, 48) :: r
REAL(KIND=dp), DIMENSION(3, 48) :: vt
iou = csym%punit
hmat = csym%hmat
nat = csym%nat
iq1 = csym%mesh(1)
iq2 = csym%mesh(2)
iq3 = csym%mesh(3)
nkpoint = 10*iq1*iq2*iq3
nkpoint = 2*MAX(iq1, iq2, iq3)**3
wvk0 = csym%wvk0
istriz = csym%istriz
a1(1:3) = hmat(1:3, 1)
a2(1:3) = hmat(1:3, 2)
a3(1:3) = hmat(1:3, 3)
alat = hmat(1, 1)
strain = 0.0_dp
ALLOCATE (xkapa(3, nat), rx(3, nat), tvec(3, 200), ty(nat), isc(nat), f0(49, nat))
ty(1:nat) = csym%atype(1:nat)
nsp = MAXVAL(ty)
DO i = 1, nat
xkapa(1:3, i) = MATMUL(hmat, csym%scoord(1:3, i))
END DO
nhash = 1000
ALLOCATE (wvkl(3, nkpoint), rlist(3, nkpoint), includ(nkpoint), list(nhash + nkpoint))
ALLOCATE (lrot(48, nkpoint), lwght(nkpoint))
IF (iou > 0) THEN
WRITE (iou, '(/,(T2,A79))') &
"*******************************************************************************", &
"** Special K-Point Generation by K290 **", &
"*******************************************************************************"
END IF
CALL K290s(iou, nat, nkpoint, nsp, iq1, iq2, iq3, istriz, &
a1, a2, a3, alat, strain, xkapa, rx, tvec, &
ty, isc, f0, ntvec, wvk0, wvkl, lwght, lrot, &
nhash, includ, list, rlist, csym%delta)
CALL GROUP1s(0, a1, a2, a3, nat, ty, xkapa, b1, b2, b3, &
ihg, ihc, isy, li, nc, indpg, ib, ntvec, &
vt, f0, r, tvec, origin, rx, isc, csym%delta)
IF (iou > 0) THEN
WRITE (iou, '((T2,A79))') &
"*******************************************************************************", &
"** Finished K290 **", &
"*******************************************************************************"
END IF
csym%rt = r
csym%vt = vt
csym%nrtot = nc
ALLOCATE (csym%f0(nat, nc))
DO i = 1, nc
csym%f0(1:nat, i) = f0(i, 1:nat)
END DO
csym%ibrot = 0
csym%ibrot(1:nc) = ib(1:nc)
kpop = 0
nkm = iq1*iq2*iq3
nkp = 0
DO i = 1, nkm
IF (lwght(i) == 0) EXIT
nkp = nkp + 1
END DO
wkp = 0
ik = 0
DO i = 1, nkp
DO j = 1, nkm
wvk0(1:3) = xkp(1:3, j) - wvkl(1:3, i)
IF (ALL(ABS(wvk0(1:3)) < 1.e-12_dp)) THEN
wkp(j) = lwght(i)
itoj = j
EXIT
END IF
END DO
DO lr = 1, lwght(i)
kr = lrot(lr, i)
rr(1:3) = kp_apply_operation(wvkl(1:3, i), r(1:3, 1:3, ABS(kr)))
IF (kr < 0) rr(1:3) = -rr(1:3)
DO j = 1, nkm
wvk0(1:3) = xkp(1:3, j) - rr(1:3)
IF (ALL(ABS(wvk0(1:3)) < 1.e-12_dp)) THEN
csym%kplink(1, j) = itoj
kpop(j) = kr
EXIT
END IF
END DO
END DO
END DO
DEALLOCATE (xkapa, rx, tvec, ty, isc, f0)
DEALLOCATE (wvkl, rlist, includ, list)
DEALLOCATE (lrot, lwght)
END SUBROUTINE kp_symmetry
! **************************************************************************************************
!> \brief ...
!> \param nk ...
!> \param xkp ...
!> \param wkp ...
@ -453,55 +562,15 @@ CONTAINS
!> \return ...
! **************************************************************************************************
FUNCTION kp_apply_operation(x, r) RESULT(y)
REAL(KIND=dp), INTENT(IN) :: x(3)
INTEGER, INTENT(IN) :: r(3, 3)
REAL(KIND=dp), INTENT(IN) :: x(3), r(3, 3)
REAL(KIND=dp) :: y(3)
y(1) = REAL(r(1, 1), dp)*x(1) + REAL(r(1, 2), dp)*x(2) + REAL(r(1, 3), dp)*x(3)
y(2) = REAL(r(2, 1), dp)*x(1) + REAL(r(2, 2), dp)*x(2) + REAL(r(2, 3), dp)*x(3)
y(3) = REAL(r(3, 1), dp)*x(1) + REAL(r(3, 2), dp)*x(2) + REAL(r(3, 3), dp)*x(3)
y(1) = r(1, 1)*x(1) + r(1, 2)*x(2) + r(1, 3)*x(3)
y(2) = r(2, 1)*x(1) + r(2, 2)*x(2) + r(2, 3)*x(3)
y(3) = r(3, 1)*x(1) + r(3, 2)*x(2) + r(3, 3)*x(3)
END FUNCTION kp_apply_operation
! **************************************************************************************************
!> \brief ...
!> \param f0 ...
!> \param csym ...
!> \param ir ...
! **************************************************************************************************
SUBROUTINE apply_rotation_coord(f0, csym, ir)
INTEGER, DIMENSION(:), INTENT(INOUT) :: f0
TYPE(csym_type) :: csym
INTEGER, INTENT(IN) :: ir
INTEGER :: ia, ib, natom
REAL(KIND=dp) :: diff
REAL(KIND=dp), DIMENSION(3) :: rb, ri, ro, tr
REAL(KIND=dp), DIMENSION(3, 3) :: rot
natom = csym%nat
rot(1:3, 1:3) = csym%rotations(1:3, 1:3, ir)
tr(1:3) = csym%translations(1:3, ir)
f0 = 0
DO ia = 1, natom
ri(1:3) = csym%scoord(1:3, ia)
ro(1) = REAL(rot(1, 1), dp)*ri(1) + REAL(rot(2, 1), dp)*ri(2) + REAL(rot(3, 1), dp)*ri(3) + tr(1)
ro(2) = REAL(rot(1, 2), dp)*ri(1) + REAL(rot(2, 2), dp)*ri(2) + REAL(rot(3, 2), dp)*ri(3) + tr(2)
ro(3) = REAL(rot(1, 3), dp)*ri(1) + REAL(rot(2, 3), dp)*ri(2) + REAL(rot(3, 3), dp)*ri(3) + tr(3)
DO ib = 1, natom
rb(1:3) = csym%scoord(1:3, ib)
diff = SQRT(SUM((ri(:) - rb(:))**2))
IF (diff < csym%delta) THEN
f0(ia) = ib
EXIT
END IF
END DO
CPASSERT(f0(ia) /= 0)
END DO
END SUBROUTINE apply_rotation_coord
! **************************************************************************************************
!> \brief ...
!> \param csym ...
@ -542,7 +611,7 @@ CONTAINS
SUBROUTINE print_kp_symmetry(csym)
TYPE(csym_type), INTENT(IN) :: csym
INTEGER :: i, iunit, plevel
INTEGER :: i, iunit, nat, plevel
iunit = csym%punit
IF (iunit >= 0) THEN
@ -559,6 +628,13 @@ CONTAINS
WRITE (iunit, '(T2,i10,3F10.5,T45,3I12)') i, csym%kpmesh(1:3, i), &
csym%kplink(1:2, i), csym%kpop(i)
END DO
IF (csym%nrtot > 0) THEN
WRITE (iunit, '(/,A)') " Atom Transformation Table"
nat = SIZE(csym%f0, 1)
DO i = 1, csym%nrtot
WRITE (iunit, '(T10,A,I3,(T21,12I5))') " Rot=", csym%ibrot(i), csym%f0(1:nat, i)
END DO
END IF
END IF
END SUBROUTINE print_kp_symmetry

View file

@ -36,8 +36,7 @@ MODULE kpoint_methods
copy_info_type, cp_fm_cleanup_copy_general, cp_fm_create, cp_fm_finish_copy_general, &
cp_fm_get_info, cp_fm_release, cp_fm_start_copy_general, cp_fm_to_fm, cp_fm_type
USE cp_log_handling, ONLY: cp_logger_get_default_io_unit
USE cryssym, ONLY: apply_rotation_coord,&
crys_sym_gen,&
USE cryssym, ONLY: crys_sym_gen,&
csym_type,&
kpoint_gen,&
print_crys_symmetry,&
@ -48,6 +47,7 @@ MODULE kpoint_methods
USE input_constants, ONLY: smear_fermi_dirac
USE kinds, ONLY: dp
USE kpoint_types, ONLY: get_kpoint_info,&
kind_rotmat_type,&
kpoint_env_create,&
kpoint_env_p_type,&
kpoint_env_type,&
@ -109,8 +109,8 @@ CONTAINS
CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_initialize'
INTEGER :: handle, i, ik, iounit, ir, is, natom, &
nr, ns
INTEGER :: handle, i, ic, ik, iounit, ir, ira, is, &
j, natom, nkind, nr, ns
INTEGER, ALLOCATABLE, DIMENSION(:) :: atype
LOGICAL :: spez
REAL(KIND=dp) :: wsum
@ -159,6 +159,9 @@ CONTAINS
ELSE
iounit = -1
END IF
! kind type list
ALLOCATE (kpoint%atype(natom))
kpoint%atype = atype
CALL crys_sym_gen(crys_sym, scoord, atype, cell%hmat, delta=kpoint%eps_geo, iounit=iounit)
CALL kpoint_gen(crys_sym, kpoint%nkp_grid, symm=kpoint%symmetry, shift=kpoint%kp_shift, &
@ -185,26 +188,50 @@ CONTAINS
! set up the symmetrization information
kpsym%nwght = NINT(crys_sym%wkpoint(ik))
ns = kpsym%nwght
! to be done correctly
!
IF (ns > 1) THEN
kpsym%apply_symmetry = .TRUE.
natom = SIZE(particle_set)
ALLOCATE (kpsym%rot(3, 3, ns))
ALLOCATE (kpsym%xkp(3, ns))
ALLOCATE (kpsym%rotp(ns))
ALLOCATE (kpsym%f0(natom, ns))
nr = 0
DO is = 1, SIZE(crys_sym%kplink, 2)
IF (crys_sym%kplink(2, is) == ik) THEN
nr = nr + 1
ir = crys_sym%kpop(is)
kpsym%rot(1:3, 1:3, nr) = crys_sym%rotations(1:3, 1:3, ir)
ira = ABS(ir)
kpsym%rotp(nr) = ir
IF (ir > 0) THEN
kpsym%rot(1:3, 1:3, nr) = crys_sym%rt(1:3, 1:3, ira)
ELSE
kpsym%rot(1:3, 1:3, nr) = -crys_sym%rt(1:3, 1:3, ira)
END IF
kpsym%xkp(1:3, nr) = crys_sym%kpmesh(1:3, is)
CALL apply_rotation_coord(kpsym%f0(1:natom, nr), crys_sym, ir)
DO ic = 1, crys_sym%nrtot
IF (crys_sym%ibrot(ic) == ira) THEN
kpsym%f0(1:natom, nr) = crys_sym%f0(1:natom, ic)
EXIT
END IF
END DO
END IF
END DO
! Reduce inversion?
kpsym%nwred = nr
END IF
END IF
END DO
IF (kpoint%symmetry) THEN
nkind = MAXVAL(atype)
ns = crys_sym%nrtot
ALLOCATE (kpoint%kind_rotmat(ns, nkind))
DO i = 1, ns
DO j = 1, nkind
NULLIFY (kpoint%kind_rotmat(i, j)%rmat)
END DO
END DO
END IF
CALL release_csym_type(crys_sym)
DEALLOCATE (scoord, atype)
@ -1125,8 +1152,8 @@ CONTAINS
CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_density_transform'
INTEGER :: handle, ic, ik, ikk, indx, is, ispin, &
nc, nimg, nkp, nspin
INTEGER :: handle, ic, ik, ikk, indx, ir, is, &
ispin, nc, nimg, nkp, nspin
INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
LOGICAL :: aux_fit, do_ext, do_symmetric, my_kpgrp, &
real_only
@ -1136,6 +1163,7 @@ CONTAINS
TYPE(copy_info_type), ALLOCATABLE, DIMENSION(:) :: info
TYPE(cp_fm_type) :: fmdummy
TYPE(dbcsr_type), POINTER :: cpmat, rpmat, scpmat, srpmat
TYPE(kind_rotmat_type), DIMENSION(:), POINTER :: kind_rot
TYPE(kpoint_env_type), POINTER :: kp
TYPE(kpoint_sym_type), POINTER :: kpsym
TYPE(mp_para_env_type), POINTER :: para_env
@ -1162,17 +1190,21 @@ CONTAINS
CALL dbcsr_create(rpmat, template=tempmat, &
matrix_type=MERGE(dbcsr_type_symmetric, dbcsr_type_no_symmetry, do_symmetric))
CALL cp_dbcsr_alloc_block_from_nbl(rpmat, sab_nl)
CALL dbcsr_set(rpmat, 0.0_dp)
ALLOCATE (cpmat)
CALL dbcsr_create(cpmat, template=tempmat, &
matrix_type=MERGE(dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, do_symmetric))
CALL cp_dbcsr_alloc_block_from_nbl(cpmat, sab_nl)
CALL dbcsr_set(cpmat, 0.0_dp)
IF (.NOT. kpoint%full_grid) THEN
ALLOCATE (srpmat)
CALL dbcsr_create(srpmat, template=rpmat)
CALL cp_dbcsr_alloc_block_from_nbl(srpmat, sab_nl)
CALL dbcsr_set(srpmat, 0.0_dp)
ALLOCATE (scpmat)
CALL dbcsr_create(scpmat, template=cpmat)
CALL cp_dbcsr_alloc_block_from_nbl(scpmat, sab_nl)
CALL dbcsr_set(scpmat, 0.0_dp)
END IF
CALL get_kpoint_info(kpoint, nkp=nkp, xkp=xkp, wkp=wkp, &
@ -1259,11 +1291,16 @@ CONTAINS
IF (kpsym%apply_symmetry) THEN
wkpx = wkp(ik)/REAL(kpsym%nwght, KIND=dp)
DO is = 1, kpsym%nwght
ir = ABS(kpsym%rotp(is))
kind_rot => kpoint%kind_rotmat(ir, :)
IF (real_only) THEN
CALL symtrans(srpmat, rpmat, kpsym%rot(1:3, 1:3, is), kpsym%f0(:, is), symmetric=.TRUE.)
CALL symtrans(srpmat, rpmat, kind_rot, kpsym%rot(1:3, 1:3, is), &
kpsym%f0(:, is), kpoint%atype, symmetric=.TRUE.)
ELSE
CALL symtrans(srpmat, rpmat, kpsym%rot(1:3, 1:3, is), kpsym%f0(:, is), symmetric=.TRUE.)
CALL symtrans(scpmat, cpmat, kpsym%rot(1:3, 1:3, is), kpsym%f0(:, is), antisymmetric=.TRUE.)
CALL symtrans(srpmat, rpmat, kind_rot, kpsym%rot(1:3, 1:3, is), &
kpsym%f0(:, is), kpoint%atype, symmetric=.TRUE.)
CALL symtrans(scpmat, cpmat, kind_rot, kpsym%rot(1:3, 1:3, is), &
kpsym%f0(:, is), kpoint%atype, antisymmetric=.TRUE.)
END IF
CALL transform_dmat(denmat, srpmat, scpmat, ispin, real_only, sab_nl, &
cell_to_index, kpsym%xkp(1:3, is), wkpx)
@ -1363,7 +1400,7 @@ CONTAINS
!We have a FT from KP to real-space: S(R) = sum_k S(k)*exp(-i*k*R), with S(k) a complex number
!Therefore, we have: S(R) = sum_k Re(S(k))*cos(k*R) -i^2*Im(S(k))*sin(k*R)
! = sum_k Re(S(k))*cos(k*R) + Im(S(k))*sin(k*R)
!fc = +- 1 is due to the usual non-symmetric real-sapce matrices stored as symmetric ones
!fc = +- 1 is due to the usual non-symmetric real-space matrices stored as symmetric ones
irow = iatom
icol = jatom
@ -1408,24 +1445,27 @@ CONTAINS
!> \brief Symmetrization of density matrix - transform to new k-point
!> \param smat density matrix at new kpoint
!> \param pmat reference density matrix
!> \param kmat Kind type rotation matrix
!> \param rot Rotation matrix
!> \param f0 Permutation of atoms under transformation
!> \param atype Atom to kind pointer
!> \param symmetric Symmetric matrix
!> \param antisymmetric Anti-Symmetric matrix
! **************************************************************************************************
SUBROUTINE symtrans(smat, pmat, rot, f0, symmetric, antisymmetric)
SUBROUTINE symtrans(smat, pmat, kmat, rot, f0, atype, symmetric, antisymmetric)
TYPE(dbcsr_type), POINTER :: smat, pmat
TYPE(kind_rotmat_type), DIMENSION(:), POINTER :: kmat
REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN) :: rot
INTEGER, DIMENSION(:), INTENT(IN) :: f0
INTEGER, DIMENSION(:), INTENT(IN) :: f0, atype
LOGICAL, INTENT(IN), OPTIONAL :: symmetric, antisymmetric
CHARACTER(LEN=*), PARAMETER :: routineN = 'symtrans'
INTEGER :: handle, iatom, icol, ip, irow, jcol, jp, &
jrow, natom, numnodes
INTEGER :: handle, iatom, icol, ikind, ip, irow, &
jcol, jkind, jp, jrow, natom, numnodes
LOGICAL :: asym, dorot, found, perm, sym, trans
REAL(KIND=dp) :: dr, fsign
REAL(KIND=dp), DIMENSION(:, :), POINTER :: pblock, sblock
REAL(KIND=dp), DIMENSION(:, :), POINTER :: kroti, krotj, pblock, sblock
TYPE(dbcsr_distribution_type) :: dist
TYPE(dbcsr_iterator_type) :: iter
@ -1459,6 +1499,8 @@ CONTAINS
IF (asym) fsign = -1.0_dp
IF (dorot .OR. perm) THEN
CALL cp_abort(__LOCATION__, "k-points need FULL_GRID currently. "// &
"Reduced grids not yet working correctly")
CALL dbcsr_set(smat, 0.0_dp)
IF (perm) THEN
CALL dbcsr_get_info(pmat, distribution=dist)
@ -1480,11 +1522,16 @@ CONTAINS
trans = .TRUE.
END IF
CALL dbcsr_get_block_p(matrix=smat, row=jrow, col=jcol, BLOCK=sblock, found=found)
IF (.NOT. found) CYCLE
CPASSERT(found)
ikind = atype(irow)
jkind = atype(icol)
kroti => kmat(ikind)%rmat
krotj => kmat(jkind)%rmat
! rotation
IF (trans) THEN
sblock = fsign*TRANSPOSE(pblock)
sblock = fsign*MATMUL(TRANSPOSE(krotj), MATMUL(TRANSPOSE(pblock), kroti))
ELSE
sblock = pblock
sblock = fsign*MATMUL(TRANSPOSE(kroti), MATMUL(pblock, krotj))
END IF
END DO
CALL dbcsr_iterator_stop(iter)
@ -1496,10 +1543,34 @@ CONTAINS
END IF
ELSE
! no atom permutations, this is always local
! ignore rotations for now
CALL dbcsr_copy(smat, pmat)
CALL cp_abort(__LOCATION__, "k-points need FULL_GRID currently. "// &
"Reduced grids not yet working correctly")
CALL dbcsr_iterator_start(iter, smat)
DO WHILE (dbcsr_iterator_blocks_left(iter))
CALL dbcsr_iterator_next_block(iter, irow, icol, sblock)
ip = f0(irow)
jp = f0(icol)
IF (ip <= jp) THEN
jrow = ip
jcol = jp
trans = .FALSE.
ELSE
jrow = jp
jcol = ip
trans = .TRUE.
END IF
ikind = atype(irow)
jkind = atype(icol)
kroti => kmat(ikind)%rmat
krotj => kmat(jkind)%rmat
! rotation
IF (trans) THEN
sblock = fsign*MATMUL(TRANSPOSE(krotj), MATMUL(TRANSPOSE(sblock), kroti))
ELSE
sblock = fsign*MATMUL(TRANSPOSE(kroti), MATMUL(sblock, krotj))
END IF
END DO
CALL dbcsr_iterator_stop(iter)
!
END IF
ELSE
! this is the identity operation, just copy the matrix

View file

@ -53,6 +53,7 @@ MODULE kpoint_types
PUBLIC :: read_kpoint_section, write_kpoint_info
PUBLIC :: kpoint_env_type, kpoint_env_p_type
PUBLIC :: kpoint_env_create, get_kpoint_env
PUBLIC :: kind_rotmat_type
PUBLIC :: kpoint_sym_type
PUBLIC :: kpoint_sym_create
@ -85,6 +86,15 @@ MODULE kpoint_types
TYPE(kpoint_env_type), POINTER :: kpoint_env => NULL()
END TYPE kpoint_env_p_type
! **************************************************************************************************
!> \brief Rotation matrices for basis sets
!> \param rmat atom basis function rotation matrix
!> \author JGH
! **************************************************************************************************
TYPE kind_rotmat_type
REAL(KIND=dp), DIMENSION(:, :), POINTER :: rmat
END TYPE kind_rotmat_type
! **************************************************************************************************
!> \brief Keeps symmetry information about a specific k-point
!> \param apply_symmetry ...
@ -97,8 +107,10 @@ MODULE kpoint_types
TYPE kpoint_sym_type
LOGICAL :: apply_symmetry = .FALSE.
INTEGER :: nwght = -1
INTEGER :: nwred = -1
REAL(KIND=dp), DIMENSION(:, :), POINTER :: xkp => NULL()
REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: rot => NULL()
INTEGER, DIMENSION(:), POINTER :: rotp => NULL()
INTEGER, DIMENSION(:, :), POINTER :: f0 => NULL()
END TYPE kpoint_sym_type
@ -168,8 +180,13 @@ MODULE kpoint_types
POINTER :: kp_env => Null()
TYPE(kpoint_env_p_type), DIMENSION(:), &
POINTER :: kp_aux_env => Null()
! symmetry
TYPE(kpoint_sym_p_type), DIMENSION(:), &
POINTER :: kp_sym => Null()
INTEGER, DIMENSION(:), POINTER :: atype => Null()
TYPE(kind_rotmat_type), DIMENSION(:, :), &
POINTER :: kind_rotmat => Null()
! pools
TYPE(qs_matrix_pools_type), POINTER :: mpools => Null()
TYPE(qs_diis_buffer_type_kp), POINTER :: scf_diis_buffer => Null()
TYPE(qs_matrix_pools_type), POINTER :: mpools_aux_fit => Null()
@ -233,7 +250,7 @@ CONTAINS
SUBROUTINE kpoint_release(kpoint)
TYPE(kpoint_type), POINTER :: kpoint
INTEGER :: ik
INTEGER :: i, ik, j
IF (ASSOCIATED(kpoint)) THEN
@ -281,6 +298,19 @@ CONTAINS
DEALLOCATE (kpoint%kp_sym)
END IF
IF (ASSOCIATED(kpoint%atype)) DEALLOCATE (kpoint%atype)
IF (ASSOCIATED(kpoint%kind_rotmat)) THEN
DO i = 1, SIZE(kpoint%kind_rotmat, 1)
DO j = 1, SIZE(kpoint%kind_rotmat, 2)
IF (ASSOCIATED(kpoint%kind_rotmat(i, j)%rmat)) THEN
DEALLOCATE (kpoint%kind_rotmat(i, j)%rmat)
END IF
END DO
END DO
DEALLOCATE (kpoint%kind_rotmat)
END IF
IF (ASSOCIATED(kpoint%scf_diis_buffer)) THEN
CALL qs_diis_b_release_kp(kpoint%scf_diis_buffer)
DEALLOCATE (kpoint%scf_diis_buffer)
@ -773,10 +803,12 @@ CONTAINS
ALLOCATE (kp_sym)
kp_sym%nwght = 0
kp_sym%nwred = 0
kp_sym%apply_symmetry = .FALSE.
NULLIFY (kp_sym%rot)
NULLIFY (kp_sym%xkp)
NULLIFY (kp_sym%rotp)
NULLIFY (kp_sym%f0)
END SUBROUTINE kpoint_sym_create
@ -800,6 +832,9 @@ CONTAINS
IF (ASSOCIATED(kp_sym%f0)) THEN
DEALLOCATE (kp_sym%f0)
END IF
IF (ASSOCIATED(kp_sym%rotp)) THEN
DEALLOCATE (kp_sym%rotp)
END IF
DEALLOCATE (kp_sym)

3070
src/kpsym.F Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,145 @@
!--------------------------------------------------------------------------------------------------!
! CP2K: A general program to perform molecular dynamics simulations !
! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
! !
! SPDX-License-Identifier: GPL-2.0-or-later !
!--------------------------------------------------------------------------------------------------!
! **************************************************************************************************
MODULE qs_basis_rotation_methods
USE basis_set_types, ONLY: get_gto_basis_set,&
gto_basis_set_type
USE cell_types, ONLY: cell_type
USE cp_control_types, ONLY: dft_control_type
USE input_constants, ONLY: do_method_dftb
USE kinds, ONLY: dp
USE kpoint_types, ONLY: kpoint_sym_type,&
kpoint_type
USE orbital_pointers, ONLY: nso
USE orbital_transformation_matrices, ONLY: calculate_rotmat,&
orbrotmat_type,&
release_rotmat
USE qs_environment_types, ONLY: get_qs_env,&
qs_environment_type
USE qs_kind_types, ONLY: get_qs_kind,&
get_qs_kind_set,&
qs_kind_type
#include "./base/base_uses.f90"
IMPLICIT NONE
PRIVATE
! Global parameters (only in this module)
CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_basis_rotation_methods'
! Public subroutines
PUBLIC :: qs_basis_rotation
CONTAINS
! **************************************************************************************************
!> \brief Construct basis set rotation matrices
!> \param qs_env ...
!> \param kpoints ...
! **************************************************************************************************
SUBROUTINE qs_basis_rotation(qs_env, kpoints)
TYPE(qs_environment_type), POINTER :: qs_env
TYPE(kpoint_type), POINTER :: kpoints
INTEGER :: ik, ikind, ir, ira, irot, lval, nkind, &
nrot
REAL(KIND=dp), DIMENSION(3, 3) :: rotmat
TYPE(cell_type), POINTER :: cell
TYPE(dft_control_type), POINTER :: dft_control
TYPE(gto_basis_set_type), POINTER :: orb_basis
TYPE(kpoint_sym_type), POINTER :: kpsym
TYPE(orbrotmat_type), DIMENSION(:), POINTER :: orbrot
TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
CPASSERT(ASSOCIATED(qs_env))
CPASSERT(ASSOCIATED(kpoints))
IF (ASSOCIATED(kpoints%kind_rotmat)) THEN
CALL get_qs_env(qs_env, cell=cell)
CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set)
CALL get_qs_kind_set(qs_kind_set, maxlgto=lval)
nrot = SIZE(kpoints%kind_rotmat, 1)
nkind = SIZE(kpoints%kind_rotmat, 2)
! remove possible old rotation matrices
DO irot = 1, nrot
DO ikind = 1, nkind
IF (ASSOCIATED(kpoints%kind_rotmat(irot, ikind)%rmat)) THEN
DEALLOCATE (kpoints%kind_rotmat(irot, ikind)%rmat)
END IF
END DO
END DO
! check all rotations needed
NULLIFY (orbrot)
CALL get_qs_env(qs_env, dft_control=dft_control)
DO ik = 1, kpoints%nkp
kpsym => kpoints%kp_sym(ik)%kpoint_sym
IF (kpsym%apply_symmetry) THEN
DO irot = 1, SIZE(kpsym%rotp)
ir = kpsym%rotp(irot)
ira = ABS(ir)
IF (ira > 0 .AND. ira <= nrot) THEN
IF (.NOT. ASSOCIATED(kpoints%kind_rotmat(ira, 1)%rmat)) THEN
rotmat(1:3, 1:3) = MATMUL(cell%h_inv, &
MATMUL(kpsym%rot(:, :, irot), cell%hmat))
NULLIFY (orbrot)
CALL calculate_rotmat(orbrot, rotmat, lval)
IF (dft_control%qs_control%method_id == do_method_dftb) THEN
CPABORT("ROTMAT")
ELSE
DO ikind = 1, nkind
CALL get_qs_kind(qs_kind_set(ikind), basis_set=orb_basis)
NULLIFY (kpoints%kind_rotmat(ira, ikind)%rmat)
CALL set_rotmat_basis(kpoints%kind_rotmat(ira, ikind)%rmat, orbrot, orb_basis)
END DO
END IF
END IF
END IF
END DO
END IF
END DO
CALL release_rotmat(orbrot)
END IF
END SUBROUTINE qs_basis_rotation
! **************************************************************************************************
!> \brief ...
!> \param rmat ...
!> \param orbrot ...
!> \param basis ...
! **************************************************************************************************
SUBROUTINE set_rotmat_basis(rmat, orbrot, basis)
REAL(KIND=dp), DIMENSION(:, :), POINTER :: rmat
TYPE(orbrotmat_type), DIMENSION(:), POINTER :: orbrot
TYPE(gto_basis_set_type), POINTER :: basis
INTEGER :: fs1, fs2, iset, ishell, l, nset, nsgf
INTEGER, DIMENSION(:), POINTER :: nshell
INTEGER, DIMENSION(:, :), POINTER :: first_sgf, lshell
CALL get_gto_basis_set(gto_basis_set=basis, nsgf=nsgf)
ALLOCATE (rmat(nsgf, nsgf))
rmat = 0.0_dp
CALL get_gto_basis_set(gto_basis_set=basis, nset=nset, nshell=nshell, l=lshell, &
first_sgf=first_sgf)
DO iset = 1, nset
DO ishell = 1, nshell(iset)
l = lshell(ishell, iset)
fs1 = first_sgf(ishell, iset)
fs2 = fs1 + nso(l) - 1
rmat(fs1:fs2, fs1:fs2) = orbrot(l)%mat(1:nso(l), 1:nso(l))
END DO
END DO
END SUBROUTINE set_rotmat_basis
END MODULE qs_basis_rotation_methods

View file

@ -132,6 +132,7 @@ MODULE qs_environment
USE particle_types, ONLY: particle_type
USE pw_env_types, ONLY: pw_env_type
USE qmmm_types_low, ONLY: qmmm_env_qm_type
USE qs_basis_rotation_methods, ONLY: qs_basis_rotation
USE qs_dftb_parameters, ONLY: qs_dftb_param_init
USE qs_dftb_types, ONLY: qs_dftb_pairpot_type
USE qs_dispersion_nonloc, ONLY: qs_dispersion_nonloc_init
@ -391,6 +392,10 @@ CONTAINS
CALL get_qs_env(qs_env=qs_env, wf_history=wf_history)
CALL wfi_create_for_kp(wf_history)
END IF
! basis set symmetry rotations
IF (do_kpoints) THEN
CALL qs_basis_rotation(qs_env, kpoints)
END IF
do_hfx = .FALSE.
hfx_section => section_vals_get_subs_vals(qs_env%input, "DFT%XC%HF")

View file

@ -8,4 +8,5 @@ bn1.inp 94 1.0E-14
#cc2.inp 1 1.0E-12 -45.38989062944852
#cc3.inp 1 1.0E-12 -45.38990176407365
#cc4.inp 1 1.0E-12 -45.38975726647867
#cc5.inp 1 1.0E-12 -45.38975726647867
#EOF

View file

@ -0,0 +1,68 @@
# Reference energy -45.2700189877
&GLOBAL
PRINT_LEVEL LOW
PROJECT C
RUN_TYPE ENERGY
&END GLOBAL
&FORCE_EVAL
&DFT
BASIS_SET_FILE_NAME GTH_BASIS_SETS
POTENTIAL_FILE_NAME POTENTIAL
&KPOINTS
EPS_GEO 1.e-8
FULL_GRID OFF
PARALLEL_GROUP_SIZE 0
SCHEME MONKHORST-PACK 2 2 2
SYMMETRY ON
VERBOSE T
&END KPOINTS
&MGRID
CUTOFF 280
REL_CUTOFF 50
&END MGRID
&QS
EPS_DEFAULT 1.0E-14
METHOD GPW
&END QS
&SCF
CHOLESKY OFF
EPS_EIGVAL 1.e-8
EPS_SCF 1.0E-8
MAX_SCF 20
SCF_GUESS ATOMIC
&MIXING
ALPHA 0.50
METHOD BROYDEN_MIXING
&END MIXING
&PRINT
&RESTART off
&END RESTART
&END PRINT
&END SCF
&XC
&XC_FUNCTIONAL PADE
&END XC_FUNCTIONAL
&END XC
&END DFT
&SUBSYS
&CELL
ABC 3.56683 3.56683 3.56683
&END CELL
&COORD
SCALED
C 0.100000 0.000000 0.000000
C 0.500000 0.500000 0.000000
C 0.500000 0.000000 0.500000
C 0.000000 0.500000 0.500000
C 0.250000 0.250000 0.250000
C 0.250000 0.750000 0.750000
C 0.750000 0.250000 0.750000
C 0.750000 0.750000 0.250000
&END COORD
&KIND C
BASIS_SET SZV-GTH
POTENTIAL GTH-PADE-q4
&END KIND
&END SUBSYS
&END FORCE_EVAL