diff --git a/docs/methods/dft/k-points.md b/docs/methods/dft/k-points.md index 227679001e..e44d82c367 100644 --- a/docs/methods/dft/k-points.md +++ b/docs/methods/dft/k-points.md @@ -1,8 +1,115 @@ # K-Points -Unfortunately no one has gotten around to writing this page yet :-( +Periodic Quickstep calculations can sample the Brillouin zone through the `&DFT%KPOINTS` section. +The most common setup is a Monkhorst-Pack mesh: -In the meantime, the following links might be helpful: +```text +&DFT + &KPOINTS + SCHEME MONKHORST-PACK 6 6 6 + WAVEFUNCTIONS COMPLEX + &END KPOINTS +&END DFT +``` + +`SCHEME GAMMA` uses only the Gamma point. `SCHEME MONKHORST-PACK` and `SCHEME MACDONALD` generate +regular meshes. `SCHEME GENERAL` uses explicitly listed k-points: + +```text +&KPOINTS + SCHEME GENERAL + KPOINT 0.0 0.0 0.0 1.0 + KPOINT 0.5 0.0 0.0 1.0 +&END KPOINTS +``` + +K-points are given in reciprocal lattice-vector coordinates by default (`UNITS B_VECTOR`). Cartesian +coordinates can be selected with `UNITS CART_BOHR` or `UNITS CART_ANGSTROM`. + +## Symmetry Reduction + +Atomic symmetry can reduce the number of k-points that have to be solved explicitly: + +```text +&KPOINTS + SCHEME MONKHORST-PACK 8 8 8 + SYMMETRY ON + SYMMETRY_BACKEND SPGLIB + WAVEFUNCTIONS COMPLEX +&END KPOINTS +``` + +`SYMMETRY_BACKEND` selects the backend that provides and applies atom and k-point symmetry +operations: + +- `K290`: the established CP2K default. +- `SPGLIB`: use the space-group operations returned by SPGLIB, including fractional translations. + +`SYMMETRY_REDUCTION_METHOD` selects the method used to build the irreducible k-point set. If +`SYMMETRY_BACKEND` is set explicitly and `SYMMETRY_REDUCTION_METHOD` is omitted, the reduction +method follows the backend. `SYMMETRY_REDUCTION_METHOD SPGLIB` with `SYMMETRY_BACKEND K290` can be +used as a comparison mode: SPGLIB proposes the k-point orbits, while only mappings represented by +the K290 backend are used for the actual transformations. + +`INVERSION_SYMMETRY_ONLY ON` restricts the reduction to time-reversal/inversion symmetry. +`FULL_GRID ON` disables symmetry reduction while still generating the regular mesh. + +For general atomic k-point symmetry, use complex wavefunctions. Real wavefunctions are only valid +for Gamma and special k-points with real Bloch phases. + +## Explicit K-Point Sets + +`SCHEME GENERAL` can be used with symmetry reduction when the explicit k-point set is equally +weighted and closed under the requested symmetry operations: + +```text +&KPOINTS + SCHEME GENERAL + SYMMETRY ON + SYMMETRY_BACKEND SPGLIB + KPOINT -0.25 -0.25 -0.25 1.0 + KPOINT -0.25 -0.25 0.25 1.0 + KPOINT -0.25 0.25 -0.25 1.0 + KPOINT -0.25 0.25 0.25 1.0 + KPOINT 0.25 -0.25 -0.25 1.0 + KPOINT 0.25 -0.25 0.25 1.0 + KPOINT 0.25 0.25 -0.25 1.0 + KPOINT 0.25 0.25 0.25 1.0 +&END KPOINTS +``` + +The same closure requirement applies to K290, SPGLIB, and mixed SPGLIB-reduction/K290-backend +setups. For band paths or other intentionally nonuniform explicit lists, keep `SYMMETRY OFF`, +because the order and weights of the points are part of the requested property. + +## Cell Convention + +CP2K's k-point machinery assumes the standard CP2K cell convention: vector `A` lies along the +Cartesian X axis and vector `B` lies in the XY plane. Using `ABC` together with `ALPHA_BETA_GAMMA`, +or reading a CIF file, lets CP2K construct the cell in that convention from orientation-independent +lattice parameters. + +## Moving Geometries + +For moving geometries (`GEO_OPT`, `CELL_OPT`, `MD`, and related run types), atomic k-point symmetry +is rebuilt from the current cell and coordinates instead of reusing operations from the initial +geometry. This applies to regular Monkhorst-Pack/MacDonald meshes and to closed `GENERAL` k-point +sets. If the current geometry no longer supports a symmetry operation, the reduced set changes +accordingly or the explicit `GENERAL` set is rejected if it is no longer symmetry-closed. + +`KEEP_SPACE_GROUP T` is the safest way to combine geometry optimization with full atomic k-point +symmetry. `KEEP_SYMMETRY T` constrains the cell metric, but does not by itself keep atoms on +space-group-related positions. + +## Wannier90 + +The Wannier90 interface already has its own k-point path controlled by +`DFT%PRINT%WANNIER90%MP_GRID`. It builds and diagonalizes a full Monkhorst-Pack grid for the +Wannier90 export. Atomic k-point symmetry from the SCF setup is not reused, because Wannier90 +expects the full mesh and its nearest-neighbour connectivity. Explicit `SCHEME GENERAL` lists and +symmetry-reduced SCF k-point sets are therefore not exported directly to Wannier90. + +## Related Pages - - [](hartree-fock/ri_kpoints) diff --git a/src/cryssym.F b/src/cryssym.F index 258429591e..da780bf799 100644 --- a/src/cryssym.F +++ b/src/cryssym.F @@ -32,7 +32,7 @@ MODULE cryssym IMPLICIT NONE PRIVATE PUBLIC :: csym_type, release_csym_type, print_crys_symmetry, print_kp_symmetry - PUBLIC :: crys_sym_gen, kpoint_gen + PUBLIC :: crys_sym_gen, kpoint_gen, kpoint_gen_general CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cryssym' @@ -47,6 +47,7 @@ MODULE cryssym LOGICAL :: inversion_only = .FALSE. LOGICAL :: spglib_reduction = .FALSE. LOGICAL :: spglib_backend = .FALSE. + LOGICAL :: spglib_requested = .TRUE. INTEGER :: plevel = 0 INTEGER :: punit = -1 INTEGER :: istriz = -1 @@ -138,20 +139,22 @@ CONTAINS !> \param hmat ... !> \param delta ... !> \param iounit ... +!> \param use_spglib ... ! ************************************************************************************************** - SUBROUTINE crys_sym_gen(csym, scoor, types, hmat, delta, iounit) + SUBROUTINE crys_sym_gen(csym, scoor, types, hmat, delta, iounit, use_spglib) TYPE(csym_type) :: csym REAL(KIND=dp), DIMENSION(:, :), INTENT(IN) :: scoor INTEGER, DIMENSION(:), INTENT(IN) :: types REAL(KIND=dp), INTENT(IN) :: hmat(3, 3) REAL(KIND=dp), INTENT(IN), OPTIONAL :: delta INTEGER, INTENT(IN), OPTIONAL :: iounit + LOGICAL, INTENT(IN), OPTIONAL :: use_spglib CHARACTER(LEN=*), PARAMETER :: routineN = 'crys_sym_gen' INTEGER :: handle, ierr, major, micro, minor, nat, & nop, tra_mat(3, 3) - LOGICAL :: spglib + LOGICAL :: my_use_spglib, spglib CALL timeset(routineN, handle) @@ -187,37 +190,44 @@ CONTAINS csym%n_operations = 0 !..try spglib - major = spg_get_major_version() - minor = spg_get_minor_version() - micro = spg_get_micro_version() - IF (major == 0) THEN - CALL cp_warn(__LOCATION__, "Symmetry library SPGLIB not available") + my_use_spglib = .TRUE. + IF (PRESENT(use_spglib)) my_use_spglib = use_spglib + csym%spglib_requested = my_use_spglib + IF (.NOT. my_use_spglib) THEN spglib = .FALSE. ELSE - spglib = .TRUE. - CALL cite_reference(Togo2018) - ierr = spg_get_international(csym%international_symbol, TRANSPOSE(hmat), scoor, types, nat, delta) - IF (ierr == 0) THEN - CALL cp_warn(__LOCATION__, "Symmetry Library SPGLIB failed") + major = spg_get_major_version() + minor = spg_get_minor_version() + micro = spg_get_micro_version() + IF (major == 0) THEN + CALL cp_warn(__LOCATION__, "Symmetry library SPGLIB not available") spglib = .FALSE. ELSE - nop = spg_get_multiplicity(TRANSPOSE(hmat), scoor, types, nat, delta) - ALLOCATE (csym%rotations(3, 3, nop), csym%translations(3, nop)) - csym%n_operations = nop - ierr = spg_get_symmetry(csym%rotations, csym%translations, nop, & - TRANSPOSE(hmat), scoor, types, nat, delta) - ! Schoenflies Symbol - csym%schoenflies = ' ' - ierr = spg_get_schoenflies(csym%schoenflies, TRANSPOSE(hmat), scoor, types, nat, delta) - ! Point Group - csym%pointgroup_symbol = ' ' - tra_mat = 0 - ierr = spg_get_pointgroup(csym%pointgroup_symbol, tra_mat, & - csym%rotations, csym%n_operations) + spglib = .TRUE. + CALL cite_reference(Togo2018) + ierr = spg_get_international(csym%international_symbol, TRANSPOSE(hmat), scoor, types, nat, delta) + IF (ierr == 0) THEN + CALL cp_warn(__LOCATION__, "Symmetry Library SPGLIB failed") + spglib = .FALSE. + ELSE + nop = spg_get_multiplicity(TRANSPOSE(hmat), scoor, types, nat, delta) + ALLOCATE (csym%rotations(3, 3, nop), csym%translations(3, nop)) + csym%n_operations = nop + ierr = spg_get_symmetry(csym%rotations, csym%translations, nop, & + TRANSPOSE(hmat), scoor, types, nat, delta) + ! Schoenflies Symbol + csym%schoenflies = ' ' + ierr = spg_get_schoenflies(csym%schoenflies, TRANSPOSE(hmat), scoor, types, nat, delta) + ! Point Group + csym%pointgroup_symbol = ' ' + tra_mat = 0 + ierr = spg_get_pointgroup(csym%pointgroup_symbol, tra_mat, & + csym%rotations, csym%n_operations) - CALL strip_control_codes(csym%international_symbol) - CALL strip_control_codes(csym%schoenflies) - CALL strip_control_codes(csym%pointgroup_symbol) + CALL strip_control_codes(csym%international_symbol) + CALL strip_control_codes(csym%schoenflies) + CALL strip_control_codes(csym%pointgroup_symbol) + END IF END IF END IF csym%symlib = spglib @@ -254,9 +264,7 @@ CONTAINS INTEGER :: handle, i, ik, j, nkp, nkpts INTEGER, ALLOCATABLE, DIMENSION(:) :: kpop, xptr LOGICAL :: fullmesh, gamma_mesh, inversion_only, & - orthorhombic_cell, spglib_backend, & - spglib_reduction - REAL(KIND=dp) :: cell_eps + spglib_backend, spglib_reduction REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: wkp REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: xkp @@ -307,15 +315,15 @@ CONTAINS END IF csym%spglib_backend = spglib_backend - cell_eps = 10.0_dp*csym%delta*MAX(1.0_dp, MAXVAL(ABS(csym%hmat))) - orthorhombic_cell = ABS(csym%hmat(1, 2)) + ABS(csym%hmat(1, 3)) + & - ABS(csym%hmat(2, 1)) + ABS(csym%hmat(2, 3)) + & - ABS(csym%hmat(3, 1)) + ABS(csym%hmat(3, 2)) <= cell_eps - IF (spglib_backend .AND. .NOT. spglib_reduction) THEN CALL cp_abort(__LOCATION__, & "SYMMETRY_BACKEND SPGLIB requires SYMMETRY_REDUCTION_METHOD SPGLIB") END IF + IF (csym%istriz == 1 .AND. .NOT. fullmesh .AND. .NOT. inversion_only .AND. & + (spglib_backend .OR. spglib_reduction) .AND. .NOT. csym%symlib) THEN + CALL cp_abort(__LOCATION__, & + "SPGLIB k-point symmetry was requested, but SPGLIB is not available") + END IF csym%nkpoint = 0 csym%mesh(1:3) = nk(1:3) @@ -362,9 +370,8 @@ CONTAINS ELSE ! no symmetry library is available CALL full_grid_gen(nk, xkp, wkp, shift, gamma_centered=gamma_mesh) - IF (csym%istriz == 1 .AND. .NOT. fullmesh .AND. .NOT. inversion_only .AND. & - orthorhombic_cell) THEN - ! fall back to the K290 atom mapping for simple cells when SPGLIB is not linked + IF (csym%istriz == 1 .AND. .NOT. fullmesh .AND. .NOT. inversion_only) THEN + ! fall back to the K290 atom mapping when SPGLIB is not linked CALL kp_symmetry(csym, xkp, wkp, kpop, use_spglib_reduction=.FALSE.) ELSE IF (csym%istriz /= 1 .AND. fullmesh) THEN ! full kpoint mesh is used @@ -439,6 +446,116 @@ CONTAINS END SUBROUTINE kpoint_gen +! ************************************************************************************************** +!> \brief Reduce an explicitly supplied GENERAL k-point set. +!> \param csym ... +!> \param xkp_in explicit k-point coordinates in reciprocal lattice coordinates +!> \param wkp_in explicit k-point weights +!> \param symm ... +!> \param full_grid ... +!> \param inversion_symmetry_only ... +!> \param use_spglib_reduction ... +!> \param use_spglib_backend ... +! ************************************************************************************************** + SUBROUTINE kpoint_gen_general(csym, xkp_in, wkp_in, symm, full_grid, & + inversion_symmetry_only, use_spglib_reduction, use_spglib_backend) + TYPE(csym_type) :: csym + REAL(KIND=dp), DIMENSION(:, :), INTENT(IN) :: xkp_in + REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: wkp_in + LOGICAL, INTENT(IN), OPTIONAL :: symm, full_grid, & + inversion_symmetry_only, & + use_spglib_reduction, & + use_spglib_backend + + CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_gen_general' + + INTEGER :: handle, i, nfull + LOGICAL :: atomic_symmetry, fullmesh, & + inversion_only, spglib_backend, & + spglib_reduction + REAL(KIND=dp) :: weight_eps + + CALL timeset(routineN, handle) + + nfull = SIZE(wkp_in) + CPASSERT(SIZE(xkp_in, 1) == 3) + CPASSERT(SIZE(xkp_in, 2) == nfull) + + atomic_symmetry = .FALSE. + IF (PRESENT(symm)) atomic_symmetry = symm + csym%istriz = -1 + IF (atomic_symmetry) csym%istriz = 1 + fullmesh = .FALSE. + IF (PRESENT(full_grid)) fullmesh = full_grid + inversion_only = .FALSE. + IF (PRESENT(inversion_symmetry_only)) inversion_only = inversion_symmetry_only + spglib_reduction = .FALSE. + IF (PRESENT(use_spglib_reduction)) spglib_reduction = use_spglib_reduction + spglib_backend = .FALSE. + IF (PRESENT(use_spglib_backend)) spglib_backend = use_spglib_backend + + csym%fullgrid = fullmesh + csym%inversion_only = inversion_only + csym%spglib_reduction = spglib_reduction + csym%spglib_backend = spglib_backend + csym%nkpoint = 0 + csym%mesh(1:3) = 0 + csym%nrtot = 0 + IF (ALLOCATED(csym%rt)) DEALLOCATE (csym%rt) + IF (ALLOCATED(csym%vt)) DEALLOCATE (csym%vt) + IF (ALLOCATED(csym%ibrot)) DEALLOCATE (csym%ibrot) + IF (ALLOCATED(csym%f0)) DEALLOCATE (csym%f0) + ALLOCATE (csym%rt(3, 3, 0), csym%vt(3, 0), csym%ibrot(0), csym%f0(csym%nat, 0)) + IF (ALLOCATED(csym%xkpoint)) DEALLOCATE (csym%xkpoint) + IF (ALLOCATED(csym%wkpoint)) DEALLOCATE (csym%wkpoint) + IF (ALLOCATED(csym%kpmesh)) DEALLOCATE (csym%kpmesh) + IF (ALLOCATED(csym%kplink)) DEALLOCATE (csym%kplink) + IF (ALLOCATED(csym%kpop)) DEALLOCATE (csym%kpop) + + ALLOCATE (csym%kpmesh(3, nfull), csym%kplink(2, nfull), csym%kpop(nfull)) + csym%kpmesh(1:3, 1:nfull) = xkp_in(1:3, 1:nfull) + csym%kplink = 0 + csym%kpop = 1 + + IF (.NOT. atomic_symmetry .OR. fullmesh) THEN + csym%nkpoint = nfull + ALLOCATE (csym%xkpoint(3, nfull), csym%wkpoint(nfull)) + csym%xkpoint(1:3, 1:nfull) = xkp_in(1:3, 1:nfull) + csym%wkpoint(1:nfull) = wkp_in(1:nfull) + DO i = 1, nfull + csym%kplink(1:2, i) = i + END DO + ELSE IF (inversion_only) THEN + CALL reduce_general_inversion(csym, xkp_in, wkp_in) + ELSE + weight_eps = MAX(1.e-12_dp, 10.0_dp*csym%delta) + IF (ANY(ABS(wkp_in(1:nfull) - wkp_in(1)) > weight_eps)) THEN + CALL cp_abort(__LOCATION__, & + "KPOINTS%SYMMETRY with SCHEME GENERAL requires equal explicit weights.") + END IF + IF (spglib_backend) THEN + IF (.NOT. csym%symlib) THEN + CALL cp_abort(__LOCATION__, & + "SCHEME GENERAL with SYMMETRY_BACKEND SPGLIB requires SPGLIB.") + END IF + CALL reduce_general_spglib(csym, xkp_in) + ELSE IF (spglib_reduction) THEN + IF (.NOT. csym%symlib) THEN + CALL cp_abort(__LOCATION__, & + "SCHEME GENERAL with SYMMETRY_REDUCTION_METHOD SPGLIB requires SPGLIB.") + END IF + CALL setup_k290_operations(csym) + CALL reduce_general_spglib_k290(csym, xkp_in) + ELSE + CALL setup_k290_operations(csym) + CALL reduce_general_k290(csym, xkp_in) + END IF + END IF + + CALL timestop(handle) + + END SUBROUTINE kpoint_gen_general + ! ************************************************************************************************** !> \brief ... !> \param csym ... @@ -539,7 +656,7 @@ CONTAINS END DO csym%ibrot(1:nc) = ib(1:nc) - IF (csym%n_operations > nc) THEN + IF (csym%n_operations > nc .AND. .NOT. spglib_reduction) THEN IF (ALLOCATED(srot)) DEALLOCATE (srot) ALLOCATE (srot(3, 3, csym%n_operations)) CALL setup_spglib_operations(csym, srot, nrot) @@ -599,6 +716,128 @@ CONTAINS END SUBROUTINE kp_symmetry_spglib +! ************************************************************************************************** +!> \brief Store K290 atomic symmetry operations without reducing a generated mesh. +!> \param csym ... +! ************************************************************************************************** + SUBROUTINE setup_k290_operations(csym) + TYPE(csym_type) :: csym + + INTEGER :: i, ihc, ihg, indpg, iou, iq1, iq2, iq3, & + isy, li, nat, nc, nhash, 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, wvk0 + REAL(KIND=dp), DIMENSION(3, 3) :: strain + REAL(KIND=dp), DIMENSION(3, 3, 48) :: r + REAL(KIND=dp), DIMENSION(3, 48) :: vt + + iou = csym%punit + nat = csym%nat + CALL setup_k290_lattice(csym, a1, a2, a3, b1, b2, b3, alat) + iq1 = MAX(1, csym%mesh(1)) + iq2 = MAX(1, csym%mesh(2)) + iq3 = MAX(1, csym%mesh(3)) + nkpoint = MAX(10, 10*iq1*iq2*iq3) + strain = 0.0_dp + wvk0 = 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(csym%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 cite_reference(Worlton1972) + + CALL K290s(iou, nat, nkpoint, nsp, iq1, iq2, iq3, csym%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%nrtot = nc + IF (ALLOCATED(csym%rt)) DEALLOCATE (csym%rt) + IF (ALLOCATED(csym%vt)) DEALLOCATE (csym%vt) + IF (ALLOCATED(csym%ibrot)) DEALLOCATE (csym%ibrot) + IF (ALLOCATED(csym%f0)) DEALLOCATE (csym%f0) + ALLOCATE (csym%rt(3, 3, nc), csym%vt(3, nc), csym%ibrot(nc)) + csym%vt(1:3, 1:nc) = vt(1:3, 1:nc) + ALLOCATE (csym%f0(nat, nc)) + DO i = 1, nc + csym%rt(1:3, 1:3, i) = r(1:3, 1:3, ib(i)) + csym%f0(1:nat, i) = f0(i, 1:nat) + END DO + csym%ibrot(1:nc) = ib(1:nc) + + DEALLOCATE (xkapa, rx, tvec, ty, isc, f0) + DEALLOCATE (wvkl, rlist, includ, list) + DEALLOCATE (lrot, lwght) + + END SUBROUTINE setup_k290_operations + +! ************************************************************************************************** +!> \brief Return K290 lattice vectors and reciprocal vectors. +!> \param csym ... +!> \param a1 first lattice vector +!> \param a2 second lattice vector +!> \param a3 third lattice vector +!> \param b1 first reciprocal lattice vector +!> \param b2 second reciprocal lattice vector +!> \param b3 third reciprocal lattice vector +!> \param alat lattice scaling used by K290 +! ************************************************************************************************** + SUBROUTINE setup_k290_lattice(csym, a1, a2, a3, b1, b2, b3, alat) + TYPE(csym_type), INTENT(IN) :: csym + REAL(KIND=dp), DIMENSION(3), INTENT(OUT) :: a1, a2, a3, b1, b2, b3 + REAL(KIND=dp), INTENT(OUT) :: alat + + REAL(KIND=dp) :: volum + + a1(1:3) = csym%hmat(1:3, 1) + a2(1:3) = csym%hmat(1:3, 2) + a3(1:3) = csym%hmat(1:3, 3) + alat = csym%hmat(1, 1) + volum = a1(1)*a2(2)*a3(3) + a2(1)*a3(2)*a1(3) + & + a3(1)*a1(2)*a2(3) - a1(3)*a2(2)*a3(1) - & + a2(3)*a3(2)*a1(1) - a3(3)*a1(2)*a2(1) + volum = ABS(volum) + b1(1) = (a2(2)*a3(3) - a2(3)*a3(2))/volum + b1(2) = (a2(3)*a3(1) - a2(1)*a3(3))/volum + b1(3) = (a2(1)*a3(2) - a2(2)*a3(1))/volum + b2(1) = (a3(2)*a1(3) - a3(3)*a1(2))/volum + b2(2) = (a3(3)*a1(1) - a3(1)*a1(3))/volum + b2(3) = (a3(1)*a1(2) - a3(2)*a1(1))/volum + b3(1) = (a1(2)*a2(3) - a1(3)*a2(2))/volum + b3(2) = (a1(3)*a2(1) - a1(1)*a2(3))/volum + b3(3) = (a1(1)*a2(2) - a1(2)*a2(1))/volum + + END SUBROUTINE setup_k290_lattice + ! ************************************************************************************************** !> \brief Store usable SPGLIB space-group operations for k-point symmetry !> \param csym ... @@ -879,6 +1118,372 @@ CONTAINS END SUBROUTINE reduce_spglib_kpoint_mesh +! ************************************************************************************************** +!> \brief Reduce an explicit k-point set by inversion/time-reversal. +!> \param csym ... +!> \param xkp_full explicit k-point coordinates +!> \param wkp_full explicit k-point weights +! ************************************************************************************************** + SUBROUTINE reduce_general_inversion(csym, xkp_full, wkp_full) + TYPE(csym_type) :: csym + REAL(KIND=dp), DIMENSION(:, :), INTENT(IN) :: xkp_full + REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: wkp_full + + INTEGER :: i, j, nfull, nred + INTEGER, ALLOCATABLE, DIMENSION(:) :: rep + LOGICAL, ALLOCATABLE, DIMENSION(:) :: used + REAL(KIND=dp) :: eps + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: wred + REAL(KIND=dp), DIMENSION(3) :: diff + + nfull = SIZE(wkp_full) + eps = MAX(1.e-12_dp, 10.0_dp*csym%delta) + ALLOCATE (rep(nfull), used(nfull), wred(nfull)) + used = .FALSE. + rep = 0 + wred = 0.0_dp + nred = 0 + + DO i = 1, nfull + IF (used(i)) CYCLE + nred = nred + 1 + rep(nred) = i + used(i) = .TRUE. + csym%kplink(1, i) = i + csym%kpop(i) = 1 + wred(nred) = wkp_full(i) + DO j = i + 1, nfull + IF (used(j)) CYCLE + diff(1:3) = xkp_full(1:3, j) + xkp_full(1:3, i) + diff(1:3) = diff(1:3) - ANINT(diff(1:3)) + IF (ALL(ABS(diff(1:3)) < eps)) THEN + IF (ABS(wkp_full(j) - wkp_full(i)) > eps) THEN + CALL cp_abort(__LOCATION__, & + "KPOINTS%INVERSION_SYMMETRY_ONLY with SCHEME GENERAL requires "// & + "equal weights for inversion-related k-points.") + END IF + used(j) = .TRUE. + csym%kplink(1, j) = i + csym%kpop(j) = -1 + wred(nred) = wred(nred) + wkp_full(j) + END IF + END DO + END DO + + csym%nkpoint = nred + ALLOCATE (csym%xkpoint(3, nred), csym%wkpoint(nred)) + DO i = 1, nred + csym%xkpoint(1:3, i) = xkp_full(1:3, rep(i)) + csym%wkpoint(i) = wred(i) + END DO + DO i = 1, nfull + DO j = 1, nred + IF (csym%kplink(1, i) == rep(j)) THEN + csym%kplink(2, i) = j + EXIT + END IF + END DO + END DO + + DEALLOCATE (rep, used, wred) + + END SUBROUTINE reduce_general_inversion + +! ************************************************************************************************** +!> \brief Reduce an explicit k-point set with K290 symmetry operations. +!> \param csym ... +!> \param xkp_full explicit k-point coordinates +! ************************************************************************************************** + SUBROUTINE reduce_general_k290(csym, xkp_full) + TYPE(csym_type) :: csym + REAL(KIND=dp), DIMENSION(:, :), INTENT(IN) :: xkp_full + + INTEGER :: i, ibsign, iop, j, kr, nfull, nred + INTEGER, ALLOCATABLE, DIMENSION(:) :: rep + LOGICAL :: found + LOGICAL, ALLOCATABLE, DIMENSION(:) :: used + REAL(KIND=dp) :: alat, eps + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: wred + REAL(KIND=dp), DIMENSION(3) :: a1, a2, a3, b1, b2, b3, diff, rr, wcart + + nfull = SIZE(xkp_full, 2) + eps = MAX(1.e-12_dp, 10.0_dp*csym%delta) + CALL setup_k290_lattice(csym, a1, a2, a3, b1, b2, b3, alat) + + ALLOCATE (rep(nfull), used(nfull), wred(nfull)) + used = .FALSE. + rep = 0 + wred = 0.0_dp + nred = 0 + + DO i = 1, nfull + IF (used(i)) CYCLE + nred = nred + 1 + rep(nred) = i + used(i) = .TRUE. + csym%kplink(1, i) = i + csym%kpop(i) = 1 + wred(nred) = 1.0_dp + + DO iop = 1, csym%nrtot + DO ibsign = 1, 2 + kr = csym%ibrot(iop) + wcart(1:3) = alat*(xkp_full(1, i)*b1(1:3) + & + xkp_full(2, i)*b2(1:3) + & + xkp_full(3, i)*b3(1:3)) + wcart(1:3) = kp_apply_operation(wcart(1:3), csym%rt(1:3, 1:3, iop)) + IF (ibsign == 2) THEN + wcart(1:3) = -wcart(1:3) + kr = -kr + END IF + rr(1) = DOT_PRODUCT(a1(1:3), wcart(1:3))/alat + rr(2) = DOT_PRODUCT(a2(1:3), wcart(1:3))/alat + rr(3) = DOT_PRODUCT(a3(1:3), wcart(1:3))/alat + + found = .FALSE. + DO j = 1, nfull + diff(1:3) = xkp_full(1:3, j) - rr(1:3) + diff(1:3) = diff(1:3) - ANINT(diff(1:3)) + IF (ALL(ABS(diff(1:3)) < eps)) THEN + found = .TRUE. + IF (.NOT. used(j)) THEN + used(j) = .TRUE. + csym%kplink(1, j) = i + csym%kpop(j) = kr + wred(nred) = wred(nred) + 1.0_dp + ELSE + CPASSERT(csym%kplink(1, j) == i) + END IF + EXIT + END IF + END DO + IF (.NOT. found) THEN + CALL cp_abort(__LOCATION__, & + "KPOINTS%SYMMETRY with SCHEME GENERAL requires the explicit k-point set "// & + "to be closed under the K290 symmetry operations.") + END IF + END DO + END DO + END DO + + CALL store_general_reduction(csym, xkp_full, rep, wred, nred) + + DEALLOCATE (rep, used, wred) + + END SUBROUTINE reduce_general_k290 + +! ************************************************************************************************** +!> \brief Reduce an explicit k-point set with SPGLIB symmetry operations. +!> \param csym ... +!> \param xkp_full explicit k-point coordinates +! ************************************************************************************************** + SUBROUTINE reduce_general_spglib(csym, xkp_full) + TYPE(csym_type) :: csym + REAL(KIND=dp), DIMENSION(:, :), INTENT(IN) :: xkp_full + + INTEGER :: i, iop, isign, j, kr, nfull, nred, nrot + INTEGER, ALLOCATABLE, DIMENSION(:) :: rep + INTEGER, ALLOCATABLE, DIMENSION(:, :, :) :: srot + INTEGER, DIMENSION(3, 3) :: krot + LOGICAL :: found + LOGICAL, ALLOCATABLE, DIMENSION(:) :: used + REAL(KIND=dp) :: eps + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: wred + REAL(KIND=dp), DIMENSION(3) :: diff, rr + + nfull = SIZE(xkp_full, 2) + eps = MAX(1.e-12_dp, 10.0_dp*csym%delta) + ALLOCATE (srot(3, 3, csym%n_operations)) + CALL setup_spglib_operations(csym, srot, nrot) + + ALLOCATE (rep(nfull), used(nfull), wred(nfull)) + used = .FALSE. + rep = 0 + wred = 0.0_dp + nred = 0 + + DO i = 1, nfull + IF (used(i)) CYCLE + nred = nred + 1 + rep(nred) = i + used(i) = .TRUE. + csym%kplink(1, i) = i + csym%kpop(i) = 1 + wred(nred) = 1.0_dp + + DO iop = 1, nrot + kr = csym%ibrot(iop) + krot = reciprocal_rotation(srot(:, :, kr)) + DO isign = 1, 2 + rr(1:3) = MATMUL(REAL(krot(1:3, 1:3), KIND=dp), xkp_full(1:3, i)) + IF (isign == 2) THEN + rr(1:3) = -rr(1:3) + kr = -csym%ibrot(iop) + ELSE + kr = csym%ibrot(iop) + END IF + + found = .FALSE. + DO j = 1, nfull + diff(1:3) = xkp_full(1:3, j) - rr(1:3) + diff(1:3) = diff(1:3) - ANINT(diff(1:3)) + IF (ALL(ABS(diff(1:3)) < eps)) THEN + found = .TRUE. + IF (.NOT. used(j)) THEN + used(j) = .TRUE. + csym%kplink(1, j) = i + csym%kpop(j) = kr + wred(nred) = wred(nred) + 1.0_dp + ELSE + CPASSERT(csym%kplink(1, j) == i) + END IF + EXIT + END IF + END DO + IF (.NOT. found) THEN + CALL cp_abort(__LOCATION__, & + "KPOINTS%SYMMETRY with SCHEME GENERAL requires the explicit k-point set "// & + "to be closed under the requested symmetry operations.") + END IF + END DO + END DO + END DO + + CALL store_general_reduction(csym, xkp_full, rep, wred, nred) + + DEALLOCATE (rep, srot, used, wred) + + END SUBROUTINE reduce_general_spglib + +! ************************************************************************************************** +!> \brief Reduce an explicit k-point set with SPGLIB rotations and K290 operations. +!> \param csym ... +!> \param xkp_full explicit k-point coordinates +! ************************************************************************************************** + SUBROUTINE reduce_general_spglib_k290(csym, xkp_full) + TYPE(csym_type) :: csym + REAL(KIND=dp), DIMENSION(:, :), INTENT(IN) :: xkp_full + + INTEGER :: i, iop, isign, j, k290_op, nfull, nred, & + nrot, nskipped + INTEGER, ALLOCATABLE, DIMENSION(:) :: rep + INTEGER, ALLOCATABLE, DIMENSION(:, :, :) :: srot + INTEGER, DIMENSION(3, 3) :: krot + LOGICAL :: found, valid + LOGICAL, ALLOCATABLE, DIMENSION(:) :: used + REAL(KIND=dp) :: alat, eps + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: wred + REAL(KIND=dp), DIMENSION(3) :: a1, a2, a3, b1, b2, b3, diff, rr + + nfull = SIZE(xkp_full, 2) + eps = MAX(1.e-12_dp, 10.0_dp*csym%delta) + CALL setup_k290_lattice(csym, a1, a2, a3, b1, b2, b3, alat) + ALLOCATE (srot(3, 3, csym%n_operations)) + CALL setup_spglib_reduction_rotations(csym, srot, nrot) + + ALLOCATE (rep(nfull), used(nfull), wred(nfull)) + used = .FALSE. + rep = 0 + wred = 0.0_dp + nred = 0 + nskipped = 0 + + DO i = 1, nfull + IF (used(i)) CYCLE + nred = nred + 1 + rep(nred) = i + used(i) = .TRUE. + csym%kplink(1, i) = i + csym%kpop(i) = 1 + wred(nred) = 1.0_dp + + DO iop = 1, nrot + krot = reciprocal_rotation(srot(:, :, iop)) + DO isign = 1, 2 + rr(1:3) = MATMUL(REAL(krot(1:3, 1:3), KIND=dp), xkp_full(1:3, i)) + IF (isign == 2) rr(1:3) = -rr(1:3) + + found = .FALSE. + DO j = 1, nfull + diff(1:3) = xkp_full(1:3, j) - rr(1:3) + diff(1:3) = diff(1:3) - ANINT(diff(1:3)) + IF (ALL(ABS(diff(1:3)) < eps)) THEN + found = .TRUE. + CALL find_k290_kpoint_operation(csym, xkp_full(1:3, i), xkp_full(1:3, j), & + a1, a2, a3, b1, b2, b3, alat, & + k290_op, valid) + IF (.NOT. valid) THEN + nskipped = nskipped + 1 + EXIT + END IF + IF (.NOT. used(j)) THEN + used(j) = .TRUE. + csym%kplink(1, j) = i + csym%kpop(j) = k290_op + wred(nred) = wred(nred) + 1.0_dp + ELSE + CPASSERT(csym%kplink(1, j) == i) + END IF + EXIT + END IF + END DO + IF (.NOT. found) THEN + CALL cp_abort(__LOCATION__, & + "KPOINTS%SYMMETRY with SCHEME GENERAL requires the explicit k-point set "// & + "to be closed under the SPGLIB symmetry operations.") + END IF + END DO + END DO + END DO + + IF (nskipped > 0) THEN + CALL cp_warn(__LOCATION__, & + "Some SPGLIB k-point mappings are not represented by the K290 backend; "// & + "the GENERAL k-point set was reduced only by the compatible mappings.") + END IF + + CALL store_general_reduction(csym, xkp_full, rep, wred, nred) + + DEALLOCATE (rep, srot, used, wred) + + END SUBROUTINE reduce_general_spglib_k290 + +! ************************************************************************************************** +!> \brief Store reduced GENERAL k-point representatives. +!> \param csym ... +!> \param xkp_full explicit k-point coordinates +!> \param rep representative indices +!> \param wred representative multiplicities +!> \param nred number of reduced representatives +! ************************************************************************************************** + SUBROUTINE store_general_reduction(csym, xkp_full, rep, wred, nred) + TYPE(csym_type) :: csym + REAL(KIND=dp), DIMENSION(:, :), INTENT(IN) :: xkp_full + INTEGER, DIMENSION(:), INTENT(IN) :: rep + REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: wred + INTEGER, INTENT(IN) :: nred + + INTEGER :: i, j, nfull + + nfull = SIZE(xkp_full, 2) + csym%nkpoint = nred + ALLOCATE (csym%xkpoint(3, nred), csym%wkpoint(nred)) + DO i = 1, nred + csym%xkpoint(1:3, i) = xkp_full(1:3, rep(i)) + csym%wkpoint(i) = wred(i) + END DO + DO i = 1, nfull + DO j = 1, nred + IF (csym%kplink(1, i) == rep(j)) THEN + csym%kplink(2, i) = j + EXIT + END IF + END DO + CPASSERT(csym%kplink(2, i) /= 0) + END DO + + END SUBROUTINE store_general_reduction + ! ************************************************************************************************** !> \brief Reduce a k-point mesh with SPGLIB rotations and K290 operations !> \param csym ... @@ -906,7 +1511,8 @@ CONTAINS REAL(KIND=dp), DIMENSION(3), INTENT(IN) :: a1, a2, a3, b1, b2, b3 REAL(KIND=dp), INTENT(IN) :: alat - INTEGER :: i, iop, isign, j, k290_op, nkpts + INTEGER :: i, iop, isign, j, k290_op, nkpts, & + nskipped INTEGER, DIMENSION(3, 3) :: krot LOGICAL :: valid REAL(KIND=dp) :: eps @@ -914,6 +1520,7 @@ CONTAINS nkpts = SIZE(wkp) eps = MAX(1.e-12_dp, 10.0_dp*csym%delta) + nskipped = 0 wkp = 0.0_dp kpop = 0 @@ -946,8 +1553,8 @@ CONTAINS a1, a2, a3, b1, b2, b3, alat, & k290_op, valid) IF (.NOT. valid) THEN - CALL cp_abort(__LOCATION__, & - "SPGLIB k-point mapping is not represented by K290 backend") + nskipped = nskipped + 1 + EXIT END IF csym%kplink(1, j) = i wkp(i) = wkp(i) + 1.0_dp @@ -964,6 +1571,11 @@ CONTAINS CPASSERT(csym%kplink(1, i) /= 0) CPASSERT(kpop(i) /= 0) END DO + IF (nskipped > 0) THEN + CALL cp_warn(__LOCATION__, & + "Some SPGLIB k-point mappings are not represented by the K290 backend; "// & + "the mesh was reduced only by the compatible mappings.") + END IF END SUBROUTINE reduce_spglib_kpoint_mesh_k290 @@ -1293,7 +1905,11 @@ CONTAINS END DO END IF ELSE - WRITE (iunit, "(T2,A)") "SPGLIB for Crystal Symmetry Information determination is not availale" + IF (csym%spglib_requested) THEN + WRITE (iunit, "(T2,A)") "SPGLIB for Crystal Symmetry Information determination is not available" + ELSE + WRITE (iunit, "(T2,A)") "SPGLIB Crystal Symmetry Information was not requested" + END IF END IF END IF @@ -1306,7 +1922,7 @@ CONTAINS SUBROUTINE print_kp_symmetry(csym) TYPE(csym_type), INTENT(IN) :: csym - INTEGER :: i, iunit, nat, plevel + INTEGER :: i, iunit, nat, nmesh, plevel iunit = csym%punit IF (iunit >= 0) THEN @@ -1317,9 +1933,15 @@ CONTAINS DO i = 1, csym%nkpoint WRITE (iunit, '(T2,i10,3F10.5,T71,I10)') i, csym%xkpoint(1:3, i), NINT(csym%wkpoint(i)) END DO - WRITE (iunit, '(/,A,T63,3I6)') " K-point Mesh: ", csym%mesh(1), csym%mesh(2), csym%mesh(3) + nmesh = csym%mesh(1)*csym%mesh(2)*csym%mesh(3) + IF (nmesh > 0) THEN + WRITE (iunit, '(/,A,T63,3I6)') " K-point Mesh: ", csym%mesh(1), csym%mesh(2), csym%mesh(3) + ELSE + nmesh = SIZE(csym%kpmesh, 2) + WRITE (iunit, '(/,A,T70,I10)') " Explicit K-point Set: ", nmesh + END IF WRITE (iunit, '(T19,A,T54,A)') " Wavevector Basis ", " Special Points Rotation" - DO i = 1, csym%mesh(1)*csym%mesh(2)*csym%mesh(3) + DO i = 1, nmesh WRITE (iunit, '(T2,i10,3F10.5,T45,3I12)') i, csym%kpmesh(1:3, i), & csym%kplink(1:2, i), csym%kpop(i) END DO diff --git a/src/force_env_methods.F b/src/force_env_methods.F index 1f2d648695..37166f91ea 100644 --- a/src/force_env_methods.F +++ b/src/force_env_methods.F @@ -592,7 +592,8 @@ CONTAINS CALL get_kpoint_info(kpoints, kp_scheme=kp_scheme, symmetry=kpoint_symmetry, full_grid=full_grid, & inversion_symmetry_only=inversion_symmetry_only) IF (.NOT. kpoint_symmetry) RETURN - IF (TRIM(kp_scheme) /= "MONKHORST-PACK" .AND. TRIM(kp_scheme) /= "MACDONALD") RETURN + IF (TRIM(kp_scheme) /= "MONKHORST-PACK" .AND. TRIM(kp_scheme) /= "MACDONALD" .AND. & + TRIM(kp_scheme) /= "GENERAL") RETURN input_full_grid = full_grid input_inversion_symmetry_only = inversion_symmetry_only diff --git a/src/input_cp2k_kpoints.F b/src/input_cp2k_kpoints.F index ef6225fc20..583306a346 100644 --- a/src/input_cp2k_kpoints.F +++ b/src/input_cp2k_kpoints.F @@ -92,8 +92,8 @@ CONTAINS "For `MONKHORST-PACK` the number of k points in all 3 dimensions has to"// & " be supplied along with the keyword. For `MACDONALD` also the list of shifts."// & " E.g. `MONKHORST-PACK 12 12 8`, `MACDONALD 4 4 4 0.25 0.25 0.25`."// & - " `GENERAL` uses the explicitly listed k-points as supplied and does not apply"// & - " SYMMETRY_BACKEND or SYMMETRY_REDUCTION_METHOD.", & + " `GENERAL` uses explicitly listed k-points. If symmetry reduction is requested,"// & + " the explicit set must be equally weighted and closed under the selected operations.", & usage="SCHEME {KPMETHOD} {integer} {integer} ..", & citations=[Monkhorst1976, MacDonald1978], & n_var=-1, type_of_var=char_t) @@ -164,8 +164,8 @@ CONTAINS description="Select the backend used to provide and apply atomic "// & "k-point symmetry operations. K290 is the established default. "// & "SPGLIB uses the symmetry operations returned by SPGLIB, including "// & - "their fractional translations. This applies to Monkhorst-Pack and MacDonald "// & - "meshes. For GENERAL, the explicit k-point list is used as supplied. If "// & + "their fractional translations. This applies to Monkhorst-Pack, MacDonald, and "// & + "closed GENERAL k-point sets. If "// & "SYMMETRY_REDUCTION_METHOD is not specified, it follows the selected backend.", & usage="SYMMETRY_BACKEND K290", type_of_var=enum_t, & enum_c_vals=s2a("K290", "SPGLIB"), & @@ -180,7 +180,8 @@ CONTAINS description="Select the method used to reduce Monkhorst-Pack and MacDonald "// & "k-point meshes when atomic symmetry is enabled. K290 is the established "// & "default. SPGLIB uses the symmetry operations returned by SPGLIB for the "// & - "k-point reduction. GENERAL k-point lists are not reduced. With "// & + "k-point reduction. GENERAL k-point lists can be reduced when the explicit set is "// & + "equally weighted and closed under the selected operations. With "// & "SYMMETRY_BACKEND K290 this can be used as a comparison mode using K290 "// & "operations for SPGLIB-generated mappings.", & usage="SYMMETRY_REDUCTION_METHOD K290", type_of_var=enum_t, & diff --git a/src/kpoint_methods.F b/src/kpoint_methods.F index d760abf517..a356f27eaf 100644 --- a/src/kpoint_methods.F +++ b/src/kpoint_methods.F @@ -46,6 +46,7 @@ MODULE kpoint_methods USE cryssym, ONLY: crys_sym_gen,& csym_type,& kpoint_gen,& + kpoint_gen_general,& print_crys_symmetry,& print_kp_symmetry,& release_csym_type @@ -54,9 +55,7 @@ MODULE kpoint_methods smear_gaussian,& smear_mp,& smear_mv - USE input_cp2k_kpoints, ONLY: use_k290_kpoint_backend,& - use_k290_kpoint_symmetry,& - use_spglib_kpoint_backend,& + USE input_cp2k_kpoints, ONLY: use_spglib_kpoint_backend,& use_spglib_kpoint_symmetry USE kinds, ONLY: dp USE kpoint_types, ONLY: get_kpoint_info,& @@ -134,6 +133,8 @@ CONTAINS REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: coord, scoord REAL(KIND=dp), DIMENSION(3) :: srot REAL(KIND=dp), DIMENSION(3, 3) :: srotmat + REAL(KIND=dp), DIMENSION(:), POINTER :: wkp_full + REAL(KIND=dp), DIMENSION(:, :), POINTER :: xkp_full TYPE(csym_type) :: crys_sym TYPE(kpoint_sym_type), POINTER :: kpsym @@ -187,7 +188,8 @@ CONTAINS agauge(1:3, i) = -FLOOR(scoord(1:3, i) + 0.5_dp - kpoint%eps_geo) END DO - CALL crys_sym_gen(crys_sym, scoord, atype, cell%hmat, delta=kpoint%eps_geo, iounit=iounit) + CALL crys_sym_gen(crys_sym, scoord, atype, cell%hmat, delta=kpoint%eps_geo, iounit=iounit, & + use_spglib=kpoint%symmetry) CALL kpoint_gen(crys_sym, kpoint%nkp_grid, symm=kpoint%symmetry, shift=kpoint%kp_shift, & full_grid=kpoint%full_grid, gamma_centered=kpoint%gamma_centered, & inversion_symmetry_only=kpoint%inversion_symmetry_only, & @@ -276,23 +278,145 @@ CONTAINS DEALLOCATE (agauge) CASE ("GENERAL") - IF (kpoint%symmetry) THEN - CALL cp_abort(__LOCATION__, & - "KPOINTS%SYMMETRY is not supported with SCHEME GENERAL; "// & - "explicit k-points are used as supplied.") + NULLIFY (xkp_full, wkp_full) + IF (ASSOCIATED(kpoint%xkp_input)) THEN + xkp_full => kpoint%xkp_input + wkp_full => kpoint%wkp_input + ELSE + xkp_full => kpoint%xkp + wkp_full => kpoint%wkp END IF - IF (kpoint%symmetry_backend /= use_k290_kpoint_backend .OR. & - kpoint%symmetry_reduction_method /= use_k290_kpoint_symmetry) THEN - CALL cp_warn(__LOCATION__, & - "KPOINTS%SYMMETRY_BACKEND and SYMMETRY_REDUCTION_METHOD are ignored with "// & - "SCHEME GENERAL; explicit k-points are used as supplied.") + CPASSERT(ASSOCIATED(xkp_full)) + CPASSERT(ASSOCIATED(wkp_full)) + IF (.NOT. ASSOCIATED(kpoint%xkp_input)) THEN + ALLOCATE (kpoint%xkp_input(3, SIZE(wkp_full)), kpoint%wkp_input(SIZE(wkp_full))) + kpoint%xkp_input(1:3, 1:SIZE(wkp_full)) = xkp_full(1:3, 1:SIZE(wkp_full)) + kpoint%wkp_input(1:SIZE(wkp_full)) = wkp_full(1:SIZE(wkp_full)) + xkp_full => kpoint%xkp_input + wkp_full => kpoint%wkp_input + END IF + IF (.NOT. kpoint%symmetry) THEN + IF (.NOT. ASSOCIATED(kpoint%xkp)) THEN + kpoint%nkp = SIZE(wkp_full) + ALLOCATE (kpoint%xkp(3, kpoint%nkp), kpoint%wkp(kpoint%nkp)) + kpoint%xkp(1:3, 1:kpoint%nkp) = xkp_full(1:3, 1:kpoint%nkp) + kpoint%wkp(1:kpoint%nkp) = wkp_full(1:kpoint%nkp) + END IF + ! default: no symmetry settings + ALLOCATE (kpoint%kp_sym(kpoint%nkp)) + DO i = 1, kpoint%nkp + NULLIFY (kpoint%kp_sym(i)%kpoint_sym) + CALL kpoint_sym_create(kpoint%kp_sym(i)%kpoint_sym) + END DO + ELSE + IF (kpoint%verbose) THEN + iounit = cp_logger_get_default_io_unit() + ELSE + iounit = -1 + END IF + natom = SIZE(particle_set) + ALLOCATE (scoord(3, natom), atype(natom)) + DO i = 1, natom + CALL get_atomic_kind(atomic_kind=particle_set(i)%atomic_kind, kind_number=atype(i)) + CALL real_to_scaled(scoord(1:3, i), particle_set(i)%r(1:3), cell) + END DO + ALLOCATE (kpoint%atype(natom)) + kpoint%atype = atype + ALLOCATE (agauge(3, natom)) + DO i = 1, natom + agauge(1:3, i) = -FLOOR(scoord(1:3, i) + 0.5_dp - kpoint%eps_geo) + END DO + + CALL crys_sym_gen(crys_sym, scoord, atype, cell%hmat, delta=kpoint%eps_geo, iounit=iounit, & + use_spglib=(kpoint%symmetry_backend == use_spglib_kpoint_backend .OR. & + kpoint%symmetry_reduction_method == use_spglib_kpoint_symmetry)) + CALL kpoint_gen_general(crys_sym, xkp_full, wkp_full, symm=kpoint%symmetry, & + full_grid=kpoint%full_grid, & + inversion_symmetry_only=kpoint%inversion_symmetry_only, & + use_spglib_reduction= & + kpoint%symmetry_reduction_method == use_spglib_kpoint_symmetry, & + use_spglib_backend=kpoint%symmetry_backend == use_spglib_kpoint_backend) + IF (ASSOCIATED(kpoint%xkp)) THEN + DEALLOCATE (kpoint%xkp) + NULLIFY (kpoint%xkp) + END IF + IF (ASSOCIATED(kpoint%wkp)) THEN + DEALLOCATE (kpoint%wkp) + NULLIFY (kpoint%wkp) + END IF + kpoint%nkp = crys_sym%nkpoint + ALLOCATE (kpoint%xkp(3, kpoint%nkp), kpoint%wkp(kpoint%nkp)) + wsum = SUM(crys_sym%wkpoint) + DO ik = 1, kpoint%nkp + kpoint%xkp(1:3, ik) = crys_sym%xkpoint(1:3, ik) + kpoint%wkp(ik) = crys_sym%wkpoint(ik)/wsum + END DO + + CALL print_crys_symmetry(crys_sym) + CALL print_kp_symmetry(crys_sym) + + ALLOCATE (kpoint%kp_sym(kpoint%nkp)) + DO ik = 1, kpoint%nkp + NULLIFY (kpoint%kp_sym(ik)%kpoint_sym) + CALL kpoint_sym_create(kpoint%kp_sym(ik)%kpoint_sym) + kpsym => kpoint%kp_sym(ik)%kpoint_sym + IF (crys_sym%nrtot > 0 .AND. .NOT. crys_sym%fullgrid .AND. & + crys_sym%istriz == 1 .AND. .NOT. crys_sym%inversion_only) THEN + kpsym%nwght = NINT(crys_sym%wkpoint(ik)) + ns = kpsym%nwght + IF (ns > 1) THEN + kpsym%apply_symmetry = .TRUE. + ALLOCATE (kpsym%rot(3, 3, ns)) + ALLOCATE (kpsym%xkp(3, ns)) + ALLOCATE (kpsym%rotp(ns)) + ALLOCATE (kpsym%f0(natom, ns)) + ALLOCATE (kpsym%fcell(3, 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) + ira = ABS(ir) + DO ic = 1, crys_sym%nrtot + IF (crys_sym%ibrot(ic) == ira) THEN + kpsym%rotp(nr) = ir + kpsym%rot(1:3, 1:3, nr) = crys_sym%rt(1:3, 1:3, ic) + srotmat = MATMUL(cell%h_inv, MATMUL(crys_sym%rt(1:3, 1:3, ic), cell%hmat)) + frot(1:3, 1:3) = NINT(srotmat(1:3, 1:3)) + kpsym%xkp(1:3, nr) = crys_sym%kpmesh(1:3, is) + kpsym%f0(1:natom, nr) = crys_sym%f0(1:natom, ic) + DO j = 1, natom + srot(1:3) = MATMUL(srotmat, scoord(1:3, j)) + crys_sym%vt(1:3, ic) + kpsym%fcell(1:3, j, nr) = & + NINT(srot(1:3) - scoord(1:3, kpsym%f0(j, nr))) + & + MATMUL(frot(1:3, 1:3), agauge(1:3, j)) - & + agauge(1:3, kpsym%f0(j, nr)) + END DO + EXIT + END IF + END DO + CPASSERT(ic <= crys_sym%nrtot) + END IF + END DO + kpsym%nwred = nr + END IF + END IF + END DO + 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 + ALLOCATE (kpoint%ibrot(ns)) + kpoint%ibrot(1:ns) = crys_sym%ibrot(1:ns) + + CALL release_csym_type(crys_sym) + DEALLOCATE (scoord, atype) + DEALLOCATE (agauge) END IF - ! default: no symmetry settings - ALLOCATE (kpoint%kp_sym(kpoint%nkp)) - DO i = 1, kpoint%nkp - NULLIFY (kpoint%kp_sym(i)%kpoint_sym) - CALL kpoint_sym_create(kpoint%kp_sym(i)%kpoint_sym) - END DO CASE DEFAULT CPASSERT(.FALSE.) END SELECT @@ -307,7 +431,6 @@ CONTAINS CPASSERT(kpoint%wkp(1) == 1.0_dp) CPASSERT(.NOT. kpoint%symmetry) CASE ("GENERAL") - CPASSERT(.NOT. kpoint%symmetry) CPASSERT(kpoint%nkp >= 1) CASE ("MONKHORST-PACK", "MACDONALD") CPASSERT(kpoint%nkp >= 1) diff --git a/src/kpoint_types.F b/src/kpoint_types.F index cac4bd1a48..e1e8aa83f9 100644 --- a/src/kpoint_types.F +++ b/src/kpoint_types.F @@ -150,6 +150,8 @@ MODULE kpoint_types !> \param nkp number of kpoints !> \param xkp kpoint coordinates !> \param wkp kpoint weights +!> \param xkp_input explicit GENERAL kpoint coordinates as read from the input +!> \param wkp_input explicit GENERAL kpoint weights as read from the input !> \param para_env 'global' parallel environment !> \param para_env_kp parallel environment of the kpoint calculation !> \param para_env_inter_kp parallel environment between kpoints @@ -180,6 +182,8 @@ MODULE kpoint_types INTEGER :: nkp = -1 REAL(KIND=dp), DIMENSION(:, :), POINTER :: xkp => Null() REAL(KIND=dp), DIMENSION(:), POINTER :: wkp => Null() + REAL(KIND=dp), DIMENSION(:, :), POINTER :: xkp_input => Null() + REAL(KIND=dp), DIMENSION(:), POINTER :: wkp_input => Null() ! parallel environment TYPE(mp_para_env_type), POINTER :: para_env => Null() TYPE(cp_blacs_env_type), POINTER :: blacs_env_all => Null() @@ -246,6 +250,7 @@ CONTAINS kpoint%nkp = 0 NULLIFY (kpoint%xkp, kpoint%wkp) + NULLIFY (kpoint%xkp_input, kpoint%wkp_input) NULLIFY (kpoint%kp_dist) NULLIFY (kpoint%para_env) @@ -285,6 +290,12 @@ CONTAINS IF (ASSOCIATED(kpoint%wkp)) THEN DEALLOCATE (kpoint%wkp) END IF + IF (ASSOCIATED(kpoint%xkp_input)) THEN + DEALLOCATE (kpoint%xkp_input) + END IF + IF (ASSOCIATED(kpoint%wkp_input)) THEN + DEALLOCATE (kpoint%wkp_input) + END IF IF (ASSOCIATED(kpoint%kp_dist)) THEN DEALLOCATE (kpoint%kp_dist) END IF @@ -366,6 +377,13 @@ CONTAINS DEALLOCATE (kpoint%wkp) NULLIFY (kpoint%wkp) END IF + IF (kpoint%kp_scheme == "GENERAL" .AND. ASSOCIATED(kpoint%xkp_input) .AND. & + ASSOCIATED(kpoint%wkp_input)) THEN + kpoint%nkp = SIZE(kpoint%wkp_input) + ALLOCATE (kpoint%xkp(3, kpoint%nkp), kpoint%wkp(kpoint%nkp)) + kpoint%xkp(1:3, 1:kpoint%nkp) = kpoint%xkp_input(1:3, 1:kpoint%nkp) + kpoint%wkp(1:kpoint%nkp) = kpoint%wkp_input(1:kpoint%nkp) + END IF IF (ASSOCIATED(kpoint%kp_dist)) THEN DEALLOCATE (kpoint%kp_dist) NULLIFY (kpoint%kp_dist) @@ -451,7 +469,7 @@ CONTAINS ALLOCATE (kpoint%index_to_cell(0:0, 0:0)) kpoint%index_to_cell(:, :) = 0 - kpoint%nkp = 0 + IF (.NOT. ASSOCIATED(kpoint%wkp)) kpoint%nkp = 0 kpoint%nkp_groups = 0 kpoint%kp_range = 0 kpoint%iogrp = .FALSE. @@ -749,6 +767,14 @@ CONTAINS CALL uppercase(ustr) CALL section_vals_val_get(kpoint_section, "KPOINT", n_rep_val=n_rep) kpoint%nkp = n_rep + IF (ASSOCIATED(kpoint%xkp_input)) THEN + DEALLOCATE (kpoint%xkp_input) + NULLIFY (kpoint%xkp_input) + END IF + IF (ASSOCIATED(kpoint%wkp_input)) THEN + DEALLOCATE (kpoint%wkp_input) + NULLIFY (kpoint%wkp_input) + END IF ALLOCATE (kpoint%xkp(3, n_rep), kpoint%wkp(n_rep)) DO i = 1, n_rep CALL section_vals_val_get(kpoint_section, "KPOINT", i_rep_val=i, & @@ -773,6 +799,9 @@ CONTAINS END DO ff = 1.0_dp/SUM(kpoint%wkp(:)) kpoint%wkp(:) = ff*kpoint%wkp(:) + ALLOCATE (kpoint%xkp_input(3, n_rep), kpoint%wkp_input(n_rep)) + kpoint%xkp_input(1:3, 1:n_rep) = kpoint%xkp(1:3, 1:n_rep) + kpoint%wkp_input(1:n_rep) = kpoint%wkp(1:n_rep) CASE DEFAULT CPABORT("") END SELECT @@ -911,7 +940,8 @@ CONTAINS END IF IF (kpoint%symmetry .AND. .NOT. kpoint%full_grid .AND. & .NOT. kpoint%inversion_symmetry_only .AND. & - (kpoint%kp_scheme == "MONKHORST-PACK" .OR. kpoint%kp_scheme == "MACDONALD")) THEN + (kpoint%kp_scheme == "MONKHORST-PACK" .OR. kpoint%kp_scheme == "MACDONALD" .OR. & + kpoint%kp_scheme == "GENERAL")) THEN SELECT CASE (kpoint%symmetry_backend) CASE (use_k290_kpoint_backend) WRITE (punit, '(A,T73,A)') ' BRILLOUIN| Symmetry backend', ' K290' diff --git a/src/qs_wannier90.F b/src/qs_wannier90.F index fe637f5ef3..36f3c65ddb 100644 --- a/src/qs_wannier90.F +++ b/src/qs_wannier90.F @@ -166,7 +166,8 @@ CONTAINS INTEGER, DIMENSION(:), POINTER :: invals INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index LOGICAL :: diis_step, do_kpoints, gamma_only, & - my_kpgrp, mygrp, spinors + input_kpoint_symmetry, my_kpgrp, & + mygrp, spinors REAL(KIND=dp) :: cmmn, ksign, rmmn REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: eigval REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: atoms_cart, b_latt, kpt_latt @@ -185,7 +186,7 @@ CONTAINS TYPE(dbcsr_type), POINTER :: cmatrix, rmatrix TYPE(dft_control_type), POINTER :: dft_control TYPE(kpoint_env_type), POINTER :: kp - TYPE(kpoint_type), POINTER :: kpoint + TYPE(kpoint_type), POINTER :: kpoint, qs_kpoint TYPE(mo_set_type), DIMENSION(:), POINTER :: mos TYPE(mp_para_env_type), POINTER :: para_env TYPE(neighbor_list_set_p_type), DIMENSION(:), & @@ -231,7 +232,7 @@ CONTAINS ! k-points ALLOCATE (kpt_latt(3, num_kpts)) CALL get_qs_env(qs_env, particle_set=particle_set) - NULLIFY (kpoint) + NULLIFY (kpoint, qs_kpoint) CALL kpoint_create(kpoint) kpoint%kp_scheme = "MONKHORST-PACK" kpoint%symmetry = .FALSE. @@ -331,7 +332,17 @@ CONTAINS ! calculate bands NULLIFY (qs_env_kp) - CALL get_qs_env(qs_env, do_kpoints=do_kpoints) + CALL get_qs_env(qs_env, do_kpoints=do_kpoints, kpoints=qs_kpoint) + input_kpoint_symmetry = .FALSE. + IF (do_kpoints .AND. ASSOCIATED(qs_kpoint)) THEN + CALL get_kpoint_info(qs_kpoint, symmetry=input_kpoint_symmetry) + END IF + IF (input_kpoint_symmetry .AND. iw > 0) THEN + WRITE (iw, '(T2,A)') & + "WANNIER90| Atomic k-point symmetry from the SCF calculation is not reused." + WRITE (iw, '(T2,A)') & + "WANNIER90| A full Monkhorst-Pack grid is generated for the Wannier90 interface." + END IF IF (do_kpoints) THEN ! we already do kpoints qs_env_kp => qs_env diff --git a/tests/QS/regtest-kp-1-spglib/TEST_FILES.toml b/tests/QS/regtest-kp-1-spglib/TEST_FILES.toml index 6b2936ec82..fc46e70238 100644 --- a/tests/QS/regtest-kp-1-spglib/TEST_FILES.toml +++ b/tests/QS/regtest-kp-1-spglib/TEST_FILES.toml @@ -17,6 +17,12 @@ {matcher="N_special_kpoints", tol=0.0, ref=1}] "h_fcc_macdonald_spglib_backend.inp" = [{matcher="E_total", tol=1e-13, ref=-4.35025489265897}, {matcher="N_special_kpoints", tol=0.0, ref=1}] +"h_fcc_general_spglib_backend.inp" = [{matcher="E_total", tol=1e-13, ref=-4.34524388359536}, + {matcher="N_special_kpoints", tol=0.0, ref=1}] +"h_fcc_general_spglib_method_k290_backend.inp" = [{matcher="E_total", tol=1e-13, ref=-4.34524388359536}, + {matcher="N_special_kpoints", tol=0.0, ref=1}] +"h_fcc_general_geo_opt_spglib_backend.inp" = [{matcher="E_total", tol=1e-8, ref=-4.34524388162712}, + {matcher="N_special_kpoints", tol=0.0, ref=1}] "h_fcc_spglib_backend_4.inp" = [{matcher="E_total", tol=1e-13, ref=-4.31445892211372}, {matcher="N_special_kpoints", tol=0.0, ref=4}] #EOF diff --git a/tests/QS/regtest-kp-1-spglib/h_fcc_general_geo_opt_spglib_backend.inp b/tests/QS/regtest-kp-1-spglib/h_fcc_general_geo_opt_spglib_backend.inp new file mode 100644 index 0000000000..5ed158d337 --- /dev/null +++ b/tests/QS/regtest-kp-1-spglib/h_fcc_general_geo_opt_spglib_backend.inp @@ -0,0 +1,86 @@ +&GLOBAL + PRINT_LEVEL LOW + PROJECT H_FCC_GENERAL_GEO_OPT_SPGLIB_BACKEND + RUN_TYPE GEO_OPT +&END GLOBAL + +&MOTION + &GEO_OPT + KEEP_SPACE_GROUP T + MAX_ITER 1 + &END GEO_OPT +&END MOTION + +&FORCE_EVAL + METHOD Quickstep + &DFT + BASIS_SET_FILE_NAME BASIS_MOLOPT_UZH + POTENTIAL_FILE_NAME POTENTIAL_UZH + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + KPOINT -0.25 -0.25 -0.25 1.0 + KPOINT -0.25 -0.25 0.25 1.0 + KPOINT -0.25 0.25 -0.25 1.0 + KPOINT -0.25 0.25 0.25 1.0 + KPOINT 0.25 -0.25 -0.25 1.0 + KPOINT 0.25 -0.25 0.25 1.0 + KPOINT 0.25 0.25 -0.25 1.0 + KPOINT 0.25 0.25 0.25 1.0 + PARALLEL_GROUP_SIZE -1 + SCHEME GENERAL + SYMMETRY ON + SYMMETRY_BACKEND SPGLIB + VERBOSE T + WAVEFUNCTIONS COMPLEX + &END KPOINTS + &MGRID + CUTOFF 100 + REL_CUTOFF 30 + &END MGRID + &QS + EPS_DEFAULT 1.0E-10 + METHOD GPW + &END QS + &SCF + CHOLESKY OFF + EPS_EIGVAL 1.e-8 + EPS_SCF 1.0E-6 + IGNORE_CONVERGENCE_FAILURE + MAX_SCF 6 + SCF_GUESS ATOMIC + &MIXING + ALPHA 0.70 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &XC + &XC_FUNCTIONAL PBE + &END XC_FUNCTIONAL + &END XC + &END DFT + &SUBSYS + &CELL + ABC 3.56683 3.56683 3.56683 + &END CELL + &COORD + SCALED + H 0.000000 0.000000 0.000000 + H 0.500000 0.500000 0.000000 + H 0.500000 0.000000 0.500000 + H 0.000000 0.500000 0.500000 + H 0.250000 0.250000 0.250000 + H 0.250000 0.750000 0.750000 + H 0.750000 0.250000 0.750000 + H 0.750000 0.750000 0.250000 + &END COORD + &KIND H + BASIS_SET ORB DZVP-MOLOPT-GGA-GTH-q1 + POTENTIAL GTH-GGA-q1 + &END KIND + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/QS/regtest-kp-1-spglib/h_fcc_general_spglib_backend.inp b/tests/QS/regtest-kp-1-spglib/h_fcc_general_spglib_backend.inp new file mode 100644 index 0000000000..e812776f98 --- /dev/null +++ b/tests/QS/regtest-kp-1-spglib/h_fcc_general_spglib_backend.inp @@ -0,0 +1,77 @@ +&GLOBAL + PRINT_LEVEL LOW + PROJECT H_FCC_GENERAL_SPGLIB_BACKEND + RUN_TYPE ENERGY +&END GLOBAL + +&FORCE_EVAL + &DFT + BASIS_SET_FILE_NAME BASIS_MOLOPT_UZH + POTENTIAL_FILE_NAME POTENTIAL_UZH + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + KPOINT -0.25 -0.25 -0.25 1.0 + KPOINT -0.25 -0.25 0.25 1.0 + KPOINT -0.25 0.25 -0.25 1.0 + KPOINT -0.25 0.25 0.25 1.0 + KPOINT 0.25 -0.25 -0.25 1.0 + KPOINT 0.25 -0.25 0.25 1.0 + KPOINT 0.25 0.25 -0.25 1.0 + KPOINT 0.25 0.25 0.25 1.0 + PARALLEL_GROUP_SIZE -1 + SCHEME GENERAL + SYMMETRY ON + SYMMETRY_BACKEND SPGLIB + VERBOSE T + WAVEFUNCTIONS COMPLEX + &END KPOINTS + &MGRID + CUTOFF 100 + REL_CUTOFF 30 + &END MGRID + &QS + EPS_DEFAULT 1.0E-10 + METHOD GPW + &END QS + &SCF + CHOLESKY OFF + EPS_EIGVAL 1.e-8 + EPS_SCF 1.0E-9 + MAX_SCF 100 + SCF_GUESS ATOMIC + &MIXING + ALPHA 0.50 + METHOD BROYDEN_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &XC + &XC_FUNCTIONAL PBE + &END XC_FUNCTIONAL + &END XC + &END DFT + &SUBSYS + &CELL + ABC 3.56683 3.56683 3.56683 + &END CELL + &COORD + SCALED + H 0.000000 0.000000 0.000000 + H 0.500000 0.500000 0.000000 + H 0.500000 0.000000 0.500000 + H 0.000000 0.500000 0.500000 + H 0.250000 0.250000 0.250000 + H 0.250000 0.750000 0.750000 + H 0.750000 0.250000 0.750000 + H 0.750000 0.750000 0.250000 + &END COORD + &KIND H + BASIS_SET ORB DZVP-MOLOPT-GGA-GTH-q1 + POTENTIAL GTH-GGA-q1 + &END KIND + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/QS/regtest-kp-1-spglib/h_fcc_general_spglib_method_k290_backend.inp b/tests/QS/regtest-kp-1-spglib/h_fcc_general_spglib_method_k290_backend.inp new file mode 100644 index 0000000000..1bf1eae898 --- /dev/null +++ b/tests/QS/regtest-kp-1-spglib/h_fcc_general_spglib_method_k290_backend.inp @@ -0,0 +1,78 @@ +&GLOBAL + PRINT_LEVEL LOW + PROJECT H_FCC_GENERAL_SPGLIB_METHOD_K290_BACKEND + RUN_TYPE ENERGY +&END GLOBAL + +&FORCE_EVAL + &DFT + BASIS_SET_FILE_NAME BASIS_MOLOPT_UZH + POTENTIAL_FILE_NAME POTENTIAL_UZH + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + KPOINT -0.25 -0.25 -0.25 1.0 + KPOINT -0.25 -0.25 0.25 1.0 + KPOINT -0.25 0.25 -0.25 1.0 + KPOINT -0.25 0.25 0.25 1.0 + KPOINT 0.25 -0.25 -0.25 1.0 + KPOINT 0.25 -0.25 0.25 1.0 + KPOINT 0.25 0.25 -0.25 1.0 + KPOINT 0.25 0.25 0.25 1.0 + PARALLEL_GROUP_SIZE -1 + SCHEME GENERAL + SYMMETRY ON + SYMMETRY_BACKEND K290 + SYMMETRY_REDUCTION_METHOD SPGLIB + VERBOSE T + WAVEFUNCTIONS COMPLEX + &END KPOINTS + &MGRID + CUTOFF 100 + REL_CUTOFF 30 + &END MGRID + &QS + EPS_DEFAULT 1.0E-10 + METHOD GPW + &END QS + &SCF + CHOLESKY OFF + EPS_EIGVAL 1.e-8 + EPS_SCF 1.0E-9 + MAX_SCF 100 + SCF_GUESS ATOMIC + &MIXING + ALPHA 0.50 + METHOD BROYDEN_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &XC + &XC_FUNCTIONAL PBE + &END XC_FUNCTIONAL + &END XC + &END DFT + &SUBSYS + &CELL + ABC 3.56683 3.56683 3.56683 + &END CELL + &COORD + SCALED + H 0.000000 0.000000 0.000000 + H 0.500000 0.500000 0.000000 + H 0.500000 0.000000 0.500000 + H 0.000000 0.500000 0.500000 + H 0.250000 0.250000 0.250000 + H 0.250000 0.750000 0.750000 + H 0.750000 0.250000 0.750000 + H 0.750000 0.750000 0.250000 + &END COORD + &KIND H + BASIS_SET ORB DZVP-MOLOPT-GGA-GTH-q1 + POTENTIAL GTH-GGA-q1 + &END KIND + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/QS/regtest-kp-1/TEST_FILES.toml b/tests/QS/regtest-kp-1/TEST_FILES.toml index f82ad1f02d..a79ccb19fb 100644 --- a/tests/QS/regtest-kp-1/TEST_FILES.toml +++ b/tests/QS/regtest-kp-1/TEST_FILES.toml @@ -36,5 +36,7 @@ {matcher="N_special_kpoints", tol=0.0, ref=12}] "h_hex_c3_gamma_macdonald_spglib.inp" = [{matcher="E_total", tol=1e-7, ref=-9.41375200649571}, {matcher="N_special_kpoints", tol=0.0, ref=12}] +"h_fcc_general_k290.inp" = [{matcher="E_total", tol=1e-13, ref=-4.34524388359535}, + {matcher="N_special_kpoints", tol=0.0, ref=1}] "h_tetra_c4_sym_red.inp" = [{matcher="E_total", tol=1e-8, ref=-3.95113501866984}] #EOF diff --git a/tests/QS/regtest-kp-1/h_fcc_general_k290.inp b/tests/QS/regtest-kp-1/h_fcc_general_k290.inp new file mode 100644 index 0000000000..5ddbd7932e --- /dev/null +++ b/tests/QS/regtest-kp-1/h_fcc_general_k290.inp @@ -0,0 +1,77 @@ +&GLOBAL + PRINT_LEVEL LOW + PROJECT H_FCC_GENERAL_K290 + RUN_TYPE ENERGY +&END GLOBAL + +&FORCE_EVAL + &DFT + BASIS_SET_FILE_NAME BASIS_MOLOPT_UZH + POTENTIAL_FILE_NAME POTENTIAL_UZH + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + KPOINT -0.25 -0.25 -0.25 1.0 + KPOINT -0.25 -0.25 0.25 1.0 + KPOINT -0.25 0.25 -0.25 1.0 + KPOINT -0.25 0.25 0.25 1.0 + KPOINT 0.25 -0.25 -0.25 1.0 + KPOINT 0.25 -0.25 0.25 1.0 + KPOINT 0.25 0.25 -0.25 1.0 + KPOINT 0.25 0.25 0.25 1.0 + PARALLEL_GROUP_SIZE -1 + SCHEME GENERAL + SYMMETRY ON + SYMMETRY_BACKEND K290 + VERBOSE T + WAVEFUNCTIONS COMPLEX + &END KPOINTS + &MGRID + CUTOFF 100 + REL_CUTOFF 30 + &END MGRID + &QS + EPS_DEFAULT 1.0E-10 + METHOD GPW + &END QS + &SCF + CHOLESKY OFF + EPS_EIGVAL 1.e-8 + EPS_SCF 1.0E-9 + MAX_SCF 100 + SCF_GUESS ATOMIC + &MIXING + ALPHA 0.50 + METHOD BROYDEN_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &XC + &XC_FUNCTIONAL PBE + &END XC_FUNCTIONAL + &END XC + &END DFT + &SUBSYS + &CELL + ABC 3.56683 3.56683 3.56683 + &END CELL + &COORD + SCALED + H 0.000000 0.000000 0.000000 + H 0.500000 0.500000 0.000000 + H 0.500000 0.000000 0.500000 + H 0.000000 0.500000 0.500000 + H 0.250000 0.250000 0.250000 + H 0.250000 0.750000 0.750000 + H 0.750000 0.250000 0.750000 + H 0.750000 0.750000 0.250000 + &END COORD + &KIND H + BASIS_SET ORB DZVP-MOLOPT-GGA-GTH-q1 + POTENTIAL GTH-GGA-q1 + &END KIND + &END SUBSYS +&END FORCE_EVAL