13#if defined (__HAS_IEEE_EXCEPTIONS)
14 USE ieee_exceptions,
ONLY: ieee_all, ieee_get_halting_mode, ieee_set_halting_mode
18#include "./base/base_uses.f90"
23 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'wannier90_projections'
38 REAL(kind=
dp),
INTENT(IN) :: eigenvalues(:)
39 INTEGER,
INTENT(IN) :: num_wann
40 REAL(kind=
dp),
INTENT(IN) :: windows(4)
41 LOGICAL,
INTENT(IN) :: window_set(4)
42 LOGICAL,
INTENT(OUT) :: allowed(:)
44 LOGICAL :: frozen(size(eigenvalues))
46 cpassert(
SIZE(allowed) ==
SIZE(eigenvalues))
48 IF (window_set(1)) allowed = allowed .AND. eigenvalues >= windows(1)
49 IF (window_set(2)) allowed = allowed .AND. eigenvalues <= windows(2)
50 IF (count(allowed) < num_wann)
THEN
51 cpabort(
'Wannier90 outer window contains too few bands.')
53 IF (window_set(4))
THEN
54 frozen = eigenvalues <= windows(4)
55 IF (window_set(3)) frozen = frozen .AND. eigenvalues >= windows(3)
56 IF (count(frozen) > num_wann)
THEN
57 cpabort(
'Wannier90 frozen window contains too many bands.')
59 IF (any(frozen .AND. .NOT. allowed))
THEN
60 cpabort(
'Wannier90 frozen states lie outside the outer window.')
62 IF (count(frozen) == num_wann) allowed = frozen
73 COMPLEX(KIND=dp),
INTENT(IN) :: ao(:, :, :)
74 INTEGER,
INTENT(IN) :: groups(:, :)
75 COMPLEX(KIND=dp),
ALLOCATABLE,
INTENT(OUT) :: candidates(:, :, :)
77 REAL(kind=
dp),
PARAMETER :: hybrid(4, 4) = 0.5_dp*reshape([1.0_dp, 1.0_dp, 1.0_dp, 1.0_dp, &
78 1.0_dp, 1.0_dp, -1.0_dp, -1.0_dp, 1.0_dp, -1.0_dp, 1.0_dp, -1.0_dp, 1.0_dp, -1.0_dp, &
79 -1.0_dp, 1.0_dp], [4, 4])
81 INTEGER :: iao, ic, ig, ik, nao, nb, nk
82 LOGICAL,
ALLOCATABLE :: grouped(:)
88 ALLOCATE (candidates(0, 0, 0))
91 cpassert(
SIZE(groups, 1) == 4)
92 cpassert(all(groups > 0) .AND. all(groups <= nao))
93 ALLOCATE (grouped(nao))
95 DO ig = 1,
SIZE(groups, 2)
97 cpassert(count(groups(:, ig) == groups(ic, ig)) == 1)
99 grouped(groups(:, ig)) = .true.
101 ALLOCATE (candidates(nb, count(.NOT. grouped) + 4*
SIZE(groups, 2), nk))
104 IF (grouped(iao)) cycle
106 candidates(:, ic, :) = ao(:, iao, :)
110 DO ig = 1,
SIZE(groups, 2)
112 candidates(:, ic + 1:ic + 4, ik) = matmul(ao(:, groups(:, ig), ik), hybrid)
130 COMPLEX(KIND=dp),
INTENT(IN) :: candidates(:, :, :)
132 COMPLEX(KIND=dp),
INTENT(OUT) :: amn(:, :, :)
133 INTEGER,
INTENT(OUT) :: pivots(:)
134 REAL(kind=
dp),
INTENT(OUT) :: min_svalue
135 INTEGER,
INTENT(IN),
OPTIONAL :: anchor_kpoint
137 COMPLEX(KIND=dp),
ALLOCATABLE :: qr(:, :)
138 INTEGER :: anchor, best_defect, defect, &
139 first_anchor, ic, ik, iw, last_anchor, &
140 nb, nc, nk, nr, nw, previous_defect, &
142 INTEGER,
ALLOCATABLE :: best_pivots(:)
147 cpassert(nb >= nw .AND. nw > 0 .AND.
SIZE(pivots) == nw)
150 IF (
PRESENT(anchor_kpoint))
THEN
151 cpassert(anchor_kpoint >= 0 .AND. anchor_kpoint <= nk)
152 first_anchor = anchor_kpoint
153 last_anchor = anchor_kpoint
156 IF (para_env%is_source())
THEN
157 nc =
SIZE(candidates, 2)
158 cpassert(
SIZE(candidates, 1) == nb .AND.
SIZE(candidates, 3) == nk)
160 ALLOCATE (best_pivots(nw))
161 best_defect = huge(0)
162 DO anchor = first_anchor, last_anchor
164 IF (anchor > 0) nr = nb
165 ALLOCATE (qr(nr, nc))
166 IF (anchor == 0)
THEN
168 qr((ik - 1)*nb + 1:ik*nb, :) = candidates(:, :, ik)
171 qr(:, :) = candidates(:, :, anchor)
175 CALL select_qr_pivots(qr, pivots)
177 amn(:, :, ik) = candidates(:, pivots, ik)
182 IF (defect < best_defect)
THEN
184 best_pivots(:) = pivots(:)
186 IF (min_svalue >= 1.0e-10_dp)
EXIT
188 IF (best_defect > 0 .AND. .NOT.
PRESENT(anchor_kpoint))
THEN
193 previous_defect = best_defect
194 repair:
DO iw = 1, nw
195 saved_pivot = pivots(iw)
197 IF (any(pivots == ic)) cycle
200 amn(:, :, ik) = candidates(:, pivots, ik)
203 IF (defect < best_defect)
THEN
207 pivots(iw) = saved_pivot
210 IF (best_defect == 0 .OR. best_defect == previous_defect)
EXIT
213 amn(:, :, ik) = candidates(:, pivots, ik)
217 DEALLOCATE (best_pivots)
219 CALL para_env%bcast(amn)
220 CALL para_env%bcast(pivots)
221 CALL para_env%bcast(min_svalue)
230 SUBROUTINE select_qr_pivots(qr, pivots)
231 COMPLEX(KIND=dp),
INTENT(INOUT) :: qr(:, :)
232 INTEGER,
INTENT(OUT) :: pivots(:)
234 REAL(kind=
dp),
PARAMETER :: tie_tolerance = 1.0e-12_dp
236 COMPLEX(KIND=dp) :: tau(1)
237 COMPLEX(KIND=dp),
ALLOCATABLE :: column(:), work(:)
238 INTEGER :: ic, info, ip, iw, nc, nr, original
239 INTEGER,
ALLOCATABLE :: order(:)
240 REAL(kind=
dp) :: largest
241 REAL(kind=
dp),
ALLOCATABLE :: norms(:)
245 cpassert(
SIZE(pivots) <= min(nr, nc))
246 ALLOCATE (column(nr), work(max(1, nc)), order(nc), norms(nc))
247 order(:) = [(ic, ic=1, nc)]
248 DO iw = 1,
SIZE(pivots)
250 norms(ic) = sum(abs(qr(iw:nr, ic))**2)
252 largest = maxval(norms(iw:nc))
256 IF (norms(ic) < largest*(1.0_dp - tie_tolerance)) cycle
257 IF (order(ic) < original)
THEN
262 column(:) = qr(:, iw)
263 qr(:, iw) = qr(:, ip)
265 order(ip) = order(iw)
267 pivots(iw) = original
269 CALL zgeqrf(nr - iw + 1, 1, qr(iw, iw), nr, tau, work,
SIZE(work), info)
272 CALL zunmqr(
'L',
'C', nr - iw + 1, nc - iw, 1, qr(iw, iw), nr, tau, &
273 qr(iw, iw + 1), nr, work,
SIZE(work), info)
277 DEALLOCATE (column, work, order, norms)
278 END SUBROUTINE select_qr_pivots
287 COMPLEX(KIND=dp),
INTENT(IN) :: amn(:, :, :)
288 INTEGER,
INTENT(OUT),
OPTIONAL :: rank_defect
289 REAL(kind=
dp) :: min_svalue
291 COMPLEX(KIND=dp) :: query(1), unused_u(1, 1), unused_v(1, 1)
292 COMPLEX(KIND=dp),
ALLOCATABLE :: matrix(:, :), work(:)
293 INTEGER :: ik, info, lwork, nb, nw
294 REAL(kind=
dp),
ALLOCATABLE :: rwork(:), svalues(:)
295#if defined (__HAS_IEEE_EXCEPTIONS)
296 LOGICAL :: halt(size(ieee_all))
301 cpassert(nb >= nw .AND. nw > 0 .AND.
SIZE(amn, 3) > 0)
302 ALLOCATE (matrix(nb, nw), svalues(nw), rwork(5*nw))
303 matrix(:, :) = amn(:, :, 1)
304 CALL zgesvd(
'N',
'N', nb, nw, matrix, nb, svalues, unused_u, 1, unused_v, 1, query, -1, rwork, info)
306 lwork = max(1, int(real(query(1), kind=
dp)))
307 ALLOCATE (work(lwork))
308 min_svalue = huge(0.0_dp)
309 IF (
PRESENT(rank_defect)) rank_defect = 0
310 DO ik = 1,
SIZE(amn, 3)
311 matrix(:, :) = amn(:, :, ik)
313#if defined (__HAS_IEEE_EXCEPTIONS)
314 CALL ieee_get_halting_mode(ieee_all, halt)
315 CALL ieee_set_halting_mode(ieee_all, .false.)
317 CALL zgesvd(
'N',
'N', nb, nw, matrix, nb, svalues, unused_u, 1, unused_v, 1, work, lwork, rwork, info)
318#if defined (__HAS_IEEE_EXCEPTIONS)
319 CALL ieee_set_halting_mode(ieee_all, halt)
322 min_svalue = min(min_svalue, minval(svalues))
323 IF (
PRESENT(rank_defect)) rank_defect = rank_defect + count(svalues < 1.0e-10_dp)
325 DEALLOCATE (matrix, work, rwork, svalues)
Defines the basic variable types.
integer, parameter, public dp
Interface to the message passing library MPI.
Gauge-covariant selection of fixed trial orbitals for Wannier90.
subroutine, public wannier90_window_mask(eigenvalues, num_wann, windows, window_set, allowed)
Restrict fixed trial selection to the bands admitted by disentanglement windows.
real(kind=dp) function, public wannier90_projection_rank(amn, rank_defect)
Validate the trial rank independently at every k-point.
subroutine, public wannier90_select_projections(candidates, para_env, amn, pivots, min_svalue, anchor_kpoint)
Select the same trial orbitals at every k-point using a mesh-wide pivoted QR.
subroutine, public wannier90_hybrid_candidates(ao, groups, candidates)
Form tetrahedral s/p trials from the full AO bank before selecting projections.
stores all the informations relevant to an mpi environment