60 integer,
allocatable :: imats(:)
61 integer,
allocatable :: coff(:)
63 logical :: is_cmplx = .false.
66 real(real64),
allocatable :: dt(:, :, :)
67 complex(real64),
allocatable :: zt(:, :, :)
74 logical,
public :: use_global_coupling = .false.
75 logical,
public :: coupling_built = .false.
76 integer :: ncluster = 0
77 integer,
allocatable :: proj_offset(:)
78 type(overlap_cluster_t),
allocatable :: clusters(:)
88 logical :: uspp_gpu_approx_warned = .false.
97 subroutine overlap_matrix_detect(this, nmat, projector_matrices, projector_to_atom, epot, space, self_overlap)
98 class(overlap_matrix_t),
intent(inout) :: this
99 integer,
intent(in) :: nmat
100 type(projector_matrix_t),
intent(in) :: projector_matrices(:)
101 integer,
intent(in) :: projector_to_atom(:)
102 type(epot_t),
intent(in) :: epot
103 class(space_t),
intent(in) :: space
104 logical,
intent(in) :: self_overlap
106 integer :: im, jm, ia, ja, ic, root, nroots, kk
107 integer,
allocatable :: parent(:), root_of(:), csize(:), cluster_of(:), fill(:)
108 logical :: any_overlap
115 safe_allocate(this%proj_offset(1:max(nmat, 1)))
118 this%proj_offset(im) = kk
119 kk = kk + projector_matrices(im)%nprojs
129 safe_allocate(parent(1:nmat))
133 any_overlap = .false.
135 ia = projector_to_atom(im)
137 ja = projector_to_atom(jm)
139 if (
submesh_overlap(epot%proj(ia)%sphere, epot%proj(ja)%sphere, space))
then
147 this%use_global_coupling = any_overlap .or. self_overlap
148 if (.not. this%use_global_coupling)
then
149 safe_deallocate_a(parent)
155 safe_allocate(cluster_of(1:nmat))
156 safe_allocate(root_of(1:nmat))
157 safe_allocate(csize(1:nmat))
164 if (root_of(kk) == root)
then
171 root_of(nroots) = root
175 csize(ic) = csize(ic) + 1
178 this%ncluster = nroots
179 safe_allocate(this%clusters(1:nroots))
180 safe_allocate(fill(1:nroots))
183 this%clusters(ic)%nmat = csize(ic)
184 safe_allocate(this%clusters(ic)%imats(1:csize(ic)))
185 safe_allocate(this%clusters(ic)%coff(1:csize(ic)))
190 fill(ic) = fill(ic) + 1
191 this%clusters(ic)%imats(fill(ic)) = im
195 do im = 1, this%clusters(ic)%nmat
196 this%clusters(ic)%coff(im) = kk
197 kk = kk + projector_matrices(this%clusters(ic)%imats(im))%nprojs
199 this%clusters(ic)%nc = kk
202 safe_deallocate_a(parent)
203 safe_deallocate_a(cluster_of)
204 safe_deallocate_a(root_of)
205 safe_deallocate_a(csize)
206 safe_deallocate_a(fill)
213 recursive integer function uf_find(parent, ii)
result(rr)
214 integer,
intent(inout) :: parent(:)
215 integer,
intent(in) :: ii
217 if (parent(ii) /= ii) parent(ii) =
uf_find(parent, parent(ii))
224 integer,
intent(inout) :: parent(:)
225 integer,
intent(in) :: ii, jj
231 if (ri /= rj) parent(rj) = ri
253 complex(real64),
allocatable,
intent(in) :: projector_phases(:, :, :, :)
254 class(
mesh_t),
intent(in) :: mesh
255 integer,
intent(in) :: kstart
256 integer,
intent(in) :: kend
258 integer :: c, ik, nc, a, b, oa, ob, ii, jj, nI
261 complex(real64),
allocatable :: zgI(:, :), zgJ(:, :), mmat(:, :), qmat(:, :), amat(:, :), tmat(:, :)
265 if (.not. this%use_global_coupling)
then
274 uspp_gpu_approx_warned = .
true.
275 message(1) =
"Ultrasoft projector spheres of different atoms overlap on the grid."
276 message(2) =
"The exact inverse overlap S^{-1} is applied on the CPU only; the GPU path"
277 message(3) =
"still uses the per-atom approximation. Convergence on GPU may be degraded."
281 phased =
allocated(projector_phases)
283 do c = 1, this%ncluster
284 cl => this%clusters(c)
288 cl%is_cmplx = phased .or. projector_matrices(cl%imats(1))%is_cmplx
290 if (cl%is_cmplx)
then
291 if (.not.
allocated(cl%zt))
then
292 safe_allocate(cl%zt(1:nc, 1:nc, kstart:kend))
295 if (.not.
allocated(cl%dt))
then
296 safe_allocate(cl%dt(1:nc, 1:nc, kstart:kend))
300 safe_allocate(mmat(1:nc, 1:nc))
301 safe_allocate(qmat(1:nc, 1:nc))
302 safe_allocate(amat(1:nc, 1:nc))
303 safe_allocate(tmat(1:nc, 1:nc))
316 projector_matrices(cl%imats(b)), zgi, zgj, mmat, oa, ob)
317 safe_deallocate_a(zgj)
319 safe_deallocate_a(zgi)
324 mmat(ii, jj) = conjg(mmat(jj, ii))
328 if (mesh%parallel_in_domains)
call mesh%allreduce(mmat, dim = (/nc, nc/))
329 mmat = mmat * mesh%volume_element
334 ni = projector_matrices(cl%imats(a))%nprojs
336 qmat(oa+1:oa+ni, oa+1:oa+ni) = &
337 cmplx(projector_matrices(cl%imats(a))%qmix(1:ni, 1:ni),
m_zero, real64)
341 amat = matmul(mmat, qmat)
343 amat(ii, ii) = amat(ii, ii) +
m_z1
346 tmat = matmul(qmat, amat)
348 if (cl%is_cmplx)
then
349 cl%zt(1:nc, 1:nc, ik) = -tmat(1:nc, 1:nc)
351 cl%dt(1:nc, 1:nc, ik) = -real(tmat(1:nc, 1:nc), real64)
356 safe_deallocate_a(mmat)
357 safe_deallocate_a(qmat)
358 safe_deallocate_a(amat)
359 safe_deallocate_a(tmat)
362 this%coupling_built = .
true.
370 integer,
intent(in) :: im
371 integer,
intent(in) :: ik
372 complex(real64),
allocatable,
intent(out) :: zg(:, :)
374 integer :: np, npr, p, i
376 np = projector_matrices(im)%npoints
377 npr = projector_matrices(im)%nprojs
378 safe_allocate(zg(1:max(np, 1), 1:npr))
381 if (
allocated(projector_matrices(im)%zprojectors))
then
384 zg(p, i) = projector_matrices(im)%zprojectors(p, i)
390 zg(p, i) = cmplx(projector_matrices(im)%dprojectors(p, i),
m_zero, real64)
398 zg(p, i) = zg(p, i) * conjg(projector_phases(p, 1, im, ik))
411 complex(real64),
intent(in) :: zgI(:, :)
412 complex(real64),
intent(in) :: zgJ(:, :)
413 complex(real64),
intent(inout) :: mmat(:, :)
414 integer,
intent(in) :: oa
415 integer,
intent(in) :: ob
417 integer :: ri, rj, ip, jp, ipe, jpe, ni, nj, i, j, dd
418 complex(real64) :: bra
422 do ri = 1, pmi%nregions
423 ipe = pmi%regions(ri + 1) - 1
424 do rj = 1, pmj%nregions
425 jpe = pmj%regions(rj + 1) - 1
428 do while (ip <= ipe .and. jp <= jpe)
429 dd = pmi%map(ip) - pmj%map(jp)
432 else if (dd > 0)
then
436 bra = conjg(zgi(ip, i))
438 mmat(oa+i, ob+j) = mmat(oa+i, ob+j) + bra*zgj(jp, j)
460 if (
allocated(this%clusters))
then
461 do ic = 1,
size(this%clusters)
462 safe_deallocate_a(this%clusters(ic)%imats)
463 safe_deallocate_a(this%clusters(ic)%coff)
464 safe_deallocate_a(this%clusters(ic)%dt)
465 safe_deallocate_a(this%clusters(ic)%zt)
467 safe_deallocate_a(this%clusters)
469 safe_deallocate_a(this%proj_offset)
471 this%use_global_coupling = .false.
472 this%coupling_built = .false.
479#include "nonlocal_overlap_matrix_inc.F90"
482#include "complex.F90"
483#include "nonlocal_overlap_matrix_inc.F90"
pure logical function, public accel_is_enabled()
real(real64), parameter, public m_zero
complex(real64), parameter, public m_z0
complex(real64), parameter, public m_z1
This module defines the meshes, which are used in Octopus.
subroutine, public messages_warning(no_lines, all_nodes, namespace)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Exact inverse of the ultrasoft/PAW generalized overlap operator for overlapping spheres.
subroutine overlap_matrix_build(this, projector_matrices, projector_phases, mesh, kstart, kend)
Assemble the exact inverse-overlap coupling -T for each overlap cluster.
subroutine doverlap_matrix_apply(this, projector_matrices, proj, nst_linear, ik)
Apply the exact inverse-overlap coupling p` = -T p (mix = -T stored per cluster), dense within each o...
subroutine uf_union(parent, ii, jj)
Union-find "union" of two projector matrices into one cluster.
subroutine overlap_matrix_detect(this, nmat, projector_matrices, projector_to_atom, epot, space, self_overlap)
Detect distinct-atom projector overlap and group the projector matrices into the connected components...
subroutine zoverlap_matrix_apply(this, projector_matrices, proj, nst_linear, ik)
Apply the exact inverse-overlap coupling p` = -T p (mix = -T stored per cluster), dense within each o...
subroutine overlap_matrix_end(this)
Release the exact inverse-overlap cluster data.
recursive integer function uf_find(parent, ii)
Union-find "find" with path compression (roots of the projector-overlap graph).
/* To use the profiling module, call profiling_in and profiling_out with the label of the region as a...
logical function, public submesh_overlap(sm1, sm2, space)
subroutine fill_phased_ket(im, ik, zg)
subroutine accumulate_gram(pmI, pmJ, zgI, zgJ, mmat, oa, ob)
Describes mesh distribution to nodes.
One connected component of the projector-overlap graph.
The exact inverse-overlap operator, grouped into overlap clusters.
A set of projectors defined on a submesh.