30#include "./base/base_uses.f90"
37 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cryssym'
45 LOGICAL :: symlib = .false.
46 LOGICAL :: fullgrid = .false.
47 LOGICAL :: inversion_only = .false.
48 LOGICAL :: spglib_reduction = .false.
49 LOGICAL :: spglib_backend = .false.
52 INTEGER :: istriz = -1
53 REAL(kind=
dp) :: delta = 1.0e-8_dp
54 REAL(kind=
dp),
DIMENSION(3, 3) :: hmat = 0.0_dp
56 REAL(kind=
dp),
DIMENSION(3) :: wvk0 = 0.0_dp
57 INTEGER,
DIMENSION(3) :: mesh = 0
58 INTEGER :: nkpoint = 0
60 INTEGER,
DIMENSION(:),
ALLOCATABLE :: atype
61 REAL(kind=
dp),
DIMENSION(:, :),
ALLOCATABLE :: scoord
62 REAL(kind=
dp),
DIMENSION(:, :),
ALLOCATABLE :: xkpoint
63 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: wkpoint
64 REAL(kind=
dp),
DIMENSION(:, :),
ALLOCATABLE :: kpmesh
65 INTEGER,
DIMENSION(:, :),
ALLOCATABLE :: kplink
66 INTEGER,
DIMENSION(:),
ALLOCATABLE :: kpop
68 CHARACTER(len=11) :: international_symbol =
""
69 CHARACTER(len=6) :: pointgroup_symbol =
""
70 CHARACTER(len=10) :: schoenflies =
""
71 INTEGER :: n_operations = 0
72 INTEGER,
DIMENSION(:, :, :),
ALLOCATABLE :: rotations
73 REAL(kind=
dp),
DIMENSION(:, :),
ALLOCATABLE :: translations
75 REAL(kind=
dp),
DIMENSION(:, :, :),
ALLOCATABLE :: rt
76 REAL(kind=
dp),
DIMENSION(:, :),
ALLOCATABLE :: vt
77 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: f0
79 INTEGER,
DIMENSION(:),
ALLOCATABLE :: ibrot
91 IF (
ALLOCATED(csym%rotations))
THEN
92 DEALLOCATE (csym%rotations)
94 IF (
ALLOCATED(csym%translations))
THEN
95 DEALLOCATE (csym%translations)
97 IF (
ALLOCATED(csym%atype))
THEN
98 DEALLOCATE (csym%atype)
100 IF (
ALLOCATED(csym%scoord))
THEN
101 DEALLOCATE (csym%scoord)
103 IF (
ALLOCATED(csym%xkpoint))
THEN
104 DEALLOCATE (csym%xkpoint)
106 IF (
ALLOCATED(csym%wkpoint))
THEN
107 DEALLOCATE (csym%wkpoint)
109 IF (
ALLOCATED(csym%kpmesh))
THEN
110 DEALLOCATE (csym%kpmesh)
112 IF (
ALLOCATED(csym%kplink))
THEN
113 DEALLOCATE (csym%kplink)
115 IF (
ALLOCATED(csym%kpop))
THEN
116 DEALLOCATE (csym%kpop)
118 IF (
ALLOCATED(csym%rt))
THEN
121 IF (
ALLOCATED(csym%vt))
THEN
124 IF (
ALLOCATED(csym%f0))
THEN
127 IF (
ALLOCATED(csym%ibrot))
THEN
128 DEALLOCATE (csym%ibrot)
144 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: scoor
145 INTEGER,
DIMENSION(:),
INTENT(IN) :: types
146 REAL(kind=
dp),
INTENT(IN) :: hmat(3, 3)
147 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: delta
148 INTEGER,
INTENT(IN),
OPTIONAL :: iounit
150 CHARACTER(LEN=*),
PARAMETER :: routinen =
'crys_sym_gen'
152 INTEGER :: handle, ierr, major, micro, minor, nat, &
156 CALL timeset(routinen, handle)
163 IF (
PRESENT(iounit))
THEN
170 IF (
PRESENT(delta))
THEN
173 csym%delta = 1.e-6_dp
180 ALLOCATE (csym%atype(nat))
181 csym%atype(1:nat) = types(1:nat)
184 ALLOCATE (csym%scoord(3, nat))
185 csym%scoord(1:3, 1:nat) = scoor(1:3, 1:nat)
187 csym%n_operations = 0
194 CALL cp_warn(__location__,
"Symmetry library SPGLIB not available")
201 CALL cp_warn(__location__,
"Symmetry Library SPGLIB failed")
205 ALLOCATE (csym%rotations(3, 3, nop), csym%translations(3, nop))
206 csym%n_operations = nop
208 transpose(hmat), scoor, types, nat, delta)
210 csym%schoenflies =
' '
213 csym%pointgroup_symbol =
' '
216 csym%rotations, csym%n_operations)
225 CALL timestop(handle)
240 SUBROUTINE kpoint_gen(csym, nk, symm, shift, full_grid, inversion_symmetry_only, &
241 use_spglib_reduction, use_spglib_backend)
243 INTEGER,
INTENT(IN) :: nk(3)
244 LOGICAL,
INTENT(IN),
OPTIONAL :: symm
245 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: shift(3)
246 LOGICAL,
INTENT(IN),
OPTIONAL :: full_grid, inversion_symmetry_only, &
247 use_spglib_reduction, &
250 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_gen'
252 INTEGER :: handle, i, ik, j, nkp, nkpts
253 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: kpop, xptr
254 LOGICAL :: fullmesh, inversion_only, &
255 orthorhombic_cell, spglib_backend, &
257 REAL(kind=
dp) :: cell_eps
258 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: wkp
259 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: xkp
261 CALL timeset(routinen, handle)
263 IF (
PRESENT(shift))
THEN
270 IF (
PRESENT(symm))
THEN
271 IF (symm) csym%istriz = 1
274 IF (
PRESENT(full_grid))
THEN
279 csym%fullgrid = fullmesh
281 IF (
PRESENT(inversion_symmetry_only))
THEN
282 inversion_only = inversion_symmetry_only
284 inversion_only = .false.
286 csym%inversion_only = inversion_only
288 IF (
PRESENT(use_spglib_reduction))
THEN
289 spglib_reduction = use_spglib_reduction
291 spglib_reduction = .false.
293 csym%spglib_reduction = spglib_reduction
295 IF (
PRESENT(use_spglib_backend))
THEN
296 spglib_backend = use_spglib_backend
298 spglib_backend = .false.
300 csym%spglib_backend = spglib_backend
302 cell_eps = 10.0_dp*csym%delta*max(1.0_dp, maxval(abs(csym%hmat)))
303 orthorhombic_cell = abs(csym%hmat(1, 2)) + abs(csym%hmat(1, 3)) + &
304 abs(csym%hmat(2, 1)) + abs(csym%hmat(2, 3)) + &
305 abs(csym%hmat(3, 1)) + abs(csym%hmat(3, 2)) <= cell_eps
307 IF (spglib_backend .AND. .NOT. spglib_reduction)
THEN
308 CALL cp_abort(__location__, &
309 "SYMMETRY_BACKEND SPGLIB requires SYMMETRY_REDUCTION_METHOD SPGLIB")
313 csym%mesh(1:3) = nk(1:3)
315 IF (
ALLOCATED(csym%rt))
DEALLOCATE (csym%rt)
316 IF (
ALLOCATED(csym%vt))
DEALLOCATE (csym%vt)
317 IF (
ALLOCATED(csym%ibrot))
DEALLOCATE (csym%ibrot)
318 IF (
ALLOCATED(csym%f0))
DEALLOCATE (csym%f0)
319 ALLOCATE (csym%rt(3, 3, 0), csym%vt(3, 0), csym%ibrot(0), csym%f0(csym%nat, 0))
321 nkpts = nk(1)*nk(2)*nk(3)
322 ALLOCATE (xkp(3, nkpts), wkp(nkpts), kpop(nkpts))
324 ALLOCATE (csym%kplink(2, nkpts))
329 IF (csym%symlib)
THEN
333 CALL full_grid_gen(nk, xkp, wkp, shift)
334 IF (csym%istriz == 1)
THEN
336 CALL inversion_symm(xkp, wkp, csym%kplink(1, :))
340 ELSE IF (csym%istriz /= 1 .OR. inversion_only)
THEN
342 CALL full_grid_gen(nk, xkp, wkp, shift)
343 CALL inversion_symm(xkp, wkp, csym%kplink(1, :))
346 IF (sum(abs(csym%wvk0)) /= 0.0_dp)
THEN
347 CALL cp_abort(__location__,
"MacDonald shifted k-point meshes are only "// &
348 "possible without symmetrization.")
351 CALL full_grid_gen(nk, xkp, wkp, shift)
352 IF (spglib_backend)
THEN
353 CALL kp_symmetry_spglib(csym, xkp, wkp, kpop)
355 CALL kp_symmetry(csym, xkp, wkp, kpop, use_spglib_reduction=spglib_reduction)
361 CALL full_grid_gen(nk, xkp, wkp, shift)
362 IF (csym%istriz == 1 .AND. .NOT. fullmesh .AND. .NOT. inversion_only .AND. &
363 orthorhombic_cell)
THEN
365 IF (sum(abs(csym%wvk0)) /= 0.0_dp)
THEN
366 CALL cp_abort(__location__,
"MacDonald shifted k-point meshes are only "// &
367 "possible without symmetrization.")
369 CALL kp_symmetry(csym, xkp, wkp, kpop, use_spglib_reduction=.false.)
370 ELSE IF (csym%istriz /= 1 .AND. fullmesh)
THEN
373 csym%kplink(1, i) = i
377 CALL inversion_symm(xkp, wkp, csym%kplink(1, :))
383 IF (wkp(i) > 0.0_dp) nkp = nkp + 1
388 ALLOCATE (csym%xkpoint(3, nkp), csym%wkpoint(nkp))
392 IF (wkp(ik) > 0.0_dp)
THEN
394 csym%wkpoint(j) = wkp(ik)
395 csym%xkpoint(1:3, j) = xkp(1:3, ik)
402 ALLOCATE (csym%kpmesh(3, nkpts))
403 csym%kpmesh(1:3, 1:nkpts) = xkp(1:3, 1:nkpts)
407 i = csym%kplink(1, ik)
409 IF (i == xptr(j))
THEN
410 csym%kplink(2, ik) = j
418 ALLOCATE (csym%kpop(nkpts))
419 IF (csym%nrtot > 0 .AND. csym%istriz == 1 .AND. .NOT. fullmesh .AND. &
420 .NOT. inversion_only)
THEN
422 csym%kpop(1:nkpts) = kpop(1:nkpts)
424 cpassert(csym%kpop(ik) /= 0)
429 IF (wkp(ik) > 0.0_dp)
THEN
437 DEALLOCATE (xkp, wkp, kpop)
439 CALL timestop(handle)
451 SUBROUTINE kp_symmetry(csym, xkp, wkp, kpop, use_spglib_reduction)
453 REAL(kind=
dp),
DIMENSION(:, :) :: xkp
454 REAL(kind=
dp),
DIMENSION(:) :: wkp
455 INTEGER,
DIMENSION(:) :: kpop
456 LOGICAL,
INTENT(IN),
OPTIONAL :: use_spglib_reduction
458 INTEGER :: i, ihc, ihg, indpg, iou, iq1, iq2, iq3, &
459 istriz, isy, li, nat, nc, nhash, &
460 nkpoint, nrot, nsp, ntvec
461 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: includ, isc,
list, lwght, ty
462 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: f0, lrot
463 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: srot
464 INTEGER,
DIMENSION(48) :: ib
465 LOGICAL :: spglib_reduction
466 REAL(kind=
dp) :: alat
467 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: rlist, rx, tvec, wvkl, xkapa
468 REAL(kind=
dp),
DIMENSION(3) :: a1, a2, a3, b1, b2, b3, origin, wvk0
469 REAL(kind=
dp),
DIMENSION(3, 3) :: hmat, strain
470 REAL(kind=
dp),
DIMENSION(3, 3, 48) :: r
471 REAL(kind=
dp),
DIMENSION(3, 48) :: vt
479 nkpoint = 10*iq1*iq2*iq3
482 IF (
PRESENT(use_spglib_reduction))
THEN
483 spglib_reduction = use_spglib_reduction
485 spglib_reduction = .false.
487 a1(1:3) = hmat(1:3, 1)
488 a2(1:3) = hmat(1:3, 2)
489 a3(1:3) = hmat(1:3, 3)
492 ALLOCATE (xkapa(3, nat), rx(3, nat), tvec(3, 200), ty(nat), isc(nat), f0(49, nat))
493 ty(1:nat) = csym%atype(1:nat)
496 xkapa(1:3, i) = matmul(hmat, csym%scoord(1:3, i))
499 ALLOCATE (wvkl(3, nkpoint), rlist(3, nkpoint), includ(nkpoint),
list(nhash + nkpoint))
500 ALLOCATE (lrot(48, nkpoint), lwght(nkpoint))
503 WRITE (iou,
'(/,(T2,A79))') &
504 "*******************************************************************************", &
505 "** Special K-Point Generation by K290 **", &
506 "*******************************************************************************"
509 IF (spglib_reduction)
CALL cite_reference(
togo2018)
511 CALL k290s(iou, nat, nkpoint, nsp, iq1, iq2, iq3, istriz, &
512 a1, a2, a3, alat, strain, xkapa, rx, tvec, &
513 ty, isc, f0, ntvec, wvk0, wvkl, lwght, lrot, &
514 nhash, includ,
list, rlist, csym%delta)
516 CALL group1s(0, a1, a2, a3, nat, ty, xkapa, b1, b2, b3, &
517 ihg, ihc, isy, li, nc, indpg, ib, ntvec, &
518 vt, f0, r, tvec, origin, rx, isc, csym%delta)
521 WRITE (iou,
'((T2,A79))') &
522 "*******************************************************************************", &
523 "** Finished K290 **", &
524 "*******************************************************************************"
528 IF (
ALLOCATED(csym%rt))
DEALLOCATE (csym%rt)
529 IF (
ALLOCATED(csym%vt))
DEALLOCATE (csym%vt)
530 IF (
ALLOCATED(csym%ibrot))
DEALLOCATE (csym%ibrot)
531 IF (
ALLOCATED(csym%f0))
DEALLOCATE (csym%f0)
532 ALLOCATE (csym%rt(3, 3, nc), csym%vt(3, nc), csym%ibrot(nc))
533 csym%vt(1:3, 1:nc) = vt(1:3, 1:nc)
534 ALLOCATE (csym%f0(nat, nc))
536 csym%rt(1:3, 1:3, i) = r(1:3, 1:3, ib(i))
537 csym%f0(1:nat, i) = f0(i, 1:nat)
539 csym%ibrot(1:nc) = ib(1:nc)
541 IF (csym%n_operations > nc)
THEN
542 IF (
ALLOCATED(srot))
DEALLOCATE (srot)
543 ALLOCATE (srot(3, 3, csym%n_operations))
544 CALL setup_spglib_operations(csym, srot, nrot)
545 CALL reduce_spglib_kpoint_mesh(csym, xkp, wkp, kpop, srot, nrot)
547 ELSE IF (spglib_reduction)
THEN
548 ALLOCATE (srot(3, 3, csym%n_operations))
549 CALL setup_spglib_reduction_rotations(csym, srot, nrot)
550 CALL reduce_spglib_kpoint_mesh_k290(csym, xkp, wkp, kpop, srot, nrot, &
551 a1, a2, a3, b1, b2, b3, alat)
554 CALL reduce_kpoint_mesh(csym, xkp, wkp, kpop, nc, ib, r, a1, a2, a3, b1, b2, b3, alat)
556 DEALLOCATE (xkapa, rx, tvec, ty, isc, f0)
557 DEALLOCATE (wvkl, rlist, includ,
list)
558 DEALLOCATE (lrot, lwght)
560 END SUBROUTINE kp_symmetry
569 SUBROUTINE kp_symmetry_spglib(csym, xkp, wkp, kpop)
571 REAL(kind=
dp),
DIMENSION(:, :) :: xkp
572 REAL(kind=
dp),
DIMENSION(:) :: wkp
573 INTEGER,
DIMENSION(:) :: kpop
576 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: srot
580 WRITE (iou,
'(/,(T2,A79))') &
581 "*******************************************************************************", &
582 "** Special K-Point Generation by SPGLIB **", &
583 "*******************************************************************************"
587 ALLOCATE (srot(3, 3, csym%n_operations))
588 CALL setup_spglib_operations(csym, srot, nrot)
589 CALL reduce_spglib_kpoint_mesh(csym, xkp, wkp, kpop, srot, nrot)
593 WRITE (iou,
'((T2,A79))') &
594 "*******************************************************************************", &
595 "** Finished SPGLIB **", &
596 "*******************************************************************************"
599 END SUBROUTINE kp_symmetry_spglib
607 SUBROUTINE setup_spglib_operations(csym, srot, nrot)
609 INTEGER,
DIMENSION(:, :, :),
INTENT(OUT) :: srot
610 INTEGER,
INTENT(OUT) :: nrot
612 INTEGER :: iop, jop, pass
613 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: perm
614 INTEGER,
DIMENSION(3, 3) :: eye, irot
615 LOGICAL :: duplicate, identity, valid, &
618 REAL(kind=
dp),
DIMENSION(3, 3) :: h_inv, rfrac
620 cpassert(csym%symlib)
624 IF (
ALLOCATED(csym%rt))
DEALLOCATE (csym%rt)
625 IF (
ALLOCATED(csym%vt))
DEALLOCATE (csym%vt)
626 IF (
ALLOCATED(csym%ibrot))
DEALLOCATE (csym%ibrot)
627 IF (
ALLOCATED(csym%f0))
DEALLOCATE (csym%f0)
628 ALLOCATE (csym%rt(3, 3, csym%n_operations), csym%vt(3, csym%n_operations))
629 ALLOCATE (csym%ibrot(csym%n_operations), csym%f0(csym%nat, csym%n_operations))
635 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
637 ALLOCATE (perm(csym%nat))
648 DO iop = 1, csym%n_operations
649 irot(1:3, 1:3) = csym%rotations(1:3, 1:3, iop)
650 identity = all(irot == eye)
651 zero_translation = all(abs(csym%translations(1:3, iop) - &
652 anint(csym%translations(1:3, iop))) <= eps)
653 IF (pass == 1 .AND. (.NOT. identity .OR. .NOT. zero_translation)) cycle
654 IF (pass == 2 .AND. (identity .OR. .NOT. zero_translation)) cycle
655 IF (pass == 3 .AND. (.NOT. identity .OR. zero_translation)) cycle
656 IF (pass == 4 .AND. (identity .OR. zero_translation)) cycle
660 IF (all(irot == srot(:, :, jop)) .AND. &
661 all(abs(csym%translations(1:3, iop) - csym%vt(1:3, jop) - &
662 anint(csym%translations(1:3, iop) - csym%vt(1:3, jop))) <= eps))
THEN
669 CALL spglib_atom_permutation(csym, irot, csym%translations(:, iop), perm, valid)
670 IF (.NOT. valid) cycle
674 srot(1:3, 1:3, nrot) = irot(1:3, 1:3)
675 rfrac(1:3, 1:3) = real(irot(1:3, 1:3), kind=
dp)
676 csym%rt(1:3, 1:3, nrot) = matmul(csym%hmat, matmul(rfrac, h_inv))
677 csym%vt(1:3, nrot) = csym%translations(1:3, iop)
678 csym%ibrot(nrot) = nrot
679 csym%f0(1:csym%nat, nrot) = perm(1:csym%nat)
685 IF (nrot == 0)
CALL cp_abort(__location__,
"SPGLIB did not return usable symmetry operations")
687 END SUBROUTINE setup_spglib_operations
695 SUBROUTINE setup_spglib_reduction_rotations(csym, srot, nrot)
697 INTEGER,
DIMENSION(:, :, :),
INTENT(OUT) :: srot
698 INTEGER,
INTENT(OUT) :: nrot
700 INTEGER :: iop, jop, pass
701 INTEGER,
DIMENSION(3, 3) :: eye, irot
702 LOGICAL :: duplicate, identity
704 cpassert(csym%symlib)
715 DO iop = 1, csym%n_operations
716 irot(1:3, 1:3) = csym%rotations(1:3, 1:3, iop)
717 identity = all(irot == eye)
718 IF (pass == 1 .AND. .NOT. identity) cycle
719 IF (pass == 2 .AND. identity) cycle
723 IF (all(irot == srot(:, :, jop)))
THEN
731 srot(1:3, 1:3, nrot) = irot(1:3, 1:3)
735 IF (nrot == 0)
CALL cp_abort(__location__,
"SPGLIB did not return usable symmetry rotations")
737 END SUBROUTINE setup_spglib_reduction_rotations
747 SUBROUTINE spglib_atom_permutation(csym, rot, trans, perm, valid)
749 INTEGER,
DIMENSION(3, 3),
INTENT(IN) :: rot
750 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: trans
751 INTEGER,
DIMENSION(:),
INTENT(OUT) :: perm
752 LOGICAL,
INTENT(OUT) :: valid
756 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: used
758 REAL(kind=
dp),
DIMENSION(3) :: diff, spos
759 REAL(kind=
dp),
DIMENSION(3, 3) :: rfrac
762 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
763 rfrac(1:3, 1:3) = real(rot(1:3, 1:3), kind=
dp)
770 spos(1:3) = matmul(rfrac(1:3, 1:3), csym%scoord(1:3, i)) + trans(1:3)
774 IF (csym%atype(i) /= csym%atype(j)) cycle
775 diff(1:3) = spos(1:3) - csym%scoord(1:3, j)
776 diff(1:3) = diff(1:3) - anint(diff(1:3))
777 IF (all(abs(diff(1:3)) < eps))
THEN
784 IF (.NOT. found)
THEN
792 END SUBROUTINE spglib_atom_permutation
803 SUBROUTINE reduce_spglib_kpoint_mesh(csym, xkp, wkp, kpop, srot, nrot)
805 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp
806 REAL(kind=
dp),
DIMENSION(:) :: wkp
807 INTEGER,
DIMENSION(:) :: kpop
808 INTEGER,
DIMENSION(:, :, :),
INTENT(IN) :: srot
809 INTEGER,
INTENT(IN) :: nrot
811 INTEGER :: i, iop, isign, j, kr, nkpts, score
812 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: kscore
813 INTEGER,
DIMENSION(3, 3) :: krot
815 REAL(kind=
dp),
DIMENSION(3) :: diff, rr
818 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
819 ALLOCATE (kscore(nkpts))
823 csym%kplink(1, :) = 0
827 IF (csym%kplink(1, i) /= 0) cycle
829 csym%kplink(1, i) = i
836 krot = reciprocal_rotation(srot(:, :, kr))
837 score = spglib_operation_score(csym, iop, srot(:, :, kr))
839 rr(1:3) = matmul(real(krot(1:3, 1:3), kind=
dp), xkp(1:3, i))
842 kr = -csym%ibrot(iop)
848 diff(1:3) = xkp(1:3, j) - rr(1:3)
849 diff(1:3) = diff(1:3) - anint(diff(1:3))
850 IF (all(abs(diff(1:3)) < eps))
THEN
851 IF (csym%kplink(1, j) == 0)
THEN
852 csym%kplink(1, j) = i
853 wkp(i) = wkp(i) + 1.0_dp
857 cpassert(csym%kplink(1, j) == i)
858 IF (score < kscore(j))
THEN
872 cpassert(csym%kplink(1, i) /= 0)
873 cpassert(kpop(i) /= 0)
877 END SUBROUTINE reduce_spglib_kpoint_mesh
895 SUBROUTINE reduce_spglib_kpoint_mesh_k290(csym, xkp, wkp, kpop, srot, nrot, &
896 a1, a2, a3, b1, b2, b3, alat)
898 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp
899 REAL(kind=
dp),
DIMENSION(:) :: wkp
900 INTEGER,
DIMENSION(:) :: kpop
901 INTEGER,
DIMENSION(:, :, :),
INTENT(IN) :: srot
902 INTEGER,
INTENT(IN) :: nrot
903 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a1, a2, a3, b1, b2, b3
904 REAL(kind=
dp),
INTENT(IN) :: alat
906 INTEGER :: i, iop, isign, j, k290_op, nkpts
907 INTEGER,
DIMENSION(3, 3) :: krot
910 REAL(kind=
dp),
DIMENSION(3) :: diff, rr
913 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
917 csym%kplink(1, :) = 0
920 IF (csym%kplink(1, i) /= 0) cycle
922 csym%kplink(1, i) = i
927 krot = reciprocal_rotation(srot(:, :, iop))
929 rr(1:3) = matmul(real(krot(1:3, 1:3), kind=
dp), xkp(1:3, i))
930 IF (isign == 2) rr(1:3) = -rr(1:3)
933 diff(1:3) = xkp(1:3, j) - rr(1:3)
934 diff(1:3) = diff(1:3) - anint(diff(1:3))
935 IF (all(abs(diff(1:3)) < eps))
THEN
937 IF (csym%kplink(1, j) /= 0)
THEN
938 cpassert(csym%kplink(1, j) == i)
942 CALL find_k290_kpoint_operation(csym, xkp(1:3, i), xkp(1:3, j), &
943 a1, a2, a3, b1, b2, b3, alat, &
945 IF (.NOT. valid)
THEN
946 CALL cp_abort(__location__, &
947 "SPGLIB k-point mapping is not represented by K290 backend")
949 csym%kplink(1, j) = i
950 wkp(i) = wkp(i) + 1.0_dp
961 cpassert(csym%kplink(1, i) /= 0)
962 cpassert(kpop(i) /= 0)
965 END SUBROUTINE reduce_spglib_kpoint_mesh_k290
982 SUBROUTINE find_k290_kpoint_operation(csym, xref, xtarget, a1, a2, a3, b1, b2, b3, alat, &
985 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xref, xtarget, a1, a2, a3, b1, b2, b3
986 REAL(kind=
dp),
INTENT(IN) :: alat
987 INTEGER,
INTENT(OUT) :: k290_op
988 LOGICAL,
INTENT(OUT) :: valid
990 INTEGER :: ibsign, iop, kr
992 REAL(kind=
dp),
DIMENSION(3) :: diff, rr, wcart
994 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
998 DO iop = 1, csym%nrtot
999 IF (iop >
SIZE(csym%rt, 3)) cycle
1000 IF (csym%ibrot(iop) == 0) cycle
1002 wcart(1:3) = alat*(xref(1)*b1(1:3) + xref(2)*b2(1:3) + xref(3)*b3(1:3))
1003 wcart(1:3) = kp_apply_operation(wcart(1:3), csym%rt(1:3, 1:3, iop))
1004 IF (ibsign == 2)
THEN
1005 wcart(1:3) = -wcart(1:3)
1006 kr = -csym%ibrot(iop)
1008 kr = csym%ibrot(iop)
1010 rr(1) = dot_product(a1(1:3), wcart(1:3))/alat
1011 rr(2) = dot_product(a2(1:3), wcart(1:3))/alat
1012 rr(3) = dot_product(a3(1:3), wcart(1:3))/alat
1014 diff(1:3) = xtarget(1:3) - rr(1:3)
1015 diff(1:3) = diff(1:3) - anint(diff(1:3))
1016 IF (all(abs(diff(1:3)) < eps))
THEN
1024 END SUBROUTINE find_k290_kpoint_operation
1033 FUNCTION spglib_operation_score(csym, iop, srot)
RESULT(score)
1035 INTEGER,
INTENT(IN) :: iop
1036 INTEGER,
DIMENSION(3, 3),
INTENT(IN) :: srot
1040 INTEGER,
DIMENSION(3, 3) :: eye, r2
1041 REAL(kind=
dp) :: eps
1043 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1044 nat =
SIZE(csym%f0, 1)
1047 IF (csym%f0(i, iop) /= i) score = score + 100
1049 IF (any(abs(csym%vt(1:3, iop) - anint(csym%vt(1:3, iop))) > eps)) score = score + 10
1055 r2(1:3, 1:3) = matmul(srot(1:3, 1:3), srot(1:3, 1:3))
1056 IF (any(r2(1:3, 1:3) /= eye(1:3, 1:3))) score = score + 1
1058 END FUNCTION spglib_operation_score
1065 FUNCTION reciprocal_rotation(rot)
RESULT(krot)
1066 INTEGER,
DIMENSION(3, 3),
INTENT(IN) :: rot
1067 INTEGER,
DIMENSION(3, 3) :: krot
1069 REAL(kind=
dp),
DIMENSION(3, 3) :: rinv
1071 rinv =
inv_3x3(real(rot(1:3, 1:3), kind=
dp))
1072 krot(1:3, 1:3) = nint(transpose(rinv(1:3, 1:3)))
1074 END FUNCTION reciprocal_rotation
1093 SUBROUTINE reduce_kpoint_mesh(csym, xkp, wkp, kpop, nc, ib, r, a1, a2, a3, b1, b2, b3, alat)
1095 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp
1096 REAL(kind=
dp),
DIMENSION(:) :: wkp
1097 INTEGER,
DIMENSION(:) :: kpop
1098 INTEGER,
INTENT(IN) :: nc
1099 INTEGER,
DIMENSION(48),
INTENT(IN) :: ib
1100 REAL(kind=
dp),
DIMENSION(3, 3, 48),
INTENT(IN) :: r
1101 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a1, a2, a3, b1, b2, b3
1102 REAL(kind=
dp),
INTENT(IN) :: alat
1104 INTEGER :: i, ibsign, iop, j, kr, nkpts
1105 REAL(kind=
dp) :: eps
1106 REAL(kind=
dp),
DIMENSION(3) :: diff, rr, wcart
1109 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1113 csym%kplink(1, :) = 0
1116 IF (csym%kplink(1, i) /= 0) cycle
1118 csym%kplink(1, i) = i
1125 wcart(1:3) = alat*(xkp(1, i)*b1(1:3) + xkp(2, i)*b2(1:3) + xkp(3, i)*b3(1:3))
1126 wcart(1:3) = kp_apply_operation(wcart(1:3), r(1:3, 1:3, kr))
1127 IF (ibsign == 2)
THEN
1128 wcart(1:3) = -wcart(1:3)
1131 rr(1) = dot_product(a1(1:3), wcart(1:3))/alat
1132 rr(2) = dot_product(a2(1:3), wcart(1:3))/alat
1133 rr(3) = dot_product(a3(1:3), wcart(1:3))/alat
1136 diff(1:3) = xkp(1:3, j) - rr(1:3)
1137 diff(1:3) = diff(1:3) - anint(diff(1:3))
1138 IF (all(abs(diff(1:3)) < eps))
THEN
1139 IF (csym%kplink(1, j) == 0)
THEN
1140 csym%kplink(1, j) = i
1141 wkp(i) = wkp(i) + 1.0_dp
1144 cpassert(csym%kplink(1, j) == i)
1150 IF (j > nkpts) cycle
1156 cpassert(csym%kplink(1, i) /= 0)
1157 cpassert(kpop(i) /= 0)
1160 END SUBROUTINE reduce_kpoint_mesh
1168 SUBROUTINE full_grid_gen(nk, xkp, wkp, shift)
1169 INTEGER,
INTENT(IN) :: nk(3)
1170 REAL(kind=
dp),
DIMENSION(:, :) :: xkp
1171 REAL(kind=
dp),
DIMENSION(:) :: wkp
1172 REAL(kind=
dp),
INTENT(IN) :: shift(3)
1174 INTEGER :: i, ix, iy, iz
1175 REAL(kind=
dp) :: kpt_latt(3)
1183 kpt_latt(1) = real(2*ix - nk(1) - 1, kind=
dp)/(2._dp*real(nk(1), kind=
dp))
1184 kpt_latt(2) = real(2*iy - nk(2) - 1, kind=
dp)/(2._dp*real(nk(2), kind=
dp))
1185 kpt_latt(3) = real(2*iz - nk(3) - 1, kind=
dp)/(2._dp*real(nk(3), kind=
dp))
1186 xkp(1:3, i) = kpt_latt(1:3)
1191 DO i = 1, nk(1)*nk(2)*nk(3)
1192 xkp(1:3, i) = xkp(1:3, i) + shift(1:3)
1195 END SUBROUTINE full_grid_gen
1203 SUBROUTINE inversion_symm(xkp, wkp, link)
1204 REAL(kind=
dp),
DIMENSION(:, :) :: xkp
1205 REAL(kind=
dp),
DIMENSION(:) :: wkp
1206 INTEGER,
DIMENSION(:) :: link
1208 INTEGER :: i, j, nkpts
1209 REAL(kind=
dp),
DIMENSION(3) :: diff
1211 nkpts =
SIZE(wkp, 1)
1215 IF (link(i) == 0) link(i) = i
1217 IF (wkp(j) == 0) cycle
1218 diff(1:3) = xkp(1:3, i) + xkp(1:3, j)
1219 diff(1:3) = diff(1:3) - anint(diff(1:3))
1220 IF (all(abs(diff(1:3)) < 1.e-12_dp))
THEN
1221 wkp(i) = wkp(i) + wkp(j)
1229 END SUBROUTINE inversion_symm
1237 FUNCTION kp_apply_operation(x, r)
RESULT(y)
1238 REAL(kind=
dp),
INTENT(IN) :: x(3), r(3, 3)
1239 REAL(kind=
dp) :: y(3)
1241 y(1) = r(1, 1)*x(1) + r(1, 2)*x(2) + r(1, 3)*x(3)
1242 y(2) = r(2, 1)*x(1) + r(2, 2)*x(2) + r(2, 3)*x(3)
1243 y(3) = r(3, 1)*x(1) + r(3, 2)*x(2) + r(3, 3)*x(3)
1245 END FUNCTION kp_apply_operation
1254 INTEGER :: i, iunit, j, plevel
1257 IF (iunit >= 0)
THEN
1258 plevel = csym%plevel
1259 WRITE (iunit,
"(/,T2,A)")
"Crystal Symmetry Information"
1260 IF (csym%symlib)
THEN
1261 WRITE (iunit,
'(A,T71,A10)')
" International Symbol: ", adjustr(trim(csym%international_symbol))
1262 WRITE (iunit,
'(A,T71,A10)')
" Point Group Symbol: ", adjustr(trim(csym%pointgroup_symbol))
1263 WRITE (iunit,
'(A,T71,A10)')
" Schoenflies Symbol: ", adjustr(trim(csym%schoenflies))
1265 WRITE (iunit,
'(A,T71,I10)')
" Number of Symmetry Operations: ", csym%n_operations
1266 IF (plevel > 0)
THEN
1267 DO i = 1, csym%n_operations
1268 WRITE (iunit,
'(A,i4,T51,3I10,/,T51,3I10,/,T51,3I10)') &
1269 " Rotation #: ", i, (csym%rotations(j, :, i), j=1, 3)
1270 WRITE (iunit,
'(T36,3F15.7)') csym%translations(:, i)
1274 WRITE (iunit,
"(T2,A)")
"SPGLIB for Crystal Symmetry Information determination is not availale"
1287 INTEGER :: i, iunit, nat, plevel
1290 IF (iunit >= 0)
THEN
1291 plevel = csym%plevel
1292 WRITE (iunit,
"(/,T2,A)")
"K-point Symmetry Information"
1293 WRITE (iunit,
'(A,T67,I14)')
" Number of Special K-points: ", csym%nkpoint
1294 WRITE (iunit,
'(T19,A,T74,A)')
" Wavevector Basis ",
" Weight"
1295 DO i = 1, csym%nkpoint
1296 WRITE (iunit,
'(T2,i10,3F10.5,T71,I10)') i, csym%xkpoint(1:3, i), nint(csym%wkpoint(i))
1298 WRITE (iunit,
'(/,A,T63,3I6)')
" K-point Mesh: ", csym%mesh(1), csym%mesh(2), csym%mesh(3)
1299 WRITE (iunit,
'(T19,A,T54,A)')
" Wavevector Basis ",
" Special Points Rotation"
1300 DO i = 1, csym%mesh(1)*csym%mesh(2)*csym%mesh(3)
1301 WRITE (iunit,
'(T2,i10,3F10.5,T45,3I12)') i, csym%kpmesh(1:3, i), &
1302 csym%kplink(1:2, i), csym%kpop(i)
1304 IF (csym%nrtot > 0)
THEN
1305 WRITE (iunit,
'(/,A)')
" Atom Transformation Table"
1306 nat =
SIZE(csym%f0, 1)
1307 DO i = 1, csym%nrtot
1308 WRITE (iunit,
'(T10,A,I5,(T21,12I5))')
" Rot=", csym%ibrot(i), csym%f0(1:nat, i)
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public togo2018
integer, save, public worlton1972
K-points and crystal symmetry routines.
subroutine, public kpoint_gen(csym, nk, symm, shift, full_grid, inversion_symmetry_only, use_spglib_reduction, use_spglib_backend)
...
subroutine, public print_crys_symmetry(csym)
...
subroutine, public crys_sym_gen(csym, scoor, types, hmat, delta, iounit)
...
subroutine, public release_csym_type(csym)
Release the CSYM type.
subroutine, public print_kp_symmetry(csym)
...
Defines the basic variable types.
integer, parameter, public dp
K-points and crystal symmetry routines based on.
subroutine, public k290s(iout, 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, delta)
...
subroutine, public group1s(iout, a1, a2, a3, nat, ty, x, b1, b2, b3, ihg, ihc, isy, li, nc, indpg, ib, ntvec, v, f0, r, tvec, origin, rx, isc, delta)
...
An array-based list which grows on demand. When the internal array is full, a new array of twice the ...
Collection of simple mathematical functions and subroutines.
pure real(kind=dp) function, dimension(3, 3), public inv_3x3(a)
Returns the inverse of the 3 x 3 matrix a.
Interface for SPGLIB symmetry routines.
integer function, public spg_get_international(symbol, lattice, position, types, num_atom, symprec)
...
integer function, public spg_get_multiplicity(lattice, position, types, num_atom, symprec)
...
integer function, public spg_get_micro_version()
...
integer function, public spg_get_minor_version()
...
integer function, public spg_get_major_version()
...
integer function, public spg_get_pointgroup(symbol, trans_mat, rotations, num_rotations)
...
integer function, public spg_get_symmetry(rotation, translation, max_size, lattice, position, types, num_atom, symprec)
...
integer function, public spg_get_schoenflies(symbol, lattice, position, types, num_atom, symprec)
...
Utilities for string manipulations.
elemental subroutine, public strip_control_codes(string)
Strip control codes and extended characters from a string, i.e. replace them with blanks.