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.
50 LOGICAL :: spglib_requested = .true.
53 INTEGER :: istriz = -1
54 REAL(kind=
dp) :: delta = 1.0e-8_dp
55 REAL(kind=
dp),
DIMENSION(3, 3) :: hmat = 0.0_dp
57 REAL(kind=
dp),
DIMENSION(3) :: wvk0 = 0.0_dp
58 INTEGER,
DIMENSION(3) :: mesh = 0
59 INTEGER :: nkpoint = 0
61 INTEGER,
DIMENSION(:),
ALLOCATABLE :: atype
62 REAL(kind=
dp),
DIMENSION(:, :),
ALLOCATABLE :: scoord
63 REAL(kind=
dp),
DIMENSION(:, :),
ALLOCATABLE :: xkpoint
64 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: wkpoint
65 REAL(kind=
dp),
DIMENSION(:, :),
ALLOCATABLE :: kpmesh
66 INTEGER,
DIMENSION(:, :),
ALLOCATABLE :: kplink
67 INTEGER,
DIMENSION(:),
ALLOCATABLE :: kpop
69 CHARACTER(len=11) :: international_symbol =
""
70 CHARACTER(len=6) :: pointgroup_symbol =
""
71 CHARACTER(len=10) :: schoenflies =
""
72 INTEGER :: n_operations = 0
73 INTEGER,
DIMENSION(:, :, :),
ALLOCATABLE :: rotations
74 REAL(kind=
dp),
DIMENSION(:, :),
ALLOCATABLE :: translations
76 REAL(kind=
dp),
DIMENSION(:, :, :),
ALLOCATABLE :: rt
77 REAL(kind=
dp),
DIMENSION(:, :),
ALLOCATABLE :: vt
78 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: f0
80 INTEGER,
DIMENSION(:),
ALLOCATABLE :: ibrot
92 IF (
ALLOCATED(csym%rotations))
THEN
93 DEALLOCATE (csym%rotations)
95 IF (
ALLOCATED(csym%translations))
THEN
96 DEALLOCATE (csym%translations)
98 IF (
ALLOCATED(csym%atype))
THEN
99 DEALLOCATE (csym%atype)
101 IF (
ALLOCATED(csym%scoord))
THEN
102 DEALLOCATE (csym%scoord)
104 IF (
ALLOCATED(csym%xkpoint))
THEN
105 DEALLOCATE (csym%xkpoint)
107 IF (
ALLOCATED(csym%wkpoint))
THEN
108 DEALLOCATE (csym%wkpoint)
110 IF (
ALLOCATED(csym%kpmesh))
THEN
111 DEALLOCATE (csym%kpmesh)
113 IF (
ALLOCATED(csym%kplink))
THEN
114 DEALLOCATE (csym%kplink)
116 IF (
ALLOCATED(csym%kpop))
THEN
117 DEALLOCATE (csym%kpop)
119 IF (
ALLOCATED(csym%rt))
THEN
122 IF (
ALLOCATED(csym%vt))
THEN
125 IF (
ALLOCATED(csym%f0))
THEN
128 IF (
ALLOCATED(csym%ibrot))
THEN
129 DEALLOCATE (csym%ibrot)
144 SUBROUTINE crys_sym_gen(csym, scoor, types, hmat, delta, iounit, use_spglib)
146 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: scoor
147 INTEGER,
DIMENSION(:),
INTENT(IN) :: types
148 REAL(kind=
dp),
INTENT(IN) :: hmat(3, 3)
149 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: delta
150 INTEGER,
INTENT(IN),
OPTIONAL :: iounit
151 LOGICAL,
INTENT(IN),
OPTIONAL :: use_spglib
153 CHARACTER(LEN=*),
PARAMETER :: routinen =
'crys_sym_gen'
155 INTEGER :: handle, ierr, major, micro, minor, nat, &
157 LOGICAL :: my_use_spglib, spglib
159 CALL timeset(routinen, handle)
166 IF (
PRESENT(iounit))
THEN
173 IF (
PRESENT(delta))
THEN
176 csym%delta = 1.e-6_dp
183 ALLOCATE (csym%atype(nat))
184 csym%atype(1:nat) = types(1:nat)
187 ALLOCATE (csym%scoord(3, nat))
188 csym%scoord(1:3, 1:nat) = scoor(1:3, 1:nat)
190 csym%n_operations = 0
193 my_use_spglib = .true.
194 IF (
PRESENT(use_spglib)) my_use_spglib = use_spglib
195 csym%spglib_requested = my_use_spglib
196 IF (.NOT. my_use_spglib)
THEN
203 CALL cp_warn(__location__,
"Symmetry library SPGLIB not available")
210 CALL cp_warn(__location__,
"Symmetry Library SPGLIB failed")
214 ALLOCATE (csym%rotations(3, 3, nop), csym%translations(3, nop))
215 csym%n_operations = nop
217 transpose(hmat), scoor, types, nat, delta)
219 csym%schoenflies =
' '
222 csym%pointgroup_symbol =
' '
225 csym%rotations, csym%n_operations)
235 CALL timestop(handle)
251 SUBROUTINE kpoint_gen(csym, nk, symm, shift, full_grid, gamma_centered, &
252 inversion_symmetry_only, use_spglib_reduction, use_spglib_backend)
254 INTEGER,
INTENT(IN) :: nk(3)
255 LOGICAL,
INTENT(IN),
OPTIONAL :: symm
256 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: shift(3)
257 LOGICAL,
INTENT(IN),
OPTIONAL :: full_grid, gamma_centered, &
258 inversion_symmetry_only, &
259 use_spglib_reduction, &
262 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_gen'
264 INTEGER :: handle, i, ik, j, nkp, nkpts
265 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: kpop, xptr
266 LOGICAL :: fullmesh, gamma_mesh, inversion_only, &
267 spglib_backend, spglib_reduction
268 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: wkp
269 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: xkp
271 CALL timeset(routinen, handle)
273 IF (
PRESENT(shift))
THEN
280 IF (
PRESENT(symm))
THEN
281 IF (symm) csym%istriz = 1
284 IF (
PRESENT(full_grid))
THEN
289 csym%fullgrid = fullmesh
291 IF (
PRESENT(gamma_centered))
THEN
292 gamma_mesh = gamma_centered
297 IF (
PRESENT(inversion_symmetry_only))
THEN
298 inversion_only = inversion_symmetry_only
300 inversion_only = .false.
302 csym%inversion_only = inversion_only
304 IF (
PRESENT(use_spglib_reduction))
THEN
305 spglib_reduction = use_spglib_reduction
307 spglib_reduction = .false.
309 csym%spglib_reduction = spglib_reduction
311 IF (
PRESENT(use_spglib_backend))
THEN
312 spglib_backend = use_spglib_backend
314 spglib_backend = .false.
316 csym%spglib_backend = spglib_backend
318 IF (spglib_backend .AND. .NOT. spglib_reduction)
THEN
319 CALL cp_abort(__location__, &
320 "SYMMETRY_BACKEND SPGLIB requires SYMMETRY_REDUCTION_METHOD SPGLIB")
322 IF (csym%istriz == 1 .AND. .NOT. fullmesh .AND. .NOT. inversion_only .AND. &
323 (spglib_backend .OR. spglib_reduction) .AND. .NOT. csym%symlib)
THEN
324 CALL cp_abort(__location__, &
325 "SPGLIB k-point symmetry was requested, but SPGLIB is not available")
329 csym%mesh(1:3) = nk(1:3)
331 IF (
ALLOCATED(csym%rt))
DEALLOCATE (csym%rt)
332 IF (
ALLOCATED(csym%vt))
DEALLOCATE (csym%vt)
333 IF (
ALLOCATED(csym%ibrot))
DEALLOCATE (csym%ibrot)
334 IF (
ALLOCATED(csym%f0))
DEALLOCATE (csym%f0)
335 ALLOCATE (csym%rt(3, 3, 0), csym%vt(3, 0), csym%ibrot(0), csym%f0(csym%nat, 0))
337 nkpts = nk(1)*nk(2)*nk(3)
338 ALLOCATE (xkp(3, nkpts), wkp(nkpts), kpop(nkpts))
340 ALLOCATE (csym%kplink(2, nkpts))
345 IF (csym%symlib)
THEN
349 CALL full_grid_gen(nk, xkp, wkp, shift, gamma_centered=gamma_mesh)
350 IF (csym%istriz == 1)
THEN
352 CALL inversion_symm(xkp, wkp, csym%kplink(1, :))
356 ELSE IF (csym%istriz /= 1 .OR. inversion_only)
THEN
358 CALL full_grid_gen(nk, xkp, wkp, shift, gamma_centered=gamma_mesh)
359 CALL inversion_symm(xkp, wkp, csym%kplink(1, :))
362 CALL full_grid_gen(nk, xkp, wkp, shift, gamma_centered=gamma_mesh)
363 IF (spglib_backend)
THEN
364 CALL kp_symmetry_spglib(csym, xkp, wkp, kpop)
366 CALL kp_symmetry(csym, xkp, wkp, kpop, use_spglib_reduction=spglib_reduction)
372 CALL full_grid_gen(nk, xkp, wkp, shift, gamma_centered=gamma_mesh)
373 IF (csym%istriz == 1 .AND. .NOT. fullmesh .AND. .NOT. inversion_only)
THEN
375 CALL kp_symmetry(csym, xkp, wkp, kpop, use_spglib_reduction=.false.)
376 ELSE IF (csym%istriz /= 1 .AND. fullmesh)
THEN
379 csym%kplink(1, i) = i
383 CALL inversion_symm(xkp, wkp, csym%kplink(1, :))
389 IF (wkp(i) > 0.0_dp) nkp = nkp + 1
394 ALLOCATE (csym%xkpoint(3, nkp), csym%wkpoint(nkp))
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)
415 IF (i == xptr(j))
THEN
416 csym%kplink(2, ik) = j
424 ALLOCATE (csym%kpop(nkpts))
425 IF (csym%nrtot > 0 .AND. csym%istriz == 1 .AND. .NOT. fullmesh .AND. &
426 .NOT. inversion_only)
THEN
428 csym%kpop(1:nkpts) = kpop(1:nkpts)
430 cpassert(csym%kpop(ik) /= 0)
435 IF (wkp(ik) > 0.0_dp)
THEN
443 DEALLOCATE (xkp, wkp, kpop)
445 CALL timestop(handle)
461 inversion_symmetry_only, use_spglib_reduction, use_spglib_backend)
463 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp_in
464 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wkp_in
465 LOGICAL,
INTENT(IN),
OPTIONAL :: symm, full_grid, &
466 inversion_symmetry_only, &
467 use_spglib_reduction, &
470 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_gen_general'
472 INTEGER :: handle, i, nfull
473 LOGICAL :: atomic_symmetry, fullmesh, &
474 inversion_only, spglib_backend, &
476 REAL(kind=
dp) :: weight_eps
478 CALL timeset(routinen, handle)
481 cpassert(
SIZE(xkp_in, 1) == 3)
482 cpassert(
SIZE(xkp_in, 2) == nfull)
484 atomic_symmetry = .false.
485 IF (
PRESENT(symm)) atomic_symmetry = symm
487 IF (atomic_symmetry) csym%istriz = 1
489 IF (
PRESENT(full_grid)) fullmesh = full_grid
490 inversion_only = .false.
491 IF (
PRESENT(inversion_symmetry_only)) inversion_only = inversion_symmetry_only
492 spglib_reduction = .false.
493 IF (
PRESENT(use_spglib_reduction)) spglib_reduction = use_spglib_reduction
494 spglib_backend = .false.
495 IF (
PRESENT(use_spglib_backend)) spglib_backend = use_spglib_backend
497 csym%fullgrid = fullmesh
498 csym%inversion_only = inversion_only
499 csym%spglib_reduction = spglib_reduction
500 csym%spglib_backend = spglib_backend
504 IF (
ALLOCATED(csym%rt))
DEALLOCATE (csym%rt)
505 IF (
ALLOCATED(csym%vt))
DEALLOCATE (csym%vt)
506 IF (
ALLOCATED(csym%ibrot))
DEALLOCATE (csym%ibrot)
507 IF (
ALLOCATED(csym%f0))
DEALLOCATE (csym%f0)
508 ALLOCATE (csym%rt(3, 3, 0), csym%vt(3, 0), csym%ibrot(0), csym%f0(csym%nat, 0))
509 IF (
ALLOCATED(csym%xkpoint))
DEALLOCATE (csym%xkpoint)
510 IF (
ALLOCATED(csym%wkpoint))
DEALLOCATE (csym%wkpoint)
511 IF (
ALLOCATED(csym%kpmesh))
DEALLOCATE (csym%kpmesh)
512 IF (
ALLOCATED(csym%kplink))
DEALLOCATE (csym%kplink)
513 IF (
ALLOCATED(csym%kpop))
DEALLOCATE (csym%kpop)
515 ALLOCATE (csym%kpmesh(3, nfull), csym%kplink(2, nfull), csym%kpop(nfull))
516 csym%kpmesh(1:3, 1:nfull) = xkp_in(1:3, 1:nfull)
520 IF (.NOT. atomic_symmetry .OR. fullmesh)
THEN
522 ALLOCATE (csym%xkpoint(3, nfull), csym%wkpoint(nfull))
523 csym%xkpoint(1:3, 1:nfull) = xkp_in(1:3, 1:nfull)
524 csym%wkpoint(1:nfull) = wkp_in(1:nfull)
526 csym%kplink(1:2, i) = i
528 ELSE IF (inversion_only)
THEN
529 CALL reduce_general_inversion(csym, xkp_in, wkp_in)
531 weight_eps = max(1.e-12_dp, 10.0_dp*csym%delta)
532 IF (any(abs(wkp_in(1:nfull) - wkp_in(1)) > weight_eps))
THEN
533 CALL cp_abort(__location__, &
534 "KPOINTS%SYMMETRY with SCHEME GENERAL requires equal explicit weights.")
536 IF (spglib_backend)
THEN
537 IF (.NOT. csym%symlib)
THEN
538 CALL cp_abort(__location__, &
539 "SCHEME GENERAL with SYMMETRY_BACKEND SPGLIB requires SPGLIB.")
541 CALL reduce_general_spglib(csym, xkp_in)
542 ELSE IF (spglib_reduction)
THEN
543 IF (.NOT. csym%symlib)
THEN
544 CALL cp_abort(__location__, &
545 "SCHEME GENERAL with SYMMETRY_REDUCTION_METHOD SPGLIB requires SPGLIB.")
547 CALL setup_k290_operations(csym)
548 CALL reduce_general_spglib_k290(csym, xkp_in)
550 CALL setup_k290_operations(csym)
551 CALL reduce_general_k290(csym, xkp_in)
555 CALL timestop(handle)
567 SUBROUTINE kp_symmetry(csym, xkp, wkp, kpop, use_spglib_reduction)
569 REAL(kind=
dp),
DIMENSION(:, :) :: xkp
570 REAL(kind=
dp),
DIMENSION(:) :: wkp
571 INTEGER,
DIMENSION(:) :: kpop
572 LOGICAL,
INTENT(IN),
OPTIONAL :: use_spglib_reduction
574 INTEGER :: i, ihc, ihg, indpg, iou, iq1, iq2, iq3, &
575 istriz, isy, li, nat, nc, nhash, &
576 nkpoint, nrot, nsp, ntvec
577 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: includ, isc,
list, lwght, ty
578 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: f0, lrot
579 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: srot
580 INTEGER,
DIMENSION(48) :: ib
581 LOGICAL :: spglib_reduction
582 REAL(kind=
dp) :: alat
583 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: rlist, rx, tvec, wvkl, xkapa
584 REAL(kind=
dp),
DIMENSION(3) :: a1, a2, a3, b1, b2, b3, origin, wvk0
585 REAL(kind=
dp),
DIMENSION(3, 3) :: hmat, strain
586 REAL(kind=
dp),
DIMENSION(3, 3, 48) :: r
587 REAL(kind=
dp),
DIMENSION(3, 48) :: vt
595 nkpoint = 10*iq1*iq2*iq3
600 IF (
PRESENT(use_spglib_reduction))
THEN
601 spglib_reduction = use_spglib_reduction
603 spglib_reduction = .false.
605 a1(1:3) = hmat(1:3, 1)
606 a2(1:3) = hmat(1:3, 2)
607 a3(1:3) = hmat(1:3, 3)
608 alat = sqrt(sum(a1**2))
610 ALLOCATE (xkapa(3, nat), rx(3, nat), tvec(3, 200), ty(nat), isc(nat), f0(49, nat))
611 ty(1:nat) = csym%atype(1:nat)
614 xkapa(1:3, i) = matmul(hmat, csym%scoord(1:3, i))
616 nhash = max(1000, nkpoint)
617 ALLOCATE (wvkl(3, nkpoint), rlist(3, nkpoint), includ(nkpoint),
list(nhash + nkpoint))
618 ALLOCATE (lrot(48, nkpoint), lwght(nkpoint))
621 WRITE (iou,
'(/,(T2,A79))') &
622 "*******************************************************************************", &
623 "** Special K-Point Generation by K290 **", &
624 "*******************************************************************************"
627 IF (spglib_reduction)
CALL cite_reference(
togo2018)
629 CALL k290s(iou, nat, nkpoint, nsp, iq1, iq2, iq3, istriz, &
630 a1, a2, a3, alat, strain, xkapa, rx, tvec, &
631 ty, isc, f0, ntvec, wvk0, wvkl, lwght, lrot, &
632 nhash, includ,
list, rlist, csym%delta)
634 CALL group1s(0, a1, a2, a3, nat, ty, xkapa, b1, b2, b3, &
635 ihg, ihc, isy, li, nc, indpg, ib, ntvec, &
636 vt, f0, r, tvec, origin, rx, isc, csym%delta)
639 WRITE (iou,
'((T2,A79))') &
640 "*******************************************************************************", &
641 "** Finished K290 **", &
642 "*******************************************************************************"
646 IF (
ALLOCATED(csym%rt))
DEALLOCATE (csym%rt)
647 IF (
ALLOCATED(csym%vt))
DEALLOCATE (csym%vt)
648 IF (
ALLOCATED(csym%ibrot))
DEALLOCATE (csym%ibrot)
649 IF (
ALLOCATED(csym%f0))
DEALLOCATE (csym%f0)
650 ALLOCATE (csym%rt(3, 3, nc), csym%vt(3, nc), csym%ibrot(nc))
651 csym%vt(1:3, 1:nc) = vt(1:3, 1:nc)
652 ALLOCATE (csym%f0(nat, nc))
654 csym%rt(1:3, 1:3, i) = r(1:3, 1:3, ib(i))
655 csym%f0(1:nat, i) = f0(i, 1:nat)
657 csym%ibrot(1:nc) = ib(1:nc)
659 IF (csym%n_operations > nc .AND. .NOT. spglib_reduction)
THEN
660 IF (
ALLOCATED(srot))
DEALLOCATE (srot)
661 ALLOCATE (srot(3, 3, csym%n_operations))
662 CALL setup_spglib_operations(csym, srot, nrot)
663 CALL reduce_spglib_kpoint_mesh(csym, xkp, wkp, kpop, srot, nrot)
665 ELSE IF (spglib_reduction)
THEN
666 ALLOCATE (srot(3, 3, csym%n_operations))
667 CALL setup_spglib_reduction_rotations(csym, srot, nrot)
668 CALL reduce_spglib_kpoint_mesh_k290(csym, xkp, wkp, kpop, srot, nrot, &
669 a1, a2, a3, b1, b2, b3, alat)
672 CALL reduce_kpoint_mesh(csym, xkp, wkp, kpop, nc, ib, r, a1, a2, a3, b1, b2, b3, alat)
674 DEALLOCATE (xkapa, rx, tvec, ty, isc, f0)
675 DEALLOCATE (wvkl, rlist, includ,
list)
676 DEALLOCATE (lrot, lwght)
678 END SUBROUTINE kp_symmetry
687 SUBROUTINE kp_symmetry_spglib(csym, xkp, wkp, kpop)
689 REAL(kind=
dp),
DIMENSION(:, :) :: xkp
690 REAL(kind=
dp),
DIMENSION(:) :: wkp
691 INTEGER,
DIMENSION(:) :: kpop
694 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: srot
698 WRITE (iou,
'(/,(T2,A79))') &
699 "*******************************************************************************", &
700 "** Special K-Point Generation by SPGLIB **", &
701 "*******************************************************************************"
705 ALLOCATE (srot(3, 3, csym%n_operations))
706 CALL setup_spglib_operations(csym, srot, nrot)
707 CALL reduce_spglib_kpoint_mesh(csym, xkp, wkp, kpop, srot, nrot)
711 WRITE (iou,
'((T2,A79))') &
712 "*******************************************************************************", &
713 "** Finished SPGLIB **", &
714 "*******************************************************************************"
717 END SUBROUTINE kp_symmetry_spglib
723 SUBROUTINE setup_k290_operations(csym)
726 INTEGER :: i, ihc, ihg, indpg, iou, iq1, iq2, iq3, &
727 isy, li, nat, nc, nhash, nkpoint, nsp, &
729 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: includ, isc,
list, lwght, ty
730 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: f0, lrot
731 INTEGER,
DIMENSION(48) :: ib
732 REAL(kind=
dp) :: alat
733 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: rlist, rx, tvec, wvkl, xkapa
734 REAL(kind=
dp),
DIMENSION(3) :: a1, a2, a3, b1, b2, b3, origin, wvk0
735 REAL(kind=
dp),
DIMENSION(3, 3) :: strain
736 REAL(kind=
dp),
DIMENSION(3, 3, 48) :: r
737 REAL(kind=
dp),
DIMENSION(3, 48) :: vt
741 CALL setup_k290_lattice(csym, a1, a2, a3, b1, b2, b3, alat)
742 iq1 = max(1, csym%mesh(1))
743 iq2 = max(1, csym%mesh(2))
744 iq3 = max(1, csym%mesh(3))
745 nkpoint = max(10, 10*iq1*iq2*iq3)
749 ALLOCATE (xkapa(3, nat), rx(3, nat), tvec(3, 200), ty(nat), isc(nat), f0(49, nat))
750 ty(1:nat) = csym%atype(1:nat)
753 xkapa(1:3, i) = matmul(csym%hmat, csym%scoord(1:3, i))
755 nhash = max(1000, nkpoint)
756 ALLOCATE (wvkl(3, nkpoint), rlist(3, nkpoint), includ(nkpoint),
list(nhash + nkpoint))
757 ALLOCATE (lrot(48, nkpoint), lwght(nkpoint))
760 WRITE (iou,
'(/,(T2,A79))') &
761 "*******************************************************************************", &
762 "** Special K-Point Generation by K290 **", &
763 "*******************************************************************************"
767 CALL k290s(iou, nat, nkpoint, nsp, iq1, iq2, iq3, csym%istriz, &
768 a1, a2, a3, alat, strain, xkapa, rx, tvec, &
769 ty, isc, f0, ntvec, wvk0, wvkl, lwght, lrot, &
770 nhash, includ,
list, rlist, csym%delta)
772 CALL group1s(0, a1, a2, a3, nat, ty, xkapa, b1, b2, b3, &
773 ihg, ihc, isy, li, nc, indpg, ib, ntvec, &
774 vt, f0, r, tvec, origin, rx, isc, csym%delta)
777 WRITE (iou,
'((T2,A79))') &
778 "*******************************************************************************", &
779 "** Finished K290 **", &
780 "*******************************************************************************"
784 IF (
ALLOCATED(csym%rt))
DEALLOCATE (csym%rt)
785 IF (
ALLOCATED(csym%vt))
DEALLOCATE (csym%vt)
786 IF (
ALLOCATED(csym%ibrot))
DEALLOCATE (csym%ibrot)
787 IF (
ALLOCATED(csym%f0))
DEALLOCATE (csym%f0)
788 ALLOCATE (csym%rt(3, 3, nc), csym%vt(3, nc), csym%ibrot(nc))
789 csym%vt(1:3, 1:nc) = vt(1:3, 1:nc)
790 ALLOCATE (csym%f0(nat, nc))
792 csym%rt(1:3, 1:3, i) = r(1:3, 1:3, ib(i))
793 csym%f0(1:nat, i) = f0(i, 1:nat)
795 csym%ibrot(1:nc) = ib(1:nc)
797 DEALLOCATE (xkapa, rx, tvec, ty, isc, f0)
798 DEALLOCATE (wvkl, rlist, includ,
list)
799 DEALLOCATE (lrot, lwght)
801 END SUBROUTINE setup_k290_operations
814 SUBROUTINE setup_k290_lattice(csym, a1, a2, a3, b1, b2, b3, alat)
816 REAL(kind=
dp),
DIMENSION(3),
INTENT(OUT) :: a1, a2, a3, b1, b2, b3
817 REAL(kind=
dp),
INTENT(OUT) :: alat
819 REAL(kind=
dp) :: volum
821 a1(1:3) = csym%hmat(1:3, 1)
822 a2(1:3) = csym%hmat(1:3, 2)
823 a3(1:3) = csym%hmat(1:3, 3)
824 alat = sqrt(sum(a1**2))
825 volum = a1(1)*a2(2)*a3(3) + a2(1)*a3(2)*a1(3) + &
826 a3(1)*a1(2)*a2(3) - a1(3)*a2(2)*a3(1) - &
827 a2(3)*a3(2)*a1(1) - a3(3)*a1(2)*a2(1)
829 b1(1) = (a2(2)*a3(3) - a2(3)*a3(2))/volum
830 b1(2) = (a2(3)*a3(1) - a2(1)*a3(3))/volum
831 b1(3) = (a2(1)*a3(2) - a2(2)*a3(1))/volum
832 b2(1) = (a3(2)*a1(3) - a3(3)*a1(2))/volum
833 b2(2) = (a3(3)*a1(1) - a3(1)*a1(3))/volum
834 b2(3) = (a3(1)*a1(2) - a3(2)*a1(1))/volum
835 b3(1) = (a1(2)*a2(3) - a1(3)*a2(2))/volum
836 b3(2) = (a1(3)*a2(1) - a1(1)*a2(3))/volum
837 b3(3) = (a1(1)*a2(2) - a1(2)*a2(1))/volum
839 END SUBROUTINE setup_k290_lattice
847 SUBROUTINE setup_spglib_operations(csym, srot, nrot)
849 INTEGER,
DIMENSION(:, :, :),
INTENT(OUT) :: srot
850 INTEGER,
INTENT(OUT) :: nrot
852 INTEGER :: iop, jop, pass
853 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: perm
854 INTEGER,
DIMENSION(3, 3) :: eye, frot, irot
855 LOGICAL :: duplicate, identity, valid, &
858 REAL(kind=
dp),
DIMENSION(3, 3) :: h_inv, rfrac
860 cpassert(csym%symlib)
864 IF (
ALLOCATED(csym%rt))
DEALLOCATE (csym%rt)
865 IF (
ALLOCATED(csym%vt))
DEALLOCATE (csym%vt)
866 IF (
ALLOCATED(csym%ibrot))
DEALLOCATE (csym%ibrot)
867 IF (
ALLOCATED(csym%f0))
DEALLOCATE (csym%f0)
868 ALLOCATE (csym%rt(3, 3, csym%n_operations), csym%vt(3, csym%n_operations))
869 ALLOCATE (csym%ibrot(csym%n_operations), csym%f0(csym%nat, csym%n_operations))
875 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
877 ALLOCATE (perm(csym%nat))
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 zero_translation = all(abs(csym%translations(1:3, iop) - &
893 anint(csym%translations(1:3, iop))) <= eps)
894 IF (pass == 1 .AND. (.NOT. identity .OR. .NOT. zero_translation)) cycle
895 IF (pass == 2 .AND. (identity .OR. .NOT. zero_translation)) cycle
896 IF (pass == 3 .AND. (.NOT. identity .OR. zero_translation)) cycle
897 IF (pass == 4 .AND. (identity .OR. zero_translation)) cycle
901 IF (all(frot == srot(:, :, jop)))
THEN
908 CALL spglib_atom_permutation(csym, frot, csym%translations(:, iop), perm, valid)
909 IF (.NOT. valid) cycle
913 srot(1:3, 1:3, nrot) = frot(1:3, 1:3)
914 rfrac(1:3, 1:3) = real(frot(1:3, 1:3), kind=
dp)
915 csym%rt(1:3, 1:3, nrot) = matmul(csym%hmat, matmul(rfrac, h_inv))
916 csym%vt(1:3, nrot) = csym%translations(1:3, iop)
917 csym%ibrot(nrot) = nrot
918 csym%f0(1:csym%nat, nrot) = perm(1:csym%nat)
924 IF (nrot == 0)
CALL cp_abort(__location__,
"SPGLIB did not return usable symmetry operations")
926 END SUBROUTINE setup_spglib_operations
934 SUBROUTINE setup_spglib_reduction_rotations(csym, srot, nrot)
936 INTEGER,
DIMENSION(:, :, :),
INTENT(OUT) :: srot
937 INTEGER,
INTENT(OUT) :: nrot
939 INTEGER :: iop, jop, pass
940 INTEGER,
DIMENSION(3, 3) :: eye, frot, irot
941 LOGICAL :: duplicate, identity
943 cpassert(csym%symlib)
954 DO iop = 1, csym%n_operations
955 irot(1:3, 1:3) = csym%rotations(1:3, 1:3, iop)
956 frot(1:3, 1:3) = transpose(irot(1:3, 1:3))
957 identity = all(frot == eye)
958 IF (pass == 1 .AND. .NOT. identity) cycle
959 IF (pass == 2 .AND. identity) cycle
963 IF (all(frot == srot(:, :, jop)))
THEN
971 srot(1:3, 1:3, nrot) = frot(1:3, 1:3)
975 IF (nrot == 0)
CALL cp_abort(__location__,
"SPGLIB did not return usable symmetry rotations")
977 END SUBROUTINE setup_spglib_reduction_rotations
987 SUBROUTINE spglib_atom_permutation(csym, rot, trans, perm, valid)
989 INTEGER,
DIMENSION(3, 3),
INTENT(IN) :: rot
990 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: trans
991 INTEGER,
DIMENSION(:),
INTENT(OUT) :: perm
992 LOGICAL,
INTENT(OUT) :: valid
996 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: used
998 REAL(kind=
dp),
DIMENSION(3) :: diff, spos
999 REAL(kind=
dp),
DIMENSION(3, 3) :: rfrac
1002 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1003 rfrac(1:3, 1:3) = real(rot(1:3, 1:3), kind=
dp)
1004 ALLOCATE (used(nat))
1010 spos(1:3) = matmul(rfrac(1:3, 1:3), csym%scoord(1:3, i)) + trans(1:3)
1014 IF (csym%atype(i) /= csym%atype(j)) cycle
1015 diff(1:3) = spos(1:3) - csym%scoord(1:3, j)
1016 diff(1:3) = diff(1:3) - anint(diff(1:3))
1017 IF (all(abs(diff(1:3)) < eps))
THEN
1024 IF (.NOT. found)
THEN
1032 END SUBROUTINE spglib_atom_permutation
1043 SUBROUTINE reduce_spglib_kpoint_mesh(csym, xkp, wkp, kpop, srot, nrot)
1045 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp
1046 REAL(kind=
dp),
DIMENSION(:) :: wkp
1047 INTEGER,
DIMENSION(:) :: kpop
1048 INTEGER,
DIMENSION(:, :, :),
INTENT(IN) :: srot
1049 INTEGER,
INTENT(IN) :: nrot
1051 INTEGER :: i, iop, isign, j, kr, nkpts, score
1052 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: kscore
1053 INTEGER,
DIMENSION(3, 3) :: krot
1054 REAL(kind=
dp) :: eps
1055 REAL(kind=
dp),
DIMENSION(3) :: diff, rr
1058 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1059 ALLOCATE (kscore(nkpts))
1063 csym%kplink(1, :) = 0
1067 IF (csym%kplink(1, i) /= 0) cycle
1069 csym%kplink(1, i) = i
1075 kr = csym%ibrot(iop)
1076 krot = reciprocal_rotation(srot(:, :, kr))
1077 score = spglib_operation_score(csym, iop, srot(:, :, kr))
1079 rr(1:3) = matmul(real(krot(1:3, 1:3), kind=
dp), xkp(1:3, i))
1080 IF (isign == 2)
THEN
1082 kr = -csym%ibrot(iop)
1084 kr = csym%ibrot(iop)
1088 diff(1:3) = xkp(1:3, j) - rr(1:3)
1089 diff(1:3) = diff(1:3) - anint(diff(1:3))
1090 IF (all(abs(diff(1:3)) < eps))
THEN
1091 IF (csym%kplink(1, j) == 0)
THEN
1092 csym%kplink(1, j) = i
1093 wkp(i) = wkp(i) + 1.0_dp
1097 cpassert(csym%kplink(1, j) == i)
1098 IF (score < kscore(j))
THEN
1106 IF (j > nkpts) cycle
1112 cpassert(csym%kplink(1, i) /= 0)
1113 cpassert(kpop(i) /= 0)
1117 END SUBROUTINE reduce_spglib_kpoint_mesh
1125 SUBROUTINE reduce_general_inversion(csym, xkp_full, wkp_full)
1127 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp_full
1128 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wkp_full
1130 INTEGER :: i, j, nfull, nred
1131 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: rep
1132 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: used
1133 REAL(kind=
dp) :: eps
1134 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: wred
1135 REAL(kind=
dp),
DIMENSION(3) :: diff
1137 nfull =
SIZE(wkp_full)
1138 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1139 ALLOCATE (rep(nfull), used(nfull), wred(nfull))
1150 csym%kplink(1, i) = i
1152 wred(nred) = wkp_full(i)
1155 diff(1:3) = xkp_full(1:3, j) + xkp_full(1:3, i)
1156 diff(1:3) = diff(1:3) - anint(diff(1:3))
1157 IF (all(abs(diff(1:3)) < eps))
THEN
1158 IF (abs(wkp_full(j) - wkp_full(i)) > eps)
THEN
1159 CALL cp_abort(__location__, &
1160 "KPOINTS%INVERSION_SYMMETRY_ONLY with SCHEME GENERAL requires "// &
1161 "equal weights for inversion-related k-points.")
1164 csym%kplink(1, j) = i
1166 wred(nred) = wred(nred) + wkp_full(j)
1172 ALLOCATE (csym%xkpoint(3, nred), csym%wkpoint(nred))
1174 csym%xkpoint(1:3, i) = xkp_full(1:3, rep(i))
1175 csym%wkpoint(i) = wred(i)
1179 IF (csym%kplink(1, i) == rep(j))
THEN
1180 csym%kplink(2, i) = j
1186 DEALLOCATE (rep, used, wred)
1188 END SUBROUTINE reduce_general_inversion
1195 SUBROUTINE reduce_general_k290(csym, xkp_full)
1197 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp_full
1199 INTEGER :: i, ibsign, iop, j, kr, nfull, nred
1200 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: rep
1202 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: used
1203 REAL(kind=
dp) :: alat, eps
1204 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: wred
1205 REAL(kind=
dp),
DIMENSION(3) :: a1, a2, a3, b1, b2, b3, diff, rr, wcart
1207 nfull =
SIZE(xkp_full, 2)
1208 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1209 CALL setup_k290_lattice(csym, a1, a2, a3, b1, b2, b3, alat)
1211 ALLOCATE (rep(nfull), used(nfull), wred(nfull))
1222 csym%kplink(1, i) = i
1226 DO iop = 1, csym%nrtot
1228 kr = csym%ibrot(iop)
1229 wcart(1:3) = alat*(xkp_full(1, i)*b1(1:3) + &
1230 xkp_full(2, i)*b2(1:3) + &
1231 xkp_full(3, i)*b3(1:3))
1232 wcart(1:3) = kp_apply_operation(wcart(1:3), csym%rt(1:3, 1:3, iop))
1233 IF (ibsign == 2)
THEN
1234 wcart(1:3) = -wcart(1:3)
1237 rr(1) = dot_product(a1(1:3), wcart(1:3))/alat
1238 rr(2) = dot_product(a2(1:3), wcart(1:3))/alat
1239 rr(3) = dot_product(a3(1:3), wcart(1:3))/alat
1243 diff(1:3) = xkp_full(1:3, j) - rr(1:3)
1244 diff(1:3) = diff(1:3) - anint(diff(1:3))
1245 IF (all(abs(diff(1:3)) < eps))
THEN
1247 IF (.NOT. used(j))
THEN
1249 csym%kplink(1, j) = i
1251 wred(nred) = wred(nred) + 1.0_dp
1253 cpassert(csym%kplink(1, j) == i)
1258 IF (.NOT. found)
THEN
1259 CALL cp_abort(__location__, &
1260 "KPOINTS%SYMMETRY with SCHEME GENERAL requires the explicit k-point set "// &
1261 "to be closed under the K290 symmetry operations.")
1267 CALL store_general_reduction(csym, xkp_full, rep, wred, nred)
1269 DEALLOCATE (rep, used, wred)
1271 END SUBROUTINE reduce_general_k290
1278 SUBROUTINE reduce_general_spglib(csym, xkp_full)
1280 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp_full
1282 INTEGER :: i, iop, isign, j, kr, nfull, nred, nrot
1283 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: rep
1284 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: srot
1285 INTEGER,
DIMENSION(3, 3) :: krot
1287 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: used
1288 REAL(kind=
dp) :: eps
1289 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: wred
1290 REAL(kind=
dp),
DIMENSION(3) :: diff, rr
1292 nfull =
SIZE(xkp_full, 2)
1293 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1294 ALLOCATE (srot(3, 3, csym%n_operations))
1295 CALL setup_spglib_operations(csym, srot, nrot)
1297 ALLOCATE (rep(nfull), used(nfull), wred(nfull))
1308 csym%kplink(1, i) = i
1313 kr = csym%ibrot(iop)
1314 krot = reciprocal_rotation(srot(:, :, kr))
1316 rr(1:3) = matmul(real(krot(1:3, 1:3), kind=
dp), xkp_full(1:3, i))
1317 IF (isign == 2)
THEN
1319 kr = -csym%ibrot(iop)
1321 kr = csym%ibrot(iop)
1326 diff(1:3) = xkp_full(1:3, j) - rr(1:3)
1327 diff(1:3) = diff(1:3) - anint(diff(1:3))
1328 IF (all(abs(diff(1:3)) < eps))
THEN
1330 IF (.NOT. used(j))
THEN
1332 csym%kplink(1, j) = i
1334 wred(nred) = wred(nred) + 1.0_dp
1336 cpassert(csym%kplink(1, j) == i)
1341 IF (.NOT. found)
THEN
1342 CALL cp_abort(__location__, &
1343 "KPOINTS%SYMMETRY with SCHEME GENERAL requires the explicit k-point set "// &
1344 "to be closed under the requested symmetry operations.")
1350 CALL store_general_reduction(csym, xkp_full, rep, wred, nred)
1352 DEALLOCATE (rep, srot, used, wred)
1354 END SUBROUTINE reduce_general_spglib
1361 SUBROUTINE reduce_general_spglib_k290(csym, xkp_full)
1363 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp_full
1365 INTEGER :: i, iop, isign, j, k290_op, nfull, nred, &
1367 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: rep
1368 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: srot
1369 INTEGER,
DIMENSION(3, 3) :: krot
1370 LOGICAL :: found, valid
1371 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: used
1372 REAL(kind=
dp) :: alat, eps
1373 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: wred
1374 REAL(kind=
dp),
DIMENSION(3) :: a1, a2, a3, b1, b2, b3, diff, rr
1376 nfull =
SIZE(xkp_full, 2)
1377 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1378 CALL setup_k290_lattice(csym, a1, a2, a3, b1, b2, b3, alat)
1379 ALLOCATE (srot(3, 3, csym%n_operations))
1380 CALL setup_spglib_reduction_rotations(csym, srot, nrot)
1382 ALLOCATE (rep(nfull), used(nfull), wred(nfull))
1394 csym%kplink(1, i) = i
1399 krot = reciprocal_rotation(srot(:, :, iop))
1401 rr(1:3) = matmul(real(krot(1:3, 1:3), kind=
dp), xkp_full(1:3, i))
1402 IF (isign == 2) rr(1:3) = -rr(1:3)
1406 diff(1:3) = xkp_full(1:3, j) - rr(1:3)
1407 diff(1:3) = diff(1:3) - anint(diff(1:3))
1408 IF (all(abs(diff(1:3)) < eps))
THEN
1410 CALL find_k290_kpoint_operation(csym, xkp_full(1:3, i), xkp_full(1:3, j), &
1411 a1, a2, a3, b1, b2, b3, alat, &
1413 IF (.NOT. valid)
THEN
1414 nskipped = nskipped + 1
1417 IF (.NOT. used(j))
THEN
1419 csym%kplink(1, j) = i
1420 csym%kpop(j) = k290_op
1421 wred(nred) = wred(nred) + 1.0_dp
1423 cpassert(csym%kplink(1, j) == i)
1428 IF (.NOT. found)
THEN
1429 CALL cp_abort(__location__, &
1430 "KPOINTS%SYMMETRY with SCHEME GENERAL requires the explicit k-point set "// &
1431 "to be closed under the SPGLIB symmetry operations.")
1437 IF (nskipped > 0)
THEN
1438 CALL cp_warn(__location__, &
1439 "Some SPGLIB k-point mappings are not represented by the K290 backend; "// &
1440 "the GENERAL k-point set was reduced only by the compatible mappings.")
1443 CALL store_general_reduction(csym, xkp_full, rep, wred, nred)
1445 DEALLOCATE (rep, srot, used, wred)
1447 END SUBROUTINE reduce_general_spglib_k290
1457 SUBROUTINE store_general_reduction(csym, xkp_full, rep, wred, nred)
1459 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp_full
1460 INTEGER,
DIMENSION(:),
INTENT(IN) :: rep
1461 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wred
1462 INTEGER,
INTENT(IN) :: nred
1464 INTEGER :: i, j, nfull
1466 nfull =
SIZE(xkp_full, 2)
1468 ALLOCATE (csym%xkpoint(3, nred), csym%wkpoint(nred))
1470 csym%xkpoint(1:3, i) = xkp_full(1:3, rep(i))
1471 csym%wkpoint(i) = wred(i)
1475 IF (csym%kplink(1, i) == rep(j))
THEN
1476 csym%kplink(2, i) = j
1480 cpassert(csym%kplink(2, i) /= 0)
1483 END SUBROUTINE store_general_reduction
1501 SUBROUTINE reduce_spglib_kpoint_mesh_k290(csym, xkp, wkp, kpop, srot, nrot, &
1502 a1, a2, a3, b1, b2, b3, alat)
1504 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp
1505 REAL(kind=
dp),
DIMENSION(:) :: wkp
1506 INTEGER,
DIMENSION(:) :: kpop
1507 INTEGER,
DIMENSION(:, :, :),
INTENT(IN) :: srot
1508 INTEGER,
INTENT(IN) :: nrot
1509 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a1, a2, a3, b1, b2, b3
1510 REAL(kind=
dp),
INTENT(IN) :: alat
1512 INTEGER :: i, iop, isign, j, k290_op, nkpts, &
1514 INTEGER,
DIMENSION(3, 3) :: krot
1516 REAL(kind=
dp) :: eps
1517 REAL(kind=
dp),
DIMENSION(3) :: diff, rr
1520 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1525 csym%kplink(1, :) = 0
1528 IF (csym%kplink(1, i) /= 0) cycle
1530 csym%kplink(1, i) = i
1535 krot = reciprocal_rotation(srot(:, :, iop))
1537 rr(1:3) = matmul(real(krot(1:3, 1:3), kind=
dp), xkp(1:3, i))
1538 IF (isign == 2) rr(1:3) = -rr(1:3)
1541 diff(1:3) = xkp(1:3, j) - rr(1:3)
1542 diff(1:3) = diff(1:3) - anint(diff(1:3))
1543 IF (all(abs(diff(1:3)) < eps))
THEN
1545 IF (csym%kplink(1, j) /= 0)
THEN
1546 cpassert(csym%kplink(1, j) == i)
1550 CALL find_k290_kpoint_operation(csym, xkp(1:3, i), xkp(1:3, j), &
1551 a1, a2, a3, b1, b2, b3, alat, &
1553 IF (.NOT. valid)
THEN
1554 nskipped = nskipped + 1
1557 csym%kplink(1, j) = i
1558 wkp(i) = wkp(i) + 1.0_dp
1563 IF (j > nkpts) cycle
1569 cpassert(csym%kplink(1, i) /= 0)
1570 cpassert(kpop(i) /= 0)
1572 IF (nskipped > 0)
THEN
1573 CALL cp_warn(__location__, &
1574 "Some SPGLIB k-point mappings are not represented by the K290 backend; "// &
1575 "the mesh was reduced only by the compatible mappings.")
1578 END SUBROUTINE reduce_spglib_kpoint_mesh_k290
1595 SUBROUTINE find_k290_kpoint_operation(csym, xref, xtarget, a1, a2, a3, b1, b2, b3, alat, &
1598 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xref, xtarget, a1, a2, a3, b1, b2, b3
1599 REAL(kind=
dp),
INTENT(IN) :: alat
1600 INTEGER,
INTENT(OUT) :: k290_op
1601 LOGICAL,
INTENT(OUT) :: valid
1603 INTEGER :: ibsign, iop, kr
1604 REAL(kind=
dp) :: eps
1605 REAL(kind=
dp),
DIMENSION(3) :: diff, rr, wcart
1607 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1611 DO iop = 1, csym%nrtot
1612 IF (iop >
SIZE(csym%rt, 3)) cycle
1613 IF (csym%ibrot(iop) == 0) cycle
1615 wcart(1:3) = alat*(xref(1)*b1(1:3) + xref(2)*b2(1:3) + xref(3)*b3(1:3))
1616 wcart(1:3) = kp_apply_operation(wcart(1:3), csym%rt(1:3, 1:3, iop))
1617 IF (ibsign == 2)
THEN
1618 wcart(1:3) = -wcart(1:3)
1619 kr = -csym%ibrot(iop)
1621 kr = csym%ibrot(iop)
1623 rr(1) = dot_product(a1(1:3), wcart(1:3))/alat
1624 rr(2) = dot_product(a2(1:3), wcart(1:3))/alat
1625 rr(3) = dot_product(a3(1:3), wcart(1:3))/alat
1627 diff(1:3) = xtarget(1:3) - rr(1:3)
1628 diff(1:3) = diff(1:3) - anint(diff(1:3))
1629 IF (all(abs(diff(1:3)) < eps))
THEN
1637 END SUBROUTINE find_k290_kpoint_operation
1646 FUNCTION spglib_operation_score(csym, iop, srot)
RESULT(score)
1648 INTEGER,
INTENT(IN) :: iop
1649 INTEGER,
DIMENSION(3, 3),
INTENT(IN) :: srot
1653 INTEGER,
DIMENSION(3, 3) :: eye, r2
1654 REAL(kind=
dp) :: eps
1656 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1657 nat =
SIZE(csym%f0, 1)
1660 IF (csym%f0(i, iop) /= i) score = score + 100
1662 IF (any(abs(csym%vt(1:3, iop) - anint(csym%vt(1:3, iop))) > eps)) score = score + 10
1668 r2(1:3, 1:3) = matmul(srot(1:3, 1:3), srot(1:3, 1:3))
1669 IF (any(r2(1:3, 1:3) /= eye(1:3, 1:3))) score = score + 1
1671 END FUNCTION spglib_operation_score
1678 FUNCTION reciprocal_rotation(rot)
RESULT(krot)
1679 INTEGER,
DIMENSION(3, 3),
INTENT(IN) :: rot
1680 INTEGER,
DIMENSION(3, 3) :: krot
1682 REAL(kind=
dp),
DIMENSION(3, 3) :: rinv
1684 rinv =
inv_3x3(real(rot(1:3, 1:3), kind=
dp))
1685 krot(1:3, 1:3) = nint(transpose(rinv(1:3, 1:3)))
1687 END FUNCTION reciprocal_rotation
1706 SUBROUTINE reduce_kpoint_mesh(csym, xkp, wkp, kpop, nc, ib, r, a1, a2, a3, b1, b2, b3, alat)
1708 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp
1709 REAL(kind=
dp),
DIMENSION(:) :: wkp
1710 INTEGER,
DIMENSION(:) :: kpop
1711 INTEGER,
INTENT(IN) :: nc
1712 INTEGER,
DIMENSION(48),
INTENT(IN) :: ib
1713 REAL(kind=
dp),
DIMENSION(3, 3, 48),
INTENT(IN) :: r
1714 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a1, a2, a3, b1, b2, b3
1715 REAL(kind=
dp),
INTENT(IN) :: alat
1717 INTEGER :: i, ibsign, iop, j, kr, nkpts, &
1719 REAL(kind=
dp) :: eps
1720 REAL(kind=
dp),
DIMENSION(3) :: diff, rr, wcart
1723 eps = max(1.e-12_dp, 10.0_dp*csym%delta)
1724 nskipped_overlaps = 0
1728 csym%kplink(1, :) = 0
1731 IF (csym%kplink(1, i) /= 0) cycle
1733 csym%kplink(1, i) = i
1740 wcart(1:3) = alat*(xkp(1, i)*b1(1:3) + xkp(2, i)*b2(1:3) + xkp(3, i)*b3(1:3))
1741 wcart(1:3) = kp_apply_operation(wcart(1:3), r(1:3, 1:3, kr))
1742 IF (ibsign == 2)
THEN
1743 wcart(1:3) = -wcart(1:3)
1746 rr(1) = dot_product(a1(1:3), wcart(1:3))/alat
1747 rr(2) = dot_product(a2(1:3), wcart(1:3))/alat
1748 rr(3) = dot_product(a3(1:3), wcart(1:3))/alat
1751 diff(1:3) = xkp(1:3, j) - rr(1:3)
1752 diff(1:3) = diff(1:3) - anint(diff(1:3))
1753 IF (all(abs(diff(1:3)) < eps))
THEN
1754 IF (csym%kplink(1, j) == 0)
THEN
1755 csym%kplink(1, j) = i
1756 wkp(i) = wkp(i) + 1.0_dp
1758 ELSEIF (csym%kplink(1, j) /= i)
THEN
1762 nskipped_overlaps = nskipped_overlaps + 1
1768 IF (j > nkpts) cycle
1773 IF (nskipped_overlaps > 0)
THEN
1775 CALL inversion_symm(xkp, wkp, csym%kplink(1, :))
1777 IF (wkp(i) > 0.0_dp)
THEN
1784 csym%inversion_only = .true.
1785 CALL cp_warn(__location__, &
1786 "The K290 k-point operations produced overlapping, non-closed mesh orbits; "// &
1787 "falling back to inversion/time-reversal symmetry. Use SYMMETRY_BACKEND SPGLIB "// &
1788 "for full reduction by a closed crystallographic symmetry group.")
1791 cpassert(csym%kplink(1, i) /= 0)
1792 cpassert(kpop(i) /= 0)
1796 END SUBROUTINE reduce_kpoint_mesh
1805 SUBROUTINE full_grid_gen(nk, xkp, wkp, shift, gamma_centered)
1806 INTEGER,
INTENT(IN) :: nk(3)
1807 REAL(kind=
dp),
DIMENSION(:, :) :: xkp
1808 REAL(kind=
dp),
DIMENSION(:) :: wkp
1809 REAL(kind=
dp),
INTENT(IN) :: shift(3)
1810 LOGICAL,
INTENT(IN),
OPTIONAL :: gamma_centered
1812 INTEGER :: i, idim, ix, iy, iz
1813 INTEGER,
DIMENSION(3) :: ik
1814 LOGICAL :: gamma_mesh
1815 REAL(kind=
dp) :: kpt_latt(3)
1817 IF (
PRESENT(gamma_centered))
THEN
1818 gamma_mesh = gamma_centered
1820 gamma_mesh = .false.
1833 IF (gamma_mesh .AND. mod(nk(idim), 2) == 0)
THEN
1834 kpt_latt(idim) = real(2*ik(idim) - nk(idim), kind=
dp)/ &
1835 (2._dp*real(nk(idim), kind=
dp))
1837 kpt_latt(idim) = real(2*ik(idim) - nk(idim) - 1, kind=
dp)/ &
1838 (2._dp*real(nk(idim), kind=
dp))
1841 xkp(1:3, i) = kpt_latt(1:3)
1846 DO i = 1, nk(1)*nk(2)*nk(3)
1847 xkp(1:3, i) = xkp(1:3, i) + shift(1:3)
1850 END SUBROUTINE full_grid_gen
1858 SUBROUTINE inversion_symm(xkp, wkp, link)
1859 REAL(kind=
dp),
DIMENSION(:, :) :: xkp
1860 REAL(kind=
dp),
DIMENSION(:) :: wkp
1861 INTEGER,
DIMENSION(:) :: link
1863 INTEGER :: i, j, nkpts
1864 REAL(kind=
dp),
DIMENSION(3) :: diff
1866 nkpts =
SIZE(wkp, 1)
1870 IF (link(i) == 0) link(i) = i
1872 IF (wkp(j) == 0) cycle
1873 diff(1:3) = xkp(1:3, i) + xkp(1:3, j)
1874 diff(1:3) = diff(1:3) - anint(diff(1:3))
1875 IF (all(abs(diff(1:3)) < 1.e-12_dp))
THEN
1876 wkp(i) = wkp(i) + wkp(j)
1884 END SUBROUTINE inversion_symm
1892 FUNCTION kp_apply_operation(x, r)
RESULT(y)
1893 REAL(kind=
dp),
INTENT(IN) :: x(3), r(3, 3)
1894 REAL(kind=
dp) :: y(3)
1896 y(1) = r(1, 1)*x(1) + r(1, 2)*x(2) + r(1, 3)*x(3)
1897 y(2) = r(2, 1)*x(1) + r(2, 2)*x(2) + r(2, 3)*x(3)
1898 y(3) = r(3, 1)*x(1) + r(3, 2)*x(2) + r(3, 3)*x(3)
1900 END FUNCTION kp_apply_operation
1909 INTEGER :: i, iunit, j, plevel
1912 IF (iunit >= 0)
THEN
1913 plevel = csym%plevel
1914 WRITE (iunit,
"(/,T2,A)")
"Crystal Symmetry Information"
1915 IF (csym%symlib)
THEN
1916 WRITE (iunit,
'(A,T71,A10)')
" International Symbol: ", adjustr(trim(csym%international_symbol))
1917 WRITE (iunit,
'(A,T71,A10)')
" Point Group Symbol: ", adjustr(trim(csym%pointgroup_symbol))
1918 WRITE (iunit,
'(A,T71,A10)')
" Schoenflies Symbol: ", adjustr(trim(csym%schoenflies))
1920 WRITE (iunit,
'(A,T71,I10)')
" Number of Symmetry Operations: ", csym%n_operations
1921 IF (plevel > 0)
THEN
1922 DO i = 1, csym%n_operations
1923 WRITE (iunit,
'(A,i4,T51,3I10,/,T51,3I10,/,T51,3I10)') &
1924 " Rotation #: ", i, (csym%rotations(j, :, i), j=1, 3)
1925 WRITE (iunit,
'(T36,3F15.7)') csym%translations(:, i)
1929 IF (csym%spglib_requested)
THEN
1930 WRITE (iunit,
"(T2,A)")
"SPGLIB for Crystal Symmetry Information determination is not available"
1932 WRITE (iunit,
"(T2,A)")
"SPGLIB Crystal Symmetry Information was not requested"
1946 INTEGER :: i, iunit, nat, nmesh, plevel
1949 IF (iunit >= 0)
THEN
1950 plevel = csym%plevel
1951 WRITE (iunit,
"(/,T2,A)")
"K-point Symmetry Information"
1952 WRITE (iunit,
'(A,T67,I14)')
" Number of Special K-points: ", csym%nkpoint
1953 WRITE (iunit,
'(T19,A,T74,A)')
" Wavevector Basis ",
" Weight"
1954 DO i = 1, csym%nkpoint
1955 WRITE (iunit,
'(T2,i10,3F10.5,T71,I10)') i, csym%xkpoint(1:3, i), nint(csym%wkpoint(i))
1957 nmesh = csym%mesh(1)*csym%mesh(2)*csym%mesh(3)
1959 WRITE (iunit,
'(/,A,T63,3I6)')
" K-point Mesh: ", csym%mesh(1), csym%mesh(2), csym%mesh(3)
1961 nmesh =
SIZE(csym%kpmesh, 2)
1962 WRITE (iunit,
'(/,A,T70,I10)')
" Explicit K-point Set: ", nmesh
1964 WRITE (iunit,
'(T19,A,T54,A)')
" Wavevector Basis ",
" Special Points Rotation"
1966 WRITE (iunit,
'(T2,i10,3F10.5,T45,3I12)') i, csym%kpmesh(1:3, i), &
1967 csym%kplink(1:2, i), csym%kpop(i)
1969 IF (csym%nrtot > 0)
THEN
1970 WRITE (iunit,
'(/,A)')
" Atom Transformation Table"
1971 nat =
SIZE(csym%f0, 1)
1972 DO i = 1, csym%nrtot
1973 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 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
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.