41 use,
intrinsic :: iso_fortran_env
92 integer :: nkpnts_start, nkpnts_end
94 integer :: nk_start, nk_end
97 integer :: nstepsthetak, nstepsphik
98 real(real64) :: thetak_rng(1:2)
99 real(real64) :: phik_rng(1:2)
100 integer :: nstepsomegak
101 integer :: nstepsomegak_start, nstepsomegak_end
102 real(real64) :: ktransf(1:3,1:3)
104 real(real64),
allocatable :: klinear(:,:)
109 real(real64),
allocatable :: kcoords_cub(:,:,:)
110 real(real64),
allocatable :: kcoords_sph(:,:,:)
114 integer,
public :: surf_shape
116 integer :: nsrfcpnts_start, nsrfcpnts_end
117 real(real64),
allocatable :: srfcnrml(:,:)
118 real(real64),
allocatable :: rcoords(:,:)
119 integer,
allocatable :: srfcpnt(:)
120 integer,
allocatable :: rankmin(:)
122 complex(real64),
allocatable :: ylm_r(:,:,:)
123 complex(real64),
allocatable :: ylm_k(:,:,:)
124 real(real64),
allocatable :: j_l(:,:)
125 real(real64) :: radius
126 integer,
allocatable :: face_idx_range(:,:)
130 complex(real64),
allocatable :: bvk_phase(:,:)
131 complex(real64),
allocatable :: expkr(:,:,:,:)
132 complex(real64),
allocatable :: expkr_perp(:,:)
134 real(real64),
allocatable :: LLr(:,:)
135 integer,
allocatable :: NN(:,:)
136 integer,
allocatable :: Lkpuvz_inv(:,:,:)
146 complex(real64),
allocatable :: wf(:,:,:,:,:)
147 complex(real64),
allocatable :: gwf(:,:,:,:,:,:)
148 real(real64),
allocatable :: veca(:,:)
149 complex(real64),
allocatable :: conjgphase_prev(:,:)
150 complex(real64),
allocatable :: spctramp_cub(:,:,:,:)
151 complex(real64),
allocatable :: spctramp_sph(:,:,:,:,:)
153 integer,
public :: ll(3)
156 type(mesh_interpolation_t) :: interp
158 logical :: parallel_in_momentum
159 logical :: arpes_grid
160 logical :: surf_interp
161 logical :: use_symmetry
162 logical :: runtime_output
163 logical :: anisotrpy_correction
165 integer :: par_strategy
170 type(accel_mem_t) :: pt_buff
171 type(accel_mem_t) :: interp_buff
172 type(accel_mem_t) :: spacing_buff
173 type(accel_mem_t) :: coords_buff
177 integer,
parameter :: &
182 integer,
parameter :: &
191 subroutine pes_flux_init(this, namespace, space, mesh, st, ext_partners, kpoints, abb, save_iter, max_iter)
200 integer,
intent(in) :: save_iter
201 integer,
intent(in) :: max_iter
204 real(real64) :: border(space%dim)
205 real(real64) :: offset(space%dim)
206 integer :: stst, stend, kptst, kptend, sdim, mdim, pdim
211 integer :: nstepsphir, nstepsthetar
213 integer :: default_shape
214 real(real64) :: fc_ptdens
216 integer :: par_strategy
217 logical :: use_symmetry
225 kptst = st%d%kpt%start
226 kptend = st%d%kpt%end
229 pdim = space%periodic_dim
231 this%surf_interp = .false.
235 if(
associated(lasers))
then
236 do il = 1, lasers%no_lasers
238 message(1) =
't-surff only works in velocity gauge.'
244 message(1) =
'Info: Calculating PES using t-surff technique.'
269 if (space%is_periodic())
then
271 else if (mdim <= 2)
then
272 default_shape = pes_cubic
274 select type (box => mesh%box)
276 default_shape = pes_cubic
280 call parse_variable(namespace,
'PES_Flux_Shape', default_shape, this%surf_shape)
285 message(1) =
'Spherical grid works only in 3d.'
298 if (this%surf_shape == pes_cubic)
then
299 call parse_variable(namespace,
'PES_Flux_AnisotropyCorrection', .false., this%anisotrpy_correction)
302 this%anisotrpy_correction = .false.
317 if (
parse_block(namespace,
'PES_Flux_Offset', blk) == 0)
then
339 if (this%surf_shape == pes_cubic .or. this%surf_shape ==
pes_plane)
then
359 if (
parse_block(namespace,
'PES_Flux_Lsize', blk) == 0)
then
364 border(1:mdim) = int(border(1:mdim) / mesh%spacing(1:mdim)) * mesh%spacing(1:mdim)
368 border(mdim) = mesh%box%bounding_box_l(mdim) *
m_half
369 if (space%is_periodic())
then
371 border(1:pdim)= mesh%box%bounding_box_l(1:pdim) *
m_two
372 call parse_variable(namespace,
'PES_Flux_Lsize', border(mdim), border(mdim))
374 border(mdim) =
floor(border(mdim) / mesh%spacing(mdim)) * mesh%spacing(mdim)
376 call parse_variable(namespace,
'PES_Flux_Lsize', border(mdim), border(mdim))
377 border(1:mdim - 1) = border(mdim)
378 border(1:mdim) =
floor(border(1:mdim) / mesh%spacing(1:mdim)) * mesh%spacing(1:mdim)
381 select type (box => mesh%box)
385 border(1:mdim) = box%half_length(1:mdim) *
m_half
387 call messages_write(
'PES_Flux_Lsize not specified. No default values available for this box shape.')
389 call messages_write(
'Specify the location of the parallelepiped with block PES_Flux_Lsize.')
392 call messages_write(
'PES_Flux_Lsize not specified. Using default values.')
406 this%surf_interp = .
true.
413 this%surf_interp = .
true.
426 select type (box => mesh%box)
428 this%radius = box%radius
430 this%radius = minval(box%half_length(1:mdim))
432 message(1) =
'PES_Flux_Radius not specified. No default values available for this box shape.'
433 message(2) =
'Specify the radius of the sphere with variable PES_Flux_Radius.'
436 message(1) =
'PES_Flux_Radius not specified. Using default values.'
448 call parse_variable(namespace,
'PES_Flux_StepsThetaR', 2 * this%lmax + 1, nstepsthetar)
459 call parse_variable(namespace,
'PES_Flux_StepsPhiR', 2 * this%lmax + 1, nstepsphir)
471 if (this%surf_shape == pes_cubic .or. this%surf_shape ==
pes_plane)
then
506 this%par_strategy = option__pes_flux_parallelization__pf_none
507 if (mesh%parallel_in_domains)
then
510 this%par_strategy = option__pes_flux_parallelization__pf_time &
511 + option__pes_flux_parallelization__pf_surface
513 this%par_strategy = option__pes_flux_parallelization__pf_surface
514 if (space%dim == 1) this%par_strategy = option__pes_flux_parallelization__pf_time
516 par_strategy = this%par_strategy
517 call parse_variable(namespace,
'PES_Flux_Parallelization', par_strategy, this%par_strategy)
525 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_surface) /= 0 .and. &
526 bitand(this%par_strategy, option__pes_flux_parallelization__pf_momentum) /= 0)
then
527 call messages_input_error(namespace,
'PES_Flux_Parallelization',
"Cannot combine pf_surface and pf_momentum")
530 write(
message(1),
'(a)')
'Input: [PES_Flux_Parallelization = '
531 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_none) /= 0)
then
534 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_time) /= 0)
then
537 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_momentum) /= 0)
then
540 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_surface) /= 0)
then
550 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_surface) /= 0)
then
552 call pes_flux_distribute(1, this%nsrfcpnts, this%nsrfcpnts_start, this%nsrfcpnts_end, mesh%mpi_grp%comm)
565 this%nsrfcpnts_start = 1
566 this%nsrfcpnts_end = this%nsrfcpnts
593 use_symmetry = .false.
594 if ((this%surf_shape == pes_cubic .or. this%surf_shape ==
pes_plane) &
596 if (this%surf_shape ==
pes_spherical .and. this%kgrid == pes_polar) use_symmetry = .
true.
597 call parse_variable(namespace,
'PES_Flux_UseSymmetries', use_symmetry, this%use_symmetry)
604 safe_allocate(this%ylm_r(this%nsrfcpnts_start:this%nsrfcpnts_end, 0:this%lmax, -this%lmax:this%lmax))
607 if (this%nsrfcpnts_start > 0)
then
610 do isp = this%nsrfcpnts_start, this%nsrfcpnts_end
611 call ylmr_cmplx(this%rcoords(1:3, isp), ll, mm, this%ylm_r(isp, ll, mm))
612 this%ylm_r(isp, ll, mm) = conjg(this%ylm_r(isp, ll, mm))
632 call parse_variable(namespace,
'PES_Flux_RuntimeOutput', .false., this%runtime_output)
640 this%max_iter = max_iter
641 this%save_iter = save_iter
645 if (mesh%parallel_in_domains .and.
bitand(this%par_strategy, option__pes_flux_parallelization__pf_time) /= 0)
then
646 this%tdsteps = mesh%mpi_grp%size
653 safe_allocate(this%wf(0:this%nsrfcpnts, stst:stend, 1:sdim, kptst:kptend, 1:this%tdsteps))
656 safe_allocate(this%gwf(0:this%nsrfcpnts, stst:stend, 1:sdim, kptst:kptend, 1:this%tdsteps, 1:mdim))
659 safe_allocate(this%veca(1:mdim, 1:this%tdsteps))
663 safe_allocate(this%spctramp_sph(1:this%nstepsomegak, stst:stend, 1:sdim, kptst:kptend, 1:this%nk))
664 this%spctramp_sph =
m_z0
666 safe_allocate(this%conjgphase_prev(1:this%nstepsomegak, 1:this%nk))
669 safe_allocate(this%spctramp_cub(stst:stend, 1:sdim, kptst:kptend, 1:this%nkpnts))
670 this%spctramp_cub =
m_z0
672 safe_allocate(this%conjgphase_prev(1:this%nkpnts, kptst:kptend))
676 this%conjgphase_prev =
m_z1
696 safe_deallocate_a(this%kcoords_sph)
697 safe_deallocate_a(this%ylm_k)
698 safe_deallocate_a(this%j_l)
699 safe_deallocate_a(this%ylm_r)
700 safe_deallocate_a(this%conjgphase_prev)
701 safe_deallocate_a(this%spctramp_sph)
703 safe_deallocate_a(this%kcoords_cub)
704 safe_deallocate_a(this%conjgphase_prev)
705 safe_deallocate_a(this%spctramp_cub)
707 if (.not. this%surf_interp)
then
708 safe_deallocate_a(this%srfcpnt)
710 safe_deallocate_a(this%rankmin)
712 safe_deallocate_a(this%face_idx_range)
713 safe_deallocate_a(this%LLr)
714 safe_deallocate_a(this%NN)
716 safe_deallocate_a(this%expkr)
717 safe_deallocate_a(this%expkr_perp)
718 safe_deallocate_a(this%bvk_phase)
720 safe_deallocate_a(this%Lkpuvz_inv)
724 safe_deallocate_a(this%klinear)
726 safe_deallocate_a(this%srfcnrml)
727 safe_deallocate_a(this%rcoords)
729 safe_deallocate_a(this%wf)
730 safe_deallocate_a(this%gwf)
731 safe_deallocate_a(this%veca)
753 class(
space_t),
intent(in) :: space
756 type(mpi_comm),
intent(in) :: comm
757 logical,
optional,
intent(in) :: post
759 integer :: mdim, pdim
760 integer :: kptst, kptend
762 integer :: ll, mm, idim, idir, ispin, nspin
763 integer :: ikk, ith, iph, iomk,ie, ik1, ik2, ik3, kgrid_block_dim
764 real(real64) :: kmax(space%dim), kmin(space%dim), kact, thetak, phik
767 real(real64) :: emin, emax, de , kvec(1:3), xx(3)
768 integer :: nkp_out, nkmin, nkmax
771 real(real64),
allocatable :: gpoints(:,:), gpoints_reduced(:,:)
772 real(real64) :: dk(1:3), kpoint(1:3), dthetak, dphik
773 logical :: use_enegy_grid, arpes_grid
777 kptst = st%d%kpt%start
778 kptend = st%d%kpt%end
780 pdim = space%periodic_dim
802 select case (this%surf_shape)
809 if (mdim == 1) kgrid = pes_polar
816 call parse_variable(namespace,
'PES_Flux_Momenutum_Grid', kgrid, this%kgrid)
829 if (space%is_periodic())
then
837 if (this%surf_shape == pes_cubic)
then
838 if (space%is_periodic())
then
859 use_enegy_grid = .false.
861 if (
parse_block(namespace,
'PES_Flux_EnergyGrid', blk) == 0)
then
868 use_enegy_grid = .
true.
890 call parse_variable(namespace,
'PES_Flux_ARPES_grid', .false., this%arpes_grid)
891 if (.not. use_enegy_grid .or. this%arpes_grid)
then
902 if (
parse_block(namespace,
'PES_Flux_Kmax', blk) == 0)
then
907 kgrid_block_dim = mdim
909 message(1) =
'Wrong block format for PES_Flux_Kmax and non-cartesian grid'
926 if (
parse_block(namespace,
'PES_Flux_Kmin', blk) == 0)
then
931 kgrid_block_dim = mdim
933 message(1) =
'Wrong block format for PES_Flux_Kmin and non-cartesian grid'
949 call parse_variable(namespace,
'PES_Flux_DeltaK', 0.02_real64, this%dk)
954 do idim = 1, kgrid_block_dim
955 if (kgrid_block_dim == 1)
then
974 if (this%kgrid == pes_polar)
then
997 this%nstepsthetak = 45
999 if (
parse_block(namespace,
'PES_Flux_ThetaK', blk) == 0)
then
1005 if (this%thetak_rng(idim) <
m_zero .or. this%thetak_rng(idim) >
m_pi)
then
1019 call parse_variable(namespace,
'PES_Flux_StepsThetaK', 45, this%nstepsthetak)
1044 this%nstepsphik = 90
1046 if (mdim == 1) this%phik_rng(1:2) = (/
m_pi,
m_zero/)
1047 if (
parse_block(namespace,
'PES_Flux_PhiK', blk) == 0)
then
1053 if (this%phik_rng(idim) <
m_zero .or. this%phik_rng(idim) >
m_two *
m_pi)
then
1068 call parse_variable(namespace,
'PES_Flux_StepsPhiK', 90, this%nstepsphik)
1070 if (this%nstepsphik == 0) this%nstepsphik = 1
1075 if (mdim == 3) dthetak = abs(this%thetak_rng(2) - this%thetak_rng(1)) / (this%nstepsthetak)
1076 dphik = abs(this%phik_rng(2) - this%phik_rng(1)) / (this%nstepsphik)
1081 this%nstepsthetak = 0
1083 this%nstepsomegak = this%nstepsphik
1086 this%nstepsthetak = 0
1087 this%nstepsomegak = this%nstepsphik
1090 if (this%nstepsthetak <= 1)
then
1092 this%nstepsthetak = 1
1096 do ith = 0, this%nstepsthetak
1097 thetak = ith * dthetak + this%thetak_rng(1)
1098 do iph = 0, this%nstepsphik - 1
1099 phik = iph * dphik + this%phik_rng(1)
1104 this%nstepsomegak = iomk
1111 write(
message(1),
'(a)')
"Polar momentum grid:"
1114 write(
message(1),
'(a,f12.6,a,f12.6,a, i6)') &
1115 " Theta = (", this%thetak_rng(1),
",",this%thetak_rng(2), &
1116 "); n = ", this%nstepsthetak
1119 write(
message(1),
'(a,f12.6,a,f12.6,a, i6)') &
1120 " Phi = (", this%phik_rng(1),
",",this%phik_rng(2), &
1121 "); n = ", this%nstepsphik
1126 if (use_enegy_grid)
then
1127 this%nk = nint(abs(emax - emin) / de)
1129 this%nk = nint(abs(kmax(1) - kmin(1)) / this%dk)
1131 this%nkpnts = this%nstepsomegak * this%nk
1133 this%ll(1) = this%nk
1134 this%ll(2) = this%nstepsphik
1135 this%ll(3) = this%nstepsthetak
1136 this%ll(mdim+1:3) = 1
1138 safe_allocate(this%klinear(1:this%nk, 1))
1144 dk(1:mdim) =
m_one/kpoints%nik_axis(1:mdim)
1146 this%arpes_grid = .false.
1147 if (space%is_periodic())
then
1158 arpes_grid = kpoints%have_zero_weight_path()
1159 call parse_variable(namespace,
'PES_Flux_ARPES_grid', arpes_grid, this%arpes_grid)
1168 if (kpoints%have_zero_weight_path())
then
1170 if (this%arpes_grid)
then
1171 nkmax =
floor(emax / de)
1172 nkmin =
floor(emin / de)
1175 nkmax =
floor(kmax(mdim) / this%dk)
1176 nkmin =
floor(kmin(mdim) / this%dk)
1180 this%ll(mdim) = abs(nkmax - nkmin) + 1
1182 this%nk = this%ll(mdim)
1187 if (.not. this%arpes_grid)
then
1188 this%ll(1:mdim) =
floor(abs(kmax(1:mdim) - kmin(1:mdim))/this%dk) + 1
1189 this%nk = maxval(this%ll(1:mdim))
1193 nkmax =
floor(emax / de)
1194 nkmin =
floor(emin / de)
1195 this%nk = abs(nkmax - nkmin) + 1
1197 this%ll(1:pdim) =
floor(abs(kmax(1:pdim) - kmin(1:pdim))/this%dk) + 1
1198 this%ll(mdim) = this%nk
1202 safe_allocate(this%klinear(1:maxval(this%ll(1:mdim)), 1:mdim))
1208 this%nkpnts = product(this%ll(1:mdim))
1217 this%parallel_in_momentum = .false.
1220 select case (this%kgrid)
1224 if (use_enegy_grid)
then
1226 this%klinear(ie, 1) =
sqrt(
m_two * (ie * de + emin))
1230 this%klinear(ikk, 1) = ikk * this%dk + kmin(1)
1244 if ((this%nk_end - this%nk_start + 1) < this%nk) this%parallel_in_momentum = .
true.
1245 call pes_flux_distribute(1, this%nstepsomegak, this%nstepsomegak_start, this%nstepsomegak_end, comm)
1257 safe_allocate(this%j_l(this%nk_start:this%nk_end, 0:this%lmax))
1260 safe_allocate(this%kcoords_sph(1:3, this%nk_start:this%nk_end, 1:this%nstepsomegak))
1261 this%kcoords_sph =
m_zero
1263 safe_allocate(this%ylm_k(this%nstepsomegak_start:this%nstepsomegak_end, -this%lmax:this%lmax, 0:this%lmax))
1268 do ith = 0, this%nstepsthetak
1269 thetak = ith * dthetak + this%thetak_rng(1)
1270 do iph = 0, this%nstepsphik - 1
1271 phik = iph * dphik + this%phik_rng(1)
1273 if (iomk >= this%nstepsomegak_start .and. iomk <= this%nstepsomegak_end)
then
1274 xx(1) =
cos(phik) *
sin(thetak)
1275 xx(2) =
sin(phik) *
sin(thetak)
1278 do ll = 0, this%lmax
1280 call ylmr_cmplx(xx, ll, mm, this%ylm_k(iomk, mm, ll))
1284 if (this%nk_start > 0)
then
1285 this%kcoords_sph(1, this%nk_start:this%nk_end, iomk) =
cos(phik) *
sin(thetak)
1286 this%kcoords_sph(2, this%nk_start:this%nk_end, iomk) =
sin(phik) *
sin(thetak)
1287 this%kcoords_sph(3, this%nk_start:this%nk_end, iomk) =
cos(thetak)
1293 if (this%nk_start > 0)
then
1295 do ikk = this%nk_start, this%nk_end
1296 kact = this%klinear(ikk,1)
1297 do ll = 0, this%lmax
1301 this%kcoords_sph(:, ikk, :) = kact * this%kcoords_sph(:, ikk, :)
1309 this%nkpnts_start = 1
1310 this%nkpnts_end = this%nkpnts
1313 safe_allocate(this%kcoords_cub(1:mdim, this%nkpnts_start:this%nkpnts_end, 1))
1315 this%kcoords_cub =
m_zero
1320 do ikk = -this%nk, this%nk
1323 kact = sign(1,ikk) * this%klinear(abs(ikk), 1)
1324 this%kcoords_cub(1, ikp, 1) = kact
1332 do ith = 0, this%nstepsthetak
1333 if (mdim == 3) thetak = ith * dthetak + this%thetak_rng(1)
1334 do iph = 0, this%nstepsphik - 1
1336 phik = iph * dphik + this%phik_rng(1)
1337 kact = this%klinear(ikk,1)
1338 this%kcoords_cub(1, ikp,1) = kact *
cos(phik) *
sin(thetak)
1339 this%kcoords_cub(2, ikp,1) = kact *
sin(phik) *
sin(thetak)
1340 if (mdim == 3) this%kcoords_cub(3, ikp,1) = kact *
cos(thetak)
1351 this%nkpnts_start = 1
1352 this%nkpnts_end = this%nkpnts
1354 if (kpoints%have_zero_weight_path())
then
1359 safe_allocate(this%kcoords_cub(1:mdim, this%nkpnts_start:this%nkpnts_end, kptst:kptend))
1360 this%kcoords_cub =
m_zero
1369 do ikpt = (kptst-1)+ispin, kptend, nspin
1371 do ikk = nkmin, nkmax
1372 kvec(1:mdim) = - kpoints%get_point(st%d%get_kpoint_index(ikpt))
1380 safe_allocate(this%kcoords_cub(1:mdim, this%nkpnts_start:this%nkpnts_end, 1))
1382 safe_allocate(this%Lkpuvz_inv(1:this%ll(1), 1:this%ll(2), 1:this%ll(3)))
1385 do ikk = 1, this%ll(idir)
1386 this%klinear(ikk, idir) = ikk * this%dk + kmin(idir)
1391 if (.not. this%arpes_grid)
then
1398 do ik3 = 1, this%ll(3)
1399 if (mdim>2) kvec(3) = this%klinear(ik3, 3)
1400 do ik2 = 1, this%ll(2)
1401 if (mdim>1) kvec(2) = this%klinear(ik2, 2)
1402 do ik1 = 1, this%ll(1)
1404 kvec(1) = this%klinear(ik1, 1)
1405 this%kcoords_cub(1:mdim, ikp, ikpt) = kvec(1:mdim)
1406 this%Lkpuvz_inv(ik1, ik2, ik3) = ikp
1418 do ikk = nkmin, nkmax
1424 do ik1 = 1, this%ll(1)
1425 kvec(1) = this%klinear(ik1,1)
1426 kvec(1:pdim) = matmul(kpoints%latt%klattice_primitive(1:pdim, 1:pdim), kvec(1:pdim))
1432 do ik2 = 1, this%ll(2)
1433 do ik1 = 1, this%ll(1)
1434 kvec(1:2) = (/this%klinear(ik1,1), this%klinear(ik2,2)/)
1435 kvec(1:pdim) = matmul(kpoints%latt%klattice_primitive(1:pdim, 1:pdim), kvec(1:pdim))
1438 this%Lkpuvz_inv(ik1, ik2, ikk - nkmin + 1) = ikp
1491 if (this%arpes_grid)
then
1500 safe_deallocate_a(gpoints)
1501 safe_deallocate_a(gpoints_reduced)
1522 this%ktransf(:,:) =
m_zero
1524 this%ktransf(idim,idim) =
m_one
1527 if (
parse_block(namespace,
'PES_Flux_GridTransformMatrix', blk) == 0)
then
1535 write(
message(1),
'(a)')
'Momentum grid transformation matrix :'
1536 do idir = 1, space%dim
1537 write(
message(1 + idir),
'(9f12.6)') ( this%ktransf(idim, idir), idim = 1, mdim)
1546 do ith = 0, this%nstepsthetak
1547 do iph = 0, this%nstepsphik - 1
1549 do ikk = this%nk_start, this%nk_end
1550 kvec(1:mdim) = this%kcoords_sph(1:mdim, ikk, iomk)
1551 this%kcoords_sph(1:mdim, ikk, iomk) = matmul(this%ktransf(1:mdim, 1:mdim), kvec(1:mdim))
1553 if (ith == 0 .or. ith == this%nstepsthetak)
exit
1559 do ikpt = kptst, kptend + 1
1560 if (ikpt == kptend + 1)
then
1561 kpoint(1:space%dim) =
m_zero
1563 kpoint(1:space%dim) = kpoints%get_point(st%d%get_kpoint_index(ikpt))
1566 do ikp = 1, this%nkpnts
1568 kvec(1:mdim) = this%kcoords_cub(1:mdim, ikp, ikpt) - kpoint(1:mdim)
1569 this%kcoords_cub(1:mdim, ikp, ikpt) = matmul(this%ktransf(1:mdim, 1:mdim), kvec(1:mdim)) &
1591 real(real64) :: kpar(1:pdim), val
1596 if (ikk /= 0) sign= ikk / abs(ikk)
1598 kpar(1:pdim) = kvec(1:pdim)
1599 val = abs(ikk) * de *
m_two - sum(kpar(1:pdim)**2)
1601 kvec(mdim) = sign *
sqrt(val)
1604 kvec(mdim) =
sqrt(val)
1605 nkp_out = nkp_out + 1
1608 this%kcoords_cub(1:mdim, ikp, ikpt) = kvec(1:mdim)
1618 subroutine pes_flux_calc(this, space, mesh, st, der, ext_partners, kpoints, iter, dt, stopping)
1620 class(
space_t),
intent(in) :: space
1621 type(
mesh_t),
intent(in) :: mesh
1626 integer,
intent(in) :: iter
1627 real(real64),
intent(in) :: dt
1628 logical,
intent(in) :: stopping
1630 integer :: stst, stend, kptst, kptend, sdim, mdim
1631 integer :: ist, ik, isdim, imdim
1633 integer :: il, ip_local
1634 integer :: ib, minst, maxst, nst_linear, ist_linear
1635 integer :: k_offset, n_boundary_points
1636 logical :: contains_isp
1638 complex(real64),
allocatable :: interp_values(:)
1639 complex(real64),
allocatable :: interp_values_accel(:, :)
1640 complex(real64),
allocatable :: wf_tmp_accel(:, :), gwf_tmp_accel(:, :, :)
1641 complex(real64),
allocatable :: gpsi(:, :), psi(:)
1650 if (iter == 0)
return
1656 kptst = st%d%kpt%start
1657 kptend = st%d%kpt%end
1661 safe_allocate(psi(1:mesh%np_part))
1662 safe_allocate(gpsi(1:mesh%np_part, 1:mdim))
1665 safe_allocate(interp_values(1:this%nsrfcpnts))
1668 this%itstep = this%itstep + 1
1672 if(
associated(lasers))
then
1673 do il = 1, lasers%no_lasers
1674 call laser_field(lasers%lasers(il), this%veca(1:mdim, this%itstep), iter*dt)
1677 this%veca(:, this%itstep) = - this%veca(:, this%itstep)
1682 call phase%init(mesh, st%d%kpt, kpoints, st%d, space)
1684 do ik = kptst, kptend
1685 do ib = st%group%block_start, st%group%block_end
1691 call st%group%psib(ib, ik)%copy_to(psib)
1693 call phase%apply_to(mesh, mesh%np_part, conjugate=.false., psib=psib, src=st%group%psib(ib, ik), async=.
true.)
1695 k_offset = psib%ik - kptst
1696 n_boundary_points = int(mesh%np_part - mesh%np)
1697 call boundaries_set(der%boundaries, mesh, psib, phase_correction=phase%phase_corr(:, psib%ik), &
1698 buff_phase_corr=phase%buff_phase_corr, offset=k_offset*n_boundary_points, async=.
true.)
1701 psib => st%group%psib(ib, ik)
1709 nst_linear = psib%nst_linear
1711 if(this%surf_interp)
then
1713 safe_allocate(interp_values_accel(1:this%nsrfcpnts, 1:nst_linear))
1716 this%rcoords(1:mdim, 1:this%nsrfcpnts), this%coords_buff, &
1717 interp_values_accel(1:this%nsrfcpnts, 1:nst_linear), this%interp_buff, this%spacing_buff, this%pt_buff)
1719 do ist = minst, maxst
1721 ist_linear = psib%ist_idim_to_linear((/ist - minst + 1, isdim/))
1722 this%wf(1:this%nsrfcpnts, ist, isdim, ik, this%itstep) = &
1723 st%occ(ist, ik) * interp_values_accel(1:this%nsrfcpnts, ist_linear)
1729 gpsib(imdim), this%rcoords(1:mdim, 1:this%nsrfcpnts), this%coords_buff, &
1730 interp_values_accel(1:this%nsrfcpnts, 1:nst_linear), this%interp_buff, this%spacing_buff, this%pt_buff)
1731 do ist = minst, maxst
1733 ist_linear = psib%ist_idim_to_linear((/ist - minst + 1, isdim/))
1734 this%gwf(1:this%nsrfcpnts, ist, isdim, ik, this%itstep, imdim) = &
1735 st%occ(ist, ik) * interp_values_accel(1:this%nsrfcpnts, ist_linear)
1740 safe_deallocate_a(interp_values_accel)
1744 call profiling_in(tostring(pes_flux_calc_cubic_reduction))
1746 safe_allocate(wf_tmp_accel(1:mesh%np_part, 1:nst_linear))
1747 safe_allocate(gwf_tmp_accel(1:mdim, 1:mesh%np_part, 1:nst_linear))
1749 call accel_read_buffer(psib%ff_device, mesh%np_part, nst_linear, wf_tmp_accel(:, :))
1751 call accel_read_buffer(gpsib(imdim)%ff_device, mesh%np_part, nst_linear, gwf_tmp_accel(imdim, :, :))
1754 do ist = minst, maxst
1755 contains_isp = .
true.
1756 do isp = 1, this%nsrfcpnts
1757 if (mesh%parallel_in_domains)
then
1758 contains_isp = mesh%mpi_grp%rank == this%rankmin(isp)
1761 if (.not. contains_isp) cycle
1763 ip_local = this%srfcpnt(isp)
1765 ist_linear = psib%ist_idim_to_linear((/ist - minst + 1, isdim/))
1766 this%wf(isp, ist, isdim, ik, this%itstep) = &
1767 st%occ(ist, ik) * wf_tmp_accel(ip_local, ist_linear)
1768 this%gwf(isp, ist, isdim, ik, this%itstep, 1:mdim) = &
1769 st%occ(ist, ik) * gwf_tmp_accel(1:mdim, ip_local, ist_linear)
1773 if (mesh%parallel_in_domains)
then
1775 call mesh%allreduce(this%wf(1:this%nsrfcpnts, ist, isdim, ik, this%itstep))
1777 call mesh%allreduce(this%gwf(1:this%nsrfcpnts, ist, isdim, ik, this%itstep, imdim))
1783 safe_deallocate_a(wf_tmp_accel)
1784 safe_deallocate_a(gwf_tmp_accel)
1792 do ist = minst, maxst
1798 call batch_get_state(gpsib(imdim), (/ist, isdim/), mesh%np_part, gpsi(:, imdim))
1801 if (this%surf_interp)
then
1804 this%rcoords(1:mdim, 1:this%nsrfcpnts), interp_values(1:this%nsrfcpnts))
1805 this%wf(1:this%nsrfcpnts, ist, isdim, ik, this%itstep) = st%occ(ist, ik) * interp_values(1:this%nsrfcpnts)
1808 this%rcoords(1:mdim, 1:this%nsrfcpnts), interp_values(1:this%nsrfcpnts))
1809 this%gwf(1:this%nsrfcpnts, ist, isdim, ik, this%itstep, imdim) = &
1810 st%occ(ist, ik) * interp_values(1:this%nsrfcpnts)
1815 contains_isp = .
true.
1816 do isp = 1, this%nsrfcpnts
1817 if (mesh%parallel_in_domains)
then
1818 contains_isp = mesh%mpi_grp%rank == this%rankmin(isp)
1821 if (.not. contains_isp) cycle
1823 ip_local = this%srfcpnt(isp)
1824 this%wf(isp, ist, isdim, ik, this%itstep) = st%occ(ist, ik) * psi(ip_local)
1825 this%gwf(isp, ist, isdim, ik, this%itstep, 1:mdim) = &
1826 st%occ(ist, ik) * gpsi(ip_local, 1:mdim)
1829 if (mesh%parallel_in_domains)
then
1830 call mesh%allreduce(this%wf(1:this%nsrfcpnts, ist, isdim, ik, this%itstep))
1832 call mesh%allreduce(this%gwf(1:this%nsrfcpnts, ist, isdim, ik, this%itstep, imdim))
1843 call gpsib(imdim)%end(copy = .false.)
1847 call psib%end(copy = .false.)
1848 safe_deallocate_p(psib)
1853 if (this%surf_interp)
then
1854 safe_deallocate_a(interp_values)
1857 safe_deallocate_a(psi)
1858 safe_deallocate_a(gpsi)
1862 if (this%itstep == this%tdsteps .or. mod(iter, this%save_iter) == 0 .or. iter == this%max_iter .or. stopping)
then
1863 if (this%surf_shape == pes_cubic .or. this%surf_shape ==
pes_plane)
then
1884 class(
space_t),
intent(in) :: space
1885 type(
mesh_t),
intent(in) :: mesh
1889 integer :: kptst, kptend, mdim
1890 integer :: ik, j1, j2, jvec(1:2)
1891 integer :: isp, ikp, ikp_start, ikp_end
1894 integer :: idir, pdim, nfaces, ifc, n_dir
1895 complex(real64) :: tmp
1896 real(real64) :: kpoint(1:3), vec(1:3), lvec(1:3)
1900 if (kpoints%have_zero_weight_path())
then
1901 kptst = st%d%kpt%start
1902 kptend = st%d%kpt%end
1909 pdim = space%periodic_dim
1911 ikp_start = this%nkpnts_start
1912 ikp_end = this%nkpnts_end
1918 this%srfcnrml(:, 1:this%nsrfcpnts) = this%srfcnrml(:, 1:this%nsrfcpnts) * mesh%coord_system%surface_element(3)
1921 if (.not. this%use_symmetry .or. kpoints%have_zero_weight_path())
then
1923 safe_allocate(this%expkr(1:this%nsrfcpnts,ikp_start:ikp_end,kptst:kptend,1))
1925 do ik = kptst, kptend
1926 do ikp = ikp_start, ikp_end
1927 do isp = 1, this%nsrfcpnts
1928 this%expkr(isp,ikp,ik,1) =
exp(-
m_zi * sum(this%rcoords(1:mdim,isp) &
1929 * this%kcoords_cub(1:mdim, ikp, ik))) &
1941 if (this%surf_shape ==
pes_plane) nfaces = 1
1944 safe_allocate(this%expkr(1:this%nsrfcpnts,maxval(this%ll(1:mdim)),kptst:kptend,1:mdim))
1945 this%expkr(:,:,:,:) =
m_z1
1947 do ik = kptst, kptend
1949 do ikp = 1, this%ll(idir)
1950 do isp = 1, this%nsrfcpnts
1951 this%expkr(isp,ikp,ik,idir) =
exp(-
m_zi * this%rcoords(idir,isp) &
1952 * this%klinear(ikp, idir)) &
1960 safe_allocate(this%expkr_perp(1:maxval(this%ll(1:mdim)), 1:nfaces))
1961 this%expkr_perp(:,:) =
m_z1
1964 if (this%face_idx_range(ifc, 1) < 0) cycle
1965 isp = this%face_idx_range(ifc, 1)
1967 if (abs(this%srfcnrml(idir, isp)) >=
m_epsilon) n_dir = idir
1970 do ikp = 1, this%ll(n_dir)
1971 this%expkr_perp(ikp, ifc) =
exp(-
m_zi * this%rcoords(n_dir,isp) &
1972 * this%klinear(ikp, n_dir)) &
1982 if (space%is_periodic())
then
1984 safe_allocate(this%bvk_phase(ikp_start:ikp_end,st%d%kpt%start:st%d%kpt%end))
1986 this%bvk_phase(:,:) =
m_z0
1989 do ik = st%d%kpt%start, st%d%kpt%end
1990 kpoint(1:mdim) = kpoints%get_point(st%d%get_kpoint_index(ik))
1991 if (kpoints%have_zero_weight_path())
then
1996 do ikp = ikp_start, ikp_end
1997 vec(1:pdim) = this%kcoords_cub(1:pdim, ikp, ik_map) + kpoint(1:pdim)
1998 do j1 = 0, kpoints%nik_axis(1) - 1
1999 do j2 = 0, kpoints%nik_axis(2) - 1
2000 jvec(1:2)=(/j1, j2/)
2001 lvec(1:pdim) = matmul(kpoints%latt%rlattice(1:pdim, 1:2), jvec(1:2))
2002 tmp = sum(lvec(1:pdim) * vec(1:pdim))
2003 this%bvk_phase(ikp, ik) = this%bvk_phase(ikp,ik) &
2011 this%bvk_phase(:,:) = this%bvk_phase(:,:) *
m_one / product(kpoints%nik_axis(1:pdim))
2033 pure function get_ikp(this, ikpu, ikpv, ikpz, n_dir)
result(ikp)
2035 integer,
intent(in) :: ikpu
2036 integer,
intent(in) :: ikpv
2037 integer,
intent(in) :: ikpz
2038 integer,
intent(in) :: n_dir
2043 ikp = this%Lkpuvz_inv(ikpz, ikpu, ikpv)
2045 ikp = this%Lkpuvz_inv(ikpu, ikpz, ikpv)
2047 ikp = this%Lkpuvz_inv(ikpu, ikpv, ikpz)
2059 type(
mesh_t),
intent(in) :: mesh
2062 integer :: mdim, nfaces, ifc, ifp_start, ifp_end
2069 if (this%surf_shape ==
pes_plane) nfaces = 1
2073 ifp_start = this%face_idx_range(ifc, 1)
2074 ifp_end = this%face_idx_range(ifc, 2)
2077 if (this%nsrfcpnts_start <= ifp_end)
then
2079 if (this%nsrfcpnts_start >= ifp_start)
then
2080 if (this%nsrfcpnts_start <= ifp_end)
then
2081 this%face_idx_range(ifc, 1) = this%nsrfcpnts_start
2083 this%face_idx_range(ifc, 1:2) = -1
2087 if (this%nsrfcpnts_end <= ifp_end)
then
2088 if (this%nsrfcpnts_end >= ifp_start)
then
2089 this%face_idx_range(ifc, 2) = this%nsrfcpnts_end
2091 this%face_idx_range(ifc, 1:2) = -1
2097 this%face_idx_range(ifc, 1:2) = -1
2116 class(
space_t),
intent(in) :: space
2117 type(
mesh_t),
intent(in) :: mesh
2120 real(real64),
intent(in) :: dt
2122 integer :: stst, stend, kptst, kptend, sdim, mdim
2123 integer :: ist, ik, isdim, imdim, ik_map
2124 integer :: ikp, itstep
2125 integer :: idir, n_dir, nfaces
2126 complex(real64),
allocatable :: Jk_cub(:,:,:,:), spctramp_cub(:,:,:,:)
2127 integer :: ikp_start, ikp_end, isp_start, isp_end
2128 real(real64) :: vec, kpoint(1:3)
2130 complex(real64),
allocatable :: wfpw(:), gwfpw(:)
2131 complex(real64),
allocatable :: phase(:,:),vphase(:,:)
2133 integer :: tdstep_on_node
2137 integer :: ikpu, ikpv, ikpz, dir_on_face(1:2)
2138 complex(real64) :: face_int_gwf, face_int_wf
2147 call messages_write(
"Debug: calculating pes_flux cub surface integral (accelerated direct expression)")
2152 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_time) /= 0)
then
2153 if (mesh%parallel_in_domains) tdstep_on_node = mesh%mpi_grp%rank + 1
2158 kptst = st%d%kpt%start
2159 kptend = st%d%kpt%end
2163 ikp_start = this%nkpnts_start
2164 ikp_end = this%nkpnts_end
2168 safe_allocate(jk_cub(stst:stend, 1:sdim, kptst:kptend, ikp_start:ikp_end))
2169 safe_allocate(spctramp_cub(stst:stend, 1:sdim, kptst:kptend, ikp_start:ikp_end))
2173 safe_allocate(vphase(ikp_start:ikp_end, kptst:kptend))
2174 safe_allocate(phase(ikp_start:ikp_end, kptst:kptend))
2180 if (this%surf_shape ==
pes_plane) nfaces = 1
2182 safe_allocate( wfpw(ikp_start:ikp_end))
2183 safe_allocate(gwfpw(ikp_start:ikp_end))
2188 if (this%face_idx_range(ifc, 1)<0) cycle
2191 isp_start = this%face_idx_range(ifc, 1)
2192 isp_end = this%face_idx_range(ifc, 2)
2195 nfp = isp_end - isp_start + 1
2203 if (abs(this%srfcnrml(idir, isp_start)) >=
m_epsilon)
then
2206 dir_on_face(imdim)=idir
2213 vphase(ikp_start:ikp_end,:) = this%conjgphase_prev(ikp_start:ikp_end,:)
2215 jk_cub(:, :, :, :) =
m_z0
2217 do itstep = 1, this%itstep
2219 do ik = kptst, kptend
2221 if (kpoints%have_zero_weight_path())
then
2227 kpoint(1:mdim) = kpoints%get_point(st%d%get_kpoint_index(ik))
2228 do ikp = ikp_start, ikp_end
2229 vec = sum((this%kcoords_cub(1:mdim, ikp, ik_map) - this%veca(1:mdim, itstep) /
p_c)**2)
2230 vphase(ikp, ik) = vphase(ikp, ik) *
exp(
m_zi * vec * dt /
m_two)
2233 if (space%is_periodic())
then
2234 phase(ikp, ik) = vphase(ikp, ik) * this%bvk_phase(ikp,ik)
2236 phase(ikp, ik) = vphase(ikp, ik)
2241 if (itstep /= tdstep_on_node) cycle
2243 do ist = stst, stend
2248 if (.not. this%use_symmetry .or. kpoints%have_zero_weight_path())
then
2250 do ikp = ikp_start , ikp_end
2253 sum(this%gwf(isp_start:isp_end, ist, isdim, ik, itstep, n_dir) &
2254 * this%expkr(isp_start:isp_end, ikp, ik_map, 1) &
2255 * this%srfcnrml(n_dir, isp_start:isp_end))
2259 sum(this%wf(isp_start:isp_end, ist, isdim, ik, itstep) &
2260 * this%expkr(isp_start:isp_end, ikp,ik_map, 1) &
2261 * this%srfcnrml(n_dir, isp_start:isp_end))
2266 do ikpu = 1, this%ll(dir_on_face(1))
2267 do ikpv = 1, this%ll(dir_on_face(2))
2270 face_int_gwf = sum(this%gwf(isp_start:isp_end, ist, isdim, ik, itstep, n_dir) &
2271 * this%expkr(isp_start:isp_end, ikpu, ik_map, dir_on_face(1)) &
2272 * this%expkr(isp_start:isp_end, ikpv, ik_map, dir_on_face(2)) &
2273 * this%srfcnrml(n_dir, isp_start:isp_end))
2275 face_int_wf = sum(this%wf(isp_start:isp_end, ist, isdim, ik, itstep) &
2276 * this%expkr(isp_start:isp_end, ikpu, ik_map, dir_on_face(1)) &
2277 * this%expkr(isp_start:isp_end, ikpv, ik_map, dir_on_face(2)) &
2278 * this%srfcnrml(n_dir, isp_start:isp_end))
2280 do ikpz = 1, this%ll(n_dir)
2282 gwfpw(
get_ikp(this, ikpu, ikpv, ikpz, n_dir)) = face_int_gwf &
2283 * this%expkr_perp(ikpz, ifc)
2284 wfpw(
get_ikp(this, ikpu, ikpv, ikpz, n_dir)) = face_int_wf &
2285 * this%expkr_perp(ikpz, ifc)
2297 jk_cub(ist, isdim, ik, ikp_start:ikp_end) = jk_cub(ist, isdim, ik, ikp_start:ikp_end) + &
2298 phase(ikp_start:ikp_end, ik) * (wfpw(ikp_start:ikp_end) * &
2299 (
m_two * this%veca(n_dir, itstep) /
p_c - this%kcoords_cub(n_dir, ikp_start:ikp_end, ik_map)) + &
2300 m_zi * gwfpw(ikp_start:ikp_end))
2310 spctramp_cub(:,:,:,:) = spctramp_cub(:,:,:,:) + jk_cub(:,:,:,:) *
m_half
2316 this%conjgphase_prev(ikp_start:ikp_end, :) = vphase(ikp_start:ikp_end, :)
2319 if (mesh%parallel_in_domains .and.(
bitand(this%par_strategy, option__pes_flux_parallelization__pf_time) /= 0 &
2320 .or.
bitand(this%par_strategy, option__pes_flux_parallelization__pf_surface) /= 0))
then
2321 call mesh%allreduce(spctramp_cub)
2326 this%spctramp_cub = this%spctramp_cub + spctramp_cub * dt
2328 safe_deallocate_a(gwfpw)
2329 safe_deallocate_a(wfpw)
2331 safe_deallocate_a(jk_cub)
2332 safe_deallocate_a(spctramp_cub)
2333 safe_deallocate_a(phase)
2334 safe_deallocate_a(vphase)
2346 type(
mesh_t),
intent(in) :: mesh
2348 real(real64),
intent(in) :: dt
2350 integer :: stst, stend, kptst, kptend, sdim
2351 integer :: ist, ik, isdim, imdim
2352 integer :: itstep, lmax
2353 integer :: ll, mm, ip
2354 complex(real64),
allocatable :: s1_node(:,:,:,:,:,:)
2355 complex(real64),
allocatable :: s2_node(:,:,:,:,:)
2356 complex(real64),
allocatable :: integ11_t(:,:,:), integ12_t(:,:,:)
2357 complex(real64),
allocatable :: integ21_t(:,:), integ22_t(:,:)
2358 complex(real64),
allocatable :: spctramp_sph(:,:,:,:,:)
2359 integer :: ikk, ikk_start, ikk_end
2360 integer :: isp_start, isp_end
2361 integer :: iomk, iomk_start, iomk_end
2362 complex(real64),
allocatable :: phase_act(:,:)
2364 complex(real64) :: weight_x, weight_y, weight_z
2365 integer :: tdstep_on_node
2371 call messages_write(
"Debug: calculating pes_flux sph surface integral")
2375 if (mesh%parallel_in_domains) tdstep_on_node = mesh%mpi_grp%rank + 1
2379 kptst = st%d%kpt%start
2380 kptend = st%d%kpt%end
2384 ikk_start = this%nk_start
2385 ikk_end = this%nk_end
2386 isp_start = this%nsrfcpnts_start
2387 isp_end = this%nsrfcpnts_end
2388 iomk_start = this%nstepsomegak_start
2389 iomk_end = this%nstepsomegak_end
2392 safe_allocate(integ11_t(1:this%nstepsomegak, 1:3, 0:lmax))
2393 safe_allocate(integ21_t(1:this%nstepsomegak, 0:lmax))
2394 safe_allocate(integ12_t(1:this%nstepsomegak, 1:3, ikk_start:ikk_end))
2395 safe_allocate(integ22_t(1:this%nstepsomegak, ikk_start:ikk_end))
2397 safe_allocate(spctramp_sph(1:this%nstepsomegak, stst:stend, 1:sdim, kptst:kptend, 1:this%nk))
2402 safe_allocate(phase_act(1:this%nstepsomegak, ikk_start:ikk_end))
2403 if (ikk_start > 0)
then
2404 phase_act(:, ikk_start:ikk_end) = this%conjgphase_prev(:, ikk_start:ikk_end)
2406 phase_act(:, ikk_start:ikk_end) =
m_z0
2413 safe_allocate(s1_node(1:3, -lmax:lmax, 0:lmax, stst:stend, 1:sdim, kptst:kptend))
2414 safe_allocate(s2_node(-lmax:lmax, 0:lmax, stst:stend, 1:sdim, kptst:kptend))
2416 do itstep = 1, this%itstep
2420 do ik = kptst, kptend
2421 do ist = stst, stend
2425 s1_node(1:3, mm, ll, ist, isdim, ik) =
m_zero
2426 s2_node(mm, ll, ist, isdim, ik) =
m_zero
2428 do ip = isp_start, isp_end
2429 weight_x = this%ylm_r(ip, ll, mm) * this%srfcnrml(1, ip)
2430 weight_y = this%ylm_r(ip, ll, mm) * this%srfcnrml(2, ip)
2431 weight_z = this%ylm_r(ip, ll, mm) * this%srfcnrml(3, ip)
2432 s1_node(1, mm, ll, ist, isdim, ik) = s1_node(1, mm, ll, ist, isdim, ik) + &
2433 weight_x * this%wf(ip, ist, isdim, ik, itstep)
2434 s1_node(2, mm, ll, ist, isdim, ik) = s1_node(2, mm, ll, ist, isdim, ik) + &
2435 weight_y * this%wf(ip, ist, isdim, ik, itstep)
2436 s1_node(3, mm, ll, ist, isdim, ik) = s1_node(3, mm, ll, ist, isdim, ik) + &
2437 weight_z * this%wf(ip, ist, isdim, ik, itstep)
2439 s2_node(mm, ll, ist, isdim, ik) = s2_node(mm, ll, ist, isdim, ik) &
2440 + weight_x * this%gwf(ip, ist, isdim, ik, itstep, 1) &
2441 + weight_y * this%gwf(ip, ist, isdim, ik, itstep, 2) &
2442 + weight_z * this%gwf(ip, ist, isdim, ik, itstep, 3)
2450 if (mesh%parallel_in_domains .and.
bitand(this%par_strategy, option__pes_flux_parallelization__pf_surface) /= 0)
then
2451 call mesh%allreduce(s1_node)
2452 call mesh%allreduce(s2_node)
2459 do ikk = ikk_start, ikk_end
2460 do iomk = 1, this%nstepsomegak
2461 vec = sum((this%kcoords_sph(1:3, ikk, iomk) - this%veca(1:3, itstep) /
p_c)**2)
2462 phase_act(iomk, ikk) = phase_act(iomk, ikk) *
exp(
m_zi * vec * dt *
m_half)
2468 do ik = kptst, kptend
2469 do ist = stst, stend
2484 do ikk = iomk_start, iomk_end
2485 integ11_t(ikk, imdim, ll) = integ11_t(ikk, imdim, ll) + &
2486 s1_node(imdim, mm, ll, ist, isdim, ik) * this%ylm_k(ikk, mm, ll)
2490 do ikk = iomk_start, iomk_end
2491 integ21_t(ikk, ll) = integ21_t(ikk, ll) + &
2492 s2_node(mm, ll, ist, isdim, ik) * this%ylm_k(ikk, mm, ll)
2498 call mesh%allreduce(integ11_t)
2499 call mesh%allreduce(integ21_t)
2503 weight_x = ( -
m_zi)**ll
2506 do ikk = ikk_start, ikk_end
2508 integ12_t(:, imdim, ikk) = integ12_t(:, imdim, ikk) + this%j_l(ikk, ll) * weight_x * integ11_t(:, imdim, ll)
2510 integ22_t(:, ikk) = integ22_t(:, ikk) + this%j_l(ikk, ll) * weight_x * integ21_t(:, ll)
2521 do ikk = ikk_start, ikk_end
2524 spctramp_sph(:, ist, isdim, ik, ikk) = &
2525 spctramp_sph(:, ist, isdim, ik, ikk) + &
2526 phase_act(:, ikk) * (integ12_t(:, imdim, ikk) * &
2527 (
m_two * this%veca(imdim, itstep) /
p_c - this%kcoords_sph(imdim, ikk,:)))
2529 spctramp_sph(:, ist, isdim, ik, ikk) = &
2530 spctramp_sph(:, ist, isdim, ik, ikk) + phase_act(:, ikk) * integ22_t(:, ikk) *
m_zi
2540 safe_deallocate_a(s1_node)
2541 safe_deallocate_a(s2_node)
2543 safe_deallocate_a(integ11_t)
2544 safe_deallocate_a(integ12_t)
2545 safe_deallocate_a(integ21_t)
2546 safe_deallocate_a(integ22_t)
2549 this%conjgphase_prev =
m_z0
2551 if (ikk_start > 0)
then
2552 this%conjgphase_prev(:, ikk_start:ikk_end) = phase_act(:, ikk_start:ikk_end)
2554 safe_deallocate_a(phase_act)
2556 if (mesh%parallel_in_domains .and.
bitand(this%par_strategy, option__pes_flux_parallelization__pf_time) /= 0)
then
2557 call mesh%allreduce(this%conjgphase_prev)
2558 call mesh%allreduce(spctramp_sph)
2563 do ik = kptst, kptend
2564 call lalg_axpy(this%nstepsomegak, stend-stst+1, sdim, dt, spctramp_sph(1:this%nstepsomegak, stst:stend, 1:sdim, ik, ikk), &
2565 this%spctramp_sph(1:this%nstepsomegak, stst:stend, 1:sdim, ik, ikk))
2568 safe_deallocate_a(spctramp_sph)
2575 type(
mesh_t),
intent(in) :: mesh
2578 real(real64),
intent(in) :: border(:)
2579 real(real64),
intent(in) :: offset(:)
2580 real(real64),
intent(in) :: fc_ptdens
2582 integer,
allocatable :: which_surface(:)
2583 real(real64) :: xx(mesh%box%dim), dd, area, dS(mesh%box%dim, 2), factor
2584 integer :: mdim, imdim, idir, isp, pm,nface, idim, ndir, iu,iv, iuv(1:2)
2585 integer(int64) :: ip_global
2587 integer :: rankmin, nsurfaces
2589 integer :: ip_local, NN(mesh%box%dim, 2), idx(mesh%box%dim, 2)
2590 integer :: isp_end, isp_start, ifc, n_dir, nfaces, mindim
2591 real(real64) :: RSmax(2), RSmin(2), RS(2), dRS(2), weight
2603 safe_allocate(this%face_idx_range(1:mdim * 2, 1:2))
2604 safe_allocate(this%LLr(mdim, 1:2))
2605 safe_allocate(this%NN(mdim, 1:2))
2607 this%face_idx_range(:, :) = 0
2612 if (this%surf_interp)
then
2629 do ndir = mdim, mindim, -1
2632 if (idir == ndir) cycle
2633 area = area * border(idir) * factor
2636 npface = int(fc_ptdens * area)
2640 if (idir == ndir) cycle
2641 nn(ndir, idim) = int(
sqrt(npface * (border(idir) * factor)**2 / area))
2642 ds(ndir, idim) = border(idir) * factor / nn(ndir, idim)
2643 this%LLr(ndir, idim) = nn(ndir, idim) * ds(ndir, idim)
2644 idx(ndir, idim) = idir
2647 this%nsrfcpnts = this%nsrfcpnts + 2 * product(nn(ndir, 1:mdim - 1))
2650 this%NN(1:mdim, :) = nn(1:mdim, :)
2653 assert(this%nsrfcpnts > 0)
2656 safe_allocate(this%srfcnrml(1:mdim, 0:this%nsrfcpnts))
2657 safe_allocate(this%rcoords(1:mdim, 0:this%nsrfcpnts))
2659 this%srfcnrml(:, :) =
m_zero
2660 this%rcoords(:, :) =
m_zero
2665 do ndir = mdim, mindim, -1
2668 this%face_idx_range(ifc,1) = isp
2669 do iu = 1, nn(ndir,1)
2670 do iv = 1, nn(ndir,2)
2671 this%rcoords(ndir, isp) = border(ndir)
2672 this%srfcnrml(ndir, isp) = product(ds(ndir,1:mdim-1))
2675 this%rcoords(idx(ndir, idim), isp) = (-nn(ndir, idim) *
m_half -
m_half + iuv(idim)) * ds(ndir, idim)
2680 this%face_idx_range(ifc, 2) = isp-1
2685 this%face_idx_range(ifc, 1) = isp
2686 do iu = 1, nn(ndir, 1)
2687 do iv = 1, nn(ndir, 2)
2688 this%rcoords(ndir, isp) = -border(ndir)
2689 this%srfcnrml(ndir, isp) = -product(ds(ndir, 1:mdim - 1))
2692 this%rcoords(idx(ndir, idim), isp) = (-nn(ndir, idim) *
m_half -
m_half + iuv(idim)) * ds(ndir, idim)
2697 this%face_idx_range(ifc, 2) = isp-1
2702 do isp = 1, this%nsrfcpnts
2703 this%rcoords(1:mdim, isp) = mesh%coord_system%to_cartesian(this%rcoords(1:mdim, isp))
2710 if (this%surf_shape ==
pes_plane) nfaces = 2
2714 safe_allocate(which_surface(1:mesh%np_global))
2719 do ip_local = 1, mesh%np
2724 xx(1:mdim) = mesh%x(ip_local, 1:mdim) - offset(1:mdim)
2727 select case (abb%abtype)
2731 in_ab = abs(abb%mf(ip_local)) >
m_epsilon
2737 if (all(abs(xx(1:mdim)) <= border(1:mdim)) .and. .not. in_ab)
then
2741 dd = border(imdim) - xx(imdim)
2743 dd = border(imdim) - abs(xx(imdim))
2745 if (dd < mesh%spacing(imdim) /
m_two)
then
2746 nsurfaces = nsurfaces + 1
2747 which_surface(ip_global) = int(sign(
m_one, xx(imdim))) * imdim
2752 if (nsurfaces == 1)
then
2753 this%nsrfcpnts = this%nsrfcpnts + 1
2755 which_surface(ip_global) = 0
2761 if (mesh%parallel_in_domains)
then
2762 assert(mesh%np_global < huge(0_int32))
2763 call mesh%allreduce(this%nsrfcpnts)
2764 call mesh%allreduce(which_surface)
2767 safe_allocate(this%srfcpnt(1:this%nsrfcpnts))
2768 safe_allocate(this%srfcnrml(1:mdim, 0:this%nsrfcpnts))
2769 safe_allocate(this%rcoords(1:mdim, 0:this%nsrfcpnts))
2770 safe_allocate(this%rankmin(1:this%nsrfcpnts))
2775 this%face_idx_range(:,:) = 0
2779 do idir = mdim, 1, -1
2782 this%face_idx_range(nface, 1) = isp + 1
2784 do ip_global = 1, mesh%np_global
2785 if (abs(which_surface(ip_global)) == idir .and. sign(1, which_surface(ip_global)) == pm)
then
2789 this%rcoords(1:mdim, isp) = xx(1:mdim)
2792 this%rankmin(isp) = rankmin
2794 this%srfcnrml(idir, isp) = sign(1, which_surface(ip_global))
2797 if (imdim == idir) cycle
2798 this%srfcnrml(idir, isp) = this%srfcnrml(idir, isp) * mesh%spacing(imdim)
2803 this%face_idx_range(nface,2) = isp
2810 do ifc = 1, nint((nfaces + 0.5) / 2)
2811 isp_start = this%face_idx_range(ifc, 1)
2812 isp_end = this%face_idx_range(ifc, 2)
2817 if (abs(this%srfcnrml(idir, isp_start)) >=
m_epsilon) n_dir = idir
2824 if (idir == n_dir) cycle
2825 drs(idim)= mesh%spacing(idir)
2833 do isp = isp_start, isp_end
2835 xx = mesh%coord_system%from_cartesian(this%rcoords(1:mdim, isp))
2838 if (idir == n_dir) cycle
2840 if (rs(idim) < rsmin(idim)) rsmin(idim) = rs(idim)
2841 if (rs(idim) > rsmax(idim)) rsmax(idim) = rs(idim)
2847 do idir = 1, mdim - 1
2848 this%LLr(n_dir, idir) = rsmax(idir) - rsmin(idir) + drs(idir)
2849 if (drs(idir) >
m_zero) this%NN(n_dir, idir) = int(this%LLr(n_dir, idir) / drs(idir))
2857 if (this%anisotrpy_correction)
then
2860 do isp = 1, this%nsrfcpnts
2861 weight = sum(this%rcoords(1:mdim, isp) * this%srfcnrml(1:mdim, isp))
2862 weight = weight/sum(this%rcoords(1:mdim, isp)**2) / sum(this%srfcnrml(1:mdim, isp)**2)
2863 this%srfcnrml(1:mdim, isp) = this%srfcnrml(1:mdim, isp) * abs(weight)
2869 safe_deallocate_a(which_surface)
2877 type(
mesh_t),
intent(in) :: mesh
2878 integer,
intent(inout) :: nstepsthetar, nstepsphir
2881 integer :: isp, ith, iph
2882 real(real64) :: thetar, phir
2883 real(real64) :: weight, dthetar
2889 if (nstepsphir == 0) nstepsphir = 1
2891 if (nstepsthetar <= 1)
then
2895 dthetar =
m_pi / nstepsthetar
2896 this%nsrfcpnts = nstepsphir * (nstepsthetar - 1) + 2
2898 safe_allocate(this%srfcnrml(1:mdim, 0:this%nsrfcpnts))
2899 safe_allocate(this%rcoords(1:mdim, 0:this%nsrfcpnts))
2906 do ith = 0, nstepsthetar
2907 thetar = ith * dthetar
2909 if (ith == 0 .or. ith == nstepsthetar)
then
2912 weight = abs(
cos(thetar - dthetar /
m_two) -
cos(thetar + dthetar /
m_two)) &
2916 do iph = 0, nstepsphir - 1
2919 this%srfcnrml(1, isp) =
cos(phir) *
sin(thetar)
2920 if (mdim >= 2) this%srfcnrml(2, isp) =
sin(phir) *
sin(thetar)
2921 if (mdim == 3) this%srfcnrml(3, isp) =
cos(thetar)
2922 this%rcoords(1:mdim, isp) = this%radius * this%srfcnrml(1:mdim, isp)
2924 this%srfcnrml(1:mdim, isp) = this%radius**
m_two * weight * this%srfcnrml(1:mdim, isp)
2925 if (ith == 0 .or. ith == nstepsthetar)
exit
2937 integer,
intent(in) :: istart_global
2938 integer,
intent(in) :: iend_global
2939 integer,
intent(inout) :: istart
2940 integer,
intent(inout) :: iend
2941 type(mpi_comm),
intent(in) :: comm
2943#if defined(HAVE_MPI)
2944 integer,
allocatable :: dimrank(:)
2945 integer :: mpisize, mpirank, irest, irank
2951#if defined(HAVE_MPI)
2952 call mpi_comm_size(comm, mpisize)
2953 call mpi_comm_rank(comm, mpirank)
2955 safe_allocate(dimrank(0:mpisize-1))
2957 inumber = iend_global - istart_global + 1
2958 irest = mod(inumber, mpisize)
2959 do irank = 0, mpisize - 1
2961 dimrank(irank) = int(inumber / mpisize) + 1
2964 dimrank(irank) = int(inumber / mpisize)
2968 iend = istart_global + sum(dimrank(:mpirank)) - 1
2969 istart = iend - dimrank(mpirank) + 1
2971 if (istart > iend)
then
2976 safe_deallocate_a(dimrank)
2979 istart = istart_global
2987#include "pes_flux_out_inc.F90"
constant times a vector plus a vector
Prints out to iunit a message in the form: ["InputVariable" = value] where "InputVariable" is given b...
double exp(double __x) __attribute__((__nothrow__
double sin(double __x) __attribute__((__nothrow__
double cos(double __x) __attribute__((__nothrow__
double floor(double __x) __attribute__((__nothrow__
integer, parameter, public imaginary_absorbing
integer, parameter, public mask_absorbing
subroutine, public accel_finish()
logical pure function, public accel_buffer_is_allocated(this)
subroutine, public accel_release_buffer(this, async)
pure logical function, public accel_is_enabled()
This module implements batches of mesh functions.
This module implements common operations on batches of mesh functions.
Module implementing boundary conditions in Octopus.
This module handles the calculation mode.
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public zderivatives_batch_grad(der, ffb, opffb, ghost_update, set_bc, to_cartesian, factor)
apply the gradient to a batch of mesh functions
integer, parameter, public spin_polarized
type(lasers_t) function, pointer, public list_get_lasers(partners)
real(real64), parameter, public m_two
real(real64), parameter, public m_zero
real(real64), parameter, public m_pi
some mathematical constants
complex(real64), parameter, public m_z0
complex(real64), parameter, public m_zi
real(real64), parameter, public m_epsilon
complex(real64), parameter, public m_z1
real(real64), parameter, public m_half
real(real64), parameter, public p_c
Electron gyromagnetic ratio, see Phys. Rev. Lett. 130, 071801 (2023)
real(real64), parameter, public m_one
real(real64), parameter, public m_three
This module defines classes and functions for interaction partners.
integer pure function, public kpoints_number(this)
integer, parameter, public e_field_vector_potential
integer pure elemental function, public laser_kind(laser)
subroutine, public laser_field(laser, field, time)
Retrieves the value of either the electric or the magnetic field. If the laser is given by a scalar p...
System information (time, memory, sysname)
This module is intended to contain "only mathematical" functions and procedures.
subroutine, public ylmr_cmplx(xx, li, mi, ylm)
Computes spherical harmonics ylm at position (x, y, z)
subroutine, public mesh_interpolation_init(this, mesh)
This module defines the meshes, which are used in Octopus.
integer function, public mesh_nearest_point(mesh, pos, dmin, rankmin)
Returns the index of the point which is nearest to a given vector position pos.
integer(int64) function, public mesh_local2global(mesh, ip)
This function returns the global mesh index for a given local index.
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, public messages_not_implemented(feature, namespace)
subroutine, public messages_new_line()
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_input_error(namespace, var, details, row, column)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
This module handles the communicators for the various parallelization strategies.
logical function, public parse_is_defined(namespace, name)
integer function, public parse_block(namespace, name, blk, check_varinfo_)
subroutine, public pes_flux_map_from_states(this, restart, st, ll, pesP, krng, Lp, istin)
subroutine pes_flux_getcube(this, mesh, abb, border, offset, fc_ptdens)
subroutine, public pes_flux_calc(this, space, mesh, st, der, ext_partners, kpoints, iter, dt, stopping)
subroutine, public pes_flux_out_energy(this, pesK, file, namespace, ll, Ekin, dim)
subroutine pes_flux_getsphere(this, mesh, nstepsthetar, nstepsphir)
subroutine, public pes_flux_output(this, box, st, namespace)
subroutine, public pes_flux_pmesh(this, namespace, dim, kpoints, ll, pmesh, idxZero, krng, nspin, Lp, Ekin)
subroutine, public pes_flux_reciprocal_mesh_gen(this, namespace, space, st, kpoints, comm, post)
subroutine, public pes_flux_load(restart, this, st, ierr)
subroutine, public pes_flux_dump(restart, this, mesh, st, ierr)
subroutine pes_flux_distribute_facepnts_cub(this, mesh)
subroutine pes_flux_integrate_sph(this, mesh, st, dt)
integer, parameter pes_cartesian
integer, parameter pes_plane
subroutine pes_flux_distribute(istart_global, iend_global, istart, iend, comm)
subroutine pes_flux_integrate_cub(this, space, mesh, st, kpoints, dt)
subroutine, public pes_flux_end(this)
pure integer function get_ikp(this, ikpu, ikpv, ikpz, n_dir)
subroutine pes_flux_integrate_cub_tabulate(this, space, mesh, st, kpoints)
subroutine, public pes_flux_init(this, namespace, space, mesh, st, ext_partners, kpoints, abb, save_iter, max_iter)
integer, parameter pes_spherical
subroutine, public pes_flux_out_vmap(this, pesK, file, namespace, ll, pmesh, dim)
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.
integer pure function, public states_elec_block_max(st, ib)
return index of last state in block ib
integer pure function, public states_elec_block_min(st, ib)
return index of first state in block ib
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
character(len=20) pure function, public units_abbrev(this)
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
This module is intended to contain simple general-purpose utility functions and procedures.
character pure function, public index2axis(idir)
subroutine fill_non_periodic_dimension(this)
Class implementing a parallelepiped box. Currently this is restricted to a rectangular cuboid (all th...
Class implementing a spherical box.
class representing derivatives
Describes mesh distribution to nodes.
A container for the phase.
The states_elec_t class contains all electronic wave functions.
batches of electronic states