37 use,
intrinsic :: iso_fortran_env
85 integer :: nkpnts_start, nkpnts_end
87 integer :: nk_start, nk_end
90 integer :: nstepsthetak, nstepsphik
91 real(real64) :: thetak_rng(1:2)
92 real(real64) :: phik_rng(1:2)
93 integer :: nstepsomegak
94 integer :: nstepsomegak_start, nstepsomegak_end
95 real(real64) :: ktransf(1:3,1:3)
97 real(real64),
allocatable :: klinear(:,:)
102 real(real64),
allocatable :: kcoords_cub(:,:,:)
103 real(real64),
allocatable :: kcoords_sph(:,:,:)
107 integer,
public :: surf_shape
109 integer :: nsrfcpnts_start, nsrfcpnts_end
110 real(real64),
allocatable :: srfcnrml(:,:)
111 real(real64),
allocatable :: rcoords(:,:)
112 integer,
allocatable :: srfcpnt(:)
113 integer,
allocatable :: rankmin(:)
115 complex(real64),
allocatable :: ylm_r(:,:,:)
116 complex(real64),
allocatable :: ylm_k(:,:,:)
117 real(real64),
allocatable :: j_l(:,:)
118 real(real64) :: radius
119 integer,
allocatable :: face_idx_range(:,:)
123 complex(real64),
allocatable :: bvk_phase(:,:)
124 complex(real64),
allocatable :: expkr(:,:,:,:)
125 complex(real64),
allocatable :: expkr_perp(:,:)
127 real(real64),
allocatable :: LLr(:,:)
128 integer,
allocatable :: NN(:,:)
129 integer,
allocatable :: Lkpuvz_inv(:,:,:)
139 complex(real64),
allocatable :: wf(:,:,:,:,:)
140 complex(real64),
allocatable :: gwf(:,:,:,:,:,:)
141 real(real64),
allocatable :: veca(:,:)
142 complex(real64),
allocatable :: conjgphase_prev(:,:)
143 complex(real64),
allocatable :: spctramp_cub(:,:,:,:)
144 complex(real64),
allocatable :: spctramp_sph(:,:,:,:,:)
146 integer,
public :: ll(3)
149 type(mesh_interpolation_t) :: interp
151 logical :: parallel_in_momentum
152 logical :: arpes_grid
153 logical :: surf_interp
154 logical :: use_symmetry
155 logical :: runtime_output
156 logical :: anisotrpy_correction
158 integer :: par_strategy
164 integer,
parameter :: &
169 integer,
parameter :: &
178 subroutine pes_flux_init(this, namespace, space, mesh, st, ext_partners, kpoints, abb, save_iter, max_iter)
181 class(
space_t),
intent(in) :: space
182 type(
mesh_t),
intent(in) :: mesh
187 integer,
intent(in) :: save_iter
188 integer,
intent(in) :: max_iter
191 real(real64) :: border(space%dim)
192 real(real64) :: offset(space%dim)
193 integer :: stst, stend, kptst, kptend, sdim, mdim, pdim
198 integer :: nstepsphir, nstepsthetar
200 integer :: default_shape
201 real(real64) :: fc_ptdens
203 integer :: par_strategy
204 logical :: use_symmetry
212 kptst = st%d%kpt%start
213 kptend = st%d%kpt%end
216 pdim = space%periodic_dim
218 this%surf_interp = .false.
222 if(
associated(lasers))
then
223 do il = 1, lasers%no_lasers
225 message(1) =
't-surff only works in velocity gauge.'
231 message(1) =
'Info: Calculating PES using t-surff technique.'
256 if (space%is_periodic())
then
258 else if (mdim <= 2)
then
259 default_shape = pes_cubic
261 select type (box => mesh%box)
263 default_shape = pes_cubic
267 call parse_variable(namespace,
'PES_Flux_Shape', default_shape, this%surf_shape)
272 message(1) =
'Spherical grid works only in 3d.'
285 if (this%surf_shape == pes_cubic)
then
286 call parse_variable(namespace,
'PES_Flux_AnisotropyCorrection', .false., this%anisotrpy_correction)
302 if (
parse_block(namespace,
'PES_Flux_Offset', blk) == 0)
then
324 if (this%surf_shape == pes_cubic .or. this%surf_shape ==
pes_plane)
then
344 if (
parse_block(namespace,
'PES_Flux_Lsize', blk) == 0)
then
349 border(1:mdim) = int(border(1:mdim) / mesh%spacing(1:mdim)) * mesh%spacing(1:mdim)
353 border(mdim) = mesh%box%bounding_box_l(mdim) *
m_half
354 if (space%is_periodic())
then
356 border(1:pdim)= mesh%box%bounding_box_l(1:pdim) *
m_two
357 call parse_variable(namespace,
'PES_Flux_Lsize', border(mdim), border(mdim))
359 border(mdim) =
floor(border(mdim) / mesh%spacing(mdim)) * mesh%spacing(mdim)
361 call parse_variable(namespace,
'PES_Flux_Lsize', border(mdim), border(mdim))
362 border(1:mdim - 1) = border(mdim)
363 border(1:mdim) =
floor(border(1:mdim) / mesh%spacing(1:mdim)) * mesh%spacing(1:mdim)
366 select type (box => mesh%box)
370 border(1:mdim) = box%half_length(1:mdim) *
m_half
372 call messages_write(
'PES_Flux_Lsize not specified. No default values available for this box shape.')
374 call messages_write(
'Specify the location of the parallelepiped with block PES_Flux_Lsize.')
377 call messages_write(
'PES_Flux_Lsize not specified. Using default values.')
391 this%surf_interp = .
true.
398 this%surf_interp = .
true.
411 select type (box => mesh%box)
413 this%radius = box%radius
415 this%radius = minval(box%half_length(1:mdim))
417 message(1) =
'PES_Flux_Radius not specified. No default values available for this box shape.'
418 message(2) =
'Specify the radius of the sphere with variable PES_Flux_Radius.'
421 message(1) =
'PES_Flux_Radius not specified. Using default values.'
433 call parse_variable(namespace,
'PES_Flux_StepsThetaR', 2 * this%lmax + 1, nstepsthetar)
444 call parse_variable(namespace,
'PES_Flux_StepsPhiR', 2 * this%lmax + 1, nstepsphir)
456 if (this%surf_shape == pes_cubic .or. this%surf_shape ==
pes_plane)
then
491 this%par_strategy = option__pes_flux_parallelization__pf_none
492 if (mesh%parallel_in_domains)
then
495 this%par_strategy = option__pes_flux_parallelization__pf_time &
496 + option__pes_flux_parallelization__pf_surface
498 this%par_strategy = option__pes_flux_parallelization__pf_surface
499 if (space%dim == 1) this%par_strategy = option__pes_flux_parallelization__pf_time
501 par_strategy = this%par_strategy
502 call parse_variable(namespace,
'PES_Flux_Parallelization', par_strategy, this%par_strategy)
510 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_surface) /= 0 .and. &
511 bitand(this%par_strategy, option__pes_flux_parallelization__pf_momentum) /= 0)
then
512 call messages_input_error(namespace,
'PES_Flux_Parallelization',
"Cannot combine pf_surface and pf_momentum")
515 write(
message(1),
'(a)')
'Input: [PES_Flux_Parallelization = '
516 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_none) /= 0)
then
519 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_time) /= 0)
then
522 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_momentum) /= 0)
then
525 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_surface) /= 0)
then
535 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_surface) /= 0)
then
537 call pes_flux_distribute(1, this%nsrfcpnts, this%nsrfcpnts_start, this%nsrfcpnts_end, mesh%mpi_grp%comm)
550 this%nsrfcpnts_start = 1
551 this%nsrfcpnts_end = this%nsrfcpnts
578 use_symmetry = .false.
579 if ((this%surf_shape == pes_cubic .or. this%surf_shape ==
pes_plane) &
581 if (this%surf_shape ==
pes_spherical .and. this%kgrid == pes_polar) use_symmetry = .
true.
582 call parse_variable(namespace,
'PES_Flux_UseSymmetries', use_symmetry, this%use_symmetry)
589 safe_allocate(this%ylm_r(0:this%lmax, -this%lmax:this%lmax, this%nsrfcpnts_start:this%nsrfcpnts_end))
592 if (this%nsrfcpnts_start > 0)
then
593 do isp = this%nsrfcpnts_start, this%nsrfcpnts_end
596 call ylmr_cmplx(this%rcoords(1:3, isp), ll, mm, this%ylm_r(ll, mm, isp))
597 this%ylm_r(ll, mm, isp) = conjg(this%ylm_r(ll, mm, isp))
617 call parse_variable(namespace,
'PES_Flux_RuntimeOutput', .false., this%runtime_output)
625 this%max_iter = max_iter
626 this%save_iter = save_iter
630 if (mesh%parallel_in_domains .and.
bitand(this%par_strategy, option__pes_flux_parallelization__pf_time) /= 0)
then
631 this%tdsteps = mesh%mpi_grp%size
638 safe_allocate(this%wf(stst:stend, 1:sdim, kptst:kptend, 0:this%nsrfcpnts, 1:this%tdsteps))
641 safe_allocate(this%gwf(stst:stend, 1:sdim, kptst:kptend, 0:this%nsrfcpnts, 1:this%tdsteps, 1:mdim))
644 safe_allocate(this%veca(1:mdim, 1:this%tdsteps))
648 safe_allocate(this%spctramp_sph(stst:stend, 1:sdim, kptst:kptend, 1:this%nk, 1:this%nstepsomegak))
649 this%spctramp_sph =
m_z0
651 safe_allocate(this%conjgphase_prev(1:this%nk, 1:this%nstepsomegak))
654 safe_allocate(this%spctramp_cub(stst:stend, 1:sdim, kptst:kptend, 1:this%nkpnts))
655 this%spctramp_cub =
m_z0
657 safe_allocate(this%conjgphase_prev(1:this%nkpnts, kptst:kptend))
661 this%conjgphase_prev =
m_z1
681 safe_deallocate_a(this%kcoords_sph)
682 safe_deallocate_a(this%ylm_k)
683 safe_deallocate_a(this%j_l)
684 safe_deallocate_a(this%ylm_r)
685 safe_deallocate_a(this%conjgphase_prev)
686 safe_deallocate_a(this%spctramp_sph)
688 safe_deallocate_a(this%kcoords_cub)
689 safe_deallocate_a(this%conjgphase_prev)
690 safe_deallocate_a(this%spctramp_cub)
692 if (.not. this%surf_interp)
then
693 safe_deallocate_a(this%srfcpnt)
695 safe_deallocate_a(this%rankmin)
697 safe_deallocate_a(this%face_idx_range)
698 safe_deallocate_a(this%LLr)
699 safe_deallocate_a(this%NN)
701 safe_deallocate_a(this%expkr)
702 safe_deallocate_a(this%expkr_perp)
703 safe_deallocate_a(this%bvk_phase)
705 safe_deallocate_a(this%Lkpuvz_inv)
709 safe_deallocate_a(this%klinear)
711 safe_deallocate_a(this%srfcnrml)
712 safe_deallocate_a(this%rcoords)
714 safe_deallocate_a(this%wf)
715 safe_deallocate_a(this%gwf)
716 safe_deallocate_a(this%veca)
725 class(
space_t),
intent(in) :: space
728 type(mpi_comm),
intent(in) :: comm
729 logical,
optional,
intent(in) :: post
731 integer :: mdim, pdim
732 integer :: kptst, kptend
734 integer :: ll, mm, idim, idir
735 integer :: ikk, ith, iph, iomk,ie, ik1, ik2, ik3, kgrid_block_dim
736 real(real64) :: kmax(space%dim), kmin(space%dim), kact, thetak, phik
739 real(real64) :: emin, emax, de , kvec(1:3), xx(3)
740 integer :: nkp_out, nkmin, nkmax
743 real(real64),
allocatable :: gpoints(:,:), gpoints_reduced(:,:)
744 real(real64) :: dk(1:3), kpoint(1:3), dthetak, dphik
745 logical :: use_enegy_grid, arpes_grid
749 kptst = st%d%kpt%start
750 kptend = st%d%kpt%end
752 pdim = space%periodic_dim
774 select case (this%surf_shape)
781 if (mdim == 1) kgrid = pes_polar
788 call parse_variable(namespace,
'PES_Flux_Momenutum_Grid', kgrid, this%kgrid)
801 if (space%is_periodic())
then
809 if (this%surf_shape == pes_cubic)
then
810 if (space%is_periodic())
then
831 use_enegy_grid = .false.
833 if (
parse_block(namespace,
'PES_Flux_EnergyGrid', blk) == 0)
then
844 use_enegy_grid = .
true.
866 call parse_variable(namespace,
'PES_Flux_ARPES_grid', .false., this%arpes_grid)
867 if (.not. use_enegy_grid .or. this%arpes_grid)
then
878 if (
parse_block(namespace,
'PES_Flux_Kmax', blk) == 0)
then
883 kgrid_block_dim = mdim
885 message(1) =
'Wrong block format for PES_Flux_Kmax and non-cartesian grid'
902 if (
parse_block(namespace,
'PES_Flux_Kmin', blk) == 0)
then
907 kgrid_block_dim = mdim
909 message(1) =
'Wrong block format for PES_Flux_Kmin and non-cartesian grid'
925 call parse_variable(namespace,
'PES_Flux_DeltaK', 0.02_real64, this%dk)
930 do idim = 1, kgrid_block_dim
931 if (kgrid_block_dim == 1)
then
950 if (this%kgrid == pes_polar)
then
973 this%nstepsthetak = 45
975 if (
parse_block(namespace,
'PES_Flux_ThetaK', blk) == 0)
then
981 if (this%thetak_rng(idim) <
m_zero .or. this%thetak_rng(idim) >
m_pi)
then
995 call parse_variable(namespace,
'PES_Flux_StepsThetaK', 45, this%nstepsthetak)
1020 this%nstepsphik = 90
1022 if (mdim == 1) this%phik_rng(1:2) = (/
m_pi,
m_zero/)
1023 if (
parse_block(namespace,
'PES_Flux_PhiK', blk) == 0)
then
1029 if (this%phik_rng(idim) <
m_zero .or. this%phik_rng(idim) >
m_two *
m_pi)
then
1044 call parse_variable(namespace,
'PES_Flux_StepsPhiK', 90, this%nstepsphik)
1046 if (this%nstepsphik == 0) this%nstepsphik = 1
1051 if (mdim == 3) dthetak = abs(this%thetak_rng(2) - this%thetak_rng(1)) / (this%nstepsthetak)
1052 dphik = abs(this%phik_rng(2) - this%phik_rng(1)) / (this%nstepsphik)
1057 this%nstepsthetak = 0
1059 this%nstepsomegak = this%nstepsphik
1062 this%nstepsthetak = 0
1063 this%nstepsomegak = this%nstepsphik
1066 if (this%nstepsthetak <= 1)
then
1068 this%nstepsthetak = 1
1072 do ith = 0, this%nstepsthetak
1073 thetak = ith * dthetak + this%thetak_rng(1)
1074 do iph = 0, this%nstepsphik - 1
1075 phik = iph * dphik + this%phik_rng(1)
1080 this%nstepsomegak = iomk
1087 write(
message(1),
'(a)')
"Polar momentum grid:"
1090 write(
message(1),
'(a,f12.6,a,f12.6,a, i6)') &
1091 " Theta = (", this%thetak_rng(1),
",",this%thetak_rng(2), &
1092 "); n = ", this%nstepsthetak
1095 write(
message(1),
'(a,f12.6,a,f12.6,a, i6)') &
1096 " Phi = (", this%phik_rng(1),
",",this%phik_rng(2), &
1097 "); n = ", this%nstepsphik
1102 if (use_enegy_grid)
then
1103 this%nk = nint(abs(emax - emin) / de)
1105 this%nk = nint(abs(kmax(1) - kmin(1)) / this%dk)
1107 this%nkpnts = this%nstepsomegak * this%nk
1109 this%ll(1) = this%nk
1110 this%ll(2) = this%nstepsphik
1111 this%ll(3) = this%nstepsthetak
1112 this%ll(mdim+1:3) = 1
1114 safe_allocate(this%klinear(1:this%nk, 1))
1120 dk(1:mdim) =
m_one/kpoints%nik_axis(1:mdim)
1122 this%arpes_grid = .false.
1123 if (space%is_periodic())
then
1134 arpes_grid = kpoints%have_zero_weight_path()
1135 call parse_variable(namespace,
'PES_Flux_ARPES_grid', arpes_grid, this%arpes_grid)
1144 if (kpoints%have_zero_weight_path())
then
1146 if (this%arpes_grid)
then
1147 nkmax =
floor(emax / de)
1148 nkmin =
floor(emin / de)
1151 nkmax =
floor(kmax(mdim) / this%dk)
1152 nkmin =
floor(kmin(mdim) / this%dk)
1156 this%ll(mdim) = abs(nkmax - nkmin) + 1
1158 this%nk = this%ll(mdim)
1163 if (.not. this%arpes_grid)
then
1164 this%ll(1:mdim) =
floor(abs(kmax(1:mdim) - kmin(1:mdim))/this%dk) + 1
1165 this%nk = maxval(this%ll(1:mdim))
1169 nkmax =
floor(emax / de)
1170 nkmin =
floor(emin / de)
1171 this%nk = abs(nkmax - nkmin) + 1
1173 this%ll(1:pdim) =
floor(abs(kmax(1:pdim) - kmin(1:pdim))/this%dk) + 1
1174 this%ll(mdim) = this%nk
1178 safe_allocate(this%klinear(1:maxval(this%ll(1:mdim)), 1:mdim))
1184 this%nkpnts = product(this%ll(1:mdim))
1193 this%parallel_in_momentum = .false.
1196 select case (this%kgrid)
1200 if (use_enegy_grid)
then
1202 this%klinear(ie, 1) =
sqrt(
m_two * (ie * de + emin))
1206 this%klinear(ikk, 1) = ikk * this%dk + kmin(1)
1220 if ((this%nk_end - this%nk_start + 1) < this%nk) this%parallel_in_momentum = .
true.
1221 call pes_flux_distribute(1, this%nstepsomegak, this%nstepsomegak_start, this%nstepsomegak_end, comm)
1233 safe_allocate(this%j_l(0:this%lmax, this%nk_start:this%nk_end))
1236 safe_allocate(this%kcoords_sph(1:3, this%nk_start:this%nk_end, 1:this%nstepsomegak))
1237 this%kcoords_sph =
m_zero
1239 safe_allocate(this%ylm_k(0:this%lmax, - this%lmax:this%lmax, this%nstepsomegak_start:this%nstepsomegak_end))
1244 do ith = 0, this%nstepsthetak
1245 thetak = ith * dthetak + this%thetak_rng(1)
1246 do iph = 0, this%nstepsphik - 1
1247 phik = iph * dphik + this%phik_rng(1)
1249 if (iomk >= this%nstepsomegak_start .and. iomk <= this%nstepsomegak_end)
then
1250 do ll = 0, this%lmax
1252 xx(1) =
cos(phik) *
sin(thetak)
1253 xx(2) =
sin(phik) *
sin(thetak)
1255 call ylmr_cmplx(xx, ll, mm, this%ylm_k(ll, mm, iomk))
1259 if (this%nk_start > 0)
then
1260 this%kcoords_sph(1, this%nk_start:this%nk_end, iomk) =
cos(phik) *
sin(thetak)
1261 this%kcoords_sph(2, this%nk_start:this%nk_end, iomk) =
sin(phik) *
sin(thetak)
1262 this%kcoords_sph(3, this%nk_start:this%nk_end, iomk) =
cos(thetak)
1268 if (this%nk_start > 0)
then
1270 do ikk = this%nk_start, this%nk_end
1271 kact = this%klinear(ikk,1)
1272 do ll = 0, this%lmax
1276 this%kcoords_sph(:, ikk, :) = kact * this%kcoords_sph(:, ikk, :)
1285 this%nkpnts_start = 1
1286 this%nkpnts_end = this%nkpnts
1289 safe_allocate(this%kcoords_cub(1:mdim, this%nkpnts_start:this%nkpnts_end, 1))
1291 this%kcoords_cub =
m_zero
1296 do ikk = -this%nk, this%nk
1299 kact = sign(1,ikk) * this%klinear(abs(ikk), 1)
1300 this%kcoords_cub(1, ikp, 1) = kact
1308 do ith = 0, this%nstepsthetak
1309 if (mdim == 3) thetak = ith * dthetak + this%thetak_rng(1)
1310 do iph = 0, this%nstepsphik - 1
1312 phik = iph * dphik + this%phik_rng(1)
1313 kact = this%klinear(ikk,1)
1314 this%kcoords_cub(1, ikp,1) = kact *
cos(phik) *
sin(thetak)
1315 this%kcoords_cub(2, ikp,1) = kact *
sin(phik) *
sin(thetak)
1316 if (mdim == 3) this%kcoords_cub(3, ikp,1) = kact *
cos(thetak)
1327 this%nkpnts_start = 1
1328 this%nkpnts_end = this%nkpnts
1334 if (kpoints%have_zero_weight_path())
then
1338 safe_allocate(this%kcoords_cub(1:mdim, this%nkpnts_start:this%nkpnts_end, kptst:kptend))
1341 do ikpt = kptst, kptend
1343 do ikk = nkmin, nkmax
1345 kvec(1:mdim) = - kpoints%get_point(ikpt)
1353 safe_allocate(this%kcoords_cub(1:mdim, this%nkpnts_start:this%nkpnts_end, 1))
1355 safe_allocate(this%Lkpuvz_inv(1:this%ll(1), 1:this%ll(2), 1:this%ll(3)))
1358 do ikk = 1, this%ll(idir)
1359 this%klinear(ikk, idir) = ikk * this%dk + kmin(idir)
1364 if (.not. this%arpes_grid)
then
1371 do ik3 = 1, this%ll(3)
1372 if (mdim>2) kvec(3) = this%klinear(ik3, 3)
1373 do ik2 = 1, this%ll(2)
1374 if (mdim>1) kvec(2) = this%klinear(ik2, 2)
1375 do ik1 = 1, this%ll(1)
1377 kvec(1) = this%klinear(ik1, 1)
1378 this%kcoords_cub(1:mdim, ikp, ikpt) = kvec(1:mdim)
1379 this%Lkpuvz_inv(ik1, ik2, ik3) = ikp
1391 do ikk = nkmin, nkmax
1397 do ik1 = 1, this%ll(1)
1398 kvec(1) = this%klinear(ik1,1)
1399 kvec(1:pdim) = matmul(kpoints%latt%klattice_primitive(1:pdim, 1:pdim), kvec(1:pdim))
1405 do ik2 = 1, this%ll(2)
1406 do ik1 = 1, this%ll(1)
1407 kvec(1:2) = (/this%klinear(ik1,1), this%klinear(ik2,2)/)
1408 kvec(1:pdim) = matmul(kpoints%latt%klattice_primitive(1:pdim, 1:pdim), kvec(1:pdim))
1411 this%Lkpuvz_inv(ik1, ik2, ikk - nkmin + 1) = ikp
1464 if (this%arpes_grid)
then
1473 safe_deallocate_a(gpoints)
1474 safe_deallocate_a(gpoints_reduced)
1495 this%ktransf(:,:) =
m_zero
1497 this%ktransf(idim,idim) =
m_one
1500 if (
parse_block(namespace,
'PES_Flux_GridTransformMatrix', blk) == 0)
then
1508 write(
message(1),
'(a)')
'Momentum grid transformation matrix :'
1509 do idir = 1, space%dim
1510 write(
message(1 + idir),
'(9f12.6)') ( this%ktransf(idim, idir), idim = 1, mdim)
1519 do ith = 0, this%nstepsthetak
1520 do iph = 0, this%nstepsphik - 1
1522 do ikk = this%nk_start, this%nk_end
1523 kvec(1:mdim) = this%kcoords_sph(1:mdim, ikk, iomk)
1524 this%kcoords_sph(1:mdim, ikk, iomk) = matmul(this%ktransf(1:mdim, 1:mdim), kvec(1:mdim))
1526 if (ith == 0 .or. ith == this%nstepsthetak)
exit
1532 do ikpt = kptst, kptend + 1
1533 if (ikpt == kptend + 1)
then
1534 kpoint(1:space%dim) =
m_zero
1536 kpoint(1:space%dim) = kpoints%get_point(ikpt)
1539 do ikp = 1, this%nkpnts
1541 kvec(1:mdim) = this%kcoords_cub(1:mdim, ikp, ikpt) - kpoint(1:mdim)
1542 this%kcoords_cub(1:mdim, ikp, ikpt) = matmul(this%ktransf(1:mdim, 1:mdim), kvec(1:mdim)) &
1564 real(real64) :: kpar(1:pdim), val
1569 if (ikk /= 0) sign= ikk / abs(ikk)
1571 kpar(1:pdim) = kvec(1:pdim)
1572 val = abs(ikk) * de *
m_two - sum(kpar(1:pdim)**2)
1574 kvec(mdim) = sign *
sqrt(val)
1577 kvec(mdim) =
sqrt(val)
1578 nkp_out = nkp_out + 1
1581 this%kcoords_cub(1:mdim, ikp, ikpt) = kvec(1:mdim)
1591 subroutine pes_flux_calc(this, space, mesh, st, der, ext_partners, kpoints, iter, dt, stopping)
1593 class(
space_t),
intent(in) :: space
1594 type(
mesh_t),
intent(in) :: mesh
1599 integer,
intent(in) :: iter
1600 real(real64),
intent(in) :: dt
1601 logical,
intent(in) :: stopping
1603 integer :: stst, stend, kptst, kptend, sdim, mdim
1604 integer :: ist, ik, isdim, imdim
1606 integer :: il, ip_local
1607 complex(real64),
allocatable :: gpsi(:,:), psi(:)
1608 complex(real64),
allocatable :: interp_values(:)
1609 logical :: contains_isp
1610 real(real64) :: kpoint(1:3)
1611 complex(real64),
allocatable :: tmp_array(:)
1621 kptst = st%d%kpt%start
1622 kptend = st%d%kpt%end
1626 safe_allocate(psi(1:mesh%np_part))
1627 safe_allocate(gpsi(1:mesh%np_part, 1:mdim))
1629 if (this%surf_interp)
then
1630 safe_allocate(interp_values(1:this%nsrfcpnts))
1633 this%itstep = this%itstep + 1
1637 if(
associated(lasers))
then
1638 do il = 1, lasers%no_lasers
1639 call laser_field(lasers%lasers(il), this%veca(1:mdim, this%itstep), iter*dt)
1642 this%veca(:, this%itstep) = - this%veca(:, this%itstep)
1647 if(mesh%parallel_in_domains)
then
1648 safe_allocate(tmp_array(1:this%nsrfcpnts))
1652 do ik = kptst, kptend
1653 do ist = stst, stend
1662 kpoint(1:mdim) = kpoints%get_point(st%d%get_kpoint_index(ik))
1665 do ip = 1, mesh%np_part
1666 psi(ip) =
exp(-
m_zi * sum(mesh%x(ip, 1:mdim) * kpoint(1:mdim))) * psi(ip)
1673 if (this%surf_interp)
then
1675 this%rcoords(1:mdim, 1:this%nsrfcpnts), interp_values(1:this%nsrfcpnts))
1676 this%wf(ist, isdim, ik, 1:this%nsrfcpnts, this%itstep) = st%occ(ist, ik) * interp_values(1:this%nsrfcpnts)
1679 this%rcoords(1:mdim, 1:this%nsrfcpnts), interp_values(1:this%nsrfcpnts))
1680 this%gwf(ist, isdim, ik, 1:this%nsrfcpnts, this%itstep, imdim) = st%occ(ist, ik) * interp_values(1:this%nsrfcpnts)
1685 contains_isp = .
true.
1686 do isp = 1, this%nsrfcpnts
1687 if (mesh%parallel_in_domains)
then
1688 if (mesh%mpi_grp%rank == this%rankmin(isp))
then
1689 contains_isp = .
true.
1691 contains_isp = .false.
1695 if (contains_isp)
then
1696 ip_local = this%srfcpnt(isp)
1697 this%wf(ist, isdim, ik, isp, this%itstep) = st%occ(ist, ik) * psi(ip_local)
1698 this%gwf(ist, isdim, ik, isp, this%itstep, 1:mdim) = &
1699 st%occ(ist, ik) * gpsi(ip_local, 1:mdim)
1702 if (mesh%parallel_in_domains)
then
1704 tmp_array = this%wf(ist, isdim, ik, 1:this%nsrfcpnts, this%itstep)
1705 call mesh%allreduce(tmp_array)
1706 this%wf(ist, isdim, ik, 1:this%nsrfcpnts, this%itstep) = tmp_array
1709 tmp_array = this%gwf(ist, isdim, ik, 1:this%nsrfcpnts, this%itstep, imdim)
1710 call mesh%allreduce(tmp_array)
1711 this%gwf(ist, isdim, ik, 1:this%nsrfcpnts, this%itstep, imdim) = tmp_array
1719 if(mesh%parallel_in_domains)
then
1720 safe_deallocate_a(tmp_array)
1723 safe_deallocate_a(psi)
1724 safe_deallocate_a(gpsi)
1726 if (this%itstep == this%tdsteps .or. mod(iter, this%save_iter) == 0 .or. iter == this%max_iter .or. stopping)
then
1727 if (this%surf_shape == pes_cubic .or. this%surf_shape ==
pes_plane)
then
1750 class(
space_t),
intent(in) :: space
1751 type(
mesh_t),
intent(in) :: mesh
1755 integer :: kptst, kptend, mdim
1756 integer :: ik, j1, j2, jvec(1:2)
1757 integer :: isp, ikp, ikp_start, ikp_end
1760 integer :: idir, pdim, nfaces, ifc, n_dir
1761 complex(real64) :: tmp
1762 real(real64) :: kpoint(1:3), vec(1:3), lvec(1:3)
1766 if (kpoints%have_zero_weight_path())
then
1767 kptst = st%d%kpt%start
1768 kptend = st%d%kpt%end
1775 pdim = space%periodic_dim
1777 ikp_start = this%nkpnts_start
1778 ikp_end = this%nkpnts_end
1784 this%srfcnrml(:, 1:this%nsrfcpnts) = this%srfcnrml(:, 1:this%nsrfcpnts) * mesh%coord_system%surface_element(3)
1787 if (.not. this%use_symmetry .or. kpoints%have_zero_weight_path())
then
1789 safe_allocate(this%expkr(1:this%nsrfcpnts,ikp_start:ikp_end,kptst:kptend,1))
1791 do ik = kptst, kptend
1792 do ikp = ikp_start, ikp_end
1793 do isp = 1, this%nsrfcpnts
1794 this%expkr(isp,ikp,ik,1) =
exp(-
m_zi * sum(this%rcoords(1:mdim,isp) &
1795 * this%kcoords_cub(1:mdim, ikp, ik))) &
1807 if (this%surf_shape ==
pes_plane) nfaces = 1
1810 safe_allocate(this%expkr(1:this%nsrfcpnts,maxval(this%ll(1:mdim)),kptst:kptend,1:mdim))
1811 this%expkr(:,:,:,:) =
m_z1
1813 do ik = kptst, kptend
1815 do ikp = 1, this%ll(idir)
1816 do isp = 1, this%nsrfcpnts
1817 this%expkr(isp,ikp,ik,idir) =
exp(-
m_zi * this%rcoords(idir,isp) &
1818 * this%klinear(ikp, idir)) &
1826 safe_allocate(this%expkr_perp(1:maxval(this%ll(1:mdim)), 1:nfaces))
1827 this%expkr_perp(:,:) =
m_z1
1830 if (this%face_idx_range(ifc, 1) < 0) cycle
1831 isp = this%face_idx_range(ifc, 1)
1833 if (abs(this%srfcnrml(idir, isp)) >=
m_epsilon) n_dir = idir
1836 do ikp = 1, this%ll(n_dir)
1837 this%expkr_perp(ikp, ifc) =
exp(-
m_zi * this%rcoords(n_dir,isp) &
1838 * this%klinear(ikp, n_dir)) &
1848 if (space%is_periodic())
then
1850 safe_allocate(this%bvk_phase(ikp_start:ikp_end,st%d%kpt%start:st%d%kpt%end))
1852 this%bvk_phase(:,:) =
m_z0
1855 do ik = st%d%kpt%start, st%d%kpt%end
1856 kpoint(1:mdim) = kpoints%get_point(ik)
1857 if (kpoints%have_zero_weight_path())
then
1862 do ikp = ikp_start, ikp_end
1863 vec(1:pdim) = this%kcoords_cub(1:pdim, ikp, ik_map) + kpoint(1:pdim)
1864 do j1 = 0, kpoints%nik_axis(1) - 1
1865 do j2 = 0, kpoints%nik_axis(2) - 1
1866 jvec(1:2)=(/j1, j2/)
1867 lvec(1:pdim) = matmul(kpoints%latt%rlattice(1:pdim, 1:2), jvec(1:2))
1868 tmp = sum(lvec(1:pdim) * vec(1:pdim))
1869 this%bvk_phase(ikp, ik) = this%bvk_phase(ikp,ik) &
1877 this%bvk_phase(:,:) = this%bvk_phase(:,:) *
m_one / product(kpoints%nik_axis(1:pdim))
1899 pure function get_ikp(this, ikpu, ikpv, ikpz, n_dir)
result(ikp)
1901 integer,
intent(in) :: ikpu
1902 integer,
intent(in) :: ikpv
1903 integer,
intent(in) :: ikpz
1904 integer,
intent(in) :: n_dir
1909 ikp = this%Lkpuvz_inv(ikpz, ikpu, ikpv)
1911 ikp = this%Lkpuvz_inv(ikpu, ikpz, ikpv)
1913 ikp = this%Lkpuvz_inv(ikpu, ikpv, ikpz)
1925 type(
mesh_t),
intent(in) :: mesh
1928 integer :: mdim, nfaces, ifc, ifp_start, ifp_end
1935 if (this%surf_shape ==
pes_plane) nfaces = 1
1939 ifp_start = this%face_idx_range(ifc, 1)
1940 ifp_end = this%face_idx_range(ifc, 2)
1943 if (this%nsrfcpnts_start <= ifp_end)
then
1945 if (this%nsrfcpnts_start >= ifp_start)
then
1946 if (this%nsrfcpnts_start <= ifp_end)
then
1947 this%face_idx_range(ifc, 1) = this%nsrfcpnts_start
1949 this%face_idx_range(ifc, 1:2) = -1
1953 if (this%nsrfcpnts_end <= ifp_end)
then
1954 if (this%nsrfcpnts_end >= ifp_start)
then
1955 this%face_idx_range(ifc, 2) = this%nsrfcpnts_end
1957 this%face_idx_range(ifc, 1:2) = -1
1963 this%face_idx_range(ifc, 1:2) = -1
1982 class(
space_t),
intent(in) :: space
1983 type(
mesh_t),
intent(in) :: mesh
1986 real(real64),
intent(in) :: dt
1988 integer :: stst, stend, kptst, kptend, sdim, mdim
1989 integer :: ist, ik, isdim, imdim, ik_map
1990 integer :: ikp, itstep
1991 integer :: idir, n_dir, nfaces
1992 complex(real64),
allocatable :: jk_cub(:,:,:,:), spctramp_cub(:,:,:,:)
1993 integer :: ikp_start, ikp_end, isp_start, isp_end
1994 real(real64) :: vec, kpoint(1:3)
1996 complex(real64),
allocatable :: wfpw(:), gwfpw(:)
1997 complex(real64),
allocatable :: phase(:,:),vphase(:,:)
1999 integer :: tdstep_on_node
2003 integer :: ikpu, ikpv, ikpz, dir_on_face(1:2)
2004 complex(real64) :: face_int_gwf, face_int_wf
2013 call messages_write(
"Debug: calculating pes_flux cub surface integral (accelerated direct expression)")
2018 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_time) /= 0)
then
2019 if (mesh%parallel_in_domains) tdstep_on_node = mesh%mpi_grp%rank + 1
2024 kptst = st%d%kpt%start
2025 kptend = st%d%kpt%end
2029 ikp_start = this%nkpnts_start
2030 ikp_end = this%nkpnts_end
2034 safe_allocate(jk_cub(stst:stend, 1:sdim, kptst:kptend, ikp_start:ikp_end))
2035 safe_allocate(spctramp_cub(stst:stend, 1:sdim, kptst:kptend, ikp_start:ikp_end))
2039 safe_allocate(vphase(ikp_start:ikp_end, kptst:kptend))
2040 safe_allocate(phase(ikp_start:ikp_end, kptst:kptend))
2046 if (this%surf_shape ==
pes_plane) nfaces = 1
2048 safe_allocate( wfpw(ikp_start:ikp_end))
2049 safe_allocate(gwfpw(ikp_start:ikp_end))
2054 if (this%face_idx_range(ifc, 1)<0) cycle
2057 isp_start = this%face_idx_range(ifc, 1)
2058 isp_end = this%face_idx_range(ifc, 2)
2061 nfp = isp_end - isp_start + 1
2069 if (abs(this%srfcnrml(idir, isp_start)) >=
m_epsilon)
then
2072 dir_on_face(imdim)=idir
2079 vphase(ikp_start:ikp_end,:) = this%conjgphase_prev(ikp_start:ikp_end,:)
2081 jk_cub(:, :, :, :) =
m_z0
2083 do itstep = 1, this%itstep
2085 do ik = kptst, kptend
2087 if (kpoints%have_zero_weight_path())
then
2093 kpoint(1:mdim) = kpoints%get_point(ik)
2094 do ikp = ikp_start, ikp_end
2095 vec = sum((this%kcoords_cub(1:mdim, ikp, ik_map) - this%veca(1:mdim, itstep) /
p_c)**2)
2096 vphase(ikp, ik) = vphase(ikp, ik) *
exp(
m_zi * vec * dt /
m_two)
2099 if (space%is_periodic())
then
2100 phase(ikp, ik) = vphase(ikp, ik) * this%bvk_phase(ikp,ik)
2102 phase(ikp, ik) = vphase(ikp, ik)
2107 if (itstep /= tdstep_on_node) cycle
2109 do ist = stst, stend
2114 if (.not. this%use_symmetry .or. kpoints%have_zero_weight_path())
then
2116 do ikp = ikp_start , ikp_end
2119 sum(this%gwf(ist, isdim, ik, isp_start:isp_end, itstep, n_dir) &
2120 * this%expkr(isp_start:isp_end, ikp, ik_map, 1) &
2121 * this%srfcnrml(n_dir, isp_start:isp_end))
2125 sum(this%wf(ist, isdim, ik, isp_start:isp_end, itstep) &
2126 * this%expkr(isp_start:isp_end, ikp,ik_map, 1) &
2127 * this%srfcnrml(n_dir, isp_start:isp_end))
2132 do ikpu = 1, this%ll(dir_on_face(1))
2133 do ikpv = 1, this%ll(dir_on_face(2))
2136 face_int_gwf = sum(this%gwf(ist, isdim, ik, isp_start:isp_end, itstep, n_dir) &
2137 * this%expkr(isp_start:isp_end, ikpu, ik_map, dir_on_face(1)) &
2138 * this%expkr(isp_start:isp_end, ikpv, ik_map, dir_on_face(2)) &
2139 * this%srfcnrml(n_dir, isp_start:isp_end))
2141 face_int_wf = sum(this%wf(ist, isdim, ik, isp_start:isp_end, itstep) &
2142 * this%expkr(isp_start:isp_end, ikpu, ik_map, dir_on_face(1)) &
2143 * this%expkr(isp_start:isp_end, ikpv, ik_map, dir_on_face(2)) &
2144 * this%srfcnrml(n_dir, isp_start:isp_end))
2146 do ikpz = 1, this%ll(n_dir)
2148 gwfpw(
get_ikp(this, ikpu, ikpv, ikpz, n_dir)) = face_int_gwf &
2149 * this%expkr_perp(ikpz, ifc)
2150 wfpw(
get_ikp(this, ikpu, ikpv, ikpz, n_dir)) = face_int_wf &
2151 * this%expkr_perp(ikpz, ifc)
2163 jk_cub(ist, isdim, ik, ikp_start:ikp_end) = jk_cub(ist, isdim, ik, ikp_start:ikp_end) + &
2164 phase(ikp_start:ikp_end, ik) * (wfpw(ikp_start:ikp_end) * &
2165 (
m_two * this%veca(n_dir, itstep) /
p_c - this%kcoords_cub(n_dir, ikp_start:ikp_end, ik_map)) + &
2166 m_zi * gwfpw(ikp_start:ikp_end))
2176 spctramp_cub(:,:,:,:) = spctramp_cub(:,:,:,:) + jk_cub(:,:,:,:) *
m_half
2182 this%conjgphase_prev(ikp_start:ikp_end, :) = vphase(ikp_start:ikp_end, :)
2185 if (mesh%parallel_in_domains .and.(
bitand(this%par_strategy, option__pes_flux_parallelization__pf_time) /= 0 &
2186 .or.
bitand(this%par_strategy, option__pes_flux_parallelization__pf_surface) /= 0))
then
2187 call mesh%allreduce(spctramp_cub)
2192 this%spctramp_cub = this%spctramp_cub + spctramp_cub * dt
2194 safe_deallocate_a(gwfpw)
2195 safe_deallocate_a(wfpw)
2197 safe_deallocate_a(jk_cub)
2198 safe_deallocate_a(spctramp_cub)
2199 safe_deallocate_a(phase)
2200 safe_deallocate_a(vphase)
2212 type(
mesh_t),
intent(in) :: mesh
2214 real(real64),
intent(in) :: dt
2216 integer :: stst, stend, kptst, kptend, sdim
2217 integer :: ist, ik, isdim, imdim
2218 integer :: itstep, lmax
2220 complex(real64),
allocatable :: s1_node(:,:,:,:,:,:), s1_act(:,:,:)
2221 complex(real64),
allocatable :: s2_node(:,:,:,:,:), s2_act(:,:)
2222 complex(real64),
allocatable :: integ11_t(:,:), integ12_t(:,:,:)
2223 complex(real64),
allocatable :: integ21_t(:), integ22_t(:,:)
2224 complex(real64),
allocatable :: spctramp_sph(:,:,:,:,:)
2225 integer :: ikk, ikk_start, ikk_end
2226 integer :: isp_start, isp_end
2227 integer :: iomk, iomk_start, iomk_end
2228 complex(real64),
allocatable :: phase_act(:,:)
2230 integer :: tdstep_on_node
2236 call messages_write(
"Debug: calculating pes_flux sph surface integral")
2240 if (mesh%parallel_in_domains) tdstep_on_node = mesh%mpi_grp%rank + 1
2244 kptst = st%d%kpt%start
2245 kptend = st%d%kpt%end
2249 ikk_start = this%nk_start
2250 ikk_end = this%nk_end
2251 isp_start = this%nsrfcpnts_start
2252 isp_end = this%nsrfcpnts_end
2253 iomk_start = this%nstepsomegak_start
2254 iomk_end = this%nstepsomegak_end
2257 safe_allocate(s1_node(stst:stend, 1:sdim, kptst:kptend, 0:lmax, -lmax:lmax, 1:3))
2258 safe_allocate(s2_node(stst:stend, 1:sdim, kptst:kptend, 0:lmax, -lmax:lmax))
2260 safe_allocate(s1_act(0:lmax, -lmax:lmax, 1:3))
2261 safe_allocate(s2_act(0:lmax, -lmax:lmax))
2263 do itstep = 1, this%itstep
2265 do ik = kptst, kptend
2266 do ist = stst, stend
2275 s1_act(ll, mm, imdim) = &
2276 sum(this%ylm_r(ll, mm, isp_start:isp_end) * this%srfcnrml(imdim, isp_start:isp_end) * &
2277 this%wf(ist, isdim, ik, isp_start:isp_end, itstep))
2279 s2_act(ll, mm) = s2_act(ll, mm) + &
2280 sum(this%ylm_r(ll, mm, isp_start:isp_end) * this%srfcnrml(imdim, isp_start:isp_end) * &
2281 this%gwf(ist, isdim, ik, isp_start:isp_end, itstep, imdim))
2286 if (mesh%parallel_in_domains .and.
bitand(this%par_strategy, option__pes_flux_parallelization__pf_surface) /= 0)
then
2287 call mesh%allreduce(s1_act)
2288 call mesh%allreduce(s2_act)
2291 if (itstep == tdstep_on_node)
then
2292 s1_node(ist, isdim, ik, :, :, :) = s1_act(:, :, :)
2293 s2_node(ist, isdim, ik, :, :) = s2_act(:, :)
2302 safe_allocate(integ11_t(0:this%nstepsomegak, 1:3))
2303 safe_allocate(integ21_t(0:this%nstepsomegak))
2304 safe_allocate(integ12_t(ikk_start:ikk_end, 1:this%nstepsomegak, 1:3))
2305 safe_allocate(integ22_t(ikk_start:ikk_end, 1:this%nstepsomegak))
2307 safe_allocate(spctramp_sph(stst:stend, 1:sdim, kptst:kptend, 0:this%nk, 1:this%nstepsomegak))
2311 safe_allocate(phase_act(ikk_start:ikk_end, 1:this%nstepsomegak))
2312 if (ikk_start > 0)
then
2313 phase_act(ikk_start:ikk_end, :) = this%conjgphase_prev(ikk_start:ikk_end, :)
2315 phase_act(ikk_start:ikk_end, :) =
m_z0
2318 do itstep = 1, this%itstep
2320 do ikk = ikk_start, ikk_end
2321 do iomk = 1, this%nstepsomegak
2322 vec = sum((this%kcoords_sph(1:3, ikk, iomk) - this%veca(1:3, itstep) /
p_c)**
m_two)
2323 phase_act(ikk, iomk) = phase_act(ikk, iomk) *
exp(
m_zi * vec * dt /
m_two)
2327 do ik = kptst, kptend
2328 do ist = stst, stend
2332 if (itstep == tdstep_on_node)
then
2333 s1_act(:,:,:) = s1_node(ist, isdim, ik, :, :, :)
2334 s2_act(:,:) = s2_node(ist, isdim, ik, :, :)
2336 if (mesh%parallel_in_domains)
then
2337 call mesh%mpi_grp%bcast(s1_act, (lmax + 1) * (2 * lmax + 1) * 3, mpi_double_complex, itstep - 1)
2338 call mesh%mpi_grp%bcast(s2_act, (lmax + 1) * (2 * lmax + 1), mpi_double_complex, itstep - 1)
2352 integ11_t(iomk_start:iomk_end, imdim) = integ11_t(iomk_start:iomk_end, imdim) + &
2353 s1_act(ll, mm, imdim) * this%ylm_k(ll, mm, iomk_start:iomk_end)
2355 integ21_t(iomk_start:iomk_end) = integ21_t(iomk_start:iomk_end) + &
2356 s2_act(ll, mm) * this%ylm_k(ll, mm, iomk_start:iomk_end)
2359 call mesh%allreduce(integ11_t)
2360 call mesh%allreduce(integ21_t)
2363 do ikk = ikk_start, ikk_end
2364 integ12_t(ikk, 1:this%nstepsomegak, 1:3) = integ12_t(ikk, 1:this%nstepsomegak, 1:3) + &
2365 integ11_t(1:this%nstepsomegak, 1:3) * this%j_l(ll, ikk) * ( -
m_zi)**ll
2366 integ22_t(ikk, 1:this%nstepsomegak) = integ22_t(ikk, 1:this%nstepsomegak) + &
2367 integ21_t(1:this%nstepsomegak) * this%j_l(ll, ikk) * ( -
m_zi)**ll
2372 spctramp_sph(ist, isdim, ik, ikk_start:ikk_end, :) = &
2373 spctramp_sph(ist, isdim, ik, ikk_start:ikk_end, :) + &
2374 phase_act(ikk_start:ikk_end,:) * (integ12_t(ikk_start:ikk_end,:, imdim) * &
2375 (
m_two * this%veca(imdim, itstep) /
p_c - this%kcoords_sph(imdim, ikk_start:ikk_end,:)))
2377 spctramp_sph(ist, isdim, ik, ikk_start:ikk_end, :) = &
2378 spctramp_sph(ist, isdim, ik, ikk_start:ikk_end,:) + &
2379 phase_act(ikk_start:ikk_end,:) * integ22_t(ikk_start:ikk_end,:) *
m_zi
2385 safe_deallocate_a(s1_node)
2386 safe_deallocate_a(s2_node)
2387 safe_deallocate_a(s1_act)
2388 safe_deallocate_a(s2_act)
2390 safe_deallocate_a(integ11_t)
2391 safe_deallocate_a(integ12_t)
2392 safe_deallocate_a(integ21_t)
2393 safe_deallocate_a(integ22_t)
2396 this%conjgphase_prev =
m_z0
2398 if (ikk_start > 0)
then
2399 this%conjgphase_prev(ikk_start:ikk_end, :) = phase_act(ikk_start:ikk_end, :)
2401 safe_deallocate_a(phase_act)
2403 if (mesh%parallel_in_domains .and.
bitand(this%par_strategy, option__pes_flux_parallelization__pf_time) /= 0)
then
2404 call mesh%allreduce(this%conjgphase_prev)
2405 call mesh%allreduce(spctramp_sph)
2408 this%spctramp_sph(:, :, :, 1:this%nk, :) = this%spctramp_sph(:, :, :, 1:this%nk, :) &
2409 + spctramp_sph(:, :, :, 1:this%nk, :) * dt
2410 safe_deallocate_a(spctramp_sph)
2417 type(
mesh_t),
intent(in) :: mesh
2420 real(real64),
intent(in) :: border(:)
2421 real(real64),
intent(in) :: offset(:)
2422 real(real64),
intent(in) :: fc_ptdens
2424 integer,
allocatable :: which_surface(:)
2425 real(real64) :: xx(mesh%box%dim), dd, area, dS(mesh%box%dim, 2), factor
2426 integer :: mdim, imdim, idir, isp, pm,nface, idim, ndir, iu,iv, iuv(1:2)
2427 integer(int64) :: ip_global
2429 integer :: rankmin, nsurfaces
2431 integer :: ip_local, NN(mesh%box%dim, 2), idx(mesh%box%dim, 2)
2432 integer :: isp_end, isp_start, ifc, n_dir, nfaces, mindim
2433 real(real64) :: RSmax(2), RSmin(2), RS(2), dRS(2), weight
2445 safe_allocate(this%face_idx_range(1:mdim * 2, 1:2))
2446 safe_allocate(this%LLr(mdim, 1:2))
2447 safe_allocate(this%NN(mdim, 1:2))
2449 this%face_idx_range(:, :) = 0
2454 if (this%surf_interp)
then
2471 do ndir = mdim, mindim, -1
2474 if (idir == ndir) cycle
2475 area = area * border(idir) * factor
2478 npface = int(fc_ptdens * area)
2482 if (idir == ndir) cycle
2483 nn(ndir, idim) = int(
sqrt(npface * (border(idir) * factor)**2 / area))
2484 ds(ndir, idim) = border(idir) * factor / nn(ndir, idim)
2485 this%LLr(ndir, idim) = nn(ndir, idim) * ds(ndir, idim)
2486 idx(ndir, idim) = idir
2489 this%nsrfcpnts = this%nsrfcpnts + 2 * product(nn(ndir, 1:mdim - 1))
2492 this%NN(1:mdim, :) = nn(1:mdim, :)
2495 assert(this%nsrfcpnts > 0)
2498 safe_allocate(this%srfcnrml(1:mdim, 0:this%nsrfcpnts))
2499 safe_allocate(this%rcoords(1:mdim, 0:this%nsrfcpnts))
2501 this%srfcnrml(:, :) =
m_zero
2502 this%rcoords(:, :) =
m_zero
2507 do ndir = mdim, mindim, -1
2510 this%face_idx_range(ifc,1) = isp
2511 do iu = 1, nn(ndir,1)
2512 do iv = 1, nn(ndir,2)
2513 this%rcoords(ndir, isp) = border(ndir)
2514 this%srfcnrml(ndir, isp) = product(ds(ndir,1:mdim-1))
2517 this%rcoords(idx(ndir, idim), isp) = (-nn(ndir, idim) *
m_half -
m_half + iuv(idim)) * ds(ndir, idim)
2522 this%face_idx_range(ifc, 2) = isp-1
2527 this%face_idx_range(ifc, 1) = isp
2528 do iu = 1, nn(ndir, 1)
2529 do iv = 1, nn(ndir, 2)
2530 this%rcoords(ndir, isp) = -border(ndir)
2531 this%srfcnrml(ndir, isp) = -product(ds(ndir, 1:mdim - 1))
2534 this%rcoords(idx(ndir, idim), isp) = (-nn(ndir, idim) *
m_half -
m_half + iuv(idim)) * ds(ndir, idim)
2539 this%face_idx_range(ifc, 2) = isp-1
2544 do isp = 1, this%nsrfcpnts
2545 this%rcoords(1:mdim, isp) = mesh%coord_system%to_cartesian(this%rcoords(1:mdim, isp))
2552 if (this%surf_shape ==
pes_plane) nfaces = 2
2556 safe_allocate(which_surface(1:mesh%np_global))
2561 do ip_local = 1, mesh%np
2566 xx(1:mdim) = mesh%x(ip_local, 1:mdim) - offset(1:mdim)
2569 select case (abb%abtype)
2573 in_ab = abs(abb%mf(ip_local)) >
m_epsilon
2579 if (all(abs(xx(1:mdim)) <= border(1:mdim)) .and. .not. in_ab)
then
2583 dd = border(imdim) - xx(imdim)
2585 dd = border(imdim) - abs(xx(imdim))
2587 if (dd < mesh%spacing(imdim) /
m_two)
then
2588 nsurfaces = nsurfaces + 1
2589 which_surface(ip_global) = int(sign(
m_one, xx(imdim))) * imdim
2594 if (nsurfaces == 1)
then
2595 this%nsrfcpnts = this%nsrfcpnts + 1
2597 which_surface(ip_global) = 0
2603 if (mesh%parallel_in_domains)
then
2604 assert(mesh%np_global < huge(0_int32))
2605 call mesh%allreduce(this%nsrfcpnts)
2606 call mesh%allreduce(which_surface)
2609 safe_allocate(this%srfcpnt(1:this%nsrfcpnts))
2610 safe_allocate(this%srfcnrml(1:mdim, 0:this%nsrfcpnts))
2611 safe_allocate(this%rcoords(1:mdim, 0:this%nsrfcpnts))
2612 safe_allocate(this%rankmin(1:this%nsrfcpnts))
2617 this%face_idx_range(:,:) = 0
2621 do idir = mdim, 1, -1
2624 this%face_idx_range(nface, 1) = isp + 1
2626 do ip_global = 1, mesh%np_global
2627 if (abs(which_surface(ip_global)) == idir .and. sign(1, which_surface(ip_global)) == pm)
then
2631 this%rcoords(1:mdim, isp) = xx(1:mdim)
2634 this%rankmin(isp) = rankmin
2636 this%srfcnrml(idir, isp) = sign(1, which_surface(ip_global))
2639 if (imdim == idir) cycle
2640 this%srfcnrml(idir, isp) = this%srfcnrml(idir, isp) * mesh%spacing(imdim)
2645 this%face_idx_range(nface,2) = isp
2652 do ifc = 1, nint((nfaces + 0.5) / 2)
2653 isp_start = this%face_idx_range(ifc, 1)
2654 isp_end = this%face_idx_range(ifc, 2)
2659 if (abs(this%srfcnrml(idir, isp_start)) >=
m_epsilon) n_dir = idir
2666 if (idir == n_dir) cycle
2667 drs(idim)= mesh%spacing(idir)
2675 do isp = isp_start, isp_end
2677 xx = mesh%coord_system%from_cartesian(this%rcoords(1:mdim, isp))
2680 if (idir == n_dir) cycle
2682 if (rs(idim) < rsmin(idim)) rsmin(idim) = rs(idim)
2683 if (rs(idim) > rsmax(idim)) rsmax(idim) = rs(idim)
2689 do idir = 1, mdim - 1
2690 this%LLr(n_dir, idir) = rsmax(idir) - rsmin(idir) + drs(idir)
2691 if (drs(idir) >
m_zero) this%NN(n_dir, idir) = int(this%LLr(n_dir, idir) / drs(idir))
2699 if (this%anisotrpy_correction)
then
2702 do isp = 1, this%nsrfcpnts
2703 weight = sum(this%rcoords(1:mdim, isp) * this%srfcnrml(1:mdim, isp))
2704 weight = weight/sum(this%rcoords(1:mdim, isp)**2) / sum(this%srfcnrml(1:mdim, isp)**2)
2705 this%srfcnrml(1:mdim, isp) = this%srfcnrml(1:mdim, isp) * abs(weight)
2711 safe_deallocate_a(which_surface)
2719 type(
mesh_t),
intent(in) :: mesh
2720 integer,
intent(inout) :: nstepsthetar, nstepsphir
2723 integer :: isp, ith, iph
2724 real(real64) :: thetar, phir
2725 real(real64) :: weight, dthetar
2731 if (nstepsphir == 0) nstepsphir = 1
2733 if (nstepsthetar <= 1)
then
2737 dthetar =
m_pi / nstepsthetar
2738 this%nsrfcpnts = nstepsphir * (nstepsthetar - 1) + 2
2740 safe_allocate(this%srfcnrml(1:mdim, 0:this%nsrfcpnts))
2741 safe_allocate(this%rcoords(1:mdim, 0:this%nsrfcpnts))
2748 do ith = 0, nstepsthetar
2749 thetar = ith * dthetar
2751 if (ith == 0 .or. ith == nstepsthetar)
then
2754 weight = abs(
cos(thetar - dthetar /
m_two) -
cos(thetar + dthetar /
m_two)) &
2758 do iph = 0, nstepsphir - 1
2761 this%srfcnrml(1, isp) =
cos(phir) *
sin(thetar)
2762 if (mdim >= 2) this%srfcnrml(2, isp) =
sin(phir) *
sin(thetar)
2763 if (mdim == 3) this%srfcnrml(3, isp) =
cos(thetar)
2764 this%rcoords(1:mdim, isp) = this%radius * this%srfcnrml(1:mdim, isp)
2766 this%srfcnrml(1:mdim, isp) = this%radius**
m_two * weight * this%srfcnrml(1:mdim, isp)
2767 if (ith == 0 .or. ith == nstepsthetar)
exit
2779 integer,
intent(in) :: istart_global
2780 integer,
intent(in) :: iend_global
2781 integer,
intent(inout) :: istart
2782 integer,
intent(inout) :: iend
2783 type(mpi_comm),
intent(in) :: comm
2785#if defined(HAVE_MPI)
2786 integer,
allocatable :: dimrank(:)
2787 integer :: mpisize, mpirank, irest, irank
2793#if defined(HAVE_MPI)
2794 call mpi_comm_size(comm, mpisize,
mpi_err)
2795 call mpi_comm_rank(comm, mpirank,
mpi_err)
2797 safe_allocate(dimrank(0:mpisize-1))
2799 inumber = iend_global - istart_global + 1
2800 irest = mod(inumber, mpisize)
2801 do irank = 0, mpisize - 1
2803 dimrank(irank) = int(inumber / mpisize) + 1
2806 dimrank(irank) = int(inumber / mpisize)
2810 iend = istart_global + sum(dimrank(:mpirank)) - 1
2811 istart = iend - dimrank(mpirank) + 1
2813 if (istart > iend)
then
2818 safe_deallocate_a(dimrank)
2821 istart = istart_global
2829#include "pes_flux_out_inc.F90"
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
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_grad(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the gradient to a mesh function
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...
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)
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)
integer, public mpi_err
used to store return values of mpi calls
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_reciprocal_mesh_gen(this, namespace, space, st, kpoints, comm, post)
subroutine, public pes_flux_load(restart, this, st, ierr)
subroutine, public pes_flux_pmesh(this, namespace, dim, kpoints, ll, pmesh, idxZero, krng, Lp, Ekin)
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.
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
type(unit_system_t), public units_inp
the units systems for reading and writing
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.
The states_elec_t class contains all electronic wave functions.