88 complex(real64),
allocatable :: phase(:, :)
91 complex(real64),
public,
allocatable :: phase_corr(:,:)
94 complex(real64),
allocatable :: phase_k(:, :)
96 complex(real64),
allocatable :: phase_corr_k(:,:)
97 complex(real64),
allocatable :: vp_phase(:)
98 complex(real64),
allocatable :: vp_phase_corr(:)
99 complex(real64),
allocatable :: phase_spiral(:,:)
102 type(accel_mem_t) :: buff_phase
103 type(accel_mem_t) :: buff_phase_spiral
104 type(accel_mem_t),
public :: buff_phase_corr
105 integer :: buff_phase_qn_start
106 real(real64),
public,
pointer :: spin(:,:,:) => null()
134 class(phase_t),
intent(inout) :: phase
135 class(mesh_t),
intent(in) :: gr
136 type(distributed_t),
intent(in) :: kpt
137 type(kpoints_t),
intent(in) :: kpoints
138 type(states_elec_dim_t),
intent(in) :: d
139 type(space_t),
intent(in) :: space
141 integer :: ip, ik, sp
142 integer(int64) :: ip_inner_global
143 real(real64) :: kpoint(space%dim), x_global(space%dim)
150 phase%buff_phase_qn_start = kpt%start
152 if(kpoints%gamma_only())
then
157 safe_allocate(phase%phase(1:gr%np_part, kpt%start:kpt%end))
158 safe_allocate(phase%phase_corr(gr%np+1:gr%np_part, kpt%start:kpt%end))
160 do ik = kpt%start, kpt%end
162 do ip = gr%np + 1, gr%np_part
163 phase%phase_corr(ip, ik) =
m_one
172 if (gr%der%boundaries%spiralBC)
then
174 if (gr%parallel_in_domains) sp = gr%np + gr%pv%np_ghost
180 safe_allocate(phase%phase_spiral(1:gr%np_part-sp, 1:2))
183 do ip = sp + 1, gr%np_part
187 phase%phase_spiral(ip-sp, 1) = &
188 exp(
m_zi * sum((gr%x(1:space%dim, ip)-x_global(1:space%dim)) * gr%der%boundaries%spiral_q(1:space%dim)))
189 phase%phase_spiral(ip-sp, 2) = &
190 exp(-
m_zi * sum((gr%x(1:space%dim, ip)-x_global(1:space%dim)) * gr%der%boundaries%spiral_q(1:space%dim)))
195 call accel_write_buffer(phase%buff_phase_spiral, gr%np_part-sp, 2, phase%phase_spiral)
206 if (gr%parallel_in_domains) sp = gr%np + gr%pv%np_ghost
209 do ik = kpt%start, kpt%end
210 kpoint(1:space%dim) = kpoints%get_point(d%get_kpoint_index(ik))
212 do ip = 1, gr%np_part
213 phase%phase(ip, ik) =
exp(-
m_zi * sum(gr%x(1:space%dim, ip) * kpoint(1:space%dim)))
219 do ip = sp + 1, gr%np_part
225 phase%phase_corr(ip, ik) = phase%phase(ip, ik)* &
226 exp(
m_zi * sum(x_global(1:space%dim) * kpoint(1:space%dim)))
236 call accel_write_buffer(phase%buff_phase_corr, gr%np_part - gr%np, kpt%nlocal(), phase%phase_corr)
244 subroutine phase_update_phases(phase, mesh, kpt, kpoints, d, space, uniform_vector_potential)
245 class(
phase_t),
intent(inout) :: phase
246 class(
mesh_t),
intent(in) :: mesh
250 type(
space_t),
intent(in) :: space
251 real(real64),
allocatable,
intent(in) :: uniform_vector_potential(:)
253 integer :: ik, ip, sp
254 integer(int64),
dimension(2) :: np, gsize, bsize
255 integer(int64) :: ip_inner_global
256 real(real64) :: kpoint(space%dim)
257 real(real64),
allocatable :: x_global(:,:), kpt_vec_pot(:,:)
258 type(
accel_mem_t) :: buff_vec_pot, buff_x_global, buff_x
261 character(len=128) :: kernel_name
262 real(real64) :: tmp_sum
264 if (.not.
allocated(uniform_vector_potential))
return
269 if (.not.
allocated(phase%phase))
then
270 safe_allocate(phase%phase(1:mesh%np_part, kpt%start:kpt%end))
273 mesh%np_part*kpt%nlocal())
277 if (.not.
allocated(phase%phase_corr))
then
278 safe_allocate(phase%phase_corr(mesh%np+1:mesh%np_part, kpt%start:kpt%end))
281 (mesh%np_part - mesh%np)*kpt%nlocal())
290 if (mesh%parallel_in_domains) sp = mesh%np + mesh%pv%np_ghost
292 safe_allocate(x_global(1:space%dim,(sp + 1):mesh%np_part))
295 do ip = sp + 1, mesh%np_part
299 x_global(:,ip) =
mesh_x_global(mesh, ip_inner_global) - mesh%x(1:space%dim, ip)
307 if (.not.
allocated(phase%phase_k))
then
308 safe_allocate(phase%phase_k(1:mesh%np_part, kpt%start:kpt%end))
309 safe_allocate(phase%phase_corr_k(sp + 1:mesh%np_part, kpt%start:kpt%end))
310 safe_allocate(phase%vp_phase(1:mesh%np_part))
311 safe_allocate(phase%vp_phase_corr(sp + 1:mesh%np_part))
313 do ik = kpt%start, kpt%end
314 kpoint(1:space%dim) = kpoints%get_point(d%get_kpoint_index(ik))
316 do ip = 1, mesh%np_part
317 tmp_sum = sum(mesh%x(1:space%dim, ip)*kpoint(1:space%dim))
318 phase%phase_k(ip, ik) = cmplx(
cos(tmp_sum), -
sin(tmp_sum), real64)
322 do ip = sp + 1, mesh%np_part
323 tmp_sum = sum(x_global(1:space%dim, ip)*kpoint(1:space%dim))
324 phase%phase_corr_k(ip, ik) = cmplx(
cos(tmp_sum),
sin(tmp_sum), real64)
334 do ip = 1, mesh%np_part
335 tmp_sum = sum(mesh%x(1:space%dim, ip)*uniform_vector_potential(1:space%dim))
336 phase%vp_phase(ip) = cmplx(
cos(tmp_sum), -
sin(tmp_sum), real64)
340 do ip = sp + 1, mesh%np_part
341 tmp_sum = sum(x_global(1:space%dim, ip)*uniform_vector_potential(1:space%dim))
342 phase%vp_phase_corr(ip) = cmplx(
cos(tmp_sum),
sin(tmp_sum), real64)
347 do ik = kpt%start, kpt%end
349 do ip = 1, mesh%np_part
350 phase%phase(ip, ik) = phase%phase_k(ip, ik) * phase%vp_phase(ip)
354 do ip = sp + 1, mesh%np_part
355 phase%phase_corr(ip, ik) = phase%phase_corr_k(ip, ik) * phase%vp_phase_corr(ip)
364 safe_allocate(kpt_vec_pot(1:space%dim,kpt%start:kpt%end))
365 do ik = kpt%start, kpt%end
366 kpoint(1:space%dim) = kpoints%get_point(d%get_kpoint_index(ik))
367 kpt_vec_pot(1:space%dim, ik) = kpoint(1:space%dim) + uniform_vector_potential(1:space%dim)
376 call accel_write_buffer(buff_x_global, space%dim, mesh%np_part-sp, x_global(1:space%dim,(sp + 1):mesh%np_part), async=.
true.)
378 write(kernel_name,
'(a,i1,a)')
'update_phases<double, Dim::D', space%dim,
'>'
379 kernel => kernels(space%dim)
394 np = (/mesh%np_part, kpt%nlocal()/)
401 call accel_read_buffer(phase%buff_phase_corr, mesh%np_part - mesh%np, kpt%nlocal(), phase%phase_corr)
406 safe_deallocate_a(kpt_vec_pot)
409 safe_deallocate_a(x_global)
417 class(
phase_t),
intent(inout) :: phase
430 safe_deallocate_a(phase%phase)
431 safe_deallocate_a(phase%phase_corr)
432 safe_deallocate_a(phase%phase_k)
433 safe_deallocate_a(phase%phase_corr_k)
434 safe_deallocate_a(phase%vp_phase)
435 safe_deallocate_a(phase%vp_phase_corr)
436 safe_deallocate_a(phase%phase_spiral)
444 class(
phase_t),
intent(inout) :: phase
445 class(
mesh_t),
intent(in) :: mesh
457 phase%buff_phase_qn_start = kpt%start
463 if (
allocated(phase%phase))
then
464 assert(
size(phase%phase, 1) == mesh%np_part)
465 nlocal = ubound(phase%phase, dim=2) - lbound(phase%phase, dim=2) + 1
470 if (
allocated(phase%phase_corr))
then
471 assert(
size(phase%phase_corr, 1) == mesh%np_part - mesh%np)
472 nlocal = ubound(phase%phase_corr, dim=2) - lbound(phase%phase_corr, dim=2) + 1
474 size(phase%phase_corr, 1)*nlocal)
475 call accel_write_buffer(phase%buff_phase_corr,
size(phase%phase_corr, 1), nlocal, phase%phase_corr)
478 if (
allocated(phase%phase_spiral))
then
480 size(phase%phase_spiral, 1)*
size(phase%phase_spiral, 2))
482 size(phase%phase_spiral, 2), phase%phase_spiral)
492 class(
phase_t),
intent(in) :: phase
493 class(
mesh_t),
intent(in) :: mesh
495 logical,
optional,
intent(in) :: async
498 logical :: phase_correction
503 phase_correction = phase%is_allocated()
507 if (phase_correction)
then
508 call phase%apply_to(mesh, mesh%np, .false., psib, async=async)
518 class(
phase_t),
intent(in) :: phase
519 class(
mesh_t),
intent(in) :: mesh
521 logical,
optional,
intent(in) :: async
523 logical :: phase_correction
528 phase_correction = phase%is_allocated()
532 if (phase_correction)
then
533 call phase%apply_to(mesh, mesh%np, .
true., psib, async=async)
543 class(
phase_t),
intent(in) :: this
544 class(
mesh_t),
intent(in) :: mesh
545 integer,
intent(in) :: np
546 logical,
intent(in) :: conjugate
547 type(
wfs_elec_t),
target,
intent(inout) :: psib
548 type(
wfs_elec_t),
optional,
target,
intent(in) :: src
549 logical,
optional,
intent(in) :: async
551 integer :: ip, ii, sp
553 complex(real64) :: phase
554 integer(int64),
dimension(3) :: gsizes, bsizes
562 assert(np <= mesh%np_part)
564 assert(psib%ik >= lbound(this%phase, dim=2))
565 assert(psib%ik <= ubound(this%phase, dim=2))
568 if (
present(src)) src_ => src
570 assert(src_%has_phase .eqv. conjugate)
571 assert(src_%ik == psib%ik)
575 sp = min(np, mesh%np)
576 if (np > mesh%np .and. mesh%parallel_in_domains) sp = mesh%np + mesh%pv%np_ghost
578 select case (psib%status())
585 do ip = 1, min(mesh%np, np)
586 phase = conjg(this%phase(ip, psib%ik))
588 do ii = 1, psib%nst_linear
589 psib%zff_pack(ii, ip) = phase*src_%zff_pack(ii, ip)
597 phase = conjg(this%phase(ip, psib%ik))
599 do ii = 1, psib%nst_linear
600 psib%zff_pack(ii, ip) = phase*src_%zff_pack(ii, ip)
609 do ip = 1, min(mesh%np, np)
610 phase = this%phase(ip, psib%ik)
612 do ii = 1, psib%nst_linear
613 psib%zff_pack(ii, ip) = phase*src_%zff_pack(ii, ip)
621 phase = this%phase(ip, psib%ik)
623 do ii = 1, psib%nst_linear
624 psib%zff_pack(ii, ip) = phase*src_%zff_pack(ii, ip)
636 do ii = 1, psib%nst_linear
638 do ip = 1, min(mesh%np, np)
639 psib%zff_linear(ip, ii) = conjg(this%phase(ip, psib%ik))*src_%zff_linear(ip, ii)
646 psib%zff_linear(ip, ii) = conjg(this%phase(ip, psib%ik))*src_%zff_linear(ip, ii)
654 do ii = 1, psib%nst_linear
656 do ip = 1, min(mesh%np, np)
657 psib%zff_linear(ip, ii) = this%phase(ip, psib%ik)*src_%zff_linear(ip, ii)
664 psib%zff_linear(ip, ii) = this%phase(ip, psib%ik)*src_%zff_linear(ip, ii)
698 psib%has_phase = .not. conjugate
711 class(
phase_t),
intent(in) :: this
712 complex(real64),
intent(inout) :: psi(:, :)
713 integer,
intent(in) :: np
714 integer,
intent(in) :: dim
715 integer,
intent(in) :: ik
716 logical,
intent(in) :: conjugate
722 assert(ik >= lbound(this%phase, dim=2))
723 assert(ik <= ubound(this%phase, dim=2))
732 psi(ip, idim) = conjg(this%phase(ip, ik))*psi(ip, idim)
741 psi(ip, idim) = this%phase(ip, ik)*psi(ip, idim)
762 class(
mesh_t),
intent(in) :: mesh
763 integer,
intent(in) :: np
764 real(real64),
contiguous,
intent(in) :: kvector(:)
765 logical,
intent(in) :: conjugate
766 complex(real64),
contiguous,
intent(out) :: phase(:)
769 complex(real64) :: factor
773 assert(
size(phase) >= np)
775 factor = merge(
m_zi, -
m_zi, conjugate)
779 phase(ip) =
exp(factor*dot_product(mesh%x(1:
size(kvector), ip), kvector))
791 class(
phase_t),
intent(in) :: this
795 integer :: ip, ii, sp
796 integer,
allocatable :: spin_label(:)
798 integer(int64) :: bsize
799 integer(int64),
dimension(2) :: np, gsizes, bsizes
806 assert(der%boundaries%spiral)
810 if (der%mesh%parallel_in_domains) sp = der%mesh%np + der%mesh%pv%np_ghost
813 select case (psib%status())
817 do ip = sp + 1, der%mesh%np_part
818 do ii = 1, psib%nst_linear, 2
819 if (this%spin(3,psib%linear_to_ist(ii), psib%ik)>0)
then
820 psib%zff_pack(ii+1, ip) = psib%zff_pack(ii+1, ip)*this%phase_spiral(ip-sp, 1)
822 psib%zff_pack(ii, ip) = psib%zff_pack(ii, ip)*this%phase_spiral(ip-sp, 2)
831 do ii = 1, psib%nst_linear, 2
832 if (this%spin(3,psib%linear_to_ist(ii), psib%ik)>0)
then
834 do ip = sp + 1, der%mesh%np_part
835 psib%zff_linear(ip, ii+1) = psib%zff_linear(ip, ii+1)*this%phase_spiral(ip-sp, 1)
840 do ip = sp + 1, der%mesh%np_part
841 psib%zff_linear(ip, ii) = psib%zff_linear(ip, ii)*this%phase_spiral(ip-sp, 2)
857 safe_allocate(spin_label(1:psib%nst_linear))
859 do ii = 1, psib%nst_linear, 2
860 if (this%spin(3, psib%linear_to_ist(ii), psib%ik) > 0) spin_label(ii)=1
878 np = (/psib%pack_size(1)/2_int64, int(der%mesh%np_part - sp, int64)/)
879 bsizes = (/psib%pack_size(1)/2, 2*bsize/)
888 safe_deallocate_a(spin_label)
898 logical pure function phase_is_allocated(this)
899 class(
phase_t),
intent(in) :: this
901 phase_is_allocated =
allocated(this%phase)
912 class(
phase_t),
intent(in) :: phase
913 type(grid_t),
intent(in) :: gr
914 type(distributed_t),
intent(in) :: kpt
915 type(wfs_elec_t),
intent(in) :: psib
916 type(wfs_elec_t),
intent(out) :: psib_with_phase
918 integer :: k_offset, n_boundary_points
922 call psib%copy_to(psib_with_phase)
923 if (phase%is_allocated())
then
924 call phase%apply_to(gr, gr%np, conjugate = .false., psib = psib_with_phase, src = psib, async=.
true.)
927 k_offset = psib%ik - kpt%start
928 n_boundary_points = int(gr%np_part - gr%np)
929 call boundaries_set(gr%der%boundaries, gr, psib_with_phase, phase_correction = phase%phase_corr(:, psib%ik), &
930 buff_phase_corr = phase%buff_phase_corr, offset=k_offset*n_boundary_points, async=.
true.)
932 call psib%copy_data_to(gr%np, psib_with_phase)
933 call boundaries_set(gr%der%boundaries, gr, psib_with_phase)
936 call psib_with_phase%do_pack(copy = .
true.)
double exp(double __x) __attribute__((__nothrow__
double sin(double __x) __attribute__((__nothrow__
double cos(double __x) __attribute__((__nothrow__
integer function, public accel_kernel_block_size(kernel)
subroutine, public accel_free_buffer(this, async)
subroutine, public accel_kernel_start_call(this, file_name, kernel_name, flags)
subroutine, public accel_finish()
subroutine, public accel_detach_buffer(this)
Clear a buffer handle without freeing device memory.
integer, parameter, public accel_mem_read_write
type(accel_kernel_t), target, save, public kernel_phase_spiral
pure logical function, public accel_is_enabled()
integer, parameter, public accel_mem_read_only
This module implements batches of mesh functions.
integer, parameter, public batch_not_packed
functions are stored in CPU memory, unpacked order
integer, parameter, public batch_device_packed
functions are stored in device memory in packed order
integer, parameter, public batch_packed
functions are stored in CPU memory, in transposed (packed) order
This module implements common operations on batches of mesh functions.
Module implementing boundary conditions in Octopus.
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
real(real64), parameter, public m_zero
complex(real64), parameter, public m_zi
real(real64), parameter, public m_one
This module implements the underlying real-space grid.
This module is intended to contain "only mathematical" functions and procedures.
This module defines the meshes, which are used in Octopus.
integer(int64) function, public mesh_periodic_point(mesh, space, ip)
This function returns the point inside the grid corresponding to a boundary point when PBCs are used....
real(real64) function, dimension(1:mesh%box%dim), public mesh_x_global(mesh, ipg)
Given a global point index, this function returns the coordinates of the point.
subroutine phase_phase_spiral(this, der, psib)
apply spiral phase
subroutine phase_unset_phase_corr(phase, mesh, psib, async)
unset the phase correction (if necessary)
subroutine, public phase_accel_rebuild(phase, mesh, kpt)
Rebuild phase accelerator buffers after an intrinsic copy.
subroutine phase_copy_and_set_phase(phase, gr, kpt, psib, psib_with_phase)
Copy a batch to another batch and apply the Bloch phase to it.
subroutine phase_init_phases(phase, gr, kpt, kpoints, d, space)
Initiliaze the phase arrays and copy to GPU the data.
subroutine phase_end(phase)
Releases the memory of the phase object.
subroutine phase_update_phases(phase, mesh, kpt, kpoints, d, space, uniform_vector_potential)
Update the phases.
subroutine, public phase_build_vector(mesh, np, kvector, conjugate, phase)
tabulate an explicitly supplied reciprocal-vector phase.
logical pure function phase_is_allocated(this)
subroutine phase_apply_batch(this, mesh, np, conjugate, psib, src, async)
apply (remove) the phase to the wave functions before (after) applying the Hamiltonian
subroutine phase_set_phase_corr(phase, mesh, psib, async)
set the phase correction (if necessary)
subroutine phase_apply_mf(this, psi, np, dim, ik, conjugate)
apply (or remove) the phase to a wave function psi
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
This module handles spin dimensions of the states and the k-point distribution.
type(type_t), parameter, public type_cmplx
type(type_t), parameter, public type_integer
type(type_t), parameter, public type_float
class representing derivatives
Distribution of N instances over mpi_grpsize processes, for the local rank mpi_grprank....
Description of the grid, containing information on derivatives, stencil, and symmetries.
Describes mesh distribution to nodes.
A container for the phase.
class for organizing spins and k-points
batches of electronic states