103#include "./base/base_uses.f90"
108 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'qs_wannier90'
109 INTEGER,
PARAMETER,
PRIVATE :: w90_kpoints_mp_grid = 0, &
110 w90_kpoints_scf = 1, w90_kpoints_nnkp = 2, w90_kpoints_wilson = 3
112 TYPE berry_matrix_type
113 TYPE(dbcsr_p_type),
DIMENSION(:, :),
POINTER :: sinmat => null(), cosmat => null()
114 END TYPE berry_matrix_type
133 CHARACTER(len=*),
PARAMETER :: routinen =
'wannier90_interface'
135 INTEGER :: handle, i, ichern, iw, iz2, &
136 max_refinement, old_chern, old_z2, &
138 LOGICAL :: converged, explicit, require_chern, &
140 REAL(kind=
dp) :: error, movement, tolerance
141 REAL(kind=
dp),
ALLOCATABLE :: centres(:, :), previous(:, :)
146 CALL timeset(routinen, handle)
148 subsection_name=
"DFT%PRINT%WANNIER90")
155 WRITE (iw,
'(/,T2,A)') &
156 '!-----------------------------------------------------------------------------!'
157 WRITE (iw,
'(T32,A)')
"Interface to Wannier90"
158 WRITE (iw,
'(T2,A)') &
159 '!-----------------------------------------------------------------------------!'
167 IF (tolerance <= 0.0_dp) cpabort(
"WILSON_TOL must be positive.")
168 IF (source == w90_kpoints_wilson)
THEN
169 IF (max_refinement < 1 .OR. max_refinement > 10)
THEN
170 cpabort(
"WILSON_MAX_REFINEMENT must be between 1 and 10.")
175 DO refinement = 0, max_refinement
176 CALL wannier90_files(qs_env, w_input, iw, refinement, centres, iz2, ichern)
177 IF (refinement > 0)
THEN
179 DO i = 1,
SIZE(previous, 2)
180 error = max(error,
wcc_distance(previous(:, i), centres(:, 2*i - 1)))
183 DO i = 2,
SIZE(centres, 2)
184 movement = max(movement,
wcc_distance(centres(:, i - 1), centres(:, i)))
186 IF (iw > 0)
WRITE (iw,
'(T2,A,I0,A,ES12.4,A,ES12.4)') &
187 "TOPOLOGY| Refinement ", refinement,
": WCC change ", error,
", transverse step ", movement
188 converged = error < tolerance .AND. movement < 0.1_dp .AND. iz2 == old_z2
189 IF (require_z2) converged = converged .AND. iz2 >= 0 .AND.
surface_resolved(centres)
190 IF (require_chern) converged = converged .AND. ichern /= huge(0) .AND. ichern == old_chern
193 CALL move_alloc(centres, previous)
197 IF (.NOT. converged)
THEN
198 cpabort(
"Wilson surface unconverged; increase WILSON_MAX_REFINEMENT or mesh.")
201 WRITE (iw,
'(T2,A)')
"TOPOLOGY| Wilson surface sampling converged."
202 IF (iz2 >= 0)
WRITE (iw,
'(T2,A,I0)')
"TOPOLOGY| Converged Z2 invariant: ", iz2
203 IF (require_chern)
WRITE (iw,
'(T2,A,I0)')
"TOPOLOGY| Converged first Chern number: ", ichern
206 CALL wannier90_files(qs_env, w_input, iw, 0, centres, iz2, ichern)
210 WRITE (iw,
'(/,T2,A)') &
211 '!--------------------------------End of Wannier90-----------------------------!'
214 CALL timestop(handle)
228 SUBROUTINE wannier90_files(qs_env, input, iw, refinement, wcc_out, z2_value, chern_value)
231 INTEGER,
INTENT(IN) :: iw, refinement
232 REAL(kind=
dp),
ALLOCATABLE,
INTENT(OUT) :: wcc_out(:, :)
233 INTEGER,
INTENT(OUT) :: z2_value, chern_value
235 INTEGER,
PARAMETER :: num_nnmax = 12
237 CHARACTER(len=2) :: asym
238 CHARACTER(len=20),
ALLOCATABLE,
DIMENSION(:) :: atom_symbols
239 CHARACTER(len=default_path_length) :: nnkp_file
240 CHARACTER(len=default_string_length) :: filename, input_kp_scheme, reuse_reason, &
242 CHARACTER(LEN=timestamp_length) :: timestamp
243 COMPLEX(KIND=dp),
ALLOCATABLE :: export_coeff(:, :), export_scalar(:, :), link_matrix(:, :), &
244 scalar_overlap(:, :), soc_h(:, :), soc_u(:, :), soc_xyz(:, :, :), spinor_coeff(:, :, :), &
245 wilson_product(:, :, :)
246 INTEGER :: aligned_degenerate_blocks, aligned_degenerate_max_size, axis, base_mesh(2), &
247 first_point, i, i_rep, ib, ib1, ib2, ibs, ik, ik2, ikk, ikpgr, iloop, ipoint, ispin, &
248 iunit, ix, iy, iz, k, kpoints_source, loop_direction(3), n_rep, nadd, nao, nberry_images, &
249 nbs, nelectron, nexcl, nkp, nloop, nmo, nntot, npoint, nscalar, nspins, num_atoms, &
250 num_bands, num_bands_tot, num_kpts, num_wann, spin_channel, state_components, state_unit, &
252 INTEGER,
ALLOCATABLE :: loop_index(:)
253 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: band_map, exclude_bands
254 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: nblist, nnlist
255 INTEGER,
ALLOCATABLE,
DIMENSION(:, :, :) :: nncell
256 INTEGER,
DIMENSION(2) :: kp_range
257 INTEGER,
DIMENSION(3) :: input_nkp_grid, mp_grid
258 INTEGER,
DIMENSION(:),
POINTER :: invals
259 INTEGER,
DIMENSION(:, :, :),
POINTER :: berry_cell_index, cell_to_index
260 LOGICAL :: diis_step, do_chern, do_kpoints, do_soc, do_wilson, do_z2, export_state, &
261 full_mesh_diagonalized, gamma_only, input_full_grid, input_gamma_centered, &
262 input_kpoint_symmetry, lowest_bands, mp_grid_explicit, mp_grid_valid, my_kpgrp, mygrp, &
263 ordered_berry, require_global_gap, reuse_scf_mos, reused_scf_mos, spinors, time_reversal, &
264 use_bloch_phases, validate_reuse_ok, validate_reuse_scf_mos
265 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: keep_band
266 REAL(kind=
dp) :: aligned_degenerate_min_svalue, berry_phase, chern_winding, cmmn, &
267 conduction_min, direct_gap, gap_tol, gauge_arg, gauge_imag, gauge_real, gauge_tmp, ksign, &
268 link_sv, loop_origin(3), pair_gap, reuse_candidate_deviation, &
269 reuse_candidate_metric_deviation, reuse_candidate_min_svalue, reuse_candidate_residual, &
270 rmmn, transverse(3), valence_max, validation_eigenvalue_deviation, validation_min_svalue, &
271 validation_subspace_deviation, wkp_ref
272 REAL(kind=
dp),
ALLOCATABLE :: loop_sv(:), scalar_values(:), &
274 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigval
275 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: atoms_cart, b_latt, kpt_latt
276 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: reference_eigenvalues
277 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :, :) :: reference_mo_imag, reference_mo_real
278 REAL(kind=
dp),
DIMENSION(3) :: bvec, input_kp_shift, phase_center
279 REAL(kind=
dp),
DIMENSION(3, 3) :: h_inv, real_lattice, recip_lattice
280 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues, wkp, wkp_source
281 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: xkp, xkp_source
282 REAL(kind=
dp),
POINTER :: rvals(:)
283 TYPE(berry_matrix_type),
DIMENSION(:),
POINTER :: berry_matrix
286 TYPE(
cp_cfm_type) :: fmk1_cfm, fmk2_cfm, mmn_cfm, omat_cfm, &
290 TYPE(
cp_fm_type) :: mat_imag, mat_real, mmn_imag, mmn_real
292 TYPE(
cp_fm_type),
POINTER :: fmdummy, fmi, fmr
293 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_ks, matrix_s, soc_matrices
294 TYPE(
dbcsr_type),
POINTER :: cmatrix, cmatrix_full, loop_imag, &
295 loop_real, rmatrix, rmatrix_full
298 TYPE(
kpoint_type),
POINTER :: berry_kpoint, kpoint, qs_kpoint
302 POINTER :: overlap_nl, sab_nl
314 ordered_berry = kpoints_source >= w90_kpoints_nnkp
322 IF (export_state .AND. .NOT. ordered_berry)
THEN
323 cpabort(
"STATE_EXPORT requires explicit NNKP or WILSON points.")
328 IF (gap_tol <= 0.0_dp) cpabort(
"WILSON_GAP_TOL must be positive.")
330 chern_value = huge(0)
331 do_wilson = do_wilson .OR. kpoints_source == w90_kpoints_wilson
332 IF (do_wilson)
CALL cite_reference(
gresch2017)
334 IF ((do_wilson .OR. do_soc) .AND. kpoints_source < w90_kpoints_nnkp)
THEN
335 cpabort(
"Native Wilson/SOC requires KPOINTS_SOURCE NNKP or WILSON.")
337 IF (do_z2 .AND. (kpoints_source /= w90_kpoints_wilson .OR. .NOT. do_soc .OR. .NOT. time_reversal))
THEN
338 cpabort(
"Z2 requires KPOINTS_SOURCE WILSON, SOC T, and TIME_REVERSAL T.")
340 IF (do_chern .AND. (kpoints_source /= w90_kpoints_wilson .OR. do_z2))
THEN
341 cpabort(
"CHERN requires a full WILSON surface and cannot be combined with Z2.")
343 IF (require_global_gap .AND. .NOT. do_wilson)
THEN
344 cpabort(
"REQUIRE_GLOBAL_GAP requires Wilson analysis.")
346 CALL get_qs_env(qs_env, dft_control=dft_control)
347 IF (spin_channel < 1 .OR. spin_channel > dft_control%nspins)
THEN
348 cpabort(
"WANNIER90%SPIN_CHANNEL is not available in this calculation.")
350 IF (do_soc .AND. dft_control%nspins /= 1)
THEN
351 cpabort(
"WANNIER90 SOC currently requires a restricted SCF.")
358 reuse_scf_mos = reuse_scf_mos .AND. kpoints_source == w90_kpoints_scf
359 validate_reuse_scf_mos = validate_reuse_scf_mos .AND. reuse_scf_mos
360 mp_grid(1:3) = invals(1:3)
366 nexcl = nexcl +
SIZE(invals)
369 ALLOCATE (exclude_bands(nexcl))
373 exclude_bands(nexcl + 1:nexcl +
SIZE(invals)) = invals(:)
374 nexcl = nexcl +
SIZE(invals)
380 CALL get_cell(cell, h=real_lattice, h_inv=h_inv)
382 CALL get_qs_env(qs_env, particle_set=particle_set)
384 phase_center = 0.0_dp
385 DO i = 1,
SIZE(particle_set)
386 phase_center(1:3) = phase_center(1:3) + matmul(h_inv, particle_set(i)%r)
388 phase_center(1:3) = phase_center(1:3)/real(
SIZE(particle_set), kind=
dp)
389 phase_center(1:3) = phase_center(1:3) - floor(phase_center(1:3))
390 recip_lattice(1:3, 1:3) = h_inv(1:3, 1:3)
391 real_lattice(1:3, 1:3) =
angstrom*real_lattice(1:3, 1:3)
392 recip_lattice(1:3, 1:3) = (
twopi/
angstrom)*transpose(recip_lattice(1:3, 1:3))
393 NULLIFY (kpoint, qs_kpoint, xkp, wkp, xkp_source, wkp_source)
394 CALL get_qs_env(qs_env, do_kpoints=do_kpoints, kpoints=qs_kpoint)
395 input_kpoint_symmetry = .false.
396 input_full_grid = .false.
398 IF (do_kpoints .AND.
ASSOCIATED(qs_kpoint))
THEN
399 CALL get_kpoint_info(qs_kpoint, kp_scheme=input_kp_scheme, nkp_grid=input_nkp_grid, &
400 kp_shift=input_kp_shift, symmetry=input_kpoint_symmetry, &
401 full_grid=input_full_grid, gamma_centered=input_gamma_centered, &
402 nkp=nkp, xkp=xkp, wkp=wkp)
406 SELECT CASE (kpoints_source)
407 CASE (w90_kpoints_nnkp, w90_kpoints_wilson)
408 IF (kpoints_source == w90_kpoints_nnkp)
THEN
413 IF (base_mesh(1) < 2 .OR. base_mesh(2) < 2)
THEN
414 cpabort(
"WILSON_MESH entries must be at least two.")
416 npoint = base_mesh(1)*2**refinement
417 nloop = (base_mesh(2) - 1)*2**refinement + 1
419 loop_direction = invals
420 IF (all(loop_direction == 0)) cpabort(
"WILSON_DIRECTION must be nonzero.")
425 bvec = [loop_direction(2)*transverse(3) - loop_direction(3)*transverse(2), &
426 loop_direction(3)*transverse(1) - loop_direction(1)*transverse(3), &
427 loop_direction(1)*transverse(2) - loop_direction(2)*transverse(1)]
428 IF (sum(bvec**2) < 1.e-20_dp)
THEN
429 cpabort(
"Wilson loop and transverse vectors must be linearly independent.")
431 IF (do_chern .AND. maxval(abs(transverse - nint(transverse))) > 1.e-10_dp)
THEN
432 cpabort(
"CHERN requires integer WILSON_TRANSVERSE: a closed full surface, not a half-plane.")
435 IF (maxval(abs(2*loop_origin - nint(2*loop_origin))) > 1.e-10_dp .OR. &
436 maxval(abs(2*transverse - nint(2*transverse))) > 1.e-10_dp)
THEN
437 cpabort(
"Z2 surface boundaries must pass through time-reversal-invariant momenta.")
440 IF (sum(abs(loop_direction)) /= 1 .OR. &
441 abs(sum(abs(transverse)) - 0.5_dp) > 1.e-10_dp .OR. &
442 abs(dot_product(real(loop_direction,
dp), transverse)) > 1.e-10_dp)
THEN
443 cpabort(
"Native Z2 requires distinct coordinate axes with windings one and one half.")
446 num_kpts = npoint*nloop
447 ALLOCATE (kpt_latt(3, num_kpts), nnlist(num_kpts, 1), nncell(3, num_kpts, 1))
450 first_point = (iloop - 1)*npoint + 1
451 DO ipoint = 1, npoint
452 i = first_point + ipoint - 1
453 kpt_latt(:, i) = loop_origin + real(iloop - 1,
dp)/real(nloop - 1,
dp)*transverse + &
454 REAL(ipoint - 1,
dp)/
REAL(npoint,
dp)*loop_direction
457 nnlist(i, 1) = first_point
458 nncell(:, i, 1) = loop_direction
461 num_kpts =
SIZE(kpt_latt, 2)
462 nntot =
SIZE(nnlist, 2)
463 kpoint%kp_scheme =
"GENERAL"
464 kpoint%symmetry = .false.
465 kpoint%verbose = .false.
466 kpoint%full_grid = .true.
467 kpoint%eps_geo = 1.0e-6_dp
468 kpoint%use_real_wfn = .false.
469 kpoint%parallel_group_size = para_env%num_pe
470 kpoint%nkp = num_kpts
471 ALLOCATE (kpoint%xkp(3, num_kpts), kpoint%wkp(num_kpts))
472 kpoint%xkp = kpt_latt
474 kpoint%wkp = 1.0_dp/real(num_kpts, kind=
dp)
475 IF (iw > 0)
WRITE (iw,
'(T2,A,I0,A,I0)') &
476 "WANNIER90| Explicit points: ", num_kpts,
", neighbours per point: ", nntot
477 CASE (w90_kpoints_mp_grid)
478 num_kpts = mp_grid(1)*mp_grid(2)*mp_grid(3)
479 ALLOCATE (kpt_latt(3, num_kpts))
480 kpoint%kp_scheme =
"MONKHORST-PACK"
481 kpoint%symmetry = .false.
482 kpoint%nkp_grid(1:3) = mp_grid(1:3)
483 kpoint%verbose = .false.
484 kpoint%full_grid = .true.
485 kpoint%eps_geo = 1.0e-6_dp
486 kpoint%use_real_wfn = .false.
487 kpoint%parallel_group_size = para_env%num_pe
489 DO ix = 0, mp_grid(1) - 1
490 DO iy = 0, mp_grid(2) - 1
491 DO iz = 0, mp_grid(3) - 1
493 kpt_latt(1, i) = real(ix, kind=
dp)/real(mp_grid(1), kind=
dp)
494 kpt_latt(2, i) = real(iy, kind=
dp)/real(mp_grid(2), kind=
dp)
495 kpt_latt(3, i) = real(iz, kind=
dp)/real(mp_grid(3), kind=
dp)
499 kpoint%nkp = num_kpts
500 ALLOCATE (kpoint%xkp(3, num_kpts), kpoint%wkp(num_kpts))
501 kpoint%wkp(:) = 1._dp/real(num_kpts, kind=
dp)
503 kpoint%xkp(1:3, i) = (
angstrom/
twopi)*matmul(recip_lattice, kpt_latt(:, i))
506 CASE (w90_kpoints_scf)
507 IF (.NOT. do_kpoints .OR. .NOT.
ASSOCIATED(qs_kpoint))
THEN
508 cpabort(
"WANNIER90%KPOINTS_SOURCE SCF requires an active DFT%KPOINTS section.")
510 SELECT CASE (trim(input_kp_scheme))
514 ALLOCATE (kpt_latt(3, num_kpts))
515 kpt_latt(1:3, 1) = 0.0_dp
516 kpoint%kp_scheme =
"GAMMA"
517 kpoint%symmetry = .false.
518 kpoint%verbose = .false.
519 kpoint%full_grid = .true.
520 kpoint%eps_geo = 1.0e-6_dp
521 kpoint%use_real_wfn = .false.
522 kpoint%parallel_group_size = para_env%num_pe
523 kpoint%nkp = num_kpts
524 ALLOCATE (kpoint%xkp(3, num_kpts), kpoint%wkp(num_kpts))
525 kpoint%xkp(1:3, 1) = 0.0_dp
526 kpoint%wkp(1) = 1.0_dp
528 CASE (
"MONKHORST-PACK",
"MACDONALD")
529 mp_grid(1:3) = input_nkp_grid(1:3)
530 kpoint%kp_scheme = input_kp_scheme
531 kpoint%symmetry = .false.
532 kpoint%nkp_grid(1:3) = input_nkp_grid(1:3)
533 kpoint%kp_shift(1:3) = input_kp_shift(1:3)
534 kpoint%gamma_centered = input_gamma_centered
535 kpoint%verbose = .false.
536 kpoint%full_grid = .true.
537 kpoint%eps_geo = 1.0e-6_dp
538 kpoint%use_real_wfn = .false.
539 kpoint%parallel_group_size = para_env%num_pe
541 num_kpts = kpoint%nkp
542 ALLOCATE (kpt_latt(3, num_kpts))
543 kpt_latt(1:3, 1:num_kpts) = kpoint%xkp(1:3, 1:num_kpts)
544 IF (input_kpoint_symmetry .AND. .NOT. input_full_grid .AND. iw > 0)
THEN
545 WRITE (iw,
'(T2,A)') &
546 "WANNIER90| SCF k-points are symmetry-reduced; regenerating the full SCF mesh."
547 IF (reuse_scf_mos)
THEN
548 WRITE (iw,
'(T2,A)') &
549 "WANNIER90| CP2K will try to reconstruct the full-mesh MOs from the SCF orbitals."
551 WRITE (iw,
'(T2,A)') &
552 "WANNIER90| The full exported mesh is diagonalized for the Wannier90 files."
557 IF (
ASSOCIATED(qs_kpoint%xkp_input))
THEN
558 xkp_source => qs_kpoint%xkp_input
559 wkp_source => qs_kpoint%wkp_input
564 IF (.NOT.
ASSOCIATED(xkp_source) .OR. .NOT.
ASSOCIATED(wkp_source))
THEN
565 cpabort(
"Could not access the SCF GENERAL k-point set for the Wannier90 export.")
567 num_kpts =
SIZE(wkp_source)
568 ALLOCATE (kpt_latt(3, num_kpts))
569 kpt_latt(1:3, 1:num_kpts) = xkp_source(1:3, 1:num_kpts)
570 IF (mp_grid_explicit)
THEN
571 IF (mp_grid(1)*mp_grid(2)*mp_grid(3) /= num_kpts)
THEN
572 cpabort(
"WANNIER90%MP_GRID must contain exactly as many points as the SCF GENERAL mesh.")
575 CALL infer_wannier_mp_grid(kpt_latt, mp_grid, mp_grid_valid)
576 IF (.NOT. mp_grid_valid)
THEN
577 cpabort(
"Could not infer WANNIER90%MP_GRID from the SCF GENERAL mesh.")
580 wkp_ref = 1.0_dp/real(num_kpts, kind=
dp)
582 IF (abs(wkp_source(i) - wkp_ref) > 1.0e-10_dp)
THEN
583 cpabort(
"WANNIER90%KPOINTS_SOURCE SCF requires equally weighted GENERAL k-points.")
586 kpoint%kp_scheme =
"GENERAL"
587 kpoint%symmetry = .false.
588 kpoint%nkp_grid(1:3) = mp_grid(1:3)
589 kpoint%verbose = .false.
590 kpoint%full_grid = .true.
591 kpoint%eps_geo = 1.0e-6_dp
592 kpoint%use_real_wfn = .false.
593 kpoint%parallel_group_size = para_env%num_pe
594 kpoint%nkp = num_kpts
595 ALLOCATE (kpoint%xkp(3, num_kpts), kpoint%wkp(num_kpts))
596 kpoint%xkp(1:3, 1:num_kpts) = xkp_source(1:3, 1:num_kpts)
597 kpoint%wkp(1:num_kpts) = wkp_ref
598 IF (input_kpoint_symmetry .AND. .NOT. input_full_grid .AND. iw > 0)
THEN
599 WRITE (iw,
'(T2,A)') &
600 "WANNIER90| SCF k-points are symmetry-reduced; using the full input GENERAL mesh."
601 IF (reuse_scf_mos)
THEN
602 WRITE (iw,
'(T2,A)') &
603 "WANNIER90| CP2K will try to reconstruct the full-mesh MOs from the SCF orbitals."
605 WRITE (iw,
'(T2,A)') &
606 "WANNIER90| The full exported mesh is diagonalized for the Wannier90 files."
611 cpabort(
"WANNIER90%KPOINTS_SOURCE SCF does not support this DFT%KPOINTS scheme.")
614 cpabort(
"Unknown WANNIER90%KPOINTS_SOURCE setting.")
618 CALL get_mo_set(mo_set=mos(1), nao=nao, nmo=num_bands_tot, nelectron=nelectron)
619 num_bands_tot = min(nao, num_bands_tot + nadd)
620 nscalar = num_bands_tot
621 IF (do_soc) num_bands_tot = 2*nscalar
622 ALLOCATE (keep_band(num_bands_tot))
625 ib = exclude_bands(i)
626 IF (ib < 1 .OR. ib > num_bands_tot) cpabort(
"WANNIER90%EXCLUDE_BANDS: index out of range.")
627 IF (.NOT. keep_band(ib)) cpabort(
"WANNIER90%EXCLUDE_BANDS: duplicate band index.")
628 keep_band(ib) = .false.
630 num_bands = count(keep_band)
631 IF (num_bands == 0) cpabort(
"WANNIER90: no bands left after EXCLUDE_BANDS.")
632 ALLOCATE (band_map(num_bands))
633 band_map(:) = pack([(i, i=1, num_bands_tot)], keep_band)
634 DEALLOCATE (keep_band)
635 lowest_bands = num_bands < num_bands_tot .AND. all(band_map == [(i, i=1, num_bands)])
636 IF (require_global_gap .AND. .NOT. lowest_bands)
THEN
637 cpabort(
"REQUIRE_GLOBAL_GAP needs a lowest-band prefix and an excluded band above it.")
640 IF (num_bands /= nelectron)
THEN
641 cpabort(
"Z2 requires one occupied spinor per electron; adjust EXCLUDE_BANDS.")
643 IF (num_bands == num_bands_tot .OR. mod(num_bands, 2) /= 0)
THEN
644 cpabort(
"Z2 needs an even occupied spinor subspace and at least one excluded conduction band.")
646 IF (any(band_map /= [(i, i=1, num_bands)]))
THEN
647 cpabort(
"Z2 requires the lowest occupied spinor bands.")
651 IF (nntot /= 1) cpabort(
"WILSON_LOOP requires exactly one directed neighbour per point.")
652 ALLOCATE (loop_index(num_kpts))
655 DO WHILE (i <= num_kpts)
659 loop_index(i) = nloop
660 IF (nnlist(i, 1) == first_point)
EXIT
661 IF (nnlist(i, 1) /= i + 1 .OR. i == num_kpts)
THEN
662 cpabort(
"WILSON_LOOP requires contiguous ordered closed loops.")
668 ALLOCATE (wilson_product(num_bands, num_bands, nloop), loop_sv(nloop))
669 wilson_product = cmplx(0.0_dp, 0.0_dp,
dp)
671 wilson_product(i, i, :) = cmplx(1.0_dp, 0.0_dp,
dp)
674 ALLOCATE (wcc_out(num_bands, nloop))
676 ALLOCATE (wcc_out(0, 0))
678 ALLOCATE (link_matrix(num_bands, num_bands))
679 IF (use_bloch_phases .AND. num_wann /= num_bands)
THEN
680 cpabort(
"WANNIER90%USE_BLOCH_PHASES requires WANNIER_FUNCTIONS to match the number of bands.")
682 num_atoms =
SIZE(particle_set)
683 ALLOCATE (atoms_cart(3, num_atoms))
684 ALLOCATE (atom_symbols(num_atoms))
686 atoms_cart(1:3, i) = particle_set(i)%r(1:3)
688 atom_symbols(i) = asym
693 IF (kpoints_source < w90_kpoints_nnkp)
THEN
694 ALLOCATE (nnlist(num_kpts, num_nnmax))
695 ALLOCATE (nncell(3, num_kpts, num_nnmax))
700 CALL wannier_setup(mp_grid, num_kpts, real_lattice, recip_lattice, &
701 kpt_latt, nntot, nnlist, nncell, iw)
703 CALL para_env%sum(nntot)
704 CALL para_env%sum(nnlist)
705 CALL para_env%sum(nncell)
710 IF (para_env%is_source() .AND. kpoints_source < w90_kpoints_nnkp)
THEN
712 WRITE (filename,
'(A,A)') trim(seed_name),
".win"
713 CALL open_file(filename, unit_number=iunit, file_status=
"UNKNOWN", file_action=
"WRITE")
716 WRITE (iunit,
"(A)")
"! Wannier90 input file generated by CP2K "
717 WRITE (iunit,
"(A,/)")
"! Creation date "//timestamp
719 WRITE (iunit,
"(A,I5)")
"num_wann = ", num_wann
720 IF (num_bands /= num_wann .OR. use_bloch_phases)
THEN
721 WRITE (iunit,
"(A,I5)")
"num_bands = ", num_bands
723 IF (use_bloch_phases)
THEN
726 WRITE (iunit,
"(A)")
"! CP2K writes identity projections for Bloch-phase complete subspaces."
728 WRITE (iunit,
"(/,A,/)")
"length_unit = bohr "
729 WRITE (iunit,
"(/,A,/)")
"! System"
730 WRITE (iunit,
"(/,A)")
"begin unit_cell_cart"
731 WRITE (iunit,
"(A)")
"bohr"
733 WRITE (iunit,
"(3F12.6)") cell%hmat(i, 1:3)
735 WRITE (iunit,
"(A,/)")
"end unit_cell_cart"
736 WRITE (iunit,
"(/,A)")
"begin atoms_cart"
737 WRITE (iunit,
"(A)")
"bohr"
739 WRITE (iunit,
"(A,3F15.10)") atom_symbols(i), atoms_cart(1:3, i)
741 WRITE (iunit,
"(A,/)")
"end atoms_cart"
742 WRITE (iunit,
"(/,A,/)")
"! Kpoints"
743 WRITE (iunit,
"(/,A,3I6/)")
"mp_grid = ", mp_grid(1:3)
744 WRITE (iunit,
"(A)")
"begin kpoints"
746 WRITE (iunit,
"(3F12.6)") kpt_latt(1:3, i)
748 WRITE (iunit,
"(A)")
"end kpoints"
750 IF (use_bloch_phases)
THEN
751 WRITE (filename,
'(A,A)') trim(seed_name),
".amn"
752 CALL open_file(filename, unit_number=iunit, file_status=
"UNKNOWN", file_action=
"WRITE")
753 WRITE (iunit,
"(A)")
"! Wannier90 identity projections generated by CP2K"
754 WRITE (iunit,
"(3I8)") num_bands, num_kpts, num_wann
757 DO ib1 = 1, num_bands
759 WRITE (iunit,
"(3I8,2E30.14)") ib1, ib2, ik, 1.0_dp, 0.0_dp
761 WRITE (iunit,
"(3I8,2E30.14)") ib1, ib2, ik, 0.0_dp, 0.0_dp
774 IF (kpoints_source == w90_kpoints_mp_grid .AND. input_kpoint_symmetry .AND. iw > 0)
THEN
775 WRITE (iw,
'(T2,A)') &
776 "WANNIER90| Atomic k-point symmetry from the SCF calculation is not reused."
777 WRITE (iw,
'(T2,A)') &
778 "WANNIER90| A full Monkhorst-Pack grid is generated for the Wannier90 interface."
789 WRITE (unit=iw, fmt=
"(/,T2,A)")
"Start K-Point Calculation ..."
791 CALL get_qs_env(qs_env=qs_env_kp, para_env=para_env, blacs_env=blacs_env)
796 CALL get_qs_env(qs_env=qs_env_kp, sab_orb=sab_nl, dft_control=dft_control)
799 CALL get_qs_env(qs_env=qs_env_kp, matrix_ks_kp=matrix_ks, matrix_s_kp=matrix_s, &
800 scf_env=scf_env, scf_control=scf_control)
801 full_mesh_diagonalized = .false.
802 reused_scf_mos = .false.
804 aligned_degenerate_blocks = 0
805 aligned_degenerate_max_size = 0
806 aligned_degenerate_min_svalue = 0.0_dp
807 IF (reuse_scf_mos)
THEN
809 CALL do_general_diag_kp(matrix_ks, matrix_s, qs_kpoint, scf_env, scf_control, .false., &
811 IF (validate_reuse_scf_mos)
THEN
813 WRITE (iw,
'(T2,A)') &
814 "WANNIER90| Validating SCF MO reuse against a full-mesh diagonalization reference."
816 CALL do_general_diag_kp(matrix_ks, matrix_s, kpoint, scf_env, scf_control, .false., diis_step)
817 full_mesh_diagonalized = .true.
818 nspins = dft_control%nspins
819 CALL save_wannier90_mo_snapshot(kpoint, nspins, para_env, reference_mo_real, &
820 reference_mo_imag, reference_eigenvalues)
821 CALL diagnose_wannier90_scf_reuse_candidates(kpoint, qs_kpoint, matrix_s, matrix_ks, &
822 cell_to_index, sab_nl, para_env, iw, &
823 reuse_candidate_deviation, &
824 reuse_candidate_min_svalue, &
825 reuse_candidate_metric_deviation, &
826 reuse_candidate_residual)
827 IF (iw > 0 .AND. reuse_candidate_deviation < 1.0e100_dp)
THEN
828 WRITE (iw,
'(T2,A,ES10.3,A,ES10.3,A,ES10.3,A,ES10.3)') &
829 "WANNIER90| Best atom/AO candidate subspace deviation ", &
830 reuse_candidate_deviation,
", minimum singular value ", &
831 reuse_candidate_min_svalue,
", max metric deviation ", &
832 reuse_candidate_metric_deviation,
", max residual ", reuse_candidate_residual
836 sab_nl, para_env, reused_scf_mos, reuse_reason, &
837 aligned_degenerate_blocks, aligned_degenerate_max_size, &
838 aligned_degenerate_min_svalue)
839 IF (validate_reuse_scf_mos)
THEN
840 IF (reused_scf_mos)
THEN
841 CALL validate_wannier90_reused_mos(kpoint, matrix_s, cell_to_index, sab_nl, &
842 para_env, reference_mo_real, reference_mo_imag, &
843 reference_eigenvalues, validate_reuse_ok, &
844 validation_subspace_deviation, validation_min_svalue, &
845 validation_eigenvalue_deviation)
847 WRITE (iw,
'(T2,A,ES10.3,A,ES10.3,A,ES10.3)') &
848 "WANNIER90| Reused MO validation: subspace deviation ", &
849 validation_subspace_deviation,
", minimum singular value ", &
850 validation_min_svalue,
", eigenvalue deviation ", &
851 validation_eigenvalue_deviation
853 IF (.NOT. validate_reuse_ok)
THEN
854 reused_scf_mos = .false.
855 WRITE (reuse_reason,
"(A,ES10.3,A,ES10.3)") &
856 "validation failed: dS=", &
857 validation_subspace_deviation,
", dE=", validation_eigenvalue_deviation
860 IF (.NOT. reused_scf_mos)
THEN
861 CALL restore_wannier90_mo_snapshot(kpoint, reference_mo_real, reference_mo_imag, &
862 reference_eigenvalues)
866 IF (reused_scf_mos)
THEN
867 WRITE (iw,
'(T2,A)') &
868 "WANNIER90| Reused SCF MO coefficients for the Wannier90 full k-point mesh."
869 IF (use_bloch_phases)
THEN
870 WRITE (iw,
'(T2,A)') &
871 "WANNIER90| Wrote identity projections for Bloch-phase complete band subspaces."
872 WRITE (iw,
'(T2,A,3F10.6)') &
873 "WANNIER90| Applied Bloch phase gauge to reused overlaps around fractional center", &
876 IF (aligned_degenerate_blocks > 0)
THEN
877 WRITE (iw,
'(T2,A,I0,A,I0,A,ES10.3)') &
878 "WANNIER90| Ritz-stabilized ", aligned_degenerate_blocks, &
879 " degenerate SCF MO subspace(s) with S(k),H(k); largest block has ", &
880 aligned_degenerate_max_size,
" band(s), min metric eigenvalue ", &
881 aligned_degenerate_min_svalue
884 WRITE (iw,
'(T2,A,A)') &
885 "WANNIER90| Could not reuse SCF MOs: ", trim(reuse_reason)
886 WRITE (iw,
'(T2,A)') &
887 "WANNIER90| Falling back to full-mesh diagonalization for the Wannier90 files."
891 IF (.NOT. reused_scf_mos .AND. .NOT. full_mesh_diagonalized)
THEN
892 CALL do_general_diag_kp(matrix_ks, matrix_s, kpoint, scf_env, scf_control, .false., diis_step)
894 IF (
ALLOCATED(reference_mo_real))
DEALLOCATE (reference_mo_real)
895 IF (
ALLOCATED(reference_mo_imag))
DEALLOCATE (reference_mo_imag)
896 IF (
ALLOCATED(reference_eigenvalues))
DEALLOCATE (reference_eigenvalues)
899 WRITE (iw,
'(T69,A)')
"... Finished"
904 IF (para_env%is_source())
THEN
905 WRITE (filename,
'(A,A)') trim(seed_name),
".mmn"
906 CALL open_file(filename, unit_number=iunit, file_status=
"UNKNOWN", file_action=
"WRITE")
908 WRITE (iunit,
"(A)")
"! Wannier90 file generated by CP2K "//timestamp
909 WRITE (iunit,
"(3I8)") num_bands, num_kpts, nntot
915 ALLOCATE (nblist(num_kpts, nntot))
916 ALLOCATE (b_latt(3, num_kpts*nntot))
921 bvec(1:3) = kpt_latt(1:3, nnlist(ik, i)) - kpt_latt(1:3, ik) + nncell(1:3, ik, i)
924 IF (sum(abs(bvec(1:3) - b_latt(1:3, k))) < 1.e-6_dp)
THEN
928 IF (sum(abs(bvec(1:3) + b_latt(1:3, k))) < 1.e-6_dp)
THEN
939 b_latt(1:3, nbs) = bvec(1:3)
946 NULLIFY (berry_kpoint)
947 IF (ordered_berry)
THEN
948 CALL get_qs_env(qs_env_kp, sab_all=overlap_nl)
953 IF (.NOT.
ASSOCIATED(overlap_nl)) cpabort(
"Explicit overlaps require k-point neighbour lists.")
954 ALLOCATE (berry_matrix(nbs))
956 NULLIFY (berry_matrix(i)%cosmat)
957 NULLIFY (berry_matrix(i)%sinmat)
958 bvec(1:3) =
twopi*matmul(transpose(cell%h_inv(1:3, 1:3)), b_latt(1:3, i))
959 IF (ordered_berry) bvec = -bvec
961 berry_matrix(i)%sinmat, bvec, ordered=ordered_berry, ordered_kpoints=berry_kpoint)
964 kp => kpoint%kp_env(1)%kpoint_env
966 IF (nmo /= nscalar) cpabort(
"WANNIER90: unexpected orbital count in export.")
967 NULLIFY (matrix_struct_ao, matrix_struct_work)
987 NULLIFY (matrix_struct_mmn)
996 ALLOCATE (rmatrix, cmatrix, rmatrix_full, cmatrix_full)
997 CALL dbcsr_create(rmatrix, template=matrix_s(1, 1)%matrix, &
998 matrix_type=dbcsr_type_symmetric)
999 CALL dbcsr_create(cmatrix, template=matrix_s(1, 1)%matrix, &
1000 matrix_type=dbcsr_type_antisymmetric)
1001 CALL dbcsr_create(rmatrix_full, template=matrix_s(1, 1)%matrix, &
1002 matrix_type=dbcsr_type_no_symmetry)
1003 CALL dbcsr_create(cmatrix_full, template=matrix_s(1, 1)%matrix, &
1004 matrix_type=dbcsr_type_no_symmetry)
1007 IF (ordered_berry)
THEN
1008 ALLOCATE (loop_real, loop_imag)
1009 CALL dbcsr_create(loop_real, template=matrix_s(1, 1)%matrix, matrix_type=dbcsr_type_no_symmetry)
1010 CALL dbcsr_create(loop_imag, template=matrix_s(1, 1)%matrix, matrix_type=dbcsr_type_no_symmetry)
1019 nspins = dft_control%nspins
1022 cpassert(all(kpoint%kp_range == [1, num_kpts]))
1023 NULLIFY (soc_matrices)
1025 ALLOCATE (soc_xyz(nmo, nmo, 3), soc_h(2*nmo, 2*nmo), soc_u(2*nmo, 2*nmo))
1026 ALLOCATE (scalar_values(2*nmo), spinor_values(2*nmo, num_kpts))
1027 ALLOCATE (spinor_coeff(2*nmo, num_bands, num_kpts), scalar_overlap(nmo, nmo))
1029 kp => kpoint%kp_env(ik)%kpoint_env
1030 fmr => kp%mos(1, 1)%mo_coeff
1031 fmi => kp%mos(2, 1)%mo_coeff
1035 CALL get_mo_set(kp%mos(1, 1), eigenvalues=eigenvalues)
1036 scalar_values(1:nmo) = eigenvalues(1:nmo)
1037 scalar_values(nmo + 1:) = eigenvalues(1:nmo)
1041 CALL rskp_transform(cmatrix, rmatrix, rsmat=soc_matrices, ispin=axis, &
1042 xkp=kpoint%xkp(:, ik), cell_to_index=cell_to_index, sab_nl=sab_nl)
1049 CALL cp_cfm_gemm(
"N",
"N", nao, nmo, nao, cmplx(1.0_dp, 0.0_dp,
dp), &
1050 omat_cfm, fmk1_cfm, cmplx(0.0_dp, 0.0_dp,
dp), tmp_cfm)
1051 CALL cp_cfm_gemm(
"C",
"N", nmo, nmo, nao, cmplx(1.0_dp, 0.0_dp,
dp), &
1052 fmk1_cfm, tmp_cfm, cmplx(0.0_dp, 0.0_dp,
dp), mmn_cfm)
1055 soc_h(1:nmo, 1:nmo) = soc_xyz(:, :, 3)
1056 soc_h(nmo + 1:, nmo + 1:) = -soc_xyz(:, :, 3)
1058 soc_h(1:nmo, nmo + 1:) = soc_xyz(:, :, 1) + cmplx(0.0_dp, 1.0_dp,
dp)*soc_xyz(:, :, 2)
1059 soc_h(nmo + 1:, 1:nmo) = soc_xyz(:, :, 1) - cmplx(0.0_dp, 1.0_dp,
dp)*soc_xyz(:, :, 2)
1061 soc_h(ib, ib) = soc_h(ib, ib) + scalar_values(ib)
1063 IF (maxval(abs(soc_h - conjg(transpose(soc_h)))) > 1.e-8_dp)
THEN
1064 IF (iw > 0)
WRITE (iw,
'(T2,A,I0,A,ES18.10)') &
1065 "TOPOLOGY| SOC Hermiticity error at point ", ik,
": ", &
1066 maxval(abs(soc_h - conjg(transpose(soc_h))))
1067 cpabort(
"WANNIER90 SOC: non-Hermitian second-variational Hamiltonian.")
1070 spinor_coeff(:, :, ik) = soc_u(:, band_map)
1073 DEALLOCATE (soc_xyz, soc_h, soc_u, scalar_values)
1074 IF (iw > 0)
WRITE (iw,
'(T2,A,I0)')
"TOPOLOGY| Scalar bands in SOC second variation: ", nmo
1076 DO ispin = spin_channel, spin_channel
1080 my_kpgrp = (ik >= kpoint%kp_range(1) .AND. ik <= kpoint%kp_range(2))
1082 ikk = ik - kpoint%kp_range(1) + 1
1083 kp => kpoint%kp_env(ikk)%kpoint_env
1084 cpassert(
SIZE(kp%mos, 1) == 2)
1085 fmr => kp%mos(1, ispin)%mo_coeff
1086 fmi => kp%mos(2, ispin)%mo_coeff
1090 NULLIFY (fmr, fmi, kp)
1099 mygrp = (ik2 >= kpoint%kp_range(1) .AND. ik2 <= kpoint%kp_range(2))
1101 ikk = ik2 - kpoint%kp_range(1) + 1
1102 kp => kpoint%kp_env(ikk)%kpoint_env
1103 cpassert(
SIZE(kp%mos, 1) == 2)
1104 fmr => kp%mos(1, ispin)%mo_coeff
1105 fmi => kp%mos(2, ispin)%mo_coeff
1109 NULLIFY (fmr, fmi, kp)
1117 ksign = sign(1.0_dp, real(ibs, kind=
dp))
1119 IF (ordered_berry)
THEN
1126 CALL rskp_transform(rmatrix_full, cmatrix_full, berry_matrix(ibs)%cosmat, 1, &
1127 kpoint%xkp(:, ik2), berry_cell_index, overlap_nl)
1128 CALL rskp_transform(loop_real, loop_imag, berry_matrix(ibs)%sinmat, 1, &
1129 kpoint%xkp(:, ik2), berry_cell_index, overlap_nl, rs_sign=ksign)
1130 CALL dbcsr_add(rmatrix_full, loop_imag, 1.0_dp, -1.0_dp)
1131 CALL dbcsr_add(cmatrix_full, loop_real, 1.0_dp, 1.0_dp)
1135 CALL rskp_transform(rmatrix, cmatrix, rsmat=berry_matrix(ibs)%cosmat, ispin=1, &
1136 xkp=kpoint%xkp(1:3, ik2), cell_to_index=cell_to_index, sab_nl=sab_nl, &
1137 is_complex=.false., rs_sign=ksign)
1138 CALL rskp_transform(cmatrix, rmatrix, rsmat=berry_matrix(ibs)%sinmat, ispin=1, &
1139 xkp=kpoint%xkp(1:3, ik2), cell_to_index=cell_to_index, sab_nl=sab_nl, &
1140 is_complex=.true., rs_sign=ksign)
1149 CALL cp_cfm_gemm(
"N",
"N", nao, nmo, nao, cmplx(1.0_dp, 0.0_dp, kind=
dp), &
1150 omat_cfm, fmk2_cfm, cmplx(0.0_dp, 0.0_dp, kind=
dp), tmp_cfm)
1151 CALL cp_cfm_gemm(
"C",
"N", nmo, nmo, nao, cmplx(1.0_dp, 0.0_dp, kind=
dp), &
1152 fmk1_cfm, tmp_cfm, cmplx(0.0_dp, 0.0_dp, kind=
dp), mmn_cfm)
1156 link_matrix(:, :) = matmul(conjg(transpose(spinor_coeff(1:nmo, :, ik))), &
1157 matmul(scalar_overlap, spinor_coeff(1:nmo, :, ik2))) + &
1158 matmul(conjg(transpose(spinor_coeff(nmo + 1:, :, ik))), &
1159 matmul(scalar_overlap, spinor_coeff(nmo + 1:, :, ik2)))
1163 IF (reused_scf_mos .AND. use_bloch_phases)
THEN
1165 gauge_arg =
twopi*dot_product(kpoint%xkp(1:3, ik2) - kpoint%xkp(1:3, ik), &
1167 gauge_real = cos(gauge_arg)
1168 gauge_imag = sin(gauge_arg)
1173 IF (para_env%is_source())
THEN
1174 WRITE (iunit,
"(2I8,3I5)") ik, ik2, nncell(1:3, ik, i)
1176 DO ib2 = 1, num_bands
1177 DO ib1 = 1, num_bands
1179 rmmn = real(link_matrix(ib1, ib2),
dp)
1180 cmmn = aimag(link_matrix(ib1, ib2))
1185 gauge_tmp = gauge_real*rmmn - gauge_imag*cmmn
1186 cmmn = gauge_imag*rmmn + gauge_real*cmmn
1188 link_matrix(ib1, ib2) = cmplx(rmmn, cmmn,
dp)
1189 IF (para_env%is_source())
THEN
1190 WRITE (iunit,
"(2E30.14)") rmmn, cmmn
1195 iloop = loop_index(ik)
1196 CALL wilson_step(wilson_product(:, :, iloop), link_matrix, link_sv, status, 1.e-10_dp)
1197 IF (status /= 0)
THEN
1198 cpabort(
"Wilson link singular or SVD failed; refine sampling and check subspace.")
1200 loop_sv(iloop) = min(loop_sv(iloop), link_sv)
1207 IF (export_state)
THEN
1208 state_components = 1
1209 IF (do_soc) state_components = 2
1210 ALLOCATE (export_scalar(nao, nscalar), export_coeff(nao*state_components, num_bands))
1212 state_components, num_bands_tot, spin_channel, band_map, state_unit)
1214 kp => kpoint%kp_env(ik)%kpoint_env
1220 export_coeff(:nao, :) = matmul(export_scalar, spinor_coeff(:nscalar, :, ik))
1221 export_coeff(nao + 1:, :) = matmul(export_scalar, spinor_coeff(nscalar + 1:, :, ik))
1224 export_coeff(:, :) = export_scalar(:, band_map)
1225 CALL get_mo_set(kp%mos(1, spin_channel), eigenvalues=eigenvalues)
1226 CALL topology_state_point(state_unit, ik, kpt_latt(:, ik), eigenvalues(:nscalar), export_coeff)
1229 IF (state_unit > 0)
CALL close_file(state_unit)
1235 DEALLOCATE (berry_matrix)
1256 IF (ordered_berry)
THEN
1261 IF (para_env%is_source())
THEN
1268 nspins = dft_control%nspins
1269 kp => kpoint%kp_env(1)%kpoint_env
1271 ALLOCATE (eigval(num_bands_tot))
1272 direct_gap = huge(1.0_dp)
1273 valence_max = -huge(1.0_dp)
1274 conduction_min = huge(1.0_dp)
1276 IF (para_env%is_source())
THEN
1277 WRITE (filename,
'(A,A)') trim(seed_name),
".eig"
1278 CALL open_file(filename, unit_number=iunit, file_status=
"UNKNOWN", file_action=
"WRITE")
1284 my_kpgrp = (ik >= kp_range(1) .AND. ik <= kp_range(2))
1285 DO ispin = spin_channel, spin_channel
1287 eigval(:) = spinor_values(:, ik)
1288 ELSE IF (my_kpgrp)
THEN
1289 ikpgr = ik - kp_range(1) + 1
1290 kp => kpoint%kp_env(ikpgr)%kpoint_env
1291 CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues)
1292 eigval(1:nmo) = eigenvalues(1:nmo)
1294 eigval(1:nmo) = 0.0_dp
1296 IF (.NOT. do_soc)
CALL kpoint%para_env_inter_kp%sum(eigval)
1298 IF (lowest_bands)
THEN
1299 valence_max = max(valence_max, eigval(num_bands))
1300 conduction_min = min(conduction_min, eigval(num_bands + 1))
1302 DO ib = 1, num_bands_tot - 1
1303 IF (any(band_map == ib) .NEQV. any(band_map == ib + 1))
THEN
1304 pair_gap = eigval(ib + 1) - eigval(ib)
1305 direct_gap = min(direct_gap, pair_gap)
1309 eigval(:) = eigval*
evolt
1312 DO ib = 1, num_bands
1313 WRITE (iunit,
"(2I8,F24.14)") ib, ik, eigval(band_map(ib))
1318 IF (para_env%is_source())
THEN
1323 IF (iw > 0 .AND. num_bands < num_bands_tot)
WRITE (iw,
'(T2,A,ES18.10)') &
1324 "TOPOLOGY| Minimum sampled subspace gap [eV]: ", direct_gap*
evolt
1325 IF (direct_gap < gap_tol) cpabort(
"Wilson subspace is not isolated on the sampled points.")
1326 IF (lowest_bands)
THEN
1328 WRITE (iw,
'(T2,A,ES18.10)') &
1329 "TOPOLOGY| Maximum selected-band energy [eV]: ", valence_max*
evolt
1330 WRITE (iw,
'(T2,A,ES18.10)') &
1331 "TOPOLOGY| Minimum excluded-band energy [eV]: ", conduction_min*
evolt
1332 WRITE (iw,
'(T2,A,ES18.10)') &
1333 "TOPOLOGY| Sampled indirect gap [eV]: ", (conduction_min - valence_max)*
evolt
1334 IF (conduction_min - valence_max <= gap_tol)
WRITE (iw,
'(T2,A)') &
1335 "TOPOLOGY| Isolated band subspace, but no resolved common spectral gap on these samples."
1337 IF (require_global_gap .AND. conduction_min - valence_max <= gap_tol)
THEN
1338 cpabort(
"No positive sampled indirect gap above the selected bands.")
1342 CALL wilson_spectrum(wilson_product(:, :, iloop), wcc_out(:, iloop), berry_phase, status)
1343 IF (status /= 0) cpabort(
"Wilson eigenvalue calculation failed.")
1344 IF (iw > 0)
WRITE (iw,
'(T2,A,I0,A,F18.12,A,ES12.4)') &
1345 "TOPOLOGY| Loop ", iloop,
" Berry phase [rad]: ", berry_phase,
" min singular value: ", loop_sv(iloop)
1347 IF (para_env%is_source())
THEN
1348 CALL open_file(trim(seed_name)//
".wilson", unit_number=iunit, file_status=
"UNKNOWN", file_action=
"WRITE")
1349 WRITE (iunit,
'(A)')
"# loop, minimum link singular value, sorted WCC (arg(lambda)/(2*pi))"
1351 WRITE (iunit,
'(I8,*(1X,ES24.16))') iloop, loop_sv(iloop), wcc_out(:, iloop)
1356 CALL z2_from_wcc(wcc_out, z2_value, status, 1.e-5_dp)
1357 IF (status /= 0 .AND. iw > 0)
WRITE (iw,
'(T2,A,I0)') &
1358 "TOPOLOGY| Kramers/crossing check requests refinement, status: ", status
1359 IF (iw > 0)
WRITE (iw,
'(T2,A,I0)')
"TOPOLOGY| Z2 candidate (before sampling convergence): ", z2_value
1362 CALL chern_from_wcc(wcc_out, chern_value, chern_winding, status, 1.e-5_dp)
1363 IF (status /= 0)
THEN
1364 chern_value = huge(0)
1365 IF (iw > 0)
WRITE (iw,
'(T2,A,I0)') &
1366 "TOPOLOGY| Chern closure/winding check requests refinement, status: ", status
1367 ELSE IF (iw > 0)
THEN
1368 WRITE (iw,
'(T2,A,I0,A,F18.12)') &
1369 "TOPOLOGY| First Chern candidate: ", chern_value,
", winding: ", chern_winding
1375 DEALLOCATE (kpt_latt, atoms_cart, atom_symbols, eigval)
1376 DEALLOCATE (nnlist, nncell)
1377 DEALLOCATE (nblist, b_latt)
1378 DEALLOCATE (band_map)
1380 DEALLOCATE (exclude_bands)
1382 IF (do_kpoints)
THEN
1386 DEALLOCATE (qs_env_kp)
1392 END SUBROUTINE wannier90_files
1410 sab_nl, para_env, success, reason, aligned_degenerate_blocks, &
1411 aligned_degenerate_max_size, &
1412 aligned_degenerate_min_svalue)
1414 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s, matrix_ks
1415 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
1419 LOGICAL,
INTENT(OUT) :: success
1420 CHARACTER(LEN=*),
INTENT(OUT) :: reason
1421 INTEGER,
INTENT(OUT) :: aligned_degenerate_blocks, &
1422 aligned_degenerate_max_size
1423 REAL(kind=
dp),
INTENT(OUT) :: aligned_degenerate_min_svalue
1425 CHARACTER(LEN=default_string_length) :: best_reason, candidate_reason
1426 INTEGER :: aligned_blocks, aligned_max_size, candidate_aligned_blocks, &
1427 candidate_aligned_max_size, ik, ikpgr, ikred, ispin, isym_try, min_gap_band, &
1428 min_gap_kpoint, min_gap_spin, nao, nao_src, nmo, nmo_src, nspins, nsymmetry, &
1430 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: source_kpoint, sym_index
1431 INTEGER,
DIMENSION(2) :: kp_range, source_kp_range
1432 LOGICAL :: my_kpgrp, my_source_kpgrp, ok, &
1434 REAL(kind=
dp) :: aligned_min_svalue, band_gap, best_residual, candidate_residual, &
1435 degenerate_band_tol, local_min_band_gap, min_band_gap, source_owner_count, &
1436 source_window_min_svalue
1437 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues_buffer, occupation_buffer, &
1438 source_eigenvalues_buffer, &
1439 source_occupation_buffer
1440 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues, occupation
1443 TYPE(
cp_fm_type) :: dst_imag, dst_imag_full, dst_real, &
1444 dst_real_full, src_imag, &
1445 src_imag_full, src_real, src_real_full
1446 TYPE(
cp_fm_type),
POINTER :: dst_fmi, dst_fmr, src_fmi, src_fmr
1452 aligned_degenerate_blocks = 0
1453 aligned_degenerate_max_size = 0
1454 aligned_degenerate_min_svalue = huge(1.0_dp)
1455 NULLIFY (matrix_struct_source, matrix_struct_work, src_fmr, src_fmi, dst_fmr, dst_fmi)
1457 IF (.NOT.
ASSOCIATED(kpoint))
THEN
1458 reason =
"internal Wannier90 k-point object is not available"
1461 IF (.NOT.
ASSOCIATED(qs_kpoint))
THEN
1462 reason =
"SCF k-point object is not available"
1465 IF (.NOT.
ASSOCIATED(kpoint%kp_env) .OR. .NOT.
ASSOCIATED(qs_kpoint%kp_env))
THEN
1466 reason =
"k-point MO environments are not initialized"
1469 IF (.NOT.
ASSOCIATED(kpoint%blacs_env))
THEN
1470 reason =
"Wannier90 k-point BLACS environment is not initialized"
1474 CALL build_wannier90_scf_mapping(kpoint, qs_kpoint, source_kpoint, sym_index, ok, reason)
1475 IF (.NOT. ok)
RETURN
1476 nsymmetry = count(sym_index > 0)
1478 kp => kpoint%kp_env(1)%kpoint_env
1479 nspins =
SIZE(kp%mos, 2)
1480 IF (
SIZE(kp%mos, 1) < 2)
THEN
1481 reason =
"Wannier90 export k-point MOs are not complex-valued"
1482 DEALLOCATE (source_kpoint, sym_index)
1485 CALL get_mo_set(kp%mos(1, 1), nao=nao, nmo=nmo)
1487 kp_source => qs_kpoint%kp_env(1)%kpoint_env
1488 IF (
SIZE(kp_source%mos, 1) < 2)
THEN
1489 reason =
"SCF MOs are real-valued; complex symmetry phases cannot be reconstructed"
1490 DEALLOCATE (source_kpoint, sym_index)
1493 CALL get_mo_set(kp_source%mos(1, 1), nao=nao_src, nmo=nmo_src)
1494 CALL para_env%max(nao_src)
1495 CALL para_env%max(nmo_src)
1496 IF (nao_src /= nao)
THEN
1497 reason =
"SCF and Wannier90 MO bases have different AO dimensions"
1498 DEALLOCATE (source_kpoint, sym_index)
1501 IF (nmo_src < nmo)
THEN
1502 reason =
"SCF MO set has fewer bands than the Wannier90 export"
1503 DEALLOCATE (source_kpoint, sym_index)
1506 source_window = nmo_src > nmo
1507 degenerate_band_tol = 1.0e-8_dp
1509 IF (source_kp_range(1) /= 1 .OR. source_kp_range(2) /= qs_kpoint%nkp)
THEN
1510 reason =
"SCF k-point symmetry data are distributed over k-point parallel groups"
1511 DEALLOCATE (source_kpoint, sym_index)
1517 IF (nsymmetry > 0 .AND. nmo_src > nmo)
THEN
1518 local_min_band_gap = huge(1.0_dp)
1522 DO ikred = source_kp_range(1), source_kp_range(2)
1523 ikpgr = ikred - source_kp_range(1) + 1
1524 kp_source => qs_kpoint%kp_env(ikpgr)%kpoint_env
1525 DO ispin = 1, nspins
1526 CALL get_mo_set(kp_source%mos(1, ispin), eigenvalues=eigenvalues)
1527 band_gap = abs(eigenvalues(nmo + 1) - eigenvalues(nmo))
1528 IF (band_gap < local_min_band_gap)
THEN
1529 local_min_band_gap = band_gap
1531 min_gap_kpoint = ikred
1532 min_gap_spin = ispin
1536 min_band_gap = local_min_band_gap
1537 CALL para_env%min(min_band_gap)
1538 IF (abs(local_min_band_gap - min_band_gap) > degenerate_band_tol*epsilon(1.0_dp))
THEN
1542 CALL para_env%max(min_gap_kpoint)
1543 CALL para_env%max(min_gap_spin)
1544 CALL para_env%max(min_gap_band)
1545 IF (min_band_gap < degenerate_band_tol)
THEN
1546 WRITE (reason,
"(A,ES9.2,A,I0,A,I0,A,I0)") &
1547 "degenerate atom/AO W90 reuse guarded: edge gap=", min_band_gap,
", k=", &
1548 min_gap_kpoint,
", s=", min_gap_spin,
", nband=", min_gap_band
1549 DEALLOCATE (source_kpoint, sym_index)
1553 blacs_env => kpoint%blacs_env
1555 para_env=para_env, context=blacs_env)
1560 IF (source_window)
THEN
1562 para_env=para_env, context=blacs_env)
1568 ALLOCATE (eigenvalues_buffer(nmo), occupation_buffer(nmo), &
1569 source_eigenvalues_buffer(nmo_src), source_occupation_buffer(nmo_src))
1574 DO ik = 1, kpoint%nkp
1575 ikred = source_kpoint(ik)
1576 my_kpgrp = (ik >= kp_range(1) .AND. ik <= kp_range(2))
1577 my_source_kpgrp = (ikred >= source_kp_range(1) .AND. ikred <= source_kp_range(2))
1578 DO ispin = 1, nspins
1579 source_eigenvalues_buffer(1:nmo_src) = 0.0_dp
1580 source_occupation_buffer(1:nmo_src) = 0.0_dp
1581 IF (my_source_kpgrp)
THEN
1582 ikpgr = ikred - source_kp_range(1) + 1
1583 kp_source => qs_kpoint%kp_env(ikpgr)%kpoint_env
1584 src_fmr => kp_source%mos(1, ispin)%mo_coeff
1585 src_fmi => kp_source%mos(2, ispin)%mo_coeff
1586 CALL get_mo_set(kp_source%mos(1, ispin), eigenvalues=eigenvalues, &
1587 occupation_numbers=occupation)
1588 source_eigenvalues_buffer(1:nmo_src) = eigenvalues(1:nmo_src)
1589 source_occupation_buffer(1:nmo_src) = occupation(1:nmo_src)
1591 NULLIFY (src_fmr, src_fmi)
1593 IF (my_source_kpgrp)
THEN
1594 source_owner_count = 1.0_dp
1596 source_owner_count = 0.0_dp
1598 CALL para_env%sum(source_owner_count)
1599 CALL para_env%sum(source_eigenvalues_buffer)
1600 CALL para_env%sum(source_occupation_buffer)
1601 IF (source_owner_count > 0.0_dp)
THEN
1602 source_eigenvalues_buffer(1:nmo_src) = &
1603 source_eigenvalues_buffer(1:nmo_src)/source_owner_count
1604 source_occupation_buffer(1:nmo_src) = &
1605 source_occupation_buffer(1:nmo_src)/source_owner_count
1607 eigenvalues_buffer(1:nmo) = source_eigenvalues_buffer(1:nmo)
1608 occupation_buffer(1:nmo) = source_occupation_buffer(1:nmo)
1609 IF (source_window)
THEN
1612 CALL copy_wannier90_mo_window(src_real_full, src_real, nmo)
1613 CALL copy_wannier90_mo_window(src_imag_full, src_imag, nmo)
1622 aligned_max_size = 0
1623 aligned_min_svalue = 0.0_dp
1624 IF (sym_index(ik) > 0)
THEN
1625 kpsym => qs_kpoint%kp_sym(ikred)%kpoint_sym
1626 IF (
ASSOCIATED(
kpsym))
THEN
1628 best_residual = huge(1.0_dp)
1631 DO isym_try = 1,
kpsym%nwred
1633 kpsym%xkp(1:3, isym_try))) cycle
1634 num_candidates = num_candidates + 1
1636 qs_kpoint, ikred, isym_try, para_env, ok, &
1639 reason = candidate_reason
1642 CALL ritz_stabilize_wannier90_subspace(dst_real, dst_imag, matrix_s, matrix_ks, &
1643 kpoint%xkp(1:3, ik), cell_to_index, &
1644 sab_nl, ispin, eigenvalues_buffer, &
1645 degenerate_band_tol, ok, candidate_reason, &
1646 candidate_aligned_blocks, &
1647 candidate_aligned_max_size, &
1648 aligned_min_svalue, candidate_residual)
1649 IF (candidate_residual < best_residual)
THEN
1650 best_residual = candidate_residual
1651 best_reason = candidate_reason
1654 IF (source_window)
THEN
1656 dst_real_full, dst_imag_full, qs_kpoint, &
1657 ikred, isym_try, para_env, ok, candidate_reason)
1659 CALL ritz_reconstruct_wannier90_window(dst_real_full, dst_imag_full, &
1660 dst_real, dst_imag, matrix_s, &
1661 matrix_ks, kpoint%xkp(1:3, ik), &
1662 cell_to_index, sab_nl, ispin, &
1663 eigenvalues_buffer, nmo, ok, &
1664 candidate_reason, source_window_min_svalue, &
1666 IF (candidate_residual < best_residual)
THEN
1667 best_residual = candidate_residual
1668 best_reason = candidate_reason
1672 CALL ritz_reconstruct_wannier90_window(dst_real, dst_imag, dst_real, &
1673 dst_imag, matrix_s, matrix_ks, &
1674 kpoint%xkp(1:3, ik), cell_to_index, &
1675 sab_nl, ispin, eigenvalues_buffer, nmo, &
1676 ok, candidate_reason, source_window_min_svalue, &
1678 IF (candidate_residual < best_residual)
THEN
1679 best_residual = candidate_residual
1680 best_reason = candidate_reason
1685 aligned_blocks = candidate_aligned_blocks
1686 aligned_max_size = candidate_aligned_max_size
1687 sym_index(ik) = isym_try
1690 reason = candidate_reason
1692 IF (.NOT. ok .AND. num_candidates > 0 .AND. best_residual < huge(1.0_dp))
THEN
1693 WRITE (reason,
"(A,I0,A,ES9.2,A,I0,A,A32)") &
1694 "atom/AO W90 guarded: best/", num_candidates,
"=", best_residual, &
1695 " k=", ik,
" ", trim(best_reason)
1696 ELSE IF (.NOT. ok .AND. num_candidates == 0)
THEN
1697 reason =
"no matching SCF symmetry operation candidate"
1700 reason =
"SCF k-point symmetry operation is not available"
1704 ikred, sym_index(ik), para_env, ok, reason)
1706 IF (ok .AND. sym_index(ik) <= 0)
THEN
1709 CALL ritz_stabilize_wannier90_subspace(dst_real, dst_imag, matrix_s, matrix_ks, &
1710 kpoint%xkp(1:3, ik), cell_to_index, sab_nl, &
1711 ispin, eigenvalues_buffer, degenerate_band_tol, &
1712 ok, reason, aligned_blocks, aligned_max_size, &
1713 aligned_min_svalue, candidate_residual)
1714 IF (.NOT. ok .AND. source_window)
THEN
1716 dst_imag_full, qs_kpoint, ikred, sym_index(ik), &
1717 para_env, ok, reason)
1719 CALL ritz_reconstruct_wannier90_window(dst_real_full, dst_imag_full, dst_real, &
1720 dst_imag, matrix_s, matrix_ks, &
1721 kpoint%xkp(1:3, ik), cell_to_index, &
1722 sab_nl, ispin, eigenvalues_buffer, nmo, ok, &
1723 reason, source_window_min_svalue, &
1726 ELSE IF (.NOT. ok)
THEN
1727 CALL ritz_reconstruct_wannier90_window(dst_real, dst_imag, dst_real, dst_imag, &
1728 matrix_s, matrix_ks, kpoint%xkp(1:3, ik), &
1729 cell_to_index, sab_nl, ispin, &
1730 eigenvalues_buffer, nmo, ok, reason, &
1731 source_window_min_svalue, candidate_residual)
1740 IF (source_window)
THEN
1747 DEALLOCATE (source_kpoint, sym_index, eigenvalues_buffer, occupation_buffer, &
1748 source_eigenvalues_buffer, source_occupation_buffer)
1751 IF (sym_index(ik) /= 0)
THEN
1752 aligned_degenerate_blocks = aligned_degenerate_blocks + aligned_blocks
1753 aligned_degenerate_max_size = max(aligned_degenerate_max_size, aligned_max_size)
1754 IF (aligned_blocks > 0)
THEN
1755 aligned_degenerate_min_svalue = min(aligned_degenerate_min_svalue, aligned_min_svalue)
1760 ikpgr = ik - kp_range(1) + 1
1761 kp => kpoint%kp_env(ikpgr)%kpoint_env
1762 dst_fmr => kp%mos(1, ispin)%mo_coeff
1763 dst_fmi => kp%mos(2, ispin)%mo_coeff
1764 CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues, &
1765 occupation_numbers=occupation)
1766 eigenvalues(1:nmo) = eigenvalues_buffer(1:nmo)
1767 occupation(1:nmo) = occupation_buffer(1:nmo)
1768 CALL get_mo_set(kp%mos(2, ispin), eigenvalues=eigenvalues, &
1769 occupation_numbers=occupation)
1770 IF (
ASSOCIATED(eigenvalues)) eigenvalues(1:nmo) = eigenvalues_buffer(1:nmo)
1771 IF (
ASSOCIATED(occupation)) occupation(1:nmo) = occupation_buffer(1:nmo)
1773 NULLIFY (dst_fmr, dst_fmi)
1785 IF (source_window)
THEN
1792 DEALLOCATE (source_kpoint, sym_index, eigenvalues_buffer, occupation_buffer, &
1793 source_eigenvalues_buffer, source_occupation_buffer)
1794 IF (aligned_degenerate_blocks == 0) aligned_degenerate_min_svalue = 0.0_dp
1808 SUBROUTINE save_wannier90_mo_snapshot(kpoint, nspins, para_env, mo_real, mo_imag, &
1809 eigenvalue_snapshot)
1811 INTEGER,
INTENT(IN) :: nspins
1813 REAL(kind=
dp),
ALLOCATABLE, &
1814 DIMENSION(:, :, :, :),
INTENT(OUT) :: mo_real, mo_imag
1815 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :), &
1816 INTENT(OUT) :: eigenvalue_snapshot
1818 INTEGER :: ik, ikpgr, ispin, nao, nkp, nmo
1819 INTEGER,
DIMENSION(2) :: kp_range
1820 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: owner_weight
1821 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues
1826 kp => kpoint%kp_env(1)%kpoint_env
1827 CALL get_mo_set(kp%mos(1, 1), nao=nao, nmo=nmo)
1828 ALLOCATE (mo_real(nao, nmo, nkp, nspins), mo_imag(nao, nmo, nkp, nspins), &
1829 eigenvalue_snapshot(nmo, nkp, nspins), owner_weight(nkp, nspins))
1830 mo_real(:, :, :, :) = 0.0_dp
1831 mo_imag(:, :, :, :) = 0.0_dp
1832 eigenvalue_snapshot(:, :, :) = 0.0_dp
1833 owner_weight(:, :) = 0.0_dp
1834 DO ik = kp_range(1), kp_range(2)
1835 ikpgr = ik - kp_range(1) + 1
1836 kp => kpoint%kp_env(ikpgr)%kpoint_env
1837 DO ispin = 1, nspins
1838 fmr => kp%mos(1, ispin)%mo_coeff
1839 fmi => kp%mos(2, ispin)%mo_coeff
1842 CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues)
1843 eigenvalue_snapshot(1:nmo, ik, ispin) = eigenvalues(1:nmo)
1844 owner_weight(ik, ispin) = 1.0_dp
1847 CALL para_env%sum(mo_real)
1848 CALL para_env%sum(mo_imag)
1849 CALL para_env%sum(eigenvalue_snapshot)
1850 CALL para_env%sum(owner_weight)
1852 DO ispin = 1, nspins
1853 IF (owner_weight(ik, ispin) > 0.0_dp)
THEN
1854 mo_real(:, :, ik, ispin) = mo_real(:, :, ik, ispin)/owner_weight(ik, ispin)
1855 mo_imag(:, :, ik, ispin) = mo_imag(:, :, ik, ispin)/owner_weight(ik, ispin)
1856 eigenvalue_snapshot(:, ik, ispin) = &
1857 eigenvalue_snapshot(:, ik, ispin)/owner_weight(ik, ispin)
1861 DEALLOCATE (owner_weight)
1863 END SUBROUTINE save_wannier90_mo_snapshot
1872 SUBROUTINE restore_wannier90_mo_snapshot(kpoint, mo_real, mo_imag, eigenvalue_snapshot)
1874 REAL(kind=
dp),
DIMENSION(:, :, :, :),
INTENT(IN) :: mo_real, mo_imag
1875 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: eigenvalue_snapshot
1877 INTEGER :: ik, ikpgr, ispin, nmo, nspins
1878 INTEGER,
DIMENSION(2) :: kp_range
1879 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues
1884 nmo =
SIZE(eigenvalue_snapshot, 1)
1885 nspins =
SIZE(eigenvalue_snapshot, 3)
1886 DO ik = kp_range(1), kp_range(2)
1887 ikpgr = ik - kp_range(1) + 1
1888 kp => kpoint%kp_env(ikpgr)%kpoint_env
1889 DO ispin = 1, nspins
1890 fmr => kp%mos(1, ispin)%mo_coeff
1891 fmi => kp%mos(2, ispin)%mo_coeff
1894 CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues)
1895 eigenvalues(1:nmo) = eigenvalue_snapshot(1:nmo, ik, ispin)
1896 CALL get_mo_set(kp%mos(2, ispin), eigenvalues=eigenvalues)
1897 IF (
ASSOCIATED(eigenvalues)) eigenvalues(1:nmo) = eigenvalue_snapshot(1:nmo, ik, ispin)
1901 END SUBROUTINE restore_wannier90_mo_snapshot
1918 SUBROUTINE validate_wannier90_reused_mos(kpoint, matrix_s, cell_to_index, sab_nl, para_env, &
1919 reference_mo_real, reference_mo_imag, reference_eigenvalues, &
1920 success, max_subspace_deviation, min_svalue, &
1921 max_eigenvalue_deviation)
1923 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s
1924 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
1928 REAL(kind=
dp),
DIMENSION(:, :, :, :),
INTENT(IN) :: reference_mo_real, reference_mo_imag
1929 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(IN) :: reference_eigenvalues
1930 LOGICAL,
INTENT(OUT) :: success
1931 REAL(kind=
dp),
INTENT(OUT) :: max_subspace_deviation, min_svalue, &
1932 max_eigenvalue_deviation
1934 REAL(kind=
dp),
PARAMETER :: eigenvalue_tol = 1.0e-8_dp, &
1935 subspace_tol = 1.0e-4_dp
1937 INTEGER :: ik, ikpgr, ispin, nao, nkp, nmo, nspins
1938 INTEGER,
DIMENSION(2) :: kp_range
1939 LOGICAL :: my_kpgrp, ok
1940 REAL(kind=
dp) :: candidate_deviation, candidate_svalue, &
1942 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalue_buffer
1943 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues
1945 TYPE(
cp_fm_type) :: cand_imag, cand_real, ref_imag, ref_real
1950 max_subspace_deviation = 0.0_dp
1951 min_svalue = huge(1.0_dp)
1952 max_eigenvalue_deviation = 0.0_dp
1953 NULLIFY (matrix_struct_work, fmr, fmi)
1956 kp => kpoint%kp_env(1)%kpoint_env
1957 nspins =
SIZE(kp%mos, 2)
1958 CALL get_mo_set(kp%mos(1, 1), nao=nao, nmo=nmo)
1959 cpassert(
SIZE(reference_mo_real, 1) == nao)
1960 cpassert(
SIZE(reference_mo_real, 2) == nmo)
1961 cpassert(
SIZE(reference_mo_real, 3) == nkp)
1962 cpassert(
SIZE(reference_mo_real, 4) == nspins)
1964 CALL cp_fm_get_info(kp%mos(1, 1)%mo_coeff, matrix_struct=matrix_struct_work)
1969 ALLOCATE (eigenvalue_buffer(nmo))
1971 DO ispin = 1, nspins
1975 my_kpgrp = (ik >= kp_range(1) .AND. ik <= kp_range(2))
1977 ikpgr = ik - kp_range(1) + 1
1978 kp => kpoint%kp_env(ikpgr)%kpoint_env
1979 fmr => kp%mos(1, ispin)%mo_coeff
1980 fmi => kp%mos(2, ispin)%mo_coeff
1981 CALL get_mo_set(kp%mos(1, ispin), eigenvalues=eigenvalues)
1982 eigenvalue_buffer(1:nmo) = eigenvalues(1:nmo)
1985 eigenvalue_buffer(1:nmo) = 0.0_dp
1990 owner_count = 1.0_dp
1992 owner_count = 0.0_dp
1994 CALL para_env%sum(owner_count)
1995 CALL para_env%sum(eigenvalue_buffer)
1996 IF (owner_count > 0.0_dp) eigenvalue_buffer(1:nmo) = eigenvalue_buffer(1:nmo)/owner_count
1997 max_eigenvalue_deviation = max(max_eigenvalue_deviation, &
1998 maxval(abs(eigenvalue_buffer(1:nmo) - &
1999 reference_eigenvalues(1:nmo, ik, ispin))))
2000 CALL measure_wannier90_subspace_error(ref_real, ref_imag, cand_real, cand_imag, matrix_s, &
2001 kpoint%xkp(1:3, ik), cell_to_index, sab_nl, para_env, &
2002 ok, candidate_deviation, candidate_svalue)
2004 max_subspace_deviation = huge(1.0_dp)
2006 max_subspace_deviation = max(max_subspace_deviation, candidate_deviation)
2007 min_svalue = min(min_svalue, candidate_svalue)
2011 CALL para_env%max(max_subspace_deviation)
2012 CALL para_env%min(min_svalue)
2013 CALL para_env%max(max_eigenvalue_deviation)
2014 success = max_subspace_deviation < subspace_tol .AND. max_eigenvalue_deviation < eigenvalue_tol
2016 DEALLOCATE (eigenvalue_buffer)
2022 END SUBROUTINE validate_wannier90_reused_mos
2039 SUBROUTINE diagnose_wannier90_scf_reuse_candidates(kpoint, qs_kpoint, matrix_s, matrix_ks, &
2040 cell_to_index, sab_nl, para_env, iw, &
2041 max_subspace_deviation, min_svalue, &
2042 max_metric_deviation, max_residual)
2044 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s, matrix_ks
2045 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
2049 INTEGER,
INTENT(IN) :: iw
2050 REAL(kind=
dp),
INTENT(OUT) :: max_subspace_deviation, min_svalue, &
2051 max_metric_deviation, max_residual
2053 REAL(kind=
dp),
PARAMETER :: print_tol = 1.0e-4_dp, &
2054 residual_print_tol = 1.0e-3_dp
2056 CHARACTER(LEN=default_string_length) :: reason
2057 INTEGER :: ik, ikpgr, ikred, ispin, isym_try, nao, &
2058 nao_src, nkp, nmo, nmo_src, nspins
2059 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: source_kpoint, sym_index
2060 INTEGER,
DIMENSION(2) :: kp_range, source_kp_range
2061 LOGICAL :: my_kpgrp, ok, source_window
2062 REAL(kind=
dp) :: best_deviation, best_metric_deviation, best_residual, best_svalue, &
2063 candidate_deviation, candidate_metric_deviation, candidate_metric_min, &
2064 candidate_residual, candidate_svalue, owner_count, ref_metric_deviation, ref_metric_min, &
2066 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues_buffer
2067 REAL(kind=
dp),
DIMENSION(:),
POINTER :: eigenvalues
2069 TYPE(
cp_fm_type) :: dst_imag, dst_real, ref_imag, ref_real, &
2070 src_imag, src_imag_full, src_real, &
2072 TYPE(
cp_fm_type),
POINTER :: fmi, fmr, src_fmi, src_fmr
2076 max_subspace_deviation = huge(1.0_dp)
2078 max_metric_deviation = huge(1.0_dp)
2079 max_residual = huge(1.0_dp)
2080 NULLIFY (matrix_struct_source, matrix_struct_work, fmi, fmr, src_fmi, src_fmr)
2082 CALL build_wannier90_scf_mapping(kpoint, qs_kpoint, source_kpoint, sym_index, ok, reason)
2083 IF (.NOT. ok)
RETURN
2084 kp => kpoint%kp_env(1)%kpoint_env
2085 kp_source => qs_kpoint%kp_env(1)%kpoint_env
2086 IF (
SIZE(kp%mos, 1) < 2 .OR.
SIZE(kp_source%mos, 1) < 2)
THEN
2087 DEALLOCATE (source_kpoint, sym_index)
2090 nspins =
SIZE(kp%mos, 2)
2091 CALL get_mo_set(kp%mos(1, 1), nao=nao, nmo=nmo)
2092 CALL get_mo_set(kp_source%mos(1, 1), nao=nao_src, nmo=nmo_src)
2093 CALL para_env%max(nao_src)
2094 CALL para_env%max(nmo_src)
2095 IF (nao_src /= nao .OR. nmo_src < nmo)
THEN
2096 DEALLOCATE (source_kpoint, sym_index)
2099 source_window = nmo_src > nmo
2102 IF (source_kp_range(1) /= 1 .OR. source_kp_range(2) /= qs_kpoint%nkp)
THEN
2103 DEALLOCATE (source_kpoint, sym_index)
2108 para_env=para_env, context=kpoint%blacs_env)
2115 ALLOCATE (eigenvalues_buffer(nmo))
2116 IF (source_window)
THEN
2118 para_env=para_env, context=kpoint%blacs_env)
2123 max_subspace_deviation = 0.0_dp
2124 min_svalue = huge(1.0_dp)
2125 max_metric_deviation = 0.0_dp
2126 max_residual = 0.0_dp
2127 DO ispin = 1, nspins
2129 my_kpgrp = (ik >= kp_range(1) .AND. ik <= kp_range(2))
2131 ikpgr = ik - kp_range(1) + 1
2132 kp => kpoint%kp_env(ikpgr)%kpoint_env
2133 fmr => kp%mos(1, ispin)%mo_coeff
2134 fmi => kp%mos(2, ispin)%mo_coeff
2141 ikred = source_kpoint(ik)
2142 my_kpgrp = (ikred >= source_kp_range(1) .AND. ikred <= source_kp_range(2))
2144 ikpgr = ikred - source_kp_range(1) + 1
2145 kp_source => qs_kpoint%kp_env(ikpgr)%kpoint_env
2146 src_fmr => kp_source%mos(1, ispin)%mo_coeff
2147 src_fmi => kp_source%mos(2, ispin)%mo_coeff
2148 CALL get_mo_set(kp_source%mos(1, ispin), eigenvalues=eigenvalues)
2149 eigenvalues_buffer(1:nmo) = eigenvalues(1:nmo)
2151 NULLIFY (src_fmr, src_fmi)
2152 eigenvalues_buffer(1:nmo) = 0.0_dp
2155 owner_count = 1.0_dp
2157 owner_count = 0.0_dp
2159 CALL para_env%sum(owner_count)
2160 CALL para_env%sum(eigenvalues_buffer)
2161 IF (owner_count > 0.0_dp) eigenvalues_buffer(1:nmo) = eigenvalues_buffer(1:nmo)/owner_count
2162 CALL measure_wannier90_eigenspace_quality(ref_real, ref_imag, matrix_s, matrix_ks, &
2163 kpoint%xkp(1:3, ik), cell_to_index, sab_nl, &
2164 para_env, ispin, eigenvalues_buffer, ok, &
2165 ref_metric_deviation, ref_metric_min, ref_residual)
2166 IF (ok .AND. para_env%is_source() .AND. iw > 0 .AND. &
2167 (ref_metric_deviation > print_tol .OR. ref_residual > residual_print_tol))
THEN
2168 WRITE (iw,
'(T2,A,I0,A,ES10.3,A,ES10.3,A,ES10.3)') &
2169 "WANNIER90| reference k=", ik,
" dM=", ref_metric_deviation, &
2170 " smin=", ref_metric_min,
" resid=", ref_residual
2172 IF (source_window)
THEN
2175 CALL copy_wannier90_mo_window(src_real_full, src_real, nmo)
2176 CALL copy_wannier90_mo_window(src_imag_full, src_imag, nmo)
2182 best_deviation = huge(1.0_dp)
2183 best_metric_deviation = 0.0_dp
2184 best_residual = 0.0_dp
2185 best_svalue = 0.0_dp
2186 IF (sym_index(ik) <= 0)
THEN
2188 ikred, sym_index(ik), para_env, ok, reason)
2190 CALL measure_wannier90_subspace_error(ref_real, ref_imag, dst_real, dst_imag, matrix_s, &
2191 kpoint%xkp(1:3, ik), cell_to_index, sab_nl, &
2192 para_env, ok, candidate_deviation, candidate_svalue)
2194 CALL measure_wannier90_eigenspace_quality(dst_real, dst_imag, matrix_s, matrix_ks, &
2195 kpoint%xkp(1:3, ik), cell_to_index, sab_nl, &
2196 para_env, ispin, eigenvalues_buffer, ok, &
2197 candidate_metric_deviation, &
2198 candidate_metric_min, candidate_residual)
2201 best_deviation = candidate_deviation
2202 best_metric_deviation = candidate_metric_deviation
2203 best_residual = candidate_residual
2204 best_svalue = candidate_svalue
2205 IF (para_env%is_source() .AND. iw > 0 .AND. &
2206 (candidate_deviation > print_tol .OR. candidate_metric_deviation > print_tol .OR. &
2207 candidate_residual > residual_print_tol))
THEN
2208 WRITE (iw,
'(T2,A,I0,A,I0,A,I0,A,ES10.3,A,ES10.3,A,ES10.3,A,ES10.3)') &
2209 "WANNIER90| reuse candidate k=", ik,
" src=", ikred,
" sym=", &
2210 sym_index(ik),
" dRef=", candidate_deviation,
" dM=", &
2211 candidate_metric_deviation,
" smin=", candidate_metric_min, &
2212 " resid=", candidate_residual
2216 ELSE IF (
ASSOCIATED(qs_kpoint%kp_sym))
THEN
2217 kpsym => qs_kpoint%kp_sym(ikred)%kpoint_sym
2218 IF (
ASSOCIATED(
kpsym))
THEN
2219 DO isym_try = 1,
kpsym%nwred
2221 kpsym%xkp(1:3, isym_try))) cycle
2223 qs_kpoint, ikred, isym_try, para_env, ok, reason)
2225 CALL measure_wannier90_subspace_error(ref_real, ref_imag, dst_real, dst_imag, &
2226 matrix_s, kpoint%xkp(1:3, ik), cell_to_index, &
2227 sab_nl, para_env, ok, candidate_deviation, &
2230 CALL measure_wannier90_eigenspace_quality(dst_real, dst_imag, matrix_s, matrix_ks, &
2231 kpoint%xkp(1:3, ik), cell_to_index, &
2232 sab_nl, para_env, ispin, &
2233 eigenvalues_buffer, ok, &
2234 candidate_metric_deviation, &
2235 candidate_metric_min, candidate_residual)
2237 IF (ok .AND. candidate_deviation < best_deviation)
THEN
2238 best_deviation = candidate_deviation
2239 best_metric_deviation = candidate_metric_deviation
2240 best_residual = candidate_residual
2241 best_svalue = candidate_svalue
2246 IF (best_deviation < huge(1.0_dp))
THEN
2247 max_subspace_deviation = max(max_subspace_deviation, best_deviation)
2248 min_svalue = min(min_svalue, best_svalue)
2249 max_metric_deviation = max(max_metric_deviation, best_metric_deviation)
2250 max_residual = max(max_residual, best_residual)
2254 CALL para_env%max(max_subspace_deviation)
2255 CALL para_env%min(min_svalue)
2256 CALL para_env%max(max_metric_deviation)
2257 CALL para_env%max(max_residual)
2259 IF (source_window)
THEN
2271 DEALLOCATE (eigenvalues_buffer)
2272 DEALLOCATE (source_kpoint, sym_index)
2274 END SUBROUTINE diagnose_wannier90_scf_reuse_candidates
2291 SUBROUTINE measure_wannier90_subspace_error(ref_real, ref_imag, cand_real, cand_imag, matrix_s, &
2292 xkp, cell_to_index, sab_nl, para_env, success, &
2293 max_subspace_deviation, min_svalue)
2294 TYPE(
cp_fm_type),
INTENT(IN) :: ref_real, ref_imag, cand_real, cand_imag
2295 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s
2296 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
2297 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
2301 LOGICAL,
INTENT(OUT) :: success
2302 REAL(kind=
dp),
INTENT(OUT) :: max_subspace_deviation, min_svalue
2304 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: metric_projected, metric_vectors, &
2305 overlap, ref_coeff, s_cand
2306 INTEGER :: ib, nao, nmo, nmo_candidate
2307 REAL(kind=
dp) :: singular_value
2308 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: metric_values
2309 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: ref_i, ref_r, s_cand_i, s_cand_r
2314 max_subspace_deviation = huge(1.0_dp)
2316 NULLIFY (matrix_struct_metric)
2318 CALL cp_fm_get_info(ref_real, nrow_global=nao, ncol_global=nmo, &
2319 matrix_struct=matrix_struct_metric)
2321 IF (nmo_candidate /= nmo)
RETURN
2325 CALL apply_wannier90_kp_matrix(matrix_s, 1, xkp, cell_to_index, sab_nl, &
2326 cand_real, cand_imag, s_cand_real, s_cand_imag)
2328 ALLOCATE (ref_r(nao, nmo), ref_i(nao, nmo), s_cand_r(nao, nmo), s_cand_i(nao, nmo))
2334 ALLOCATE (ref_coeff(nao, nmo), s_cand(nao, nmo), overlap(nmo, nmo), &
2335 metric_projected(nmo, nmo), metric_vectors(nmo, nmo), metric_values(nmo))
2336 ref_coeff(:, :) = cmplx(ref_r, ref_i, kind=
dp)
2337 s_cand(:, :) = cmplx(s_cand_r, s_cand_i, kind=
dp)
2338 overlap(:, :) = matmul(conjg(transpose(ref_coeff)), s_cand)
2339 metric_projected(:, :) = matmul(conjg(transpose(overlap)), overlap)
2340 metric_projected(:, :) = 0.5_dp*(metric_projected + conjg(transpose(metric_projected)))
2341 CALL diag_complex(metric_projected, metric_vectors, metric_values)
2343 min_svalue = huge(1.0_dp)
2344 max_subspace_deviation = 0.0_dp
2346 singular_value = sqrt(max(metric_values(ib), 0.0_dp))
2347 min_svalue = min(min_svalue, singular_value)
2348 max_subspace_deviation = max(max_subspace_deviation, abs(singular_value - 1.0_dp))
2350 CALL para_env%max(max_subspace_deviation)
2351 CALL para_env%min(min_svalue)
2354 DEALLOCATE (ref_coeff, s_cand, overlap, metric_projected, metric_vectors, metric_values)
2355 DEALLOCATE (ref_r, ref_i, s_cand_r, s_cand_i)
2359 END SUBROUTINE measure_wannier90_subspace_error
2378 SUBROUTINE measure_wannier90_eigenspace_quality(cand_real, cand_imag, matrix_s, matrix_ks, xkp, &
2379 cell_to_index, sab_nl, para_env, ispin, eigenvalues, &
2380 success, metric_deviation, min_metric_eigenvalue, &
2382 TYPE(
cp_fm_type),
INTENT(IN) :: cand_real, cand_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
2389 INTEGER,
INTENT(IN) :: ispin
2390 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: eigenvalues
2391 LOGICAL,
INTENT(OUT) :: success
2392 REAL(kind=
dp),
INTENT(OUT) :: metric_deviation, min_metric_eigenvalue, &
2395 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: cand_coeff, h_coeff, metric_vectors, &
2396 residual_block, s_coeff, s_projected
2397 INTEGER :: ib, nao, nmo
2398 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: metric_values
2399 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: cand_i, cand_r, h_coeff_i, h_coeff_r, &
2400 s_coeff_i, s_coeff_r
2403 matrix_struct_projected
2404 TYPE(
cp_fm_type) :: h_cand_imag, h_cand_real, s_cand_imag, &
2408 metric_deviation = huge(1.0_dp)
2409 min_metric_eigenvalue = 0.0_dp
2410 residual_norm = huge(1.0_dp)
2411 NULLIFY (matrix_struct_metric, matrix_struct_projected)
2413 CALL cp_fm_get_info(cand_real, nrow_global=nao, ncol_global=nmo, &
2414 matrix_struct=matrix_struct_metric)
2415 IF (
SIZE(eigenvalues) < nmo)
RETURN
2425 CALL apply_wannier90_kp_matrix(matrix_s, 1, xkp, cell_to_index, sab_nl, &
2426 cand_real, cand_imag, s_cand_real, s_cand_imag)
2427 CALL apply_wannier90_kp_matrix(matrix_ks, ispin, xkp, cell_to_index, sab_nl, &
2428 cand_real, cand_imag, h_cand_real, h_cand_imag)
2430 ALLOCATE (cand_r(nao, nmo), cand_i(nao, nmo), s_coeff_r(nao, nmo), &
2431 s_coeff_i(nao, nmo), h_coeff_r(nao, nmo), h_coeff_i(nao, nmo))
2439 ALLOCATE (cand_coeff(nao, nmo), h_coeff(nao, nmo), metric_vectors(nmo, nmo), &
2440 residual_block(nao, nmo), s_coeff(nao, nmo), s_projected(nmo, nmo), &
2442 cand_coeff(:, :) = cmplx(cand_r, cand_i, kind=
dp)
2443 s_coeff(:, :) = cmplx(s_coeff_r, s_coeff_i, kind=
dp)
2444 h_coeff(:, :) = cmplx(h_coeff_r, h_coeff_i, kind=
dp)
2446 para_env=matrix_struct_metric%para_env, &
2447 context=matrix_struct_metric%context)
2451 CALL cp_cfm_gemm(
"C",
"N", nmo, nmo, nao, cmplx(1.0_dp, 0.0_dp, kind=
dp), cand_cfm, &
2452 s_cfm, cmplx(0.0_dp, 0.0_dp, kind=
dp), metric_cfm)
2454 s_projected(:, :) = 0.5_dp*(s_projected + conjg(transpose(s_projected)))
2455 CALL diag_complex(s_projected, metric_vectors, metric_values)
2456 metric_deviation = maxval(abs(metric_values - 1.0_dp))
2457 min_metric_eigenvalue = minval(metric_values)
2459 residual_block(:, :) = h_coeff
2461 residual_block(:, ib) = residual_block(:, ib) - eigenvalues(ib)*s_coeff(:, ib)
2463 residual_norm = maxval(abs(residual_block))
2464 CALL para_env%max(metric_deviation)
2465 CALL para_env%min(min_metric_eigenvalue)
2466 CALL para_env%max(residual_norm)
2469 DEALLOCATE (cand_coeff, h_coeff, metric_vectors, residual_block, s_coeff, s_projected, &
2471 DEALLOCATE (cand_r, cand_i, s_coeff_r, s_coeff_i, h_coeff_r, h_coeff_i)
2482 END SUBROUTINE measure_wannier90_eigenspace_quality
2490 SUBROUTINE copy_wannier90_mo_window(source, destination, ncol)
2491 TYPE(
cp_fm_type),
INTENT(IN) :: source, destination
2492 INTEGER,
INTENT(IN) :: ncol
2494 INTEGER :: ncol_source, nrow
2495 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: destination_buffer, source_buffer
2497 CALL cp_fm_get_info(source, nrow_global=nrow, ncol_global=ncol_source)
2498 cpassert(ncol_source >= ncol)
2499 ALLOCATE (source_buffer(nrow, ncol_source), destination_buffer(nrow, ncol))
2501 destination_buffer(1:nrow, 1:ncol) = source_buffer(1:nrow, 1:ncol)
2503 DEALLOCATE (source_buffer, destination_buffer)
2505 END SUBROUTINE copy_wannier90_mo_window
2519 SUBROUTINE apply_wannier90_kp_matrix(rsmat, ispin, xkp, cell_to_index, sab_nl, &
2520 coeff_real, coeff_imag, result_real, result_imag)
2522 INTEGER,
INTENT(IN) :: ispin
2523 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
2524 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
2527 TYPE(
cp_fm_type),
INTENT(IN) :: coeff_real, coeff_imag, result_real, &
2530 INTEGER :: nao, ncol
2531 TYPE(
cp_cfm_type) :: coeff_cfm, kmat_cfm, result_cfm
2534 TYPE(
dbcsr_type),
POINTER :: kmat_imag, kmat_imag_full, kmat_real, &
2537 NULLIFY (matrix_struct_ao, matrix_struct_coeff, kmat_imag, kmat_imag_full, kmat_real, &
2540 CALL cp_fm_get_info(coeff_real, nrow_global=nao, ncol_global=ncol, &
2541 matrix_struct=matrix_struct_coeff)
2543 ALLOCATE (kmat_real, kmat_imag, kmat_real_full, kmat_imag_full)
2544 CALL dbcsr_create(kmat_real, template=rsmat(ispin, 1)%matrix, &
2545 matrix_type=dbcsr_type_symmetric)
2546 CALL dbcsr_create(kmat_imag, template=rsmat(ispin, 1)%matrix, &
2547 matrix_type=dbcsr_type_antisymmetric)
2548 CALL dbcsr_create(kmat_real_full, template=rsmat(ispin, 1)%matrix, &
2549 matrix_type=dbcsr_type_no_symmetry)
2550 CALL dbcsr_create(kmat_imag_full, template=rsmat(ispin, 1)%matrix, &
2551 matrix_type=dbcsr_type_no_symmetry)
2556 CALL rskp_transform(kmat_real, kmat_imag, rsmat=rsmat, ispin=ispin, &
2557 xkp=xkp, cell_to_index=cell_to_index, sab_nl=sab_nl)
2562 para_env=matrix_struct_coeff%para_env, &
2563 context=matrix_struct_coeff%context)
2574 CALL cp_cfm_gemm(
"N",
"N", nao, ncol, nao, cmplx(1.0_dp, 0.0_dp, kind=
dp), kmat_cfm, &
2575 coeff_cfm, cmplx(0.0_dp, 0.0_dp, kind=
dp), result_cfm)
2576 CALL cp_cfm_to_fm(result_cfm, result_real, result_imag)
2589 END SUBROUTINE apply_wannier90_kp_matrix
2610 SUBROUTINE ritz_stabilize_wannier90_subspace(dst_real, dst_imag, matrix_s, matrix_ks, &
2611 xkp, cell_to_index, sab_nl, ispin, eigenvalues, &
2612 degenerate_band_tol, success, reason, aligned_blocks, &
2613 aligned_max_size, aligned_min_svalue, max_residual)
2614 TYPE(
cp_fm_type),
INTENT(IN) :: dst_real, dst_imag
2615 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s, matrix_ks
2616 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
2617 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
2620 INTEGER,
INTENT(IN) :: ispin
2621 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: eigenvalues
2622 REAL(kind=
dp),
INTENT(IN) :: degenerate_band_tol
2623 LOGICAL,
INTENT(OUT) :: success
2624 CHARACTER(LEN=*),
INTENT(OUT) :: reason
2625 INTEGER,
INTENT(OUT) :: aligned_blocks, aligned_max_size
2626 REAL(kind=
dp),
INTENT(OUT) :: aligned_min_svalue, max_residual
2628 REAL(kind=
dp),
PARAMETER :: residual_tol = 1.0e-2_dp
2630 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: block_coeff, h_block, h_coeff, &
2631 h_projected, h_projected_work, metric_vectors, residual_block, ritz_vectors, s_block, &
2632 s_coeff, s_projected, stabilized
2633 INTEGER :: block_first, block_last, block_size, ib, &
2635 REAL(kind=
dp) :: metric_deviation, norm_value, &
2637 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: metric_values, ritz_values
2638 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: dst_i, dst_r, h_coeff_i, h_coeff_r, &
2639 s_coeff_i, s_coeff_r
2641 TYPE(
cp_fm_type) :: h_dst_imag, h_dst_real, s_dst_imag, &
2647 aligned_max_size = 0
2648 aligned_min_svalue = huge(1.0_dp)
2649 max_residual = 0.0_dp
2651 NULLIFY (matrix_struct_metric)
2652 CALL cp_fm_get_info(dst_real, nrow_global=nao, ncol_global=nmo, &
2653 matrix_struct=matrix_struct_metric)
2654 IF (
SIZE(eigenvalues) < nmo)
THEN
2655 reason =
"not enough eigenvalues for Wannier90 Ritz subspace stabilization"
2665 CALL apply_wannier90_kp_matrix(matrix_s, 1, xkp, cell_to_index, sab_nl, &
2666 dst_real, dst_imag, s_dst_real, s_dst_imag)
2667 CALL apply_wannier90_kp_matrix(matrix_ks, ispin, xkp, cell_to_index, sab_nl, &
2668 dst_real, dst_imag, h_dst_real, h_dst_imag)
2670 ALLOCATE (dst_r(nao, nmo), dst_i(nao, nmo), s_coeff_r(nao, nmo), s_coeff_i(nao, nmo), &
2671 h_coeff_r(nao, nmo), h_coeff_i(nao, nmo))
2679 ALLOCATE (s_coeff(nao, nmo), h_coeff(nao, nmo))
2680 s_coeff(:, :) = cmplx(s_coeff_r, s_coeff_i, kind=
dp)
2681 h_coeff(:, :) = cmplx(h_coeff_r, h_coeff_i, kind=
dp)
2684 DO WHILE (block_first <= nmo)
2685 block_last = block_first
2686 DO WHILE (block_last < nmo)
2687 IF (abs(eigenvalues(block_last + 1) - eigenvalues(block_last)) >= degenerate_band_tol)
EXIT
2688 block_last = block_last + 1
2690 block_size = block_last - block_first + 1
2691 IF (block_size > 1)
THEN
2695 ALLOCATE (block_coeff(nao, block_size), h_block(nao, block_size), &
2696 h_projected(block_size, block_size), h_projected_work(block_size, block_size), &
2697 metric_vectors(block_size, block_size), residual_block(nao, block_size), &
2698 ritz_vectors(block_size, block_size), s_block(nao, block_size), &
2699 s_projected(block_size, block_size), stabilized(nao, block_size), &
2700 metric_values(block_size), ritz_values(block_size))
2701 block_coeff(:, :) = cmplx(dst_r(:, block_first:block_last), &
2702 dst_i(:, block_first:block_last), kind=
dp)
2703 s_block(:, :) = s_coeff(:, block_first:block_last)
2704 h_block(:, :) = h_coeff(:, block_first:block_last)
2705 s_projected(:, :) = matmul(conjg(transpose(block_coeff)), s_block)
2706 h_projected(:, :) = matmul(conjg(transpose(block_coeff)), h_block)
2707 s_projected(:, :) = 0.5_dp*(s_projected + conjg(transpose(s_projected)))
2708 h_projected(:, :) = 0.5_dp*(h_projected + conjg(transpose(h_projected)))
2710 CALL diag_complex(s_projected, metric_vectors, metric_values)
2711 aligned_min_svalue = min(aligned_min_svalue, minval(metric_values))
2712 metric_deviation = maxval(abs(metric_values - 1.0_dp))
2713 IF (minval(metric_values) < 1.0e-10_dp)
THEN
2714 WRITE (reason,
"(A,I0,A,ES9.2,A,ES9.2)") &
2715 "singular metric blk=", block_first,
" smin=", minval(metric_values), &
2716 " dS=", metric_deviation
2717 max_residual = huge(1.0_dp)
2718 DEALLOCATE (block_coeff, h_block, h_projected, h_projected_work, metric_vectors, &
2719 residual_block, ritz_vectors, s_block, s_projected, stabilized, &
2720 metric_values, ritz_values)
2721 DEALLOCATE (s_coeff, h_coeff, dst_r, dst_i, s_coeff_r, s_coeff_i, h_coeff_r, &
2731 DO ib = 1, block_size
2732 metric_vectors(:, ib) = metric_vectors(:, ib)/sqrt(metric_values(ib))
2734 h_projected_work(:, :) = matmul(h_projected, metric_vectors)
2735 h_projected(:, :) = matmul(conjg(transpose(metric_vectors)), h_projected_work)
2736 h_projected(:, :) = 0.5_dp*(h_projected + conjg(transpose(h_projected)))
2737 CALL diag_complex(h_projected, ritz_vectors, ritz_values)
2738 h_projected_work(:, :) = matmul(metric_vectors, ritz_vectors)
2739 ritz_vectors(:, :) = h_projected_work
2740 stabilized(:, :) = matmul(block_coeff, ritz_vectors)
2741 residual_block(:, :) = matmul(h_block, ritz_vectors)
2742 h_block(:, :) = residual_block
2743 residual_block(:, :) = matmul(s_block, ritz_vectors)
2744 s_block(:, :) = residual_block
2745 DO ib = 1, block_size
2746 norm_value = sqrt(abs(real(dot_product(stabilized(:, ib), s_block(:, ib)), kind=
dp)))
2747 IF (norm_value > epsilon(1.0_dp))
THEN
2748 stabilized(:, ib) = stabilized(:, ib)/norm_value
2749 h_block(:, ib) = h_block(:, ib)/norm_value
2750 s_block(:, ib) = s_block(:, ib)/norm_value
2753 residual_block(:, :) = h_block
2754 DO ib = 1, block_size
2755 residual_block(:, ib) = residual_block(:, ib) - &
2756 eigenvalues(block_first + ib - 1)*s_block(:, ib)
2758 residual_norm = maxval(abs(residual_block))
2759 max_residual = max(max_residual, residual_norm)
2760 IF (residual_norm > residual_tol)
THEN
2761 WRITE (reason,
"(A,I0,A,ES9.2)") &
2762 "blk=", block_first,
" dS=", metric_deviation
2763 DEALLOCATE (block_coeff, h_block, h_projected, h_projected_work, metric_vectors, &
2764 residual_block, ritz_vectors, s_block, s_projected, stabilized, &
2765 metric_values, ritz_values)
2766 DEALLOCATE (s_coeff, h_coeff, dst_r, dst_i, s_coeff_r, s_coeff_i, h_coeff_r, &
2776 dst_r(:, block_first:block_last) = real(stabilized, kind=
dp)
2777 dst_i(:, block_first:block_last) = aimag(stabilized)
2778 h_coeff(:, block_first:block_last) = h_block
2779 s_coeff(:, block_first:block_last) = s_block
2780 aligned_blocks = aligned_blocks + 1
2781 aligned_max_size = max(aligned_max_size, block_size)
2782 DEALLOCATE (block_coeff, h_block, h_projected, h_projected_work, metric_vectors, &
2783 residual_block, ritz_vectors, s_block, s_projected, stabilized, metric_values, &
2786 block_first = block_last + 1
2790 residual_norm = maxval(abs(h_coeff(:, ib) - eigenvalues(ib)*s_coeff(:, ib)))
2791 max_residual = max(max_residual, residual_norm)
2793 IF (max_residual > residual_tol)
THEN
2794 WRITE (reason,
"(A,ES10.3)") &
2795 "atom/AO W90 reuse guarded: Ritz residual=", max_residual
2796 DEALLOCATE (s_coeff, h_coeff, dst_r, dst_i, s_coeff_r, s_coeff_i, h_coeff_r, h_coeff_i)
2808 IF (aligned_blocks == 0) aligned_min_svalue = 0.0_dp
2811 DEALLOCATE (s_coeff, h_coeff, dst_r, dst_i, s_coeff_r, s_coeff_i, h_coeff_r, h_coeff_i)
2818 END SUBROUTINE ritz_stabilize_wannier90_subspace
2839 SUBROUTINE ritz_reconstruct_wannier90_window(src_real, src_imag, dst_real, dst_imag, matrix_s, &
2840 matrix_ks, xkp, cell_to_index, sab_nl, ispin, &
2841 eigenvalues, nmo_export, success, reason, min_svalue, &
2843 TYPE(
cp_fm_type),
INTENT(IN) :: src_real, src_imag, dst_real, dst_imag
2844 TYPE(
dbcsr_p_type),
DIMENSION(:, :),
POINTER :: matrix_s, matrix_ks
2845 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: xkp
2846 INTEGER,
DIMENSION(:, :, :),
POINTER :: cell_to_index
2849 INTEGER,
INTENT(IN) :: ispin
2850 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: eigenvalues
2851 INTEGER,
INTENT(IN) :: nmo_export
2852 LOGICAL,
INTENT(OUT) :: success
2853 CHARACTER(LEN=*),
INTENT(OUT) :: reason
2854 REAL(kind=
dp),
INTENT(OUT) :: min_svalue, max_residual
2856 REAL(kind=
dp),
PARAMETER :: eigenvalue_tol = 1.0e-6_dp, &
2857 residual_tol = 1.0e-7_dp
2859 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: coeff_work, h_coeff, h_projected, &
2860 h_projected_work, metric_vectors, residual_block, ritz_vectors, s_coeff, s_projected, &
2861 source_coeff, stabilized
2862 INTEGER :: ib, nao, nmo_source
2863 REAL(kind=
dp) :: max_eigenvalue_shift, metric_deviation, &
2865 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: metric_values, ritz_values, &
2867 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: dst_i, dst_r, h_coeff_i, h_coeff_r, &
2868 s_coeff_i, s_coeff_r, src_i, src_r
2870 TYPE(
cp_fm_type) :: h_src_imag, h_src_real, s_src_imag, &
2875 min_svalue = huge(1.0_dp)
2876 max_residual = huge(1.0_dp)
2878 NULLIFY (matrix_struct_metric)
2879 CALL cp_fm_get_info(src_real, nrow_global=nao, ncol_global=nmo_source, &
2880 matrix_struct=matrix_struct_metric)
2881 IF (nmo_export > nmo_source)
THEN
2882 reason =
"Wannier90 export window is larger than the transformed SCF MO space"
2885 IF (
SIZE(eigenvalues) < nmo_export)
THEN
2886 reason =
"not enough eigenvalue storage for Wannier90 source-window reconstruction"
2896 CALL apply_wannier90_kp_matrix(matrix_s, 1, xkp, cell_to_index, sab_nl, &
2897 src_real, src_imag, s_src_real, s_src_imag)
2898 CALL apply_wannier90_kp_matrix(matrix_ks, ispin, xkp, cell_to_index, sab_nl, &
2899 src_real, src_imag, h_src_real, h_src_imag)
2901 ALLOCATE (src_r(nao, nmo_source), src_i(nao, nmo_source), &
2902 s_coeff_r(nao, nmo_source), s_coeff_i(nao, nmo_source), &
2903 h_coeff_r(nao, nmo_source), h_coeff_i(nao, nmo_source), &
2904 dst_r(nao, nmo_export), dst_i(nao, nmo_export))
2912 ALLOCATE (source_coeff(nao, nmo_source), s_coeff(nao, nmo_source), &
2913 h_coeff(nao, nmo_source), h_projected(nmo_source, nmo_source), &
2914 h_projected_work(nmo_source, nmo_source), metric_vectors(nmo_source, nmo_source), &
2915 residual_block(nao, nmo_export), ritz_vectors(nmo_source, nmo_source), &
2916 s_projected(nmo_source, nmo_source), stabilized(nao, nmo_export), &
2917 coeff_work(nao, nmo_source), metric_values(nmo_source), ritz_values(nmo_source), &
2918 source_eigenvalues(nmo_export))
2919 source_eigenvalues(1:nmo_export) = eigenvalues(1:nmo_export)
2920 source_coeff(:, :) = cmplx(src_r, src_i, kind=
dp)
2921 s_coeff(:, :) = cmplx(s_coeff_r, s_coeff_i, kind=
dp)
2922 h_coeff(:, :) = cmplx(h_coeff_r, h_coeff_i, kind=
dp)
2923 s_projected(:, :) = matmul(conjg(transpose(source_coeff)), s_coeff)
2924 h_projected(:, :) = matmul(conjg(transpose(source_coeff)), h_coeff)
2925 s_projected(:, :) = 0.5_dp*(s_projected + conjg(transpose(s_projected)))
2926 h_projected(:, :) = 0.5_dp*(h_projected + conjg(transpose(h_projected)))
2928 reconstruct_window: block
2929 CALL diag_complex(s_projected, metric_vectors, metric_values)
2930 min_svalue = minval(metric_values)
2931 metric_deviation = maxval(abs(metric_values - 1.0_dp))
2932 IF (min_svalue < 1.0e-10_dp)
THEN
2933 WRITE (reason,
"(A,ES9.2,A,ES9.2)") &
2934 "singular expanded metric smin=", min_svalue,
" dS=", metric_deviation
2935 EXIT reconstruct_window
2938 DO ib = 1, nmo_source
2939 metric_vectors(:, ib) = metric_vectors(:, ib)/sqrt(metric_values(ib))
2941 h_projected_work(:, :) = matmul(h_projected, metric_vectors)
2942 h_projected(:, :) = matmul(conjg(transpose(metric_vectors)), h_projected_work)
2943 h_projected(:, :) = 0.5_dp*(h_projected + conjg(transpose(h_projected)))
2944 CALL diag_complex(h_projected, ritz_vectors, ritz_values)
2945 h_projected_work(:, :) = matmul(metric_vectors, ritz_vectors)
2946 ritz_vectors(:, :) = h_projected_work
2947 stabilized(:, :) = matmul(source_coeff, ritz_vectors(:, 1:nmo_export))
2948 coeff_work(:, :) = matmul(h_coeff, ritz_vectors)
2949 h_coeff(:, :) = coeff_work
2950 coeff_work(:, :) = matmul(s_coeff, ritz_vectors)
2951 s_coeff(:, :) = coeff_work
2952 DO ib = 1, nmo_export
2953 norm_value = sqrt(abs(real(dot_product(stabilized(:, ib), s_coeff(:, ib)), kind=
dp)))
2954 IF (norm_value > epsilon(1.0_dp))
THEN
2955 stabilized(:, ib) = stabilized(:, ib)/norm_value
2956 h_coeff(:, ib) = h_coeff(:, ib)/norm_value
2957 s_coeff(:, ib) = s_coeff(:, ib)/norm_value
2960 residual_block(:, :) = h_coeff(:, 1:nmo_export)
2961 DO ib = 1, nmo_export
2962 residual_block(:, ib) = residual_block(:, ib) - ritz_values(ib)*s_coeff(:, ib)
2964 max_residual = maxval(abs(residual_block))
2965 IF (max_residual > residual_tol)
THEN
2966 WRITE (reason,
"(A,ES9.2)") &
2967 "expanded dS=", metric_deviation
2968 EXIT reconstruct_window
2970 max_eigenvalue_shift = maxval(abs(ritz_values(1:nmo_export) - source_eigenvalues(1:nmo_export)))
2971 IF (max_eigenvalue_shift > eigenvalue_tol)
THEN
2972 WRITE (reason,
"(A,ES9.2)") &
2973 "expanded dS=", metric_deviation
2974 EXIT reconstruct_window
2977 dst_r(:, :) = real(stabilized, kind=
dp)
2978 dst_i(:, :) = aimag(stabilized)
2983 END BLOCK reconstruct_window
2985 DEALLOCATE (source_coeff, s_coeff, h_coeff, h_projected, h_projected_work, metric_vectors, &
2986 residual_block, ritz_vectors, s_projected, stabilized, coeff_work, metric_values, &
2987 ritz_values, source_eigenvalues)
2988 DEALLOCATE (src_r, src_i, s_coeff_r, s_coeff_i, h_coeff_r, h_coeff_i, dst_r, dst_i)
2995 END SUBROUTINE ritz_reconstruct_wannier90_window
3006 SUBROUTINE build_wannier90_scf_mapping(kpoint, qs_kpoint, source_kpoint, sym_index, success, &
3008 TYPE(kpoint_type),
POINTER :: kpoint, qs_kpoint
3009 INTEGER,
ALLOCATABLE,
DIMENSION(:),
INTENT(OUT) :: source_kpoint, sym_index
3010 LOGICAL,
INTENT(OUT) :: success
3011 CHARACTER(LEN=*),
INTENT(OUT) :: reason
3013 INTEGER :: ik, ikred, imatch, isym, nfull
3014 TYPE(kpoint_sym_type),
POINTER ::
kpsym
3019 ALLOCATE (source_kpoint(nfull), sym_index(nfull))
3020 source_kpoint(:) = 0
3023 DO ikred = 1, qs_kpoint%nkp
3024 imatch = find_matching_kpoint(kpoint%xkp, qs_kpoint%xkp(1:3, ikred))
3025 IF (imatch > 0 .AND. source_kpoint(imatch) == 0)
THEN
3026 source_kpoint(imatch) = ikred
3027 sym_index(imatch) = 0
3032 DO ikred = 1, qs_kpoint%nkp
3033 imatch = find_matching_kpoint(kpoint%xkp, -qs_kpoint%xkp(1:3, ikred))
3034 IF (imatch > 0 .AND. source_kpoint(imatch) == 0)
THEN
3035 source_kpoint(imatch) = ikred
3036 sym_index(imatch) = -1
3040 IF (
ASSOCIATED(qs_kpoint%kp_sym))
THEN
3041 DO ikred = 1, qs_kpoint%nkp
3042 kpsym => qs_kpoint%kp_sym(ikred)%kpoint_sym
3043 IF (.NOT.
ASSOCIATED(
kpsym)) cycle
3044 IF (.NOT.
kpsym%apply_symmetry) cycle
3045 DO isym = 1,
kpsym%nwred
3046 imatch = find_matching_kpoint(kpoint%xkp,
kpsym%xkp(1:3, isym))
3047 IF (imatch > 0 .AND. source_kpoint(imatch) == 0)
THEN
3048 source_kpoint(imatch) = ikred
3049 sym_index(imatch) = isym
3056 IF (source_kpoint(ik) == 0)
THEN
3057 reason =
"not all full-mesh k-points are represented by the SCF symmetry orbits"
3063 END SUBROUTINE build_wannier90_scf_mapping
3071 INTEGER FUNCTION find_matching_kpoint(xkp_mesh, xkp_search)
RESULT(ik_match)
3072 REAL(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: xkp_mesh
3073 REAL(kind=dp),
DIMENSION(3),
INTENT(IN) :: xkp_search
3078 DO ik = 1,
SIZE(xkp_mesh, 2)
3079 IF (kpoint_same_periodic(xkp_mesh(1:3, ik), xkp_search))
THEN
3085 END FUNCTION find_matching_kpoint
3093 SUBROUTINE infer_wannier_mp_grid(kpt_latt, mp_grid, valid)
3094 REAL(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: kpt_latt
3095 INTEGER,
DIMENSION(3),
INTENT(OUT) :: mp_grid
3096 LOGICAL,
INTENT(OUT) :: valid
3098 INTEGER :: coord_id, i, idim,
idx, n_unique, &
3099 num_kpts, stride, unique_id
3101 LOGICAL,
ALLOCATABLE,
DIMENSION(:) :: seen
3102 REAL(kind=dp) :: coord
3103 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: unique_coord
3105 num_kpts =
SIZE(kpt_latt, 2)
3107 ALLOCATE (unique_coord(3, num_kpts))
3111 coord = kpt_latt(idim, i) - floor(kpt_latt(idim, i))
3112 IF (abs(coord - 1.0_dp) < 1.0e-8_dp) coord = 0.0_dp
3114 DO unique_id = 1, n_unique
3115 IF (abs(unique_coord(idim, unique_id) - coord) < 1.0e-8_dp)
THEN
3120 IF (.NOT. known)
THEN
3121 n_unique = n_unique + 1
3122 unique_coord(idim, n_unique) = coord
3125 mp_grid(idim) = n_unique
3127 valid = (mp_grid(1)*mp_grid(2)*mp_grid(3) == num_kpts)
3129 ALLOCATE (seen(num_kpts))
3135 coord = kpt_latt(idim, i) - floor(kpt_latt(idim, i))
3136 IF (abs(coord - 1.0_dp) < 1.0e-8_dp) coord = 0.0_dp
3138 DO unique_id = 1, mp_grid(idim)
3139 IF (abs(unique_coord(idim, unique_id) - coord) < 1.0e-8_dp)
THEN
3140 coord_id = unique_id
3144 cpassert(coord_id > 0)
3145 idx =
idx + (coord_id - 1)*stride
3146 stride = stride*mp_grid(idim)
3148 IF (seen(
idx)) valid = .false.
3151 valid = valid .AND. all(seen)
3154 DEALLOCATE (unique_coord)
3156 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.
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public gresch2017
integer, save, public soluyanov2011
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_scale(matrix, alpha_scalar)
...
subroutine, public dbcsr_deallocate_matrix(matrix)
...
subroutine, public dbcsr_desymmetrize(matrix_a, matrix_b)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_add(matrix_a, matrix_b, alpha_scalar, beta_scalar)
...
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
integer, parameter, public default_path_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 kpoint_release(kpoint)
Release a kpoint environment, deallocate all data.
subroutine, public get_kpoint_info(kpoint, kp_scheme, nkp_grid, kp_shift, symmetry, verbose, full_grid, use_real_wfn, eps_geo, parallel_group_size, kp_range, nkp, xkp, wkp, para_env, blacs_env_all, para_env_kp, para_env_inter_kp, blacs_env, kp_env, kp_aux_env, mpools, iogrp, nkp_groups, kp_dist, cell_to_index, index_to_cell, sab_nl, sab_nl_nosym, inversion_symmetry_only, symmetry_backend, symmetry_reduction_method, gamma_centered, lattice_fft)
Retrieve information from a kpoint environment.
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, ordered, ordered_kpoints)
...
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, matrix_t, store_ot_matrices, transfer_only, added_mos_auto_grow)
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
subroutine, public v_soc_xyz_from_pseudopotential(qs_env, mat_v_soc_xyz)
V^SOC_µν^(α),R = ħ/2 < ϕ_µ cell O | sum_ℓ ΔV_ℓ^SO(r,r') L^(α) | ϕ_ν cell R>, α = x,...
Versioned Gaussian-basis snapshots for cross-geometry topology overlaps. Atomic units,...
subroutine, public topology_state_begin(qs_env, filename, nao, nband, npoint, nspin, ntotal, spin_channel, bands, unit)
Write basis metadata; all ranks call, only the source writes.
subroutine, public topology_state_point(unit, point, k, eigenvalues, coefficients)
Write one point with eigenvalues in Hartree and physical AO coefficients.
Local Wilson-loop linear algebra, independent of the electronic-structure representation....
real(kind=dp) function, public wcc_distance(a, b)
Minimum maximal cyclic matching distance between two WCC sets.
subroutine, public wilson_step(product, overlap, minimum_sv, status, sv_tol)
Multiply by the unitary polar factor of an overlap. Reject rank-deficient links.
subroutine, public z2_from_wcc(wcc, invariant, status, pair_tol)
Largest-gap crossing parity for an ordered time-reversal half-surface. Endpoint degeneracy is necessa...
logical function, public surface_resolved(wcc)
Conservative neighbouring-line movement and largest-gap separation checks.
subroutine, public wilson_spectrum(product, wcc, berry, status)
Sorted Wilson eigenphases in reduced units and total Berry phase in radians.
subroutine, public chern_from_wcc(wcc, invariant, winding, status, closure_tol)
First Chern number from determinant Wilson-phase winding on a closed surface. Both transverse endpoin...
Read explicit Wannier90 overlap connections, including nonuniform closed loops.
subroutine, public read_wannier90_nnkpts(filename, real_lattice, recip_lattice, kpt, nnlist, nncell)
Read and validate the cell, points, and directed connections of an nnkp file.
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