29 dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, dbcsr_type_symmetric
87#include "./base/base_uses.f90"
92 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'qs_wannier90'
93 INTEGER,
PARAMETER,
PRIVATE :: w90_kpoints_mp_grid = 0, &
96 TYPE berry_matrix_type
97 TYPE(dbcsr_p_type),
DIMENSION(:, :),
POINTER :: sinmat => null(), cosmat => null()
98 END TYPE berry_matrix_type
117 CHARACTER(len=*),
PARAMETER :: routinen =
'wannier90_interface'
119 INTEGER :: handle, iw
125 CALL timeset(routinen, handle)
127 subsection_name=
"DFT%PRINT%WANNIER90")
134 WRITE (iw,
'(/,T2,A)') &
135 '!-----------------------------------------------------------------------------!'
136 WRITE (iw,
'(T32,A)')
"Interface to Wannier90"
137 WRITE (iw,
'(T2,A)') &
138 '!-----------------------------------------------------------------------------!'
141 CALL wannier90_files(qs_env, w_input, iw)
144 WRITE (iw,
'(/,T2,A)') &
145 '!--------------------------------End of Wannier90-----------------------------!'
148 CALL timestop(handle)
158 SUBROUTINE wannier90_files(qs_env, input, iw)
161 INTEGER,
INTENT(IN) :: iw
163 INTEGER,
PARAMETER :: num_nnmax = 12
165 CHARACTER(len=2) :: asym
166 CHARACTER(len=20),
ALLOCATABLE,
DIMENSION(:) :: atom_symbols
167 CHARACTER(len=default_string_length) :: filename, input_kp_scheme, reuse_reason, &
169 CHARACTER(LEN=timestamp_length) :: timestamp
170 INTEGER :: aligned_degenerate_blocks, aligned_degenerate_max_size, i, i_rep, ib, ib1, ib2, &
171 ibs, ik, ik2, ikk, ikpgr, ispin, iunit, ix, iy, iz, k, kpoints_source, n_rep, nadd, nao, &
172 nbs, nexcl, nkp, nmo, nntot, nspins, num_atoms, num_bands, num_bands_tot, num_kpts, &
174 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: exclude_bands
175 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: nblist, nnlist
176 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: nncell
177 INTEGER,
DIMENSION(2) :: kp_range
178 INTEGER,
DIMENSION(3) :: input_nkp_grid, mp_grid
179 INTEGER,
DIMENSION(:),
POINTER :: invals
180 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
181 LOGICAL :: diis_step, do_kpoints, full_mesh_diagonalized, gamma_only, input_full_grid, &
182 input_gamma_centered, input_kpoint_symmetry, mp_grid_explicit, mp_grid_valid, my_kpgrp, &
183 mygrp, reuse_scf_mos, reused_scf_mos, spinors, use_bloch_phases, validate_reuse_ok, &
184 validate_reuse_scf_mos
185 REAL(kind=
dp) :: aligned_degenerate_min_svalue, cmmn, gauge_arg, gauge_imag, gauge_real, &
186 gauge_tmp, ksign, reuse_candidate_deviation, reuse_candidate_metric_deviation, &
187 reuse_candidate_min_svalue, reuse_candidate_residual, rmmn, &
188 validation_eigenvalue_deviation, validation_min_svalue, validation_subspace_deviation, &
190 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigval
191 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: atoms_cart, b_latt, kpt_latt
192 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: reference_eigenvalues
193 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :, :) :: reference_mo_imag, reference_mo_real
194 REAL(kind=
dp),
DIMENSION(3) :: bvec, input_kp_shift, phase_center
195 REAL(kind=
dp),
DIMENSION(3, 3) :: h_inv, real_lattice, recip_lattice
196 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues, wkp, wkp_source
197 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: xkp, xkp_source
198 TYPE(berry_matrix_type),
DIMENSION(:),
POINTER :: berry_matrix
201 TYPE(
cp_cfm_type) :: fmk1_cfm, fmk2_cfm, mmn_cfm, omat_cfm, &
205 TYPE(
cp_fm_type) :: mat_imag, mat_real, mmn_imag, mmn_real
207 TYPE(
cp_fm_type),
POINTER :: fmdummy, fmi, fmr
208 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_ks, matrix_s
209 TYPE(
dbcsr_type),
POINTER :: cmatrix, cmatrix_full, rmatrix, &
236 reuse_scf_mos = reuse_scf_mos .AND. kpoints_source == w90_kpoints_scf
237 validate_reuse_scf_mos = validate_reuse_scf_mos .AND. reuse_scf_mos
238 mp_grid(1:3) = invals(1:3)
244 nexcl = nexcl +
SIZE(invals)
247 ALLOCATE (exclude_bands(nexcl))
251 exclude_bands(nexcl + 1:nexcl +
SIZE(invals)) = invals(:)
252 nexcl = nexcl +
SIZE(invals)
258 CALL get_cell(cell, h=real_lattice, h_inv=h_inv)
260 CALL get_qs_env(qs_env, particle_set=particle_set)
262 phase_center = 0.0_dp
263 DO i = 1,
SIZE(particle_set)
264 phase_center(1:3) = phase_center(1:3) + matmul(h_inv, particle_set(i)%r)
266 phase_center(1:3) = phase_center(1:3)/real(
SIZE(particle_set), kind=
dp)
267 phase_center(1:3) = phase_center(1:3) - floor(phase_center(1:3))
268 recip_lattice(1:3, 1:3) = h_inv(1:3, 1:3)
269 real_lattice(1:3, 1:3) =
angstrom*real_lattice(1:3, 1:3)
270 recip_lattice(1:3, 1:3) = (
twopi/
angstrom)*transpose(recip_lattice(1:3, 1:3))
271 NULLIFY (kpoint, qs_kpoint, xkp, wkp, xkp_source, wkp_source)
272 CALL get_qs_env(qs_env, do_kpoints=do_kpoints, kpoints=qs_kpoint)
273 input_kpoint_symmetry = .false.
274 input_full_grid = .false.
276 IF (do_kpoints .AND.
ASSOCIATED(qs_kpoint))
THEN
277 CALL get_kpoint_info(qs_kpoint, kp_scheme=input_kp_scheme, nkp_grid=input_nkp_grid, &
278 kp_shift=input_kp_shift, symmetry=input_kpoint_symmetry, &
279 full_grid=input_full_grid, gamma_centered=input_gamma_centered, &
280 nkp=nkp, xkp=xkp, wkp=wkp)
284 SELECT CASE (kpoints_source)
285 CASE (w90_kpoints_mp_grid)
286 num_kpts = mp_grid(1)*mp_grid(2)*mp_grid(3)
287 ALLOCATE (kpt_latt(3, num_kpts))
288 kpoint%kp_scheme =
"MONKHORST-PACK"
289 kpoint%symmetry = .false.
290 kpoint%nkp_grid(1:3) = mp_grid(1:3)
291 kpoint%verbose = .false.
292 kpoint%full_grid = .true.
293 kpoint%eps_geo = 1.0e-6_dp
294 kpoint%use_real_wfn = .false.
295 kpoint%parallel_group_size = para_env%num_pe
297 DO ix = 0, mp_grid(1) - 1
298 DO iy = 0, mp_grid(2) - 1
299 DO iz = 0, mp_grid(3) - 1
301 kpt_latt(1, i) = real(ix, kind=
dp)/real(mp_grid(1), kind=
dp)
302 kpt_latt(2, i) = real(iy, kind=
dp)/real(mp_grid(2), kind=
dp)
303 kpt_latt(3, i) = real(iz, kind=
dp)/real(mp_grid(3), kind=
dp)
307 kpoint%nkp = num_kpts
308 ALLOCATE (kpoint%xkp(3, num_kpts), kpoint%wkp(num_kpts))
309 kpoint%wkp(:) = 1._dp/real(num_kpts, kind=
dp)
311 kpoint%xkp(1:3, i) = (
angstrom/
twopi)*matmul(recip_lattice, kpt_latt(:, i))
314 CASE (w90_kpoints_scf)
315 IF (.NOT. do_kpoints .OR. .NOT.
ASSOCIATED(qs_kpoint))
THEN
316 cpabort(
"WANNIER90%KPOINTS_SOURCE SCF requires an active DFT%KPOINTS section.")
318 SELECT CASE (trim(input_kp_scheme))
322 ALLOCATE (kpt_latt(3, num_kpts))
323 kpt_latt(1:3, 1) = 0.0_dp
324 kpoint%kp_scheme =
"GAMMA"
325 kpoint%symmetry = .false.
326 kpoint%verbose = .false.
327 kpoint%full_grid = .true.
328 kpoint%eps_geo = 1.0e-6_dp
329 kpoint%use_real_wfn = .false.
330 kpoint%parallel_group_size = para_env%num_pe
331 kpoint%nkp = num_kpts
332 ALLOCATE (kpoint%xkp(3, num_kpts), kpoint%wkp(num_kpts))
333 kpoint%xkp(1:3, 1) = 0.0_dp
334 kpoint%wkp(1) = 1.0_dp
336 CASE (
"MONKHORST-PACK",
"MACDONALD")
337 mp_grid(1:3) = input_nkp_grid(1:3)
338 kpoint%kp_scheme = input_kp_scheme
339 kpoint%symmetry = .false.
340 kpoint%nkp_grid(1:3) = input_nkp_grid(1:3)
341 kpoint%kp_shift(1:3) = input_kp_shift(1:3)
342 kpoint%gamma_centered = input_gamma_centered
343 kpoint%verbose = .false.
344 kpoint%full_grid = .true.
345 kpoint%eps_geo = 1.0e-6_dp
346 kpoint%use_real_wfn = .false.
347 kpoint%parallel_group_size = para_env%num_pe
349 num_kpts = kpoint%nkp
350 ALLOCATE (kpt_latt(3, num_kpts))
351 kpt_latt(1:3, 1:num_kpts) = kpoint%xkp(1:3, 1:num_kpts)
352 IF (input_kpoint_symmetry .AND. .NOT. input_full_grid .AND. iw > 0)
THEN
353 WRITE (iw,
'(T2,A)') &
354 "WANNIER90| SCF k-points are symmetry-reduced; regenerating the full SCF mesh."
355 IF (reuse_scf_mos)
THEN
356 WRITE (iw,
'(T2,A)') &
357 "WANNIER90| CP2K will try to reconstruct the full-mesh MOs from the SCF orbitals."
359 WRITE (iw,
'(T2,A)') &
360 "WANNIER90| The full exported mesh is diagonalized for the Wannier90 files."
365 IF (
ASSOCIATED(qs_kpoint%xkp_input))
THEN
366 xkp_source => qs_kpoint%xkp_input
367 wkp_source => qs_kpoint%wkp_input
372 IF (.NOT.
ASSOCIATED(xkp_source) .OR. .NOT.
ASSOCIATED(wkp_source))
THEN
373 cpabort(
"Could not access the SCF GENERAL k-point set for the Wannier90 export.")
375 num_kpts =
SIZE(wkp_source)
376 ALLOCATE (kpt_latt(3, num_kpts))
377 kpt_latt(1:3, 1:num_kpts) = xkp_source(1:3, 1:num_kpts)
378 IF (mp_grid_explicit)
THEN
379 IF (mp_grid(1)*mp_grid(2)*mp_grid(3) /= num_kpts)
THEN
380 cpabort(
"WANNIER90%MP_GRID must contain exactly as many points as the SCF GENERAL mesh.")
383 CALL infer_wannier_mp_grid(kpt_latt, mp_grid, mp_grid_valid)
384 IF (.NOT. mp_grid_valid)
THEN
385 cpabort(
"Could not infer WANNIER90%MP_GRID from the SCF GENERAL mesh.")
388 wkp_ref = 1.0_dp/real(num_kpts, kind=
dp)
390 IF (abs(wkp_source(i) - wkp_ref) > 1.0e-10_dp)
THEN
391 cpabort(
"WANNIER90%KPOINTS_SOURCE SCF requires equally weighted GENERAL k-points.")
394 kpoint%kp_scheme =
"GENERAL"
395 kpoint%symmetry = .false.
396 kpoint%nkp_grid(1:3) = mp_grid(1:3)
397 kpoint%verbose = .false.
398 kpoint%full_grid = .true.
399 kpoint%eps_geo = 1.0e-6_dp
400 kpoint%use_real_wfn = .false.
401 kpoint%parallel_group_size = para_env%num_pe
402 kpoint%nkp = num_kpts
403 ALLOCATE (kpoint%xkp(3, num_kpts), kpoint%wkp(num_kpts))
404 kpoint%xkp(1:3, 1:num_kpts) = xkp_source(1:3, 1:num_kpts)
405 kpoint%wkp(1:num_kpts) = wkp_ref
406 IF (input_kpoint_symmetry .AND. .NOT. input_full_grid .AND. iw > 0)
THEN
407 WRITE (iw,
'(T2,A)') &
408 "WANNIER90| SCF k-points are symmetry-reduced; using the full input GENERAL mesh."
409 IF (reuse_scf_mos)
THEN
410 WRITE (iw,
'(T2,A)') &
411 "WANNIER90| CP2K will try to reconstruct the full-mesh MOs from the SCF orbitals."
413 WRITE (iw,
'(T2,A)') &
414 "WANNIER90| The full exported mesh is diagonalized for the Wannier90 files."
419 cpabort(
"WANNIER90%KPOINTS_SOURCE SCF does not support this DFT%KPOINTS scheme.")
422 cpabort(
"Unknown WANNIER90%KPOINTS_SOURCE setting.")
426 CALL get_mo_set(mo_set=mos(1), nao=nao, nmo=num_bands_tot)
427 num_bands_tot = min(nao, num_bands_tot + nadd)
428 num_bands = num_bands_tot
429 IF (use_bloch_phases .AND. num_wann /= num_bands)
THEN
430 cpabort(
"WANNIER90%USE_BLOCH_PHASES requires WANNIER_FUNCTIONS to match the number of bands.")
432 num_atoms =
SIZE(particle_set)
433 ALLOCATE (atoms_cart(3, num_atoms))
434 ALLOCATE (atom_symbols(num_atoms))
436 atoms_cart(1:3, i) = particle_set(i)%r(1:3)
438 atom_symbols(i) = asym
443 ALLOCATE (nnlist(num_kpts, num_nnmax))
444 ALLOCATE (nncell(3, num_kpts, num_nnmax))
451 CALL wannier_setup(mp_grid, num_kpts, real_lattice, recip_lattice, &
452 kpt_latt, nntot, nnlist, nncell, iw)
456 CALL para_env%sum(nntot)
457 CALL para_env%sum(nnlist)
458 CALL para_env%sum(nncell)
460 IF (para_env%is_source())
THEN
462 WRITE (filename,
'(A,A)') trim(seed_name),
".win"
463 CALL open_file(filename, unit_number=iunit, file_status=
"UNKNOWN", file_action=
"WRITE")
466 WRITE (iunit,
"(A)")
"! Wannier90 input file generated by CP2K "
467 WRITE (iunit,
"(A,/)")
"! Creation date "//timestamp
469 WRITE (iunit,
"(A,I5)")
"num_wann = ", num_wann
470 IF (num_bands /= num_wann .OR. use_bloch_phases)
THEN
471 WRITE (iunit,
"(A,I5)")
"num_bands = ", num_bands
473 IF (use_bloch_phases)
THEN
476 WRITE (iunit,
"(A)")
"! CP2K writes identity projections for Bloch-phase complete subspaces."
478 WRITE (iunit,
"(/,A,/)")
"length_unit = bohr "
479 WRITE (iunit,
"(/,A,/)")
"! System"
480 WRITE (iunit,
"(/,A)")
"begin unit_cell_cart"
481 WRITE (iunit,
"(A)")
"bohr"
483 WRITE (iunit,
"(3F12.6)") cell%hmat(i, 1:3)
485 WRITE (iunit,
"(A,/)")
"end unit_cell_cart"
486 WRITE (iunit,
"(/,A)")
"begin atoms_cart"
487 WRITE (iunit,
"(A)")
"bohr"
489 WRITE (iunit,
"(A,3F15.10)") atom_symbols(i), atoms_cart(1:3, i)
491 WRITE (iunit,
"(A,/)")
"end atoms_cart"
492 WRITE (iunit,
"(/,A,/)")
"! Kpoints"
493 WRITE (iunit,
"(/,A,3I6/)")
"mp_grid = ", mp_grid(1:3)
494 WRITE (iunit,
"(A)")
"begin kpoints"
496 WRITE (iunit,
"(3F12.6)") kpt_latt(1:3, i)
498 WRITE (iunit,
"(A)")
"end kpoints"
500 IF (use_bloch_phases)
THEN
501 WRITE (filename,
'(A,A)') trim(seed_name),
".amn"
502 CALL open_file(filename, unit_number=iunit, file_status=
"UNKNOWN", file_action=
"WRITE")
503 WRITE (iunit,
"(A)")
"! Wannier90 identity projections generated by CP2K"
504 WRITE (iunit,
"(3I8)") num_bands, num_kpts, num_wann
507 DO ib1 = 1, num_bands
509 WRITE (iunit,
"(3I8,2E30.14)") ib1, ib2, ik, 1.0_dp, 0.0_dp
511 WRITE (iunit,
"(3I8,2E30.14)") ib1, ib2, ik, 0.0_dp, 0.0_dp
524 IF (kpoints_source == w90_kpoints_mp_grid .AND. input_kpoint_symmetry .AND. iw > 0)
THEN
525 WRITE (iw,
'(T2,A)') &
526 "WANNIER90| Atomic k-point symmetry from the SCF calculation is not reused."
527 WRITE (iw,
'(T2,A)') &
528 "WANNIER90| A full Monkhorst-Pack grid is generated for the Wannier90 interface."
539 WRITE (unit=iw, fmt=
"(/,T2,A)")
"Start K-Point Calculation ..."
541 CALL get_qs_env(qs_env=qs_env_kp, para_env=para_env, blacs_env=blacs_env)
546 CALL get_qs_env(qs_env=qs_env_kp, sab_orb=sab_nl, dft_control=dft_control)
549 CALL get_qs_env(qs_env=qs_env_kp, matrix_ks_kp=matrix_ks, matrix_s_kp=matrix_s, &
550 scf_env=scf_env, scf_control=scf_control)
551 full_mesh_diagonalized = .false.
552 reused_scf_mos = .false.
554 aligned_degenerate_blocks = 0
555 aligned_degenerate_max_size = 0
556 aligned_degenerate_min_svalue = 0.0_dp
557 IF (reuse_scf_mos)
THEN
559 CALL do_general_diag_kp(matrix_ks, matrix_s, qs_kpoint, scf_env, scf_control, .false., &
561 IF (validate_reuse_scf_mos)
THEN
563 WRITE (iw,
'(T2,A)') &
564 "WANNIER90| Validating SCF MO reuse against a full-mesh diagonalization reference."
566 CALL do_general_diag_kp(matrix_ks, matrix_s, kpoint, scf_env, scf_control, .false., diis_step)
567 full_mesh_diagonalized = .true.
568 nspins = dft_control%nspins
569 CALL save_wannier90_mo_snapshot(kpoint, nspins, para_env, reference_mo_real, &
570 reference_mo_imag, reference_eigenvalues)
571 CALL diagnose_wannier90_scf_reuse_candidates(kpoint, qs_kpoint, matrix_s, matrix_ks, &
572 cell_to_index, sab_nl, para_env, iw, &
573 reuse_candidate_deviation, &
574 reuse_candidate_min_svalue, &
575 reuse_candidate_metric_deviation, &
576 reuse_candidate_residual)
577 IF (iw > 0 .AND. reuse_candidate_deviation < 1.0e100_dp)
THEN
578 WRITE (iw,
'(T2,A,ES10.3,A,ES10.3,A,ES10.3,A,ES10.3)') &
579 "WANNIER90| Best atom/AO candidate subspace deviation ", &
580 reuse_candidate_deviation,
", minimum singular value ", &
581 reuse_candidate_min_svalue,
", max metric deviation ", &
582 reuse_candidate_metric_deviation,
", max residual ", reuse_candidate_residual
586 sab_nl, para_env, reused_scf_mos, reuse_reason, &
587 aligned_degenerate_blocks, aligned_degenerate_max_size, &
588 aligned_degenerate_min_svalue)
589 IF (validate_reuse_scf_mos)
THEN
590 IF (reused_scf_mos)
THEN
591 CALL validate_wannier90_reused_mos(kpoint, matrix_s, cell_to_index, sab_nl, &
592 para_env, reference_mo_real, reference_mo_imag, &
593 reference_eigenvalues, validate_reuse_ok, &
594 validation_subspace_deviation, validation_min_svalue, &
595 validation_eigenvalue_deviation)
597 WRITE (iw,
'(T2,A,ES10.3,A,ES10.3,A,ES10.3)') &
598 "WANNIER90| Reused MO validation: subspace deviation ", &
599 validation_subspace_deviation,
", minimum singular value ", &
600 validation_min_svalue,
", eigenvalue deviation ", &
601 validation_eigenvalue_deviation
603 IF (.NOT. validate_reuse_ok)
THEN
604 reused_scf_mos = .false.
605 WRITE (reuse_reason,
"(A,ES10.3,A,ES10.3)") &
606 "validation failed: dS=", &
607 validation_subspace_deviation,
", dE=", validation_eigenvalue_deviation
610 IF (.NOT. reused_scf_mos)
THEN
611 CALL restore_wannier90_mo_snapshot(kpoint, reference_mo_real, reference_mo_imag, &
612 reference_eigenvalues)
616 IF (reused_scf_mos)
THEN
617 WRITE (iw,
'(T2,A)') &
618 "WANNIER90| Reused SCF MO coefficients for the Wannier90 full k-point mesh."
619 IF (use_bloch_phases)
THEN
620 WRITE (iw,
'(T2,A)') &
621 "WANNIER90| Wrote identity projections for Bloch-phase complete band subspaces."
622 WRITE (iw,
'(T2,A,3F10.6)') &
623 "WANNIER90| Applied Bloch phase gauge to reused overlaps around fractional center", &
626 IF (aligned_degenerate_blocks > 0)
THEN
627 WRITE (iw,
'(T2,A,I0,A,I0,A,ES10.3)') &
628 "WANNIER90| Ritz-stabilized ", aligned_degenerate_blocks, &
629 " degenerate SCF MO subspace(s) with S(k),H(k); largest block has ", &
630 aligned_degenerate_max_size,
" band(s), min metric eigenvalue ", &
631 aligned_degenerate_min_svalue
634 WRITE (iw,
'(T2,A,A)') &
635 "WANNIER90| Could not reuse SCF MOs: ", trim(reuse_reason)
636 WRITE (iw,
'(T2,A)') &
637 "WANNIER90| Falling back to full-mesh diagonalization for the Wannier90 files."
641 IF (.NOT. reused_scf_mos .AND. .NOT. full_mesh_diagonalized)
THEN
642 CALL do_general_diag_kp(matrix_ks, matrix_s, kpoint, scf_env, scf_control, .false., diis_step)
644 IF (
ALLOCATED(reference_mo_real))
DEALLOCATE (reference_mo_real)
645 IF (
ALLOCATED(reference_mo_imag))
DEALLOCATE (reference_mo_imag)
646 IF (
ALLOCATED(reference_eigenvalues))
DEALLOCATE (reference_eigenvalues)
649 WRITE (iw,
'(T69,A)')
"... Finished"
654 IF (para_env%is_source())
THEN
655 WRITE (filename,
'(A,A)') trim(seed_name),
".mmn"
656 CALL open_file(filename, unit_number=iunit, file_status=
"UNKNOWN", file_action=
"WRITE")
658 WRITE (iunit,
"(A)")
"! Wannier90 file generated by CP2K "//timestamp
659 WRITE (iunit,
"(3I8)") num_bands, num_kpts, nntot
665 ALLOCATE (nblist(num_kpts, nntot))
666 ALLOCATE (b_latt(3, num_kpts*nntot))
671 bvec(1:3) = kpt_latt(1:3, nnlist(ik, i)) - kpt_latt(1:3, ik) + nncell(1:3, ik, i)
674 IF (sum(abs(bvec(1:3) - b_latt(1:3, k))) < 1.e-6_dp)
THEN
678 IF (sum(abs(bvec(1:3) + b_latt(1:3, k))) < 1.e-6_dp)
THEN
689 b_latt(1:3, nbs) = bvec(1:3)
695 ALLOCATE (berry_matrix(nbs))
697 NULLIFY (berry_matrix(i)%cosmat)
698 NULLIFY (berry_matrix(i)%sinmat)
699 bvec(1:3) =
twopi*matmul(transpose(cell%h_inv(1:3, 1:3)), b_latt(1:3, i))
701 berry_matrix(i)%sinmat, bvec)
704 kp => kpoint%kp_env(1)%kpoint_env
706 NULLIFY (matrix_struct_ao, matrix_struct_work)
726 NULLIFY (matrix_struct_mmn)
735 ALLOCATE (rmatrix, cmatrix, rmatrix_full, cmatrix_full)
736 CALL dbcsr_create(rmatrix, template=matrix_s(1, 1)%matrix, &
737 matrix_type=dbcsr_type_symmetric)
738 CALL dbcsr_create(cmatrix, template=matrix_s(1, 1)%matrix, &
739 matrix_type=dbcsr_type_antisymmetric)
740 CALL dbcsr_create(rmatrix_full, template=matrix_s(1, 1)%matrix, &
741 matrix_type=dbcsr_type_no_symmetry)
742 CALL dbcsr_create(cmatrix_full, template=matrix_s(1, 1)%matrix, &
743 matrix_type=dbcsr_type_no_symmetry)
749 nspins = dft_control%nspins
754 my_kpgrp = (ik >= kpoint%kp_range(1) .AND. ik <= kpoint%kp_range(2))
756 ikk = ik - kpoint%kp_range(1) + 1
757 kp => kpoint%kp_env(ikk)%kpoint_env
758 cpassert(
SIZE(kp%mos, 1) == 2)
759 fmr => kp%mos(1, ispin)%mo_coeff
760 fmi => kp%mos(2, ispin)%mo_coeff
764 NULLIFY (fmr, fmi, kp)
773 mygrp = (ik2 >= kpoint%kp_range(1) .AND. ik2 <= kpoint%kp_range(2))
775 ikk = ik2 - kpoint%kp_range(1) + 1
776 kp => kpoint%kp_env(ikk)%kpoint_env
777 cpassert(
SIZE(kp%mos, 1) == 2)
778 fmr => kp%mos(1, ispin)%mo_coeff
779 fmi => kp%mos(2, ispin)%mo_coeff
783 NULLIFY (fmr, fmi, kp)
791 ksign = sign(1.0_dp, real(ibs, kind=
dp))
795 CALL rskp_transform(rmatrix, cmatrix, rsmat=berry_matrix(ibs)%cosmat, ispin=1, &
796 xkp=kpoint%xkp(1:3, ik2), cell_to_index=cell_to_index, sab_nl=sab_nl, &
797 is_complex=.false., rs_sign=ksign)
798 CALL rskp_transform(cmatrix, rmatrix, rsmat=berry_matrix(ibs)%sinmat, ispin=1, &
799 xkp=kpoint%xkp(1:3, ik2), cell_to_index=cell_to_index, sab_nl=sab_nl, &
800 is_complex=.true., rs_sign=ksign)
808 CALL cp_cfm_gemm(
"N",
"N", nao, nmo, nao, cmplx(1.0_dp, 0.0_dp, kind=
dp), &
809 omat_cfm, fmk2_cfm, cmplx(0.0_dp, 0.0_dp, kind=
dp), tmp_cfm)
810 CALL cp_cfm_gemm(
"C",
"N", nmo, nmo, nao, cmplx(1.0_dp, 0.0_dp, kind=
dp), &
811 fmk1_cfm, tmp_cfm, cmplx(0.0_dp, 0.0_dp, kind=
dp), mmn_cfm)
815 IF (reused_scf_mos .AND. use_bloch_phases)
THEN
817 gauge_arg =
twopi*dot_product(kpoint%xkp(1:3, ik2) - kpoint%xkp(1:3, ik), &
819 gauge_real = cos(gauge_arg)
820 gauge_imag = sin(gauge_arg)
825 IF (para_env%is_source())
THEN
826 WRITE (iunit,
"(2I8,3I5)") ik, ik2, nncell(1:3, ik, i)
832 gauge_tmp = gauge_real*rmmn - gauge_imag*cmmn
833 cmmn = gauge_imag*rmmn + gauge_real*cmmn
835 IF (para_env%is_source())
THEN
836 WRITE (iunit,
"(2E30.14)") rmmn, cmmn
848 DEALLOCATE (berry_matrix)
870 IF (para_env%is_source())
THEN
877 nspins = dft_control%nspins
878 kp => kpoint%kp_env(1)%kpoint_env
880 ALLOCATE (eigval(nmo))
882 IF (para_env%is_source())
THEN
883 WRITE (filename,
'(A,A)') trim(seed_name),
".eig"
884 CALL open_file(filename, unit_number=iunit, file_status=
"UNKNOWN", file_action=
"WRITE")
890 my_kpgrp = (ik >= kp_range(1) .AND. ik <= kp_range(2))
893 ikpgr = ik - kp_range(1) + 1
894 kp => kpoint%kp_env(ikpgr)%kpoint_env
895 CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues)
896 eigval(1:nmo) = eigenvalues(1:nmo)
898 eigval(1:nmo) = 0.0_dp
900 CALL kpoint%para_env_inter_kp%sum(eigval)
901 eigval(1:nmo) = eigval(1:nmo)*
evolt
905 WRITE (iunit,
"(2I8,F24.14)") ib, ik, eigval(ib)
910 IF (para_env%is_source())
THEN
915 DEALLOCATE (kpt_latt, atoms_cart, atom_symbols, eigval)
916 DEALLOCATE (nnlist, nncell)
917 DEALLOCATE (nblist, b_latt)
919 DEALLOCATE (exclude_bands)
925 DEALLOCATE (qs_env_kp)
931 END SUBROUTINE wannier90_files
949 sab_nl, para_env, success, reason, aligned_degenerate_blocks, &
950 aligned_degenerate_max_size, &
951 aligned_degenerate_min_svalue)
953 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s, matrix_ks
954 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
958 LOGICAL,
INTENT(OUT) :: success
959 CHARACTER(LEN=*),
INTENT(OUT) :: reason
960 INTEGER,
INTENT(OUT) :: aligned_degenerate_blocks, &
961 aligned_degenerate_max_size
962 REAL(kind=
dp),
INTENT(OUT) :: aligned_degenerate_min_svalue
964 CHARACTER(LEN=default_string_length) :: best_reason, candidate_reason
965 INTEGER :: aligned_blocks, aligned_max_size, candidate_aligned_blocks, &
966 candidate_aligned_max_size, ik, ikpgr, ikred, ispin, isym_try, min_gap_band, &
967 min_gap_kpoint, min_gap_spin, nao, nao_src, nmo, nmo_src, nspins, nsymmetry, &
969 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: source_kpoint, sym_index
970 INTEGER,
DIMENSION(2) :: kp_range, source_kp_range
971 LOGICAL :: my_kpgrp, my_source_kpgrp, ok, &
973 REAL(kind=
dp) :: aligned_min_svalue, band_gap, best_residual, candidate_residual, &
974 degenerate_band_tol, local_min_band_gap, min_band_gap, source_owner_count, &
975 source_window_min_svalue
976 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues_buffer, occupation_buffer, &
977 source_eigenvalues_buffer, &
978 source_occupation_buffer
979 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues, occupation
982 TYPE(
cp_fm_type) :: dst_imag, dst_imag_full, dst_real, &
983 dst_real_full, src_imag, &
984 src_imag_full, src_real, src_real_full
985 TYPE(
cp_fm_type),
POINTER :: dst_fmi, dst_fmr, src_fmi, src_fmr
991 aligned_degenerate_blocks = 0
992 aligned_degenerate_max_size = 0
993 aligned_degenerate_min_svalue = huge(1.0_dp)
994 NULLIFY (matrix_struct_source, matrix_struct_work, src_fmr, src_fmi, dst_fmr, dst_fmi)
996 IF (.NOT.
ASSOCIATED(kpoint))
THEN
997 reason =
"internal Wannier90 k-point object is not available"
1000 IF (.NOT.
ASSOCIATED(qs_kpoint))
THEN
1001 reason =
"SCF k-point object is not available"
1004 IF (.NOT.
ASSOCIATED(kpoint%kp_env) .OR. .NOT.
ASSOCIATED(qs_kpoint%kp_env))
THEN
1005 reason =
"k-point MO environments are not initialized"
1008 IF (.NOT.
ASSOCIATED(kpoint%blacs_env))
THEN
1009 reason =
"Wannier90 k-point BLACS environment is not initialized"
1013 CALL build_wannier90_scf_mapping(kpoint, qs_kpoint, source_kpoint, sym_index, ok, reason)
1014 IF (.NOT. ok)
RETURN
1015 nsymmetry = count(sym_index > 0)
1017 kp => kpoint%kp_env(1)%kpoint_env
1018 nspins =
SIZE(kp%mos, 2)
1019 IF (
SIZE(kp%mos, 1) < 2)
THEN
1020 reason =
"Wannier90 export k-point MOs are not complex-valued"
1021 DEALLOCATE (source_kpoint, sym_index)
1024 CALL get_mo_set(kp%mos(1, 1), nao=nao, nmo=nmo)
1026 kp_source => qs_kpoint%kp_env(1)%kpoint_env
1027 IF (
SIZE(kp_source%mos, 1) < 2)
THEN
1028 reason =
"SCF MOs are real-valued; complex symmetry phases cannot be reconstructed"
1029 DEALLOCATE (source_kpoint, sym_index)
1032 CALL get_mo_set(kp_source%mos(1, 1), nao=nao_src, nmo=nmo_src)
1033 CALL para_env%max(nao_src)
1034 CALL para_env%max(nmo_src)
1035 IF (nao_src /= nao)
THEN
1036 reason =
"SCF and Wannier90 MO bases have different AO dimensions"
1037 DEALLOCATE (source_kpoint, sym_index)
1040 IF (nmo_src < nmo)
THEN
1041 reason =
"SCF MO set has fewer bands than the Wannier90 export"
1042 DEALLOCATE (source_kpoint, sym_index)
1045 source_window = nmo_src > nmo
1046 degenerate_band_tol = 1.0e-8_dp
1048 IF (source_kp_range(1) /= 1 .OR. source_kp_range(2) /= qs_kpoint%nkp)
THEN
1049 reason =
"SCF k-point symmetry data are distributed over k-point parallel groups"
1050 DEALLOCATE (source_kpoint, sym_index)
1056 IF (nsymmetry > 0 .AND. nmo_src > nmo)
THEN
1057 local_min_band_gap = huge(1.0_dp)
1061 DO ikred = source_kp_range(1), source_kp_range(2)
1062 ikpgr = ikred - source_kp_range(1) + 1
1063 kp_source => qs_kpoint%kp_env(ikpgr)%kpoint_env
1064 DO ispin = 1, nspins
1065 CALL get_mo_set(kp_source%mos(1, ispin), eigenvalues=eigenvalues)
1066 band_gap = abs(eigenvalues(nmo + 1) - eigenvalues(nmo))
1067 IF (band_gap < local_min_band_gap)
THEN
1068 local_min_band_gap = band_gap
1070 min_gap_kpoint = ikred
1071 min_gap_spin = ispin
1075 min_band_gap = local_min_band_gap
1076 CALL para_env%min(min_band_gap)
1077 IF (abs(local_min_band_gap - min_band_gap) > degenerate_band_tol*epsilon(1.0_dp))
THEN
1081 CALL para_env%max(min_gap_kpoint)
1082 CALL para_env%max(min_gap_spin)
1083 CALL para_env%max(min_gap_band)
1084 IF (min_band_gap < degenerate_band_tol)
THEN
1085 WRITE (reason,
"(A,ES9.2,A,I0,A,I0,A,I0)") &
1086 "degenerate atom/AO W90 reuse guarded: edge gap=", min_band_gap,
", k=", &
1087 min_gap_kpoint,
", s=", min_gap_spin,
", nband=", min_gap_band
1088 DEALLOCATE (source_kpoint, sym_index)
1092 blacs_env => kpoint%blacs_env
1094 para_env=para_env, context=blacs_env)
1099 IF (source_window)
THEN
1101 para_env=para_env, context=blacs_env)
1107 ALLOCATE (eigenvalues_buffer(nmo), occupation_buffer(nmo), &
1108 source_eigenvalues_buffer(nmo_src), source_occupation_buffer(nmo_src))
1113 DO ik = 1, kpoint%nkp
1114 ikred = source_kpoint(ik)
1115 my_kpgrp = (ik >= kp_range(1) .AND. ik <= kp_range(2))
1116 my_source_kpgrp = (ikred >= source_kp_range(1) .AND. ikred <= source_kp_range(2))
1117 DO ispin = 1, nspins
1118 source_eigenvalues_buffer(1:nmo_src) = 0.0_dp
1119 source_occupation_buffer(1:nmo_src) = 0.0_dp
1120 IF (my_source_kpgrp)
THEN
1121 ikpgr = ikred - source_kp_range(1) + 1
1122 kp_source => qs_kpoint%kp_env(ikpgr)%kpoint_env
1123 src_fmr => kp_source%mos(1, ispin)%mo_coeff
1124 src_fmi => kp_source%mos(2, ispin)%mo_coeff
1125 CALL get_mo_set(kp_source%mos(1, ispin), eigenvalues=eigenvalues, &
1126 occupation_numbers=occupation)
1127 source_eigenvalues_buffer(1:nmo_src) = eigenvalues(1:nmo_src)
1128 source_occupation_buffer(1:nmo_src) = occupation(1:nmo_src)
1130 NULLIFY (src_fmr, src_fmi)
1132 IF (my_source_kpgrp)
THEN
1133 source_owner_count = 1.0_dp
1135 source_owner_count = 0.0_dp
1137 CALL para_env%sum(source_owner_count)
1138 CALL para_env%sum(source_eigenvalues_buffer)
1139 CALL para_env%sum(source_occupation_buffer)
1140 IF (source_owner_count > 0.0_dp)
THEN
1141 source_eigenvalues_buffer(1:nmo_src) = &
1142 source_eigenvalues_buffer(1:nmo_src)/source_owner_count
1143 source_occupation_buffer(1:nmo_src) = &
1144 source_occupation_buffer(1:nmo_src)/source_owner_count
1146 eigenvalues_buffer(1:nmo) = source_eigenvalues_buffer(1:nmo)
1147 occupation_buffer(1:nmo) = source_occupation_buffer(1:nmo)
1148 IF (source_window)
THEN
1151 CALL copy_wannier90_mo_window(src_real_full, src_real, nmo)
1152 CALL copy_wannier90_mo_window(src_imag_full, src_imag, nmo)
1161 aligned_max_size = 0
1162 aligned_min_svalue = 0.0_dp
1163 IF (sym_index(ik) > 0)
THEN
1164 kpsym => qs_kpoint%kp_sym(ikred)%kpoint_sym
1165 IF (
ASSOCIATED(
kpsym))
THEN
1167 best_residual = huge(1.0_dp)
1170 DO isym_try = 1,
kpsym%nwred
1171 IF (.NOT. same_periodic_kpoint(kpoint%xkp(1:3, ik), &
1172 kpsym%xkp(1:3, isym_try))) cycle
1173 num_candidates = num_candidates + 1
1174 CALL transform_wannier90_scf_mo(src_real, src_imag, dst_real, dst_imag, &
1175 qs_kpoint, ikred, isym_try, para_env, ok, &
1178 reason = candidate_reason
1181 CALL ritz_stabilize_wannier90_subspace(dst_real, dst_imag, matrix_s, matrix_ks, &
1182 kpoint%xkp(1:3, ik), cell_to_index, &
1183 sab_nl, ispin, eigenvalues_buffer, &
1184 degenerate_band_tol, ok, candidate_reason, &
1185 candidate_aligned_blocks, &
1186 candidate_aligned_max_size, &
1187 aligned_min_svalue, candidate_residual)
1188 IF (candidate_residual < best_residual)
THEN
1189 best_residual = candidate_residual
1190 best_reason = candidate_reason
1193 IF (source_window)
THEN
1194 CALL transform_wannier90_scf_mo(src_real_full, src_imag_full, &
1195 dst_real_full, dst_imag_full, qs_kpoint, &
1196 ikred, isym_try, para_env, ok, candidate_reason)
1198 CALL ritz_reconstruct_wannier90_window(dst_real_full, dst_imag_full, &
1199 dst_real, dst_imag, matrix_s, &
1200 matrix_ks, kpoint%xkp(1:3, ik), &
1201 cell_to_index, sab_nl, ispin, &
1202 eigenvalues_buffer, nmo, ok, &
1203 candidate_reason, source_window_min_svalue, &
1205 IF (candidate_residual < best_residual)
THEN
1206 best_residual = candidate_residual
1207 best_reason = candidate_reason
1211 CALL ritz_reconstruct_wannier90_window(dst_real, dst_imag, dst_real, &
1212 dst_imag, matrix_s, matrix_ks, &
1213 kpoint%xkp(1:3, ik), cell_to_index, &
1214 sab_nl, ispin, eigenvalues_buffer, nmo, &
1215 ok, candidate_reason, source_window_min_svalue, &
1217 IF (candidate_residual < best_residual)
THEN
1218 best_residual = candidate_residual
1219 best_reason = candidate_reason
1224 aligned_blocks = candidate_aligned_blocks
1225 aligned_max_size = candidate_aligned_max_size
1226 sym_index(ik) = isym_try
1229 reason = candidate_reason
1231 IF (.NOT. ok .AND. num_candidates > 0 .AND. best_residual < huge(1.0_dp))
THEN
1232 WRITE (reason,
"(A,I0,A,ES9.2,A,I0,A,A32)") &
1233 "atom/AO W90 guarded: best/", num_candidates,
"=", best_residual, &
1234 " k=", ik,
" ", trim(best_reason)
1235 ELSEIF (.NOT. ok .AND. num_candidates == 0)
THEN
1236 reason =
"no matching SCF symmetry operation candidate"
1239 reason =
"SCF k-point symmetry operation is not available"
1242 CALL transform_wannier90_scf_mo(src_real, src_imag, dst_real, dst_imag, qs_kpoint, &
1243 ikred, sym_index(ik), para_env, ok, reason)
1245 IF (ok .AND. sym_index(ik) <= 0)
THEN
1248 CALL ritz_stabilize_wannier90_subspace(dst_real, dst_imag, matrix_s, matrix_ks, &
1249 kpoint%xkp(1:3, ik), cell_to_index, sab_nl, &
1250 ispin, eigenvalues_buffer, degenerate_band_tol, &
1251 ok, reason, aligned_blocks, aligned_max_size, &
1252 aligned_min_svalue, candidate_residual)
1253 IF (.NOT. ok .AND. source_window)
THEN
1254 CALL transform_wannier90_scf_mo(src_real_full, src_imag_full, dst_real_full, &
1255 dst_imag_full, qs_kpoint, ikred, sym_index(ik), &
1256 para_env, ok, reason)
1258 CALL ritz_reconstruct_wannier90_window(dst_real_full, dst_imag_full, dst_real, &
1259 dst_imag, matrix_s, matrix_ks, &
1260 kpoint%xkp(1:3, ik), cell_to_index, &
1261 sab_nl, ispin, eigenvalues_buffer, nmo, ok, &
1262 reason, source_window_min_svalue, &
1265 ELSEIF (.NOT. ok)
THEN
1266 CALL ritz_reconstruct_wannier90_window(dst_real, dst_imag, dst_real, dst_imag, &
1267 matrix_s, matrix_ks, kpoint%xkp(1:3, ik), &
1268 cell_to_index, sab_nl, ispin, &
1269 eigenvalues_buffer, nmo, ok, reason, &
1270 source_window_min_svalue, candidate_residual)
1279 IF (source_window)
THEN
1286 DEALLOCATE (source_kpoint, sym_index, eigenvalues_buffer, occupation_buffer, &
1287 source_eigenvalues_buffer, source_occupation_buffer)
1290 IF (sym_index(ik) /= 0)
THEN
1291 aligned_degenerate_blocks = aligned_degenerate_blocks + aligned_blocks
1292 aligned_degenerate_max_size = max(aligned_degenerate_max_size, aligned_max_size)
1293 IF (aligned_blocks > 0)
THEN
1294 aligned_degenerate_min_svalue = min(aligned_degenerate_min_svalue, aligned_min_svalue)
1299 ikpgr = ik - kp_range(1) + 1
1300 kp => kpoint%kp_env(ikpgr)%kpoint_env
1301 dst_fmr => kp%mos(1, ispin)%mo_coeff
1302 dst_fmi => kp%mos(2, ispin)%mo_coeff
1303 CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues, &
1304 occupation_numbers=occupation)
1305 eigenvalues(1:nmo) = eigenvalues_buffer(1:nmo)
1306 occupation(1:nmo) = occupation_buffer(1:nmo)
1307 CALL get_mo_set(kp%mos(2, ispin), eigenvalues=eigenvalues, &
1308 occupation_numbers=occupation)
1309 IF (
ASSOCIATED(eigenvalues)) eigenvalues(1:nmo) = eigenvalues_buffer(1:nmo)
1310 IF (
ASSOCIATED(occupation)) occupation(1:nmo) = occupation_buffer(1:nmo)
1312 NULLIFY (dst_fmr, dst_fmi)
1324 IF (source_window)
THEN
1331 DEALLOCATE (source_kpoint, sym_index, eigenvalues_buffer, occupation_buffer, &
1332 source_eigenvalues_buffer, source_occupation_buffer)
1333 IF (aligned_degenerate_blocks == 0) aligned_degenerate_min_svalue = 0.0_dp
1347 SUBROUTINE save_wannier90_mo_snapshot(kpoint, nspins, para_env, mo_real, mo_imag, &
1348 eigenvalue_snapshot)
1350 INTEGER,
INTENT(IN) :: nspins
1352 REAL(kind=
dp),
ALLOCATABLE, &
1353 DIMENSION(:, :, :, :),
INTENT(OUT) :: mo_real, mo_imag
1354 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :), &
1355 INTENT(OUT) :: eigenvalue_snapshot
1357 INTEGER :: ik, ikpgr, ispin, nao, nkp, nmo
1358 INTEGER,
DIMENSION(2) :: kp_range
1359 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: owner_weight
1360 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues
1365 kp => kpoint%kp_env(1)%kpoint_env
1366 CALL get_mo_set(kp%mos(1, 1), nao=nao, nmo=nmo)
1367 ALLOCATE (mo_real(nao, nmo, nkp, nspins), mo_imag(nao, nmo, nkp, nspins), &
1368 eigenvalue_snapshot(nmo, nkp, nspins), owner_weight(nkp, nspins))
1369 mo_real(:, :, :, :) = 0.0_dp
1370 mo_imag(:, :, :, :) = 0.0_dp
1371 eigenvalue_snapshot(:, :, :) = 0.0_dp
1372 owner_weight(:, :) = 0.0_dp
1373 DO ik = kp_range(1), kp_range(2)
1374 ikpgr = ik - kp_range(1) + 1
1375 kp => kpoint%kp_env(ikpgr)%kpoint_env
1376 DO ispin = 1, nspins
1377 fmr => kp%mos(1, ispin)%mo_coeff
1378 fmi => kp%mos(2, ispin)%mo_coeff
1381 CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues)
1382 eigenvalue_snapshot(1:nmo, ik, ispin) = eigenvalues(1:nmo)
1383 owner_weight(ik, ispin) = 1.0_dp
1386 CALL para_env%sum(mo_real)
1387 CALL para_env%sum(mo_imag)
1388 CALL para_env%sum(eigenvalue_snapshot)
1389 CALL para_env%sum(owner_weight)
1391 DO ispin = 1, nspins
1392 IF (owner_weight(ik, ispin) > 0.0_dp)
THEN
1393 mo_real(:, :, ik, ispin) = mo_real(:, :, ik, ispin)/owner_weight(ik, ispin)
1394 mo_imag(:, :, ik, ispin) = mo_imag(:, :, ik, ispin)/owner_weight(ik, ispin)
1395 eigenvalue_snapshot(:, ik, ispin) = &
1396 eigenvalue_snapshot(:, ik, ispin)/owner_weight(ik, ispin)
1400 DEALLOCATE (owner_weight)
1402 END SUBROUTINE save_wannier90_mo_snapshot
1411 SUBROUTINE restore_wannier90_mo_snapshot(kpoint, mo_real, mo_imag, eigenvalue_snapshot)
1413 REAL(kind=
dp),
DIMENSION(:, :, :, :),
INTENT(IN) :: mo_real, mo_imag
1414 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: eigenvalue_snapshot
1416 INTEGER :: ik, ikpgr, ispin, nmo, nspins
1417 INTEGER,
DIMENSION(2) :: kp_range
1418 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues
1423 nmo =
SIZE(eigenvalue_snapshot, 1)
1424 nspins =
SIZE(eigenvalue_snapshot, 3)
1425 DO ik = kp_range(1), kp_range(2)
1426 ikpgr = ik - kp_range(1) + 1
1427 kp => kpoint%kp_env(ikpgr)%kpoint_env
1428 DO ispin = 1, nspins
1429 fmr => kp%mos(1, ispin)%mo_coeff
1430 fmi => kp%mos(2, ispin)%mo_coeff
1433 CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues)
1434 eigenvalues(1:nmo) = eigenvalue_snapshot(1:nmo, ik, ispin)
1435 CALL get_mo_set(kp%mos(2, ispin), eigenvalues=eigenvalues)
1436 IF (
ASSOCIATED(eigenvalues)) eigenvalues(1:nmo) = eigenvalue_snapshot(1:nmo, ik, ispin)
1440 END SUBROUTINE restore_wannier90_mo_snapshot
1457 SUBROUTINE validate_wannier90_reused_mos(kpoint, matrix_s, cell_to_index, sab_nl, para_env, &
1458 reference_mo_real, reference_mo_imag, reference_eigenvalues, &
1459 success, max_subspace_deviation, min_svalue, &
1460 max_eigenvalue_deviation)
1462 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s
1463 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
1467 REAL(kind=
dp),
DIMENSION(:, :, :, :),
INTENT(IN) :: reference_mo_real, reference_mo_imag
1468 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: reference_eigenvalues
1469 LOGICAL,
INTENT(OUT) :: success
1470 REAL(kind=
dp),
INTENT(OUT) :: max_subspace_deviation, min_svalue, &
1471 max_eigenvalue_deviation
1473 REAL(kind=
dp),
PARAMETER :: eigenvalue_tol = 1.0e-8_dp, &
1474 subspace_tol = 1.0e-4_dp
1476 INTEGER :: ik, ikpgr, ispin, nao, nkp, nmo, nspins
1477 INTEGER,
DIMENSION(2) :: kp_range
1478 LOGICAL :: my_kpgrp, ok
1479 REAL(kind=
dp) :: candidate_deviation, candidate_svalue, &
1481 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalue_buffer
1482 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues
1484 TYPE(
cp_fm_type) :: cand_imag, cand_real, ref_imag, ref_real
1489 max_subspace_deviation = 0.0_dp
1490 min_svalue = huge(1.0_dp)
1491 max_eigenvalue_deviation = 0.0_dp
1492 NULLIFY (matrix_struct_work, fmr, fmi)
1495 kp => kpoint%kp_env(1)%kpoint_env
1496 nspins =
SIZE(kp%mos, 2)
1497 CALL get_mo_set(kp%mos(1, 1), nao=nao, nmo=nmo)
1498 cpassert(
SIZE(reference_mo_real, 1) == nao)
1499 cpassert(
SIZE(reference_mo_real, 2) == nmo)
1500 cpassert(
SIZE(reference_mo_real, 3) == nkp)
1501 cpassert(
SIZE(reference_mo_real, 4) == nspins)
1503 CALL cp_fm_get_info(kp%mos(1, 1)%mo_coeff, matrix_struct=matrix_struct_work)
1508 ALLOCATE (eigenvalue_buffer(nmo))
1510 DO ispin = 1, nspins
1514 my_kpgrp = (ik >= kp_range(1) .AND. ik <= kp_range(2))
1516 ikpgr = ik - kp_range(1) + 1
1517 kp => kpoint%kp_env(ikpgr)%kpoint_env
1518 fmr => kp%mos(1, ispin)%mo_coeff
1519 fmi => kp%mos(2, ispin)%mo_coeff
1520 CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues)
1521 eigenvalue_buffer(1:nmo) = eigenvalues(1:nmo)
1524 eigenvalue_buffer(1:nmo) = 0.0_dp
1529 owner_count = 1.0_dp
1531 owner_count = 0.0_dp
1533 CALL para_env%sum(owner_count)
1534 CALL para_env%sum(eigenvalue_buffer)
1535 IF (owner_count > 0.0_dp) eigenvalue_buffer(1:nmo) = eigenvalue_buffer(1:nmo)/owner_count
1536 max_eigenvalue_deviation = max(max_eigenvalue_deviation, &
1537 maxval(abs(eigenvalue_buffer(1:nmo) - &
1538 reference_eigenvalues(1:nmo, ik, ispin))))
1539 CALL measure_wannier90_subspace_error(ref_real, ref_imag, cand_real, cand_imag, matrix_s, &
1540 kpoint%xkp(1:3, ik), cell_to_index, sab_nl, para_env, &
1541 ok, candidate_deviation, candidate_svalue)
1543 max_subspace_deviation = huge(1.0_dp)
1545 max_subspace_deviation = max(max_subspace_deviation, candidate_deviation)
1546 min_svalue = min(min_svalue, candidate_svalue)
1550 CALL para_env%max(max_subspace_deviation)
1551 CALL para_env%min(min_svalue)
1552 CALL para_env%max(max_eigenvalue_deviation)
1553 success = max_subspace_deviation < subspace_tol .AND. max_eigenvalue_deviation < eigenvalue_tol
1555 DEALLOCATE (eigenvalue_buffer)
1561 END SUBROUTINE validate_wannier90_reused_mos
1578 SUBROUTINE diagnose_wannier90_scf_reuse_candidates(kpoint, qs_kpoint, matrix_s, matrix_ks, &
1579 cell_to_index, sab_nl, para_env, iw, &
1580 max_subspace_deviation, min_svalue, &
1581 max_metric_deviation, max_residual)
1583 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s, matrix_ks
1584 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
1588 INTEGER,
INTENT(IN) :: iw
1589 REAL(kind=
dp),
INTENT(OUT) :: max_subspace_deviation, min_svalue, &
1590 max_metric_deviation, max_residual
1592 REAL(kind=
dp),
PARAMETER :: print_tol = 1.0e-4_dp, &
1593 residual_print_tol = 1.0e-3_dp
1595 CHARACTER(LEN=default_string_length) :: reason
1596 INTEGER :: ik, ikpgr, ikred, ispin, isym_try, nao, &
1597 nao_src, nkp, nmo, nmo_src, nspins
1598 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: source_kpoint, sym_index
1599 INTEGER,
DIMENSION(2) :: kp_range, source_kp_range
1600 LOGICAL :: my_kpgrp, ok, source_window
1601 REAL(kind=
dp) :: best_deviation, best_metric_deviation, best_residual, best_svalue, &
1602 candidate_deviation, candidate_metric_deviation, candidate_metric_min, &
1603 candidate_residual, candidate_svalue, owner_count, ref_metric_deviation, ref_metric_min, &
1605 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues_buffer
1606 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues
1608 TYPE(
cp_fm_type) :: dst_imag, dst_real, ref_imag, ref_real, &
1609 src_imag, src_imag_full, src_real, &
1611 TYPE(
cp_fm_type),
POINTER :: fmi, fmr, src_fmi, src_fmr
1615 max_subspace_deviation = huge(1.0_dp)
1617 max_metric_deviation = huge(1.0_dp)
1618 max_residual = huge(1.0_dp)
1619 NULLIFY (matrix_struct_source, matrix_struct_work, fmi, fmr, src_fmi, src_fmr)
1621 CALL build_wannier90_scf_mapping(kpoint, qs_kpoint, source_kpoint, sym_index, ok, reason)
1622 IF (.NOT. ok)
RETURN
1623 kp => kpoint%kp_env(1)%kpoint_env
1624 kp_source => qs_kpoint%kp_env(1)%kpoint_env
1625 IF (
SIZE(kp%mos, 1) < 2 .OR.
SIZE(kp_source%mos, 1) < 2)
THEN
1626 DEALLOCATE (source_kpoint, sym_index)
1629 nspins =
SIZE(kp%mos, 2)
1630 CALL get_mo_set(kp%mos(1, 1), nao=nao, nmo=nmo)
1631 CALL get_mo_set(kp_source%mos(1, 1), nao=nao_src, nmo=nmo_src)
1632 CALL para_env%max(nao_src)
1633 CALL para_env%max(nmo_src)
1634 IF (nao_src /= nao .OR. nmo_src < nmo)
THEN
1635 DEALLOCATE (source_kpoint, sym_index)
1638 source_window = nmo_src > nmo
1641 IF (source_kp_range(1) /= 1 .OR. source_kp_range(2) /= qs_kpoint%nkp)
THEN
1642 DEALLOCATE (source_kpoint, sym_index)
1647 para_env=para_env, context=kpoint%blacs_env)
1654 ALLOCATE (eigenvalues_buffer(nmo))
1655 IF (source_window)
THEN
1657 para_env=para_env, context=kpoint%blacs_env)
1662 max_subspace_deviation = 0.0_dp
1663 min_svalue = huge(1.0_dp)
1664 max_metric_deviation = 0.0_dp
1665 max_residual = 0.0_dp
1666 DO ispin = 1, nspins
1668 my_kpgrp = (ik >= kp_range(1) .AND. ik <= kp_range(2))
1670 ikpgr = ik - kp_range(1) + 1
1671 kp => kpoint%kp_env(ikpgr)%kpoint_env
1672 fmr => kp%mos(1, ispin)%mo_coeff
1673 fmi => kp%mos(2, ispin)%mo_coeff
1680 ikred = source_kpoint(ik)
1681 my_kpgrp = (ikred >= source_kp_range(1) .AND. ikred <= source_kp_range(2))
1683 ikpgr = ikred - source_kp_range(1) + 1
1684 kp_source => qs_kpoint%kp_env(ikpgr)%kpoint_env
1685 src_fmr => kp_source%mos(1, ispin)%mo_coeff
1686 src_fmi => kp_source%mos(2, ispin)%mo_coeff
1687 CALL get_mo_set(kp_source%mos(1, ispin), eigenvalues=eigenvalues)
1688 eigenvalues_buffer(1:nmo) = eigenvalues(1:nmo)
1690 NULLIFY (src_fmr, src_fmi)
1691 eigenvalues_buffer(1:nmo) = 0.0_dp
1694 owner_count = 1.0_dp
1696 owner_count = 0.0_dp
1698 CALL para_env%sum(owner_count)
1699 CALL para_env%sum(eigenvalues_buffer)
1700 IF (owner_count > 0.0_dp) eigenvalues_buffer(1:nmo) = eigenvalues_buffer(1:nmo)/owner_count
1701 CALL measure_wannier90_eigenspace_quality(ref_real, ref_imag, matrix_s, matrix_ks, &
1702 kpoint%xkp(1:3, ik), cell_to_index, sab_nl, &
1703 para_env, ispin, eigenvalues_buffer, ok, &
1704 ref_metric_deviation, ref_metric_min, ref_residual)
1705 IF (ok .AND. para_env%is_source() .AND. iw > 0 .AND. &
1706 (ref_metric_deviation > print_tol .OR. ref_residual > residual_print_tol))
THEN
1707 WRITE (iw,
'(T2,A,I0,A,ES10.3,A,ES10.3,A,ES10.3)') &
1708 "WANNIER90| reference k=", ik,
" dM=", ref_metric_deviation, &
1709 " smin=", ref_metric_min,
" resid=", ref_residual
1711 IF (source_window)
THEN
1714 CALL copy_wannier90_mo_window(src_real_full, src_real, nmo)
1715 CALL copy_wannier90_mo_window(src_imag_full, src_imag, nmo)
1721 best_deviation = huge(1.0_dp)
1722 best_metric_deviation = 0.0_dp
1723 best_residual = 0.0_dp
1724 best_svalue = 0.0_dp
1725 IF (sym_index(ik) <= 0)
THEN
1726 CALL transform_wannier90_scf_mo(src_real, src_imag, dst_real, dst_imag, qs_kpoint, &
1727 ikred, sym_index(ik), para_env, ok, reason)
1729 CALL measure_wannier90_subspace_error(ref_real, ref_imag, dst_real, dst_imag, matrix_s, &
1730 kpoint%xkp(1:3, ik), cell_to_index, sab_nl, &
1731 para_env, ok, candidate_deviation, candidate_svalue)
1733 CALL measure_wannier90_eigenspace_quality(dst_real, dst_imag, matrix_s, matrix_ks, &
1734 kpoint%xkp(1:3, ik), cell_to_index, sab_nl, &
1735 para_env, ispin, eigenvalues_buffer, ok, &
1736 candidate_metric_deviation, &
1737 candidate_metric_min, candidate_residual)
1740 best_deviation = candidate_deviation
1741 best_metric_deviation = candidate_metric_deviation
1742 best_residual = candidate_residual
1743 best_svalue = candidate_svalue
1744 IF (para_env%is_source() .AND. iw > 0 .AND. &
1745 (candidate_deviation > print_tol .OR. candidate_metric_deviation > print_tol .OR. &
1746 candidate_residual > residual_print_tol))
THEN
1747 WRITE (iw,
'(T2,A,I0,A,I0,A,I0,A,ES10.3,A,ES10.3,A,ES10.3,A,ES10.3)') &
1748 "WANNIER90| reuse candidate k=", ik,
" src=", ikred,
" sym=", &
1749 sym_index(ik),
" dRef=", candidate_deviation,
" dM=", &
1750 candidate_metric_deviation,
" smin=", candidate_metric_min, &
1751 " resid=", candidate_residual
1755 ELSEIF (
ASSOCIATED(qs_kpoint%kp_sym))
THEN
1756 kpsym => qs_kpoint%kp_sym(ikred)%kpoint_sym
1757 IF (
ASSOCIATED(
kpsym))
THEN
1758 DO isym_try = 1,
kpsym%nwred
1759 IF (.NOT. same_periodic_kpoint(kpoint%xkp(1:3, ik), &
1760 kpsym%xkp(1:3, isym_try))) cycle
1761 CALL transform_wannier90_scf_mo(src_real, src_imag, dst_real, dst_imag, &
1762 qs_kpoint, ikred, isym_try, para_env, ok, reason)
1764 CALL measure_wannier90_subspace_error(ref_real, ref_imag, dst_real, dst_imag, &
1765 matrix_s, kpoint%xkp(1:3, ik), cell_to_index, &
1766 sab_nl, para_env, ok, candidate_deviation, &
1769 CALL measure_wannier90_eigenspace_quality(dst_real, dst_imag, matrix_s, matrix_ks, &
1770 kpoint%xkp(1:3, ik), cell_to_index, &
1771 sab_nl, para_env, ispin, &
1772 eigenvalues_buffer, ok, &
1773 candidate_metric_deviation, &
1774 candidate_metric_min, candidate_residual)
1776 IF (ok .AND. candidate_deviation < best_deviation)
THEN
1777 best_deviation = candidate_deviation
1778 best_metric_deviation = candidate_metric_deviation
1779 best_residual = candidate_residual
1780 best_svalue = candidate_svalue
1785 IF (best_deviation < huge(1.0_dp))
THEN
1786 max_subspace_deviation = max(max_subspace_deviation, best_deviation)
1787 min_svalue = min(min_svalue, best_svalue)
1788 max_metric_deviation = max(max_metric_deviation, best_metric_deviation)
1789 max_residual = max(max_residual, best_residual)
1793 CALL para_env%max(max_subspace_deviation)
1794 CALL para_env%min(min_svalue)
1795 CALL para_env%max(max_metric_deviation)
1796 CALL para_env%max(max_residual)
1798 IF (source_window)
THEN
1810 DEALLOCATE (eigenvalues_buffer)
1811 DEALLOCATE (source_kpoint, sym_index)
1813 END SUBROUTINE diagnose_wannier90_scf_reuse_candidates
1830 SUBROUTINE measure_wannier90_subspace_error(ref_real, ref_imag, cand_real, cand_imag, matrix_s, &
1831 xkp, cell_to_index, sab_nl, para_env, success, &
1832 max_subspace_deviation, min_svalue)
1833 TYPE(
cp_fm_type),
INTENT(IN) :: ref_real, ref_imag, cand_real, cand_imag
1834 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s
1835 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
1836 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
1840 LOGICAL,
INTENT(OUT) :: success
1841 REAL(kind=
dp),
INTENT(OUT) :: max_subspace_deviation, min_svalue
1843 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: metric_projected, metric_vectors, &
1844 overlap, ref_coeff, s_cand
1845 INTEGER :: ib, nao, nmo, nmo_candidate
1846 REAL(kind=
dp) :: singular_value
1847 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: metric_values
1848 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: ref_i, ref_r, s_cand_i, s_cand_r
1853 max_subspace_deviation = huge(1.0_dp)
1855 NULLIFY (matrix_struct_metric)
1857 CALL cp_fm_get_info(ref_real, nrow_global=nao, ncol_global=nmo, &
1858 matrix_struct=matrix_struct_metric)
1860 IF (nmo_candidate /= nmo)
RETURN
1864 CALL apply_wannier90_kp_matrix(matrix_s, 1, xkp, cell_to_index, sab_nl, &
1865 cand_real, cand_imag, s_cand_real, s_cand_imag)
1867 ALLOCATE (ref_r(nao, nmo), ref_i(nao, nmo), s_cand_r(nao, nmo), s_cand_i(nao, nmo))
1873 ALLOCATE (ref_coeff(nao, nmo), s_cand(nao, nmo), overlap(nmo, nmo), &
1874 metric_projected(nmo, nmo), metric_vectors(nmo, nmo), metric_values(nmo))
1875 ref_coeff(:, :) = cmplx(ref_r, ref_i, kind=
dp)
1876 s_cand(:, :) = cmplx(s_cand_r, s_cand_i, kind=
dp)
1877 overlap(:, :) = matmul(conjg(transpose(ref_coeff)), s_cand)
1878 metric_projected(:, :) = matmul(conjg(transpose(overlap)), overlap)
1879 metric_projected(:, :) = 0.5_dp*(metric_projected + conjg(transpose(metric_projected)))
1880 CALL diag_complex(metric_projected, metric_vectors, metric_values)
1882 min_svalue = huge(1.0_dp)
1883 max_subspace_deviation = 0.0_dp
1885 singular_value = sqrt(max(metric_values(ib), 0.0_dp))
1886 min_svalue = min(min_svalue, singular_value)
1887 max_subspace_deviation = max(max_subspace_deviation, abs(singular_value - 1.0_dp))
1889 CALL para_env%max(max_subspace_deviation)
1890 CALL para_env%min(min_svalue)
1893 DEALLOCATE (ref_coeff, s_cand, overlap, metric_projected, metric_vectors, metric_values)
1894 DEALLOCATE (ref_r, ref_i, s_cand_r, s_cand_i)
1898 END SUBROUTINE measure_wannier90_subspace_error
1917 SUBROUTINE measure_wannier90_eigenspace_quality(cand_real, cand_imag, matrix_s, matrix_ks, xkp, &
1918 cell_to_index, sab_nl, para_env, ispin, eigenvalues, &
1919 success, metric_deviation, min_metric_eigenvalue, &
1921 TYPE(
cp_fm_type),
INTENT(IN) :: cand_real, cand_imag
1922 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s, matrix_ks
1923 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
1924 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
1928 INTEGER,
INTENT(IN) :: ispin
1929 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: eigenvalues
1930 LOGICAL,
INTENT(OUT) :: success
1931 REAL(kind=
dp),
INTENT(OUT) :: metric_deviation, min_metric_eigenvalue, &
1934 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: cand_coeff, h_coeff, metric_vectors, &
1935 residual_block, s_coeff, s_projected
1936 INTEGER :: ib, nao, nmo
1937 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: metric_values
1938 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: cand_i, cand_r, h_coeff_i, h_coeff_r, &
1939 s_coeff_i, s_coeff_r
1942 matrix_struct_projected
1943 TYPE(
cp_fm_type) :: h_cand_imag, h_cand_real, s_cand_imag, &
1947 metric_deviation = huge(1.0_dp)
1948 min_metric_eigenvalue = 0.0_dp
1949 residual_norm = huge(1.0_dp)
1950 NULLIFY (matrix_struct_metric, matrix_struct_projected)
1952 CALL cp_fm_get_info(cand_real, nrow_global=nao, ncol_global=nmo, &
1953 matrix_struct=matrix_struct_metric)
1954 IF (
SIZE(eigenvalues) < nmo)
RETURN
1964 CALL apply_wannier90_kp_matrix(matrix_s, 1, xkp, cell_to_index, sab_nl, &
1965 cand_real, cand_imag, s_cand_real, s_cand_imag)
1966 CALL apply_wannier90_kp_matrix(matrix_ks, ispin, xkp, cell_to_index, sab_nl, &
1967 cand_real, cand_imag, h_cand_real, h_cand_imag)
1969 ALLOCATE (cand_r(nao, nmo), cand_i(nao, nmo), s_coeff_r(nao, nmo), &
1970 s_coeff_i(nao, nmo), h_coeff_r(nao, nmo), h_coeff_i(nao, nmo))
1978 ALLOCATE (cand_coeff(nao, nmo), h_coeff(nao, nmo), metric_vectors(nmo, nmo), &
1979 residual_block(nao, nmo), s_coeff(nao, nmo), s_projected(nmo, nmo), &
1981 cand_coeff(:, :) = cmplx(cand_r, cand_i, kind=
dp)
1982 s_coeff(:, :) = cmplx(s_coeff_r, s_coeff_i, kind=
dp)
1983 h_coeff(:, :) = cmplx(h_coeff_r, h_coeff_i, kind=
dp)
1985 para_env=matrix_struct_metric%para_env, &
1986 context=matrix_struct_metric%context)
1990 CALL cp_cfm_gemm(
"C",
"N", nmo, nmo, nao, cmplx(1.0_dp, 0.0_dp, kind=
dp), cand_cfm, &
1991 s_cfm, cmplx(0.0_dp, 0.0_dp, kind=
dp), metric_cfm)
1993 s_projected(:, :) = 0.5_dp*(s_projected + conjg(transpose(s_projected)))
1994 CALL diag_complex(s_projected, metric_vectors, metric_values)
1995 metric_deviation = maxval(abs(metric_values - 1.0_dp))
1996 min_metric_eigenvalue = minval(metric_values)
1998 residual_block(:, :) = h_coeff
2000 residual_block(:, ib) = residual_block(:, ib) - eigenvalues(ib)*s_coeff(:, ib)
2002 residual_norm = maxval(abs(residual_block))
2003 CALL para_env%max(metric_deviation)
2004 CALL para_env%min(min_metric_eigenvalue)
2005 CALL para_env%max(residual_norm)
2008 DEALLOCATE (cand_coeff, h_coeff, metric_vectors, residual_block, s_coeff, s_projected, &
2010 DEALLOCATE (cand_r, cand_i, s_coeff_r, s_coeff_i, h_coeff_r, h_coeff_i)
2021 END SUBROUTINE measure_wannier90_eigenspace_quality
2029 SUBROUTINE copy_wannier90_mo_window(source, destination, ncol)
2030 TYPE(
cp_fm_type),
INTENT(IN) :: source, destination
2031 INTEGER,
INTENT(IN) :: ncol
2033 INTEGER :: ncol_source, nrow
2034 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: destination_buffer, source_buffer
2036 CALL cp_fm_get_info(source, nrow_global=nrow, ncol_global=ncol_source)
2037 cpassert(ncol_source >= ncol)
2038 ALLOCATE (source_buffer(nrow, ncol_source), destination_buffer(nrow, ncol))
2040 destination_buffer(1:nrow, 1:ncol) = source_buffer(1:nrow, 1:ncol)
2042 DEALLOCATE (source_buffer, destination_buffer)
2044 END SUBROUTINE copy_wannier90_mo_window
2058 SUBROUTINE apply_wannier90_kp_matrix(rsmat, ispin, xkp, cell_to_index, sab_nl, &
2059 coeff_real, coeff_imag, result_real, result_imag)
2061 INTEGER,
INTENT(IN) :: ispin
2062 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
2063 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
2066 TYPE(
cp_fm_type),
INTENT(IN) :: coeff_real, coeff_imag, result_real, &
2069 INTEGER :: nao, ncol
2070 TYPE(
cp_cfm_type) :: coeff_cfm, kmat_cfm, result_cfm
2073 TYPE(
dbcsr_type),
POINTER :: kmat_imag, kmat_imag_full, kmat_real, &
2076 NULLIFY (matrix_struct_ao, matrix_struct_coeff, kmat_imag, kmat_imag_full, kmat_real, &
2079 CALL cp_fm_get_info(coeff_real, nrow_global=nao, ncol_global=ncol, &
2080 matrix_struct=matrix_struct_coeff)
2082 ALLOCATE (kmat_real, kmat_imag, kmat_real_full, kmat_imag_full)
2083 CALL dbcsr_create(kmat_real, template=rsmat(ispin, 1)%matrix, &
2084 matrix_type=dbcsr_type_symmetric)
2085 CALL dbcsr_create(kmat_imag, template=rsmat(ispin, 1)%matrix, &
2086 matrix_type=dbcsr_type_antisymmetric)
2087 CALL dbcsr_create(kmat_real_full, template=rsmat(ispin, 1)%matrix, &
2088 matrix_type=dbcsr_type_no_symmetry)
2089 CALL dbcsr_create(kmat_imag_full, template=rsmat(ispin, 1)%matrix, &
2090 matrix_type=dbcsr_type_no_symmetry)
2095 CALL rskp_transform(kmat_real, kmat_imag, rsmat=rsmat, ispin=ispin, &
2096 xkp=xkp, cell_to_index=cell_to_index, sab_nl=sab_nl)
2101 para_env=matrix_struct_coeff%para_env, &
2102 context=matrix_struct_coeff%context)
2113 CALL cp_cfm_gemm(
"N",
"N", nao, ncol, nao, cmplx(1.0_dp, 0.0_dp, kind=
dp), kmat_cfm, &
2114 coeff_cfm, cmplx(0.0_dp, 0.0_dp, kind=
dp), result_cfm)
2115 CALL cp_cfm_to_fm(result_cfm, result_real, result_imag)
2128 END SUBROUTINE apply_wannier90_kp_matrix
2149 SUBROUTINE ritz_stabilize_wannier90_subspace(dst_real, dst_imag, matrix_s, matrix_ks, &
2150 xkp, cell_to_index, sab_nl, ispin, eigenvalues, &
2151 degenerate_band_tol, success, reason, aligned_blocks, &
2152 aligned_max_size, aligned_min_svalue, max_residual)
2153 TYPE(
cp_fm_type),
INTENT(IN) :: dst_real, dst_imag
2154 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s, matrix_ks
2155 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
2156 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
2159 INTEGER,
INTENT(IN) :: ispin
2160 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: eigenvalues
2161 REAL(kind=
dp),
INTENT(IN) :: degenerate_band_tol
2162 LOGICAL,
INTENT(OUT) :: success
2163 CHARACTER(LEN=*),
INTENT(OUT) :: reason
2164 INTEGER,
INTENT(OUT) :: aligned_blocks, aligned_max_size
2165 REAL(kind=
dp),
INTENT(OUT) :: aligned_min_svalue, max_residual
2167 REAL(kind=
dp),
PARAMETER :: residual_tol = 1.0e-2_dp
2169 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: block_coeff, h_block, h_coeff, &
2170 h_projected, h_projected_work, metric_vectors, residual_block, ritz_vectors, s_block, &
2171 s_coeff, s_projected, stabilized
2172 INTEGER :: block_first, block_last, block_size, ib, &
2174 REAL(kind=
dp) :: metric_deviation, norm_value, &
2176 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: metric_values, ritz_values
2177 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: dst_i, dst_r, h_coeff_i, h_coeff_r, &
2178 s_coeff_i, s_coeff_r
2180 TYPE(
cp_fm_type) :: h_dst_imag, h_dst_real, s_dst_imag, &
2186 aligned_max_size = 0
2187 aligned_min_svalue = huge(1.0_dp)
2188 max_residual = 0.0_dp
2190 NULLIFY (matrix_struct_metric)
2191 CALL cp_fm_get_info(dst_real, nrow_global=nao, ncol_global=nmo, &
2192 matrix_struct=matrix_struct_metric)
2193 IF (
SIZE(eigenvalues) < nmo)
THEN
2194 reason =
"not enough eigenvalues for Wannier90 Ritz subspace stabilization"
2204 CALL apply_wannier90_kp_matrix(matrix_s, 1, xkp, cell_to_index, sab_nl, &
2205 dst_real, dst_imag, s_dst_real, s_dst_imag)
2206 CALL apply_wannier90_kp_matrix(matrix_ks, ispin, xkp, cell_to_index, sab_nl, &
2207 dst_real, dst_imag, h_dst_real, h_dst_imag)
2209 ALLOCATE (dst_r(nao, nmo), dst_i(nao, nmo), s_coeff_r(nao, nmo), s_coeff_i(nao, nmo), &
2210 h_coeff_r(nao, nmo), h_coeff_i(nao, nmo))
2218 ALLOCATE (s_coeff(nao, nmo), h_coeff(nao, nmo))
2219 s_coeff(:, :) = cmplx(s_coeff_r, s_coeff_i, kind=
dp)
2220 h_coeff(:, :) = cmplx(h_coeff_r, h_coeff_i, kind=
dp)
2223 DO WHILE (block_first <= nmo)
2224 block_last = block_first
2225 DO WHILE (block_last < nmo)
2226 IF (abs(eigenvalues(block_last + 1) - eigenvalues(block_last)) >= degenerate_band_tol)
EXIT
2227 block_last = block_last + 1
2229 block_size = block_last - block_first + 1
2230 IF (block_size > 1)
THEN
2234 ALLOCATE (block_coeff(nao, block_size), h_block(nao, block_size), &
2235 h_projected(block_size, block_size), h_projected_work(block_size, block_size), &
2236 metric_vectors(block_size, block_size), residual_block(nao, block_size), &
2237 ritz_vectors(block_size, block_size), s_block(nao, block_size), &
2238 s_projected(block_size, block_size), stabilized(nao, block_size), &
2239 metric_values(block_size), ritz_values(block_size))
2240 block_coeff(:, :) = cmplx(dst_r(:, block_first:block_last), &
2241 dst_i(:, block_first:block_last), kind=
dp)
2242 s_block(:, :) = s_coeff(:, block_first:block_last)
2243 h_block(:, :) = h_coeff(:, block_first:block_last)
2244 s_projected(:, :) = matmul(conjg(transpose(block_coeff)), s_block)
2245 h_projected(:, :) = matmul(conjg(transpose(block_coeff)), h_block)
2246 s_projected(:, :) = 0.5_dp*(s_projected + conjg(transpose(s_projected)))
2247 h_projected(:, :) = 0.5_dp*(h_projected + conjg(transpose(h_projected)))
2249 CALL diag_complex(s_projected, metric_vectors, metric_values)
2250 aligned_min_svalue = min(aligned_min_svalue, minval(metric_values))
2251 metric_deviation = maxval(abs(metric_values - 1.0_dp))
2252 IF (minval(metric_values) < 1.0e-10_dp)
THEN
2253 WRITE (reason,
"(A,I0,A,ES9.2,A,ES9.2)") &
2254 "singular metric blk=", block_first,
" smin=", minval(metric_values), &
2255 " dS=", metric_deviation
2256 max_residual = huge(1.0_dp)
2257 DEALLOCATE (block_coeff, h_block, h_projected, h_projected_work, metric_vectors, &
2258 residual_block, ritz_vectors, s_block, s_projected, stabilized, &
2259 metric_values, ritz_values)
2260 DEALLOCATE (s_coeff, h_coeff, dst_r, dst_i, s_coeff_r, s_coeff_i, h_coeff_r, &
2270 DO ib = 1, block_size
2271 metric_vectors(:, ib) = metric_vectors(:, ib)/sqrt(metric_values(ib))
2273 h_projected_work(:, :) = matmul(h_projected, metric_vectors)
2274 h_projected(:, :) = matmul(conjg(transpose(metric_vectors)), h_projected_work)
2275 h_projected(:, :) = 0.5_dp*(h_projected + conjg(transpose(h_projected)))
2276 CALL diag_complex(h_projected, ritz_vectors, ritz_values)
2277 h_projected_work(:, :) = matmul(metric_vectors, ritz_vectors)
2278 ritz_vectors(:, :) = h_projected_work
2279 stabilized(:, :) = matmul(block_coeff, ritz_vectors)
2280 residual_block(:, :) = matmul(h_block, ritz_vectors)
2281 h_block(:, :) = residual_block
2282 residual_block(:, :) = matmul(s_block, ritz_vectors)
2283 s_block(:, :) = residual_block
2284 DO ib = 1, block_size
2285 norm_value = sqrt(abs(real(dot_product(stabilized(:, ib), s_block(:, ib)), kind=
dp)))
2286 IF (norm_value > epsilon(1.0_dp))
THEN
2287 stabilized(:, ib) = stabilized(:, ib)/norm_value
2288 h_block(:, ib) = h_block(:, ib)/norm_value
2289 s_block(:, ib) = s_block(:, ib)/norm_value
2292 residual_block(:, :) = h_block
2293 DO ib = 1, block_size
2294 residual_block(:, ib) = residual_block(:, ib) - &
2295 eigenvalues(block_first + ib - 1)*s_block(:, ib)
2297 residual_norm = maxval(abs(residual_block))
2298 max_residual = max(max_residual, residual_norm)
2299 IF (residual_norm > residual_tol)
THEN
2300 WRITE (reason,
"(A,I0,A,ES9.2)") &
2301 "blk=", block_first,
" dS=", metric_deviation
2302 DEALLOCATE (block_coeff, h_block, h_projected, h_projected_work, metric_vectors, &
2303 residual_block, ritz_vectors, s_block, s_projected, stabilized, &
2304 metric_values, ritz_values)
2305 DEALLOCATE (s_coeff, h_coeff, dst_r, dst_i, s_coeff_r, s_coeff_i, h_coeff_r, &
2315 dst_r(:, block_first:block_last) = real(stabilized, kind=
dp)
2316 dst_i(:, block_first:block_last) = aimag(stabilized)
2317 h_coeff(:, block_first:block_last) = h_block
2318 s_coeff(:, block_first:block_last) = s_block
2319 aligned_blocks = aligned_blocks + 1
2320 aligned_max_size = max(aligned_max_size, block_size)
2321 DEALLOCATE (block_coeff, h_block, h_projected, h_projected_work, metric_vectors, &
2322 residual_block, ritz_vectors, s_block, s_projected, stabilized, metric_values, &
2325 block_first = block_last + 1
2329 residual_norm = maxval(abs(h_coeff(:, ib) - eigenvalues(ib)*s_coeff(:, ib)))
2330 max_residual = max(max_residual, residual_norm)
2332 IF (max_residual > residual_tol)
THEN
2333 WRITE (reason,
"(A,ES10.3)") &
2334 "atom/AO W90 reuse guarded: Ritz residual=", max_residual
2335 DEALLOCATE (s_coeff, h_coeff, dst_r, dst_i, s_coeff_r, s_coeff_i, h_coeff_r, h_coeff_i)
2347 IF (aligned_blocks == 0) aligned_min_svalue = 0.0_dp
2350 DEALLOCATE (s_coeff, h_coeff, dst_r, dst_i, s_coeff_r, s_coeff_i, h_coeff_r, h_coeff_i)
2357 END SUBROUTINE ritz_stabilize_wannier90_subspace
2378 SUBROUTINE ritz_reconstruct_wannier90_window(src_real, src_imag, dst_real, dst_imag, matrix_s, &
2379 matrix_ks, xkp, cell_to_index, sab_nl, ispin, &
2380 eigenvalues, nmo_export, success, reason, min_svalue, &
2382 TYPE(
cp_fm_type),
INTENT(IN) :: src_real, src_imag, dst_real, dst_imag
2383 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s, matrix_ks
2384 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
2385 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
2388 INTEGER,
INTENT(IN) :: ispin
2389 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: eigenvalues
2390 INTEGER,
INTENT(IN) :: nmo_export
2391 LOGICAL,
INTENT(OUT) :: success
2392 CHARACTER(LEN=*),
INTENT(OUT) :: reason
2393 REAL(kind=
dp),
INTENT(OUT) :: min_svalue, max_residual
2395 REAL(kind=
dp),
PARAMETER :: eigenvalue_tol = 1.0e-6_dp, &
2396 residual_tol = 1.0e-7_dp
2398 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: coeff_work, h_coeff, h_projected, &
2399 h_projected_work, metric_vectors, residual_block, ritz_vectors, s_coeff, s_projected, &
2400 source_coeff, stabilized
2401 INTEGER :: ib, nao, nmo_source
2402 REAL(kind=
dp) :: max_eigenvalue_shift, metric_deviation, &
2404 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: metric_values, ritz_values, &
2406 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: dst_i, dst_r, h_coeff_i, h_coeff_r, &
2407 s_coeff_i, s_coeff_r, src_i, src_r
2409 TYPE(
cp_fm_type) :: h_src_imag, h_src_real, s_src_imag, &
2414 min_svalue = huge(1.0_dp)
2415 max_residual = huge(1.0_dp)
2417 NULLIFY (matrix_struct_metric)
2418 CALL cp_fm_get_info(src_real, nrow_global=nao, ncol_global=nmo_source, &
2419 matrix_struct=matrix_struct_metric)
2420 IF (nmo_export > nmo_source)
THEN
2421 reason =
"Wannier90 export window is larger than the transformed SCF MO space"
2424 IF (
SIZE(eigenvalues) < nmo_export)
THEN
2425 reason =
"not enough eigenvalue storage for Wannier90 source-window reconstruction"
2435 CALL apply_wannier90_kp_matrix(matrix_s, 1, xkp, cell_to_index, sab_nl, &
2436 src_real, src_imag, s_src_real, s_src_imag)
2437 CALL apply_wannier90_kp_matrix(matrix_ks, ispin, xkp, cell_to_index, sab_nl, &
2438 src_real, src_imag, h_src_real, h_src_imag)
2440 ALLOCATE (src_r(nao, nmo_source), src_i(nao, nmo_source), &
2441 s_coeff_r(nao, nmo_source), s_coeff_i(nao, nmo_source), &
2442 h_coeff_r(nao, nmo_source), h_coeff_i(nao, nmo_source), &
2443 dst_r(nao, nmo_export), dst_i(nao, nmo_export))
2451 ALLOCATE (source_coeff(nao, nmo_source), s_coeff(nao, nmo_source), &
2452 h_coeff(nao, nmo_source), h_projected(nmo_source, nmo_source), &
2453 h_projected_work(nmo_source, nmo_source), metric_vectors(nmo_source, nmo_source), &
2454 residual_block(nao, nmo_export), ritz_vectors(nmo_source, nmo_source), &
2455 s_projected(nmo_source, nmo_source), stabilized(nao, nmo_export), &
2456 coeff_work(nao, nmo_source), metric_values(nmo_source), ritz_values(nmo_source), &
2457 source_eigenvalues(nmo_export))
2458 source_eigenvalues(1:nmo_export) = eigenvalues(1:nmo_export)
2459 source_coeff(:, :) = cmplx(src_r, src_i, kind=
dp)
2460 s_coeff(:, :) = cmplx(s_coeff_r, s_coeff_i, kind=
dp)
2461 h_coeff(:, :) = cmplx(h_coeff_r, h_coeff_i, kind=
dp)
2462 s_projected(:, :) = matmul(conjg(transpose(source_coeff)), s_coeff)
2463 h_projected(:, :) = matmul(conjg(transpose(source_coeff)), h_coeff)
2464 s_projected(:, :) = 0.5_dp*(s_projected + conjg(transpose(s_projected)))
2465 h_projected(:, :) = 0.5_dp*(h_projected + conjg(transpose(h_projected)))
2467 reconstruct_window: block
2468 CALL diag_complex(s_projected, metric_vectors, metric_values)
2469 min_svalue = minval(metric_values)
2470 metric_deviation = maxval(abs(metric_values - 1.0_dp))
2471 IF (min_svalue < 1.0e-10_dp)
THEN
2472 WRITE (reason,
"(A,ES9.2,A,ES9.2)") &
2473 "singular expanded metric smin=", min_svalue,
" dS=", metric_deviation
2474 EXIT reconstruct_window
2477 DO ib = 1, nmo_source
2478 metric_vectors(:, ib) = metric_vectors(:, ib)/sqrt(metric_values(ib))
2480 h_projected_work(:, :) = matmul(h_projected, metric_vectors)
2481 h_projected(:, :) = matmul(conjg(transpose(metric_vectors)), h_projected_work)
2482 h_projected(:, :) = 0.5_dp*(h_projected + conjg(transpose(h_projected)))
2483 CALL diag_complex(h_projected, ritz_vectors, ritz_values)
2484 h_projected_work(:, :) = matmul(metric_vectors, ritz_vectors)
2485 ritz_vectors(:, :) = h_projected_work
2486 stabilized(:, :) = matmul(source_coeff, ritz_vectors(:, 1:nmo_export))
2487 coeff_work(:, :) = matmul(h_coeff, ritz_vectors)
2488 h_coeff(:, :) = coeff_work
2489 coeff_work(:, :) = matmul(s_coeff, ritz_vectors)
2490 s_coeff(:, :) = coeff_work
2491 DO ib = 1, nmo_export
2492 norm_value = sqrt(abs(real(dot_product(stabilized(:, ib), s_coeff(:, ib)), kind=
dp)))
2493 IF (norm_value > epsilon(1.0_dp))
THEN
2494 stabilized(:, ib) = stabilized(:, ib)/norm_value
2495 h_coeff(:, ib) = h_coeff(:, ib)/norm_value
2496 s_coeff(:, ib) = s_coeff(:, ib)/norm_value
2499 residual_block(:, :) = h_coeff(:, 1:nmo_export)
2500 DO ib = 1, nmo_export
2501 residual_block(:, ib) = residual_block(:, ib) - ritz_values(ib)*s_coeff(:, ib)
2503 max_residual = maxval(abs(residual_block))
2504 IF (max_residual > residual_tol)
THEN
2505 WRITE (reason,
"(A,ES9.2)") &
2506 "expanded dS=", metric_deviation
2507 EXIT reconstruct_window
2509 max_eigenvalue_shift = maxval(abs(ritz_values(1:nmo_export) - source_eigenvalues(1:nmo_export)))
2510 IF (max_eigenvalue_shift > eigenvalue_tol)
THEN
2511 WRITE (reason,
"(A,ES9.2)") &
2512 "expanded dS=", metric_deviation
2513 EXIT reconstruct_window
2516 dst_r(:, :) = real(stabilized, kind=
dp)
2517 dst_i(:, :) = aimag(stabilized)
2522 END BLOCK reconstruct_window
2524 DEALLOCATE (source_coeff, s_coeff, h_coeff, h_projected, h_projected_work, metric_vectors, &
2525 residual_block, ritz_vectors, s_projected, stabilized, coeff_work, metric_values, &
2526 ritz_values, source_eigenvalues)
2527 DEALLOCATE (src_r, src_i, s_coeff_r, s_coeff_i, h_coeff_r, h_coeff_i, dst_r, dst_i)
2534 END SUBROUTINE ritz_reconstruct_wannier90_window
2545 SUBROUTINE build_wannier90_scf_mapping(kpoint, qs_kpoint, source_kpoint, sym_index, success, &
2547 TYPE(kpoint_type),
POINTER :: kpoint, qs_kpoint
2548 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: source_kpoint, sym_index
2549 LOGICAL,
INTENT(OUT) :: success
2550 CHARACTER(LEN=*),
INTENT(OUT) :: reason
2552 INTEGER :: ik, ikred, imatch, isym, nfull
2553 TYPE(kpoint_sym_type),
POINTER ::
kpsym
2558 ALLOCATE (source_kpoint(nfull), sym_index(nfull))
2559 source_kpoint(:) = 0
2562 DO ikred = 1, qs_kpoint%nkp
2563 imatch = find_matching_kpoint(kpoint%xkp, qs_kpoint%xkp(1:3, ikred))
2564 IF (imatch > 0 .AND. source_kpoint(imatch) == 0)
THEN
2565 source_kpoint(imatch) = ikred
2566 sym_index(imatch) = 0
2571 DO ikred = 1, qs_kpoint%nkp
2572 imatch = find_matching_kpoint(kpoint%xkp, -qs_kpoint%xkp(1:3, ikred))
2573 IF (imatch > 0 .AND. source_kpoint(imatch) == 0)
THEN
2574 source_kpoint(imatch) = ikred
2575 sym_index(imatch) = -1
2579 IF (
ASSOCIATED(qs_kpoint%kp_sym))
THEN
2580 DO ikred = 1, qs_kpoint%nkp
2581 kpsym => qs_kpoint%kp_sym(ikred)%kpoint_sym
2582 IF (.NOT.
ASSOCIATED(
kpsym)) cycle
2583 IF (.NOT.
kpsym%apply_symmetry) cycle
2584 DO isym = 1,
kpsym%nwred
2585 imatch = find_matching_kpoint(kpoint%xkp,
kpsym%xkp(1:3, isym))
2586 IF (imatch > 0 .AND. source_kpoint(imatch) == 0)
THEN
2587 source_kpoint(imatch) = ikred
2588 sym_index(imatch) = isym
2595 IF (source_kpoint(ik) == 0)
THEN
2596 reason =
"not all full-mesh k-points are represented by the SCF symmetry orbits"
2602 END SUBROUTINE build_wannier90_scf_mapping
2610 INTEGER FUNCTION find_matching_kpoint(xkp_mesh, xkp_search)
RESULT(ik_match)
2611 REAL(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: xkp_mesh
2612 REAL(kind=dp),
DIMENSION(3),
INTENT(IN) :: xkp_search
2617 DO ik = 1,
SIZE(xkp_mesh, 2)
2618 IF (same_periodic_kpoint(xkp_mesh(1:3, ik), xkp_search))
THEN
2624 END FUNCTION find_matching_kpoint
2632 LOGICAL FUNCTION same_periodic_kpoint(xkp_a, xkp_b)
RESULT(same)
2633 REAL(kind=dp),
DIMENSION(3),
INTENT(IN) :: xkp_a, xkp_b
2635 REAL(kind=dp),
DIMENSION(3) :: diff
2637 diff(1:3) = xkp_a(1:3) - xkp_b(1:3)
2638 diff(1:3) = diff(1:3) - real(nint(diff(1:3)), kind=dp)
2639 same = sum(abs(diff(1:3))) < 1.0e-8_dp
2641 END FUNCTION same_periodic_kpoint
2656 SUBROUTINE transform_wannier90_scf_mo(src_real, src_imag, dst_real, dst_imag, qs_kpoint, ikred, &
2657 isym, para_env, success, reason)
2658 TYPE(cp_fm_type),
INTENT(IN) :: src_real, src_imag, dst_real, dst_imag
2659 TYPE(kpoint_type),
POINTER :: qs_kpoint
2660 INTEGER,
INTENT(IN) :: ikred, isym
2661 TYPE(mp_para_env_type),
POINTER :: para_env
2662 LOGICAL,
INTENT(OUT) :: success
2663 CHARACTER(LEN=*),
INTENT(OUT) :: reason
2665 INTEGER :: iao, iatom, ikind, imo, irow, irow_source, irow_target, irow_work, nao, natom, &
2666 nmo, rot_slot, source_atom, source_dim, target_atom, target_dim
2667 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ao_size, ao_start
2668 LOGICAL :: reverse_phase, time_reversal
2669 REAL(kind=dp) :: arg, coeff_imag, coeff_real, coskl, &
2670 phase_imag, phase_real, sinkl
2671 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: dst_i, dst_r, src_i, src_r
2672 REAL(kind=dp),
DIMENSION(3) :: xkp_phase
2673 REAL(kind=dp),
DIMENSION(:, :),
POINTER :: rotmat
2674 TYPE(kind_rotmat_type),
DIMENSION(:),
POINTER :: kind_rot
2675 TYPE(kpoint_sym_type),
POINTER ::
kpsym
2680 CALL cp_fm_copy_general(src_real, dst_real, para_env)
2681 CALL cp_fm_copy_general(src_imag, dst_imag, para_env)
2686 CALL cp_fm_get_info(src_real, nrow_global=nao, ncol_global=nmo)
2687 ALLOCATE (src_r(nao, nmo), src_i(nao, nmo), dst_r(nao, nmo), dst_i(nao, nmo))
2688 CALL cp_fm_get_submatrix(src_real, src_r)
2689 CALL cp_fm_get_submatrix(src_imag, src_i)
2690 dst_r(:, :) = 0.0_dp
2691 dst_i(:, :) = 0.0_dp
2693 IF (isym == -1)
THEN
2694 dst_r(1:nao, 1:nmo) = src_r(1:nao, 1:nmo)
2695 dst_i(1:nao, 1:nmo) = -src_i(1:nao, 1:nmo)
2696 CALL cp_fm_set_submatrix(dst_real, dst_r)
2697 CALL cp_fm_set_submatrix(dst_imag, dst_i)
2698 DEALLOCATE (src_r, src_i, dst_r, dst_i)
2703 IF (.NOT.
ASSOCIATED(qs_kpoint%kp_sym))
THEN
2704 reason =
"SCF symmetry operation data are not available"
2705 DEALLOCATE (src_r, src_i, dst_r, dst_i)
2708 kpsym => qs_kpoint%kp_sym(ikred)%kpoint_sym
2709 IF (.NOT.
ASSOCIATED(
kpsym))
THEN
2710 reason =
"SCF k-point symmetry operation is not available"
2711 DEALLOCATE (src_r, src_i, dst_r, dst_i)
2714 IF (isym >
kpsym%nwred)
THEN
2715 reason =
"SCF k-point symmetry operation index is out of range"
2716 DEALLOCATE (src_r, src_i, dst_r, dst_i)
2719 IF (.NOT.
ASSOCIATED(qs_kpoint%atype) .OR. .NOT.
ASSOCIATED(qs_kpoint%kind_rotmat))
THEN
2720 reason =
"SCF atom mappings or basis rotation matrices are not available"
2721 DEALLOCATE (src_r, src_i, dst_r, dst_i)
2725 rot_slot = find_wannier90_rotation_slot(qs_kpoint,
kpsym%rotp(isym))
2726 IF (rot_slot == 0)
THEN
2727 reason =
"could not match the SCF symmetry operation to a basis rotation"
2728 DEALLOCATE (src_r, src_i, dst_r, dst_i)
2731 kind_rot => qs_kpoint%kind_rotmat(rot_slot, :)
2732 natom =
SIZE(qs_kpoint%atype)
2733 ALLOCATE (ao_start(natom), ao_size(natom))
2736 ikind = qs_kpoint%atype(iatom)
2737 IF (.NOT.
ASSOCIATED(kind_rot(ikind)%rmat))
THEN
2738 reason =
"a required basis rotation matrix is not available"
2739 DEALLOCATE (src_r, src_i, dst_r, dst_i, ao_start, ao_size)
2742 ao_start(iatom) = irow
2743 ao_size(iatom) =
SIZE(kind_rot(ikind)%rmat, 2)
2744 irow = irow + ao_size(iatom)
2746 IF (irow - 1 /= nao)
THEN
2747 reason =
"atom-resolved AO dimensions do not match the MO coefficient matrix"
2748 DEALLOCATE (src_r, src_i, dst_r, dst_i, ao_start, ao_size)
2752 time_reversal =
kpsym%rotp(isym) < 0
2753 reverse_phase = qs_kpoint%gamma_centered .AND. any(mod(qs_kpoint%nkp_grid, 2) == 0)
2754 xkp_phase(1:3) =
kpsym%xkp(1:3, isym)
2757 target_atom =
kpsym%f0(iatom, isym)
2758 ikind = qs_kpoint%atype(source_atom)
2759 rotmat => kind_rot(ikind)%rmat
2760 source_dim = ao_size(source_atom)
2761 target_dim = ao_size(target_atom)
2762 IF (
SIZE(rotmat, 1) /= target_dim .OR.
SIZE(rotmat, 2) /= source_dim)
THEN
2763 reason =
"basis rotation dimensions do not match the atom/AO symmetry transform"
2764 DEALLOCATE (src_r, src_i, dst_r, dst_i, ao_start, ao_size)
2767 arg = real(
kpsym%fcell(1, source_atom, isym), kind=dp)*xkp_phase(1) + &
2768 REAL(
kpsym%fcell(2, source_atom, isym), kind=dp)*xkp_phase(2) + &
2769 REAL(
kpsym%fcell(3, source_atom, isym), kind=dp)*xkp_phase(3)
2770 IF (
ASSOCIATED(
kpsym%kgphase))
THEN
2771 arg = arg +
kpsym%kgphase(source_atom, isym)
2773 IF (reverse_phase) arg = -arg
2774 coskl = cos(twopi*arg)
2775 sinkl = sin(twopi*arg)
2777 DO irow_work = 1, source_dim
2778 irow_source = ao_start(source_atom) + irow_work - 1
2779 coeff_real = src_r(irow_source, imo)
2780 coeff_imag = src_i(irow_source, imo)
2781 IF (time_reversal) coeff_imag = -coeff_imag
2782 phase_real = coskl*coeff_real - sinkl*coeff_imag
2783 phase_imag = sinkl*coeff_real + coskl*coeff_imag
2784 DO iao = 1, target_dim
2785 irow_target = ao_start(target_atom) + iao - 1
2786 dst_r(irow_target, imo) = dst_r(irow_target, imo) + &
2787 rotmat(iao, irow_work)*phase_real
2788 dst_i(irow_target, imo) = dst_i(irow_target, imo) + &
2789 rotmat(iao, irow_work)*phase_imag
2795 CALL cp_fm_set_submatrix(dst_real, dst_r)
2796 CALL cp_fm_set_submatrix(dst_imag, dst_i)
2797 DEALLOCATE (src_r, src_i, dst_r, dst_i, ao_start, ao_size)
2800 END SUBROUTINE transform_wannier90_scf_mo
2808 INTEGER FUNCTION find_wannier90_rotation_slot(qs_kpoint, rotp)
RESULT(rot_slot)
2809 TYPE(kpoint_type),
POINTER :: qs_kpoint
2810 INTEGER,
INTENT(IN) :: rotp
2812 INTEGER :: irot, rot_abs
2816 IF (.NOT.
ASSOCIATED(qs_kpoint%ibrot))
RETURN
2817 DO irot = 1,
SIZE(qs_kpoint%ibrot)
2818 IF (rot_abs == qs_kpoint%ibrot(irot))
THEN
2824 END FUNCTION find_wannier90_rotation_slot
2832 SUBROUTINE infer_wannier_mp_grid(kpt_latt, mp_grid, valid)
2833 REAL(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: kpt_latt
2834 INTEGER,
DIMENSION(3),
INTENT(OUT) :: mp_grid
2835 LOGICAL,
INTENT(OUT) :: valid
2837 INTEGER :: coord_id, i, idim,
idx, n_unique, &
2838 num_kpts, stride, unique_id
2840 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: seen
2841 REAL(kind=dp) :: coord
2842 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: unique_coord
2844 num_kpts =
SIZE(kpt_latt, 2)
2846 ALLOCATE (unique_coord(3, num_kpts))
2850 coord = kpt_latt(idim, i) - floor(kpt_latt(idim, i))
2851 IF (abs(coord - 1.0_dp) < 1.0e-8_dp) coord = 0.0_dp
2853 DO unique_id = 1, n_unique
2854 IF (abs(unique_coord(idim, unique_id) - coord) < 1.0e-8_dp)
THEN
2859 IF (.NOT. known)
THEN
2860 n_unique = n_unique + 1
2861 unique_coord(idim, n_unique) = coord
2864 mp_grid(idim) = n_unique
2866 valid = (mp_grid(1)*mp_grid(2)*mp_grid(3) == num_kpts)
2868 ALLOCATE (seen(num_kpts))
2874 coord = kpt_latt(idim, i) - floor(kpt_latt(idim, i))
2875 IF (abs(coord - 1.0_dp) < 1.0e-8_dp) coord = 0.0_dp
2877 DO unique_id = 1, mp_grid(idim)
2878 IF (abs(unique_coord(idim, unique_id) - coord) < 1.0e-8_dp)
THEN
2879 coord_id = unique_id
2883 cpassert(coord_id > 0)
2884 idx =
idx + (coord_id - 1)*stride
2885 stride = stride*mp_grid(idim)
2887 IF (seen(
idx)) valid = .false.
2890 valid = valid .AND. all(seen)
2893 DEALLOCATE (unique_coord)
2895 END SUBROUTINE infer_wannier_mp_grid
static GRID_HOST_DEVICE int idx(const orbital a)
Return coset index of given orbital angular momentum.
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 get_cell(cell, alpha, beta, gamma, deth, orthorhombic, abc, periodic, h, h_inv, symmetry_id, tag)
Get informations about a simulation cell.
methods related to the blacs parallel environment
Basic linear algebra operations for complex full matrices.
subroutine, public cp_cfm_gemm(transa, transb, m, n, k, alpha, matrix_a, matrix_b, beta, matrix_c, a_first_col, a_first_row, b_first_col, b_first_row, c_first_col, c_first_row)
Performs one of the matrix-matrix operations: matrix_c = alpha * op1( matrix_a ) * op2( matrix_b ) + ...
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_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_deallocate_matrix(matrix)
...
subroutine, public dbcsr_desymmetrize(matrix_a, matrix_b)
...
subroutine, public dbcsr_set(matrix, alpha)
...
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_dbcsr_to_fm(matrix, fm)
Copy a DBCSR matrix to a BLACS matrix.
Utility routines to open and close files. Tracking of preconnections.
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
subroutine, public cp_fm_copy_general(source, destination, para_env)
General copy of a fm matrix to another fm matrix. Uses non-blocking MPI rather than ScaLAPACK.
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_get_element(matrix, irow_global, icol_global, alpha, local)
returns an element of a fm this value is valid on every cpu using this call is expensive
subroutine, public cp_fm_set_submatrix(fm, new_values, start_row, start_col, n_rows, n_cols, alpha, beta, transpose)
sets a submatrix of a full matrix fm(start_row:start_row+n_rows,start_col:start_col+n_cols) = alpha*o...
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_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...
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_string_length
Routines needed for kpoint calculation.
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, 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 kpoint_initialize(kpoint, particle_set, cell)
Generate the kpoints and initialize the kpoint environment.
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 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)
Retrieve information from a kpoint environment.
subroutine, public kpoint_release(kpoint)
Release a kpoint environment, deallocate all data.
subroutine, public kpoint_create(kpoint)
Create a kpoint environment.
K-points and crystal symmetry routines based on.
Machine interface based on Fortran 2003 and POSIX.
integer, parameter, public timestamp_length
subroutine, public m_timestamp(timestamp)
Returns a human readable timestamp.
Definition of mathematical constants and functions.
real(kind=dp), parameter, public twopi
Collection of simple mathematical functions and subroutines.
subroutine, public diag_complex(matrix, eigenvectors, eigenvalues)
Diagonalizes a local complex Hermitian matrix using LAPACK. Based on cp_cfm_heevd.
Interface to the message passing library MPI.
Define the data structure for the particle information.
Definition of physical constants:
real(kind=dp), parameter, public evolt
real(kind=dp), parameter, public angstrom
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, mimic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
subroutine, public qs_env_release(qs_env)
releases the given qs_env (see doc/ReferenceCounting.html)
Initialize a qs_env for kpoint calculations starting from a gamma point qs_env.
subroutine, public create_kp_from_gamma(qs_env, qs_env_kp, with_xc_terms)
...
Definition and initialisation of the mo data type.
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)
Get the components of a MO set data structure.
Calculates the moment integrals <a|r^m|b> and <a|r x d/dr|b>
subroutine, public build_berry_kpoint_matrix(qs_env, cosmat, sinmat, kvec, basis_type)
...
Define the neighbor list data types and the corresponding functionality.
Different diagonalization schemes that can be used for the iterative solution of the eigenvalue probl...
subroutine, public do_general_diag_kp(matrix_ks, matrix_s, kpoints, scf_env, scf_control, update_p, diis_step, diis_error, qs_env, probe)
Kpoint diagonalization routine Transforms matrices to kpoint, distributes kpoint groups,...
module that contains the definitions of the scf types
Interface to Wannier90 code.
subroutine, public prepare_wannier90_scf_mos(kpoint, qs_kpoint, matrix_s, matrix_ks, cell_to_index, sab_nl, para_env, success, reason, aligned_degenerate_blocks, aligned_degenerate_max_size, aligned_degenerate_min_svalue)
Reconstruct a full Wannier90 k-point MO set from the SCF k-point MOs.
subroutine, public wannier90_interface(input, logger, qs_env)
...
parameters that control an scf iteration
Outtakes from Wannier90 code.
subroutine, public wannier_setup(mp_grid_loc, num_kpts_loc, real_lattice_loc, recip_lattice_loc, kpt_latt_loc, nntot_loc, nnlist_loc, nncell_loc, iounit)
...
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.
keeps the information about the structure of a full matrix
type of a logger, at the moment it contains just a print level starting at which level it should be l...
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