29#include "./base/base_uses.f90"
36 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cryssym'
44 LOGICAL :: symlib = .false.
45 LOGICAL :: fullgrid = .false.
46 LOGICAL :: inversion_only = .false.
47 LOGICAL :: spglib_reduction = .false.
48 LOGICAL :: spglib_backend = .false.
49 LOGICAL :: spglib_requested = .true.
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)
143 SUBROUTINE crys_sym_gen(csym, scoor, types, hmat, delta, iounit, use_spglib)
145 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: scoor
146 INTEGER,
DIMENSION(:),
INTENT(IN) :: types
147 REAL(kind=
dp),
INTENT(IN) :: hmat(3, 3)
148 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: delta
149 INTEGER,
INTENT(IN),
OPTIONAL :: iounit
150 LOGICAL,
INTENT(IN),
OPTIONAL :: use_spglib
152 CHARACTER(LEN=*),
PARAMETER :: routinen =
'crys_sym_gen'
154 INTEGER :: handle, ierr, major, micro, minor, nat, &
156 LOGICAL :: my_use_spglib, spglib
158 CALL timeset(routinen, handle)
165 IF (
PRESENT(iounit))
THEN
172 IF (
PRESENT(delta))
THEN
175 csym%delta = 1.e-6_dp
182 ALLOCATE (csym%atype(nat))
183 csym%atype(1:nat) = types(1:nat)
186 ALLOCATE (csym%scoord(3, nat))
187 csym%scoord(1:3, 1:nat) = scoor(1:3, 1:nat)
189 csym%n_operations = 0
192 my_use_spglib = .true.
193 IF (
PRESENT(use_spglib)) my_use_spglib = use_spglib
194 csym%spglib_requested = my_use_spglib
195 IF (.NOT. my_use_spglib)
THEN
202 CALL cp_warn(__location__,
"Symmetry library SPGLIB not available")
209 CALL cp_warn(__location__,
"Symmetry Library SPGLIB failed")
213 ALLOCATE (csym%rotations(3, 3, nop), csym%translations(3, nop))
214 csym%n_operations = nop
216 transpose(hmat), scoor, types, nat, delta)
218 csym%schoenflies =
' '
219 ierr =
spg_get_schoenflies(csym%schoenflies(1:7), transpose(hmat), scoor, types, nat, delta)
221 csym%pointgroup_symbol =
' '
224 csym%rotations, csym%n_operations)
234 CALL timestop(handle)
250 SUBROUTINE kpoint_gen(csym, nk, symm, shift, full_grid, gamma_centered, &
251 inversion_symmetry_only, use_spglib_reduction, use_spglib_backend)
253 INTEGER,
INTENT(IN) :: nk(3)
254 LOGICAL,
INTENT(IN),
OPTIONAL :: symm
255 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: shift(3)
256 LOGICAL,
INTENT(IN),
OPTIONAL :: full_grid, gamma_centered, &
257 inversion_symmetry_only, &
258 use_spglib_reduction, &
261 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_gen'
263 INTEGER :: handle, i, ik, j, nkp, nkpts
264 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: kpop, rep_to_red
265 LOGICAL :: fullmesh, gamma_mesh, inversion_only, &
266 spglib_backend, spglib_reduction
267 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: wkp
268 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: xkp
270 CALL timeset(routinen, handle)
272 IF (
PRESENT(shift))
THEN
279 IF (
PRESENT(symm))
THEN
280 IF (symm) csym%istriz = 1
283 IF (
PRESENT(full_grid))
THEN
288 csym%fullgrid = fullmesh
290 IF (
PRESENT(gamma_centered))
THEN
291 gamma_mesh = gamma_centered
296 IF (
PRESENT(inversion_symmetry_only))
THEN
297 inversion_only = inversion_symmetry_only
299 inversion_only = .false.
301 csym%inversion_only = inversion_only
303 IF (
PRESENT(use_spglib_reduction))
THEN
304 spglib_reduction = use_spglib_reduction
306 spglib_reduction = .false.
308 csym%spglib_reduction = spglib_reduction
310 IF (
PRESENT(use_spglib_backend))
THEN
311 spglib_backend = use_spglib_backend
313 spglib_backend = .false.
315 csym%spglib_backend = spglib_backend
317 IF (spglib_backend .AND. .NOT. spglib_reduction)
THEN
318 CALL cp_abort(__location__, &
319 "SYMMETRY_BACKEND SPGLIB requires SYMMETRY_REDUCTION_METHOD SPGLIB")
321 IF (csym%istriz == 1 .AND. .NOT. fullmesh .AND. .NOT. inversion_only .AND. &
322 (spglib_backend .OR. spglib_reduction) .AND. .NOT. csym%symlib)
THEN
323 CALL cp_abort(__location__, &
324 "SPGLIB k-point symmetry was requested, but SPGLIB is not available")
328 csym%mesh(1:3) = nk(1:3)
330 IF (
ALLOCATED(csym%rt))
DEALLOCATE (csym%rt)
331 IF (
ALLOCATED(csym%vt))
DEALLOCATE (csym%vt)
332 IF (
ALLOCATED(csym%ibrot))
DEALLOCATE (csym%ibrot)
333 IF (
ALLOCATED(csym%f0))
DEALLOCATE (csym%f0)
334 ALLOCATE (csym%rt(3, 3, 0), csym%vt(3, 0), csym%ibrot(0), csym%f0(csym%nat, 0))
336 nkpts = nk(1)*nk(2)*nk(3)
337 ALLOCATE (xkp(3, nkpts), wkp(nkpts), kpop(nkpts))
339 ALLOCATE (csym%kplink(2, nkpts))
344 IF (csym%symlib)
THEN
348 CALL full_grid_gen(nk, xkp, wkp, shift, gamma_centered=gamma_mesh)
349 IF (csym%istriz == 1)
THEN
351 CALL inversion_symm(xkp, wkp, csym%kplink(1, :))
355 ELSE IF (csym%istriz /= 1 .OR. inversion_only)
THEN
357 CALL full_grid_gen(nk, xkp, wkp, shift, gamma_centered=gamma_mesh)
358 CALL inversion_symm(xkp, wkp, csym%kplink(1, :))
361 CALL full_grid_gen(nk, xkp, wkp, shift, gamma_centered=gamma_mesh)
362 IF (spglib_backend)
THEN
363 CALL kp_symmetry_spglib(csym, xkp, wkp, kpop)
365 CALL kp_symmetry(csym, xkp, wkp, kpop, use_spglib_reduction=spglib_reduction)
371 CALL full_grid_gen(nk, xkp, wkp, shift, gamma_centered=gamma_mesh)
372 IF (csym%istriz == 1 .AND. .NOT. fullmesh .AND. .NOT. inversion_only)
THEN
374 CALL kp_symmetry(csym, xkp, wkp, kpop, use_spglib_reduction=.false.)
375 ELSE IF (csym%istriz /= 1 .AND. fullmesh)
THEN
378 csym%kplink(1, i) = i
382 CALL inversion_symm(xkp, wkp, csym%kplink(1, :))
388 IF (wkp(i) > 0.0_dp) nkp = nkp + 1
393 ALLOCATE (csym%xkpoint(3, nkp), csym%wkpoint(nkp))
394 ALLOCATE (rep_to_red(nkpts))
398 IF (wkp(ik) > 0.0_dp)
THEN
400 csym%wkpoint(j) = wkp(ik)
401 csym%xkpoint(1:3, j) = xkp(1:3, ik)
408 ALLOCATE (csym%kpmesh(3, nkpts))
409 csym%kpmesh(1:3, 1:nkpts) = xkp(1:3, 1:nkpts)
413 i = csym%kplink(1, ik)
414 cpassert(i > 0 .AND. i <= nkpts)
415 csym%kplink(2, ik) = rep_to_red(i)
416 cpassert(csym%kplink(2, ik) > 0)
418 DEALLOCATE (rep_to_red)
421 ALLOCATE (csym%kpop(nkpts))
422 IF (csym%nrtot > 0 .AND. csym%istriz == 1 .AND. .NOT. fullmesh .AND. &
423 .NOT. inversion_only)
THEN
425 csym%kpop(1:nkpts) = kpop(1:nkpts)
427 cpassert(csym%kpop(ik) /= 0)
432 IF (wkp(ik) > 0.0_dp)
THEN
440 DEALLOCATE (xkp, wkp, kpop)
442 CALL timestop(handle)
458 inversion_symmetry_only, use_spglib_reduction, use_spglib_backend)
460 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp_in
461 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wkp_in
462 LOGICAL,
INTENT(IN),
OPTIONAL :: symm, full_grid, &
463 inversion_symmetry_only, &
464 use_spglib_reduction, &
467 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_gen_general'
469 INTEGER :: handle, i, nfull
470 LOGICAL :: atomic_symmetry, fullmesh, &
471 inversion_only, spglib_backend, &
473 REAL(kind=
dp) :: weight_eps
475 CALL timeset(routinen, handle)
478 cpassert(
SIZE(xkp_in, 1) == 3)
479 cpassert(
SIZE(xkp_in, 2) == nfull)
481 atomic_symmetry = .false.
482 IF (
PRESENT(symm)) atomic_symmetry = symm
484 IF (atomic_symmetry) csym%istriz = 1
486 IF (
PRESENT(full_grid)) fullmesh = full_grid
487 inversion_only = .false.
488 IF (
PRESENT(inversion_symmetry_only)) inversion_only = inversion_symmetry_only
489 spglib_reduction = .false.
490 IF (
PRESENT(use_spglib_reduction)) spglib_reduction = use_spglib_reduction
491 spglib_backend = .false.
492 IF (
PRESENT(use_spglib_backend)) spglib_backend = use_spglib_backend
494 csym%fullgrid = fullmesh
495 csym%inversion_only = inversion_only
496 csym%spglib_reduction = spglib_reduction
497 csym%spglib_backend = spglib_backend
501 IF (
ALLOCATED(csym%rt))
DEALLOCATE (csym%rt)
502 IF (
ALLOCATED(csym%vt))
DEALLOCATE (csym%vt)
503 IF (
ALLOCATED(csym%ibrot))
DEALLOCATE (csym%ibrot)
504 IF (
ALLOCATED(csym%f0))
DEALLOCATE (csym%f0)
505 ALLOCATE (csym%rt(3, 3, 0), csym%vt(3, 0), csym%ibrot(0), csym%f0(csym%nat, 0))
506 IF (
ALLOCATED(csym%xkpoint))
DEALLOCATE (csym%xkpoint)
507 IF (
ALLOCATED(csym%wkpoint))
DEALLOCATE (csym%wkpoint)
508 IF (
ALLOCATED(csym%kpmesh))
DEALLOCATE (csym%kpmesh)
509 IF (
ALLOCATED(csym%kplink))
DEALLOCATE (csym%kplink)
510 IF (
ALLOCATED(csym%kpop))
DEALLOCATE (csym%kpop)
512 ALLOCATE (csym%kpmesh(3, nfull), csym%kplink(2, nfull), csym%kpop(nfull))
513 csym%kpmesh(1:3, 1:nfull) = xkp_in(1:3, 1:nfull)
517 IF (.NOT. atomic_symmetry .OR. fullmesh)
THEN
519 ALLOCATE (csym%xkpoint(3, nfull), csym%wkpoint(nfull))
520 csym%xkpoint(1:3, 1:nfull) = xkp_in(1:3, 1:nfull)
521 csym%wkpoint(1:nfull) = wkp_in(1:nfull)
523 csym%kplink(1:2, i) = i
525 ELSE IF (inversion_only)
THEN
526 CALL reduce_general_inversion(csym, xkp_in, wkp_in)
528 weight_eps = max(1.e-12_dp, 10.0_dp*csym%delta)
529 IF (any(abs(wkp_in(1:nfull) - wkp_in(1)) > weight_eps))
THEN
530 CALL cp_abort(__location__, &
531 "KPOINTS%SYMMETRY with SCHEME GENERAL requires equal explicit weights.")
533 IF (spglib_backend)
THEN
534 IF (.NOT. csym%symlib)
THEN
535 CALL cp_abort(__location__, &
536 "SCHEME GENERAL with SYMMETRY_BACKEND SPGLIB requires SPGLIB.")
538 CALL reduce_general_spglib(csym, xkp_in)
539 ELSE IF (spglib_reduction)
THEN
540 IF (.NOT. csym%symlib)
THEN
541 CALL cp_abort(__location__, &
542 "SCHEME GENERAL with SYMMETRY_REDUCTION_METHOD SPGLIB requires SPGLIB.")
544 CALL setup_k290_operations(csym)
545 CALL reduce_general_spglib_k290(csym, xkp_in)
547 CALL setup_k290_operations(csym)
548 CALL reduce_general_k290(csym, xkp_in)
552 CALL timestop(handle)
564 SUBROUTINE kp_symmetry(csym, xkp, wkp, kpop, use_spglib_reduction)
566 REAL(kind=
dp),
DIMENSION(:, :) :: xkp
567 REAL(kind=
dp),
DIMENSION(:) :: wkp
568 INTEGER,
DIMENSION(:) :: kpop
569 LOGICAL,
INTENT(IN),
OPTIONAL :: use_spglib_reduction
572 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: srot
573 INTEGER,
DIMENSION(48) :: ib
574 LOGICAL :: spglib_reduction
575 REAL(kind=
dp) :: alat
576 REAL(kind=
dp),
DIMENSION(3) :: a1, a2, a3, b1, b2, b3
577 REAL(kind=
dp),
DIMENSION(3, 3, 48) :: r
579 IF (
PRESENT(use_spglib_reduction))
THEN
580 spglib_reduction = use_spglib_reduction
582 spglib_reduction = .false.
585 CALL detect_k290_symmetry(csym, a1, a2, a3, b1, b2, b3, alat, nc, ib, r)
586 IF (spglib_reduction)
CALL cite_reference(
togo2018)
588 IF (csym%n_operations > nc .AND. .NOT. spglib_reduction)
THEN
589 ALLOCATE (srot(3, 3, csym%n_operations))
590 CALL setup_spglib_operations(csym, srot, nrot)
591 CALL reduce_spglib_kpoint_mesh(csym, xkp, wkp, kpop, srot, nrot)
593 ELSE IF (spglib_reduction)
THEN
594 ALLOCATE (srot(3, 3, csym%n_operations))
595 CALL setup_spglib_reduction_rotations(csym, srot, nrot)
596 CALL reduce_spglib_kpoint_mesh_k290(csym, xkp, wkp, kpop, srot, nrot, &
597 a1, a2, a3, b1, b2, b3, alat)
600 CALL reduce_kpoint_mesh(csym, xkp, wkp, kpop, nc, ib, r, a1, a2, a3, b1, b2, b3, alat)
603 END SUBROUTINE kp_symmetry
612 SUBROUTINE kp_symmetry_spglib(csym, xkp, wkp, kpop)
614 REAL(kind=
dp),
DIMENSION(:, :) :: xkp
615 REAL(kind=
dp),
DIMENSION(:) :: wkp
616 INTEGER,
DIMENSION(:) :: kpop
619 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: srot
623 WRITE (iou,
'(/,(T2,A79))') &
624 "*******************************************************************************", &
625 "** Special K-Point Generation by SPGLIB **", &
626 "*******************************************************************************"
630 ALLOCATE (srot(3, 3, csym%n_operations))
631 CALL setup_spglib_operations(csym, srot, nrot)
632 CALL reduce_spglib_kpoint_mesh(csym, xkp, wkp, kpop, srot, nrot)
636 WRITE (iou,
'((T2,A79))') &
637 "*******************************************************************************", &
638 "** Finished SPGLIB **", &
639 "*******************************************************************************"
642 END SUBROUTINE kp_symmetry_spglib
648 SUBROUTINE setup_k290_operations(csym)
652 INTEGER,
DIMENSION(48) :: ib
653 REAL(kind=
dp) :: alat
654 REAL(kind=
dp),
DIMENSION(3) :: a1, a2, a3, b1, b2, b3
655 REAL(kind=
dp),
DIMENSION(3, 3, 48) :: r
657 CALL detect_k290_symmetry(csym, a1, a2, a3, b1, b2, b3, alat, nc, ib, r)
659 END SUBROUTINE setup_k290_operations
675 SUBROUTINE detect_k290_symmetry(csym, a1, a2, a3, b1, b2, b3, alat, nc, ib, r)
677 REAL(kind=
dp),
DIMENSION(3),
INTENT(OUT) :: a1, a2, a3, b1, b2, b3
678 REAL(kind=
dp),
INTENT(OUT) :: alat
679 INTEGER,
INTENT(OUT) :: nc
680 INTEGER,
DIMENSION(48),
INTENT(OUT) :: ib
681 REAL(kind=
dp),
DIMENSION(3, 3, 48),
INTENT(OUT) :: r
683 INTEGER :: i, ihc, ihg, indpg, iou, isy, li, nat, &
685 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: isc, ty
686 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: f0
687 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: rx, tvec, xkapa
688 REAL(kind=
dp),
DIMENSION(3) :: origin
689 REAL(kind=
dp),
DIMENSION(3, 48) :: vt
693 CALL setup_k290_lattice(csym, a1, a2, a3, b1, b2, b3, alat)
695 ALLOCATE (xkapa(3, nat), rx(3, nat), tvec(3, nat), ty(nat), isc(nat), f0(49, nat))
696 ty(1:nat) = csym%atype(1:nat)
698 xkapa(1:3, i) = matmul(csym%hmat, csym%scoord(1:3, i))
702 WRITE (iou,
'(/,(T2,A79))') &
703 "*******************************************************************************", &
704 "** Crystal Symmetry Analysis by K290 **", &
705 "*******************************************************************************"
709 CALL group1s(iou, a1, a2, a3, nat, ty, xkapa, b1, b2, b3, &
710 ihg, ihc, isy, li, nc, indpg, ib, ntvec, &
711 vt, f0, r, tvec, origin, rx, isc, csym%delta)
714 WRITE (iou,
'((T2,A79))') &
715 "*******************************************************************************", &
716 "** Finished K290 **", &
717 "*******************************************************************************"
721 IF (
ALLOCATED(csym%rt))
DEALLOCATE (csym%rt)
722 IF (
ALLOCATED(csym%vt))
DEALLOCATE (csym%vt)
723 IF (
ALLOCATED(csym%ibrot))
DEALLOCATE (csym%ibrot)
724 IF (
ALLOCATED(csym%f0))
DEALLOCATE (csym%f0)
725 ALLOCATE (csym%rt(3, 3, nc), csym%vt(3, nc), csym%ibrot(nc), csym%f0(nat, nc))
726 csym%vt(1:3, 1:nc) = vt(1:3, 1:nc)
728 csym%rt(1:3, 1:3, i) = r(1:3, 1:3, ib(i))
729 csym%f0(1:nat, i) = f0(i, 1:nat)
731 csym%ibrot(1:nc) = ib(1:nc)
733 DEALLOCATE (xkapa, rx, tvec, ty, isc, f0)
735 END SUBROUTINE detect_k290_symmetry
748 SUBROUTINE setup_k290_lattice(csym, a1, a2, a3, b1, b2, b3, alat)
750 REAL(kind=
dp),
DIMENSION(3),
INTENT(OUT) :: a1, a2, a3, b1, b2, b3
751 REAL(kind=
dp),
INTENT(OUT) :: alat
753 REAL(kind=
dp) :: volum
755 a1(1:3) = csym%hmat(1:3, 1)
756 a2(1:3) = csym%hmat(1:3, 2)
757 a3(1:3) = csym%hmat(1:3, 3)
758 alat = sqrt(sum(a1**2))
759 volum = a1(1)*a2(2)*a3(3) + a2(1)*a3(2)*a1(3) + &
760 a3(1)*a1(2)*a2(3) - a1(3)*a2(2)*a3(1) - &
761 a2(3)*a3(2)*a1(1) - a3(3)*a1(2)*a2(1)
763 b1(1) = (a2(2)*a3(3) - a2(3)*a3(2))/volum
764 b1(2) = (a2(3)*a3(1) - a2(1)*a3(3))/volum
765 b1(3) = (a2(1)*a3(2) - a2(2)*a3(1))/volum
766 b2(1) = (a3(2)*a1(3) - a3(3)*a1(2))/volum
767 b2(2) = (a3(3)*a1(1) - a3(1)*a1(3))/volum
768 b2(3) = (a3(1)*a1(2) - a3(2)*a1(1))/volum
769 b3(1) = (a1(2)*a2(3) - a1(3)*a2(2))/volum
770 b3(2) = (a1(3)*a2(1) - a1(1)*a2(3))/volum
771 b3(3) = (a1(1)*a2(2) - a1(2)*a2(1))/volum
773 END SUBROUTINE setup_k290_lattice
781 SUBROUTINE setup_spglib_operations(csym, srot, nrot)
783 INTEGER,
DIMENSION(:, :, :),
INTENT(OUT) :: srot
784 INTEGER,
INTENT(OUT) :: nrot
786 INTEGER :: iop, jop, pass
787 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: perm
788 INTEGER,
DIMENSION(3, 3) :: eye, frot, irot
789 LOGICAL :: duplicate, identity, valid, &
792 REAL(kind=
dp),
DIMENSION(3, 3) :: h_inv, rfrac
794 cpassert(csym%symlib)
798 IF (
ALLOCATED(csym%rt))
DEALLOCATE (csym%rt)
799 IF (
ALLOCATED(csym%vt))
DEALLOCATE (csym%vt)
800 IF (
ALLOCATED(csym%ibrot))
DEALLOCATE (csym%ibrot)
801 IF (
ALLOCATED(csym%f0))
DEALLOCATE (csym%f0)
802 ALLOCATE (csym%rt(3, 3, csym%n_operations), csym%vt(3, csym%n_operations))
803 ALLOCATE (csym%ibrot(csym%n_operations), csym%f0(csym%nat, csym%n_operations))
809 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
811 ALLOCATE (perm(csym%nat))
822 DO iop = 1, csym%n_operations
823 irot(1:3, 1:3) = csym%rotations(1:3, 1:3, iop)
824 frot(1:3, 1:3) = transpose(irot(1:3, 1:3))
825 identity = all(frot == eye)
826 zero_translation = all(abs(csym%translations(1:3, iop) - &
827 anint(csym%translations(1:3, iop))) <= eps)
828 IF (pass == 1 .AND. (.NOT. identity .OR. .NOT. zero_translation)) cycle
829 IF (pass == 2 .AND. (identity .OR. .NOT. zero_translation)) cycle
830 IF (pass == 3 .AND. (.NOT. identity .OR. zero_translation)) cycle
831 IF (pass == 4 .AND. (identity .OR. zero_translation)) cycle
835 IF (all(frot == srot(:, :, jop)))
THEN
842 CALL spglib_atom_permutation(csym, frot, csym%translations(:, iop), perm, valid)
843 IF (.NOT. valid) cycle
847 srot(1:3, 1:3, nrot) = frot(1:3, 1:3)
848 rfrac(1:3, 1:3) = real(frot(1:3, 1:3), kind=
dp)
849 csym%rt(1:3, 1:3, nrot) = matmul(csym%hmat, matmul(rfrac, h_inv))
850 csym%vt(1:3, nrot) = csym%translations(1:3, iop)
851 csym%ibrot(nrot) = nrot
852 csym%f0(1:csym%nat, nrot) = perm(1:csym%nat)
858 IF (nrot == 0)
CALL cp_abort(__location__,
"SPGLIB did not return usable symmetry operations")
860 END SUBROUTINE setup_spglib_operations
868 SUBROUTINE setup_spglib_reduction_rotations(csym, srot, nrot)
870 INTEGER,
DIMENSION(:, :, :),
INTENT(OUT) :: srot
871 INTEGER,
INTENT(OUT) :: nrot
873 INTEGER :: iop, jop, pass
874 INTEGER,
DIMENSION(3, 3) :: eye, frot, irot
875 LOGICAL :: duplicate, identity
877 cpassert(csym%symlib)
888 DO iop = 1, csym%n_operations
889 irot(1:3, 1:3) = csym%rotations(1:3, 1:3, iop)
890 frot(1:3, 1:3) = transpose(irot(1:3, 1:3))
891 identity = all(frot == eye)
892 IF (pass == 1 .AND. .NOT. identity) cycle
893 IF (pass == 2 .AND. identity) cycle
897 IF (all(frot == srot(:, :, jop)))
THEN
905 srot(1:3, 1:3, nrot) = frot(1:3, 1:3)
909 IF (nrot == 0)
CALL cp_abort(__location__,
"SPGLIB did not return usable symmetry rotations")
911 END SUBROUTINE setup_spglib_reduction_rotations
921 SUBROUTINE spglib_atom_permutation(csym, rot, trans, perm, valid)
923 INTEGER,
DIMENSION(3, 3),
INTENT(IN) :: rot
924 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: trans
925 INTEGER,
DIMENSION(:),
INTENT(OUT) :: perm
926 LOGICAL,
INTENT(OUT) :: valid
930 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: used
932 REAL(kind=
dp),
DIMENSION(3) :: diff, spos
933 REAL(kind=
dp),
DIMENSION(3, 3) :: rfrac
936 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
937 rfrac(1:3, 1:3) = real(rot(1:3, 1:3), kind=
dp)
944 spos(1:3) = matmul(rfrac(1:3, 1:3), csym%scoord(1:3, i)) + trans(1:3)
948 IF (csym%atype(i) /= csym%atype(j)) cycle
949 diff(1:3) = spos(1:3) - csym%scoord(1:3, j)
950 diff(1:3) = diff(1:3) - anint(diff(1:3))
951 IF (all(abs(diff(1:3)) < eps))
THEN
958 IF (.NOT. found)
THEN
966 END SUBROUTINE spglib_atom_permutation
977 SUBROUTINE reduce_spglib_kpoint_mesh(csym, xkp, wkp, kpop, srot, nrot)
979 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp
980 REAL(kind=
dp),
DIMENSION(:) :: wkp
981 INTEGER,
DIMENSION(:) :: kpop
982 INTEGER,
DIMENSION(:, :, :),
INTENT(IN) :: srot
983 INTEGER,
INTENT(IN) :: nrot
985 INTEGER :: i, iop, isign, j, kr, nkpts
986 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: kscore, op_score
987 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: krot
989 REAL(kind=
dp),
DIMENSION(3) :: rr
992 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
993 ALLOCATE (kscore(nkpts), op_score(nrot), krot(3, 3, nrot))
997 krot(1:3, 1:3, iop) = reciprocal_rotation(srot(1:3, 1:3, kr))
998 op_score(iop) = spglib_operation_score(csym, iop, srot(1:3, 1:3, kr))
1003 csym%kplink(1, :) = 0
1007 IF (csym%kplink(1, i) /= 0) cycle
1009 csym%kplink(1, i) = i
1016 rr(1:3) = matmul(real(krot(1:3, 1:3, iop), kind=
dp), xkp(1:3, i))
1017 kr = csym%ibrot(iop)
1018 IF (isign == 2)
THEN
1023 j = regular_kpoint_index(rr, xkp(1:3, 1), csym%mesh, eps)
1025 IF (csym%kplink(1, j) == 0)
THEN
1026 csym%kplink(1, j) = i
1027 wkp(i) = wkp(i) + 1.0_dp
1029 kscore(j) = op_score(iop)
1031 cpassert(csym%kplink(1, j) == i)
1032 IF (op_score(iop) < kscore(j))
THEN
1034 kscore(j) = op_score(iop)
1042 cpassert(csym%kplink(1, i) /= 0)
1043 cpassert(kpop(i) /= 0)
1045 DEALLOCATE (kscore, op_score, krot)
1047 END SUBROUTINE reduce_spglib_kpoint_mesh
1055 SUBROUTINE reduce_general_inversion(csym, xkp_full, wkp_full)
1057 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp_full
1058 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wkp_full
1060 INTEGER :: i, j, nfull, nred
1061 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: rep
1062 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: used
1063 REAL(kind=
dp) :: eps
1064 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: wred
1065 REAL(kind=
dp),
DIMENSION(3) :: diff
1067 nfull =
SIZE(wkp_full)
1068 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1069 ALLOCATE (rep(nfull), used(nfull), wred(nfull))
1080 csym%kplink(1, i) = i
1082 wred(nred) = wkp_full(i)
1085 diff(1:3) = xkp_full(1:3, j) + xkp_full(1:3, i)
1086 diff(1:3) = diff(1:3) - anint(diff(1:3))
1087 IF (all(abs(diff(1:3)) < eps))
THEN
1088 IF (abs(wkp_full(j) - wkp_full(i)) > eps)
THEN
1089 CALL cp_abort(__location__, &
1090 "KPOINTS%INVERSION_SYMMETRY_ONLY with SCHEME GENERAL requires "// &
1091 "equal weights for inversion-related k-points.")
1094 csym%kplink(1, j) = i
1096 wred(nred) = wred(nred) + wkp_full(j)
1102 ALLOCATE (csym%xkpoint(3, nred), csym%wkpoint(nred))
1104 csym%xkpoint(1:3, i) = xkp_full(1:3, rep(i))
1105 csym%wkpoint(i) = wred(i)
1109 IF (csym%kplink(1, i) == rep(j))
THEN
1110 csym%kplink(2, i) = j
1116 DEALLOCATE (rep, used, wred)
1118 END SUBROUTINE reduce_general_inversion
1125 SUBROUTINE reduce_general_k290(csym, xkp_full)
1127 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp_full
1129 INTEGER :: i, ibsign, iop, j, kr, nfull, nred
1130 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: rep
1132 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: used
1133 REAL(kind=
dp) :: alat, eps
1134 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: wred
1135 REAL(kind=
dp),
DIMENSION(3) :: a1, a2, a3, b1, b2, b3, diff, rr, wcart
1137 nfull =
SIZE(xkp_full, 2)
1138 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1139 CALL setup_k290_lattice(csym, a1, a2, a3, b1, b2, b3, alat)
1141 ALLOCATE (rep(nfull), used(nfull), wred(nfull))
1152 csym%kplink(1, i) = i
1156 DO iop = 1, csym%nrtot
1158 kr = csym%ibrot(iop)
1159 wcart(1:3) = alat*(xkp_full(1, i)*b1(1:3) + &
1160 xkp_full(2, i)*b2(1:3) + &
1161 xkp_full(3, i)*b3(1:3))
1162 wcart(1:3) = kp_apply_operation(wcart(1:3), csym%rt(1:3, 1:3, iop))
1163 IF (ibsign == 2)
THEN
1164 wcart(1:3) = -wcart(1:3)
1167 rr(1) = dot_product(a1(1:3), wcart(1:3))/alat
1168 rr(2) = dot_product(a2(1:3), wcart(1:3))/alat
1169 rr(3) = dot_product(a3(1:3), wcart(1:3))/alat
1173 diff(1:3) = xkp_full(1:3, j) - rr(1:3)
1174 diff(1:3) = diff(1:3) - anint(diff(1:3))
1175 IF (all(abs(diff(1:3)) < eps))
THEN
1177 IF (.NOT. used(j))
THEN
1179 csym%kplink(1, j) = i
1181 wred(nred) = wred(nred) + 1.0_dp
1183 cpassert(csym%kplink(1, j) == i)
1188 IF (.NOT. found)
THEN
1189 CALL cp_abort(__location__, &
1190 "KPOINTS%SYMMETRY with SCHEME GENERAL requires the explicit k-point set "// &
1191 "to be closed under the K290 symmetry operations.")
1197 CALL store_general_reduction(csym, xkp_full, rep, wred, nred)
1199 DEALLOCATE (rep, used, wred)
1201 END SUBROUTINE reduce_general_k290
1208 SUBROUTINE reduce_general_spglib(csym, xkp_full)
1210 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp_full
1212 INTEGER :: i, iop, isign, j, kr, nfull, nred, nrot
1213 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: rep
1214 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: srot
1215 INTEGER,
DIMENSION(3, 3) :: krot
1217 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: used
1218 REAL(kind=
dp) :: eps
1219 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: wred
1220 REAL(kind=
dp),
DIMENSION(3) :: diff, rr
1222 nfull =
SIZE(xkp_full, 2)
1223 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1224 ALLOCATE (srot(3, 3, csym%n_operations))
1225 CALL setup_spglib_operations(csym, srot, nrot)
1227 ALLOCATE (rep(nfull), used(nfull), wred(nfull))
1238 csym%kplink(1, i) = i
1243 kr = csym%ibrot(iop)
1244 krot = reciprocal_rotation(srot(:, :, kr))
1246 rr(1:3) = matmul(real(krot(1:3, 1:3), kind=
dp), xkp_full(1:3, i))
1247 IF (isign == 2)
THEN
1249 kr = -csym%ibrot(iop)
1251 kr = csym%ibrot(iop)
1256 diff(1:3) = xkp_full(1:3, j) - rr(1:3)
1257 diff(1:3) = diff(1:3) - anint(diff(1:3))
1258 IF (all(abs(diff(1:3)) < eps))
THEN
1260 IF (.NOT. used(j))
THEN
1262 csym%kplink(1, j) = i
1264 wred(nred) = wred(nred) + 1.0_dp
1266 cpassert(csym%kplink(1, j) == i)
1271 IF (.NOT. found)
THEN
1272 CALL cp_abort(__location__, &
1273 "KPOINTS%SYMMETRY with SCHEME GENERAL requires the explicit k-point set "// &
1274 "to be closed under the requested symmetry operations.")
1280 CALL store_general_reduction(csym, xkp_full, rep, wred, nred)
1282 DEALLOCATE (rep, srot, used, wred)
1284 END SUBROUTINE reduce_general_spglib
1291 SUBROUTINE reduce_general_spglib_k290(csym, xkp_full)
1293 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp_full
1295 INTEGER :: i, iop, isign, j, k290_op, nfull, nred, &
1297 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: rep
1298 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: srot
1299 INTEGER,
DIMENSION(3, 3) :: krot
1300 LOGICAL :: found, valid
1301 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: used
1302 REAL(kind=
dp) :: alat, eps
1303 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: wred
1304 REAL(kind=
dp),
DIMENSION(3) :: a1, a2, a3, b1, b2, b3, diff, rr
1306 nfull =
SIZE(xkp_full, 2)
1307 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1308 CALL setup_k290_lattice(csym, a1, a2, a3, b1, b2, b3, alat)
1309 ALLOCATE (srot(3, 3, csym%n_operations))
1310 CALL setup_spglib_reduction_rotations(csym, srot, nrot)
1312 ALLOCATE (rep(nfull), used(nfull), wred(nfull))
1324 csym%kplink(1, i) = i
1329 krot = reciprocal_rotation(srot(:, :, iop))
1331 rr(1:3) = matmul(real(krot(1:3, 1:3), kind=
dp), xkp_full(1:3, i))
1332 IF (isign == 2) rr(1:3) = -rr(1:3)
1336 diff(1:3) = xkp_full(1:3, j) - rr(1:3)
1337 diff(1:3) = diff(1:3) - anint(diff(1:3))
1338 IF (all(abs(diff(1:3)) < eps))
THEN
1340 CALL find_k290_kpoint_operation(csym, xkp_full(1:3, i), xkp_full(1:3, j), &
1341 a1, a2, a3, b1, b2, b3, alat, &
1343 IF (.NOT. valid)
THEN
1344 nskipped = nskipped + 1
1347 IF (.NOT. used(j))
THEN
1349 csym%kplink(1, j) = i
1350 csym%kpop(j) = k290_op
1351 wred(nred) = wred(nred) + 1.0_dp
1353 cpassert(csym%kplink(1, j) == i)
1358 IF (.NOT. found)
THEN
1359 CALL cp_abort(__location__, &
1360 "KPOINTS%SYMMETRY with SCHEME GENERAL requires the explicit k-point set "// &
1361 "to be closed under the SPGLIB symmetry operations.")
1367 IF (nskipped > 0)
THEN
1368 CALL cp_warn(__location__, &
1369 "Some SPGLIB k-point mappings are not represented by the K290 backend; "// &
1370 "the GENERAL k-point set was reduced only by the compatible mappings.")
1373 CALL store_general_reduction(csym, xkp_full, rep, wred, nred)
1375 DEALLOCATE (rep, srot, used, wred)
1377 END SUBROUTINE reduce_general_spglib_k290
1387 SUBROUTINE store_general_reduction(csym, xkp_full, rep, wred, nred)
1389 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp_full
1390 INTEGER,
DIMENSION(:),
INTENT(IN) :: rep
1391 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wred
1392 INTEGER,
INTENT(IN) :: nred
1394 INTEGER :: i, j, nfull
1396 nfull =
SIZE(xkp_full, 2)
1398 ALLOCATE (csym%xkpoint(3, nred), csym%wkpoint(nred))
1400 csym%xkpoint(1:3, i) = xkp_full(1:3, rep(i))
1401 csym%wkpoint(i) = wred(i)
1405 IF (csym%kplink(1, i) == rep(j))
THEN
1406 csym%kplink(2, i) = j
1410 cpassert(csym%kplink(2, i) /= 0)
1413 END SUBROUTINE store_general_reduction
1431 SUBROUTINE reduce_spglib_kpoint_mesh_k290(csym, xkp, wkp, kpop, srot, nrot, &
1432 a1, a2, a3, b1, b2, b3, alat)
1434 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp
1435 REAL(kind=
dp),
DIMENSION(:) :: wkp
1436 INTEGER,
DIMENSION(:) :: kpop
1437 INTEGER,
DIMENSION(:, :, :),
INTENT(IN) :: srot
1438 INTEGER,
INTENT(IN) :: nrot
1439 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a1, a2, a3, b1, b2, b3
1440 REAL(kind=
dp),
INTENT(IN) :: alat
1442 INTEGER :: i, iop, isign, j, k290_op, nkpts, &
1444 INTEGER,
DIMENSION(3, 3) :: krot
1446 REAL(kind=
dp) :: eps
1447 REAL(kind=
dp),
DIMENSION(3) :: rr
1450 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1455 csym%kplink(1, :) = 0
1458 IF (csym%kplink(1, i) /= 0) cycle
1460 csym%kplink(1, i) = i
1465 krot = reciprocal_rotation(srot(:, :, iop))
1467 rr(1:3) = matmul(real(krot(1:3, 1:3), kind=
dp), xkp(1:3, i))
1468 IF (isign == 2) rr(1:3) = -rr(1:3)
1470 j = regular_kpoint_index(rr, xkp(1:3, 1), csym%mesh, eps)
1471 IF (j == 0 .OR. j == i) cycle
1472 IF (csym%kplink(1, j) /= 0)
THEN
1473 cpassert(csym%kplink(1, j) == i)
1477 CALL find_k290_kpoint_operation(csym, xkp(1:3, i), xkp(1:3, j), &
1478 a1, a2, a3, b1, b2, b3, alat, &
1480 IF (.NOT. valid)
THEN
1481 nskipped = nskipped + 1
1484 csym%kplink(1, j) = i
1485 wkp(i) = wkp(i) + 1.0_dp
1492 cpassert(csym%kplink(1, i) /= 0)
1493 cpassert(kpop(i) /= 0)
1495 IF (nskipped > 0)
THEN
1496 CALL cp_warn(__location__, &
1497 "Some SPGLIB k-point mappings are not represented by the K290 backend; "// &
1498 "the mesh was reduced only by the compatible mappings.")
1501 END SUBROUTINE reduce_spglib_kpoint_mesh_k290
1518 SUBROUTINE find_k290_kpoint_operation(csym, xref, xtarget, a1, a2, a3, b1, b2, b3, alat, &
1521 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xref, xtarget, a1, a2, a3, b1, b2, b3
1522 REAL(kind=
dp),
INTENT(IN) :: alat
1523 INTEGER,
INTENT(OUT) :: k290_op
1524 LOGICAL,
INTENT(OUT) :: valid
1526 INTEGER :: ibsign, iop, kr
1527 REAL(kind=
dp) :: eps
1528 REAL(kind=
dp),
DIMENSION(3) :: diff, rr, wcart
1530 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1534 DO iop = 1, csym%nrtot
1535 IF (iop >
SIZE(csym%rt, 3)) cycle
1536 IF (csym%ibrot(iop) == 0) cycle
1538 wcart(1:3) = alat*(xref(1)*b1(1:3) + xref(2)*b2(1:3) + xref(3)*b3(1:3))
1539 wcart(1:3) = kp_apply_operation(wcart(1:3), csym%rt(1:3, 1:3, iop))
1540 IF (ibsign == 2)
THEN
1541 wcart(1:3) = -wcart(1:3)
1542 kr = -csym%ibrot(iop)
1544 kr = csym%ibrot(iop)
1546 rr(1) = dot_product(a1(1:3), wcart(1:3))/alat
1547 rr(2) = dot_product(a2(1:3), wcart(1:3))/alat
1548 rr(3) = dot_product(a3(1:3), wcart(1:3))/alat
1550 diff(1:3) = xtarget(1:3) - rr(1:3)
1551 diff(1:3) = diff(1:3) - anint(diff(1:3))
1552 IF (all(abs(diff(1:3)) < eps))
THEN
1560 END SUBROUTINE find_k290_kpoint_operation
1569 FUNCTION spglib_operation_score(csym, iop, srot)
RESULT(score)
1571 INTEGER,
INTENT(IN) :: iop
1572 INTEGER,
DIMENSION(3, 3),
INTENT(IN) :: srot
1576 INTEGER,
DIMENSION(3, 3) :: eye, r2
1577 REAL(kind=
dp) :: eps
1579 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1580 nat =
SIZE(csym%f0, 1)
1583 IF (csym%f0(i, iop) /= i) score = score + 100
1585 IF (any(abs(csym%vt(1:3, iop) - anint(csym%vt(1:3, iop))) > eps)) score = score + 10
1591 r2(1:3, 1:3) = matmul(srot(1:3, 1:3), srot(1:3, 1:3))
1592 IF (any(r2(1:3, 1:3) /= eye(1:3, 1:3))) score = score + 1
1594 END FUNCTION spglib_operation_score
1601 FUNCTION reciprocal_rotation(rot)
RESULT(krot)
1602 INTEGER,
DIMENSION(3, 3),
INTENT(IN) :: rot
1603 INTEGER,
DIMENSION(3, 3) :: krot
1605 REAL(kind=
dp),
DIMENSION(3, 3) :: rinv
1607 rinv =
inv_3x3(real(rot(1:3, 1:3), kind=
dp))
1608 krot(1:3, 1:3) = nint(transpose(rinv(1:3, 1:3)))
1610 END FUNCTION reciprocal_rotation
1629 SUBROUTINE reduce_kpoint_mesh(csym, xkp, wkp, kpop, nc, ib, r, a1, a2, a3, b1, b2, b3, alat)
1631 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp
1632 REAL(kind=
dp),
DIMENSION(:) :: wkp
1633 INTEGER,
DIMENSION(:) :: kpop
1634 INTEGER,
INTENT(IN) :: nc
1635 INTEGER,
DIMENSION(48),
INTENT(IN) :: ib
1636 REAL(kind=
dp),
DIMENSION(3, 3, 48),
INTENT(IN) :: r
1637 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a1, a2, a3, b1, b2, b3
1638 REAL(kind=
dp),
INTENT(IN) :: alat
1640 INTEGER :: i, ibsign, iop, j, kr, nkpts, &
1642 REAL(kind=
dp) :: eps
1643 REAL(kind=
dp),
DIMENSION(3) :: rr, wcart
1646 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1647 nskipped_overlaps = 0
1651 csym%kplink(1, :) = 0
1654 IF (csym%kplink(1, i) /= 0) cycle
1656 csym%kplink(1, i) = i
1663 wcart(1:3) = alat*(xkp(1, i)*b1(1:3) + xkp(2, i)*b2(1:3) + xkp(3, i)*b3(1:3))
1664 wcart(1:3) = kp_apply_operation(wcart(1:3), r(1:3, 1:3, kr))
1665 IF (ibsign == 2)
THEN
1666 wcart(1:3) = -wcart(1:3)
1669 rr(1) = dot_product(a1(1:3), wcart(1:3))/alat
1670 rr(2) = dot_product(a2(1:3), wcart(1:3))/alat
1671 rr(3) = dot_product(a3(1:3), wcart(1:3))/alat
1673 j = regular_kpoint_index(rr, xkp(1:3, 1), csym%mesh, eps)
1676 IF (csym%kplink(1, j) == 0)
THEN
1677 csym%kplink(1, j) = i
1678 wkp(i) = wkp(i) + 1.0_dp
1680 ELSE IF (csym%kplink(1, j) /= i)
THEN
1684 nskipped_overlaps = nskipped_overlaps + 1
1690 IF (nskipped_overlaps > 0)
THEN
1692 CALL inversion_symm(xkp, wkp, csym%kplink(1, :))
1694 IF (wkp(i) > 0.0_dp)
THEN
1701 csym%inversion_only = .true.
1702 CALL cp_warn(__location__, &
1703 "The K290 k-point operations produced overlapping, non-closed mesh orbits; "// &
1704 "falling back to inversion/time-reversal symmetry. Use SYMMETRY_BACKEND SPGLIB "// &
1705 "for full reduction by a closed crystallographic symmetry group.")
1708 cpassert(csym%kplink(1, i) /= 0)
1709 cpassert(kpop(i) /= 0)
1713 END SUBROUTINE reduce_kpoint_mesh
1723 PURE FUNCTION regular_kpoint_index(x, origin, mesh, eps)
RESULT(index)
1724 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: x, origin
1725 INTEGER,
DIMENSION(3),
INTENT(IN) :: mesh
1726 REAL(kind=
dp),
INTENT(IN) :: eps
1730 INTEGER,
DIMENSION(3) :: icoord, istep
1731 REAL(kind=
dp) :: scaled
1734 IF (any(mesh <= 0))
RETURN
1736 scaled = (x(idim) - origin(idim))*real(mesh(idim), kind=
dp)
1737 istep(idim) = nint(scaled)
1738 IF (abs(scaled - real(istep(idim), kind=
dp)) > eps*real(mesh(idim), kind=
dp))
RETURN
1739 icoord(idim) =
modulo(istep(idim), mesh(idim)) + 1
1742 index = ((icoord(1) - 1)*mesh(2) + icoord(2) - 1)*mesh(3) + icoord(3)
1744 END FUNCTION regular_kpoint_index
1754 SUBROUTINE full_grid_gen(nk, xkp, wkp, shift, gamma_centered)
1755 INTEGER,
INTENT(IN) :: nk(3)
1756 REAL(kind=
dp),
DIMENSION(:, :) :: xkp
1757 REAL(kind=
dp),
DIMENSION(:) :: wkp
1758 REAL(kind=
dp),
INTENT(IN) :: shift(3)
1759 LOGICAL,
INTENT(IN),
OPTIONAL :: gamma_centered
1761 INTEGER :: i, idim, ix, iy, iz
1762 INTEGER,
DIMENSION(3) :: ik
1763 LOGICAL :: gamma_mesh
1764 REAL(kind=
dp) :: kpt_latt(3)
1766 IF (
PRESENT(gamma_centered))
THEN
1767 gamma_mesh = gamma_centered
1769 gamma_mesh = .false.
1782 IF (gamma_mesh .AND. mod(nk(idim), 2) == 0)
THEN
1783 kpt_latt(idim) = real(2*ik(idim) - nk(idim), kind=
dp)/ &
1784 (2._dp*real(nk(idim), kind=
dp))
1786 kpt_latt(idim) = real(2*ik(idim) - nk(idim) - 1, kind=
dp)/ &
1787 (2._dp*real(nk(idim), kind=
dp))
1790 xkp(1:3, i) = kpt_latt(1:3)
1795 DO i = 1, nk(1)*nk(2)*nk(3)
1796 xkp(1:3, i) = xkp(1:3, i) + shift(1:3)
1799 END SUBROUTINE full_grid_gen
1807 SUBROUTINE inversion_symm(xkp, wkp, link)
1808 REAL(kind=
dp),
DIMENSION(:, :) :: xkp
1809 REAL(kind=
dp),
DIMENSION(:) :: wkp
1810 INTEGER,
DIMENSION(:) :: link
1812 INTEGER :: i, j, nkpts
1813 REAL(kind=
dp),
DIMENSION(3) :: diff
1815 nkpts =
SIZE(wkp, 1)
1819 IF (link(i) == 0) link(i) = i
1821 IF (wkp(j) == 0) cycle
1822 diff(1:3) = xkp(1:3, i) + xkp(1:3, j)
1823 diff(1:3) = diff(1:3) - anint(diff(1:3))
1824 IF (all(abs(diff(1:3)) < 1.e-12_dp))
THEN
1825 wkp(i) = wkp(i) + wkp(j)
1833 END SUBROUTINE inversion_symm
1841 FUNCTION kp_apply_operation(x, r)
RESULT(y)
1842 REAL(kind=
dp),
INTENT(IN) :: x(3), r(3, 3)
1843 REAL(kind=
dp) :: y(3)
1845 y(1) = r(1, 1)*x(1) + r(1, 2)*x(2) + r(1, 3)*x(3)
1846 y(2) = r(2, 1)*x(1) + r(2, 2)*x(2) + r(2, 3)*x(3)
1847 y(3) = r(3, 1)*x(1) + r(3, 2)*x(2) + r(3, 3)*x(3)
1849 END FUNCTION kp_apply_operation
1858 INTEGER :: i, iunit, j, plevel
1861 IF (iunit >= 0)
THEN
1862 plevel = csym%plevel
1863 WRITE (iunit,
"(/,T2,A)")
"Crystal Symmetry Information"
1864 IF (csym%symlib)
THEN
1865 WRITE (iunit,
'(A,T71,A10)')
" International Symbol: ", adjustr(trim(csym%international_symbol))
1866 WRITE (iunit,
'(A,T71,A10)')
" Point Group Symbol: ", adjustr(trim(csym%pointgroup_symbol))
1867 WRITE (iunit,
'(A,T71,A10)')
" Schoenflies Symbol: ", adjustr(trim(csym%schoenflies))
1869 WRITE (iunit,
'(A,T71,I10)')
" Number of Symmetry Operations: ", csym%n_operations
1870 IF (plevel > 0)
THEN
1871 DO i = 1, csym%n_operations
1872 WRITE (iunit,
'(A,i4,T51,3I10,/,T51,3I10,/,T51,3I10)') &
1873 " Rotation #: ", i, (csym%rotations(j, :, i), j=1, 3)
1874 WRITE (iunit,
'(T36,3F15.7)') csym%translations(:, i)
1878 IF (csym%spglib_requested)
THEN
1879 WRITE (iunit,
"(T2,A)")
"SPGLIB for Crystal Symmetry Information determination is not available"
1881 WRITE (iunit,
"(T2,A)")
"SPGLIB Crystal Symmetry Information was not requested"
1895 INTEGER :: i, iunit, nat, nmesh, plevel
1898 IF (iunit >= 0)
THEN
1899 plevel = csym%plevel
1900 WRITE (iunit,
"(/,T2,A)")
"K-point Symmetry Information"
1901 WRITE (iunit,
'(A,T67,I14)')
" Number of Special K-points: ", csym%nkpoint
1902 WRITE (iunit,
'(T19,A,T74,A)')
" Wavevector Basis ",
" Weight"
1903 DO i = 1, csym%nkpoint
1904 WRITE (iunit,
'(T2,i10,3F10.5,T71,I10)') i, csym%xkpoint(1:3, i), nint(csym%wkpoint(i))
1906 nmesh = csym%mesh(1)*csym%mesh(2)*csym%mesh(3)
1908 WRITE (iunit,
'(/,A,T63,3I6)')
" K-point Mesh: ", csym%mesh(1), csym%mesh(2), csym%mesh(3)
1910 nmesh =
SIZE(csym%kpmesh, 2)
1911 WRITE (iunit,
'(/,A,T70,I10)')
" Explicit K-point Set: ", nmesh
1913 WRITE (iunit,
'(T19,A,T54,A)')
" Wavevector Basis ",
" Special Points Rotation"
1915 WRITE (iunit,
'(T2,i10,3F10.5,T45,3I12)') i, csym%kpmesh(1:3, i), &
1916 csym%kplink(1:2, i), csym%kpop(i)
1918 IF (csym%nrtot > 0)
THEN
1919 WRITE (iunit,
'(/,A)')
" Atom Transformation Table"
1920 nat =
SIZE(csym%f0, 1)
1921 DO i = 1, csym%nrtot
1922 WRITE (iunit,
'(T10,A,I5,(T21,12I5))')
" Rot=", csym%ibrot(i), csym%f0(1:nat, i)
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
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 print_crys_symmetry(csym)
...
subroutine, public kpoint_gen(csym, nk, symm, shift, full_grid, gamma_centered, inversion_symmetry_only, use_spglib_reduction, use_spglib_backend)
...
subroutine, public release_csym_type(csym)
Release the CSYM type.
subroutine, public kpoint_gen_general(csym, xkp_in, wkp_in, symm, full_grid, inversion_symmetry_only, use_spglib_reduction, use_spglib_backend)
Reduce an explicitly supplied GENERAL k-point set.
subroutine, public print_kp_symmetry(csym)
...
subroutine, public crys_sym_gen(csym, scoor, types, hmat, delta, iounit, use_spglib)
...
Defines the basic variable types.
integer, parameter, public dp
Crystal-symmetry routines originating from the K290/ACMI code.
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)
...
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.