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(:,:)
122 complex(real64),
allocatable :: bvk_phase(:,:)
123 complex(real64),
allocatable :: expkr(:,:,:,:)
124 complex(real64),
allocatable :: expkr_perp(:,:)
125 real(real64),
allocatable :: LLr(:,:)
126 integer,
allocatable :: NN(:,:)
127 integer,
allocatable :: Lkpuvz_inv(:,:,:)
137 complex(real64),
allocatable :: wf(:,:,:,:,:)
138 complex(real64),
allocatable :: gwf(:,:,:,:,:,:)
139 real(real64),
allocatable :: veca(:,:)
140 complex(real64),
allocatable :: conjgphase_prev(:,:)
141 complex(real64),
allocatable :: spctramp_cub(:,:,:,:)
142 complex(real64),
allocatable :: spctramp_sph(:,:,:,:,:)
144 integer,
public :: ll(3)
147 type(mesh_interpolation_t) :: interp
149 logical :: parallel_in_momentum
150 logical :: arpes_grid
151 logical :: surf_interp
152 logical :: use_symmetry
153 logical :: runtime_output
154 logical :: anisotrpy_correction
156 integer :: par_strategy
162 integer,
parameter :: &
167 integer,
parameter :: &
176 subroutine pes_flux_init(this, namespace, space, mesh, st, ext_partners, kpoints, abb, save_iter, max_iter)
185 integer,
intent(in) :: save_iter
186 integer,
intent(in) :: max_iter
189 real(real64) :: border(space%dim)
190 real(real64) :: offset(space%dim)
191 integer :: stst, stend, kptst, kptend, sdim, mdim, pdim
196 integer :: nstepsphir, nstepsthetar
198 integer :: default_shape
199 real(real64) :: fc_ptdens
201 integer :: par_strategy
202 logical :: use_symmetry
210 kptst = st%d%kpt%start
211 kptend = st%d%kpt%end
214 pdim = space%periodic_dim
216 this%surf_interp = .false.
220 if(
associated(lasers))
then
221 do il = 1, lasers%no_lasers
223 message(1) =
't-surff only works in velocity gauge.'
229 message(1) =
'Info: Calculating PES using t-surff technique.'
254 if (space%is_periodic())
then
256 else if (mdim <= 2)
then
257 default_shape = pes_cubic
259 select type (box => mesh%box)
261 default_shape = pes_cubic
265 call parse_variable(namespace,
'PES_Flux_Shape', default_shape, this%surf_shape)
270 message(1) =
'Spherical grid works only in 3d.'
283 if (this%surf_shape == pes_cubic)
then
284 call parse_variable(namespace,
'PES_Flux_AnisotropyCorrection', .false., this%anisotrpy_correction)
300 if (
parse_block(namespace,
'PES_Flux_Offset', blk) == 0)
then
322 if (this%surf_shape == pes_cubic .or. this%surf_shape ==
pes_plane)
then
342 if (
parse_block(namespace,
'PES_Flux_Lsize', blk) == 0)
then
347 border(1:mdim) = int(border(1:mdim) / mesh%spacing(1:mdim)) * mesh%spacing(1:mdim)
351 border(mdim) = mesh%box%bounding_box_l(mdim) *
m_half
352 if (space%is_periodic())
then
354 border(1:pdim)= mesh%box%bounding_box_l(1:pdim) *
m_two
355 call parse_variable(namespace,
'PES_Flux_Lsize', border(mdim), border(mdim))
357 border(mdim) =
floor(border(mdim) / mesh%spacing(mdim)) * mesh%spacing(mdim)
359 call parse_variable(namespace,
'PES_Flux_Lsize', border(mdim), border(mdim))
360 border(1:mdim - 1) = border(mdim)
361 border(1:mdim) =
floor(border(1:mdim) / mesh%spacing(1:mdim)) * mesh%spacing(1:mdim)
364 select type (box => mesh%box)
368 border(1:mdim) = box%half_length(1:mdim) *
m_half
370 call messages_write(
'PES_Flux_Lsize not specified. No default values available for this box shape.')
372 call messages_write(
'Specify the location of the parallelepiped with block PES_Flux_Lsize.')
375 call messages_write(
'PES_Flux_Lsize not specified. Using default values.')
389 this%surf_interp = .
true.
396 this%surf_interp = .
true.
409 select type (box => mesh%box)
411 this%radius = box%radius
413 this%radius = minval(box%half_length(1:mdim))
415 message(1) =
'PES_Flux_Radius not specified. No default values available for this box shape.'
416 message(2) =
'Specify the radius of the sphere with variable PES_Flux_Radius.'
419 message(1) =
'PES_Flux_Radius not specified. Using default values.'
431 call parse_variable(namespace,
'PES_Flux_StepsThetaR', 2 * this%lmax + 1, nstepsthetar)
442 call parse_variable(namespace,
'PES_Flux_StepsPhiR', 2 * this%lmax + 1, nstepsphir)
454 if (this%surf_shape == pes_cubic .or. this%surf_shape ==
pes_plane)
then
489 this%par_strategy = option__pes_flux_parallelization__pf_none
490 if (mesh%parallel_in_domains)
then
493 this%par_strategy = option__pes_flux_parallelization__pf_time &
494 + option__pes_flux_parallelization__pf_surface
496 this%par_strategy = option__pes_flux_parallelization__pf_surface
497 if (space%dim == 1) this%par_strategy = option__pes_flux_parallelization__pf_time
499 par_strategy = this%par_strategy
500 call parse_variable(namespace,
'PES_Flux_Parallelization', par_strategy, this%par_strategy)
508 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_surface) /= 0 .and. &
509 bitand(this%par_strategy, option__pes_flux_parallelization__pf_momentum) /= 0)
then
510 call messages_input_error(namespace,
'PES_Flux_Parallelization',
"Cannot combine pf_surface and pf_momentum")
513 write(
message(1),
'(a)')
'Input: [PES_Flux_Parallelization = '
514 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_none) /= 0)
then
517 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_time) /= 0)
then
520 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_momentum) /= 0)
then
523 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_surface) /= 0)
then
533 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_surface) /= 0)
then
535 call pes_flux_distribute(1, this%nsrfcpnts, this%nsrfcpnts_start, this%nsrfcpnts_end, mesh%mpi_grp%comm)
548 this%nsrfcpnts_start = 1
549 this%nsrfcpnts_end = this%nsrfcpnts
576 use_symmetry = .false.
577 if ((this%surf_shape == pes_cubic .or. this%surf_shape ==
pes_plane) &
579 if (this%surf_shape ==
pes_spherical .and. this%kgrid == pes_polar) use_symmetry = .
true.
580 call parse_variable(namespace,
'PES_Flux_UseSymmetries', use_symmetry, this%use_symmetry)
587 safe_allocate(this%ylm_r(0:this%lmax, -this%lmax:this%lmax, this%nsrfcpnts_start:this%nsrfcpnts_end))
590 if (this%nsrfcpnts_start > 0)
then
591 do isp = this%nsrfcpnts_start, this%nsrfcpnts_end
594 call ylmr_cmplx(this%rcoords(1:3, isp), ll, mm, this%ylm_r(ll, mm, isp))
595 this%ylm_r(ll, mm, isp) = conjg(this%ylm_r(ll, mm, isp))
615 call parse_variable(namespace,
'PES_Flux_RuntimeOutput', .false., this%runtime_output)
623 this%max_iter = max_iter
624 this%save_iter = save_iter
628 if (mesh%parallel_in_domains .and.
bitand(this%par_strategy, option__pes_flux_parallelization__pf_time) /= 0)
then
629 this%tdsteps = mesh%mpi_grp%size
636 safe_allocate(this%wf(stst:stend, 1:sdim, kptst:kptend, 0:this%nsrfcpnts, 1:this%tdsteps))
639 safe_allocate(this%gwf(stst:stend, 1:sdim, kptst:kptend, 0:this%nsrfcpnts, 1:this%tdsteps, 1:mdim))
642 safe_allocate(this%veca(1:mdim, 1:this%tdsteps))
646 safe_allocate(this%spctramp_sph(stst:stend, 1:sdim, kptst:kptend, 1:this%nk, 1:this%nstepsomegak))
647 this%spctramp_sph =
m_z0
649 safe_allocate(this%conjgphase_prev(1:this%nk, 1:this%nstepsomegak))
652 safe_allocate(this%spctramp_cub(stst:stend, 1:sdim, kptst:kptend, 1:this%nkpnts))
653 this%spctramp_cub =
m_z0
655 safe_allocate(this%conjgphase_prev(1:this%nkpnts, kptst:kptend))
659 this%conjgphase_prev =
m_z1
679 safe_deallocate_a(this%kcoords_sph)
680 safe_deallocate_a(this%ylm_k)
681 safe_deallocate_a(this%j_l)
682 safe_deallocate_a(this%ylm_r)
683 safe_deallocate_a(this%conjgphase_prev)
684 safe_deallocate_a(this%spctramp_sph)
686 safe_deallocate_a(this%kcoords_cub)
687 safe_deallocate_a(this%conjgphase_prev)
688 safe_deallocate_a(this%spctramp_cub)
690 if (.not. this%surf_interp)
then
691 safe_deallocate_a(this%srfcpnt)
693 safe_deallocate_a(this%rankmin)
695 safe_deallocate_a(this%face_idx_range)
696 safe_deallocate_a(this%LLr)
697 safe_deallocate_a(this%NN)
699 safe_deallocate_a(this%expkr)
700 safe_deallocate_a(this%expkr_perp)
701 safe_deallocate_a(this%bvk_phase)
703 safe_deallocate_a(this%Lkpuvz_inv)
707 safe_deallocate_a(this%klinear)
709 safe_deallocate_a(this%srfcnrml)
710 safe_deallocate_a(this%rcoords)
712 safe_deallocate_a(this%wf)
713 safe_deallocate_a(this%gwf)
714 safe_deallocate_a(this%veca)
723 class(
space_t),
intent(in) :: space
726 type(mpi_comm),
intent(in) :: comm
727 logical,
optional,
intent(in) :: post
729 integer :: mdim, pdim
730 integer :: kptst, kptend
732 integer :: ll, mm, idim, idir
733 integer :: ikk, ith, iph, iomk,ie, ik1, ik2, ik3, kgrid_block_dim
734 real(real64) :: kmax(space%dim), kmin(space%dim), kact, thetak, phik
737 real(real64) :: emin, emax, de , kvec(1:3), xx(3)
738 integer :: nkp_out, nkmin, nkmax
741 real(real64),
allocatable :: gpoints(:,:), gpoints_reduced(:,:)
742 real(real64) :: dk(1:3), kpoint(1:3), dthetak, dphik
743 logical :: use_enegy_grid, arpes_grid
747 kptst = st%d%kpt%start
748 kptend = st%d%kpt%end
750 pdim = space%periodic_dim
772 select case (this%surf_shape)
779 if (mdim == 1) kgrid = pes_polar
786 call parse_variable(namespace,
'PES_Flux_Momenutum_Grid', kgrid, this%kgrid)
799 if (space%is_periodic())
then
807 if (this%surf_shape == pes_cubic)
then
808 if (space%is_periodic())
then
829 use_enegy_grid = .false.
831 if (
parse_block(namespace,
'PES_Flux_EnergyGrid', blk) == 0)
then
842 use_enegy_grid = .
true.
864 call parse_variable(namespace,
'PES_Flux_ARPES_grid', .false., this%arpes_grid)
865 if (.not. use_enegy_grid .or. this%arpes_grid)
then
876 if (
parse_block(namespace,
'PES_Flux_Kmax', blk) == 0)
then
881 kgrid_block_dim = mdim
883 message(1) =
'Wrong block format for PES_Flux_Kmax and non-cartesian grid'
900 if (
parse_block(namespace,
'PES_Flux_Kmin', blk) == 0)
then
905 kgrid_block_dim = mdim
907 message(1) =
'Wrong block format for PES_Flux_Kmin and non-cartesian grid'
923 call parse_variable(namespace,
'PES_Flux_DeltaK', 0.02_real64, this%dk)
928 do idim = 1, kgrid_block_dim
929 if (kgrid_block_dim == 1)
then
948 if (this%kgrid == pes_polar)
then
971 this%nstepsthetak = 45
973 if (
parse_block(namespace,
'PES_Flux_ThetaK', blk) == 0)
then
979 if (this%thetak_rng(idim) <
m_zero .or. this%thetak_rng(idim) >
m_pi)
then
993 call parse_variable(namespace,
'PES_Flux_StepsThetaK', 45, this%nstepsthetak)
1018 this%nstepsphik = 90
1020 if (mdim == 1) this%phik_rng(1:2) = (/
m_pi,
m_zero/)
1021 if (
parse_block(namespace,
'PES_Flux_PhiK', blk) == 0)
then
1027 if (this%phik_rng(idim) <
m_zero .or. this%phik_rng(idim) >
m_two *
m_pi)
then
1042 call parse_variable(namespace,
'PES_Flux_StepsPhiK', 90, this%nstepsphik)
1044 if (this%nstepsphik == 0) this%nstepsphik = 1
1049 if (mdim == 3) dthetak = abs(this%thetak_rng(2) - this%thetak_rng(1)) / (this%nstepsthetak)
1050 dphik = abs(this%phik_rng(2) - this%phik_rng(1)) / (this%nstepsphik)
1055 this%nstepsthetak = 0
1057 this%nstepsomegak = this%nstepsphik
1060 this%nstepsthetak = 0
1061 this%nstepsomegak = this%nstepsphik
1064 if (this%nstepsthetak <= 1)
then
1066 this%nstepsthetak = 1
1070 do ith = 0, this%nstepsthetak
1071 thetak = ith * dthetak + this%thetak_rng(1)
1072 do iph = 0, this%nstepsphik - 1
1073 phik = iph * dphik + this%phik_rng(1)
1078 this%nstepsomegak = iomk
1085 write(
message(1),
'(a)')
"Polar momentum grid:"
1088 write(
message(1),
'(a,f12.6,a,f12.6,a, i6)') &
1089 " Theta = (", this%thetak_rng(1),
",",this%thetak_rng(2), &
1090 "); n = ", this%nstepsthetak
1093 write(
message(1),
'(a,f12.6,a,f12.6,a, i6)') &
1094 " Phi = (", this%phik_rng(1),
",",this%phik_rng(2), &
1095 "); n = ", this%nstepsphik
1100 if (use_enegy_grid)
then
1101 this%nk = nint(abs(emax - emin) / de)
1103 this%nk = nint(abs(kmax(1) - kmin(1)) / this%dk)
1105 this%nkpnts = this%nstepsomegak * this%nk
1107 this%ll(1) = this%nk
1108 this%ll(2) = this%nstepsphik
1109 this%ll(3) = this%nstepsthetak
1110 this%ll(mdim+1:3) = 1
1112 safe_allocate(this%klinear(1:this%nk, 1))
1118 dk(1:mdim) =
m_one/kpoints%nik_axis(1:mdim)
1120 this%arpes_grid = .false.
1121 if (space%is_periodic())
then
1132 arpes_grid = kpoints%have_zero_weight_path()
1133 call parse_variable(namespace,
'PES_Flux_ARPES_grid', arpes_grid, this%arpes_grid)
1142 if (kpoints%have_zero_weight_path())
then
1144 if (this%arpes_grid)
then
1145 nkmax =
floor(emax / de)
1146 nkmin =
floor(emin / de)
1149 nkmax =
floor(kmax(mdim) / this%dk)
1150 nkmin =
floor(kmin(mdim) / this%dk)
1154 this%ll(mdim) = abs(nkmax - nkmin) + 1
1156 this%nk = this%ll(mdim)
1161 if (.not. this%arpes_grid)
then
1162 this%ll(1:mdim) =
floor(abs(kmax(1:mdim) - kmin(1:mdim))/this%dk) + 1
1163 this%nk = maxval(this%ll(1:mdim))
1167 nkmax =
floor(emax / de)
1168 nkmin =
floor(emin / de)
1169 this%nk = abs(nkmax - nkmin) + 1
1171 this%ll(1:pdim) =
floor(abs(kmax(1:pdim) - kmin(1:pdim))/this%dk) + 1
1172 this%ll(mdim) = this%nk
1176 safe_allocate(this%klinear(1:maxval(this%ll(1:mdim)), 1:mdim))
1182 this%nkpnts = product(this%ll(1:mdim))
1191 this%parallel_in_momentum = .false.
1194 select case (this%kgrid)
1198 if (use_enegy_grid)
then
1200 this%klinear(ie, 1) =
sqrt(
m_two * (ie * de + emin))
1204 this%klinear(ikk, 1) = ikk * this%dk + kmin(1)
1218 if ((this%nk_end - this%nk_start + 1) < this%nk) this%parallel_in_momentum = .
true.
1219 call pes_flux_distribute(1, this%nstepsomegak, this%nstepsomegak_start, this%nstepsomegak_end, comm)
1231 safe_allocate(this%j_l(0:this%lmax, this%nk_start:this%nk_end))
1234 safe_allocate(this%kcoords_sph(1:3, this%nk_start:this%nk_end, 1:this%nstepsomegak))
1235 this%kcoords_sph =
m_zero
1237 safe_allocate(this%ylm_k(0:this%lmax, - this%lmax:this%lmax, this%nstepsomegak_start:this%nstepsomegak_end))
1242 do ith = 0, this%nstepsthetak
1243 thetak = ith * dthetak + this%thetak_rng(1)
1244 do iph = 0, this%nstepsphik - 1
1245 phik = iph * dphik + this%phik_rng(1)
1247 if (iomk >= this%nstepsomegak_start .and. iomk <= this%nstepsomegak_end)
then
1248 do ll = 0, this%lmax
1250 xx(1) =
cos(phik) *
sin(thetak)
1251 xx(2) =
sin(phik) *
sin(thetak)
1253 call ylmr_cmplx(xx, ll, mm, this%ylm_k(ll, mm, iomk))
1257 if (this%nk_start > 0)
then
1258 this%kcoords_sph(1, this%nk_start:this%nk_end, iomk) =
cos(phik) *
sin(thetak)
1259 this%kcoords_sph(2, this%nk_start:this%nk_end, iomk) =
sin(phik) *
sin(thetak)
1260 this%kcoords_sph(3, this%nk_start:this%nk_end, iomk) =
cos(thetak)
1266 if (this%nk_start > 0)
then
1268 do ikk = this%nk_start, this%nk_end
1269 kact = this%klinear(ikk,1)
1270 do ll = 0, this%lmax
1274 this%kcoords_sph(:, ikk, :) = kact * this%kcoords_sph(:, ikk, :)
1283 this%nkpnts_start = 1
1284 this%nkpnts_end = this%nkpnts
1287 safe_allocate(this%kcoords_cub(1:mdim, this%nkpnts_start:this%nkpnts_end, 1))
1289 this%kcoords_cub =
m_zero
1294 do ikk = -this%nk, this%nk
1297 kact = sign(1,ikk) * this%klinear(abs(ikk), 1)
1298 this%kcoords_cub(1, ikp, 1) = kact
1306 do ith = 0, this%nstepsthetak
1307 if (mdim == 3) thetak = ith * dthetak + this%thetak_rng(1)
1308 do iph = 0, this%nstepsphik - 1
1310 phik = iph * dphik + this%phik_rng(1)
1311 kact = this%klinear(ikk,1)
1312 this%kcoords_cub(1, ikp,1) = kact *
cos(phik) *
sin(thetak)
1313 this%kcoords_cub(2, ikp,1) = kact *
sin(phik) *
sin(thetak)
1314 if (mdim == 3) this%kcoords_cub(3, ikp,1) = kact *
cos(thetak)
1325 this%nkpnts_start = 1
1326 this%nkpnts_end = this%nkpnts
1332 if (kpoints%have_zero_weight_path())
then
1336 safe_allocate(this%kcoords_cub(1:mdim, this%nkpnts_start:this%nkpnts_end, kptst:kptend))
1339 do ikpt = kptst, kptend
1341 do ikk = nkmin, nkmax
1343 kvec(1:mdim) = - kpoints%get_point(ikpt)
1351 safe_allocate(this%kcoords_cub(1:mdim, this%nkpnts_start:this%nkpnts_end, 1))
1353 safe_allocate(this%Lkpuvz_inv(1:this%ll(1), 1:this%ll(2), 1:this%ll(3)))
1356 do ikk = 1, this%ll(idir)
1357 this%klinear(ikk, idir) = ikk * this%dk + kmin(idir)
1362 if (.not. this%arpes_grid)
then
1369 do ik3 = 1, this%ll(3)
1370 if (mdim>2) kvec(3) = this%klinear(ik3, 3)
1371 do ik2 = 1, this%ll(2)
1372 if (mdim>1) kvec(2) = this%klinear(ik2, 2)
1373 do ik1 = 1, this%ll(1)
1375 kvec(1) = this%klinear(ik1, 1)
1376 this%kcoords_cub(1:mdim, ikp, ikpt) = kvec(1:mdim)
1377 this%Lkpuvz_inv(ik1, ik2, ik3) = ikp
1389 do ikk = nkmin, nkmax
1395 do ik1 = 1, this%ll(1)
1396 kvec(1) = this%klinear(ik1,1)
1397 kvec(1:pdim) = matmul(kpoints%latt%klattice_primitive(1:pdim, 1:pdim), kvec(1:pdim))
1403 do ik2 = 1, this%ll(2)
1404 do ik1 = 1, this%ll(1)
1405 kvec(1:2) = (/this%klinear(ik1,1), this%klinear(ik2,2)/)
1406 kvec(1:pdim) = matmul(kpoints%latt%klattice_primitive(1:pdim, 1:pdim), kvec(1:pdim))
1409 this%Lkpuvz_inv(ik1, ik2, ikk - nkmin + 1) = ikp
1462 if (this%arpes_grid)
then
1471 safe_deallocate_a(gpoints)
1472 safe_deallocate_a(gpoints_reduced)
1493 this%ktransf(:,:) =
m_zero
1495 this%ktransf(idim,idim) =
m_one
1498 if (
parse_block(namespace,
'PES_Flux_GridTransformMatrix', blk) == 0)
then
1506 write(
message(1),
'(a)')
'Momentum grid transformation matrix :'
1507 do idir = 1, space%dim
1508 write(
message(1 + idir),
'(9f12.6)') ( this%ktransf(idim, idir), idim = 1, mdim)
1517 do ith = 0, this%nstepsthetak
1518 do iph = 0, this%nstepsphik - 1
1520 do ikk = this%nk_start, this%nk_end
1521 kvec(1:mdim) = this%kcoords_sph(1:mdim, ikk, iomk)
1522 this%kcoords_sph(1:mdim, ikk, iomk) = matmul(this%ktransf(1:mdim, 1:mdim), kvec(1:mdim))
1524 if (ith == 0 .or. ith == this%nstepsthetak)
exit
1530 do ikpt = kptst, kptend + 1
1531 if (ikpt == kptend + 1)
then
1532 kpoint(1:space%dim) =
m_zero
1534 kpoint(1:space%dim) = kpoints%get_point(ikpt)
1537 do ikp = 1, this%nkpnts
1539 kvec(1:mdim) = this%kcoords_cub(1:mdim, ikp, ikpt) - kpoint(1:mdim)
1540 this%kcoords_cub(1:mdim, ikp, ikpt) = matmul(this%ktransf(1:mdim, 1:mdim), kvec(1:mdim)) &
1562 real(real64) :: kpar(1:pdim), val
1567 if (ikk /= 0) sign= ikk / abs(ikk)
1569 kpar(1:pdim) = kvec(1:pdim)
1570 val = abs(ikk) * de *
m_two - sum(kpar(1:pdim)**2)
1572 kvec(mdim) = sign *
sqrt(val)
1575 kvec(mdim) =
sqrt(val)
1576 nkp_out = nkp_out + 1
1579 this%kcoords_cub(1:mdim, ikp, ikpt) = kvec(1:mdim)
1589 subroutine pes_flux_calc(this, space, mesh, st, der, ext_partners, kpoints, iter, dt, stopping)
1591 class(
space_t),
intent(in) :: space
1592 type(
mesh_t),
intent(in) :: mesh
1597 integer,
intent(in) :: iter
1598 real(real64),
intent(in) :: dt
1599 logical,
intent(in) :: stopping
1601 integer :: stst, stend, kptst, kptend, sdim, mdim
1602 integer :: ist, ik, isdim, imdim
1604 integer :: il, ip_local
1605 complex(real64),
allocatable :: gpsi(:,:), psi(:)
1606 complex(real64),
allocatable :: interp_values(:)
1607 logical :: contains_isp
1608 real(real64) :: kpoint(1:3)
1609 complex(real64),
allocatable :: tmp_array(:)
1619 kptst = st%d%kpt%start
1620 kptend = st%d%kpt%end
1624 safe_allocate(psi(1:mesh%np_part))
1625 safe_allocate(gpsi(1:mesh%np_part, 1:mdim))
1627 if (this%surf_interp)
then
1628 safe_allocate(interp_values(1:this%nsrfcpnts))
1631 this%itstep = this%itstep + 1
1635 if(
associated(lasers))
then
1636 do il = 1, lasers%no_lasers
1637 call laser_field(lasers%lasers(il), this%veca(1:mdim, this%itstep), iter*dt)
1640 this%veca(:, this%itstep) = - this%veca(:, this%itstep)
1645 if(mesh%parallel_in_domains)
then
1646 safe_allocate(tmp_array(1:this%nsrfcpnts))
1650 do ik = kptst, kptend
1651 do ist = stst, stend
1660 kpoint(1:mdim) = kpoints%get_point(st%d%get_kpoint_index(ik))
1663 do ip = 1, mesh%np_part
1664 psi(ip) =
exp(-
m_zi * sum(mesh%x(ip, 1:mdim) * kpoint(1:mdim))) * psi(ip)
1671 if (this%surf_interp)
then
1673 this%rcoords(1:mdim, 1:this%nsrfcpnts), interp_values(1:this%nsrfcpnts))
1674 this%wf(ist, isdim, ik, 1:this%nsrfcpnts, this%itstep) = st%occ(ist, ik) * interp_values(1:this%nsrfcpnts)
1677 this%rcoords(1:mdim, 1:this%nsrfcpnts), interp_values(1:this%nsrfcpnts))
1678 this%gwf(ist, isdim, ik, 1:this%nsrfcpnts, this%itstep, imdim) = st%occ(ist, ik) * interp_values(1:this%nsrfcpnts)
1683 contains_isp = .
true.
1684 do isp = 1, this%nsrfcpnts
1685 if (mesh%parallel_in_domains)
then
1686 if (mesh%mpi_grp%rank == this%rankmin(isp))
then
1687 contains_isp = .
true.
1689 contains_isp = .false.
1693 if (contains_isp)
then
1694 ip_local = this%srfcpnt(isp)
1695 this%wf(ist, isdim, ik, isp, this%itstep) = st%occ(ist, ik) * psi(ip_local)
1696 this%gwf(ist, isdim, ik, isp, this%itstep, 1:mdim) = &
1697 st%occ(ist, ik) * gpsi(ip_local, 1:mdim)
1700 if (mesh%parallel_in_domains)
then
1702 tmp_array = this%wf(ist, isdim, ik, 1:this%nsrfcpnts, this%itstep)
1703 call mesh%allreduce(tmp_array)
1704 this%wf(ist, isdim, ik, 1:this%nsrfcpnts, this%itstep) = tmp_array
1707 tmp_array = this%gwf(ist, isdim, ik, 1:this%nsrfcpnts, this%itstep, imdim)
1708 call mesh%allreduce(tmp_array)
1709 this%gwf(ist, isdim, ik, 1:this%nsrfcpnts, this%itstep, imdim) = tmp_array
1717 if(mesh%parallel_in_domains)
then
1718 safe_deallocate_a(tmp_array)
1721 safe_deallocate_a(psi)
1722 safe_deallocate_a(gpsi)
1724 if (this%itstep == this%tdsteps .or. mod(iter, this%save_iter) == 0 .or. iter == this%max_iter .or. stopping)
then
1725 if (this%surf_shape == pes_cubic .or. this%surf_shape ==
pes_plane)
then
1748 class(
space_t),
intent(in) :: space
1749 type(
mesh_t),
intent(in) :: mesh
1753 integer :: kptst, kptend, mdim
1754 integer :: ik, j1, j2, jvec(1:2)
1755 integer :: isp, ikp, ikp_start, ikp_end
1758 integer :: idir, pdim, nfaces, ifc, n_dir
1759 complex(real64) :: tmp
1760 real(real64) :: kpoint(1:3), vec(1:3), lvec(1:3)
1764 if (kpoints%have_zero_weight_path())
then
1765 kptst = st%d%kpt%start
1766 kptend = st%d%kpt%end
1773 pdim = space%periodic_dim
1775 ikp_start = this%nkpnts_start
1776 ikp_end = this%nkpnts_end
1782 this%srfcnrml(:, 1:this%nsrfcpnts) = this%srfcnrml(:, 1:this%nsrfcpnts) * mesh%coord_system%surface_element(3)
1785 if (.not. this%use_symmetry .or. kpoints%have_zero_weight_path())
then
1787 safe_allocate(this%expkr(1:this%nsrfcpnts,ikp_start:ikp_end,kptst:kptend,1))
1789 do ik = kptst, kptend
1790 do ikp = ikp_start, ikp_end
1791 do isp = 1, this%nsrfcpnts
1792 this%expkr(isp,ikp,ik,1) =
exp(-
m_zi * sum(this%rcoords(1:mdim,isp) &
1793 * this%kcoords_cub(1:mdim, ikp, ik))) &
1805 if (this%surf_shape ==
pes_plane) nfaces = 1
1808 safe_allocate(this%expkr(1:this%nsrfcpnts,maxval(this%ll(1:mdim)),kptst:kptend,1:mdim))
1809 this%expkr(:,:,:,:) =
m_z1
1811 do ik = kptst, kptend
1813 do ikp = 1, this%ll(idir)
1814 do isp = 1, this%nsrfcpnts
1815 this%expkr(isp,ikp,ik,idir) =
exp(-
m_zi * this%rcoords(idir,isp) &
1816 * this%klinear(ikp, idir)) &
1824 safe_allocate(this%expkr_perp(1:maxval(this%ll(1:mdim)), 1:nfaces))
1825 this%expkr_perp(:,:) =
m_z1
1828 if (this%face_idx_range(ifc, 1) < 0) cycle
1829 isp = this%face_idx_range(ifc, 1)
1831 if (abs(this%srfcnrml(idir, isp)) >=
m_epsilon) n_dir = idir
1834 do ikp = 1, this%ll(n_dir)
1835 this%expkr_perp(ikp, ifc) =
exp(-
m_zi * this%rcoords(n_dir,isp) &
1836 * this%klinear(ikp, n_dir)) &
1846 if (space%is_periodic())
then
1848 safe_allocate(this%bvk_phase(ikp_start:ikp_end,st%d%kpt%start:st%d%kpt%end))
1850 this%bvk_phase(:,:) =
m_z0
1853 do ik = st%d%kpt%start, st%d%kpt%end
1854 kpoint(1:mdim) = kpoints%get_point(ik)
1855 if (kpoints%have_zero_weight_path())
then
1860 do ikp = ikp_start, ikp_end
1861 vec(1:pdim) = this%kcoords_cub(1:pdim, ikp, ik_map) + kpoint(1:pdim)
1862 do j1 = 0, kpoints%nik_axis(1) - 1
1863 do j2 = 0, kpoints%nik_axis(2) - 1
1864 jvec(1:2)=(/j1, j2/)
1865 lvec(1:pdim) = matmul(kpoints%latt%rlattice(1:pdim, 1:2), jvec(1:2))
1866 tmp = sum(lvec(1:pdim) * vec(1:pdim))
1867 this%bvk_phase(ikp, ik) = this%bvk_phase(ikp,ik) &
1875 this%bvk_phase(:,:) = this%bvk_phase(:,:) *
m_one / product(kpoints%nik_axis(1:pdim))
1897 pure function get_ikp(this, ikpu, ikpv, ikpz, n_dir)
result(ikp)
1899 integer,
intent(in) :: ikpu
1900 integer,
intent(in) :: ikpv
1901 integer,
intent(in) :: ikpz
1902 integer,
intent(in) :: n_dir
1907 ikp = this%Lkpuvz_inv(ikpz, ikpu, ikpv)
1909 ikp = this%Lkpuvz_inv(ikpu, ikpz, ikpv)
1911 ikp = this%Lkpuvz_inv(ikpu, ikpv, ikpz)
1923 type(
mesh_t),
intent(in) :: mesh
1926 integer :: mdim, nfaces, ifc, ifp_start, ifp_end
1933 if (this%surf_shape ==
pes_plane) nfaces = 1
1937 ifp_start = this%face_idx_range(ifc, 1)
1938 ifp_end = this%face_idx_range(ifc, 2)
1941 if (this%nsrfcpnts_start <= ifp_end)
then
1943 if (this%nsrfcpnts_start >= ifp_start)
then
1944 if (this%nsrfcpnts_start <= ifp_end)
then
1945 this%face_idx_range(ifc, 1) = this%nsrfcpnts_start
1947 this%face_idx_range(ifc, 1:2) = -1
1951 if (this%nsrfcpnts_end <= ifp_end)
then
1952 if (this%nsrfcpnts_end >= ifp_start)
then
1953 this%face_idx_range(ifc, 2) = this%nsrfcpnts_end
1955 this%face_idx_range(ifc, 1:2) = -1
1961 this%face_idx_range(ifc, 1:2) = -1
1980 class(
space_t),
intent(in) :: space
1981 type(
mesh_t),
intent(in) :: mesh
1984 real(real64),
intent(in) :: dt
1986 integer :: stst, stend, kptst, kptend, sdim, mdim
1987 integer :: ist, ik, isdim, imdim, ik_map
1988 integer :: ikp, itstep
1989 integer :: idir, n_dir, nfaces
1990 complex(real64),
allocatable :: jk_cub(:,:,:,:), spctramp_cub(:,:,:,:)
1991 integer :: ikp_start, ikp_end, isp_start, isp_end
1992 real(real64) :: vec, kpoint(1:3)
1994 complex(real64),
allocatable :: wfpw(:), gwfpw(:)
1995 complex(real64),
allocatable :: phase(:,:),vphase(:,:)
1997 integer :: tdstep_on_node
2001 integer :: ikpu, ikpv, ikpz, dir_on_face(1:2)
2002 complex(real64) :: face_int_gwf, face_int_wf
2011 call messages_write(
"Debug: calculating pes_flux cub surface integral (accelerated direct expression)")
2016 if (
bitand(this%par_strategy, option__pes_flux_parallelization__pf_time) /= 0)
then
2017 if (mesh%parallel_in_domains) tdstep_on_node = mesh%mpi_grp%rank + 1
2022 kptst = st%d%kpt%start
2023 kptend = st%d%kpt%end
2027 ikp_start = this%nkpnts_start
2028 ikp_end = this%nkpnts_end
2032 safe_allocate(jk_cub(stst:stend, 1:sdim, kptst:kptend, ikp_start:ikp_end))
2033 safe_allocate(spctramp_cub(stst:stend, 1:sdim, kptst:kptend, ikp_start:ikp_end))
2037 safe_allocate(vphase(ikp_start:ikp_end, kptst:kptend))
2038 safe_allocate(phase(ikp_start:ikp_end, kptst:kptend))
2044 if (this%surf_shape ==
pes_plane) nfaces = 1
2046 safe_allocate( wfpw(ikp_start:ikp_end))
2047 safe_allocate(gwfpw(ikp_start:ikp_end))
2052 if (this%face_idx_range(ifc, 1)<0) cycle
2055 isp_start = this%face_idx_range(ifc, 1)
2056 isp_end = this%face_idx_range(ifc, 2)
2059 nfp = isp_end - isp_start + 1
2067 if (abs(this%srfcnrml(idir, isp_start)) >=
m_epsilon)
then
2070 dir_on_face(imdim)=idir
2077 vphase(ikp_start:ikp_end,:) = this%conjgphase_prev(ikp_start:ikp_end,:)
2079 jk_cub(:, :, :, :) =
m_z0
2081 do itstep = 1, this%itstep
2083 do ik = kptst, kptend
2085 if (kpoints%have_zero_weight_path())
then
2091 kpoint(1:mdim) = kpoints%get_point(ik)
2092 do ikp = ikp_start, ikp_end
2093 vec = sum((this%kcoords_cub(1:mdim, ikp, ik_map) - this%veca(1:mdim, itstep) /
p_c)**2)
2094 vphase(ikp, ik) = vphase(ikp, ik) *
exp(
m_zi * vec * dt /
m_two)
2097 if (space%is_periodic())
then
2098 phase(ikp, ik) = vphase(ikp, ik) * this%bvk_phase(ikp,ik)
2100 phase(ikp, ik) = vphase(ikp, ik)
2105 if (itstep /= tdstep_on_node) cycle
2107 do ist = stst, stend
2112 if (.not. this%use_symmetry .or. kpoints%have_zero_weight_path())
then
2114 do ikp = ikp_start , ikp_end
2117 sum(this%gwf(ist, isdim, ik, isp_start:isp_end, itstep, n_dir) &
2118 * this%expkr(isp_start:isp_end, ikp, ik_map, 1) &
2119 * this%srfcnrml(n_dir, isp_start:isp_end))
2123 sum(this%wf(ist, isdim, ik, isp_start:isp_end, itstep) &
2124 * this%expkr(isp_start:isp_end, ikp,ik_map, 1) &
2125 * this%srfcnrml(n_dir, isp_start:isp_end))
2130 do ikpu = 1, this%ll(dir_on_face(1))
2131 do ikpv = 1, this%ll(dir_on_face(2))
2134 face_int_gwf = sum(this%gwf(ist, isdim, ik, isp_start:isp_end, itstep, n_dir) &
2135 * this%expkr(isp_start:isp_end, ikpu, ik_map, dir_on_face(1)) &
2136 * this%expkr(isp_start:isp_end, ikpv, ik_map, dir_on_face(2)) &
2137 * this%srfcnrml(n_dir, isp_start:isp_end))
2139 face_int_wf = sum(this%wf(ist, isdim, ik, isp_start:isp_end, itstep) &
2140 * this%expkr(isp_start:isp_end, ikpu, ik_map, dir_on_face(1)) &
2141 * this%expkr(isp_start:isp_end, ikpv, ik_map, dir_on_face(2)) &
2142 * this%srfcnrml(n_dir, isp_start:isp_end))
2144 do ikpz = 1, this%ll(n_dir)
2146 gwfpw(
get_ikp(this, ikpu, ikpv, ikpz, n_dir)) = face_int_gwf &
2147 * this%expkr_perp(ikpz, ifc)
2148 wfpw(
get_ikp(this, ikpu, ikpv, ikpz, n_dir)) = face_int_wf &
2149 * this%expkr_perp(ikpz, ifc)
2161 jk_cub(ist, isdim, ik, ikp_start:ikp_end) = jk_cub(ist, isdim, ik, ikp_start:ikp_end) + &
2162 phase(ikp_start:ikp_end, ik) * (wfpw(ikp_start:ikp_end) * &
2163 (
m_two * this%veca(n_dir, itstep) /
p_c - this%kcoords_cub(n_dir, ikp_start:ikp_end, ik_map)) + &
2164 m_zi * gwfpw(ikp_start:ikp_end))
2174 spctramp_cub(:,:,:,:) = spctramp_cub(:,:,:,:) + jk_cub(:,:,:,:) *
m_half
2180 this%conjgphase_prev(ikp_start:ikp_end, :) = vphase(ikp_start:ikp_end, :)
2183 if (mesh%parallel_in_domains .and.(
bitand(this%par_strategy, option__pes_flux_parallelization__pf_time) /= 0 &
2184 .or.
bitand(this%par_strategy, option__pes_flux_parallelization__pf_surface) /= 0))
then
2185 call mesh%allreduce(spctramp_cub)
2190 this%spctramp_cub = this%spctramp_cub + spctramp_cub * dt
2192 safe_deallocate_a(gwfpw)
2193 safe_deallocate_a(wfpw)
2195 safe_deallocate_a(jk_cub)
2196 safe_deallocate_a(spctramp_cub)
2197 safe_deallocate_a(phase)
2198 safe_deallocate_a(vphase)
2210 type(
mesh_t),
intent(in) :: mesh
2212 real(real64),
intent(in) :: dt
2214 integer :: stst, stend, kptst, kptend, sdim
2215 integer :: ist, ik, isdim, imdim
2216 integer :: itstep, lmax
2218 complex(real64),
allocatable :: s1_node(:,:,:,:,:,:), s1_act(:,:,:)
2219 complex(real64),
allocatable :: s2_node(:,:,:,:,:), s2_act(:,:)
2220 complex(real64),
allocatable :: integ11_t(:,:), integ12_t(:,:,:)
2221 complex(real64),
allocatable :: integ21_t(:), integ22_t(:,:)
2222 complex(real64),
allocatable :: spctramp_sph(:,:,:,:,:)
2223 integer :: ikk, ikk_start, ikk_end
2224 integer :: isp_start, isp_end
2225 integer :: iomk, iomk_start, iomk_end
2226 complex(real64),
allocatable :: phase_act(:,:)
2228 integer :: tdstep_on_node
2234 call messages_write(
"Debug: calculating pes_flux sph surface integral")
2238 if (mesh%parallel_in_domains) tdstep_on_node = mesh%mpi_grp%rank + 1
2242 kptst = st%d%kpt%start
2243 kptend = st%d%kpt%end
2247 ikk_start = this%nk_start
2248 ikk_end = this%nk_end
2249 isp_start = this%nsrfcpnts_start
2250 isp_end = this%nsrfcpnts_end
2251 iomk_start = this%nstepsomegak_start
2252 iomk_end = this%nstepsomegak_end
2255 safe_allocate(s1_node(stst:stend, 1:sdim, kptst:kptend, 0:lmax, -lmax:lmax, 1:3))
2256 safe_allocate(s2_node(stst:stend, 1:sdim, kptst:kptend, 0:lmax, -lmax:lmax))
2258 safe_allocate(s1_act(0:lmax, -lmax:lmax, 1:3))
2259 safe_allocate(s2_act(0:lmax, -lmax:lmax))
2261 do itstep = 1, this%itstep
2263 do ik = kptst, kptend
2264 do ist = stst, stend
2273 s1_act(ll, mm, imdim) = &
2274 sum(this%ylm_r(ll, mm, isp_start:isp_end) * this%srfcnrml(imdim, isp_start:isp_end) * &
2275 this%wf(ist, isdim, ik, isp_start:isp_end, itstep))
2277 s2_act(ll, mm) = s2_act(ll, mm) + &
2278 sum(this%ylm_r(ll, mm, isp_start:isp_end) * this%srfcnrml(imdim, isp_start:isp_end) * &
2279 this%gwf(ist, isdim, ik, isp_start:isp_end, itstep, imdim))
2284 if (mesh%parallel_in_domains .and.
bitand(this%par_strategy, option__pes_flux_parallelization__pf_surface) /= 0)
then
2285 call mesh%allreduce(s1_act)
2286 call mesh%allreduce(s2_act)
2289 if (itstep == tdstep_on_node)
then
2290 s1_node(ist, isdim, ik, :, :, :) = s1_act(:, :, :)
2291 s2_node(ist, isdim, ik, :, :) = s2_act(:, :)
2300 safe_allocate(integ11_t(0:this%nstepsomegak, 1:3))
2301 safe_allocate(integ21_t(0:this%nstepsomegak))
2302 safe_allocate(integ12_t(ikk_start:ikk_end, 1:this%nstepsomegak, 1:3))
2303 safe_allocate(integ22_t(ikk_start:ikk_end, 1:this%nstepsomegak))
2305 safe_allocate(spctramp_sph(stst:stend, 1:sdim, kptst:kptend, 0:this%nk, 1:this%nstepsomegak))
2309 safe_allocate(phase_act(ikk_start:ikk_end, 1:this%nstepsomegak))
2310 if (ikk_start > 0)
then
2311 phase_act(ikk_start:ikk_end, :) = this%conjgphase_prev(ikk_start:ikk_end, :)
2313 phase_act(ikk_start:ikk_end, :) =
m_z0
2316 do itstep = 1, this%itstep
2318 do ikk = ikk_start, ikk_end
2319 do iomk = 1, this%nstepsomegak
2320 vec = sum((this%kcoords_sph(1:3, ikk, iomk) - this%veca(1:3, itstep) /
p_c)**
m_two)
2321 phase_act(ikk, iomk) = phase_act(ikk, iomk) *
exp(
m_zi * vec * dt /
m_two)
2325 do ik = kptst, kptend
2326 do ist = stst, stend
2330 if (itstep == tdstep_on_node)
then
2331 s1_act(:,:,:) = s1_node(ist, isdim, ik, :, :, :)
2332 s2_act(:,:) = s2_node(ist, isdim, ik, :, :)
2334 if (mesh%parallel_in_domains)
then
2335 call mesh%mpi_grp%bcast(s1_act, (lmax + 1) * (2 * lmax + 1) * 3, mpi_double_complex, itstep - 1)
2336 call mesh%mpi_grp%bcast(s2_act, (lmax + 1) * (2 * lmax + 1), mpi_double_complex, itstep - 1)
2350 integ11_t(iomk_start:iomk_end, imdim) = integ11_t(iomk_start:iomk_end, imdim) + &
2351 s1_act(ll, mm, imdim) * this%ylm_k(ll, mm, iomk_start:iomk_end)
2353 integ21_t(iomk_start:iomk_end) = integ21_t(iomk_start:iomk_end) + &
2354 s2_act(ll, mm) * this%ylm_k(ll, mm, iomk_start:iomk_end)
2357 if (mesh%parallel_in_domains)
then
2358 call mesh%allreduce(integ11_t)
2359 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
2470 do ndir = mdim, mindim, -1
2473 if (idir == ndir) cycle
2474 area = area * border(idir) * factor
2477 npface = int(fc_ptdens * area)
2481 if (idir == ndir) cycle
2482 nn(ndir, idim) = int(
sqrt(npface * (border(idir) * factor)**2 / area))
2483 ds(ndir, idim) = border(idir) * factor / nn(ndir, idim)
2484 this%LLr(ndir, idim) = nn(ndir, idim) * ds(ndir, idim)
2485 idx(ndir, idim) = idir
2488 this%nsrfcpnts = this%nsrfcpnts + 2 * product(nn(ndir, 1:mdim - 1))
2491 this%NN(1:mdim, :) = nn(1:mdim, :)
2494 assert(this%nsrfcpnts > 0)
2497 safe_allocate(this%srfcnrml(1:mdim, 0:this%nsrfcpnts))
2498 safe_allocate(this%rcoords(1:mdim, 0:this%nsrfcpnts))
2500 this%srfcnrml(:, :) =
m_zero
2501 this%rcoords(:, :) =
m_zero
2506 do ndir = mdim, mindim, -1
2509 this%face_idx_range(ifc,1) = isp
2510 do iu = 1, nn(ndir,1)
2511 do iv = 1, nn(ndir,2)
2512 this%rcoords(ndir, isp) = border(ndir)
2513 this%srfcnrml(ndir, isp) = product(ds(ndir,1:mdim-1))
2516 this%rcoords(idx(ndir, idim), isp) = (-nn(ndir, idim) *
m_half -
m_half + iuv(idim)) * ds(ndir, idim)
2521 this%face_idx_range(ifc, 2) = isp-1
2526 this%face_idx_range(ifc, 1) = isp
2527 do iu = 1, nn(ndir, 1)
2528 do iv = 1, nn(ndir, 2)
2529 this%rcoords(ndir, isp) = -border(ndir)
2530 this%srfcnrml(ndir, isp) = -product(ds(ndir, 1:mdim - 1))
2533 this%rcoords(idx(ndir, idim), isp) = (-nn(ndir, idim) *
m_half -
m_half + iuv(idim)) * ds(ndir, idim)
2538 this%face_idx_range(ifc, 2) = isp-1
2543 do isp = 1, this%nsrfcpnts
2544 this%rcoords(1:mdim, isp) = mesh%coord_system%to_cartesian(this%rcoords(1:mdim, isp))
2551 if (this%surf_shape ==
pes_plane) nfaces = 2
2555 safe_allocate(which_surface(1:mesh%np_global))
2560 do ip_local = 1, mesh%np
2565 xx(1:mdim) = mesh%x(ip_local, 1:mdim) - offset(1:mdim)
2568 select case (abb%abtype)
2572 in_ab = abs(abb%mf(ip_local)) >
m_epsilon
2578 if (all(abs(xx(1:mdim)) <= border(1:mdim)) .and. .not. in_ab)
then
2582 dd = border(imdim) - xx(imdim)
2584 dd = border(imdim) - abs(xx(imdim))
2586 if (dd < mesh%spacing(imdim) /
m_two)
then
2587 nsurfaces = nsurfaces + 1
2588 which_surface(ip_global) = int(sign(
m_one, xx(imdim))) * imdim
2593 if (nsurfaces == 1)
then
2594 this%nsrfcpnts = this%nsrfcpnts + 1
2596 which_surface(ip_global) = 0
2602 if (mesh%parallel_in_domains)
then
2603 assert(mesh%np_global < huge(0_int32))
2604 call mesh%allreduce(this%nsrfcpnts)
2605 call mesh%allreduce(which_surface)
2608 safe_allocate(this%srfcpnt(1:this%nsrfcpnts))
2609 safe_allocate(this%srfcnrml(1:mdim, 0:this%nsrfcpnts))
2610 safe_allocate(this%rcoords(1:mdim, 0:this%nsrfcpnts))
2611 safe_allocate(this%rankmin(1:this%nsrfcpnts))
2616 this%face_idx_range(:,:) = 0
2620 do idir = mdim, 1, -1
2623 this%face_idx_range(nface, 1) = isp + 1
2625 do ip_global = 1, mesh%np_global
2626 if (abs(which_surface(ip_global)) == idir .and. sign(1, which_surface(ip_global)) == pm)
then
2630 this%rcoords(1:mdim, isp) = xx(1:mdim)
2633 this%rankmin(isp) = rankmin
2635 this%srfcnrml(idir, isp) = sign(1, which_surface(ip_global))
2638 if (imdim == idir) cycle
2639 this%srfcnrml(idir, isp) = this%srfcnrml(idir, isp) * mesh%spacing(imdim)
2644 this%face_idx_range(nface,2) = isp
2651 do ifc = 1, nint((nfaces + 0.5) / 2)
2652 isp_start = this%face_idx_range(ifc, 1)
2653 isp_end = this%face_idx_range(ifc, 2)
2658 if (abs(this%srfcnrml(idir, isp_start)) >=
m_epsilon) n_dir = idir
2665 if (idir == n_dir) cycle
2666 drs(idim)= mesh%spacing(idir)
2674 do isp = isp_start, isp_end
2676 xx = mesh%coord_system%from_cartesian(this%rcoords(1:mdim, isp))
2679 if (idir == n_dir) cycle
2681 if (rs(idim) < rsmin(idim)) rsmin(idim) = rs(idim)
2682 if (rs(idim) > rsmax(idim)) rsmax(idim) = rs(idim)
2688 do idir = 1, mdim - 1
2689 this%LLr(n_dir, idir) = rsmax(idir) - rsmin(idir) + drs(idir)
2690 if (drs(idir) >
m_zero) this%NN(n_dir, idir) = int(this%LLr(n_dir, idir) / drs(idir))
2698 if (this%anisotrpy_correction)
then
2701 do isp = 1, this%nsrfcpnts
2702 weight = sum(this%rcoords(1:mdim, isp) * this%srfcnrml(1:mdim, isp))
2703 weight = weight/sum(this%rcoords(1:mdim, isp)**2) / sum(this%srfcnrml(1:mdim, isp)**2)
2704 this%srfcnrml(1:mdim, isp) = this%srfcnrml(1:mdim, isp) * abs(weight)
2710 safe_deallocate_a(which_surface)
2718 type(
mesh_t),
intent(in) :: mesh
2719 integer,
intent(inout) :: nstepsthetar, nstepsphir
2722 integer :: isp, ith, iph
2723 real(real64) :: thetar, phir
2724 real(real64) :: weight, dthetar
2730 if (nstepsphir == 0) nstepsphir = 1
2732 if (nstepsthetar <= 1)
then
2736 dthetar =
m_pi / nstepsthetar
2737 this%nsrfcpnts = nstepsphir * (nstepsthetar - 1) + 2
2739 safe_allocate(this%srfcnrml(1:mdim, 0:this%nsrfcpnts))
2740 safe_allocate(this%rcoords(1:mdim, 0:this%nsrfcpnts))
2747 do ith = 0, nstepsthetar
2748 thetar = ith * dthetar
2750 if (ith == 0 .or. ith == nstepsthetar)
then
2753 weight = abs(
cos(thetar - dthetar /
m_two) -
cos(thetar + dthetar /
m_two)) &
2757 do iph = 0, nstepsphir - 1
2760 this%srfcnrml(1, isp) =
cos(phir) *
sin(thetar)
2761 if (mdim >= 2) this%srfcnrml(2, isp) =
sin(phir) *
sin(thetar)
2762 if (mdim == 3) this%srfcnrml(3, isp) =
cos(thetar)
2763 this%rcoords(1:mdim, isp) = this%radius * this%srfcnrml(1:mdim, isp)
2765 this%srfcnrml(1:mdim, isp) = this%radius**
m_two * weight * this%srfcnrml(1:mdim, isp)
2766 if (ith == 0 .or. ith == nstepsthetar)
exit
2778 integer,
intent(in) :: istart_global
2779 integer,
intent(in) :: iend_global
2780 integer,
intent(inout) :: istart
2781 integer,
intent(inout) :: iend
2782 type(mpi_comm),
intent(in) :: comm
2784#if defined(HAVE_MPI)
2785 integer,
allocatable :: dimrank(:)
2786 integer :: mpisize, mpirank, irest, irank
2792#if defined(HAVE_MPI)
2793 call mpi_comm_size(comm, mpisize,
mpi_err)
2794 call mpi_comm_rank(comm, mpirank,
mpi_err)
2796 safe_allocate(dimrank(0:mpisize-1))
2798 inumber = iend_global - istart_global + 1
2799 irest = mod(inumber, mpisize)
2800 do irank = 0, mpisize - 1
2802 dimrank(irank) = int(inumber / mpisize) + 1
2805 dimrank(irank) = int(inumber / mpisize)
2809 iend = istart_global + sum(dimrank(:mpirank)) - 1
2810 istart = iend - dimrank(mpirank) + 1
2812 if (istart > iend)
then
2817 safe_deallocate_a(dimrank)
2820 istart = istart_global
2828#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.