29 dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, dbcsr_type_symmetric
88#include "./base/base_uses.f90"
93 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'qs_wannier90'
94 INTEGER,
PARAMETER,
PRIVATE :: w90_kpoints_mp_grid = 0, &
97 TYPE berry_matrix_type
98 TYPE(dbcsr_p_type),
DIMENSION(:, :),
POINTER :: sinmat => null(), cosmat => null()
99 END TYPE berry_matrix_type
118 CHARACTER(len=*),
PARAMETER :: routinen =
'wannier90_interface'
120 INTEGER :: handle, iw
126 CALL timeset(routinen, handle)
128 subsection_name=
"DFT%PRINT%WANNIER90")
135 WRITE (iw,
'(/,T2,A)') &
136 '!-----------------------------------------------------------------------------!'
137 WRITE (iw,
'(T32,A)')
"Interface to Wannier90"
138 WRITE (iw,
'(T2,A)') &
139 '!-----------------------------------------------------------------------------!'
142 CALL wannier90_files(qs_env, w_input, iw)
145 WRITE (iw,
'(/,T2,A)') &
146 '!--------------------------------End of Wannier90-----------------------------!'
149 CALL timestop(handle)
159 SUBROUTINE wannier90_files(qs_env, input, iw)
162 INTEGER,
INTENT(IN) :: iw
164 INTEGER,
PARAMETER :: num_nnmax = 12
166 CHARACTER(len=2) :: asym
167 CHARACTER(len=20),
ALLOCATABLE,
DIMENSION(:) :: atom_symbols
168 CHARACTER(len=default_string_length) :: filename, input_kp_scheme, reuse_reason, &
170 CHARACTER(LEN=timestamp_length) :: timestamp
171 INTEGER :: aligned_degenerate_blocks, aligned_degenerate_max_size, i, i_rep, ib, ib1, ib2, &
172 ibs, ik, ik2, ikk, ikpgr, ispin, iunit, ix, iy, iz, k, kpoints_source, n_rep, nadd, nao, &
173 nbs, nexcl, nkp, nmo, nntot, nspins, num_atoms, num_bands, num_bands_tot, num_kpts, &
175 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: exclude_bands
176 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: nblist, nnlist
177 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: nncell
178 INTEGER,
DIMENSION(2) :: kp_range
179 INTEGER,
DIMENSION(3) :: input_nkp_grid, mp_grid
180 INTEGER,
DIMENSION(:),
POINTER :: invals
181 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
182 LOGICAL :: diis_step, do_kpoints, full_mesh_diagonalized, gamma_only, input_full_grid, &
183 input_gamma_centered, input_kpoint_symmetry, mp_grid_explicit, mp_grid_valid, my_kpgrp, &
184 mygrp, reuse_scf_mos, reused_scf_mos, spinors, use_bloch_phases, validate_reuse_ok, &
185 validate_reuse_scf_mos
186 REAL(kind=
dp) :: aligned_degenerate_min_svalue, cmmn, gauge_arg, gauge_imag, gauge_real, &
187 gauge_tmp, ksign, reuse_candidate_deviation, reuse_candidate_metric_deviation, &
188 reuse_candidate_min_svalue, reuse_candidate_residual, rmmn, &
189 validation_eigenvalue_deviation, validation_min_svalue, validation_subspace_deviation, &
191 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigval
192 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: atoms_cart, b_latt, kpt_latt
193 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: reference_eigenvalues
194 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :, :) :: reference_mo_imag, reference_mo_real
195 REAL(kind=
dp),
DIMENSION(3) :: bvec, input_kp_shift, phase_center
196 REAL(kind=
dp),
DIMENSION(3, 3) :: h_inv, real_lattice, recip_lattice
197 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues, wkp, wkp_source
198 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: xkp, xkp_source
199 TYPE(berry_matrix_type),
DIMENSION(:),
POINTER :: berry_matrix
202 TYPE(
cp_cfm_type) :: fmk1_cfm, fmk2_cfm, mmn_cfm, omat_cfm, &
206 TYPE(
cp_fm_type) :: mat_imag, mat_real, mmn_imag, mmn_real
208 TYPE(
cp_fm_type),
POINTER :: fmdummy, fmi, fmr
209 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_ks, matrix_s
210 TYPE(
dbcsr_type),
POINTER :: cmatrix, cmatrix_full, rmatrix, &
237 reuse_scf_mos = reuse_scf_mos .AND. kpoints_source == w90_kpoints_scf
238 validate_reuse_scf_mos = validate_reuse_scf_mos .AND. reuse_scf_mos
239 mp_grid(1:3) = invals(1:3)
245 nexcl = nexcl +
SIZE(invals)
248 ALLOCATE (exclude_bands(nexcl))
252 exclude_bands(nexcl + 1:nexcl +
SIZE(invals)) = invals(:)
253 nexcl = nexcl +
SIZE(invals)
259 CALL get_cell(cell, h=real_lattice, h_inv=h_inv)
261 CALL get_qs_env(qs_env, particle_set=particle_set)
263 phase_center = 0.0_dp
264 DO i = 1,
SIZE(particle_set)
265 phase_center(1:3) = phase_center(1:3) + matmul(h_inv, particle_set(i)%r)
267 phase_center(1:3) = phase_center(1:3)/real(
SIZE(particle_set), kind=
dp)
268 phase_center(1:3) = phase_center(1:3) - floor(phase_center(1:3))
269 recip_lattice(1:3, 1:3) = h_inv(1:3, 1:3)
270 real_lattice(1:3, 1:3) =
angstrom*real_lattice(1:3, 1:3)
271 recip_lattice(1:3, 1:3) = (
twopi/
angstrom)*transpose(recip_lattice(1:3, 1:3))
272 NULLIFY (kpoint, qs_kpoint, xkp, wkp, xkp_source, wkp_source)
273 CALL get_qs_env(qs_env, do_kpoints=do_kpoints, kpoints=qs_kpoint)
274 input_kpoint_symmetry = .false.
275 input_full_grid = .false.
277 IF (do_kpoints .AND.
ASSOCIATED(qs_kpoint))
THEN
278 CALL get_kpoint_info(qs_kpoint, kp_scheme=input_kp_scheme, nkp_grid=input_nkp_grid, &
279 kp_shift=input_kp_shift, symmetry=input_kpoint_symmetry, &
280 full_grid=input_full_grid, gamma_centered=input_gamma_centered, &
281 nkp=nkp, xkp=xkp, wkp=wkp)
285 SELECT CASE (kpoints_source)
286 CASE (w90_kpoints_mp_grid)
287 num_kpts = mp_grid(1)*mp_grid(2)*mp_grid(3)
288 ALLOCATE (kpt_latt(3, num_kpts))
289 kpoint%kp_scheme =
"MONKHORST-PACK"
290 kpoint%symmetry = .false.
291 kpoint%nkp_grid(1:3) = mp_grid(1:3)
292 kpoint%verbose = .false.
293 kpoint%full_grid = .true.
294 kpoint%eps_geo = 1.0e-6_dp
295 kpoint%use_real_wfn = .false.
296 kpoint%parallel_group_size = para_env%num_pe
298 DO ix = 0, mp_grid(1) - 1
299 DO iy = 0, mp_grid(2) - 1
300 DO iz = 0, mp_grid(3) - 1
302 kpt_latt(1, i) = real(ix, kind=
dp)/real(mp_grid(1), kind=
dp)
303 kpt_latt(2, i) = real(iy, kind=
dp)/real(mp_grid(2), kind=
dp)
304 kpt_latt(3, i) = real(iz, kind=
dp)/real(mp_grid(3), kind=
dp)
308 kpoint%nkp = num_kpts
309 ALLOCATE (kpoint%xkp(3, num_kpts), kpoint%wkp(num_kpts))
310 kpoint%wkp(:) = 1._dp/real(num_kpts, kind=
dp)
312 kpoint%xkp(1:3, i) = (
angstrom/
twopi)*matmul(recip_lattice, kpt_latt(:, i))
315 CASE (w90_kpoints_scf)
316 IF (.NOT. do_kpoints .OR. .NOT.
ASSOCIATED(qs_kpoint))
THEN
317 cpabort(
"WANNIER90%KPOINTS_SOURCE SCF requires an active DFT%KPOINTS section.")
319 SELECT CASE (trim(input_kp_scheme))
323 ALLOCATE (kpt_latt(3, num_kpts))
324 kpt_latt(1:3, 1) = 0.0_dp
325 kpoint%kp_scheme =
"GAMMA"
326 kpoint%symmetry = .false.
327 kpoint%verbose = .false.
328 kpoint%full_grid = .true.
329 kpoint%eps_geo = 1.0e-6_dp
330 kpoint%use_real_wfn = .false.
331 kpoint%parallel_group_size = para_env%num_pe
332 kpoint%nkp = num_kpts
333 ALLOCATE (kpoint%xkp(3, num_kpts), kpoint%wkp(num_kpts))
334 kpoint%xkp(1:3, 1) = 0.0_dp
335 kpoint%wkp(1) = 1.0_dp
337 CASE (
"MONKHORST-PACK",
"MACDONALD")
338 mp_grid(1:3) = input_nkp_grid(1:3)
339 kpoint%kp_scheme = input_kp_scheme
340 kpoint%symmetry = .false.
341 kpoint%nkp_grid(1:3) = input_nkp_grid(1:3)
342 kpoint%kp_shift(1:3) = input_kp_shift(1:3)
343 kpoint%gamma_centered = input_gamma_centered
344 kpoint%verbose = .false.
345 kpoint%full_grid = .true.
346 kpoint%eps_geo = 1.0e-6_dp
347 kpoint%use_real_wfn = .false.
348 kpoint%parallel_group_size = para_env%num_pe
350 num_kpts = kpoint%nkp
351 ALLOCATE (kpt_latt(3, num_kpts))
352 kpt_latt(1:3, 1:num_kpts) = kpoint%xkp(1:3, 1:num_kpts)
353 IF (input_kpoint_symmetry .AND. .NOT. input_full_grid .AND. iw > 0)
THEN
354 WRITE (iw,
'(T2,A)') &
355 "WANNIER90| SCF k-points are symmetry-reduced; regenerating the full SCF mesh."
356 IF (reuse_scf_mos)
THEN
357 WRITE (iw,
'(T2,A)') &
358 "WANNIER90| CP2K will try to reconstruct the full-mesh MOs from the SCF orbitals."
360 WRITE (iw,
'(T2,A)') &
361 "WANNIER90| The full exported mesh is diagonalized for the Wannier90 files."
366 IF (
ASSOCIATED(qs_kpoint%xkp_input))
THEN
367 xkp_source => qs_kpoint%xkp_input
368 wkp_source => qs_kpoint%wkp_input
373 IF (.NOT.
ASSOCIATED(xkp_source) .OR. .NOT.
ASSOCIATED(wkp_source))
THEN
374 cpabort(
"Could not access the SCF GENERAL k-point set for the Wannier90 export.")
376 num_kpts =
SIZE(wkp_source)
377 ALLOCATE (kpt_latt(3, num_kpts))
378 kpt_latt(1:3, 1:num_kpts) = xkp_source(1:3, 1:num_kpts)
379 IF (mp_grid_explicit)
THEN
380 IF (mp_grid(1)*mp_grid(2)*mp_grid(3) /= num_kpts)
THEN
381 cpabort(
"WANNIER90%MP_GRID must contain exactly as many points as the SCF GENERAL mesh.")
384 CALL infer_wannier_mp_grid(kpt_latt, mp_grid, mp_grid_valid)
385 IF (.NOT. mp_grid_valid)
THEN
386 cpabort(
"Could not infer WANNIER90%MP_GRID from the SCF GENERAL mesh.")
389 wkp_ref = 1.0_dp/real(num_kpts, kind=
dp)
391 IF (abs(wkp_source(i) - wkp_ref) > 1.0e-10_dp)
THEN
392 cpabort(
"WANNIER90%KPOINTS_SOURCE SCF requires equally weighted GENERAL k-points.")
395 kpoint%kp_scheme =
"GENERAL"
396 kpoint%symmetry = .false.
397 kpoint%nkp_grid(1:3) = mp_grid(1:3)
398 kpoint%verbose = .false.
399 kpoint%full_grid = .true.
400 kpoint%eps_geo = 1.0e-6_dp
401 kpoint%use_real_wfn = .false.
402 kpoint%parallel_group_size = para_env%num_pe
403 kpoint%nkp = num_kpts
404 ALLOCATE (kpoint%xkp(3, num_kpts), kpoint%wkp(num_kpts))
405 kpoint%xkp(1:3, 1:num_kpts) = xkp_source(1:3, 1:num_kpts)
406 kpoint%wkp(1:num_kpts) = wkp_ref
407 IF (input_kpoint_symmetry .AND. .NOT. input_full_grid .AND. iw > 0)
THEN
408 WRITE (iw,
'(T2,A)') &
409 "WANNIER90| SCF k-points are symmetry-reduced; using the full input GENERAL mesh."
410 IF (reuse_scf_mos)
THEN
411 WRITE (iw,
'(T2,A)') &
412 "WANNIER90| CP2K will try to reconstruct the full-mesh MOs from the SCF orbitals."
414 WRITE (iw,
'(T2,A)') &
415 "WANNIER90| The full exported mesh is diagonalized for the Wannier90 files."
420 cpabort(
"WANNIER90%KPOINTS_SOURCE SCF does not support this DFT%KPOINTS scheme.")
423 cpabort(
"Unknown WANNIER90%KPOINTS_SOURCE setting.")
427 CALL get_mo_set(mo_set=mos(1), nao=nao, nmo=num_bands_tot)
428 num_bands_tot = min(nao, num_bands_tot + nadd)
429 num_bands = num_bands_tot
430 IF (use_bloch_phases .AND. num_wann /= num_bands)
THEN
431 cpabort(
"WANNIER90%USE_BLOCH_PHASES requires WANNIER_FUNCTIONS to match the number of bands.")
433 num_atoms =
SIZE(particle_set)
434 ALLOCATE (atoms_cart(3, num_atoms))
435 ALLOCATE (atom_symbols(num_atoms))
437 atoms_cart(1:3, i) = particle_set(i)%r(1:3)
439 atom_symbols(i) = asym
444 ALLOCATE (nnlist(num_kpts, num_nnmax))
445 ALLOCATE (nncell(3, num_kpts, num_nnmax))
452 CALL wannier_setup(mp_grid, num_kpts, real_lattice, recip_lattice, &
453 kpt_latt, nntot, nnlist, nncell, iw)
457 CALL para_env%sum(nntot)
458 CALL para_env%sum(nnlist)
459 CALL para_env%sum(nncell)
461 IF (para_env%is_source())
THEN
463 WRITE (filename,
'(A,A)') trim(seed_name),
".win"
464 CALL open_file(filename, unit_number=iunit, file_status=
"UNKNOWN", file_action=
"WRITE")
467 WRITE (iunit,
"(A)")
"! Wannier90 input file generated by CP2K "
468 WRITE (iunit,
"(A,/)")
"! Creation date "//timestamp
470 WRITE (iunit,
"(A,I5)")
"num_wann = ", num_wann
471 IF (num_bands /= num_wann .OR. use_bloch_phases)
THEN
472 WRITE (iunit,
"(A,I5)")
"num_bands = ", num_bands
474 IF (use_bloch_phases)
THEN
477 WRITE (iunit,
"(A)")
"! CP2K writes identity projections for Bloch-phase complete subspaces."
479 WRITE (iunit,
"(/,A,/)")
"length_unit = bohr "
480 WRITE (iunit,
"(/,A,/)")
"! System"
481 WRITE (iunit,
"(/,A)")
"begin unit_cell_cart"
482 WRITE (iunit,
"(A)")
"bohr"
484 WRITE (iunit,
"(3F12.6)") cell%hmat(i, 1:3)
486 WRITE (iunit,
"(A,/)")
"end unit_cell_cart"
487 WRITE (iunit,
"(/,A)")
"begin atoms_cart"
488 WRITE (iunit,
"(A)")
"bohr"
490 WRITE (iunit,
"(A,3F15.10)") atom_symbols(i), atoms_cart(1:3, i)
492 WRITE (iunit,
"(A,/)")
"end atoms_cart"
493 WRITE (iunit,
"(/,A,/)")
"! Kpoints"
494 WRITE (iunit,
"(/,A,3I6/)")
"mp_grid = ", mp_grid(1:3)
495 WRITE (iunit,
"(A)")
"begin kpoints"
497 WRITE (iunit,
"(3F12.6)") kpt_latt(1:3, i)
499 WRITE (iunit,
"(A)")
"end kpoints"
501 IF (use_bloch_phases)
THEN
502 WRITE (filename,
'(A,A)') trim(seed_name),
".amn"
503 CALL open_file(filename, unit_number=iunit, file_status=
"UNKNOWN", file_action=
"WRITE")
504 WRITE (iunit,
"(A)")
"! Wannier90 identity projections generated by CP2K"
505 WRITE (iunit,
"(3I8)") num_bands, num_kpts, num_wann
508 DO ib1 = 1, num_bands
510 WRITE (iunit,
"(3I8,2E30.14)") ib1, ib2, ik, 1.0_dp, 0.0_dp
512 WRITE (iunit,
"(3I8,2E30.14)") ib1, ib2, ik, 0.0_dp, 0.0_dp
525 IF (kpoints_source == w90_kpoints_mp_grid .AND. input_kpoint_symmetry .AND. iw > 0)
THEN
526 WRITE (iw,
'(T2,A)') &
527 "WANNIER90| Atomic k-point symmetry from the SCF calculation is not reused."
528 WRITE (iw,
'(T2,A)') &
529 "WANNIER90| A full Monkhorst-Pack grid is generated for the Wannier90 interface."
540 WRITE (unit=iw, fmt=
"(/,T2,A)")
"Start K-Point Calculation ..."
542 CALL get_qs_env(qs_env=qs_env_kp, para_env=para_env, blacs_env=blacs_env)
547 CALL get_qs_env(qs_env=qs_env_kp, sab_orb=sab_nl, dft_control=dft_control)
550 CALL get_qs_env(qs_env=qs_env_kp, matrix_ks_kp=matrix_ks, matrix_s_kp=matrix_s, &
551 scf_env=scf_env, scf_control=scf_control)
552 full_mesh_diagonalized = .false.
553 reused_scf_mos = .false.
555 aligned_degenerate_blocks = 0
556 aligned_degenerate_max_size = 0
557 aligned_degenerate_min_svalue = 0.0_dp
558 IF (reuse_scf_mos)
THEN
560 CALL do_general_diag_kp(matrix_ks, matrix_s, qs_kpoint, scf_env, scf_control, .false., &
562 IF (validate_reuse_scf_mos)
THEN
564 WRITE (iw,
'(T2,A)') &
565 "WANNIER90| Validating SCF MO reuse against a full-mesh diagonalization reference."
567 CALL do_general_diag_kp(matrix_ks, matrix_s, kpoint, scf_env, scf_control, .false., diis_step)
568 full_mesh_diagonalized = .true.
569 nspins = dft_control%nspins
570 CALL save_wannier90_mo_snapshot(kpoint, nspins, para_env, reference_mo_real, &
571 reference_mo_imag, reference_eigenvalues)
572 CALL diagnose_wannier90_scf_reuse_candidates(kpoint, qs_kpoint, matrix_s, matrix_ks, &
573 cell_to_index, sab_nl, para_env, iw, &
574 reuse_candidate_deviation, &
575 reuse_candidate_min_svalue, &
576 reuse_candidate_metric_deviation, &
577 reuse_candidate_residual)
578 IF (iw > 0 .AND. reuse_candidate_deviation < 1.0e100_dp)
THEN
579 WRITE (iw,
'(T2,A,ES10.3,A,ES10.3,A,ES10.3,A,ES10.3)') &
580 "WANNIER90| Best atom/AO candidate subspace deviation ", &
581 reuse_candidate_deviation,
", minimum singular value ", &
582 reuse_candidate_min_svalue,
", max metric deviation ", &
583 reuse_candidate_metric_deviation,
", max residual ", reuse_candidate_residual
587 sab_nl, para_env, reused_scf_mos, reuse_reason, &
588 aligned_degenerate_blocks, aligned_degenerate_max_size, &
589 aligned_degenerate_min_svalue)
590 IF (validate_reuse_scf_mos)
THEN
591 IF (reused_scf_mos)
THEN
592 CALL validate_wannier90_reused_mos(kpoint, matrix_s, cell_to_index, sab_nl, &
593 para_env, reference_mo_real, reference_mo_imag, &
594 reference_eigenvalues, validate_reuse_ok, &
595 validation_subspace_deviation, validation_min_svalue, &
596 validation_eigenvalue_deviation)
598 WRITE (iw,
'(T2,A,ES10.3,A,ES10.3,A,ES10.3)') &
599 "WANNIER90| Reused MO validation: subspace deviation ", &
600 validation_subspace_deviation,
", minimum singular value ", &
601 validation_min_svalue,
", eigenvalue deviation ", &
602 validation_eigenvalue_deviation
604 IF (.NOT. validate_reuse_ok)
THEN
605 reused_scf_mos = .false.
606 WRITE (reuse_reason,
"(A,ES10.3,A,ES10.3)") &
607 "validation failed: dS=", &
608 validation_subspace_deviation,
", dE=", validation_eigenvalue_deviation
611 IF (.NOT. reused_scf_mos)
THEN
612 CALL restore_wannier90_mo_snapshot(kpoint, reference_mo_real, reference_mo_imag, &
613 reference_eigenvalues)
617 IF (reused_scf_mos)
THEN
618 WRITE (iw,
'(T2,A)') &
619 "WANNIER90| Reused SCF MO coefficients for the Wannier90 full k-point mesh."
620 IF (use_bloch_phases)
THEN
621 WRITE (iw,
'(T2,A)') &
622 "WANNIER90| Wrote identity projections for Bloch-phase complete band subspaces."
623 WRITE (iw,
'(T2,A,3F10.6)') &
624 "WANNIER90| Applied Bloch phase gauge to reused overlaps around fractional center", &
627 IF (aligned_degenerate_blocks > 0)
THEN
628 WRITE (iw,
'(T2,A,I0,A,I0,A,ES10.3)') &
629 "WANNIER90| Ritz-stabilized ", aligned_degenerate_blocks, &
630 " degenerate SCF MO subspace(s) with S(k),H(k); largest block has ", &
631 aligned_degenerate_max_size,
" band(s), min metric eigenvalue ", &
632 aligned_degenerate_min_svalue
635 WRITE (iw,
'(T2,A,A)') &
636 "WANNIER90| Could not reuse SCF MOs: ", trim(reuse_reason)
637 WRITE (iw,
'(T2,A)') &
638 "WANNIER90| Falling back to full-mesh diagonalization for the Wannier90 files."
642 IF (.NOT. reused_scf_mos .AND. .NOT. full_mesh_diagonalized)
THEN
643 CALL do_general_diag_kp(matrix_ks, matrix_s, kpoint, scf_env, scf_control, .false., diis_step)
645 IF (
ALLOCATED(reference_mo_real))
DEALLOCATE (reference_mo_real)
646 IF (
ALLOCATED(reference_mo_imag))
DEALLOCATE (reference_mo_imag)
647 IF (
ALLOCATED(reference_eigenvalues))
DEALLOCATE (reference_eigenvalues)
650 WRITE (iw,
'(T69,A)')
"... Finished"
655 IF (para_env%is_source())
THEN
656 WRITE (filename,
'(A,A)') trim(seed_name),
".mmn"
657 CALL open_file(filename, unit_number=iunit, file_status=
"UNKNOWN", file_action=
"WRITE")
659 WRITE (iunit,
"(A)")
"! Wannier90 file generated by CP2K "//timestamp
660 WRITE (iunit,
"(3I8)") num_bands, num_kpts, nntot
666 ALLOCATE (nblist(num_kpts, nntot))
667 ALLOCATE (b_latt(3, num_kpts*nntot))
672 bvec(1:3) = kpt_latt(1:3, nnlist(ik, i)) - kpt_latt(1:3, ik) + nncell(1:3, ik, i)
675 IF (sum(abs(bvec(1:3) - b_latt(1:3, k))) < 1.e-6_dp)
THEN
679 IF (sum(abs(bvec(1:3) + b_latt(1:3, k))) < 1.e-6_dp)
THEN
690 b_latt(1:3, nbs) = bvec(1:3)
696 ALLOCATE (berry_matrix(nbs))
698 NULLIFY (berry_matrix(i)%cosmat)
699 NULLIFY (berry_matrix(i)%sinmat)
700 bvec(1:3) =
twopi*matmul(transpose(cell%h_inv(1:3, 1:3)), b_latt(1:3, i))
702 berry_matrix(i)%sinmat, bvec)
705 kp => kpoint%kp_env(1)%kpoint_env
707 NULLIFY (matrix_struct_ao, matrix_struct_work)
727 NULLIFY (matrix_struct_mmn)
736 ALLOCATE (rmatrix, cmatrix, rmatrix_full, cmatrix_full)
737 CALL dbcsr_create(rmatrix, template=matrix_s(1, 1)%matrix, &
738 matrix_type=dbcsr_type_symmetric)
739 CALL dbcsr_create(cmatrix, template=matrix_s(1, 1)%matrix, &
740 matrix_type=dbcsr_type_antisymmetric)
741 CALL dbcsr_create(rmatrix_full, template=matrix_s(1, 1)%matrix, &
742 matrix_type=dbcsr_type_no_symmetry)
743 CALL dbcsr_create(cmatrix_full, template=matrix_s(1, 1)%matrix, &
744 matrix_type=dbcsr_type_no_symmetry)
750 nspins = dft_control%nspins
755 my_kpgrp = (ik >= kpoint%kp_range(1) .AND. ik <= kpoint%kp_range(2))
757 ikk = ik - kpoint%kp_range(1) + 1
758 kp => kpoint%kp_env(ikk)%kpoint_env
759 cpassert(
SIZE(kp%mos, 1) == 2)
760 fmr => kp%mos(1, ispin)%mo_coeff
761 fmi => kp%mos(2, ispin)%mo_coeff
765 NULLIFY (fmr, fmi, kp)
774 mygrp = (ik2 >= kpoint%kp_range(1) .AND. ik2 <= kpoint%kp_range(2))
776 ikk = ik2 - kpoint%kp_range(1) + 1
777 kp => kpoint%kp_env(ikk)%kpoint_env
778 cpassert(
SIZE(kp%mos, 1) == 2)
779 fmr => kp%mos(1, ispin)%mo_coeff
780 fmi => kp%mos(2, ispin)%mo_coeff
784 NULLIFY (fmr, fmi, kp)
792 ksign = sign(1.0_dp, real(ibs, kind=
dp))
796 CALL rskp_transform(rmatrix, cmatrix, rsmat=berry_matrix(ibs)%cosmat, ispin=1, &
797 xkp=kpoint%xkp(1:3, ik2), cell_to_index=cell_to_index, sab_nl=sab_nl, &
798 is_complex=.false., rs_sign=ksign)
799 CALL rskp_transform(cmatrix, rmatrix, rsmat=berry_matrix(ibs)%sinmat, ispin=1, &
800 xkp=kpoint%xkp(1:3, ik2), cell_to_index=cell_to_index, sab_nl=sab_nl, &
801 is_complex=.true., rs_sign=ksign)
809 CALL cp_cfm_gemm(
"N",
"N", nao, nmo, nao, cmplx(1.0_dp, 0.0_dp, kind=
dp), &
810 omat_cfm, fmk2_cfm, cmplx(0.0_dp, 0.0_dp, kind=
dp), tmp_cfm)
811 CALL cp_cfm_gemm(
"C",
"N", nmo, nmo, nao, cmplx(1.0_dp, 0.0_dp, kind=
dp), &
812 fmk1_cfm, tmp_cfm, cmplx(0.0_dp, 0.0_dp, kind=
dp), mmn_cfm)
816 IF (reused_scf_mos .AND. use_bloch_phases)
THEN
818 gauge_arg =
twopi*dot_product(kpoint%xkp(1:3, ik2) - kpoint%xkp(1:3, ik), &
820 gauge_real = cos(gauge_arg)
821 gauge_imag = sin(gauge_arg)
826 IF (para_env%is_source())
THEN
827 WRITE (iunit,
"(2I8,3I5)") ik, ik2, nncell(1:3, ik, i)
833 gauge_tmp = gauge_real*rmmn - gauge_imag*cmmn
834 cmmn = gauge_imag*rmmn + gauge_real*cmmn
836 IF (para_env%is_source())
THEN
837 WRITE (iunit,
"(2E30.14)") rmmn, cmmn
849 DEALLOCATE (berry_matrix)
871 IF (para_env%is_source())
THEN
878 nspins = dft_control%nspins
879 kp => kpoint%kp_env(1)%kpoint_env
881 ALLOCATE (eigval(nmo))
883 IF (para_env%is_source())
THEN
884 WRITE (filename,
'(A,A)') trim(seed_name),
".eig"
885 CALL open_file(filename, unit_number=iunit, file_status=
"UNKNOWN", file_action=
"WRITE")
891 my_kpgrp = (ik >= kp_range(1) .AND. ik <= kp_range(2))
894 ikpgr = ik - kp_range(1) + 1
895 kp => kpoint%kp_env(ikpgr)%kpoint_env
896 CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues)
897 eigval(1:nmo) = eigenvalues(1:nmo)
899 eigval(1:nmo) = 0.0_dp
901 CALL kpoint%para_env_inter_kp%sum(eigval)
902 eigval(1:nmo) = eigval(1:nmo)*
evolt
906 WRITE (iunit,
"(2I8,F24.14)") ib, ik, eigval(ib)
911 IF (para_env%is_source())
THEN
916 DEALLOCATE (kpt_latt, atoms_cart, atom_symbols, eigval)
917 DEALLOCATE (nnlist, nncell)
918 DEALLOCATE (nblist, b_latt)
920 DEALLOCATE (exclude_bands)
926 DEALLOCATE (qs_env_kp)
932 END SUBROUTINE wannier90_files
950 sab_nl, para_env, success, reason, aligned_degenerate_blocks, &
951 aligned_degenerate_max_size, &
952 aligned_degenerate_min_svalue)
954 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s, matrix_ks
955 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
959 LOGICAL,
INTENT(OUT) :: success
960 CHARACTER(LEN=*),
INTENT(OUT) :: reason
961 INTEGER,
INTENT(OUT) :: aligned_degenerate_blocks, &
962 aligned_degenerate_max_size
963 REAL(kind=
dp),
INTENT(OUT) :: aligned_degenerate_min_svalue
965 CHARACTER(LEN=default_string_length) :: best_reason, candidate_reason
966 INTEGER :: aligned_blocks, aligned_max_size, candidate_aligned_blocks, &
967 candidate_aligned_max_size, ik, ikpgr, ikred, ispin, isym_try, min_gap_band, &
968 min_gap_kpoint, min_gap_spin, nao, nao_src, nmo, nmo_src, nspins, nsymmetry, &
970 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: source_kpoint, sym_index
971 INTEGER,
DIMENSION(2) :: kp_range, source_kp_range
972 LOGICAL :: my_kpgrp, my_source_kpgrp, ok, &
974 REAL(kind=
dp) :: aligned_min_svalue, band_gap, best_residual, candidate_residual, &
975 degenerate_band_tol, local_min_band_gap, min_band_gap, source_owner_count, &
976 source_window_min_svalue
977 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues_buffer, occupation_buffer, &
978 source_eigenvalues_buffer, &
979 source_occupation_buffer
980 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues, occupation
983 TYPE(
cp_fm_type) :: dst_imag, dst_imag_full, dst_real, &
984 dst_real_full, src_imag, &
985 src_imag_full, src_real, src_real_full
986 TYPE(
cp_fm_type),
POINTER :: dst_fmi, dst_fmr, src_fmi, src_fmr
992 aligned_degenerate_blocks = 0
993 aligned_degenerate_max_size = 0
994 aligned_degenerate_min_svalue = huge(1.0_dp)
995 NULLIFY (matrix_struct_source, matrix_struct_work, src_fmr, src_fmi, dst_fmr, dst_fmi)
997 IF (.NOT.
ASSOCIATED(kpoint))
THEN
998 reason =
"internal Wannier90 k-point object is not available"
1001 IF (.NOT.
ASSOCIATED(qs_kpoint))
THEN
1002 reason =
"SCF k-point object is not available"
1005 IF (.NOT.
ASSOCIATED(kpoint%kp_env) .OR. .NOT.
ASSOCIATED(qs_kpoint%kp_env))
THEN
1006 reason =
"k-point MO environments are not initialized"
1009 IF (.NOT.
ASSOCIATED(kpoint%blacs_env))
THEN
1010 reason =
"Wannier90 k-point BLACS environment is not initialized"
1014 CALL build_wannier90_scf_mapping(kpoint, qs_kpoint, source_kpoint, sym_index, ok, reason)
1015 IF (.NOT. ok)
RETURN
1016 nsymmetry = count(sym_index > 0)
1018 kp => kpoint%kp_env(1)%kpoint_env
1019 nspins =
SIZE(kp%mos, 2)
1020 IF (
SIZE(kp%mos, 1) < 2)
THEN
1021 reason =
"Wannier90 export k-point MOs are not complex-valued"
1022 DEALLOCATE (source_kpoint, sym_index)
1025 CALL get_mo_set(kp%mos(1, 1), nao=nao, nmo=nmo)
1027 kp_source => qs_kpoint%kp_env(1)%kpoint_env
1028 IF (
SIZE(kp_source%mos, 1) < 2)
THEN
1029 reason =
"SCF MOs are real-valued; complex symmetry phases cannot be reconstructed"
1030 DEALLOCATE (source_kpoint, sym_index)
1033 CALL get_mo_set(kp_source%mos(1, 1), nao=nao_src, nmo=nmo_src)
1034 CALL para_env%max(nao_src)
1035 CALL para_env%max(nmo_src)
1036 IF (nao_src /= nao)
THEN
1037 reason =
"SCF and Wannier90 MO bases have different AO dimensions"
1038 DEALLOCATE (source_kpoint, sym_index)
1041 IF (nmo_src < nmo)
THEN
1042 reason =
"SCF MO set has fewer bands than the Wannier90 export"
1043 DEALLOCATE (source_kpoint, sym_index)
1046 source_window = nmo_src > nmo
1047 degenerate_band_tol = 1.0e-8_dp
1049 IF (source_kp_range(1) /= 1 .OR. source_kp_range(2) /= qs_kpoint%nkp)
THEN
1050 reason =
"SCF k-point symmetry data are distributed over k-point parallel groups"
1051 DEALLOCATE (source_kpoint, sym_index)
1057 IF (nsymmetry > 0 .AND. nmo_src > nmo)
THEN
1058 local_min_band_gap = huge(1.0_dp)
1062 DO ikred = source_kp_range(1), source_kp_range(2)
1063 ikpgr = ikred - source_kp_range(1) + 1
1064 kp_source => qs_kpoint%kp_env(ikpgr)%kpoint_env
1065 DO ispin = 1, nspins
1066 CALL get_mo_set(kp_source%mos(1, ispin), eigenvalues=eigenvalues)
1067 band_gap = abs(eigenvalues(nmo + 1) - eigenvalues(nmo))
1068 IF (band_gap < local_min_band_gap)
THEN
1069 local_min_band_gap = band_gap
1071 min_gap_kpoint = ikred
1072 min_gap_spin = ispin
1076 min_band_gap = local_min_band_gap
1077 CALL para_env%min(min_band_gap)
1078 IF (abs(local_min_band_gap - min_band_gap) > degenerate_band_tol*epsilon(1.0_dp))
THEN
1082 CALL para_env%max(min_gap_kpoint)
1083 CALL para_env%max(min_gap_spin)
1084 CALL para_env%max(min_gap_band)
1085 IF (min_band_gap < degenerate_band_tol)
THEN
1086 WRITE (reason,
"(A,ES9.2,A,I0,A,I0,A,I0)") &
1087 "degenerate atom/AO W90 reuse guarded: edge gap=", min_band_gap,
", k=", &
1088 min_gap_kpoint,
", s=", min_gap_spin,
", nband=", min_gap_band
1089 DEALLOCATE (source_kpoint, sym_index)
1093 blacs_env => kpoint%blacs_env
1095 para_env=para_env, context=blacs_env)
1100 IF (source_window)
THEN
1102 para_env=para_env, context=blacs_env)
1108 ALLOCATE (eigenvalues_buffer(nmo), occupation_buffer(nmo), &
1109 source_eigenvalues_buffer(nmo_src), source_occupation_buffer(nmo_src))
1114 DO ik = 1, kpoint%nkp
1115 ikred = source_kpoint(ik)
1116 my_kpgrp = (ik >= kp_range(1) .AND. ik <= kp_range(2))
1117 my_source_kpgrp = (ikred >= source_kp_range(1) .AND. ikred <= source_kp_range(2))
1118 DO ispin = 1, nspins
1119 source_eigenvalues_buffer(1:nmo_src) = 0.0_dp
1120 source_occupation_buffer(1:nmo_src) = 0.0_dp
1121 IF (my_source_kpgrp)
THEN
1122 ikpgr = ikred - source_kp_range(1) + 1
1123 kp_source => qs_kpoint%kp_env(ikpgr)%kpoint_env
1124 src_fmr => kp_source%mos(1, ispin)%mo_coeff
1125 src_fmi => kp_source%mos(2, ispin)%mo_coeff
1126 CALL get_mo_set(kp_source%mos(1, ispin), eigenvalues=eigenvalues, &
1127 occupation_numbers=occupation)
1128 source_eigenvalues_buffer(1:nmo_src) = eigenvalues(1:nmo_src)
1129 source_occupation_buffer(1:nmo_src) = occupation(1:nmo_src)
1131 NULLIFY (src_fmr, src_fmi)
1133 IF (my_source_kpgrp)
THEN
1134 source_owner_count = 1.0_dp
1136 source_owner_count = 0.0_dp
1138 CALL para_env%sum(source_owner_count)
1139 CALL para_env%sum(source_eigenvalues_buffer)
1140 CALL para_env%sum(source_occupation_buffer)
1141 IF (source_owner_count > 0.0_dp)
THEN
1142 source_eigenvalues_buffer(1:nmo_src) = &
1143 source_eigenvalues_buffer(1:nmo_src)/source_owner_count
1144 source_occupation_buffer(1:nmo_src) = &
1145 source_occupation_buffer(1:nmo_src)/source_owner_count
1147 eigenvalues_buffer(1:nmo) = source_eigenvalues_buffer(1:nmo)
1148 occupation_buffer(1:nmo) = source_occupation_buffer(1:nmo)
1149 IF (source_window)
THEN
1152 CALL copy_wannier90_mo_window(src_real_full, src_real, nmo)
1153 CALL copy_wannier90_mo_window(src_imag_full, src_imag, nmo)
1162 aligned_max_size = 0
1163 aligned_min_svalue = 0.0_dp
1164 IF (sym_index(ik) > 0)
THEN
1165 kpsym => qs_kpoint%kp_sym(ikred)%kpoint_sym
1166 IF (
ASSOCIATED(
kpsym))
THEN
1168 best_residual = huge(1.0_dp)
1171 DO isym_try = 1,
kpsym%nwred
1173 kpsym%xkp(1:3, isym_try))) cycle
1174 num_candidates = num_candidates + 1
1176 qs_kpoint, ikred, isym_try, para_env, ok, &
1179 reason = candidate_reason
1182 CALL ritz_stabilize_wannier90_subspace(dst_real, dst_imag, matrix_s, matrix_ks, &
1183 kpoint%xkp(1:3, ik), cell_to_index, &
1184 sab_nl, ispin, eigenvalues_buffer, &
1185 degenerate_band_tol, ok, candidate_reason, &
1186 candidate_aligned_blocks, &
1187 candidate_aligned_max_size, &
1188 aligned_min_svalue, candidate_residual)
1189 IF (candidate_residual < best_residual)
THEN
1190 best_residual = candidate_residual
1191 best_reason = candidate_reason
1194 IF (source_window)
THEN
1196 dst_real_full, dst_imag_full, qs_kpoint, &
1197 ikred, isym_try, para_env, ok, candidate_reason)
1199 CALL ritz_reconstruct_wannier90_window(dst_real_full, dst_imag_full, &
1200 dst_real, dst_imag, matrix_s, &
1201 matrix_ks, kpoint%xkp(1:3, ik), &
1202 cell_to_index, sab_nl, ispin, &
1203 eigenvalues_buffer, nmo, ok, &
1204 candidate_reason, source_window_min_svalue, &
1206 IF (candidate_residual < best_residual)
THEN
1207 best_residual = candidate_residual
1208 best_reason = candidate_reason
1212 CALL ritz_reconstruct_wannier90_window(dst_real, dst_imag, dst_real, &
1213 dst_imag, matrix_s, matrix_ks, &
1214 kpoint%xkp(1:3, ik), cell_to_index, &
1215 sab_nl, ispin, eigenvalues_buffer, nmo, &
1216 ok, candidate_reason, source_window_min_svalue, &
1218 IF (candidate_residual < best_residual)
THEN
1219 best_residual = candidate_residual
1220 best_reason = candidate_reason
1225 aligned_blocks = candidate_aligned_blocks
1226 aligned_max_size = candidate_aligned_max_size
1227 sym_index(ik) = isym_try
1230 reason = candidate_reason
1232 IF (.NOT. ok .AND. num_candidates > 0 .AND. best_residual < huge(1.0_dp))
THEN
1233 WRITE (reason,
"(A,I0,A,ES9.2,A,I0,A,A32)") &
1234 "atom/AO W90 guarded: best/", num_candidates,
"=", best_residual, &
1235 " k=", ik,
" ", trim(best_reason)
1236 ELSE IF (.NOT. ok .AND. num_candidates == 0)
THEN
1237 reason =
"no matching SCF symmetry operation candidate"
1240 reason =
"SCF k-point symmetry operation is not available"
1244 ikred, sym_index(ik), para_env, ok, reason)
1246 IF (ok .AND. sym_index(ik) <= 0)
THEN
1249 CALL ritz_stabilize_wannier90_subspace(dst_real, dst_imag, matrix_s, matrix_ks, &
1250 kpoint%xkp(1:3, ik), cell_to_index, sab_nl, &
1251 ispin, eigenvalues_buffer, degenerate_band_tol, &
1252 ok, reason, aligned_blocks, aligned_max_size, &
1253 aligned_min_svalue, candidate_residual)
1254 IF (.NOT. ok .AND. source_window)
THEN
1256 dst_imag_full, qs_kpoint, ikred, sym_index(ik), &
1257 para_env, ok, reason)
1259 CALL ritz_reconstruct_wannier90_window(dst_real_full, dst_imag_full, dst_real, &
1260 dst_imag, matrix_s, matrix_ks, &
1261 kpoint%xkp(1:3, ik), cell_to_index, &
1262 sab_nl, ispin, eigenvalues_buffer, nmo, ok, &
1263 reason, source_window_min_svalue, &
1266 ELSE IF (.NOT. ok)
THEN
1267 CALL ritz_reconstruct_wannier90_window(dst_real, dst_imag, dst_real, dst_imag, &
1268 matrix_s, matrix_ks, kpoint%xkp(1:3, ik), &
1269 cell_to_index, sab_nl, ispin, &
1270 eigenvalues_buffer, nmo, ok, reason, &
1271 source_window_min_svalue, candidate_residual)
1280 IF (source_window)
THEN
1287 DEALLOCATE (source_kpoint, sym_index, eigenvalues_buffer, occupation_buffer, &
1288 source_eigenvalues_buffer, source_occupation_buffer)
1291 IF (sym_index(ik) /= 0)
THEN
1292 aligned_degenerate_blocks = aligned_degenerate_blocks + aligned_blocks
1293 aligned_degenerate_max_size = max(aligned_degenerate_max_size, aligned_max_size)
1294 IF (aligned_blocks > 0)
THEN
1295 aligned_degenerate_min_svalue = min(aligned_degenerate_min_svalue, aligned_min_svalue)
1300 ikpgr = ik - kp_range(1) + 1
1301 kp => kpoint%kp_env(ikpgr)%kpoint_env
1302 dst_fmr => kp%mos(1, ispin)%mo_coeff
1303 dst_fmi => kp%mos(2, ispin)%mo_coeff
1304 CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues, &
1305 occupation_numbers=occupation)
1306 eigenvalues(1:nmo) = eigenvalues_buffer(1:nmo)
1307 occupation(1:nmo) = occupation_buffer(1:nmo)
1308 CALL get_mo_set(kp%mos(2, ispin), eigenvalues=eigenvalues, &
1309 occupation_numbers=occupation)
1310 IF (
ASSOCIATED(eigenvalues)) eigenvalues(1:nmo) = eigenvalues_buffer(1:nmo)
1311 IF (
ASSOCIATED(occupation)) occupation(1:nmo) = occupation_buffer(1:nmo)
1313 NULLIFY (dst_fmr, dst_fmi)
1325 IF (source_window)
THEN
1332 DEALLOCATE (source_kpoint, sym_index, eigenvalues_buffer, occupation_buffer, &
1333 source_eigenvalues_buffer, source_occupation_buffer)
1334 IF (aligned_degenerate_blocks == 0) aligned_degenerate_min_svalue = 0.0_dp
1348 SUBROUTINE save_wannier90_mo_snapshot(kpoint, nspins, para_env, mo_real, mo_imag, &
1349 eigenvalue_snapshot)
1351 INTEGER,
INTENT(IN) :: nspins
1353 REAL(kind=
dp),
ALLOCATABLE, &
1354 DIMENSION(:, :, :, :),
INTENT(OUT) :: mo_real, mo_imag
1355 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :), &
1356 INTENT(OUT) :: eigenvalue_snapshot
1358 INTEGER :: ik, ikpgr, ispin, nao, nkp, nmo
1359 INTEGER,
DIMENSION(2) :: kp_range
1360 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: owner_weight
1361 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues
1366 kp => kpoint%kp_env(1)%kpoint_env
1367 CALL get_mo_set(kp%mos(1, 1), nao=nao, nmo=nmo)
1368 ALLOCATE (mo_real(nao, nmo, nkp, nspins), mo_imag(nao, nmo, nkp, nspins), &
1369 eigenvalue_snapshot(nmo, nkp, nspins), owner_weight(nkp, nspins))
1370 mo_real(:, :, :, :) = 0.0_dp
1371 mo_imag(:, :, :, :) = 0.0_dp
1372 eigenvalue_snapshot(:, :, :) = 0.0_dp
1373 owner_weight(:, :) = 0.0_dp
1374 DO ik = kp_range(1), kp_range(2)
1375 ikpgr = ik - kp_range(1) + 1
1376 kp => kpoint%kp_env(ikpgr)%kpoint_env
1377 DO ispin = 1, nspins
1378 fmr => kp%mos(1, ispin)%mo_coeff
1379 fmi => kp%mos(2, ispin)%mo_coeff
1382 CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues)
1383 eigenvalue_snapshot(1:nmo, ik, ispin) = eigenvalues(1:nmo)
1384 owner_weight(ik, ispin) = 1.0_dp
1387 CALL para_env%sum(mo_real)
1388 CALL para_env%sum(mo_imag)
1389 CALL para_env%sum(eigenvalue_snapshot)
1390 CALL para_env%sum(owner_weight)
1392 DO ispin = 1, nspins
1393 IF (owner_weight(ik, ispin) > 0.0_dp)
THEN
1394 mo_real(:, :, ik, ispin) = mo_real(:, :, ik, ispin)/owner_weight(ik, ispin)
1395 mo_imag(:, :, ik, ispin) = mo_imag(:, :, ik, ispin)/owner_weight(ik, ispin)
1396 eigenvalue_snapshot(:, ik, ispin) = &
1397 eigenvalue_snapshot(:, ik, ispin)/owner_weight(ik, ispin)
1401 DEALLOCATE (owner_weight)
1403 END SUBROUTINE save_wannier90_mo_snapshot
1412 SUBROUTINE restore_wannier90_mo_snapshot(kpoint, mo_real, mo_imag, eigenvalue_snapshot)
1414 REAL(kind=
dp),
DIMENSION(:, :, :, :),
INTENT(IN) :: mo_real, mo_imag
1415 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: eigenvalue_snapshot
1417 INTEGER :: ik, ikpgr, ispin, nmo, nspins
1418 INTEGER,
DIMENSION(2) :: kp_range
1419 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues
1424 nmo =
SIZE(eigenvalue_snapshot, 1)
1425 nspins =
SIZE(eigenvalue_snapshot, 3)
1426 DO ik = kp_range(1), kp_range(2)
1427 ikpgr = ik - kp_range(1) + 1
1428 kp => kpoint%kp_env(ikpgr)%kpoint_env
1429 DO ispin = 1, nspins
1430 fmr => kp%mos(1, ispin)%mo_coeff
1431 fmi => kp%mos(2, ispin)%mo_coeff
1434 CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues)
1435 eigenvalues(1:nmo) = eigenvalue_snapshot(1:nmo, ik, ispin)
1436 CALL get_mo_set(kp%mos(2, ispin), eigenvalues=eigenvalues)
1437 IF (
ASSOCIATED(eigenvalues)) eigenvalues(1:nmo) = eigenvalue_snapshot(1:nmo, ik, ispin)
1441 END SUBROUTINE restore_wannier90_mo_snapshot
1458 SUBROUTINE validate_wannier90_reused_mos(kpoint, matrix_s, cell_to_index, sab_nl, para_env, &
1459 reference_mo_real, reference_mo_imag, reference_eigenvalues, &
1460 success, max_subspace_deviation, min_svalue, &
1461 max_eigenvalue_deviation)
1463 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s
1464 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
1468 REAL(kind=
dp),
DIMENSION(:, :, :, :),
INTENT(IN) :: reference_mo_real, reference_mo_imag
1469 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: reference_eigenvalues
1470 LOGICAL,
INTENT(OUT) :: success
1471 REAL(kind=
dp),
INTENT(OUT) :: max_subspace_deviation, min_svalue, &
1472 max_eigenvalue_deviation
1474 REAL(kind=
dp),
PARAMETER :: eigenvalue_tol = 1.0e-8_dp, &
1475 subspace_tol = 1.0e-4_dp
1477 INTEGER :: ik, ikpgr, ispin, nao, nkp, nmo, nspins
1478 INTEGER,
DIMENSION(2) :: kp_range
1479 LOGICAL :: my_kpgrp, ok
1480 REAL(kind=
dp) :: candidate_deviation, candidate_svalue, &
1482 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalue_buffer
1483 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues
1485 TYPE(
cp_fm_type) :: cand_imag, cand_real, ref_imag, ref_real
1490 max_subspace_deviation = 0.0_dp
1491 min_svalue = huge(1.0_dp)
1492 max_eigenvalue_deviation = 0.0_dp
1493 NULLIFY (matrix_struct_work, fmr, fmi)
1496 kp => kpoint%kp_env(1)%kpoint_env
1497 nspins =
SIZE(kp%mos, 2)
1498 CALL get_mo_set(kp%mos(1, 1), nao=nao, nmo=nmo)
1499 cpassert(
SIZE(reference_mo_real, 1) == nao)
1500 cpassert(
SIZE(reference_mo_real, 2) == nmo)
1501 cpassert(
SIZE(reference_mo_real, 3) == nkp)
1502 cpassert(
SIZE(reference_mo_real, 4) == nspins)
1504 CALL cp_fm_get_info(kp%mos(1, 1)%mo_coeff, matrix_struct=matrix_struct_work)
1509 ALLOCATE (eigenvalue_buffer(nmo))
1511 DO ispin = 1, nspins
1515 my_kpgrp = (ik >= kp_range(1) .AND. ik <= kp_range(2))
1517 ikpgr = ik - kp_range(1) + 1
1518 kp => kpoint%kp_env(ikpgr)%kpoint_env
1519 fmr => kp%mos(1, ispin)%mo_coeff
1520 fmi => kp%mos(2, ispin)%mo_coeff
1521 CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues)
1522 eigenvalue_buffer(1:nmo) = eigenvalues(1:nmo)
1525 eigenvalue_buffer(1:nmo) = 0.0_dp
1530 owner_count = 1.0_dp
1532 owner_count = 0.0_dp
1534 CALL para_env%sum(owner_count)
1535 CALL para_env%sum(eigenvalue_buffer)
1536 IF (owner_count > 0.0_dp) eigenvalue_buffer(1:nmo) = eigenvalue_buffer(1:nmo)/owner_count
1537 max_eigenvalue_deviation = max(max_eigenvalue_deviation, &
1538 maxval(abs(eigenvalue_buffer(1:nmo) - &
1539 reference_eigenvalues(1:nmo, ik, ispin))))
1540 CALL measure_wannier90_subspace_error(ref_real, ref_imag, cand_real, cand_imag, matrix_s, &
1541 kpoint%xkp(1:3, ik), cell_to_index, sab_nl, para_env, &
1542 ok, candidate_deviation, candidate_svalue)
1544 max_subspace_deviation = huge(1.0_dp)
1546 max_subspace_deviation = max(max_subspace_deviation, candidate_deviation)
1547 min_svalue = min(min_svalue, candidate_svalue)
1551 CALL para_env%max(max_subspace_deviation)
1552 CALL para_env%min(min_svalue)
1553 CALL para_env%max(max_eigenvalue_deviation)
1554 success = max_subspace_deviation < subspace_tol .AND. max_eigenvalue_deviation < eigenvalue_tol
1556 DEALLOCATE (eigenvalue_buffer)
1562 END SUBROUTINE validate_wannier90_reused_mos
1579 SUBROUTINE diagnose_wannier90_scf_reuse_candidates(kpoint, qs_kpoint, matrix_s, matrix_ks, &
1580 cell_to_index, sab_nl, para_env, iw, &
1581 max_subspace_deviation, min_svalue, &
1582 max_metric_deviation, max_residual)
1584 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s, matrix_ks
1585 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
1589 INTEGER,
INTENT(IN) :: iw
1590 REAL(kind=
dp),
INTENT(OUT) :: max_subspace_deviation, min_svalue, &
1591 max_metric_deviation, max_residual
1593 REAL(kind=
dp),
PARAMETER :: print_tol = 1.0e-4_dp, &
1594 residual_print_tol = 1.0e-3_dp
1596 CHARACTER(LEN=default_string_length) :: reason
1597 INTEGER :: ik, ikpgr, ikred, ispin, isym_try, nao, &
1598 nao_src, nkp, nmo, nmo_src, nspins
1599 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: source_kpoint, sym_index
1600 INTEGER,
DIMENSION(2) :: kp_range, source_kp_range
1601 LOGICAL :: my_kpgrp, ok, source_window
1602 REAL(kind=
dp) :: best_deviation, best_metric_deviation, best_residual, best_svalue, &
1603 candidate_deviation, candidate_metric_deviation, candidate_metric_min, &
1604 candidate_residual, candidate_svalue, owner_count, ref_metric_deviation, ref_metric_min, &
1606 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues_buffer
1607 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues
1609 TYPE(
cp_fm_type) :: dst_imag, dst_real, ref_imag, ref_real, &
1610 src_imag, src_imag_full, src_real, &
1612 TYPE(
cp_fm_type),
POINTER :: fmi, fmr, src_fmi, src_fmr
1616 max_subspace_deviation = huge(1.0_dp)
1618 max_metric_deviation = huge(1.0_dp)
1619 max_residual = huge(1.0_dp)
1620 NULLIFY (matrix_struct_source, matrix_struct_work, fmi, fmr, src_fmi, src_fmr)
1622 CALL build_wannier90_scf_mapping(kpoint, qs_kpoint, source_kpoint, sym_index, ok, reason)
1623 IF (.NOT. ok)
RETURN
1624 kp => kpoint%kp_env(1)%kpoint_env
1625 kp_source => qs_kpoint%kp_env(1)%kpoint_env
1626 IF (
SIZE(kp%mos, 1) < 2 .OR.
SIZE(kp_source%mos, 1) < 2)
THEN
1627 DEALLOCATE (source_kpoint, sym_index)
1630 nspins =
SIZE(kp%mos, 2)
1631 CALL get_mo_set(kp%mos(1, 1), nao=nao, nmo=nmo)
1632 CALL get_mo_set(kp_source%mos(1, 1), nao=nao_src, nmo=nmo_src)
1633 CALL para_env%max(nao_src)
1634 CALL para_env%max(nmo_src)
1635 IF (nao_src /= nao .OR. nmo_src < nmo)
THEN
1636 DEALLOCATE (source_kpoint, sym_index)
1639 source_window = nmo_src > nmo
1642 IF (source_kp_range(1) /= 1 .OR. source_kp_range(2) /= qs_kpoint%nkp)
THEN
1643 DEALLOCATE (source_kpoint, sym_index)
1648 para_env=para_env, context=kpoint%blacs_env)
1655 ALLOCATE (eigenvalues_buffer(nmo))
1656 IF (source_window)
THEN
1658 para_env=para_env, context=kpoint%blacs_env)
1663 max_subspace_deviation = 0.0_dp
1664 min_svalue = huge(1.0_dp)
1665 max_metric_deviation = 0.0_dp
1666 max_residual = 0.0_dp
1667 DO ispin = 1, nspins
1669 my_kpgrp = (ik >= kp_range(1) .AND. ik <= kp_range(2))
1671 ikpgr = ik - kp_range(1) + 1
1672 kp => kpoint%kp_env(ikpgr)%kpoint_env
1673 fmr => kp%mos(1, ispin)%mo_coeff
1674 fmi => kp%mos(2, ispin)%mo_coeff
1681 ikred = source_kpoint(ik)
1682 my_kpgrp = (ikred >= source_kp_range(1) .AND. ikred <= source_kp_range(2))
1684 ikpgr = ikred - source_kp_range(1) + 1
1685 kp_source => qs_kpoint%kp_env(ikpgr)%kpoint_env
1686 src_fmr => kp_source%mos(1, ispin)%mo_coeff
1687 src_fmi => kp_source%mos(2, ispin)%mo_coeff
1688 CALL get_mo_set(kp_source%mos(1, ispin), eigenvalues=eigenvalues)
1689 eigenvalues_buffer(1:nmo) = eigenvalues(1:nmo)
1691 NULLIFY (src_fmr, src_fmi)
1692 eigenvalues_buffer(1:nmo) = 0.0_dp
1695 owner_count = 1.0_dp
1697 owner_count = 0.0_dp
1699 CALL para_env%sum(owner_count)
1700 CALL para_env%sum(eigenvalues_buffer)
1701 IF (owner_count > 0.0_dp) eigenvalues_buffer(1:nmo) = eigenvalues_buffer(1:nmo)/owner_count
1702 CALL measure_wannier90_eigenspace_quality(ref_real, ref_imag, matrix_s, matrix_ks, &
1703 kpoint%xkp(1:3, ik), cell_to_index, sab_nl, &
1704 para_env, ispin, eigenvalues_buffer, ok, &
1705 ref_metric_deviation, ref_metric_min, ref_residual)
1706 IF (ok .AND. para_env%is_source() .AND. iw > 0 .AND. &
1707 (ref_metric_deviation > print_tol .OR. ref_residual > residual_print_tol))
THEN
1708 WRITE (iw,
'(T2,A,I0,A,ES10.3,A,ES10.3,A,ES10.3)') &
1709 "WANNIER90| reference k=", ik,
" dM=", ref_metric_deviation, &
1710 " smin=", ref_metric_min,
" resid=", ref_residual
1712 IF (source_window)
THEN
1715 CALL copy_wannier90_mo_window(src_real_full, src_real, nmo)
1716 CALL copy_wannier90_mo_window(src_imag_full, src_imag, nmo)
1722 best_deviation = huge(1.0_dp)
1723 best_metric_deviation = 0.0_dp
1724 best_residual = 0.0_dp
1725 best_svalue = 0.0_dp
1726 IF (sym_index(ik) <= 0)
THEN
1728 ikred, sym_index(ik), para_env, ok, reason)
1730 CALL measure_wannier90_subspace_error(ref_real, ref_imag, dst_real, dst_imag, matrix_s, &
1731 kpoint%xkp(1:3, ik), cell_to_index, sab_nl, &
1732 para_env, ok, candidate_deviation, candidate_svalue)
1734 CALL measure_wannier90_eigenspace_quality(dst_real, dst_imag, matrix_s, matrix_ks, &
1735 kpoint%xkp(1:3, ik), cell_to_index, sab_nl, &
1736 para_env, ispin, eigenvalues_buffer, ok, &
1737 candidate_metric_deviation, &
1738 candidate_metric_min, candidate_residual)
1741 best_deviation = candidate_deviation
1742 best_metric_deviation = candidate_metric_deviation
1743 best_residual = candidate_residual
1744 best_svalue = candidate_svalue
1745 IF (para_env%is_source() .AND. iw > 0 .AND. &
1746 (candidate_deviation > print_tol .OR. candidate_metric_deviation > print_tol .OR. &
1747 candidate_residual > residual_print_tol))
THEN
1748 WRITE (iw,
'(T2,A,I0,A,I0,A,I0,A,ES10.3,A,ES10.3,A,ES10.3,A,ES10.3)') &
1749 "WANNIER90| reuse candidate k=", ik,
" src=", ikred,
" sym=", &
1750 sym_index(ik),
" dRef=", candidate_deviation,
" dM=", &
1751 candidate_metric_deviation,
" smin=", candidate_metric_min, &
1752 " resid=", candidate_residual
1756 ELSE IF (
ASSOCIATED(qs_kpoint%kp_sym))
THEN
1757 kpsym => qs_kpoint%kp_sym(ikred)%kpoint_sym
1758 IF (
ASSOCIATED(
kpsym))
THEN
1759 DO isym_try = 1,
kpsym%nwred
1761 kpsym%xkp(1:3, isym_try))) cycle
1763 qs_kpoint, ikred, isym_try, para_env, ok, reason)
1765 CALL measure_wannier90_subspace_error(ref_real, ref_imag, dst_real, dst_imag, &
1766 matrix_s, kpoint%xkp(1:3, ik), cell_to_index, &
1767 sab_nl, para_env, ok, candidate_deviation, &
1770 CALL measure_wannier90_eigenspace_quality(dst_real, dst_imag, matrix_s, matrix_ks, &
1771 kpoint%xkp(1:3, ik), cell_to_index, &
1772 sab_nl, para_env, ispin, &
1773 eigenvalues_buffer, ok, &
1774 candidate_metric_deviation, &
1775 candidate_metric_min, candidate_residual)
1777 IF (ok .AND. candidate_deviation < best_deviation)
THEN
1778 best_deviation = candidate_deviation
1779 best_metric_deviation = candidate_metric_deviation
1780 best_residual = candidate_residual
1781 best_svalue = candidate_svalue
1786 IF (best_deviation < huge(1.0_dp))
THEN
1787 max_subspace_deviation = max(max_subspace_deviation, best_deviation)
1788 min_svalue = min(min_svalue, best_svalue)
1789 max_metric_deviation = max(max_metric_deviation, best_metric_deviation)
1790 max_residual = max(max_residual, best_residual)
1794 CALL para_env%max(max_subspace_deviation)
1795 CALL para_env%min(min_svalue)
1796 CALL para_env%max(max_metric_deviation)
1797 CALL para_env%max(max_residual)
1799 IF (source_window)
THEN
1811 DEALLOCATE (eigenvalues_buffer)
1812 DEALLOCATE (source_kpoint, sym_index)
1814 END SUBROUTINE diagnose_wannier90_scf_reuse_candidates
1831 SUBROUTINE measure_wannier90_subspace_error(ref_real, ref_imag, cand_real, cand_imag, matrix_s, &
1832 xkp, cell_to_index, sab_nl, para_env, success, &
1833 max_subspace_deviation, min_svalue)
1834 TYPE(
cp_fm_type),
INTENT(IN) :: ref_real, ref_imag, cand_real, cand_imag
1835 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s
1836 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
1837 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
1841 LOGICAL,
INTENT(OUT) :: success
1842 REAL(kind=
dp),
INTENT(OUT) :: max_subspace_deviation, min_svalue
1844 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: metric_projected, metric_vectors, &
1845 overlap, ref_coeff, s_cand
1846 INTEGER :: ib, nao, nmo, nmo_candidate
1847 REAL(kind=
dp) :: singular_value
1848 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: metric_values
1849 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: ref_i, ref_r, s_cand_i, s_cand_r
1854 max_subspace_deviation = huge(1.0_dp)
1856 NULLIFY (matrix_struct_metric)
1858 CALL cp_fm_get_info(ref_real, nrow_global=nao, ncol_global=nmo, &
1859 matrix_struct=matrix_struct_metric)
1861 IF (nmo_candidate /= nmo)
RETURN
1865 CALL apply_wannier90_kp_matrix(matrix_s, 1, xkp, cell_to_index, sab_nl, &
1866 cand_real, cand_imag, s_cand_real, s_cand_imag)
1868 ALLOCATE (ref_r(nao, nmo), ref_i(nao, nmo), s_cand_r(nao, nmo), s_cand_i(nao, nmo))
1874 ALLOCATE (ref_coeff(nao, nmo), s_cand(nao, nmo), overlap(nmo, nmo), &
1875 metric_projected(nmo, nmo), metric_vectors(nmo, nmo), metric_values(nmo))
1876 ref_coeff(:, :) = cmplx(ref_r, ref_i, kind=
dp)
1877 s_cand(:, :) = cmplx(s_cand_r, s_cand_i, kind=
dp)
1878 overlap(:, :) = matmul(conjg(transpose(ref_coeff)), s_cand)
1879 metric_projected(:, :) = matmul(conjg(transpose(overlap)), overlap)
1880 metric_projected(:, :) = 0.5_dp*(metric_projected + conjg(transpose(metric_projected)))
1881 CALL diag_complex(metric_projected, metric_vectors, metric_values)
1883 min_svalue = huge(1.0_dp)
1884 max_subspace_deviation = 0.0_dp
1886 singular_value = sqrt(max(metric_values(ib), 0.0_dp))
1887 min_svalue = min(min_svalue, singular_value)
1888 max_subspace_deviation = max(max_subspace_deviation, abs(singular_value - 1.0_dp))
1890 CALL para_env%max(max_subspace_deviation)
1891 CALL para_env%min(min_svalue)
1894 DEALLOCATE (ref_coeff, s_cand, overlap, metric_projected, metric_vectors, metric_values)
1895 DEALLOCATE (ref_r, ref_i, s_cand_r, s_cand_i)
1899 END SUBROUTINE measure_wannier90_subspace_error
1918 SUBROUTINE measure_wannier90_eigenspace_quality(cand_real, cand_imag, matrix_s, matrix_ks, xkp, &
1919 cell_to_index, sab_nl, para_env, ispin, eigenvalues, &
1920 success, metric_deviation, min_metric_eigenvalue, &
1922 TYPE(
cp_fm_type),
INTENT(IN) :: cand_real, cand_imag
1923 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s, matrix_ks
1924 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
1925 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
1929 INTEGER,
INTENT(IN) :: ispin
1930 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: eigenvalues
1931 LOGICAL,
INTENT(OUT) :: success
1932 REAL(kind=
dp),
INTENT(OUT) :: metric_deviation, min_metric_eigenvalue, &
1935 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: cand_coeff, h_coeff, metric_vectors, &
1936 residual_block, s_coeff, s_projected
1937 INTEGER :: ib, nao, nmo
1938 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: metric_values
1939 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: cand_i, cand_r, h_coeff_i, h_coeff_r, &
1940 s_coeff_i, s_coeff_r
1943 matrix_struct_projected
1944 TYPE(
cp_fm_type) :: h_cand_imag, h_cand_real, s_cand_imag, &
1948 metric_deviation = huge(1.0_dp)
1949 min_metric_eigenvalue = 0.0_dp
1950 residual_norm = huge(1.0_dp)
1951 NULLIFY (matrix_struct_metric, matrix_struct_projected)
1953 CALL cp_fm_get_info(cand_real, nrow_global=nao, ncol_global=nmo, &
1954 matrix_struct=matrix_struct_metric)
1955 IF (
SIZE(eigenvalues) < nmo)
RETURN
1965 CALL apply_wannier90_kp_matrix(matrix_s, 1, xkp, cell_to_index, sab_nl, &
1966 cand_real, cand_imag, s_cand_real, s_cand_imag)
1967 CALL apply_wannier90_kp_matrix(matrix_ks, ispin, xkp, cell_to_index, sab_nl, &
1968 cand_real, cand_imag, h_cand_real, h_cand_imag)
1970 ALLOCATE (cand_r(nao, nmo), cand_i(nao, nmo), s_coeff_r(nao, nmo), &
1971 s_coeff_i(nao, nmo), h_coeff_r(nao, nmo), h_coeff_i(nao, nmo))
1979 ALLOCATE (cand_coeff(nao, nmo), h_coeff(nao, nmo), metric_vectors(nmo, nmo), &
1980 residual_block(nao, nmo), s_coeff(nao, nmo), s_projected(nmo, nmo), &
1982 cand_coeff(:, :) = cmplx(cand_r, cand_i, kind=
dp)
1983 s_coeff(:, :) = cmplx(s_coeff_r, s_coeff_i, kind=
dp)
1984 h_coeff(:, :) = cmplx(h_coeff_r, h_coeff_i, kind=
dp)
1986 para_env=matrix_struct_metric%para_env, &
1987 context=matrix_struct_metric%context)
1991 CALL cp_cfm_gemm(
"C",
"N", nmo, nmo, nao, cmplx(1.0_dp, 0.0_dp, kind=
dp), cand_cfm, &
1992 s_cfm, cmplx(0.0_dp, 0.0_dp, kind=
dp), metric_cfm)
1994 s_projected(:, :) = 0.5_dp*(s_projected + conjg(transpose(s_projected)))
1995 CALL diag_complex(s_projected, metric_vectors, metric_values)
1996 metric_deviation = maxval(abs(metric_values - 1.0_dp))
1997 min_metric_eigenvalue = minval(metric_values)
1999 residual_block(:, :) = h_coeff
2001 residual_block(:, ib) = residual_block(:, ib) - eigenvalues(ib)*s_coeff(:, ib)
2003 residual_norm = maxval(abs(residual_block))
2004 CALL para_env%max(metric_deviation)
2005 CALL para_env%min(min_metric_eigenvalue)
2006 CALL para_env%max(residual_norm)
2009 DEALLOCATE (cand_coeff, h_coeff, metric_vectors, residual_block, s_coeff, s_projected, &
2011 DEALLOCATE (cand_r, cand_i, s_coeff_r, s_coeff_i, h_coeff_r, h_coeff_i)
2022 END SUBROUTINE measure_wannier90_eigenspace_quality
2030 SUBROUTINE copy_wannier90_mo_window(source, destination, ncol)
2031 TYPE(
cp_fm_type),
INTENT(IN) :: source, destination
2032 INTEGER,
INTENT(IN) :: ncol
2034 INTEGER :: ncol_source, nrow
2035 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: destination_buffer, source_buffer
2037 CALL cp_fm_get_info(source, nrow_global=nrow, ncol_global=ncol_source)
2038 cpassert(ncol_source >= ncol)
2039 ALLOCATE (source_buffer(nrow, ncol_source), destination_buffer(nrow, ncol))
2041 destination_buffer(1:nrow, 1:ncol) = source_buffer(1:nrow, 1:ncol)
2043 DEALLOCATE (source_buffer, destination_buffer)
2045 END SUBROUTINE copy_wannier90_mo_window
2059 SUBROUTINE apply_wannier90_kp_matrix(rsmat, ispin, xkp, cell_to_index, sab_nl, &
2060 coeff_real, coeff_imag, result_real, result_imag)
2062 INTEGER,
INTENT(IN) :: ispin
2063 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
2064 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
2067 TYPE(
cp_fm_type),
INTENT(IN) :: coeff_real, coeff_imag, result_real, &
2070 INTEGER :: nao, ncol
2071 TYPE(
cp_cfm_type) :: coeff_cfm, kmat_cfm, result_cfm
2074 TYPE(
dbcsr_type),
POINTER :: kmat_imag, kmat_imag_full, kmat_real, &
2077 NULLIFY (matrix_struct_ao, matrix_struct_coeff, kmat_imag, kmat_imag_full, kmat_real, &
2080 CALL cp_fm_get_info(coeff_real, nrow_global=nao, ncol_global=ncol, &
2081 matrix_struct=matrix_struct_coeff)
2083 ALLOCATE (kmat_real, kmat_imag, kmat_real_full, kmat_imag_full)
2084 CALL dbcsr_create(kmat_real, template=rsmat(ispin, 1)%matrix, &
2085 matrix_type=dbcsr_type_symmetric)
2086 CALL dbcsr_create(kmat_imag, template=rsmat(ispin, 1)%matrix, &
2087 matrix_type=dbcsr_type_antisymmetric)
2088 CALL dbcsr_create(kmat_real_full, template=rsmat(ispin, 1)%matrix, &
2089 matrix_type=dbcsr_type_no_symmetry)
2090 CALL dbcsr_create(kmat_imag_full, template=rsmat(ispin, 1)%matrix, &
2091 matrix_type=dbcsr_type_no_symmetry)
2096 CALL rskp_transform(kmat_real, kmat_imag, rsmat=rsmat, ispin=ispin, &
2097 xkp=xkp, cell_to_index=cell_to_index, sab_nl=sab_nl)
2102 para_env=matrix_struct_coeff%para_env, &
2103 context=matrix_struct_coeff%context)
2114 CALL cp_cfm_gemm(
"N",
"N", nao, ncol, nao, cmplx(1.0_dp, 0.0_dp, kind=
dp), kmat_cfm, &
2115 coeff_cfm, cmplx(0.0_dp, 0.0_dp, kind=
dp), result_cfm)
2116 CALL cp_cfm_to_fm(result_cfm, result_real, result_imag)
2129 END SUBROUTINE apply_wannier90_kp_matrix
2150 SUBROUTINE ritz_stabilize_wannier90_subspace(dst_real, dst_imag, matrix_s, matrix_ks, &
2151 xkp, cell_to_index, sab_nl, ispin, eigenvalues, &
2152 degenerate_band_tol, success, reason, aligned_blocks, &
2153 aligned_max_size, aligned_min_svalue, max_residual)
2154 TYPE(
cp_fm_type),
INTENT(IN) :: dst_real, dst_imag
2155 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s, matrix_ks
2156 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
2157 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
2160 INTEGER,
INTENT(IN) :: ispin
2161 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: eigenvalues
2162 REAL(kind=
dp),
INTENT(IN) :: degenerate_band_tol
2163 LOGICAL,
INTENT(OUT) :: success
2164 CHARACTER(LEN=*),
INTENT(OUT) :: reason
2165 INTEGER,
INTENT(OUT) :: aligned_blocks, aligned_max_size
2166 REAL(kind=
dp),
INTENT(OUT) :: aligned_min_svalue, max_residual
2168 REAL(kind=
dp),
PARAMETER :: residual_tol = 1.0e-2_dp
2170 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: block_coeff, h_block, h_coeff, &
2171 h_projected, h_projected_work, metric_vectors, residual_block, ritz_vectors, s_block, &
2172 s_coeff, s_projected, stabilized
2173 INTEGER :: block_first, block_last, block_size, ib, &
2175 REAL(kind=
dp) :: metric_deviation, norm_value, &
2177 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: metric_values, ritz_values
2178 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: dst_i, dst_r, h_coeff_i, h_coeff_r, &
2179 s_coeff_i, s_coeff_r
2181 TYPE(
cp_fm_type) :: h_dst_imag, h_dst_real, s_dst_imag, &
2187 aligned_max_size = 0
2188 aligned_min_svalue = huge(1.0_dp)
2189 max_residual = 0.0_dp
2191 NULLIFY (matrix_struct_metric)
2192 CALL cp_fm_get_info(dst_real, nrow_global=nao, ncol_global=nmo, &
2193 matrix_struct=matrix_struct_metric)
2194 IF (
SIZE(eigenvalues) < nmo)
THEN
2195 reason =
"not enough eigenvalues for Wannier90 Ritz subspace stabilization"
2205 CALL apply_wannier90_kp_matrix(matrix_s, 1, xkp, cell_to_index, sab_nl, &
2206 dst_real, dst_imag, s_dst_real, s_dst_imag)
2207 CALL apply_wannier90_kp_matrix(matrix_ks, ispin, xkp, cell_to_index, sab_nl, &
2208 dst_real, dst_imag, h_dst_real, h_dst_imag)
2210 ALLOCATE (dst_r(nao, nmo), dst_i(nao, nmo), s_coeff_r(nao, nmo), s_coeff_i(nao, nmo), &
2211 h_coeff_r(nao, nmo), h_coeff_i(nao, nmo))
2219 ALLOCATE (s_coeff(nao, nmo), h_coeff(nao, nmo))
2220 s_coeff(:, :) = cmplx(s_coeff_r, s_coeff_i, kind=
dp)
2221 h_coeff(:, :) = cmplx(h_coeff_r, h_coeff_i, kind=
dp)
2224 DO WHILE (block_first <= nmo)
2225 block_last = block_first
2226 DO WHILE (block_last < nmo)
2227 IF (abs(eigenvalues(block_last + 1) - eigenvalues(block_last)) >= degenerate_band_tol)
EXIT
2228 block_last = block_last + 1
2230 block_size = block_last - block_first + 1
2231 IF (block_size > 1)
THEN
2235 ALLOCATE (block_coeff(nao, block_size), h_block(nao, block_size), &
2236 h_projected(block_size, block_size), h_projected_work(block_size, block_size), &
2237 metric_vectors(block_size, block_size), residual_block(nao, block_size), &
2238 ritz_vectors(block_size, block_size), s_block(nao, block_size), &
2239 s_projected(block_size, block_size), stabilized(nao, block_size), &
2240 metric_values(block_size), ritz_values(block_size))
2241 block_coeff(:, :) = cmplx(dst_r(:, block_first:block_last), &
2242 dst_i(:, block_first:block_last), kind=
dp)
2243 s_block(:, :) = s_coeff(:, block_first:block_last)
2244 h_block(:, :) = h_coeff(:, block_first:block_last)
2245 s_projected(:, :) = matmul(conjg(transpose(block_coeff)), s_block)
2246 h_projected(:, :) = matmul(conjg(transpose(block_coeff)), h_block)
2247 s_projected(:, :) = 0.5_dp*(s_projected + conjg(transpose(s_projected)))
2248 h_projected(:, :) = 0.5_dp*(h_projected + conjg(transpose(h_projected)))
2250 CALL diag_complex(s_projected, metric_vectors, metric_values)
2251 aligned_min_svalue = min(aligned_min_svalue, minval(metric_values))
2252 metric_deviation = maxval(abs(metric_values - 1.0_dp))
2253 IF (minval(metric_values) < 1.0e-10_dp)
THEN
2254 WRITE (reason,
"(A,I0,A,ES9.2,A,ES9.2)") &
2255 "singular metric blk=", block_first,
" smin=", minval(metric_values), &
2256 " dS=", metric_deviation
2257 max_residual = huge(1.0_dp)
2258 DEALLOCATE (block_coeff, h_block, h_projected, h_projected_work, metric_vectors, &
2259 residual_block, ritz_vectors, s_block, s_projected, stabilized, &
2260 metric_values, ritz_values)
2261 DEALLOCATE (s_coeff, h_coeff, dst_r, dst_i, s_coeff_r, s_coeff_i, h_coeff_r, &
2271 DO ib = 1, block_size
2272 metric_vectors(:, ib) = metric_vectors(:, ib)/sqrt(metric_values(ib))
2274 h_projected_work(:, :) = matmul(h_projected, metric_vectors)
2275 h_projected(:, :) = matmul(conjg(transpose(metric_vectors)), h_projected_work)
2276 h_projected(:, :) = 0.5_dp*(h_projected + conjg(transpose(h_projected)))
2277 CALL diag_complex(h_projected, ritz_vectors, ritz_values)
2278 h_projected_work(:, :) = matmul(metric_vectors, ritz_vectors)
2279 ritz_vectors(:, :) = h_projected_work
2280 stabilized(:, :) = matmul(block_coeff, ritz_vectors)
2281 residual_block(:, :) = matmul(h_block, ritz_vectors)
2282 h_block(:, :) = residual_block
2283 residual_block(:, :) = matmul(s_block, ritz_vectors)
2284 s_block(:, :) = residual_block
2285 DO ib = 1, block_size
2286 norm_value = sqrt(abs(real(dot_product(stabilized(:, ib), s_block(:, ib)), kind=
dp)))
2287 IF (norm_value > epsilon(1.0_dp))
THEN
2288 stabilized(:, ib) = stabilized(:, ib)/norm_value
2289 h_block(:, ib) = h_block(:, ib)/norm_value
2290 s_block(:, ib) = s_block(:, ib)/norm_value
2293 residual_block(:, :) = h_block
2294 DO ib = 1, block_size
2295 residual_block(:, ib) = residual_block(:, ib) - &
2296 eigenvalues(block_first + ib - 1)*s_block(:, ib)
2298 residual_norm = maxval(abs(residual_block))
2299 max_residual = max(max_residual, residual_norm)
2300 IF (residual_norm > residual_tol)
THEN
2301 WRITE (reason,
"(A,I0,A,ES9.2)") &
2302 "blk=", block_first,
" dS=", metric_deviation
2303 DEALLOCATE (block_coeff, h_block, h_projected, h_projected_work, metric_vectors, &
2304 residual_block, ritz_vectors, s_block, s_projected, stabilized, &
2305 metric_values, ritz_values)
2306 DEALLOCATE (s_coeff, h_coeff, dst_r, dst_i, s_coeff_r, s_coeff_i, h_coeff_r, &
2316 dst_r(:, block_first:block_last) = real(stabilized, kind=
dp)
2317 dst_i(:, block_first:block_last) = aimag(stabilized)
2318 h_coeff(:, block_first:block_last) = h_block
2319 s_coeff(:, block_first:block_last) = s_block
2320 aligned_blocks = aligned_blocks + 1
2321 aligned_max_size = max(aligned_max_size, block_size)
2322 DEALLOCATE (block_coeff, h_block, h_projected, h_projected_work, metric_vectors, &
2323 residual_block, ritz_vectors, s_block, s_projected, stabilized, metric_values, &
2326 block_first = block_last + 1
2330 residual_norm = maxval(abs(h_coeff(:, ib) - eigenvalues(ib)*s_coeff(:, ib)))
2331 max_residual = max(max_residual, residual_norm)
2333 IF (max_residual > residual_tol)
THEN
2334 WRITE (reason,
"(A,ES10.3)") &
2335 "atom/AO W90 reuse guarded: Ritz residual=", max_residual
2336 DEALLOCATE (s_coeff, h_coeff, dst_r, dst_i, s_coeff_r, s_coeff_i, h_coeff_r, h_coeff_i)
2348 IF (aligned_blocks == 0) aligned_min_svalue = 0.0_dp
2351 DEALLOCATE (s_coeff, h_coeff, dst_r, dst_i, s_coeff_r, s_coeff_i, h_coeff_r, h_coeff_i)
2358 END SUBROUTINE ritz_stabilize_wannier90_subspace
2379 SUBROUTINE ritz_reconstruct_wannier90_window(src_real, src_imag, dst_real, dst_imag, matrix_s, &
2380 matrix_ks, xkp, cell_to_index, sab_nl, ispin, &
2381 eigenvalues, nmo_export, success, reason, min_svalue, &
2383 TYPE(
cp_fm_type),
INTENT(IN) :: src_real, src_imag, dst_real, dst_imag
2384 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s, matrix_ks
2385 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
2386 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
2389 INTEGER,
INTENT(IN) :: ispin
2390 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: eigenvalues
2391 INTEGER,
INTENT(IN) :: nmo_export
2392 LOGICAL,
INTENT(OUT) :: success
2393 CHARACTER(LEN=*),
INTENT(OUT) :: reason
2394 REAL(kind=
dp),
INTENT(OUT) :: min_svalue, max_residual
2396 REAL(kind=
dp),
PARAMETER :: eigenvalue_tol = 1.0e-6_dp, &
2397 residual_tol = 1.0e-7_dp
2399 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: coeff_work, h_coeff, h_projected, &
2400 h_projected_work, metric_vectors, residual_block, ritz_vectors, s_coeff, s_projected, &
2401 source_coeff, stabilized
2402 INTEGER :: ib, nao, nmo_source
2403 REAL(kind=
dp) :: max_eigenvalue_shift, metric_deviation, &
2405 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: metric_values, ritz_values, &
2407 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: dst_i, dst_r, h_coeff_i, h_coeff_r, &
2408 s_coeff_i, s_coeff_r, src_i, src_r
2410 TYPE(
cp_fm_type) :: h_src_imag, h_src_real, s_src_imag, &
2415 min_svalue = huge(1.0_dp)
2416 max_residual = huge(1.0_dp)
2418 NULLIFY (matrix_struct_metric)
2419 CALL cp_fm_get_info(src_real, nrow_global=nao, ncol_global=nmo_source, &
2420 matrix_struct=matrix_struct_metric)
2421 IF (nmo_export > nmo_source)
THEN
2422 reason =
"Wannier90 export window is larger than the transformed SCF MO space"
2425 IF (
SIZE(eigenvalues) < nmo_export)
THEN
2426 reason =
"not enough eigenvalue storage for Wannier90 source-window reconstruction"
2436 CALL apply_wannier90_kp_matrix(matrix_s, 1, xkp, cell_to_index, sab_nl, &
2437 src_real, src_imag, s_src_real, s_src_imag)
2438 CALL apply_wannier90_kp_matrix(matrix_ks, ispin, xkp, cell_to_index, sab_nl, &
2439 src_real, src_imag, h_src_real, h_src_imag)
2441 ALLOCATE (src_r(nao, nmo_source), src_i(nao, nmo_source), &
2442 s_coeff_r(nao, nmo_source), s_coeff_i(nao, nmo_source), &
2443 h_coeff_r(nao, nmo_source), h_coeff_i(nao, nmo_source), &
2444 dst_r(nao, nmo_export), dst_i(nao, nmo_export))
2452 ALLOCATE (source_coeff(nao, nmo_source), s_coeff(nao, nmo_source), &
2453 h_coeff(nao, nmo_source), h_projected(nmo_source, nmo_source), &
2454 h_projected_work(nmo_source, nmo_source), metric_vectors(nmo_source, nmo_source), &
2455 residual_block(nao, nmo_export), ritz_vectors(nmo_source, nmo_source), &
2456 s_projected(nmo_source, nmo_source), stabilized(nao, nmo_export), &
2457 coeff_work(nao, nmo_source), metric_values(nmo_source), ritz_values(nmo_source), &
2458 source_eigenvalues(nmo_export))
2459 source_eigenvalues(1:nmo_export) = eigenvalues(1:nmo_export)
2460 source_coeff(:, :) = cmplx(src_r, src_i, kind=
dp)
2461 s_coeff(:, :) = cmplx(s_coeff_r, s_coeff_i, kind=
dp)
2462 h_coeff(:, :) = cmplx(h_coeff_r, h_coeff_i, kind=
dp)
2463 s_projected(:, :) = matmul(conjg(transpose(source_coeff)), s_coeff)
2464 h_projected(:, :) = matmul(conjg(transpose(source_coeff)), h_coeff)
2465 s_projected(:, :) = 0.5_dp*(s_projected + conjg(transpose(s_projected)))
2466 h_projected(:, :) = 0.5_dp*(h_projected + conjg(transpose(h_projected)))
2468 reconstruct_window: block
2469 CALL diag_complex(s_projected, metric_vectors, metric_values)
2470 min_svalue = minval(metric_values)
2471 metric_deviation = maxval(abs(metric_values - 1.0_dp))
2472 IF (min_svalue < 1.0e-10_dp)
THEN
2473 WRITE (reason,
"(A,ES9.2,A,ES9.2)") &
2474 "singular expanded metric smin=", min_svalue,
" dS=", metric_deviation
2475 EXIT reconstruct_window
2478 DO ib = 1, nmo_source
2479 metric_vectors(:, ib) = metric_vectors(:, ib)/sqrt(metric_values(ib))
2481 h_projected_work(:, :) = matmul(h_projected, metric_vectors)
2482 h_projected(:, :) = matmul(conjg(transpose(metric_vectors)), h_projected_work)
2483 h_projected(:, :) = 0.5_dp*(h_projected + conjg(transpose(h_projected)))
2484 CALL diag_complex(h_projected, ritz_vectors, ritz_values)
2485 h_projected_work(:, :) = matmul(metric_vectors, ritz_vectors)
2486 ritz_vectors(:, :) = h_projected_work
2487 stabilized(:, :) = matmul(source_coeff, ritz_vectors(:, 1:nmo_export))
2488 coeff_work(:, :) = matmul(h_coeff, ritz_vectors)
2489 h_coeff(:, :) = coeff_work
2490 coeff_work(:, :) = matmul(s_coeff, ritz_vectors)
2491 s_coeff(:, :) = coeff_work
2492 DO ib = 1, nmo_export
2493 norm_value = sqrt(abs(real(dot_product(stabilized(:, ib), s_coeff(:, ib)), kind=
dp)))
2494 IF (norm_value > epsilon(1.0_dp))
THEN
2495 stabilized(:, ib) = stabilized(:, ib)/norm_value
2496 h_coeff(:, ib) = h_coeff(:, ib)/norm_value
2497 s_coeff(:, ib) = s_coeff(:, ib)/norm_value
2500 residual_block(:, :) = h_coeff(:, 1:nmo_export)
2501 DO ib = 1, nmo_export
2502 residual_block(:, ib) = residual_block(:, ib) - ritz_values(ib)*s_coeff(:, ib)
2504 max_residual = maxval(abs(residual_block))
2505 IF (max_residual > residual_tol)
THEN
2506 WRITE (reason,
"(A,ES9.2)") &
2507 "expanded dS=", metric_deviation
2508 EXIT reconstruct_window
2510 max_eigenvalue_shift = maxval(abs(ritz_values(1:nmo_export) - source_eigenvalues(1:nmo_export)))
2511 IF (max_eigenvalue_shift > eigenvalue_tol)
THEN
2512 WRITE (reason,
"(A,ES9.2)") &
2513 "expanded dS=", metric_deviation
2514 EXIT reconstruct_window
2517 dst_r(:, :) = real(stabilized, kind=
dp)
2518 dst_i(:, :) = aimag(stabilized)
2523 END BLOCK reconstruct_window
2525 DEALLOCATE (source_coeff, s_coeff, h_coeff, h_projected, h_projected_work, metric_vectors, &
2526 residual_block, ritz_vectors, s_projected, stabilized, coeff_work, metric_values, &
2527 ritz_values, source_eigenvalues)
2528 DEALLOCATE (src_r, src_i, s_coeff_r, s_coeff_i, h_coeff_r, h_coeff_i, dst_r, dst_i)
2535 END SUBROUTINE ritz_reconstruct_wannier90_window
2546 SUBROUTINE build_wannier90_scf_mapping(kpoint, qs_kpoint, source_kpoint, sym_index, success, &
2548 TYPE(kpoint_type),
POINTER :: kpoint, qs_kpoint
2549 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: source_kpoint, sym_index
2550 LOGICAL,
INTENT(OUT) :: success
2551 CHARACTER(LEN=*),
INTENT(OUT) :: reason
2553 INTEGER :: ik, ikred, imatch, isym, nfull
2554 TYPE(kpoint_sym_type),
POINTER ::
kpsym
2559 ALLOCATE (source_kpoint(nfull), sym_index(nfull))
2560 source_kpoint(:) = 0
2563 DO ikred = 1, qs_kpoint%nkp
2564 imatch = find_matching_kpoint(kpoint%xkp, qs_kpoint%xkp(1:3, ikred))
2565 IF (imatch > 0 .AND. source_kpoint(imatch) == 0)
THEN
2566 source_kpoint(imatch) = ikred
2567 sym_index(imatch) = 0
2572 DO ikred = 1, qs_kpoint%nkp
2573 imatch = find_matching_kpoint(kpoint%xkp, -qs_kpoint%xkp(1:3, ikred))
2574 IF (imatch > 0 .AND. source_kpoint(imatch) == 0)
THEN
2575 source_kpoint(imatch) = ikred
2576 sym_index(imatch) = -1
2580 IF (
ASSOCIATED(qs_kpoint%kp_sym))
THEN
2581 DO ikred = 1, qs_kpoint%nkp
2582 kpsym => qs_kpoint%kp_sym(ikred)%kpoint_sym
2583 IF (.NOT.
ASSOCIATED(
kpsym)) cycle
2584 IF (.NOT.
kpsym%apply_symmetry) cycle
2585 DO isym = 1,
kpsym%nwred
2586 imatch = find_matching_kpoint(kpoint%xkp,
kpsym%xkp(1:3, isym))
2587 IF (imatch > 0 .AND. source_kpoint(imatch) == 0)
THEN
2588 source_kpoint(imatch) = ikred
2589 sym_index(imatch) = isym
2596 IF (source_kpoint(ik) == 0)
THEN
2597 reason =
"not all full-mesh k-points are represented by the SCF symmetry orbits"
2603 END SUBROUTINE build_wannier90_scf_mapping
2611 INTEGER FUNCTION find_matching_kpoint(xkp_mesh, xkp_search)
RESULT(ik_match)
2612 REAL(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: xkp_mesh
2613 REAL(kind=dp),
DIMENSION(3),
INTENT(IN) :: xkp_search
2618 DO ik = 1,
SIZE(xkp_mesh, 2)
2619 IF (kpoint_same_periodic(xkp_mesh(1:3, ik), xkp_search))
THEN
2625 END FUNCTION find_matching_kpoint
2633 SUBROUTINE infer_wannier_mp_grid(kpt_latt, mp_grid, valid)
2634 REAL(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: kpt_latt
2635 INTEGER,
DIMENSION(3),
INTENT(OUT) :: mp_grid
2636 LOGICAL,
INTENT(OUT) :: valid
2638 INTEGER :: coord_id, i, idim,
idx, n_unique, &
2639 num_kpts, stride, unique_id
2641 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: seen
2642 REAL(kind=dp) :: coord
2643 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: unique_coord
2645 num_kpts =
SIZE(kpt_latt, 2)
2647 ALLOCATE (unique_coord(3, num_kpts))
2651 coord = kpt_latt(idim, i) - floor(kpt_latt(idim, i))
2652 IF (abs(coord - 1.0_dp) < 1.0e-8_dp) coord = 0.0_dp
2654 DO unique_id = 1, n_unique
2655 IF (abs(unique_coord(idim, unique_id) - coord) < 1.0e-8_dp)
THEN
2660 IF (.NOT. known)
THEN
2661 n_unique = n_unique + 1
2662 unique_coord(idim, n_unique) = coord
2665 mp_grid(idim) = n_unique
2667 valid = (mp_grid(1)*mp_grid(2)*mp_grid(3) == num_kpts)
2669 ALLOCATE (seen(num_kpts))
2675 coord = kpt_latt(idim, i) - floor(kpt_latt(idim, i))
2676 IF (abs(coord - 1.0_dp) < 1.0e-8_dp) coord = 0.0_dp
2678 DO unique_id = 1, mp_grid(idim)
2679 IF (abs(unique_coord(idim, unique_id) - coord) < 1.0e-8_dp)
THEN
2680 coord_id = unique_id
2684 cpassert(coord_id > 0)
2685 idx =
idx + (coord_id - 1)*stride
2686 stride = stride*mp_grid(idim)
2688 IF (seen(
idx)) valid = .false.
2691 valid = valid .AND. all(seen)
2694 DEALLOCATE (unique_coord)
2696 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.
Utilities for transforming k-point MO coefficients under symmetry operations.
logical function, public kpoint_same_periodic(xkp_a, xkp_b)
Compare two fractional k-points modulo reciprocal lattice vectors.
subroutine, public kpoint_transform_scf_mo(src_real, src_imag, dst_real, dst_imag, qs_kpoint, ikred, isym, para_env, success, reason)
Transform one SCF MO coefficient matrix to an equivalent full-mesh k-point.
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, matrix_vhxc, 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...
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