40 dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, dbcsr_type_symmetric
119#include "./base/base_uses.f90"
125 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'kpoint_methods'
128 INTEGER :: nentry = 0, ngroup = 0
129 LOGICAL :: symmetric = .false.
130 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: col, col_offset, group_start, image, row, row_offset
131 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: cell
132 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: symmetry_sign
136 TYPE :: kp_symmetry_op_type
138 INTEGER,
DIMENSION(:),
POINTER :: atom_map => null(), atom_kind => null()
139 INTEGER,
DIMENSION(:, :),
POINTER :: cell_shift => null()
140 REAL(kind=
dp),
DIMENSION(3) :: xkp = 0.0_dp
141 LOGICAL :: time_reversal = .false., identity = .false., redistribute = .false.
142 END TYPE kp_symmetry_op_type
145 TYPE :: kp_density_group_type
146 TYPE(kp_symmetry_op_type) :: op
147 LOGICAL :: reverse_phase = .false.
148 INTEGER,
ALLOCATABLE :: inverse(:), ikp(:)
149 REAL(kind=
dp),
ALLOCATABLE :: xkp(:, :), weight(:)
150 END TYPE kp_density_group_type
165 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: values
166 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: block_col, block_nelem, block_offset, block_row
167 LOGICAL :: ready = .false.
183 INTEGER,
INTENT(IN) :: representative(:), nkp
184 INTEGER,
ALLOCATABLE,
INTENT(OUT) :: start(:), order(:)
187 INTEGER,
ALLOCATABLE :: count(:), next(:)
189 ALLOCATE (count(nkp), next(nkp), start(nkp + 1), order(
SIZE(representative)))
191 DO i = 1,
SIZE(representative)
192 ik = representative(i)
193 cpassert(ik >= 1 .AND. ik <= nkp)
194 count(ik) = count(ik) + 1
198 start(ik + 1) = start(ik) + count(ik)
201 DO i = 1,
SIZE(representative)
202 ik = representative(i)
204 next(ik) = next(ik) + 1
217 SUBROUTINE kp_rotation_cache_create(crys_sym, cell, srot, frot, krot)
221 REAL(KIND=
dp),
ALLOCATABLE,
INTENT(OUT) :: srot(:, :, :)
222 INTEGER,
ALLOCATABLE,
INTENT(OUT) :: frot(:, :, :), krot(:, :, :)
226 ALLOCATE (srot(3, 3, crys_sym%nrtot), frot(3, 3, crys_sym%nrtot), krot(3, 3, crys_sym%nrtot))
227 DO ic = 1, crys_sym%nrtot
228 srot(:, :, ic) = matmul(cell%h_inv, matmul(crys_sym%rt(:, :, ic), cell%hmat))
229 frot(:, :, ic) = nint(srot(:, :, ic))
230 krot(:, :, ic) = nint(transpose(
inv_3x3(real(frot(:, :, ic), kind=
dp))))
233 END SUBROUTINE kp_rotation_cache_create
250 SUBROUTINE kp_symmetry_import(kpoint, crys_sym, ik, natom, scoord, agauge, eps_kpoint, &
251 link_start, link_order, srot_cache, frot_cache, krot_cache)
255 INTEGER,
INTENT(IN) :: ik, natom
256 REAL(KIND=
dp),
INTENT(IN) :: scoord(:, :)
257 INTEGER,
INTENT(IN) :: agauge(:, :)
258 REAL(KIND=
dp),
INTENT(IN) :: eps_kpoint
259 INTEGER,
ALLOCATABLE,
INTENT(IN) :: link_start(:), link_order(:)
260 REAL(KIND=
dp),
ALLOCATABLE,
INTENT(IN) :: srot_cache(:, :, :)
261 INTEGER,
ALLOCATABLE,
INTENT(IN) :: frot_cache(:, :, :), krot_cache(:, :, :)
263 INTEGER :: ic, ilink, ir, ira, is, isign, j, nr, ns
264 INTEGER,
DIMENSION(3, 3) :: frot, krot
265 REAL(KIND=
dp),
DIMENSION(3) :: diff, kgvec, srot
266 REAL(KIND=
dp),
DIMENSION(3, 3) :: srotmat
269 NULLIFY (kpoint%kp_sym(ik)%kpoint_sym)
271 kpsym => kpoint%kp_sym(ik)%kpoint_sym
272 IF (crys_sym%nrtot <= 0 .OR. crys_sym%fullgrid .OR. &
273 crys_sym%istriz /= 1 .OR. crys_sym%inversion_only)
RETURN
275 cpassert(
ALLOCATED(link_start) .AND.
ALLOCATED(link_order))
276 cpassert(
ALLOCATED(srot_cache) .AND.
ALLOCATED(frot_cache) .AND.
ALLOCATED(krot_cache))
277 kpsym%nwght = nint(crys_sym%wkpoint(ik))
282 DO ilink = link_start(ik), link_start(ik + 1) - 1
283 is = link_order(ilink)
284 DO ic = 1, crys_sym%nrtot
285 krot(1:3, 1:3) = krot_cache(1:3, 1:3, ic)
287 ir = merge(crys_sym%ibrot(ic), -crys_sym%ibrot(ic), isign == 1)
288 IF (ir == crys_sym%kpop(is)) cycle
289 kgvec(1:3) = crys_sym%kpmesh(1:3, is) - &
290 matmul(real(merge(krot(1:3, 1:3), -krot(1:3, 1:3), isign == 1), kind=
dp), &
292 diff(1:3) = kgvec(1:3) - anint(kgvec(1:3))
293 IF (all(abs(diff(1:3)) < eps_kpoint)) ns = ns + 1
298 kpsym%apply_symmetry = .true.
300 ALLOCATE (
kpsym%f0(natom, ns),
kpsym%fcell(3, natom, ns),
kpsym%fcell_gauge(3, natom, ns))
301 ALLOCATE (
kpsym%phase_mode(ns),
kpsym%kgphase(natom, ns))
302 kpsym%phase_mode(:) = 0
305 DO ilink = link_start(ik), link_start(ik + 1) - 1
306 is = link_order(ilink)
308 ir = crys_sym%kpop(is)
310 DO ic = 1, crys_sym%nrtot
311 IF (crys_sym%ibrot(ic) /= ira) cycle
313 kpsym%rot(1:3, 1:3, nr) = crys_sym%rt(1:3, 1:3, ic)
314 srotmat(1:3, 1:3) = srot_cache(1:3, 1:3, ic)
315 frot(1:3, 1:3) = frot_cache(1:3, 1:3, ic)
316 kpsym%xkp(1:3, nr) = crys_sym%kpmesh(1:3, is)
317 krot(1:3, 1:3) = krot_cache(1:3, 1:3, ic)
318 IF (ir < 0) krot(1:3, 1:3) = -krot(1:3, 1:3)
319 kgvec(1:3) =
kpsym%xkp(1:3, nr) - &
320 matmul(real(krot(1:3, 1:3), kind=
dp), kpoint%xkp(1:3, ik))
321 kgvec(1:3) = anint(kgvec(1:3))
322 kpsym%f0(1:natom, nr) = crys_sym%f0(1:natom, ic)
324 srot(1:3) = matmul(srotmat, scoord(1:3, j)) + crys_sym%vt(1:3, ic)
325 kpsym%fcell(1:3, j, nr) = nint(srot(1:3) - scoord(1:3,
kpsym%f0(j, nr)))
326 kpsym%fcell_gauge(1:3, j, nr) =
kpsym%fcell(1:3, j, nr) + &
327 matmul(frot, agauge(1:3, j)) - &
328 agauge(1:3,
kpsym%f0(j, nr))
329 kpsym%kgphase(j, nr) = dot_product(kgvec(1:3), &
330 scoord(1:3, j) + real(agauge(1:3, j), kind=
dp))
334 cpassert(ic <= crys_sym%nrtot)
338 DO ilink = link_start(ik), link_start(ik + 1) - 1
339 is = link_order(ilink)
340 DO ic = 1, crys_sym%nrtot
341 srotmat(1:3, 1:3) = srot_cache(1:3, 1:3, ic)
342 frot(1:3, 1:3) = frot_cache(1:3, 1:3, ic)
343 krot(1:3, 1:3) = krot_cache(1:3, 1:3, ic)
345 ir = merge(crys_sym%ibrot(ic), -crys_sym%ibrot(ic), isign == 1)
346 IF (ir == crys_sym%kpop(is)) cycle
347 kgvec(1:3) = crys_sym%kpmesh(1:3, is) - &
348 matmul(real(merge(krot(1:3, 1:3), -krot(1:3, 1:3), isign == 1), kind=
dp), &
350 diff(1:3) = kgvec(1:3) - anint(kgvec(1:3))
351 IF (.NOT. all(abs(diff(1:3)) < eps_kpoint)) cycle
354 kpsym%rot(1:3, 1:3, nr) = crys_sym%rt(1:3, 1:3, ic)
355 kpsym%xkp(1:3, nr) = crys_sym%kpmesh(1:3, is)
356 kgvec(1:3) = anint(kgvec(1:3))
357 kpsym%f0(1:natom, nr) = crys_sym%f0(1:natom, ic)
359 srot(1:3) = matmul(srotmat, scoord(1:3, j)) + crys_sym%vt(1:3, ic)
360 kpsym%fcell(1:3, j, nr) = nint(srot(1:3) - scoord(1:3,
kpsym%f0(j, nr)))
361 kpsym%fcell_gauge(1:3, j, nr) =
kpsym%fcell(1:3, j, nr) + &
362 matmul(frot, agauge(1:3, j)) - &
363 agauge(1:3,
kpsym%f0(j, nr))
364 kpsym%kgphase(j, nr) = dot_product(kgvec(1:3), &
365 scoord(1:3, j) + real(agauge(1:3, j), kind=
dp))
373 END SUBROUTINE kp_symmetry_import
387 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_initialize'
389 INTEGER :: handle, i, ik, iounit, j, natom, nkind, &
391 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: atype, kp_link_order, kp_link_start
392 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: agauge
393 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: frot_cache, krot_cache
395 REAL(kind=
dp) :: eps_kpoint, wsum
396 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: coord, scoord
397 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: srot_cache
398 REAL(kind=
dp),
DIMENSION(3) :: r_pbc, scoord_pbc
399 REAL(kind=
dp),
DIMENSION(:),
POINTER :: wkp_full
400 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: xkp_full
403 CALL timeset(routinen, handle)
405 cpassert(
ASSOCIATED(kpoint))
407 SELECT CASE (kpoint%kp_scheme)
412 ALLOCATE (kpoint%xkp(3, 1), kpoint%wkp(1))
413 kpoint%xkp(1:3, 1) = 0.0_dp
414 kpoint%wkp(1) = 1.0_dp
415 ALLOCATE (kpoint%kp_sym(1))
416 NULLIFY (kpoint%kp_sym(1)%kpoint_sym)
418 CASE (
"MONKHORST-PACK",
"MACDONALD")
420 IF (.NOT. kpoint%symmetry)
THEN
423 ALLOCATE (coord(3, natom), scoord(3, natom), atype(natom))
426 coord(1, i) = sin(i*0.12345_dp)
427 coord(2, i) = cos(i*0.23456_dp)
428 coord(3, i) = sin(i*0.34567_dp)
432 natom =
SIZE(particle_set)
433 ALLOCATE (scoord(3, natom), atype(natom))
435 CALL get_atomic_kind(atomic_kind=particle_set(i)%atomic_kind, kind_number=atype(i))
439 IF (kpoint%verbose)
THEN
445 ALLOCATE (kpoint%atype(natom))
448 ALLOCATE (agauge(3, natom))
450 IF (kpoint%symmetry)
THEN
452 r_pbc(1:3) =
pbc_stable(particle_set(i)%r(1:3), cell)
454 agauge(1:3, i) = nint(scoord_pbc(1:3) - scoord(1:3, i))
458 CALL crys_sym_gen(crys_sym, scoord, atype, cell%hmat, delta=kpoint%eps_geo, iounit=iounit, &
459 use_spglib=kpoint%symmetry)
460 CALL kpoint_gen(crys_sym, kpoint%nkp_grid, symm=kpoint%symmetry, shift=kpoint%kp_shift, &
461 full_grid=kpoint%full_grid, gamma_centered=kpoint%gamma_centered, &
462 inversion_symmetry_only=kpoint%inversion_symmetry_only, &
463 use_spglib_reduction= &
466 IF (crys_sym%inversion_only) kpoint%inversion_symmetry_only = .true.
467 kpoint%nkp = crys_sym%nkpoint
468 ALLOCATE (kpoint%xkp(3, kpoint%nkp), kpoint%wkp(kpoint%nkp))
469 wsum = sum(crys_sym%wkpoint)
470 DO ik = 1, kpoint%nkp
471 kpoint%xkp(1:3, ik) = crys_sym%xkpoint(1:3, ik)
472 kpoint%wkp(ik) = crys_sym%wkpoint(ik)/wsum
474 IF (crys_sym%nrtot > 0 .AND. .NOT. crys_sym%fullgrid .AND. &
475 crys_sym%istriz == 1 .AND. .NOT. crys_sym%inversion_only)
THEN
477 CALL kp_rotation_cache_create(crys_sym, cell, srot_cache, frot_cache, krot_cache)
480 eps_kpoint = max(1.e-12_dp, 10.0_dp*kpoint%eps_geo)
486 ALLOCATE (kpoint%kp_sym(kpoint%nkp))
487 DO ik = 1, kpoint%nkp
488 CALL kp_symmetry_import(kpoint, crys_sym, ik, natom, scoord, agauge, eps_kpoint, &
489 kp_link_start, kp_link_order, srot_cache, frot_cache, krot_cache)
491 IF (kpoint%symmetry)
THEN
492 nkind = maxval(atype)
494 ALLOCATE (kpoint%kind_rotmat(ns, nkind))
497 NULLIFY (kpoint%kind_rotmat(i, j)%rmat)
500 ALLOCATE (kpoint%ibrot(ns))
501 kpoint%ibrot(1:ns) = crys_sym%ibrot(1:ns)
505 DEALLOCATE (scoord, atype)
509 NULLIFY (xkp_full, wkp_full)
510 IF (
ASSOCIATED(kpoint%xkp_input))
THEN
511 xkp_full => kpoint%xkp_input
512 wkp_full => kpoint%wkp_input
514 xkp_full => kpoint%xkp
515 wkp_full => kpoint%wkp
517 cpassert(
ASSOCIATED(xkp_full))
518 cpassert(
ASSOCIATED(wkp_full))
519 IF (.NOT.
ASSOCIATED(kpoint%xkp_input))
THEN
520 ALLOCATE (kpoint%xkp_input(3,
SIZE(wkp_full)), kpoint%wkp_input(
SIZE(wkp_full)))
521 kpoint%xkp_input(1:3, 1:
SIZE(wkp_full)) = xkp_full(1:3, 1:
SIZE(wkp_full))
522 kpoint%wkp_input(1:
SIZE(wkp_full)) = wkp_full(1:
SIZE(wkp_full))
523 xkp_full => kpoint%xkp_input
524 wkp_full => kpoint%wkp_input
526 IF (.NOT. kpoint%symmetry)
THEN
527 IF (.NOT.
ASSOCIATED(kpoint%xkp))
THEN
528 kpoint%nkp =
SIZE(wkp_full)
529 ALLOCATE (kpoint%xkp(3, kpoint%nkp), kpoint%wkp(kpoint%nkp))
530 kpoint%xkp(1:3, 1:kpoint%nkp) = xkp_full(1:3, 1:kpoint%nkp)
531 kpoint%wkp(1:kpoint%nkp) = wkp_full(1:kpoint%nkp)
534 ALLOCATE (kpoint%kp_sym(kpoint%nkp))
536 NULLIFY (kpoint%kp_sym(i)%kpoint_sym)
540 IF (kpoint%verbose)
THEN
545 natom =
SIZE(particle_set)
546 ALLOCATE (scoord(3, natom), atype(natom))
548 CALL get_atomic_kind(atomic_kind=particle_set(i)%atomic_kind, kind_number=atype(i))
551 ALLOCATE (kpoint%atype(natom))
553 ALLOCATE (agauge(3, natom))
555 r_pbc(1:3) =
pbc_stable(particle_set(i)%r(1:3), cell)
557 agauge(1:3, i) = nint(scoord_pbc(1:3) - scoord(1:3, i))
560 CALL crys_sym_gen(crys_sym, scoord, atype, cell%hmat, delta=kpoint%eps_geo, iounit=iounit, &
564 full_grid=kpoint%full_grid, &
565 inversion_symmetry_only=kpoint%inversion_symmetry_only, &
566 use_spglib_reduction= &
569 IF (crys_sym%inversion_only) kpoint%inversion_symmetry_only = .true.
570 IF (
ASSOCIATED(kpoint%xkp))
THEN
571 DEALLOCATE (kpoint%xkp)
574 IF (
ASSOCIATED(kpoint%wkp))
THEN
575 DEALLOCATE (kpoint%wkp)
578 kpoint%nkp = crys_sym%nkpoint
579 ALLOCATE (kpoint%xkp(3, kpoint%nkp), kpoint%wkp(kpoint%nkp))
580 wsum = sum(crys_sym%wkpoint)
581 DO ik = 1, kpoint%nkp
582 kpoint%xkp(1:3, ik) = crys_sym%xkpoint(1:3, ik)
583 kpoint%wkp(ik) = crys_sym%wkpoint(ik)/wsum
585 IF (crys_sym%nrtot > 0 .AND. .NOT. crys_sym%fullgrid .AND. &
586 crys_sym%istriz == 1 .AND. .NOT. crys_sym%inversion_only)
THEN
588 CALL kp_rotation_cache_create(crys_sym, cell, srot_cache, frot_cache, krot_cache)
591 eps_kpoint = max(1.e-12_dp, 10.0_dp*kpoint%eps_geo)
595 ALLOCATE (kpoint%kp_sym(kpoint%nkp))
596 DO ik = 1, kpoint%nkp
597 CALL kp_symmetry_import(kpoint, crys_sym, ik, natom, scoord, agauge, eps_kpoint, &
598 kp_link_start, kp_link_order, srot_cache, frot_cache, krot_cache)
600 nkind = maxval(atype)
602 ALLOCATE (kpoint%kind_rotmat(ns, nkind))
605 NULLIFY (kpoint%kind_rotmat(i, j)%rmat)
608 ALLOCATE (kpoint%ibrot(ns))
609 kpoint%ibrot(1:ns) = crys_sym%ibrot(1:ns)
612 DEALLOCATE (scoord, atype)
616 cpabort(
"Option invalid or unavailable for kpoint%kp_scheme")
620 SELECT CASE (kpoint%kp_scheme)
624 cpassert(kpoint%nkp == 1)
625 cpassert(sum(abs(kpoint%xkp)) <= 1.e-12_dp)
626 cpassert(kpoint%wkp(1) == 1.0_dp)
627 cpassert(.NOT. kpoint%symmetry)
629 cpassert(kpoint%nkp >= 1)
630 CASE (
"MONKHORST-PACK",
"MACDONALD")
631 cpassert(kpoint%nkp >= 1)
633 IF (kpoint%use_real_wfn)
THEN
635 ikloop:
DO ik = 1, kpoint%nkp
637 spez = (kpoint%xkp(i, ik) == 0.0_dp .OR. kpoint%xkp(i, ik) == 0.5_dp)
638 IF (.NOT. spez)
EXIT ikloop
643 CALL cp_warn(__location__, &
644 "A calculation using real wavefunctions is requested. "// &
645 "We could not determine if the symmetry of the system allows real wavefunctions. ")
649 CALL timestop(handle)
665 LOGICAL,
INTENT(IN),
OPTIONAL :: with_aux_fit
667 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_env_initialize'
669 INTEGER :: handle, igr, ngr, niogrp, nkp, &
670 nkp_grp, nkp_loc, npe, unit_nr
671 INTEGER,
DIMENSION(2) :: dims, pos
676 CALL timeset(routinen, handle)
678 IF (
PRESENT(with_aux_fit))
THEN
679 aux_fit = with_aux_fit
684 kpoint%para_env => para_env
685 CALL kpoint%para_env%retain()
686 kpoint%blacs_env_all => blacs_env
687 CALL kpoint%blacs_env_all%retain()
689 cpassert(.NOT.
ASSOCIATED(kpoint%kp_env))
691 cpassert(.NOT.
ASSOCIATED(kpoint%kp_aux_env))
695 npe = para_env%num_pe
698 ALLOCATE (kpoint%kp_dist(2, 1))
699 kpoint%kp_dist(1, 1) = 1
700 kpoint%kp_dist(2, 1) = nkp
701 kpoint%kp_range(1) = 1
702 kpoint%kp_range(2) = nkp
705 kpoint%para_env_kp => para_env
706 CALL kpoint%para_env_kp%retain()
707 kpoint%para_env_inter_kp => para_env
708 CALL kpoint%para_env_inter_kp%retain()
709 kpoint%iogrp = .true.
710 kpoint%nkp_groups = 1
712 IF (kpoint%parallel_group_size == -1)
THEN
716 IF (mod(npe, igr) /= 0) cycle
718 IF (nkp_grp > nkp) cycle
721 ELSE IF (kpoint%parallel_group_size == 0)
THEN
724 ELSE IF (kpoint%parallel_group_size > 0)
THEN
725 ngr = min(kpoint%parallel_group_size, npe)
727 cpabort(
"kpoint%parallel_group_size cannot be smaller than -1")
733 IF ((dims(1)*dims(2) /= npe))
THEN
734 cpabort(
"Number of processors is not divisible by the kpoint group size.")
736 IF (nkp_grp > nkp)
THEN
737 cpabort(
"Too many kpoint groups. Increase PARALLEL_GROUP_SIZE.")
741 CALL comm_cart%create(comm_old=para_env, ndims=2, dims=dims)
742 pos = comm_cart%mepos_cart
743 ALLOCATE (para_env_kp)
744 CALL para_env_kp%from_split(comm_cart, pos(2))
745 ALLOCATE (para_env_inter_kp)
746 CALL para_env_inter_kp%from_split(comm_cart, pos(1))
747 CALL comm_cart%free()
750 IF (para_env%is_source()) niogrp = 1
751 CALL para_env_kp%sum(niogrp)
752 kpoint%iogrp = (niogrp == 1)
755 kpoint%para_env_kp => para_env_kp
756 kpoint%para_env_inter_kp => para_env_inter_kp
759 ALLOCATE (kpoint%kp_dist(2, nkp_grp))
761 kpoint%kp_dist(1:2, igr) =
get_limit(nkp, nkp_grp, igr - 1)
764 kpoint%kp_range(1:2) = kpoint%kp_dist(1:2, para_env_inter_kp%mepos + 1)
765 nkp_loc = kpoint%kp_range(2) - kpoint%kp_range(1) + 1
769 IF (unit_nr > 0 .AND. kpoint%verbose)
THEN
771 WRITE (unit_nr, fmt=
"(T2,A,T71,I10)")
"KPOINTS| Total number of kpoints", nkp
772 WRITE (unit_nr, fmt=
"(T2,A,T71,I10)")
"KPOINTS| Number of kpoint groups ", nkp_grp
773 WRITE (unit_nr, fmt=
"(T2,A,T71,I10)")
"KPOINTS| Size of each kpoint group", ngr
774 IF (mod(nkp, nkp_grp) == 0)
THEN
775 WRITE (unit_nr, fmt=
"(T2,A,T71,I10)")
"KPOINTS| Number of kpoints per group", nkp_loc
777 WRITE (unit_nr, fmt=
"(T2,A,T71,I10)")
"KPOINTS| Minimum number of kpoints per group", nkp/nkp_grp
778 WRITE (unit_nr, fmt=
"(T2,A,T71,I10)")
"KPOINTS| Maximum number of kpoints per group", nkp/nkp_grp + 1
781 kpoint%nkp_groups = nkp_grp
785 nkp_loc = kpoint%kp_range(2) - kpoint%kp_range(1) + 1
786 CALL create_local_environments(kpoint%kp_env)
787 IF (aux_fit)
CALL create_local_environments(kpoint%kp_aux_env)
789 CALL timestop(handle)
797 SUBROUTINE create_local_environments(env)
803 ALLOCATE (env(nkp_loc))
805 ikk = kpoint%kp_range(1) + ik - 1
807 kp => env(ik)%kpoint_env
809 kp%wkp = kpoint%wkp(ikk)
810 kp%xkp(1:3) = kpoint%xkp(1:3, ikk)
811 kp%is_local = (kpoint%para_env_kp%num_pe == 1)
813 END SUBROUTINE create_local_environments
827 TYPE(
mo_set_type),
DIMENSION(:),
INTENT(INOUT) :: mos
828 INTEGER,
INTENT(IN),
OPTIONAL :: added_mos
829 LOGICAL,
OPTIONAL :: for_aux_fit
831 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_initialize_mos'
833 INTEGER :: handle, ic, ik, is, nadd, nao, nc, &
834 nelectron, nkp_loc, nmo, nmorig(2), &
837 REAL(kind=
dp) :: flexible_electron_count, maxocc, n_el_f
845 CALL timeset(routinen, handle)
847 IF (
PRESENT(for_aux_fit))
THEN
848 aux_fit = for_aux_fit
853 cpassert(
ASSOCIATED(kpoint))
856 cpassert(
ASSOCIATED(kpoint%kp_aux_env))
859 IF (
PRESENT(added_mos))
THEN
865 IF (kpoint%use_real_wfn)
THEN
871 nkp_loc = kpoint%kp_range(2) - kpoint%kp_range(1) + 1
872 IF (nkp_loc > 0)
THEN
874 cpassert(
SIZE(kpoint%kp_aux_env) == nkp_loc)
876 cpassert(
SIZE(kpoint%kp_env) == nkp_loc)
881 kp => kpoint%kp_aux_env(ik)%kpoint_env
883 kp => kpoint%kp_env(ik)%kpoint_env
885 ALLOCATE (kp%mos(nspin))
887 CALL get_mo_set(mos(is), nao=nao, nmo=nmo, nelectron=nelectron, &
888 n_el_f=n_el_f, maxocc=maxocc, flexible_electron_count=flexible_electron_count)
889 nmo = min(nao, nmo + nadd)
890 CALL allocate_mo_set(kp%mos(is), nao, nmo, nelectron, n_el_f, maxocc, &
891 flexible_electron_count)
895 kp%mos_prefilled = .false.
903 IF (
ASSOCIATED(kpoint%blacs_env))
THEN
904 blacs_env => kpoint%blacs_env
907 kpoint%blacs_env => blacs_env
913 nmo = min(nao, nmorig(is) + nadd)
921 blacs_env=blacs_env, para_env=kpoint%para_env_kp)
924 kpoint%mpools_aux_fit => mpools
926 kpoint%mpools => mpools
935 CALL mpools_get(mpools, ao_ao_fm_pools=ao_ao_fm_pools)
941 kp => kpoint%kp_aux_env(ik)%kpoint_env
943 kp => kpoint%kp_env(ik)%kpoint_env
947 ALLOCATE (kp%pmat(nc, nspin))
955 ALLOCATE (kp%wmat(nc, nspin))
967 CALL timestop(handle)
978 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_initialize_mo_set'
980 INTEGER :: handle, ik, ispin
984 CALL timeset(routinen, handle)
986 DO ik = 1,
SIZE(kpoint%kp_env)
987 CALL mpools_get(kpoint%mpools, ao_mo_fm_pools=ao_mo_fm_pools)
988 moskp => kpoint%kp_env(ik)%kpoint_env%mos
989 cpassert(
ASSOCIATED(moskp))
990 DO ispin = 1,
SIZE(moskp)
991 IF (
ASSOCIATED(moskp(ispin)%mo_coeff) .OR. &
992 ASSOCIATED(moskp(ispin)%cmo_coeff)) cycle
993 CALL init_mo_set(moskp(ispin), fm_pool=ao_mo_fm_pools(ispin)%pool, &
994 name=
"kpoints", complex_coeff=.NOT. kpoint%use_real_wfn)
998 CALL timestop(handle)
1016 INTEGER,
INTENT(OUT) :: nimages
1018 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_init_cell_index'
1020 INTEGER :: handle, i1, i2, i3, ic, icount, it, &
1022 INTEGER,
DIMENSION(3) :: cell, itm
1023 INTEGER,
DIMENSION(:, :),
POINTER :: index_to_cell,
list
1024 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index, cti
1027 DIMENSION(:),
POINTER :: nl_iterator
1029 NULLIFY (cell_to_index, index_to_cell)
1031 CALL timeset(routinen, handle)
1033 cpassert(
ASSOCIATED(kpoint))
1035 ALLOCATE (
list(3, 125))
1045 IF (cell(1) ==
list(1, ic) .AND. cell(2) ==
list(2, ic) .AND. &
1046 cell(3) ==
list(3, ic))
THEN
1053 IF (icount >
SIZE(
list, 2))
THEN
1056 list(1:3, icount) = cell(1:3)
1062 itm(1) = maxval(abs(
list(1, 1:icount)))
1063 itm(2) = maxval(abs(
list(2, 1:icount)))
1064 itm(3) = maxval(abs(
list(3, 1:icount)))
1065 CALL para_env%max(itm)
1066 it = maxval(itm(1:3))
1067 IF (
ASSOCIATED(kpoint%cell_to_index))
THEN
1068 DEALLOCATE (kpoint%cell_to_index)
1070 ALLOCATE (kpoint%cell_to_index(-itm(1):itm(1), -itm(2):itm(2), -itm(3):itm(3)))
1071 cell_to_index => kpoint%cell_to_index
1072 cti => cell_to_index
1078 cti(i1, i2, i3) = ic
1080 CALL para_env%sum(cti)
1082 DO i1 = -itm(1), itm(1)
1083 DO i2 = -itm(2), itm(2)
1084 DO i3 = -itm(3), itm(3)
1085 IF (cti(i1, i2, i3) == 0)
THEN
1086 cti(i1, i2, i3) = 1000000
1089 cti(i1, i2, i3) = (abs(i1) + abs(i2) + abs(i3))*1000 + abs(i3)*100 + abs(i2)*10 + abs(i1)
1090 cti(i1, i2, i3) = cti(i1, i2, i3) + (i1 + i2 + i3)
1096 IF (
ASSOCIATED(kpoint%index_to_cell))
THEN
1097 DEALLOCATE (kpoint%index_to_cell)
1099 ALLOCATE (kpoint%index_to_cell(3, ncount))
1100 index_to_cell => kpoint%index_to_cell
1103 i1 = cell(1) - 1 - itm(1)
1104 i2 = cell(2) - 1 - itm(2)
1105 i3 = cell(3) - 1 - itm(3)
1106 cti(i1, i2, i3) = 1000000
1107 index_to_cell(1, ic) = i1
1108 index_to_cell(2, ic) = i2
1109 index_to_cell(3, ic) = i3
1113 i1 = index_to_cell(1, ic)
1114 i2 = index_to_cell(2, ic)
1115 i3 = index_to_cell(3, ic)
1116 cti(i1, i2, i3) = ic
1120 kpoint%sab_nl => sab_nl
1123 nimages =
SIZE(index_to_cell, 2)
1127 CALL timestop(handle)
1144 xkp, cell_to_index, sab_nl, is_complex, rs_sign)
1149 INTEGER,
INTENT(IN) :: ispin
1150 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
1151 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
1154 LOGICAL,
INTENT(IN),
OPTIONAL :: is_complex
1155 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: rs_sign
1157 CHARACTER(LEN=*),
PARAMETER :: routinen =
'rskp_transform'
1159 INTEGER :: handle, iatom, ic, icol, irow, jatom, &
1161 INTEGER,
DIMENSION(3) :: cell
1162 LOGICAL :: do_symmetric, found, my_complex, &
1164 REAL(kind=
dp) :: arg, coskl, fsign, fsym, sinkl
1165 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: cblock, rblock, rsblock
1167 DIMENSION(:),
POINTER :: nl_iterator
1169 CALL timeset(routinen, handle)
1171 my_complex = .false.
1172 IF (
PRESENT(is_complex)) my_complex = is_complex
1175 IF (
PRESENT(rs_sign)) fsign = rs_sign
1177 wfn_real_only = .true.
1178 IF (
PRESENT(cmatrix)) wfn_real_only = .false.
1180 nimg =
SIZE(rsmat, 2)
1193 IF (do_symmetric .AND. (iatom > jatom))
THEN
1199 ic = cell_to_index(cell(1), cell(2), cell(3))
1200 IF (ic < 1 .OR. ic > nimg) cycle
1202 arg = real(cell(1),
dp)*xkp(1) + real(cell(2),
dp)*xkp(2) + real(cell(3),
dp)*xkp(3)
1203 IF (my_complex)
THEN
1204 coskl = fsign*fsym*cos(
twopi*arg)
1205 sinkl = fsign*sin(
twopi*arg)
1207 coskl = fsign*cos(
twopi*arg)
1208 sinkl = fsign*fsym*sin(
twopi*arg)
1212 block=rsblock, found=found)
1213 IF (.NOT. found) cycle
1215 IF (wfn_real_only)
THEN
1217 block=rblock, found=found)
1218 IF (.NOT. found) cycle
1219 rblock = rblock + coskl*rsblock
1222 block=rblock, found=found)
1223 IF (.NOT. found) cycle
1225 block=cblock, found=found)
1226 IF (.NOT. found) cycle
1227 rblock = rblock + coskl*rsblock
1228 cblock = cblock + sinkl*rsblock
1234 CALL timestop(handle)
1255 cell_to_index, sab_nl, used_fft, is_complex, rs_sign, &
1261 INTEGER,
INTENT(IN) :: ispin
1262 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: xkp
1263 INTEGER,
DIMENSION(3),
INTENT(IN) :: nkp_grid
1264 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
1267 LOGICAL,
INTENT(OUT) :: used_fft
1268 LOGICAL,
INTENT(IN),
OPTIONAL :: is_complex
1269 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: rs_sign
1270 INTEGER(KIND=int_8),
INTENT(IN),
OPTIONAL :: max_storage_bytes
1272 CHARACTER(LEN=*),
PARAMETER :: routinen =
'rskp_transform_grid_prepare'
1274 INTEGER :: handle, i1, i2, i3, iatom, iblock, ic, &
1275 icol, irow, jatom, nblkcols, nblkrows, &
1276 nblocks, ncell, nelem, nimg, nkp, &
1278 INTEGER(KIND=int_8) :: memory_limit, storage_bytes
1279 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: block_map, index_to_cell
1280 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: fft_cell_to_index
1281 INTEGER,
DIMENSION(3) :: cell, fft_cell
1282 LOGICAL :: do_symmetric, found, my_complex
1283 REAL(kind=
dp) :: fsign, fsym, value_sign
1284 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: values_rs
1285 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: rblock, rsblock
1288 DIMENSION(:),
POINTER :: nl_iterator
1290 CALL timeset(routinen, handle)
1295 nimg =
SIZE(rsmat, 2)
1296 IF (nkp < 2 .OR. product(nkp_grid) /= nkp)
THEN
1297 CALL timestop(handle)
1301 CALL timestop(handle)
1310 nblocks = nblocks + 1
1311 nvalues = nvalues +
SIZE(rblock)
1314 IF (nblocks == 0 .OR. nvalues == 0)
THEN
1315 CALL timestop(handle)
1319 CALL dbcsr_get_info(rmatrix, nblkrows_total=nblkrows, nblkcols_total=nblkcols)
1320 ALLOCATE (block_map(nblkrows, nblkcols), source=0)
1321 ALLOCATE (grid%block_row(nblocks), grid%block_col(nblocks), &
1322 grid%block_offset(nblocks), grid%block_nelem(nblocks))
1329 grid%block_row(iblock) = irow
1330 grid%block_col(iblock) = icol
1331 grid%block_offset(iblock) = nelem + 1
1332 grid%block_nelem(iblock) =
SIZE(rblock)
1333 block_map(irow, icol) = iblock
1334 nelem = nelem +
SIZE(rblock)
1338 ALLOCATE (fft_cell_to_index(lbound(cell_to_index, 1):ubound(cell_to_index, 1), &
1339 lbound(cell_to_index, 2):ubound(cell_to_index, 2), &
1340 lbound(cell_to_index, 3):ubound(cell_to_index, 3)), source=0)
1342 DO i3 = lbound(cell_to_index, 3), ubound(cell_to_index, 3)
1343 DO i2 = lbound(cell_to_index, 2), ubound(cell_to_index, 2)
1344 DO i1 = lbound(cell_to_index, 1), ubound(cell_to_index, 1)
1345 IF (cell_to_index(i1, i2, i3) < 1 .OR. cell_to_index(i1, i2, i3) > nimg) cycle
1346 IF (fft_cell_to_index(i1, i2, i3) == 0)
THEN
1348 fft_cell_to_index(i1, i2, i3) = ncell
1350 IF (fft_cell_to_index(-i1, -i2, -i3) == 0)
THEN
1352 fft_cell_to_index(-i1, -i2, -i3) = ncell
1357 IF (ncell == 0)
THEN
1359 CALL timestop(handle)
1363 memory_limit = 512_int_8*1024_int_8**2
1364 IF (
PRESENT(max_storage_bytes)) memory_limit = max_storage_bytes
1366 storage_bytes = int(nvalues,
int_8)*(8_int_8*int(ncell,
int_8) + &
1367 80_int_8*int(nkp,
int_8))
1368 IF (storage_bytes > memory_limit)
THEN
1370 CALL timestop(handle)
1374 ALLOCATE (index_to_cell(3, ncell), source=0)
1375 DO i3 = lbound(fft_cell_to_index, 3), ubound(fft_cell_to_index, 3)
1376 DO i2 = lbound(fft_cell_to_index, 2), ubound(fft_cell_to_index, 2)
1377 DO i1 = lbound(fft_cell_to_index, 1), ubound(fft_cell_to_index, 1)
1378 ic = fft_cell_to_index(i1, i2, i3)
1379 IF (ic > 0) index_to_cell(:, ic) = [i1, i2, i3]
1384 ALLOCATE (values_rs(nvalues, 1, ncell), source=0.0_dp)
1385 ALLOCATE (grid%values(nvalues, 1, nkp))
1386 my_complex = .false.
1387 IF (
PRESENT(is_complex)) my_complex = is_complex
1389 IF (
PRESENT(rs_sign)) fsign = rs_sign
1399 IF (do_symmetric .AND. iatom > jatom)
THEN
1404 IF (irow < 1 .OR. irow > nblkrows .OR. icol < 1 .OR. icol > nblkcols) cycle
1405 iblock = block_map(irow, icol)
1406 IF (iblock == 0) cycle
1408 ic = cell_to_index(cell(1), cell(2), cell(3))
1409 IF (ic < 1 .OR. ic > nimg) cycle
1411 block=rsblock, found=found)
1412 IF (.NOT. found) cycle
1416 IF (fsym < 0.0_dp) fft_cell = -cell
1417 IF (my_complex) value_sign = value_sign*fsym
1418 ic = fft_cell_to_index(fft_cell(1), fft_cell(2), fft_cell(3))
1419 nelem = grid%block_nelem(iblock)
1420 i1 = grid%block_offset(iblock)
1421 values_rs(i1:i1 + nelem - 1, 1, ic) = values_rs(i1:i1 + nelem - 1, 1, ic) + &
1422 value_sign*reshape(rsblock, [nelem])
1426 CALL cell_to_k_grid_fft(values_rs, index_to_cell, xkp, nkp_grid, grid%values, used_fft)
1433 CALL timestop(handle)
1447 INTEGER,
INTENT(IN) :: ikp
1449 TYPE(
dbcsr_type),
INTENT(INOUT),
OPTIONAL :: cmatrix
1451 INTEGER :: iblock, ioffset, nelem
1453 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: cblock, rblock
1455 cpassert(grid%ready)
1456 cpassert(ikp >= 1 .AND. ikp <=
SIZE(grid%values, 3))
1458 IF (
PRESENT(cmatrix))
CALL dbcsr_set(cmatrix, 0.0_dp)
1460 DO iblock = 1,
SIZE(grid%block_row)
1461 ioffset = grid%block_offset(iblock)
1462 nelem = grid%block_nelem(iblock)
1463 CALL dbcsr_get_block_p(rmatrix, grid%block_row(iblock), grid%block_col(iblock), &
1464 rblock, found=found)
1466 rblock = reshape(real(grid%values(ioffset:ioffset + nelem - 1, 1, ikp), kind=
dp), &
1468 IF (
PRESENT(cmatrix))
THEN
1469 CALL dbcsr_get_block_p(cmatrix, grid%block_row(iblock), grid%block_col(iblock), &
1470 cblock, found=found)
1472 cblock = reshape(aimag(grid%values(ioffset:ioffset + nelem - 1, 1, ikp)), shape(cblock))
1486 IF (
ALLOCATED(grid%values))
DEALLOCATE (grid%values)
1487 IF (
ALLOCATED(grid%block_row))
DEALLOCATE (grid%block_row)
1488 IF (
ALLOCATED(grid%block_col))
DEALLOCATE (grid%block_col)
1489 IF (
ALLOCATED(grid%block_offset))
DEALLOCATE (grid%block_offset)
1490 IF (
ALLOCATED(grid%block_nelem))
DEALLOCATE (grid%block_nelem)
1491 grid%ready = .false.
1505 kpoint, smear, probe, added_mos_auto, added_mos_auto_grow, separate_spin_occupations)
1511 LOGICAL,
DIMENSION(:),
INTENT(IN),
OPTIONAL :: added_mos_auto
1512 LOGICAL,
INTENT(OUT),
OPTIONAL :: added_mos_auto_grow
1513 LOGICAL,
INTENT(IN),
OPTIONAL :: separate_spin_occupations
1515 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_set_mo_occupation'
1517 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: csmatrix
1518 INTEGER :: handle, ik, ikpgr, ispin, kplocal, nao, &
1519 nb, ncol_global, ne_a, ne_b, &
1520 nelectron, nkp, nmo, nrow_global, nspin
1521 INTEGER,
DIMENSION(2) :: kp_range
1522 LOGICAL :: my_added_mos_auto_grow, &
1523 my_separate_spin_occupations
1524 REAL(kind=
dp) :: kts, kts_spin(2), mu, mus(2), nel
1525 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: smatrix
1526 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: weig, wocc
1527 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :, :) :: icoeff, rcoeff
1528 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues, occupation, wkp
1535 CALL timeset(routinen, handle)
1537 my_added_mos_auto_grow = .false.
1538 IF (
PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .false.
1542 kp => kpoint%kp_env(1)%kpoint_env
1543 nspin =
SIZE(kp%mos)
1544 my_separate_spin_occupations = smear%fixed_mag_mom > 0.0_dp
1545 IF (
PRESENT(separate_spin_occupations))
THEN
1546 my_separate_spin_occupations = my_separate_spin_occupations .OR. separate_spin_occupations
1549 CALL get_mo_set(mo_set, nmo=nmo, nao=nao, nelectron=nelectron)
1551 IF (nspin == 2)
THEN
1552 CALL get_mo_set(kp%mos(2), nmo=nb, nelectron=ne_b)
1555 ALLOCATE (weig(nmo, nkp, nspin), wocc(nmo, nkp, nspin))
1558 IF (
PRESENT(probe))
THEN
1559 ALLOCATE (rcoeff(nao, nmo, nkp, nspin), icoeff(nao, nmo, nkp, nspin))
1564 kplocal = kp_range(2) - kp_range(1) + 1
1565 DO ikpgr = 1, kplocal
1566 ik = kp_range(1) + ikpgr - 1
1567 kp => kpoint%kp_env(ikpgr)%kpoint_env
1569 mo_set => kp%mos(ispin)
1570 CALL get_mo_set(mo_set, eigenvalues=eigenvalues)
1571 weig(1:nmo, ik, ispin) = eigenvalues(1:nmo)
1572 IF (
PRESENT(probe))
THEN
1573 IF (kpoint%use_real_wfn)
THEN
1575 CALL cp_fm_get_info(mo_coeff, nrow_global=nrow_global, ncol_global=ncol_global)
1576 ALLOCATE (smatrix(nrow_global, ncol_global))
1578 rcoeff(1:nao, 1:nmo, ik, ispin) = smatrix(1:nao, 1:nmo)
1579 DEALLOCATE (smatrix)
1582 CALL cp_cfm_get_info(cmo_coeff, nrow_global=nrow_global, ncol_global=ncol_global)
1583 ALLOCATE (csmatrix(nrow_global, ncol_global))
1585 rcoeff(1:nao, 1:nmo, ik, ispin) = real(csmatrix(1:nao, 1:nmo), kind=
dp)
1586 icoeff(1:nao, 1:nmo, ik, ispin) = aimag(csmatrix(1:nao, 1:nmo))
1587 DEALLOCATE (csmatrix)
1593 CALL para_env_inter_kp%sum(weig)
1595 IF (
PRESENT(probe))
THEN
1596 CALL para_env_inter_kp%sum(rcoeff)
1597 CALL para_env_inter_kp%sum(icoeff)
1604 IF (
PRESENT(probe))
THEN
1605 smear%do_smear = .false.
1607 IF (nspin == 1)
THEN
1608 nel = real(nelectron, kind=
dp)
1609 CALL probe_occupancy_kp(wocc(:, :, :), mus(1), kts, weig(:, :, :), rcoeff(:, :, :, :), icoeff(:, :, :, :), 2.0d0, &
1612 nel = real(ne_a, kind=
dp) + real(ne_b, kind=
dp)
1613 CALL probe_occupancy_kp(wocc(:, :, :), mu, kts, weig(:, :, :), rcoeff(:, :, :, :), icoeff(:, :, :, :), 1.0d0, &
1619 DO ikpgr = 1, kplocal
1620 ik = kp_range(1) + ikpgr - 1
1621 kp => kpoint%kp_env(ikpgr)%kpoint_env
1623 mo_set => kp%mos(ispin)
1624 CALL get_mo_set(mo_set, eigenvalues=eigenvalues, occupation_numbers=occupation)
1625 eigenvalues(1:nmo) = weig(1:nmo, ik, ispin)
1626 occupation(1:nmo) = wocc(1:nmo, ik, ispin)
1628 mo_set%mu = mus(ispin)
1633 DEALLOCATE (weig, wocc, rcoeff, icoeff)
1637 IF (
PRESENT(probe) .EQV. .false.)
THEN
1638 IF (smear%do_smear)
THEN
1639 SELECT CASE (smear%method)
1642 IF (nspin == 1)
THEN
1643 nel = real(nelectron, kind=
dp)
1644 CALL smearkp(wocc(:, :, 1), mus(1), kts, weig(:, :, 1), nel, wkp, &
1647 ELSE IF (my_separate_spin_occupations)
THEN
1648 nel = real(ne_a, kind=
dp)
1649 CALL smearkp(wocc(:, :, 1), mus(1), kts, weig(:, :, 1), nel, wkp, &
1652 nel = real(ne_b, kind=
dp)
1653 CALL smearkp(wocc(:, :, 2), mus(2), kts, weig(:, :, 2), nel, wkp, &
1657 nel = real(ne_a, kind=
dp) + real(ne_b, kind=
dp)
1658 CALL smearkp2(wocc(:, :, :), mu, kts, weig(:, :, :), nel, wkp, &
1665 IF (nspin == 1)
THEN
1666 nel = real(nelectron, kind=
dp)
1667 CALL smearkp(wocc(:, :, 1), mus(1), kts, weig(:, :, 1), nel, wkp, &
1668 smear%smearing_width, 2.0_dp, smear%method)
1670 ELSE IF (my_separate_spin_occupations)
THEN
1671 nel = real(ne_a, kind=
dp)
1672 CALL smearkp(wocc(:, :, 1), mus(1), kts, weig(:, :, 1), nel, wkp, &
1673 smear%smearing_width, 1.0_dp, smear%method)
1675 nel = real(ne_b, kind=
dp)
1676 CALL smearkp(wocc(:, :, 2), mus(2), kts, weig(:, :, 2), nel, wkp, &
1677 smear%smearing_width, 1.0_dp, smear%method)
1680 nel = real(ne_a, kind=
dp) + real(ne_b, kind=
dp)
1681 CALL smearkp2(wocc(:, :, :), mu, kts, weig(:, :, :), nel, wkp, &
1682 smear%smearing_width, smear%method)
1688 cpabort(
"kpoints: Selected smearing not (yet) supported")
1692 IF (nspin == 1)
THEN
1693 nel = real(nelectron, kind=
dp)
1694 CALL smearkp(wocc(:, :, 1), mus(1), kts, weig(:, :, 1), nel, wkp, &
1698 nel = real(ne_a, kind=
dp)
1699 CALL smearkp(wocc(:, :, 1), mus(1), kts, weig(:, :, 1), nel, wkp, &
1702 nel = real(ne_b, kind=
dp)
1703 CALL smearkp(wocc(:, :, 2), mus(2), kts, weig(:, :, 2), nel, wkp, &
1708 IF (smear%do_smear .AND.
PRESENT(added_mos_auto))
THEN
1709 CALL kpoint_check_added_mos_auto_occupation( &
1710 wocc, wkp, smear, nspin, added_mos_auto, nao, my_added_mos_auto_grow)
1712 IF (my_added_mos_auto_grow)
THEN
1713 IF (
PRESENT(added_mos_auto_grow))
THEN
1714 added_mos_auto_grow = .true.
1715 DEALLOCATE (weig, wocc)
1716 CALL timestop(handle)
1719 CALL cp_abort(__location__, &
1720 "K-point ADDED_MOS AUTO needs a larger virtual-space buffer, "// &
1721 "but this call path cannot grow it.")
1724 DO ikpgr = 1, kplocal
1725 ik = kp_range(1) + ikpgr - 1
1726 kp => kpoint%kp_env(ikpgr)%kpoint_env
1728 mo_set => kp%mos(ispin)
1729 CALL get_mo_set(mo_set, eigenvalues=eigenvalues, occupation_numbers=occupation)
1730 eigenvalues(1:nmo) = weig(1:nmo, ik, ispin)
1731 occupation(1:nmo) = wocc(1:nmo, ik, ispin)
1732 mo_set%kTS = kts_spin(ispin)
1733 mo_set%mu = mus(ispin)
1734 IF (.NOT. smear%do_smear)
THEN
1736 kp%mos(ispin)%homo = count(occupation(1:nmo) > 0.0_dp)
1741 DEALLOCATE (weig, wocc)
1745 CALL timestop(handle)
1761 first_fractional, last_occupied, last_occupied_spin)
1763 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: wocc
1764 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wkp
1766 INTEGER,
INTENT(IN) :: nspin
1767 LOGICAL,
INTENT(OUT) :: has_weight, first_fractional, &
1769 LOGICAL,
DIMENSION(:),
INTENT(OUT),
OPTIONAL :: last_occupied_spin
1771 INTEGER :: ik, ispin, nmo
1772 LOGICAL :: band_occupied
1773 REAL(kind=
dp) :: eps_occ, maxocc, weight, weight_threshold
1775 has_weight = .false.
1776 first_fractional = .false.
1777 last_occupied = .false.
1778 IF (
PRESENT(last_occupied_spin)) last_occupied_spin(:) = .false.
1779 IF (.NOT. smear%do_smear)
RETURN
1783 eps_occ = max(smear%eps_fermi_dirac, 10.0_dp*epsilon(1.0_dp))
1784 weight_threshold = 10.0_dp*epsilon(1.0_dp)
1786 DO ispin = 1, min(nspin,
SIZE(wocc, 3))
1787 maxocc = merge(2.0_dp, 1.0_dp, nspin == 1)
1788 DO ik = 1, min(
SIZE(wkp),
SIZE(wocc, 2))
1789 weight = abs(wkp(ik))
1790 IF (weight <= weight_threshold) cycle
1792 first_fractional = first_fractional .OR. &
1793 abs(wocc(1, ik, ispin) - maxocc) > eps_occ
1794 band_occupied = abs(wocc(nmo, ik, ispin)) > eps_occ
1795 last_occupied = last_occupied .OR. band_occupied
1796 IF (band_occupied .AND.
PRESENT(last_occupied_spin))
THEN
1797 IF (ispin <=
SIZE(last_occupied_spin)) last_occupied_spin(ispin) = .true.
1814 SUBROUTINE kpoint_check_added_mos_auto_occupation(wocc, wkp, smear, nspin, &
1815 added_mos_auto, nao, added_mos_auto_grow)
1817 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: wocc
1818 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: wkp
1820 INTEGER,
INTENT(IN) :: nspin
1821 LOGICAL,
DIMENSION(:),
INTENT(IN) :: added_mos_auto
1822 INTEGER,
INTENT(IN) :: nao
1823 LOGICAL,
INTENT(OUT) :: added_mos_auto_grow
1825 INTEGER :: ispin, nmo
1826 LOGICAL :: first_fractional, has_weight, &
1828 LOGICAL,
DIMENSION(nspin) :: last_occupied_spin
1830 added_mos_auto_grow = .false.
1831 IF (.NOT. any(added_mos_auto) .OR. .NOT. smear%do_smear)
RETURN
1834 first_fractional, last_occupied, &
1835 last_occupied_spin=last_occupied_spin)
1836 IF (.NOT. has_weight)
RETURN
1839 DO ispin = 1, min(nspin,
SIZE(added_mos_auto))
1840 IF (.NOT. added_mos_auto(ispin) .OR. .NOT. last_occupied_spin(ispin)) cycle
1841 IF (nmo >= nao)
THEN
1842 CALL cp_abort(__location__, &
1843 "K-point ADDED_MOS AUTO exhausted the AO basis but the highest band "// &
1844 "is still occupied. Use a larger basis or reduce the smearing width.")
1846 added_mos_auto_grow = .true.
1850 END SUBROUTINE kpoint_check_added_mos_auto_occupation
1861 LOGICAL,
OPTIONAL :: energy_weighted, for_aux_fit
1863 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_density_matrices'
1865 INTEGER :: handle, ikpgr, ispin, kplocal, nao, nmo, &
1866 nspin, nworkers, thread
1867 LOGICAL :: aux_fit, local, wtype
1868 TYPE(
cp_cfm_type),
ALLOCATABLE :: cdensity(:), cwork(:)
1874 CALL timeset(routinen, handle)
1876 IF (
PRESENT(energy_weighted)) wtype = energy_weighted
1878 IF (
PRESENT(for_aux_fit)) aux_fit = for_aux_fit
1880 cpassert(
ASSOCIATED(kpoint%kp_aux_env))
1881 kp => kpoint%kp_aux_env(1)%kpoint_env
1883 kp => kpoint%kp_env(1)%kpoint_env
1886 IF (kpoint%use_real_wfn)
THEN
1887 CALL cp_fm_get_info(kp%mos(1)%mo_coeff, matrix_struct=matrix_struct)
1889 CALL cp_cfm_get_info(kp%mos(1)%cmo_coeff, matrix_struct=matrix_struct)
1891 kplocal = kpoint%kp_range(2) - kpoint%kp_range(1) + 1
1892 nspin =
SIZE(kp%mos)
1894 local = product(matrix_struct%context%num_pe) == 1
1897 ALLOCATE (gemm_ctx(nworkers))
1898 IF (kpoint%use_real_wfn)
THEN
1899 ALLOCATE (work(nworkers))
1901 ALLOCATE (cwork(nworkers), cdensity(nworkers))
1903 DO thread = 1, nworkers
1904 IF (kpoint%use_real_wfn)
THEN
1908 CALL cp_cfm_create(cdensity(thread), kp%pmat(1, 1)%matrix_struct)
1915 DO ikpgr = 1, kplocal
1919 IF (kpoint%use_real_wfn)
THEN
1920 CALL kpoint_density_matrix_job(kpoint, ikpgr, ispin, wtype, aux_fit, nao, nmo, &
1921 local, gemm_ctx(thread), work=work(thread))
1923 CALL kpoint_density_matrix_job(kpoint, ikpgr, ispin, wtype, aux_fit, nao, nmo, &
1924 local, gemm_ctx(thread), cwork=cwork(thread), cdensity=cdensity(thread))
1929 DO thread = 1, nworkers
1930 CALL gemm_ctx(thread)%destroy()
1931 IF (kpoint%use_real_wfn)
THEN
1938 IF (.NOT. wtype .AND. .NOT. aux_fit)
THEN
1939 kpoint%lowdin_density_ready = .true.
1940 kpoint%lowdin_population_ready = .false.
1942 CALL timestop(handle)
1959 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: occupation
1962 COMPLEX(KIND=dp),
PARAMETER :: zhalf = (0.5_dp, 0.0_dp), &
1963 zone = (1.0_dp, 0.0_dp), &
1964 zzero = (0.0_dp, 0.0_dp)
1966 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:) :: occupation_complex
1972 cpassert(
SIZE(occupation) >= nmo)
1975 CALL cp_cfm_create(hblock, coeff%matrix_struct, nrow=nmo, ncol=nmo)
1976 CALL cp_cfm_create(hblock_h, coeff%matrix_struct, nrow=nmo, ncol=nmo)
1977 CALL parallel_gemm(
"C",
"N", nmo, nmo, nao, zone, coeff, hc, zzero, hblock)
1979 ALLOCATE (occupation_complex(nmo))
1980 occupation_complex(:) = cmplx(occupation(1:nmo), 0.0_dp, kind=
dp)
1982 DEALLOCATE (occupation_complex)
1986 CALL parallel_gemm(
"N",
"N", nao, nmo, nmo, zone, coeff, hblock, zzero, weighted)
1987 CALL parallel_gemm(
"N",
"C", nao, nao, nmo, zone, weighted, coeff, zzero, wmat)
2010 SUBROUTINE kpoint_density_matrix_job(kpoint, ikpgr, ispin, wtype, aux_fit, nao, nmo, &
2011 local, gemm_ctx, work, cwork, cdensity)
2014 INTEGER,
INTENT(IN) :: ikpgr, ispin
2015 LOGICAL,
INTENT(IN) :: wtype, aux_fit
2016 INTEGER,
INTENT(IN) :: nao, nmo
2017 LOGICAL,
INTENT(IN) :: local
2019 TYPE(
cp_fm_type),
INTENT(INOUT),
OPTIONAL :: work
2020 TYPE(
cp_cfm_type),
INTENT(INOUT),
OPTIONAL :: cwork, cdensity
2022 COMPLEX(KIND=dp) :: weights(nmo)
2023 REAL(kind=
dp),
POINTER :: eigenvalues(:), occupation(:)
2025 TYPE(
cp_fm_type),
POINTER :: coeff, cpmat, rpmat
2029 kp => kpoint%kp_aux_env(ikpgr)%kpoint_env
2031 kp => kpoint%kp_env(ikpgr)%kpoint_env
2033 CALL get_mo_set(kp%mos(ispin), occupation_numbers=occupation, eigenvalues=eigenvalues)
2035 rpmat => kp%wmat(1, ispin)
2037 rpmat => kp%pmat(1, ispin)
2039 IF (kpoint%use_real_wfn)
THEN
2040 cpassert(
PRESENT(work))
2041 coeff => kp%mos(ispin)%mo_coeff
2046 cpassert(product(coeff%matrix_struct%context%num_pe) == 1)
2047 cpassert(product(work%matrix_struct%context%num_pe) == 1)
2048 cpassert(product(rpmat%matrix_struct%context%num_pe) == 1)
2049 CALL gemm_ctx%gemm(
"N",
"T", nao, nao, nmo, 1.0_dp, &
2050 coeff%local_data,
SIZE(coeff%local_data, 1), &
2051 work%local_data,
SIZE(work%local_data, 1), 0.0_dp, &
2052 rpmat%local_data,
SIZE(rpmat%local_data, 1))
2054 CALL parallel_gemm(
"N",
"T", nao, nao, nmo, 1.0_dp, coeff, work, 0.0_dp, rpmat)
2057 cpassert(
PRESENT(cwork) .AND.
PRESENT(cdensity))
2059 cpmat => kp%wmat(2, ispin)
2061 cpmat => kp%pmat(2, ispin)
2063 ccoeff => kp%mos(ispin)%cmo_coeff
2064 weights = cmplx(occupation(1:nmo), 0.0_dp, kind=
dp)
2065 IF (wtype) weights = weights*eigenvalues(1:nmo)
2069 cpassert(product(ccoeff%matrix_struct%context%num_pe) == 1)
2070 CALL gemm_ctx%gemm(
"N",
"C", nao, nao, nmo,
z_one, &
2071 ccoeff%local_data,
SIZE(ccoeff%local_data, 1), &
2072 cwork%local_data,
SIZE(cwork%local_data, 1),
z_zero, &
2073 cdensity%local_data,
SIZE(cdensity%local_data, 1))
2080 END SUBROUTINE kpoint_density_matrix_job
2093 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: pmat_diag
2095 CHARACTER(LEN=*),
PARAMETER :: routinen =
'lowdin_kp_trans'
2096 COMPLEX(KIND=dp),
PARAMETER :: cone = (1.0_dp, 0.0_dp), &
2097 czero = (0.0_dp, 0.0_dp)
2099 INTEGER :: handle, ikpgr, ispin, kplocal, nao, nspin
2100 INTEGER,
DIMENSION(2) :: kp_range
2101 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: dele
2106 TYPE(
cp_fm_type),
POINTER :: cpmat, pmat, rpmat, shalf
2110 CALL timeset(routinen, handle)
2112 nspin =
SIZE(pmat_diag, 2)
2117 matrix_struct=matrix_struct, nrow_global=nao)
2118 IF (kpoint%use_real_wfn)
THEN
2119 CALL cp_fm_create(f1work, matrix_struct, nrow=nao, ncol=nao)
2120 CALL cp_fm_create(f2work, matrix_struct, nrow=nao, ncol=nao)
2122 CALL cp_fm_create(f2work, matrix_struct, nrow=nao, ncol=nao)
2123 CALL cp_cfm_create(cf1work, matrix_struct, nrow=nao, ncol=nao)
2124 CALL cp_cfm_create(cf2work, matrix_struct, nrow=nao, ncol=nao)
2126 ALLOCATE (dele(nao))
2129 kplocal = kp_range(2) - kp_range(1) + 1
2130 DO ikpgr = 1, kplocal
2131 kp => kpoint%kp_env(ikpgr)%kpoint_env
2133 IF (kpoint%use_real_wfn)
THEN
2134 pmat => kp%pmat(1, ispin)
2136 CALL parallel_gemm(
"N",
"N", nao, nao, nao, 1.0_dp, pmat, shalf, 0.0_dp, f1work)
2137 CALL parallel_gemm(
"N",
"N", nao, nao, nao, 1.0_dp, shalf, f1work, 0.0_dp, f2work)
2139 rpmat => kp%pmat(1, ispin)
2140 cpmat => kp%pmat(2, ispin)
2143 CALL parallel_gemm(
"N",
"N", nao, nao, nao, cone, cf1work, cshalf, czero, cf2work)
2144 CALL parallel_gemm(
"N",
"N", nao, nao, nao, cone, cshalf, cf2work, czero, cf1work)
2148 pmat_diag(1:nao, ispin) = pmat_diag(1:nao, ispin) + kp%wkp*dele(1:nao)
2153 CALL para_env_inter_kp%sum(pmat_diag)
2155 IF (kpoint%use_real_wfn)
THEN
2165 CALL timestop(handle)
2180 INTEGER,
INTENT(IN) :: ispin
2182 TYPE(
cp_fm_type),
INTENT(INOUT),
OPTIONAL :: shalfc
2183 TYPE(
cp_cfm_type),
INTENT(INOUT),
OPTIONAL :: cshalfc
2189 cpassert(
PRESENT(shalfc))
2190 mo_set => kp%mos(ispin)
2193 CALL parallel_gemm(
"N",
"N", nao, nmo, nao, 1.0_dp, kp%shalf, &
2194 mo_set%mo_coeff, 0.0_dp, shalfc)
2196 cpassert(
PRESENT(cshalfc))
2197 mo_set => kp%mos(ispin)
2200 mo_set%cmo_coeff,
z_zero, cshalfc)
2219 pmat_ext, overlap_rs)
2223 LOGICAL,
INTENT(IN) :: wtype
2227 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN),
TARGET :: fmwork
2228 LOGICAL,
OPTIONAL :: for_aux_fit
2229 TYPE(
cp_fm_type),
DIMENSION(:, :, :),
INTENT(IN), &
2230 OPTIONAL,
TARGET :: pmat_ext
2232 POINTER :: overlap_rs
2234 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_density_transform'
2236 INTEGER :: handle, ic, ik, ikp, ispin, kplocal, nc, &
2238 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
2239 LOGICAL :: aux_fit, do_symmetric, local, &
2240 regular_grid_done, &
2241 regular_grid_eligible
2243 DIMENSION(:, :, :) :: source
2250 CALL timeset(routinen, handle)
2254 IF (
PRESENT(for_aux_fit))
THEN
2255 aux_fit = for_aux_fit
2261 cpassert(
ASSOCIATED(kpoint%kp_aux_env))
2267 matrix_type=merge(dbcsr_type_symmetric, dbcsr_type_no_symmetry, do_symmetric))
2271 components(1)%matrix => rpmat
2274 IF (
PRESENT(overlap_rs))
THEN
2275 CALL calibrate_symmetry_phases(kpoint, overlap_rs, tempmat, sab_nl, cell_to_index)
2279 kp => kpoint%kp_aux_env(1)%kpoint_env
2281 kp => kpoint%kp_env(1)%kpoint_env
2283 nspin =
SIZE(kp%mos)
2284 nc =
SIZE(kp%pmat, 1)
2285 nimg =
SIZE(denmat, 2)
2287 group_entries=.true.)
2291 kplocal = kpoint%kp_range(2) - kpoint%kp_range(1) + 1
2292 ALLOCATE (source(kplocal, nc, nspin))
2296 kp => kpoint%kp_aux_env(ikp)%kpoint_env
2298 kp => kpoint%kp_env(ikp)%kpoint_env
2301 IF (
PRESENT(pmat_ext))
THEN
2302 source(ikp, ic, ispin)%matrix => pmat_ext(ikp, ic, ispin)
2303 ELSE IF (wtype)
THEN
2304 source(ikp, ic, ispin)%matrix => kp%wmat(ic, ispin)
2306 source(ikp, ic, ispin)%matrix => kp%pmat(ic, ispin)
2312 para_env => kpoint%blacs_env_all%para_env
2313 local = para_env%num_pe == 1
2315 cpassert(kpoint%kp_range(1) == 1 .AND. kplocal == nkp)
2319 regular_grid_eligible = nimg < nkp
2320 IF (
ASSOCIATED(kpoint%index_to_cell))
THEN
2321 regular_grid_eligible = regular_grid_eligible .AND. nimg <=
SIZE(kpoint%index_to_cell, 2)
2323 regular_grid_eligible = .false.
2325 IF (regular_grid_eligible)
THEN
2327 IF (kpoint%kp_sym(ik)%kpoint_sym%apply_symmetry)
THEN
2328 regular_grid_eligible = .false.
2334 regular_grid_done = .false.
2335 IF (regular_grid_eligible)
THEN
2338 matrix_type=merge(dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, do_symmetric))
2341 components(2)%matrix => cpmat
2342 CALL kpoint_density_transform_regular_grid(kpoint, source, denmat, components, fmwork, &
2343 transform_plan, regular_grid_done)
2345 IF (.NOT. regular_grid_done)
THEN
2346 CALL kpoint_density_transform_batched(kpoint, source, denmat, rpmat, transform_plan)
2352 CALL timestop(handle)
2367 SUBROUTINE kpoint_density_transform_batched(kpoint, source, denmat, template, plan)
2369 TYPE(
cp_fm_p_type),
DIMENSION(:, :, :),
INTENT(IN) :: source
2374 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_density_transform_batched'
2375 INTEGER(KIND=int_8),
PARAMETER :: max_bytes = 64_int_8*1024*1024
2376 INTEGER,
PARAMETER :: images_per_tile = 8, max_batch = 256
2378 INTEGER :: a, b, batch, first, handle, i, ic, igroup, ikp, image, ispin, j, last, nblock, &
2379 ncol, njob, nlocal, nrow, nthreads, ntile, nvalue, orientation, owner, slot, thread, tile
2380 INTEGER(KIND=int_8) :: block_size
2381 INTEGER,
ALLOCATABLE :: available(:, :, :), counts(:), &
2382 jobs(:, :), local_jobs(:, :), &
2383 offsets(:), tile_start(:), &
2384 tiles(:, :, :, :, :)
2385 INTEGER,
DIMENSION(:),
POINTER :: col_offset, col_size, row_offset, &
2387 LOGICAL :: found, trans
2388 REAL(kind=
dp),
ALLOCATABLE :: packed(:, :), phases(:, :), &
2390 REAL(kind=
dp),
ALLOCATABLE,
TARGET :: sums(:, :), values(:)
2391 REAL(kind=
dp),
POINTER :: block(:, :)
2392 TYPE(kp_density_group_type),
ALLOCATABLE :: groups(:)
2396 CALL timeset(routinen, handle)
2397 world => kpoint%blacs_env_all%para_env
2398 CALL dbcsr_get_info(template, row_blk_size=row_size, col_blk_size=col_size, &
2399 row_blk_offset=row_offset, col_blk_offset=col_offset)
2400 CALL kp_density_groups_create(kpoint,
SIZE(row_size), groups)
2401 cpassert(
SIZE(row_size) ==
SIZE(col_size))
2402 ALLOCATE (tiles(4,
SIZE(row_size),
SIZE(source, 1),
SIZE(source, 2),
SIZE(source, 3)))
2403 DO ispin = 1,
SIZE(source, 3)
2404 DO ic = 1,
SIZE(source, 2)
2405 DO ikp = 1,
SIZE(source, 1)
2406 CALL kp_density_layout_create(source(ikp, ic, ispin)%matrix, row_size, col_size, &
2407 row_offset, col_offset, tiles(:, :, ikp, ic, ispin))
2410 DO image = 1,
SIZE(denmat, 2)
2411 CALL dbcsr_set(denmat(ispin, image)%matrix, 0.0_dp)
2417 ALLOCATE (local_jobs(8, plan%ngroup), counts(0:world%num_pe - 1))
2419 DO igroup = 1, plan%ngroup
2420 first = plan%group_start(igroup)
2421 last = plan%group_start(igroup + 1) - 1
2423 plan%row(first), plan%col(first), block, found=found)
2424 IF (.NOT. found) cycle
2426 local_jobs(:, nlocal) = [plan%row(first), plan%col(first), plan%image(first), &
2427 plan%cell(:, first), last - first + 1, &
2428 nint(sum(plan%symmetry_sign(first:last)))]
2430 CALL world%allgather(nlocal, counts)
2431 IF (maxval(counts) == 0)
THEN
2432 CALL timestop(handle)
2435 block_size = int(maxval(row_size),
int_8)*maxval(col_size)
2436 batch = max(1, min(max_batch, maxval(counts), int(max_bytes/(8_int_8*block_size))))
2437 ALLOCATE (jobs(8, batch), offsets(batch + 1), tile_start(batch + 1), values(int(block_size)*batch), &
2438 available(2, 0:ubound(groups, 1), batch))
2441 ALLOCATE (gemm_ctx(nthreads))
2442 DO thread = 1, nthreads
2446 DO owner = 0, world%num_pe - 1
2447 DO first = 1, counts(owner), batch
2448 njob = min(batch, counts(owner) - first + 1)
2449 IF (world%mepos == owner) jobs(:, 1:njob) = local_jobs(:, first:first + njob - 1)
2450 IF (world%num_pe > 1)
CALL world%bcast(jobs(:, 1:njob), owner)
2453 offsets(j + 1) = offsets(j) + row_size(jobs(1, j))*col_size(jobs(2, j))
2459 DO WHILE (i <= njob)
2461 tile_start(ntile) = i
2463 DO WHILE (j <= min(njob, i + images_per_tile - 1))
2464 IF (any(jobs(1:2, j) /= jobs(1:2, i)))
EXIT
2469 tile_start(ntile + 1) = njob + 1
2470 available(:, :, :) = 0
2472 j = tile_start(tile)
2473 DO slot = 0, ubound(groups, 1)
2474 IF (.NOT.
ALLOCATED(groups(slot)%inverse)) cycle
2475 DO orientation = 1, 2
2476 CALL kp_density_source_block(groups(slot), jobs(1:2, j), plan%symmetric, &
2477 orientation, a, b, trans)
2480 available(orientation, slot, tile) = merge(1, 0, found)
2486 IF (world%num_pe > 1)
CALL world%sum(available(:, :, 1:ntile))
2487 nvalue = offsets(njob + 1) - 1
2488 nthreads = min(
SIZE(gemm_ctx), ntile)
2489 DO ispin = 1,
SIZE(source, 3)
2490 values(1:nvalue) = 0.0_dp
2499 j = tile_start(tile)
2500 last = tile_start(tile + 1) - 1
2501 nrow = row_size(jobs(1, j))
2502 ncol = col_size(jobs(2, j))
2503 block(1:nrow*ncol, 1:last - j + 1) => values(offsets(j):offsets(last + 1) - 1)
2504 CALL kp_density_contract_tile(source(:, :, ispin), tiles(:, :, :, :, ispin), groups, &
2505 jobs(:, j:last), available(:, :, tile), plan%symmetric, &
2506 row_size, col_size, row_offset, col_offset, block, &
2507 packed, phases, sums, rotation_work, gemm_ctx(thread))
2511 IF (world%num_pe > 1)
CALL world%sum(values(1:nvalue), root=owner)
2512 IF (world%mepos /= owner) cycle
2514 CALL dbcsr_get_block_p(denmat(ispin, jobs(3, j))%matrix, jobs(1, j), jobs(2, j), block, found=found)
2516 nrow =
SIZE(block, 1)
2517 DO i = 1,
SIZE(block, 2)
2518 nblock = offsets(j) + (i - 1)*nrow
2519 block(:, i) = values(nblock:nblock + nrow - 1)
2525 DO thread = 1,
SIZE(gemm_ctx)
2526 CALL gemm_ctx(thread)%destroy()
2528 CALL timestop(handle)
2529 END SUBROUTINE kpoint_density_transform_batched
2539 SUBROUTINE kp_density_groups_create(kpoint, natom, groups)
2541 INTEGER,
INTENT(IN) :: natom
2542 TYPE(kp_density_group_type),
ALLOCATABLE, &
2543 INTENT(OUT) :: groups(:)
2545 INTEGER :: i, ik, ikp, is, ncontrib, nrot, pass, &
2547 INTEGER,
ALLOCATABLE :: counts(:)
2551 IF (
ASSOCIATED(kpoint%ibrot)) nrot =
SIZE(kpoint%ibrot)
2552 ALLOCATE (groups(0:4*nrot), counts(0:4*nrot))
2555 DO ik = 1, kpoint%nkp
2556 ikp = ik - kpoint%kp_range(1) + 1
2557 kpsym => kpoint%kp_sym(ik)%kpoint_sym
2559 IF (
kpsym%apply_symmetry) ncontrib =
kpsym%nwght
2562 IF (
kpsym%apply_symmetry)
THEN
2563 cpassert(
kpsym%phase_mode(is) >= 1 .AND.
kpsym%phase_mode(is) <= 2)
2566 slot = slot + nrot*merge(1, 0,
kpsym%rotp(is) < 0) + 2*nrot*(
kpsym%phase_mode(is) - 1)
2569 IF (.NOT.
ALLOCATED(groups(slot)%inverse))
THEN
2570 ALLOCATE (groups(slot)%inverse(natom))
2571 groups(slot)%op%identity = .true.
2573 groups(slot)%inverse(i) = i
2576 CALL kp_symmetry_op_init(groups(slot)%op, kpoint,
kpsym, is)
2577 groups(slot)%reverse_phase =
kpsym%phase_mode(is) == 2
2579 groups(slot)%inverse(groups(slot)%op%atom_map(i)) = i
2582 ELSE IF (slot > 0)
THEN
2584 cpassert(all(groups(slot)%op%atom_map ==
kpsym%f0(:, is)))
2585 cpassert(all(groups(slot)%op%cell_shift ==
kpsym%fcell_gauge(:, :, is)))
2588 IF (ik < kpoint%kp_range(1) .OR. ik > kpoint%kp_range(2)) cycle
2589 counts(slot) = counts(slot) + 1
2592 groups(slot)%ikp(i) = ikp
2593 groups(slot)%weight(i) = kpoint%wkp(ik)/real(ncontrib,
dp)
2595 groups(slot)%xkp(:, i) = kpoint%xkp(:, ik)
2597 groups(slot)%xkp(:, i) =
kpsym%xkp(:, is)
2604 ALLOCATE (groups(slot)%ikp(counts(slot)), groups(slot)%weight(counts(slot)), &
2605 groups(slot)%xkp(3, counts(slot)))
2609 END SUBROUTINE kp_density_groups_create
2620 SUBROUTINE kp_density_layout_create(matrix, row_size, col_size, row_offset, col_offset, tile)
2622 INTEGER,
INTENT(IN) :: row_size(:), col_size(:), row_offset(:), &
2624 INTEGER,
INTENT(OUT) :: tile(:, :)
2626 INTEGER :: a, i, ncol, nrow
2627 INTEGER,
ALLOCATABLE :: cols(:), rows(:)
2628 INTEGER,
POINTER :: col_indices(:), row_indices(:)
2630 cpassert(matrix%matrix_struct%nrow_global == sum(row_size))
2631 cpassert(matrix%matrix_struct%ncol_global == sum(col_size))
2633 row_indices=row_indices, col_indices=col_indices)
2634 ALLOCATE (rows(0:sum(row_size)), cols(0:sum(col_size)))
2638 rows(row_indices(i)) = 1
2641 cols(col_indices(i)) = 1
2643 DO i = 1, ubound(rows, 1)
2644 rows(i) = rows(i) + rows(i - 1)
2646 DO i = 1, ubound(cols, 1)
2647 cols(i) = cols(i) + cols(i - 1)
2649 DO a = 1,
SIZE(row_size)
2650 tile(1:2, a) = [rows(row_offset(a) - 1) + 1, rows(row_offset(a) + row_size(a) - 1)]
2652 DO a = 1,
SIZE(col_size)
2653 tile(3:4, a) = [cols(col_offset(a) - 1) + 1, cols(col_offset(a) + col_size(a) - 1)]
2655 END SUBROUTINE kp_density_layout_create
2669 SUBROUTINE kp_density_source_block(group, TARGET, symmetric, orientation, a, b, trans)
2670 TYPE(kp_density_group_type),
INTENT(IN) :: group
2671 INTEGER,
INTENT(IN) ::
target(2)
2672 LOGICAL,
INTENT(IN) :: symmetric
2673 INTEGER,
INTENT(IN) :: orientation
2674 INTEGER,
INTENT(OUT) :: a, b
2675 LOGICAL,
INTENT(OUT) :: trans
2682 IF (group%op%identity)
THEN
2683 IF (orientation == 1)
THEN
2689 IF (target(1) > target(2))
RETURN
2690 i = group%inverse(target(1))
2691 j = group%inverse(target(2))
2692 IF (orientation == 2 .AND. (symmetric .OR. i == j))
RETURN
2695 IF (orientation == 2)
THEN
2699 trans = group%op%atom_map(a) > group%op%atom_map(b)
2700 END SUBROUTINE kp_density_source_block
2724 SUBROUTINE kp_density_contract_tile(source, tiles, groups, jobs, available, symmetric, &
2725 row_size, col_size, row_offset, col_offset, TARGET, &
2726 packed, phases, sums, rotation_work, gemm_ctx)
2728 INTEGER,
INTENT(IN) :: tiles(:, :, :, :)
2729 TYPE(kp_density_group_type),
INTENT(IN) :: groups(0:)
2730 INTEGER,
INTENT(IN) :: jobs(:, :), available(:, 0:)
2731 LOGICAL,
INTENT(IN) :: symmetric
2732 INTEGER,
INTENT(IN) :: row_size(:), col_size(:), row_offset(:), &
2734 REAL(kind=
dp),
CONTIGUOUS,
INTENT(INOUT),
TARGET :: target(:, :)
2735 REAL(kind=
dp),
ALLOCATABLE,
INTENT(INOUT) :: packed(:, :), phases(:, :)
2736 REAL(kind=
dp),
ALLOCATABLE,
INTENT(INOUT),
TARGET :: sums(:, :)
2737 REAL(kind=
dp),
ALLOCATABLE,
INTENT(INOUT) :: rotation_work(:, :)
2740 INTEGER(KIND=int_8),
PARAMETER :: max_elements = 65536_int_8
2742 INTEGER :: a, b, batch, column, first, i, ic, &
2743 ifirst, ii, ikp, ilast, image, j, jj, &
2744 k, last, nc, nelement, nimage, nrow, &
2745 orientation, shift(3), slot
2746 LOGICAL :: contributes, real_only, trans
2747 REAL(kind=
dp) :: arg, cosine, factors(2, 2), sine
2748 REAL(kind=
dp),
POINTER :: left_rot(:, :), right_rot(:, :), &
2749 source_block(:, :), target_block(:, :)
2754 nc =
SIZE(source, 2)
2756 nimage =
SIZE(jobs, 2)
2757 DO slot = 0, ubound(groups, 1)
2758 IF (
SIZE(groups(slot)%ikp) == 0) cycle
2759 DO orientation = 1, 2
2760 IF (available(orientation, slot) == 0) cycle
2761 CALL kp_density_source_block(groups(slot), jobs(1:2, 1), symmetric, orientation, a, b, trans)
2763 nelement = row_size(a)*col_size(b)
2764 batch = max(1, min(128,
SIZE(groups(slot)%ikp), int(max_elements/(int(nelement,
int_8)*nc))))
2765 CALL ensure_work_matrix(packed, nelement, nc*batch)
2766 CALL ensure_work_matrix(phases, nc*batch, nimage)
2767 CALL ensure_work_matrix(sums, nelement, nimage)
2770 IF (.NOT. groups(slot)%op%identity)
THEN
2771 shift(:) = groups(slot)%op%cell_shift(:, b) - groups(slot)%op%cell_shift(:, a)
2772 IF (groups(slot)%reverse_phase) shift(:) = -shift
2774 DO first = 1,
SIZE(groups(slot)%ikp), batch
2775 last = min(first + batch - 1,
SIZE(groups(slot)%ikp))
2776 packed(:, :) = 0.0_dp
2777 contributes = .false.
2779 ikp = groups(slot)%ikp(k)
2780 CALL kp_symmetry_phase_factors(shift, groups(slot)%xkp(:, k), &
2781 groups(slot)%op%time_reversal, real_only, factors)
2782 DO image = 1, nimage
2783 arg =
twopi*dot_product(real(jobs(4:6, image),
dp), groups(slot)%xkp(:, k))
2784 cosine = real(jobs(7, image),
dp)*cos(arg)
2785 sine = real(jobs(8, image),
dp)*sin(arg)*merge(-1.0_dp, 1.0_dp, trans)
2786 IF (real_only) sine = 0.0_dp
2788 column = (k - first)*nc + ic
2789 phases(column, image) = groups(slot)%weight(k)*(cosine*factors(1, ic) + sine*factors(2, ic))
2793 ifirst = tiles(1, a, ikp, ic)
2794 ilast = tiles(2, a, ikp, ic)
2795 IF (ifirst > ilast .OR. tiles(3, b, ikp, ic) > tiles(4, b, ikp, ic)) cycle
2796 contributes = .true.
2797 column = (k - first)*nc + ic
2798 matrix => source(ikp, ic)%matrix
2799 nrow = ilast - ifirst + 1
2800 DO j = tiles(3, b, ikp, ic), tiles(4, b, ikp, ic)
2801 jj = matrix%matrix_struct%col_indices(j) - col_offset(b)
2802 ii = matrix%matrix_struct%row_indices(ifirst) - row_offset(a) + 1 + jj*row_size(a)
2803 IF (matrix%matrix_struct%row_indices(ilast) - &
2804 matrix%matrix_struct%row_indices(ifirst) == nrow - 1)
THEN
2805 packed(ii:ii + nrow - 1, column) = matrix%local_data(ifirst:ilast, j)
2807 DO i = ifirst, ilast
2808 ii = matrix%matrix_struct%row_indices(i) - row_offset(a) + 1 + jj*row_size(a)
2809 packed(ii, column) = matrix%local_data(i, j)
2815 IF (.NOT. contributes) cycle
2816 CALL gemm_ctx%gemm(
'N',
'N', nelement, nimage, nc*(last - first + 1), 1.0_dp, &
2817 packed,
SIZE(packed, 1), phases,
SIZE(phases, 1), &
2818 1.0_dp, sums,
SIZE(sums, 1))
2820 IF (groups(slot)%op%identity)
THEN
2821 target(:, :) =
TARGET + sums
2823 left_rot => groups(slot)%op%kind_rot(groups(slot)%op%atom_kind(groups(slot)%inverse(jobs(1, 1))))%rmat
2824 right_rot => groups(slot)%op%kind_rot(groups(slot)%op%atom_kind(groups(slot)%inverse(jobs(2, 1))))%rmat
2825 DO image = 1, nimage
2826 source_block(1:row_size(a), 1:col_size(b)) => sums(:, image)
2827 target_block(1:row_size(jobs(1, image)), 1:col_size(jobs(2, image))) => target(:, image)
2828 CALL kp_symmetry_rotate_block(source_block, left_rot, right_rot, trans, &
2829 1.0_dp, target_block, rotation_work)
2834 END SUBROUTINE kp_density_contract_tile
2848 SUBROUTINE kpoint_density_transform_regular_grid(kpoint, source, denmat, components, fmwork, plan, completed)
2851 TYPE(
cp_fm_p_type),
DIMENSION(:, :, :),
INTENT(IN) :: source
2853 TYPE(
dbcsr_p_type),
DIMENSION(:),
INTENT(IN) :: components
2854 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(IN),
TARGET :: fmwork
2856 LOGICAL,
INTENT(OUT) :: completed
2858 CHARACTER(LEN=*),
PARAMETER :: routinen =
'kpoint_density_transform_regular_grid'
2860 INTEGER :: compatible, element, first, handle, i, &
2861 ic, igroup, ik, ikp, image, ispin, j, &
2862 kplocal, nc, ncol, nrow
2863 INTEGER,
DIMENSION(14) :: layout, layout_max, layout_min
2864 INTEGER,
DIMENSION(2) :: fft_range
2865 LOGICAL :: found, local, same_layout
2866 REAL(kind=
dp) :: arg, dense_work, sparse_work
2867 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: phase
2868 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: fft_density
2869 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: block
2873 TYPE(
cp_fm_type),
DIMENSION(2),
TARGET :: partial
2874 TYPE(
cp_fm_type),
DIMENSION(:),
POINTER :: image_source
2878 para_env => kpoint%blacs_env_all%para_env
2879 inter => kpoint%para_env_inter_kp
2880 local = para_env%num_pe == 1
2881 kplocal =
SIZE(source, 1)
2882 nc =
SIZE(source, 2)
2883 cpassert(nc >= 1 .AND. nc <= 2)
2884 fms => source(1, 1, 1)%matrix%matrix_struct
2885 same_layout = .true.
2886 DO ispin = 1,
SIZE(source, 3)
2890 same_layout = same_layout .AND. &
2891 all(fms%first_p_pos == source(ikp, ic, ispin)%matrix%matrix_struct%first_p_pos)
2895 CALL cp_fm_get_info(source(1, 1, 1)%matrix, nrow_local=nrow, ncol_local=ncol)
2896 layout = [fms%nrow_global, fms%ncol_global, fms%nrow_block, fms%ncol_block, &
2897 fms%first_p_pos, fms%context%num_pe, fms%context%mepos, &
2898 shape(source(1, 1, 1)%matrix%local_data), nrow, ncol]
2901 IF (inter%num_pe > 1)
THEN
2902 CALL inter%min(layout_min)
2903 CALL inter%max(layout_max)
2905 compatible = merge(1, 0, same_layout .AND. all(layout_min == layout_max))
2906 IF (.NOT. local)
CALL para_env%min(compatible)
2907 IF (compatible == 0)
RETURN
2911 sparse_work = -1.0_dp
2912 dense_work = real(nrow,
dp)*real(ncol,
dp)*
SIZE(denmat, 2)
2914 sparse_work = 0.0_dp
2915 DO igroup = 1, plan%ngroup
2916 first = plan%group_start(igroup)
2918 IF (found) sparse_work = sparse_work + real(
SIZE(block),
dp)
2922 CALL timeset(routinen, handle)
2923 ALLOCATE (phase(kplocal, nc))
2924 DO ispin = 1,
SIZE(source, 3)
2925 CALL kp_density_fft(kpoint, source(:, :, ispin), nrow, ncol,
SIZE(denmat, 2), &
2926 fft_range, fft_density, local)
2927 IF (ispin == 1)
THEN
2928 IF (local .AND. .NOT.
ALLOCATED(fft_density) .AND. dense_work > sparse_work)
EXIT
2932 image_source => partial
2933 IF (.NOT. local)
THEN
2934 cpassert(
SIZE(fmwork) >= nc)
2935 image_source => fmwork
2938 DO image = 1,
SIZE(denmat, 2)
2940 partial(ic)%local_data(:, :) = 0.0_dp
2942 IF (
ALLOCATED(fft_density))
THEN
2945 DO element = fft_range(1), fft_range(2)
2946 i =
modulo(element - 1, nrow) + 1
2947 j = (element - 1)/nrow + 1
2949 partial(ic)%local_data(i, j) = fft_density(element - fft_range(1) + 1, ic, image)
2955 ik = kpoint%kp_range(1) + ikp - 1
2956 arg =
twopi*dot_product(real(kpoint%index_to_cell(:, image),
dp), kpoint%xkp(:, ik))
2957 phase(ikp, 1) = kpoint%wkp(ik)*cos(arg)
2958 IF (nc == 2) phase(ikp, 2) = kpoint%wkp(ik)*sin(arg)
2966 partial(ic)%local_data(1:nrow, j) = partial(ic)%local_data(1:nrow, j) + &
2967 phase(ikp, ic)*source(ikp, ic, ispin)%matrix%local_data(1:nrow, j)
2974 IF (.NOT. local)
THEN
2976 IF (inter%num_pe > 1)
CALL inter%sum(partial(ic)%local_data)
2977 IF (kpoint%iogrp)
THEN
2989 CALL kp_copy_fm_to_dbcsr(image_source(ic), components(ic)%matrix, local)
2991 CALL kp_accumulate_density_image(denmat(ispin, image)%matrix, components(1)%matrix, &
2992 components(2)%matrix, image, nc == 1, plan)
2994 IF (
ALLOCATED(fft_density))
DEALLOCATE (fft_density)
3002 CALL timestop(handle)
3004 END SUBROUTINE kpoint_density_transform_regular_grid
3021 SUBROUTINE kp_density_fft(kpoint, source, nrow, ncol, nimg, owned, density, local)
3024 TYPE(
cp_fm_p_type),
DIMENSION(:, :),
INTENT(IN) :: source
3025 INTEGER,
INTENT(IN) :: nrow, ncol, nimg
3026 INTEGER,
DIMENSION(2),
INTENT(OUT) :: owned
3027 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :), &
3028 INTENT(OUT) :: density
3029 LOGICAL,
INTENT(IN) :: local
3031 INTEGER(KIND=int_8),
PARAMETER :: max_bytes = 64_int_8*1024*1024, &
3032 min_fft_peer_bytes = 32_int_8*1024
3033 INTEGER,
PARAMETER :: max_batch = 32
3035 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:), &
3037 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: values_rs
3038 COMPLEX(KIND=dp),
CONTIGUOUS,
DIMENSION(:), &
3040 COMPLEX(KIND=dp),
CONTIGUOUS,
DIMENSION(:, :, :), &
3042 INTEGER :: batch, count, element, first, group, handle, i, ikp, j, last, local_k, &
3043 min_local_k, mine, nc, nel, ngroup, nkp, nowned, offset, pos, width
3044 INTEGER(KIND=int_8) :: fixed_bytes, peer_bytes, per_entry, &
3046 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: rcount, rdispl, scount, sdispl
3047 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: cells, ranges
3048 INTEGER,
DIMENSION(2) :: choice
3049 INTEGER,
DIMENSION(3) :: nfft
3050 LOGICAL :: compatible
3056 nkp =
SIZE(kpoint%xkp, 2)
3061 IF (any(kpoint%nkp_grid <= 0))
RETURN
3063 IF (32_int_8*product(int(kpoint%nkp_grid,
int_8)) > max_bytes)
RETURN
3065 IF (.NOT. compatible)
RETURN
3066 IF (32_int_8*product(int(nfft,
int_8)) > max_bytes)
RETURN
3068 IF (.NOT. compatible)
RETURN
3070 inter => kpoint%para_env_inter_kp
3071 ngroup = inter%num_pe
3072 mine = inter%mepos + 1
3073 local_k =
SIZE(source, 1)
3074 nc =
SIZE(source, 2)
3075 tile_size = int(nrow,
int_8)*ncol
3078 IF (tile_size <= huge(nel)) nel = int(tile_size)
3079 ALLOCATE (ranges(2, ngroup))
3080 DO group = 1, ngroup
3081 ranges(1, group) = int(int(nel,
int_8)*(group - 1)/ngroup) + 1
3082 ranges(2, group) = int(int(nel,
int_8)*group/ngroup)
3084 owned = ranges(:, mine)
3085 nowned = max(0, owned(2) - owned(1) + 1)
3086 fixed_bytes = 8_int_8*nowned*nc*nimg + 32_int_8*product(int(nfft,
int_8)) + &
3087 4_int_8*product(int(kpoint%nkp_grid,
int_8)) + 44_int_8*nkp + 52_int_8*nc*nimg + &
3088 24_int_8*ngroup + 64_int_8
3089 per_entry = 16_int_8*(int(ngroup,
int_8)*local_k + nkp + int(nc,
int_8)*nimg)
3090 width = int(max(0_int_8, min(int(max_batch,
int_8), (max_bytes - fixed_bytes)/per_entry)))
3091 choice = [merge(1, 0, tile_size <= huge(nel)), width]
3093 IF (kpoint%blacs_env_all%para_env%num_pe > 1)
CALL kpoint%blacs_env_all%para_env%min(choice)
3094 IF (choice(1) == 0 .OR. choice(2) == 0)
RETURN
3099 min_local_k = minval(kpoint%kp_dist(2, :) - kpoint%kp_dist(1, :) + 1)
3100 peer_bytes = 16_int_8*int(width,
int_8)*int(min_local_k,
int_8)
3101 IF (peer_bytes < min_fft_peer_bytes)
RETURN
3104 CALL timeset(
"kp_density_fft", handle)
3105 ALLOCATE (density(nowned, nc, nimg))
3106 ALLOCATE (cells(3, nc*nimg))
3107 cells(:, 1:nimg) = kpoint%index_to_cell(:, 1:nimg)
3108 IF (nc == 2) cells(:, nimg + 1:) = -cells(:, 1:nimg)
3109 ALLOCATE (scount(ngroup), sdispl(ngroup), rcount(ngroup), rdispl(ngroup))
3110 ALLOCATE (recvbuf(max(1, width*nkp)))
3111 IF (ngroup == 1)
THEN
3114 ALLOCATE (sendbuf(max(1, width*ngroup*local_k)))
3116 ALLOCATE (values_rs(width, 1, nc*nimg))
3117 IF (nowned > 0)
THEN
3119 weights=kpoint%wkp, allow_incomplete=.true.)
3121 DO batch = 1, maxval(ranges(2, :) - ranges(1, :) + 1), width
3122 count = max(0, min(width, nowned - batch + 1))
3124 DO group = 1, ngroup
3125 first = ranges(1, group) + batch - 1
3126 last = min(first + width - 1, ranges(2, group))
3127 scount(group) = max(0, last - first + 1)*local_k
3128 sdispl(group) = offset
3129 offset = offset + scount(group)
3130 rcount(group) = count*(kpoint%kp_dist(2, group) - kpoint%kp_dist(1, group) + 1)
3131 rdispl(group) = count*(kpoint%kp_dist(1, group) - 1)
3138 DO element = first, last
3139 i =
modulo(element - 1, nrow) + 1
3140 j = (element - 1)/nrow + 1
3141 pos = sdispl(group) + (ikp - 1)*(last - first + 1) + element - first + 1
3142 sendbuf(pos) = cmplx(source(ikp, 1)%matrix%local_data(i, j), 0.0_dp,
dp)
3143 IF (nc == 2) sendbuf(pos) = cmplx(real(sendbuf(pos),
dp), &
3144 source(ikp, 2)%matrix%local_data(i, j),
dp)
3149 IF (ngroup > 1)
CALL inter%alltoall(sendbuf, scount, sdispl, recvbuf, rcount, rdispl)
3150 IF (count == 0) cycle
3151 values_k(1:count, 1:1, 1:nkp) => recvbuf(1:count*nkp)
3156 density(batch:batch + count - 1, 1, i) = real(values_rs(1:count, 1, i),
dp)
3158 density(batch:batch + count - 1, 1, i) = 0.5_dp* &
3159 REAL(values_rs(1:count, 1, i) + values_rs(1:count, 1, nimg + i),
dp)
3160 density(batch:batch + count - 1, 2, i) = 0.5_dp* &
3161 REAL(values_rs(1:count, 1, i) - values_rs(1:count, 1, nimg + i),
dp)
3166 IF (ngroup > 1)
DEALLOCATE (sendbuf)
3168 CALL timestop(handle)
3170 END SUBROUTINE kp_density_fft
3183 SUBROUTINE kp_accumulate_density_image(denmat, rpmat, cpmat, image, real_only, plan)
3185 TYPE(
dbcsr_type),
POINTER :: denmat, rpmat, cpmat
3186 INTEGER,
INTENT(IN) :: image
3187 LOGICAL,
INTENT(IN) :: real_only
3190 INTEGER :: first, igroup, last
3192 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: cblock, dblock, rblock
3198 DO igroup = 1, plan%ngroup
3199 first = plan%group_start(igroup)
3200 IF (plan%image(first) /= image) cycle
3201 last = plan%group_start(igroup + 1) - 1
3202 CALL dbcsr_get_block_p(denmat, plan%row(first), plan%col(first), dblock, found=found)
3203 IF (.NOT. found) cycle
3205 IF (.NOT. found) cycle
3206 IF (.NOT. real_only)
THEN
3208 IF (.NOT. found) cycle
3210 dblock = real(last - first + 1,
dp)*rblock
3211 IF (.NOT. real_only) dblock = dblock + sum(plan%symmetry_sign(first:last))*cblock
3215 END SUBROUTINE kp_accumulate_density_image
3223 SUBROUTINE kp_copy_fm_to_dbcsr(fm, matrix, local)
3227 LOGICAL,
INTENT(IN) :: local
3229 INTEGER :: col_offset, row_offset
3230 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
3232 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: block
3235 IF (.NOT. local)
THEN
3243 col_offset=col_offset)
3244 block(:, :) = full(row_offset:row_offset +
SIZE(block, 1) - 1, &
3245 col_offset:col_offset +
SIZE(block, 2) - 1)
3249 END SUBROUTINE kp_copy_fm_to_dbcsr
3265 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
3266 INTEGER,
INTENT(IN) :: nimg
3267 TYPE(
dbcsr_type),
INTENT(IN),
OPTIONAL :: block_template
3268 LOGICAL,
INTENT(IN),
OPTIONAL :: group_entries
3270 INTEGER :: i, iatom, icell, icol, igroup, irow, &
3272 INTEGER(KIND=int_8),
ALLOCATABLE,
DIMENSION(:) :: key
3273 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: order
3274 INTEGER,
DIMENSION(3) :: cell
3275 INTEGER,
DIMENSION(:),
POINTER :: col_offsets, row_offsets
3276 LOGICAL :: do_grouping, do_symmetric, store_offsets
3278 DIMENSION(:),
POINTER :: iterator
3281 plan%symmetric = do_symmetric
3282 do_grouping = .false.
3283 IF (
PRESENT(group_entries)) do_grouping = group_entries
3284 store_offsets =
PRESENT(block_template)
3285 IF (store_offsets)
THEN
3286 CALL dbcsr_get_info(block_template, row_blk_offset=row_offsets, col_blk_offset=col_offsets)
3291 icell = cell_to_index(cell(1), cell(2), cell(3))
3292 IF (icell >= 1 .AND. icell <= nimg) plan%nentry = plan%nentry + 1
3296 ALLOCATE (plan%row(plan%nentry), plan%col(plan%nentry), plan%image(plan%nentry), &
3297 plan%cell(3, plan%nentry), plan%symmetry_sign(plan%nentry))
3298 IF (store_offsets)
THEN
3299 ALLOCATE (plan%row_offset(plan%nentry), plan%col_offset(plan%nentry))
3306 icell = cell_to_index(cell(1), cell(2), cell(3))
3307 IF (icell < 1 .OR. icell > nimg) cycle
3311 plan%symmetry_sign(i) = 1.0_dp
3312 IF (do_symmetric .AND. iatom > jatom)
THEN
3315 plan%symmetry_sign(i) = -1.0_dp
3319 IF (store_offsets)
THEN
3320 plan%row_offset(i) = row_offsets(irow)
3321 plan%col_offset(i) = col_offsets(icol)
3323 plan%image(i) = icell
3324 plan%cell(:, i) = cell
3327 cpassert(i == plan%nentry)
3329 IF (do_grouping .AND. plan%nentry > 0)
THEN
3330 nblock = max(maxval(plan%row), maxval(plan%col))
3331 ALLOCATE (key(plan%nentry), order(plan%nentry))
3332 DO i = 1, plan%nentry
3333 key(i) = int(plan%image(i), kind=
int_8) + int(nimg, kind=
int_8)* &
3334 (int(plan%row(i) - 1, kind=
int_8) + int(nblock, kind=
int_8)* &
3335 int(plan%col(i) - 1, kind=
int_8))
3337 CALL sort(key, plan%nentry, order)
3338 plan%row(:) = plan%row(order)
3339 plan%col(:) = plan%col(order)
3340 IF (store_offsets)
THEN
3341 plan%row_offset(:) = plan%row_offset(order)
3342 plan%col_offset(:) = plan%col_offset(order)
3344 plan%image(:) = plan%image(order)
3345 plan%cell(:, :) = plan%cell(:, order)
3346 plan%symmetry_sign(:) = plan%symmetry_sign(order)
3349 DO i = 2, plan%nentry
3350 IF (key(i) /= key(i - 1)) plan%ngroup = plan%ngroup + 1
3352 ALLOCATE (plan%group_start(plan%ngroup + 1))
3354 plan%group_start(igroup) = 1
3355 DO i = 2, plan%nentry
3356 IF (key(i) /= key(i - 1))
THEN
3358 plan%group_start(igroup) = i
3361 plan%group_start(plan%ngroup + 1) = plan%nentry + 1
3362 DEALLOCATE (key, order)
3373 SUBROUTINE ensure_work_matrix(work, nrow, ncol)
3375 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :), &
3376 INTENT(INOUT) :: work
3377 INTEGER,
INTENT(IN) :: nrow, ncol
3379 IF (
ALLOCATED(work))
THEN
3380 IF (
SIZE(work, 1) == nrow .AND.
SIZE(work, 2) == ncol)
RETURN
3383 ALLOCATE (work(nrow, ncol))
3385 END SUBROUTINE ensure_work_matrix
3395 SUBROUTINE calibrate_symmetry_phases(kpoint, overlap_rs, tempmat, sab_nl, cell_to_index)
3398 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: overlap_rs
3402 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
3404 CHARACTER(LEN=*),
PARAMETER :: routinen =
'calibrate_symmetry_phases'
3406 CHARACTER(LEN=256) :: phase_error
3407 INTEGER :: best_mode, handle, iatom, ik, is, key, &
3408 mode, nrot, rot_slot
3409 INTEGER,
ALLOCATABLE :: best_ik(:), best_is(:), mode_by_op(:)
3410 LOGICAL :: needs_calibration, reverse
3411 REAL(kind=
dp) :: arg, best_residual, candidate_norm, &
3412 direct_norm, overlap_dot, phase_score, &
3413 phase_tolerance, relative_residual
3414 REAL(kind=
dp),
ALLOCATABLE :: best_score(:)
3415 TYPE(
dbcsr_type),
POINTER :: direct_c, direct_r, source_c, source_r, &
3417 TYPE(kp_symmetry_op_type) :: op
3420 needs_calibration = .false.
3421 DO ik = 1, kpoint%nkp
3422 kpsym => kpoint%kp_sym(ik)%kpoint_sym
3423 IF (
kpsym%apply_symmetry)
THEN
3425 IF (any(
kpsym%phase_mode(1:
kpsym%nwght) == 0))
THEN
3426 needs_calibration = .true.
3431 IF (.NOT. needs_calibration)
RETURN
3433 CALL timeset(routinen, handle)
3434 cpassert(
ASSOCIATED(kpoint%ibrot))
3435 nrot =
SIZE(kpoint%ibrot)
3436 ALLOCATE (best_ik(2*nrot), best_is(2*nrot), mode_by_op(2*nrot), best_score(2*nrot))
3440 best_score(:) = -1.0_dp
3446 DO ik = 1, kpoint%nkp
3447 kpsym => kpoint%kp_sym(ik)%kpoint_sym
3448 IF (.NOT.
kpsym%apply_symmetry) cycle
3449 DO is = 1,
kpsym%nwght
3451 cpassert(rot_slot > 0)
3452 key = rot_slot + nrot*merge(1, 0,
kpsym%rotp(is) < 0)
3453 IF (
kpsym%phase_mode(is) > 0)
THEN
3454 IF (mode_by_op(key) == 0)
THEN
3455 mode_by_op(key) =
kpsym%phase_mode(is)
3457 cpassert(mode_by_op(key) ==
kpsym%phase_mode(is))
3462 phase_score = 0.0_dp
3463 DO iatom = 2,
SIZE(
kpsym%fcell_gauge, 2)
3464 arg = dot_product(real(
kpsym%fcell_gauge(:, iatom, is) - &
3465 kpsym%fcell_gauge(:, 1, is), kind=
dp), &
3467 phase_score = max(phase_score, abs(sin(
twopi*arg)))
3469 IF (phase_score > best_score(key))
THEN
3470 best_score(key) = phase_score
3477 ALLOCATE (source_r, source_c, direct_r, direct_c, sym_r, sym_c)
3478 CALL dbcsr_create(source_r, template=tempmat, matrix_type=dbcsr_type_symmetric)
3479 CALL dbcsr_create(source_c, template=tempmat, matrix_type=dbcsr_type_antisymmetric)
3480 CALL dbcsr_create(direct_r, template=tempmat, matrix_type=dbcsr_type_symmetric)
3481 CALL dbcsr_create(direct_c, template=tempmat, matrix_type=dbcsr_type_antisymmetric)
3482 CALL dbcsr_create(sym_r, template=tempmat, matrix_type=dbcsr_type_symmetric)
3483 CALL dbcsr_create(sym_c, template=tempmat, matrix_type=dbcsr_type_antisymmetric)
3491 phase_tolerance = max(1.0e-6_dp, 100.0_dp*kpoint%eps_geo)
3493 IF (mode_by_op(key) > 0 .OR. best_ik(key) == 0) cycle
3496 IF (best_score(key) <= 1000.0_dp*epsilon(1.0_dp))
THEN
3503 kpsym => kpoint%kp_sym(ik)%kpoint_sym
3506 CALL rskp_transform(source_r, source_c, overlap_rs, 1, kpoint%xkp(1:3, ik), &
3507 cell_to_index, sab_nl)
3511 cell_to_index, sab_nl)
3512 CALL dbcsr_dot(direct_r, direct_r, direct_norm)
3513 CALL dbcsr_dot(direct_c, direct_c, candidate_norm)
3514 direct_norm = direct_norm + candidate_norm
3516 CALL kp_symmetry_op_init(op, kpoint,
kpsym, is)
3518 best_residual = huge(1.0_dp)
3521 CALL symtrans_phase(sym_r, sym_c, source_r, source_c, .false., op, reverse)
3522 CALL dbcsr_dot(sym_r, sym_r, candidate_norm)
3523 CALL dbcsr_dot(sym_c, sym_c, relative_residual)
3524 candidate_norm = candidate_norm + relative_residual
3525 CALL dbcsr_dot(sym_r, direct_r, overlap_dot)
3526 CALL dbcsr_dot(sym_c, direct_c, relative_residual)
3527 overlap_dot = overlap_dot + relative_residual
3528 relative_residual = sqrt(max(0.0_dp, candidate_norm + direct_norm - &
3529 2.0_dp*overlap_dot)/max(direct_norm, tiny(1.0_dp)))
3530 IF (relative_residual < best_residual)
THEN
3531 best_residual = relative_residual
3535 IF (best_residual > phase_tolerance)
THEN
3536 WRITE (phase_error,
'(A,ES12.4,A,I0,A,I0)') &
3537 "No Bloch-phase direction preserves overlap covariance; residual=", &
3538 best_residual,
", irreducible k-point=", ik,
", operation=", is
3539 CALL cp_abort(__location__, trim(phase_error))
3541 mode_by_op(key) = best_mode
3544 DO ik = 1, kpoint%nkp
3545 kpsym => kpoint%kp_sym(ik)%kpoint_sym
3546 IF (.NOT.
kpsym%apply_symmetry) cycle
3547 DO is = 1,
kpsym%nwght
3548 IF (
kpsym%phase_mode(is) > 0) cycle
3550 cpassert(rot_slot > 0)
3551 key = rot_slot + nrot*merge(1, 0,
kpsym%rotp(is) < 0)
3552 cpassert(mode_by_op(key) > 0)
3553 kpsym%phase_mode(is) = mode_by_op(key)
3563 CALL timestop(handle)
3565 END SUBROUTINE calibrate_symmetry_phases
3574 SUBROUTINE kp_symmetry_op_init(op, kpoint, kpsym, is)
3575 TYPE(kp_symmetry_op_type),
INTENT(OUT) :: op
3578 INTEGER,
INTENT(IN) :: is
3580 INTEGER :: iatom, rot_slot
3581 LOGICAL :: has_phase, perm, rotates
3583 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: rot
3586 cpassert(rot_slot > 0)
3587 op%kind_rot => kpoint%kind_rotmat(rot_slot, :)
3588 op%atom_map =>
kpsym%f0(:, is)
3589 op%atom_kind => kpoint%atype
3590 op%cell_shift =>
kpsym%fcell_gauge(:, :, is)
3591 op%xkp(:) =
kpsym%xkp(:, is)
3592 op%time_reversal =
kpsym%rotp(is) < 0
3595 DO iatom = 1,
SIZE(op%atom_map)
3596 IF (op%atom_map(iatom) == iatom) cycle
3600 rot =>
kpsym%rot(:, :, is)
3601 dr = abs(rot(1, 1) - 1.0_dp) + abs(rot(2, 2) - 1.0_dp) + abs(rot(3, 3) - 1.0_dp)
3602 rotates = abs(sum(abs(rot)) - 3.0_dp) > 1.e-12_dp .OR. abs(dr) > 1.e-12_dp
3603 has_phase = any(op%cell_shift /= 0) .OR. op%time_reversal
3604 op%identity = .NOT. (rotates .OR. perm .OR. has_phase)
3605 op%redistribute = perm .OR. has_phase
3607 END SUBROUTINE kp_symmetry_op_init
3619 SUBROUTINE symtrans_phase(srpmat, scpmat, rpmat, cpmat, real_only, op, reverse_phase)
3620 TYPE(
dbcsr_type),
POINTER :: srpmat, scpmat, rpmat, cpmat
3621 LOGICAL,
INTENT(IN) :: real_only
3622 TYPE(kp_symmetry_op_type),
INTENT(IN) :: op
3623 LOGICAL,
INTENT(IN) :: reverse_phase
3625 CHARACTER(LEN=*),
PARAMETER :: routinen =
'symtrans_phase'
3627 INTEGER :: handle, icol, ip, irow, jcol, jp, jrow, &
3628 mynode, nthreads, numnodes, owner
3629 INTEGER,
DIMENSION(3) :: shift
3630 LOGICAL :: found, trans
3631 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: cwork, rwork, twork
3632 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: cblock, left_rot, rblock, right_rot, &
3637 CALL timeset(routinen, handle)
3639 IF (op%identity)
THEN
3641 IF (.NOT. real_only)
CALL dbcsr_copy(scpmat, cpmat)
3642 CALL timestop(handle)
3648 IF (numnodes /= 1 .AND. op%redistribute)
THEN
3654 IF (.NOT. real_only)
CALL dbcsr_set(scpmat, 0.0_dp)
3666 shift(:) = op%cell_shift(:, icol) - op%cell_shift(:, irow)
3667 IF (reverse_phase) shift(:) = -shift
3669 CALL kp_symmetry_phase_block(rblock, shift, op%xkp, op%time_reversal, rwork)
3672 IF (.NOT. found)
NULLIFY (cblock)
3673 CALL kp_symmetry_phase_block(rblock, shift, op%xkp, op%time_reversal, rwork, cwork, cblock)
3676 ip = op%atom_map(irow)
3677 jp = op%atom_map(icol)
3682 left_rot => op%kind_rot(op%atom_kind(icol))%rmat
3683 right_rot => op%kind_rot(op%atom_kind(irow))%rmat
3685 left_rot => op%kind_rot(op%atom_kind(irow))%rmat
3686 right_rot => op%kind_rot(op%atom_kind(icol))%rmat
3689 CALL dbcsr_get_block_p(matrix=srpmat, row=jrow, col=jcol, block=srblock, found=found)
3690 IF (.NOT. found)
THEN
3692 cpassert(owner /= mynode)
3695 CALL kp_symmetry_rotate_block(rwork, left_rot, right_rot, trans, 1.0_dp, srblock, twork)
3696 IF (.NOT. real_only)
THEN
3697 CALL dbcsr_get_block_p(matrix=scpmat, row=jrow, col=jcol, block=scblock, found=found)
3700 CALL kp_symmetry_rotate_block(cwork, left_rot, right_rot, trans, &
3701 merge(-1.0_dp, 1.0_dp, trans), scblock, twork)
3706 IF (numnodes /= 1 .AND. op%redistribute)
THEN
3711 CALL timestop(handle)
3713 END SUBROUTINE symtrans_phase
3723 SUBROUTINE kp_symmetry_phase_factors(shift, xkp, time_reversal, real_only, phase)
3724 INTEGER,
INTENT(IN) :: shift(3)
3725 REAL(kind=
dp),
INTENT(IN) :: xkp(3)
3726 LOGICAL,
INTENT(IN) :: time_reversal, real_only
3727 REAL(kind=
dp),
INTENT(OUT) :: phase(2, 2)
3729 REAL(kind=
dp) :: arg, cosine, sine
3731 arg = real(shift(1),
dp)*xkp(1) + real(shift(2),
dp)*xkp(2) + real(shift(3),
dp)*xkp(3)
3732 cosine = cos(
twopi*arg)
3733 sine = sin(
twopi*arg)
3734 IF (real_only .AND. abs(sine) > 1.e-12_dp)
THEN
3735 CALL cp_abort(__location__,
"Real k-point wavefunctions cannot represent symmetry phases")
3737 phase(:, 1) = [cosine, -sine]
3738 phase(:, 2) = merge(-1.0_dp, 1.0_dp, time_reversal)*[sine, cosine]
3739 END SUBROUTINE kp_symmetry_phase_factors
3751 SUBROUTINE kp_symmetry_phase_block(rblock, shift, xkp, time_reversal, rwork, cwork, cblock)
3752 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: rblock
3753 INTEGER,
DIMENSION(3),
INTENT(IN) :: shift
3754 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
3755 LOGICAL,
INTENT(IN) :: time_reversal
3756 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :), &
3757 INTENT(INOUT) :: rwork
3758 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :), &
3759 INTENT(INOUT),
OPTIONAL :: cwork
3760 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN), &
3763 REAL(kind=
dp) :: phase(2, 2)
3765 CALL kp_symmetry_phase_factors(shift, xkp, time_reversal,.NOT.
PRESENT(cwork), phase)
3766 CALL ensure_work_matrix(rwork,
SIZE(rblock, 1),
SIZE(rblock, 2))
3767 rwork(:, :) = phase(1, 1)*rblock
3768 IF (.NOT.
PRESENT(cwork))
RETURN
3769 CALL ensure_work_matrix(cwork,
SIZE(rblock, 1),
SIZE(rblock, 2))
3770 cwork(:, :) = phase(2, 1)*rblock
3771 IF (
PRESENT(cblock))
THEN
3772 rwork(:, :) = rwork + phase(1, 2)*cblock
3773 cwork(:, :) = cwork + phase(2, 2)*cblock
3776 END SUBROUTINE kp_symmetry_phase_block
3788 SUBROUTINE kp_symmetry_rotate_block(block, left_rot, right_rot, trans, alpha, TARGET, work)
3789 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: block, left_rot, right_rot
3790 LOGICAL,
INTENT(IN) :: trans
3791 REAL(kind=
dp),
INTENT(IN) :: alpha
3792 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) ::
target
3793 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :), &
3794 INTENT(INOUT) :: work
3798 ncol = merge(
SIZE(block, 1),
SIZE(block, 2), trans)
3799 CALL ensure_work_matrix(work,
SIZE(left_rot, 1), ncol)
3800 CALL dgemm(
'N', merge(
'T',
'N', trans),
SIZE(left_rot, 1), ncol,
SIZE(left_rot, 2), &
3801 1.0_dp, left_rot,
SIZE(left_rot, 1), block,
SIZE(block, 1), &
3802 0.0_dp, work,
SIZE(work, 1))
3803 CALL dgemm(
'N',
'T',
SIZE(work, 1),
SIZE(right_rot, 1),
SIZE(work, 2), &
3804 alpha, work,
SIZE(work, 1), right_rot,
SIZE(right_rot, 1), &
3805 1.0_dp,
TARGET,
SIZE(
TARGET, 1))
3807 END SUBROUTINE kp_symmetry_rotate_block
static GRID_HOST_DEVICE int modulo(int a, int m)
Equivalent of Fortran's MODULO, which always return a positive number. https://gcc....
static void dgemm(const char transa, const char transb, const int m, const int n, const int k, const double alpha, const double *a, const int lda, const double *b, const int ldb, const double beta, double *c, const int ldc)
Convenient wrapper to hide Fortran nature of dgemm_, swapping a and b.
Define the atomic kind types and their sub types.
subroutine, public get_atomic_kind(atomic_kind, fist_potential, element_symbol, name, mass, kind_number, natom, atom_list, rcov, rvdw, z, qeff, apol, cpol, mm_radius, shell, shell_active, damping)
Get attributes of an atomic kind.
Handles all functions related to the CELL.
subroutine, public real_to_scaled(s, r, cell)
Transform real to scaled cell coordinates. s=h_inv*r.
real(kind=dp) function, dimension(3), public pbc_stable(r, cell)
Apply a stable periodic-image convention for k-point Bloch gauges.
methods related to the blacs parallel environment
subroutine, public cp_blacs_env_create(blacs_env, para_env, blacs_grid_layout, blacs_repeatable, row_major, grid_2d)
allocates and initializes a type that represent a blacs context
Basic linear algebra operations for complex full matrices.
subroutine, public cp_cfm_scale_and_add(alpha, matrix_a, beta, matrix_b)
Scale and add two BLACS matrices (a = alpha*a + beta*b).
subroutine, public cp_cfm_transpose(matrix, trans, matrixt)
Transposes a BLACS distributed complex matrix.
subroutine, public cp_cfm_column_scale(matrix_a, scaling)
Scales columns of the full matrix by corresponding factors.
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_get_submatrix(fm, target_m, start_row, start_col, n_rows, n_cols, transpose)
Extract a sub-matrix from the full matrix: op(target_m)(1:n_rows,1:n_cols) = fm(start_row:start_row+n...
subroutine, public cp_cfm_release(matrix)
Releases a full matrix.
subroutine, public cp_fm_to_cfm(msourcer, msourcei, mtarget)
Construct a complex full matrix by taking its real and imaginary parts from two separate real-value f...
subroutine, public cp_cfm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
Creates a new full matrix with the given structure.
subroutine, public cp_cfm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, matrix_struct, para_env)
Returns information about a full matrix.
subroutine, public cp_cfm_to_fm(msource, mtargetr, mtargeti)
Copy real and imaginary parts of a complex full matrix into separate real-value full matrices.
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
subroutine, public dbcsr_get_readonly_block_p(matrix, row, col, block, found, row_size, col_size)
Like dbcsr_get_block_p() but with matrix being INTENT(IN). When invoking this routine,...
subroutine, public dbcsr_deallocate_matrix(matrix)
...
logical function, public dbcsr_iterator_blocks_left(iterator)
...
subroutine, public dbcsr_iterator_stop(iterator)
...
subroutine, public dbcsr_copy(matrix_b, matrix_a, name, keep_sparsity, keep_imaginary)
...
subroutine, public dbcsr_get_block_p(matrix, row, col, block, found, row_size, col_size)
...
subroutine, public dbcsr_replicate_all(matrix)
...
subroutine, public dbcsr_get_info(matrix, nblkrows_total, nblkcols_total, nfullrows_total, nfullcols_total, nblkrows_local, nblkcols_local, nfullrows_local, nfullcols_local, my_prow, my_pcol, local_rows, local_cols, proc_row_dist, proc_col_dist, row_blk_size, col_blk_size, row_blk_offset, col_blk_offset, distribution, name, matrix_type, group)
...
subroutine, public dbcsr_get_stored_coordinates(matrix, row, column, processor)
...
subroutine, public dbcsr_distribute(matrix)
...
subroutine, public dbcsr_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset, transposed)
...
subroutine, public dbcsr_iterator_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_iterator_readonly_start(iterator, matrix, shared, dynamic, dynamic_byrows)
Like dbcsr_iterator_start() but with matrix being INTENT(IN). When invoking this routine,...
subroutine, public dbcsr_distribution_get(dist, row_dist, col_dist, nrows, ncols, has_threads, group, mynode, numnodes, nprows, npcols, myprow, mypcol, pgrid, subgroups_defined, prow_group, pcol_group)
...
subroutine, public dbcsr_dot(matrix_a, matrix_b, trace)
Computes the dot product of two matrices, also known as the trace of their matrix product.
Routines that link DBCSR and CP2K concepts together.
subroutine, public cp_dbcsr_alloc_block_from_nbl(matrix, sab_orb, desymmetrize)
allocate the blocks of a dbcsr based on the neighbor list
DBCSR operations in CP2K.
subroutine, public copy_fm_to_dbcsr(fm, matrix, keep_sparsity)
Copy a BLACS matrix to a dbcsr matrix.
Basic linear algebra operations for full matrices.
subroutine, public cp_fm_column_scale(matrixa, scaling)
scales column i of matrix a with scaling(i)
pool for for elements that are retained and released
subroutine, public fm_pool_create_fm(pool, element, name)
returns an element, allocating it if none is in the pool
subroutine, public fm_pool_give_back_fm(pool, element)
returns the element to the pool
represent the structure of a full matrix
logical function, public cp_fm_struct_equivalent(fmstruct1, fmstruct2)
returns true if the two matrix structures are equivalent, false otherwise.
represent a full matrix distributed on many processors
subroutine, public cp_fm_get_diag(matrix, diag)
returns the diagonal elements of a fm
subroutine, public cp_fm_start_copy_general(source, destination, para_env, info)
Initiates the copy operation: get distribution data, post MPI isend and irecvs.
subroutine, public cp_fm_cleanup_copy_general(info)
Completes the copy operation: wait for comms clean up MPI state.
subroutine, public cp_fm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, nrow_locals, ncol_locals, matrix_struct, para_env)
returns all kind of information about the full matrix
subroutine, public cp_fm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
subroutine, public cp_fm_finish_copy_general(destination, info)
Completes the copy operation: wait for comms, unpack, clean up MPI state.
subroutine, public cp_fm_get_submatrix(fm, target_m, start_row, start_col, n_rows, n_cols, transpose)
gets a submatrix of a full matrix op(target_m)(1:n_rows,1:n_cols) =fm(start_row:start_row+n_rows,...
various routines to log and control the output. The idea is that decisions about where to log should ...
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
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)
...
subroutine, public probe_occupancy_kp(occ, fermi, kts, energies, rcoeff, icoeff, maxocc, probe, n, wk)
subroutine to calculate occupation number and 'Fermi' level using the
Defines the basic variable types.
integer, parameter, public int_8
integer, parameter, public dp
Batched lattice Fourier transforms on regular k-point grids.
subroutine, public k_grid_to_cell_prepare(work, xkp, nkp_grid, index_to_cell, weights, allow_incomplete)
Prepare one inverse lattice transform for repeated matrix batches.
logical function, public regular_kpoint_grid(xkp, nkp_grid, grid_index, k_offset, allow_incomplete)
Test and map a uniformly shifted reciprocal grid or an explicitly allowed subset.
subroutine, public k_grid_to_cell_execute(work, values_k, values_rs, used_fft)
Execute a matrix batch using the prepared inverse lattice transform. Call outside OpenMP worker regio...
subroutine, public k_grid_to_cell_release(work)
Release call-scoped inverse lattice maps and FFT buffers.
subroutine, public cell_to_k_grid_fft(values_rs, index_to_cell, xkp, nkp_grid, values_k, used_fft, deriv_direction, hmat, selected_kpoints)
Transform a batch of real matrices from image cells to every supplied k point.
logical function, public lattice_fft_shape(n, nfft, allow_arbitrary)
Find backend-supported FFT dimensions that preserve the original lattice grid. Sample the padded tran...
Routines needed for kpoint calculation.
subroutine, public kpoint_smearing_edge_status(wocc, wkp, smear, nspin, has_weight, first_fractional, last_occupied, last_occupied_spin)
summarize whether weighted k-point smearing reaches the available band edges
subroutine, public kpoint_density_transform(kpoint, denmat, wtype, tempmat, sab_nl, fmwork, for_aux_fit, pmat_ext, overlap_rs)
generate real space density matrices in DBCSR format
subroutine, public lowdin_kp_mo_coeff(kp, ispin, use_real_wfn, shalfc, cshalfc)
Calculate S(k)^1/2 C(k) for real or complex k-point wavefunctions.
subroutine, public kpoint_initialize_mo_set(kpoint)
...
subroutine, public rskp_transform(rmatrix, cmatrix, rsmat, ispin, xkp, cell_to_index, sab_nl, is_complex, rs_sign)
Transformation of real space matrices to a kpoint.
subroutine, public kpoint_init_cell_index(kpoint, sab_nl, para_env, nimages)
Generates the mapping of cell indices and linear RS index CELL (0,0,0) is always mapped to index 1.
subroutine kp_link_index_create(representative, nkp, start, order)
Index full-grid links by irreducible k-point without rescanning the complete mesh.
subroutine, public kpoint_set_mo_occupation(kpoint, smear, probe, added_mos_auto, added_mos_auto_grow, separate_spin_occupations)
Given the eigenvalues of all kpoints, calculates the occupation numbers.
subroutine, public rskp_transform_grid_extract(grid, ikp, rmatrix, cmatrix)
Extract one reciprocal-grid matrix from a prepared local DBCSR block cache.
subroutine, public rskp_transform_grid_release(grid)
Release a reciprocal-grid transformation cache.
subroutine, public kpoint_initialize_mos(kpoint, mos, added_mos, for_aux_fit)
Initialize a set of MOs and density matrix for each kpoint (kpoint group).
subroutine, public kp_transform_plan_create(plan, sab_nl, cell_to_index, nimg, block_template, group_entries)
Build the immutable neighbor-list traversal shared by R-to-K and K-to-R transforms.
subroutine, public kpoint_initialize(kpoint, particle_set, cell)
Generate the kpoints and initialize the kpoint environment.
subroutine, public kpoint_ot_energy_weighted_density(coeff, hc, occupation, wmat)
Build W(k) for noncanonical complex OT orbitals from H(k) C(k). The occupied-space Lagrange multiplie...
subroutine, public rskp_transform_grid_prepare(grid, rmatrix, rsmat, ispin, xkp, nkp_grid, cell_to_index, sab_nl, used_fft, is_complex, rs_sign, max_storage_bytes)
Prepare a batched real-cell to complete reciprocal-grid transform for local DBCSR blocks....
subroutine, public kpoint_density_matrices(kpoint, energy_weighted, for_aux_fit)
Calculate kpoint density matrices (rho(k), owned by kpoint groups).
subroutine, public lowdin_kp_trans(kpoint, pmat_diag)
Calculate Lowdin transformation of density matrix S^1/2 P S^1/2 Integrate diagonal elements over k-po...
subroutine, public kpoint_env_initialize(kpoint, para_env, blacs_env, with_aux_fit)
Initialize the kpoint environment.
Types and basic routines needed for a kpoint calculation.
subroutine, public kpoint_sym_create(kp_sym)
Create a single kpoint symmetry environment.
integer function, public find_kpoint_rotation_slot(qs_kpoint, rotp)
Locate the basis-rotation slot corresponding to a signed k-point symmetry operation.
subroutine, public kpoint_env_create(kp_env)
Create a single kpoint environment.
subroutine, public get_kpoint_info(kpoint, kp_scheme, nkp_grid, kp_shift, symmetry, verbose, full_grid, use_real_wfn, eps_geo, parallel_group_size, kp_range, nkp, xkp, wkp, para_env, blacs_env_all, para_env_kp, para_env_inter_kp, blacs_env, kp_env, kp_aux_env, mpools, iogrp, nkp_groups, kp_dist, cell_to_index, index_to_cell, sab_nl, sab_nl_nosym, inversion_symmetry_only, symmetry_backend, symmetry_reduction_method, gamma_centered, lattice_fft)
Retrieve information from a kpoint environment.
Crystal-symmetry routines originating from the K290/ACMI code.
An array-based list which grows on demand. When the internal array is full, a new array of twice the ...
integer, parameter, public local_gemm_pu_gpu
integer, parameter, public local_gemm_pu_host
Definition of mathematical constants and functions.
complex(kind=dp), parameter, public z_one
real(kind=dp), parameter, public twopi
complex(kind=dp), parameter, public z_zero
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.
Utility routines for the memory handling.
Interface to the message passing library MPI.
basic linear algebra operations for full matrixes
Define the data structure for the particle information.
wrapper for the pools of matrixes
subroutine, public mpools_create(mpools)
creates a mpools
subroutine, public mpools_rebuild_fm_pools(mpools, mos, blacs_env, para_env, nmosub)
rebuilds the pools of the (ao x mo, ao x ao , mo x mo) full matrixes
subroutine, public mpools_get(mpools, ao_mo_fm_pools, ao_ao_fm_pools, mo_mo_fm_pools, ao_mosub_fm_pools, mosub_mosub_fm_pools, maxao_maxmo_fm_pool, maxao_maxao_fm_pool, maxmo_maxmo_fm_pool)
returns various attributes of the mpools (notably the pools contained in it)
Definition and initialisation of the mo data type.
subroutine, public set_mo_set(mo_set, maxocc, homo, lfomo, nao, nelectron, n_el_f, nmo, eigenvalues, occupation_numbers, uniform_occupation, kts, mu, flexible_electron_count)
Set the components of a MO set data structure.
subroutine, public init_mo_set(mo_set, fm_pool, fm_ref, fm_struct, name, counter, complex_coeff)
initializes an allocated mo_set. eigenvalues, mo_coeff, occupation_numbers are valid only after this ...
subroutine, public allocate_mo_set(mo_set, nao, nmo, nelectron, n_el_f, maxocc, flexible_electron_count)
Allocates a mo set and partially initializes it (nao,nmo,nelectron, and flexible_electron_count are v...
subroutine, public get_mo_set(mo_set, maxocc, homo, lfomo, nao, nelectron, n_el_f, nmo, eigenvalues, occupation_numbers, mo_coeff, mo_coeff_b, uniform_occupation, kts, mu, flexible_electron_count, cmo_coeff)
Get the components of a MO set data structure.
Define the neighbor list data types and the corresponding functionality.
subroutine, public neighbor_list_iterator_create(iterator_set, nl, search, nthread)
Neighbor list iterator functions.
subroutine, public neighbor_list_iterator_release(iterator_set)
...
subroutine, public get_neighbor_list_set_p(neighbor_list_sets, nlist, symmetric)
Return the components of the first neighbor list set.
integer function, public neighbor_list_iterate(iterator_set, mepos)
...
subroutine, public get_iterator_info(iterator_set, mepos, ikind, jkind, nkind, ilist, nlist, inode, nnode, iatom, jatom, r, cell)
...
parameters that control an scf iteration
Unified smearing module supporting four methods: smear_fermi_dirac — Fermi-Dirac distribution smear_g...
subroutine, public smearkp(f, mu, kts, e, nel, wk, sigma, maxocc, method)
Bisection search for mu given a target electron count (k-point case, single spin channel or spin-dege...
subroutine, public smearkp2(f, mu, kts, e, nel, wk, sigma, method)
Bisection search for mu (k-point, spin-polarised with a shared chemical potential across both spin ch...
All kind of helpful little routines.
pure integer function, dimension(2), public get_limit(m, n, me)
divide m entries into n parts, return size of part me
Type defining parameters related to the simulation cell.
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
Represent a complex full matrix.
to create arrays of pools
keeps the information about the structure of a full matrix
Stores the state of a copy between cp_fm_start_copy_general and cp_fm_finish_copy_general.
just to build arrays of pointers to matrices
Rotation matrices for basis sets.
Keeps information about a specific k-point.
Keeps symmetry information about a specific k-point.
Contains information about kpoints.
stores all the informations relevant to an mpi environment
container for the pools of matrixes used by qs
contains the parameters needed by a scf run