28 use,
intrinsic :: iso_c_binding, only: c_double, c_int, c_f_pointer
29 use,
intrinsic :: iso_fortran_env, only: input_unit, int32, int64, real64, output_unit
33 use algorithms,
only: findloc
37 use blas_lapack_gbl,
only: blasint
38 use phys_const_gbl,
only: pi, imu, to_ev
39 use precisn_gbl,
only: wp
53 type intermediatestate
63 real(wp),
allocatable :: ck(:, :, :)
69 real(wp),
allocatable :: ap(:, :, :)
77 real(wp),
allocatable :: dip(:, :, :)
80 type(intermediatestate),
pointer :: parent => null()
83 type(intermediatestate),
pointer :: prev => null()
84 type(intermediatestate),
pointer :: next => null()
86 end type intermediatestate
107 integer,
allocatable :: rchs_pws(:)
108 integer,
allocatable :: rchs_ion(:)
110 complex(wp),
allocatable :: vals_pws(:, :)
111 complex(wp),
allocatable :: vals_ion(:, :)
134 use,
intrinsic :: iso_c_binding, only: c_ptr
136 use linalg_cl,
only: initialize_cl, finalize_cl
137 use mpi_gbl,
only: comm_rank => myrank, comm_size => nprocs, mpi_mod_finalize, mpi_mod_start, mpi_xermsg
146 type(moleculardata) :: moldat
147 type(kmatrix),
allocatable :: km(:)
148 type(scatakcoeffs),
allocatable :: ak(:)
150 character(len=256) :: arg, rmt_data, raw, msg
153 integer :: order, nirr, lusct(8), lukmt(8), lubnd, nkset(8), iarg, narg, input, i, erange(2), p(nMaxPhotons)
154 integer :: lu_pw_dipoles
155 logical :: verbose, mpiio, gpu
156 real(wp) :: omega(nMaxPhotons), first_IP, rasym
157 complex(wp) :: polar(3, nMaxPhotons)
159 call print_ukrmol_header(output_unit)
161 print
'(/,A)',
'Program MULTIDIP: Calculation of multi-photon ionization'
164 narg = command_argument_count()
168 dummy = gsl_set_error_handler_off()
171 do while (iarg <= narg)
172 call get_command_argument(iarg, arg)
173 if (arg ==
'--test')
then
176 else if (arg ==
'--input')
then
178 call get_command_argument(iarg, arg)
179 open (input, file = trim(arg), action =
'read', form =
'formatted')
180 else if (arg ==
'--help')
then
181 print
'(/,A,/)',
'Available options:'
182 print
'(A)',
' --help display this help and exit'
183 print
'(A)',
' --input FILE use FILE as the input file (instead of standard input)'
184 print
'(A)',
' --test run internal sanity checks and exit'
188 write (msg,
'(3a)')
'Unknown command line argument "', trim(arg),
'"'
189 call mpi_xermsg(
'multidip_routines',
'multidip_main', trim(msg), 1, 1)
194 call read_input_namelist(input, order, lusct, lukmt, lubnd, nkset, polar, omega, verbose, rmt_data, first_ip, rasym, raw, &
195 erange, mpiio, gpu, p, lu_pw_dipoles)
197 if (input /= input_unit)
close (input)
203 print
'(/,A,I0,A,I0)',
'Parallel mode; image ',
myproc,
' of ',
nprocs
205 print
'(/,A,/)',
'Absorbed photons'
207 print
'(2x,A,I0,3x,A,SP,2F6.3,A,2F6.3,A,2F6.3,A,F0.3,A)', &
208 '#', i,
'eX: ', polar(1, i),
'i, eY: ', polar(2, i),
'i, eZ: ', polar(3, i),
'i, energy: ', omega(i) * to_ev,
' eV'
211 if (first_ip > 0)
then
212 print
'(/,A,F0.5,A)',
'Override first IP to ', first_ip * to_ev,
' eV'
214 print
'(/,A)',
'Use calculated IP'
217 nirr = count(lukmt > 0)
221 if (any(lusct > 0))
then
229 if (any(erange /= 0))
then
230 if (erange(1) < 1 .or. erange(1) > erange(2) .or. erange(2) > minval(km % nescat))
then
231 write (msg,
'(a,i0)')
'Error: Energy range must satisfy 1 <= erange(1) <= erange(2) <= ', minval(km % nescat)
232 call mpi_xermsg(
'multidip_routines',
'multidip_main', trim(msg), 1, 1)
236 erange(2) = minval(km % nescat)
239 if (moldat % nz < moldat % nelc)
then
240 write (msg,
'(a,i0,a,i0,a)')
'Error: Number of protons (nz = ', moldat % nz,
') is smaller than the number of &
241 &electrons in residual ion (nelc = ', moldat % nelc,
').'
242 call mpi_xermsg(
'multidip_routines',
'multidip_main', trim(msg), 1, 1)
245 if (rasym > moldat % rmatr)
then
247 write (*,
'(/,A,F0.1,A,F0.1,A)', advance =
'no')
'Interval ', moldat % rmatr,
' to ', rasym, &
248 ' will be integrated numerically using '
250 case (1); print
'(a)',
'Romberg quadrature'
251 case (2); print
'(a)',
'Levin quadrature'
254 print
'(/,a)',
'Warning: Numerical integration (rasym) is currently only implemented for the second order.'
259 if (gpu)
call initialize_cl(-1_c_int, int(merge(-1,
myproc - 1,
nprocs == 1), c_int))
260 call multidip_driver(order, moldat, km, ak, lubnd, omega(1:order), polar(:, 1:order), verbose, first_ip, rasym, raw, &
261 erange, p, lu_pw_dipoles)
262 if (gpu)
call finalize_cl
264 call mpi_mod_finalize
302 subroutine multidip_driver (order, moldat, km, ak, lubnd, omega, polar, verbose, first_IP, r0, raw, erange, p, lu_pw_dipoles)
306 integer,
intent(in) :: order, erange(2), lubnd, p(:), lu_pw_dipoles
307 logical,
intent(in) :: verbose
308 type(moleculardata),
intent(in) :: moldat
309 type(kmatrix),
allocatable,
intent(in) :: km(:)
310 type(scatakcoeffs),
allocatable,
intent(in) :: ak(:)
311 real(wp),
intent(in) :: omega(:), first_IP, r0
312 complex(wp),
intent(in) :: polar(:, :)
313 character(len=*),
intent(in) :: raw
317 type(intermediatestate),
pointer :: states, state
319 integer,
allocatable :: iidip(:), ifdip(:)
320 real(wp),
allocatable :: escat(:)
322 integer :: j, s, mgvni, mgvnn, mgvn1, mgvn2, nesc, irri, iki, icomp, nstati, nchani
326 mgvni = km(iki) % mgvn
327 nesc = erange(2) - erange(1) + 1
328 irri = findloc(moldat % mgvns, mgvni, 1)
329 nstati = moldat % mnp1(irri)
330 nchani = moldat % nchan(irri)
333 allocate (states % ck(nstati, 2, (nesc +
nprocs - 1) /
nprocs))
334 allocate (states % ap(nchani, 2, (nesc +
nprocs - 1) /
nprocs))
342 print
'(/,2(A,I0))',
'Photon ', j,
' of ', order
353 do s = 1,
size(iidip)
360 do while (
associated(state))
363 if (state % order + 1 == j)
then
369 if ((mgvnn == mgvn1 .or. mgvnn == mgvn2) .and. &
370 any(km(:) % mgvn == mgvn1) .and. &
371 any(km(:) % mgvn == mgvn2))
then
376 mgvn1, mgvn2, km, state, verbose, ei, first_ip, r0, erange)
379 mgvn1, mgvn2, km, ak, state, verbose, ei, first_ip, r0, erange)
387 state => state % next
395 if (
allocated(integral_cache))
then
396 deallocate (integral_cache)
402 escat = km(iki) % escat(erange(1):erange(2))
405 call calculate_asymmetry_parameters(moldat, order, states, escat, ei, first_ip, omega, raw, erange, p, lu_pw_dipoles)
409 do while (
associated(state % next))
410 state => state % next
411 deallocate (state % prev)
437 type(intermediatestate),
pointer,
intent(inout) :: states
438 type(moleculardata),
intent(in) :: moldat
439 integer,
intent(in) :: irr, lubnd
440 real(wp),
intent(out) :: Ei
442 complex(wp),
allocatable :: ap(:)
443 real(wp),
allocatable :: Ek(:), bnd(:, :), wbnd(:, :), fc(:), gc(:), fcp(:), gcp(:)
445 integer :: mye, nmye, nchan, nstat, ichan, stot, mgvn, nbnd
447 nmye =
size(states % ck, 3)
448 mgvn = moldat % mgvns(irr)
449 stot = moldat % stot(irr)
450 nchan = moldat % nchan(irr)
451 nstat = moldat % mnp1(irr)
454 ei = moldat % eig(1, irr)
461 allocate (bnd(nstat, nbnd))
471 states % ck(:, 1, mye) = bnd(:, 1)
472 states % ck(:, 2, mye) = 0
475 print
'(/,a,/)',
'Bound state information'
476 print
'(4x,a,e25.15)',
'First R-matrix pole = ', moldat % eig(1, irr)
477 print
'(4x,a,e25.15)',
'Calculated initial energy = ', ei
482 allocate (wbnd(nchan, nbnd), fc(nchan), gc(nchan), fcp(nchan), gcp(nchan), ap(nchan))
487 ek = ei - moldat % etarg(moldat % ichl(: , irr))
495 states % ap(:, 1, mye) = real(ap)
496 states % ap(:, 2, mye) = aimag(ap)
499 print
'(4x,a,e25.15)',
'Total inner norm = ', norm2(bnd(:, 1))
500 print
'(/,a,/)',
'Bound state outer region channel coefficients and amplitudes'
501 print
'(4x,a,4x,a,23x,a,20x,a,20x,a)',
'chan',
'Ek',
'Re ap',
'Im ap',
'f_p'
503 print
'(i6,a,4e25.15)', ichan,
': ', ek(ichan), ap(ichan), wbnd(ichan, 1)
508 states % ap(:, :, :) = 0
513 call test_outer_expansion(
'initial-state.txt', moldat, irr, states % ck(:, :, 1), states % ap(:, :, 1), ei)
547 km, state, verbose, calc_Ei, first_IP, r0, erange)
555 type(moleculardata),
intent(in) :: moldat
556 type(kmatrix),
allocatable,
intent(in) :: km(:)
559 type(intermediatestate),
pointer,
intent(inout) :: state
560 type(intermediatestate),
pointer :: last
562 integer,
intent(in) :: order, icomp, s, mgvnn, mgvn1, mgvn2, erange(2)
563 logical,
intent(in) :: verbose
564 real(wp),
intent(in) :: Ephoton(:), calc_Ei, first_IP, r0
566 integer :: nstatn, nstatf, nchann, nchanf, nopen, mgvnf, irrn, irrf, ikn, ikf, ipw, nesc, ie, mye, t, dt, i
567 real(wp) :: Ei, Ek, Etotf
568 character(len=1) :: transp
569 character(len=1024) :: filename
571 complex(wp),
allocatable :: beta(:), app(:), H(:, :), lambda(:), hc(:), hcp(:)
572 real(wp),
allocatable :: fc(:), fcp(:), gc(:), gcp(:)
574 integer,
allocatable :: lf(:)
575 real(wp),
allocatable :: Ef(:), P(:), rhs(:, :), omega(:), echl(:)
576 real(wp),
allocatable :: Pw(:, :), wPw(:, :), wPD(:, :), IwPD(:, :), wckp(:, :), Dpsi(:, :, :), corr(:, :), ckp(:, :)
578 if (mgvnn == mgvn1)
then
586 irrn = findloc(moldat % mgvns, mgvnn, 1)
587 irrf = findloc(moldat % mgvns, mgvnf, 1)
589 ikn = findloc(km(:) % mgvn, mgvnn, 1)
590 ikf = findloc(km(:) % mgvn, mgvnf, 1)
592 nstatn = moldat % mnp1(irrn)
593 nstatf = moldat % mnp1(irrf)
595 nchann = moldat % nchan(irrn)
596 nchanf = moldat % nchan(irrf)
598 nesc = erange(2) - erange(1) + 1
602 allocate (pw(nstatf, nchanf), wpd(nchanf, 2), iwpd(nchanf, 2), wpw(nchanf, nchanf), wckp(nchanf, 2), omega(order), &
603 dpsi(nstatf, 2, (nesc +
nprocs - 1) /
nprocs), fc(nchanf), gc(nchanf), fcp(nchanf), gcp(nchanf), &
604 hc(nchanf), hcp(nchanf), corr(nchanf, 2), echl(nchanf), &
605 ef(nchanf), lf(nchanf), ckp(nstatf, 2), h(nchanf, nchanf), lambda(nchanf), beta(nchanf), &
608 echl(1:nchanf) = moldat % etarg(moldat % ichl(1:nchanf, irrf)) - moldat % etarg(1)
612 do while (
associated(last % next))
615 allocate (last % next)
616 last % next % prev => last
618 last % order = state % order + 1
621 last % parent => state
622 allocate (last % ck(nstatf, 2, (nesc +
nprocs - 1) /
nprocs))
623 allocate (last % ap(nchanf, 2, (nesc +
nprocs - 1) /
nprocs))
631 print
'(4x,A,I0,A)',
'inner dipoles applied in ', dt,
' s'
634 call calculate_r_matrix(0, moldat, irrf, 0._wp, [ 0._wp ], pw, wpw);
646 etotf = ei + sum(omega(1 : last % order))
647 ef = km(ikf) % escat(ie) - echl - sum(omega(last % order + 1 :))
648 lf = moldat % l2p(1:nchanf, irrf)
651 print
'(4x,A,*(I0,A))',
'energy ', ie,
' of ', km(ikf) % nescat, &
652 ' (', count(ef > 0),
' open / ', nopen,
' open + weakly closed channels of ', nchanf,
')'
655 fc = 0; fcp = 0; gc = 0; gcp = 0; hc = 0; hcp = 0; lambda = 0
658 hc(ipw) = gc(ipw) +
imu*fc(ipw)
659 hcp(ipw) = gcp(ipw) +
imu*fcp(ipw)
660 lambda(ipw) = hcp(ipw) / hc(ipw)
664 rhs = dpsi(:, :, mye)
667 ek = km(ikf) % escat(ie) - sum(omega(last % order + 1 :))
668 call multiint(moldat, r0, ei, ek, omega, mye, last, +1, beta, cache)
669 beta = -2 * beta / sqrt(2*abs(ef))
670 where (ef < 0) beta = beta /
imu
671 corr(:, 1) = real(beta * (fcp - lambda * fc), wp)
672 corr(:, 2) = aimag(beta * (fcp - lambda * fc))
674 rhs = rhs - 0.5 * dpsi(:, :, mye)
677 p = 1 / (etotf - moldat % eig(1:nstatf, irrf))
678 ckp(:, 1) = p * rhs(:, 1)
679 ckp(:, 2) = p * rhs(:, 2)
685 call calculate_r_matrix(1, moldat, irrf, etotf, p, pw, wpw)
686 h(1:nopen, 1:nopen) = wpw(1:nopen, 1:nopen)
688 h(i, i) = h(i, i) + 2/lambda(i)
690 do i = nopen + 1, nchanf
701 ckp(:, 1) = p * (rhs(:, 1) - ckp(:, 1))
702 ckp(:, 2) = p * (rhs(:, 2) - ckp(:, 2))
708 app = cmplx(wckp(:, 1), wckp(:, 2), wp)
710 app = (app - beta*fc) / hc
717 wckp(:, 1) = real(app)
718 wckp(:, 2) = aimag(app)
719 write (filename,
'(a,i0,a,i0,a)')
'intermediate-state-', irrf,
'-', ie,
'.txt'
723 if (verbose) print
'(4x,A,*(E25.15))',
' - beta: ', beta(1:nopen)
724 if (verbose) print
'(4x,A,*(E25.15))',
' - ap: ', app(1:nopen)
726 last % ck(:, 1, mye) = ckp(:, 1)
727 last % ck(:, 2, mye) = ckp(:, 2)
729 last % ap(:, 1, mye) = real(app, wp)
730 last % ap(:, 2, mye) = aimag(app)
735 call calculate_r_matrix(2, moldat, irrf, 0._wp, [ 0._wp ], pw, wpw);
738 print
'(4x,A,I0,A)',
'intermediate states solved in ', dt,
' s'
769 km, ak, state, verbose, calc_Ei, first_IP, r0, erange)
776 type(moleculardata),
intent(in) :: moldat
777 type(kmatrix),
allocatable,
intent(in) :: km(:)
778 type(scatakcoeffs),
allocatable,
intent(in) :: ak(:)
781 type(intermediatestate),
pointer,
intent(inout) :: state
782 type(intermediatestate),
pointer :: last
784 integer,
intent(in) :: order, icomp, s, mgvnn, mgvn1, mgvn2, erange(2)
785 logical,
intent(in) :: verbose
786 real(wp),
intent(in) :: Ephoton(:), calc_Ei, first_IP, r0
788 character(len=1) :: transp
789 character(len=1024) :: filename
791 complex(wp),
allocatable :: Af(:, :), dm(:), dp(:), Sm(:, :), tmat(:, :)
792 real(wp),
allocatable :: Dpsi(:, :, :), Ef(:), echlf(:), d_inner(:, :), d_outer(:, :), Re_Af(:, :), Im_Af(:, :)
793 real(wp),
allocatable :: omega(:), d_total(:, :), kmat(:, :), Sf(:), Cf(:), Sfp(:), Cfp(:)
794 integer,
allocatable :: lf(:)
796 real(wp) :: Etotf, Ei, Ek
797 integer :: mgvnf, irrn, irrf, ikn, ikf, nstatn, nstatf, nchann, nchanf, nesc, ie, nopen, nochf, mye, nene, maxchan, i
800 integer(blasint) :: m, n, lds, inc = 1
802 if (mgvnn == mgvn1)
then
810 irrn = findloc(moldat % mgvns, mgvnn, 1)
811 irrf = findloc(moldat % mgvns, mgvnf, 1)
813 ikn = findloc(km(:) % mgvn, mgvnn, 1)
814 ikf = findloc(km(:) % mgvn, mgvnf, 1)
816 nstatn = moldat % mnp1(irrn)
817 nstatf = moldat % mnp1(irrf)
819 nchann = km(ikn) % nchan
820 nchanf = km(ikf) % nchan
822 nesc = erange(2) - erange(1) + 1
829 maxchan = count(moldat % ichl(1:nchanf, irrf) <=
maxtarg)
832 allocate (dpsi(nstatf, 2, nene), omega(order), ef(nchanf), lf(nchanf), echlf(nchanf), &
833 re_af(nstatf, maxchan), im_af(nstatf, maxchan), af(nstatf, maxchan), sm(nchanf, nchanf), &
834 d_inner(maxchan, 2), d_outer(maxchan, 2), d_total(maxchan, 2), dm(maxchan), dp(nchanf), &
835 sf(nchanf), cf(nchanf), sfp(nchanf), cfp(nchanf), kmat(nchanf, nchanf), tmat(nchanf, nchanf))
837 echlf(1:nchanf) = moldat % etarg(moldat % ichl(1:nchanf, irrf)) - moldat % etarg(1)
841 do while (
associated(last % next))
844 allocate (last % next)
845 last % next % prev => last
850 last % parent => state
851 allocate (last % dip(maxchan, 2, nene))
859 print
'(4x,A,I0,A)',
'inner dipoles applied in ', dt,
' s'
862 call km(ikf) % reset_kmatrix_position(skip =
myproc - 1)
863 if (
allocated(ak))
call ak(ikf) % reset_wfncoeffs_position(skip =
myproc - 1)
869 call km(ikf) % get_kmatrix(kmat, skip =
nprocs - 1)
870 if (
allocated(ak))
call ak(ikf) % get_wfncoeffs(ek, re_af, im_af, skip =
nprocs - 1)
871 if (ie < erange(1)) cycle
874 last % dip(:, :, mye) = 0
881 etotf = ei + sum(omega)
882 ef = km(ikf) % escat(ie) - echlf
883 lf = moldat % l2p(1:nchanf, irrf)
884 nopen = count(ef > 0)
885 nochf = min(nopen, maxchan)
887 print
'(4x,A,*(I0,A))',
'energy ', ie,
' of ', km(ikf) % nescat,
' (', nopen,
' open channels of ', nchanf,
')'
894 call calculate_k_matrix(moldat, nopen, irrf, etotf, sf, cf, sfp, cfp, kmat)
896 call calculate_t_matrix(kmat, tmat, nopen)
899 if (.not.
allocated(ak))
then
900 call apply_ak_coefficients_multidip(dpsi(:, :, mye), d_inner, moldat, nopen, irrf, etotf, &
901 sfp, cfp, kmat, tmat, .true.)
903 call apply_ak_coefficiens_compak(dpsi(:, :, mye), d_inner, re_af(:, 1:nochf), im_af(:, 1:nochf))
909 call multiint(moldat, r0, ei, km(ikf) % escat(ie), omega, mye, last, -1, dm(1:nochf), cache)
910 call multiint(moldat, r0, ei, km(ikf) % escat(ie), omega, mye, last, +1, dp(1:nopen), cache)
911 dm(1:nochf) = dm(1:nochf) *
imu / sqrt(2*
pi*sqrt(2*ef(1:nochf)))
912 dp(1:nopen) = dp(1:nopen) *
imu / sqrt(2*
pi*sqrt(2*ef(1:nopen)))
913 if (verbose) print
'(5x,A,1x,*(1x,E25.15))',
'dm = ', dm(1:nochf)
914 if (verbose) print
'(5x,A,1x,*(1x,E25.15))',
'dp = ', dp(1:nopen)
916 m = int(nopen, blasint)
917 n = int(nochf, blasint)
918 lds = int(nchanf, blasint)
919 call calculate_s_matrix(tmat, sm, nopen)
920 call blas_zgemv(
'T', m, n, -
cone, sm, lds, dp, inc,
cone, dm, inc)
922 d_outer(:, 1) = real(dm)
923 d_outer(:, 2) = aimag(dm)
927 write (filename,
'(a,i0,a,i0,a)')
'final-state-', irrf,
'-', ie,
'.txt'
932 d_total = d_inner + d_outer
933 last % dip(:, :, mye) = d_total
935 if (verbose) print
'(5x,A,1x,*(1x,E25.15))',
'd_inner = ', (d_inner(i, 1), d_inner(i, 2), i = 1, nochf)
936 if (verbose) print
'(5x,A,1x,*(1x,E25.15))',
'd_outer = ', (d_outer(i, 1), d_outer(i, 2), i = 1, nochf)
937 if (verbose) print
'(5x,A,1x,*(1x,E25.15))',
'd_total = ', (d_total(i, 1), d_total(i, 2), i = 1, nochf)
942 print
'(4x,A,I0,A)',
'matrix elements calculated in ', dt,
' s'
960 type(intermediatestate),
pointer,
intent(in) :: state
961 type(intermediatestate),
pointer :: ptr
963 integer,
allocatable :: irreds(:), compts(:)
966 order = state % order
968 allocate (irreds(order + 1), compts(order))
971 irreds(order + 1) = ptr % mgvn
972 do while (
associated(ptr % parent))
973 compts(order) = ptr % dcomp
975 irreds(order) = ptr % mgvn
979 write (*,
'(2x,a)', advance =
'no')
'Transition'
980 do i = 1, state % order
981 write (*,
'(1x,i0,1x,3a)', advance =
'no') irreds(i),
'-[',
compt(compts(i)),
']->'
983 write (*,
'(1x,i0)') irreds(state % order + 1)
999 subroutine apply_ak_coefficiens_compak (psi, Apsi, ReAk, ImAk)
1004 real(wp),
intent(in) :: psi(:, :), ReAk(:, :), ImAk(:, :)
1005 real(wp),
intent(inout) :: Apsi(:, :)
1007 integer(blasint) :: m, n, inc = 1
1009 m = int(
size(reak, 1), blasint)
1010 n = int(
size(reak, 2), blasint)
1012 call blas_dgemv(
'T', m, n,
rone, reak, m, psi(:, 1), inc,
rzero, apsi(:, 1), inc)
1013 call blas_dgemv(
'T', m, n, +
rone, imak, m, psi(:, 2), inc, +
rone, apsi(:, 1), inc)
1014 call blas_dgemv(
'T', m, n,
rone, reak, m, psi(:, 2), inc,
rzero, apsi(:, 2), inc)
1015 call blas_dgemv(
'T', m, n, -
rone, imak, m, psi(:, 1), inc, +
rone, apsi(:, 2), inc)
1017 end subroutine apply_ak_coefficiens_compak
1058 subroutine apply_ak_coefficients_multidip (psi, Apsi, moldat, nopen, irr, Etot, Sp, Cp, kmat, tmat, conj)
1063 type(moleculardata),
intent(in) :: moldat
1064 real(wp),
intent(in) :: psi(:, :), Etot
1065 real(wp),
intent(inout) :: Apsi(:, :)
1066 integer,
intent(in) :: nopen, irr
1067 real(wp),
intent(in) :: Sp(:), Cp(:), kmat(:, :)
1068 complex(wp),
intent(in) :: tmat(:, :)
1069 logical,
intent(in) :: conj
1071 real(wp),
allocatable :: tmps(:, :), tmpc(:, :)
1072 complex(wp),
allocatable :: tmpo(:)
1074 integer :: nchan, nstat, i, j
1078 nstat = moldat % mnp1(irr)
1079 nchan = moldat % nchan(irr)
1081 allocate (tmps(nstat, 2), tmpc(nchan, 2), tmpo(nopen))
1084 tmps(:, 1) = psi(:, 1) / (moldat % eig(1:nstat, irr) - etot)
1085 tmps(:, 2) = psi(:, 2) / (moldat % eig(1:nstat, irr) - etot)
1094 fij = (merge(sp(i),
rzero, i == j) + cp(i)*kmat(i, j)) / sqrt(2*
pi)
1095 tmpo(j) = tmpo(j) + cmplx(tmpc(i, 1), tmpc(i, 2), wp)*fij
1100 do j = 1, min(nopen,
size(apsi, 1))
1104 t = merge(1, 0, i == j) + conjg(tmat(i, j))/2
1105 if (conj) t = conjg(t)
1107 apsi(j, 1) = apsi(j, 1) + real(z)
1108 apsi(j, 2) = apsi(j, 2) + aimag(z)
1113 do j = nopen + 1, min(nchan,
size(apsi, 1))
1118 end subroutine apply_ak_coefficients_multidip
1134 character(len=*),
intent(in) :: filename
1135 type(moleculardata),
intent(in) :: moldat
1136 integer,
intent(in) :: irr, nopen
1137 real(wp),
intent(in) :: Etot, Ek(:), Sp(:), Cp(:), kmat(:, :)
1138 complex(wp),
intent(in) :: tmat(:, :)
1140 real(wp),
allocatable :: psi(:, :), Apsi(:, :), S(:), C(:), dSdr(:), dCdr(:)
1141 complex(wp),
allocatable :: Fqp(:, :), Hp(:), Hm(:)
1144 integer :: i, nfdm, u, nchan, p, q, nstat
1146 nfdm =
size(moldat % r_points) - 1
1147 nchan = moldat % nchan(irr)
1148 nstat = moldat % mnp1(irr)
1151 allocate (fqp(nchan, nopen), psi(nstat, 2), apsi(nchan, 2), s(nchan), c(nchan), hp(nchan), hm(nchan), dsdr(nchan), &
1154 open (newunit = u, file = filename, action =
'write', form =
'formatted')
1158 write (u,
'(e25.15)', advance =
'no') moldat % r_points(i)
1160 if (.not.
associated(moldat % wmat2(i, irr) % mat))
then
1161 print
'(a)',
'Error: wmat2 has not been read from molecular_data'
1163 else if (moldat % wmat2(i, irr) % distributed)
then
1164 print
'(a)',
'Error: test_outer_expansion not implemented in MPI-IO mode'
1168 psi(:, 1) = moldat % wmat2(i, irr) % mat(q, :)
1171 call apply_ak_coefficients_multidip(psi, apsi, moldat, nopen, irr, etot, sp, cp, kmat, tmat, .false.)
1173 fqp(q, 1:nopen) = cmplx(apsi(1:nopen, 1), apsi(1:nopen, 2), wp)
1175 write (u,
'(*(e25.15))') fqp(1:nchan, 1:nopen)
1179 do i = 0, nint(moldat % rmatr/dr)
1180 r = moldat % rmatr + i*dr
1181 write (u,
'(e25.15)', advance =
'no') r
1183 hp = (c + imu*s) * (-imu) / sqrt(2*pi)
1184 hm = (c - imu*s) * (-imu) / sqrt(2*pi)
1187 if (q == p) fqp(q, p) = hp(q)
1188 if (q /= p) fqp(q, p) = 0
1189 fqp(q, p) = fqp(q, p) - hm(q) * conjg(1 + tmat(q, p))
1190 write (u,
'(*(e25.15))', advance =
'no') fqp(q, p)
1213 use mpi_gbl,
only: mpi_mod_barrier
1215 integer,
intent(inout) :: t
1216 integer,
intent(out) :: dt
1217 integer :: clk_now, clk_rate, clk_max, ierr
1219 call mpi_mod_barrier(ierr)
1221 call system_clock(clk_now, clk_rate, clk_max)
1223 if (t < clk_now)
then
1224 dt = (clk_now - t) / clk_rate
1228 dt = ((clk_max - t) + clk_now) / clk_rate
1255 real(wp),
intent(in) :: first_IP, escat, etarg, Ephoton(:)
1256 real(wp),
intent(inout) :: Ei, omega(:)
1266 if (first_ip > 0)
then
1267 ip = first_ip + escat
1272 where (ephoton /= 0)
1275 omega = (ip - sum(ephoton)) / (
size(omega) - count(ephoton /= 0))
1305 type(moleculardata),
intent(in) :: moldat
1307 real(wp),
intent(in) :: esc(:), Ephoton(:), r0, calc_Ei, first_IP
1308 integer,
intent(in) :: nphot, erange(2)
1309 logical,
intent(in) :: verbose
1311 complex(wp),
allocatable :: ks(:)
1312 integer,
allocatable :: rchs(:), ms(:), ls(:), pws_coupled(:, :), ion_coupled(:, :)
1314 real(wp) :: ebase, etarg, escat, Ei, Ek, omega(size(Ephoton))
1315 integer :: nesc, nene, mye, rchi, rchj, nredch, ntarg, itarg, jtarg, li, lj, order, ie, lmax, nrchs, t, dt
1321 print
'(2x,a)',
'Precomputing outer integrals'
1325 ntarg =
size(moldat % etarg)
1326 lmax = maxval(moldat % l2p)
1327 nredch = ntarg * (lmax + 1)
1328 ebase = moldat % etarg(1)
1332 allocate (integral_cache(nene), rchs(order + 1), ms(order), ks(order + 1), ls(order + 1), &
1333 pws_coupled(nredch + 1, nredch), ion_coupled(nredch + 1, nredch))
1338 do lj = max(0, li - 1), min(lmax, li + 1)
1340 rchi = li*ntarg + itarg
1341 rchj = lj*ntarg + itarg
1342 pws_coupled(rchi + 1, rchj) = rchi
1343 pws_coupled(rchj + 1, rchi) = rchj
1352 if (any(moldat % crlv(itarg, jtarg, :) /= 0))
then
1354 rchi = li*ntarg + itarg
1355 rchj = li*ntarg + jtarg
1356 ion_coupled(rchi + 1, rchj) = rchi
1357 ion_coupled(rchj + 1, rchi) = rchj
1366 nrchs = count(pws_coupled(2:, rchi) /= 0, 1)
1367 pws_coupled(1, rchi) = nrchs
1368 pws_coupled(2:nrchs + 1, rchi) = pack(pws_coupled(2:, rchi), pws_coupled(2:, rchi) /= 0)
1370 nrchs = count(ion_coupled(2:, rchi) /= 0, 1)
1371 ion_coupled(1, rchi) = nrchs
1372 ion_coupled(2:nrchs + 1, rchi) = pack(ion_coupled(2:, rchi), ion_coupled(2:, rchi) /= 0)
1377 allocate (integral_cache(mye) % next_pws(nredch))
1388 if (ie < erange(1) .or. ie > erange(2)) cycle
1394 rchs(order + 1) = rchi
1395 itarg = mod(rchi - 1, ntarg) + 1
1396 etarg = moldat % etarg(itarg)
1397 escat = esc(ie) - sum(omega(nphot + 1:))
1398 ek = escat + ebase - etarg
1400 ks(order + 1) = sqrt(2*ek)
1402 ks(order + 1) = cmplx(0._wp, sqrt(-2*ek), wp)
1405 ls(order + 1) = (rchi - 1) / ntarg
1407 order, omega(1:nphot), escat, r0, rchs, ms, ks, ls)
1417 print
'(4x,a,i0,a)',
'radial integrals precomputed in ', dt,
' s'
1443 escat, r0, rchs, ms, ks, ls)
1450 type(moleculardata),
intent(in) :: moldat
1452 real(wp),
intent(in) :: omega(:), escat, r0
1453 integer,
intent(in) :: order, pws_coupled(:, :), ion_coupled(:, :)
1454 integer,
intent(inout) :: rchs(:), ms(:), ls(:)
1455 complex(wp),
intent(inout) :: ks(:)
1457 integer :: rchi, rchj, n, ntarg, ncoup, icoup, jtarg
1458 real(wp) :: ebase, etarg, a, z, c, ek, ekj
1460 rchi = rchs(order + 1)
1461 n =
size(rchs) - order
1462 ebase = moldat % etarg(1)
1463 ntarg =
size(moldat % etarg)
1465 z = moldat % nz - moldat % nelc
1469 ek = escat - sum(omega(
size(omega) - order + 1:))
1472 ncoup = pws_coupled(1, rchi)
1473 allocate (integral_cache % rchs_pws(ncoup), integral_cache % vals_pws(2, ncoup), integral_cache % next_pws(ncoup))
1475 rchj = pws_coupled(1 + icoup, rchi)
1476 jtarg = mod(rchj - 1, ntarg) + 1
1477 etarg = moldat % etarg(jtarg)
1478 ekj = ek + ebase - etarg
1483 ks(order) = sqrt(2*ekj)
1485 ks(order) = cmplx(0._wp, sqrt(-2*ekj), wp)
1487 ls(order) = (rchj - 1)/ntarg
1489 integral_cache % rchs_pws(icoup) = rchs(order)
1490 integral_cache % vals_pws(1, icoup) =
nested_cgreen_integ(z, a, r0, c, n, +1, +1, ms(order:), ls(order:), ks(order:))
1491 integral_cache % vals_pws(2, icoup) =
nested_cgreen_integ(z, a, r0, c, n, +1, -1, ms(order:), ls(order:), ks(order:))
1494 order - 1, omega, escat, r0, rchs, ms, ks, ls)
1499 ncoup = ion_coupled(1, rchi)
1500 allocate (integral_cache % rchs_ion(ncoup), integral_cache % vals_ion(2, ncoup), integral_cache % next_ion(ncoup))
1502 rchj = ion_coupled(1 + icoup, rchi)
1503 jtarg = mod(rchj - 1, ntarg) + 1
1504 etarg = moldat % etarg(jtarg)
1505 ekj = ek + ebase - etarg
1510 ks(order) = sqrt(2*ekj)
1512 ks(order) = cmplx(0._wp, sqrt(-2*ekj), wp)
1514 ls(order) = (rchj - 1)/ntarg
1516 integral_cache % rchs_ion(icoup) = rchs(order)
1517 integral_cache % vals_ion(1, icoup) =
nested_cgreen_integ(z, a, r0, c, n, +1, +1, ms(order:), ls(order:), ks(order:))
1518 integral_cache % vals_ion(2, icoup) =
nested_cgreen_integ(z, a, r0, c, n, +1, -1, ms(order:), ls(order:), ks(order:))
1521 order - 1, omega, escat, r0, rchs, ms, ks, ls)
1537 integer,
intent(in) :: erange(2), ntarg
1542 if (i < erange(1)) cycle
1543 print
'(4x,a,i0)',
'cache for energy #', i
1544 do j = 1,
size(cache(i) % next_pws)
1559 integer,
intent(in) :: ntarg, level, chain(level)
1561 integer :: i, j, l, rch, ichl
1562 complex(wp) :: val(2)
1564 if (
allocated(cache % rchs_pws))
then
1565 do i = 1,
size(cache % rchs_pws)
1567 ichl = mod(rch - 1, ntarg) + 1
1569 write (*,
'(6x,a,i0,a,i0,1x,i0)', advance =
'no')
'( [', rch,
'] ', ichl, l
1572 ichl = mod(rch - 1, ntarg) + 1
1574 write (*,
'(a,i0,a,i0,1x,i0)', advance =
'no')
' | [', rch,
'] ', ichl, l
1576 rch = cache % rchs_pws(i)
1577 val = cache % vals_pws(:, i)
1578 ichl = mod(rch - 1, ntarg) + 1
1580 write (*,
'(a,i0,a,i0,1x,i0,a,4e25.15)')
' | [', rch,
'] ', ichl, l,
' ):', val
1585 if (
allocated(cache % rchs_ion))
then
1586 do i = 1,
size(cache % rchs_ion)
1588 ichl = mod(rch - 1, ntarg) + 1
1590 write (*,
'(6x,a,i0,a,i0,1x,i0)', advance =
'no')
'( [', rch,
'] ', ichl, l
1593 ichl = mod(rch - 1, ntarg) + 1
1595 write (*,
'(a,i0,a,i0,1x,i0)', advance =
'no')
' | [', rch,
'] ', ichl, l
1597 rch = cache % rchs_ion(i)
1598 val = cache % vals_ion(:, i)
1599 ichl = mod(rch - 1, ntarg) + 1
1601 write (*,
'(a,i0,a,i0,1x,i0,a,4e25.15)')
' | [', rch,
'] ', ichl, l,
' ):', val
1626 subroutine calculate_r_matrix (stage, moldat, irr, etot, P, Pw, wPw)
1628 use linalg_cl,
only: is_initialized_cl, residr_cl
1631 type(moleculardata),
intent(in) :: moldat
1633 integer,
intent(in) :: stage, irr
1634 real(wp),
intent(in) :: etot, P(:)
1635 real(wp),
intent(inout) :: Pw(:, :), wPw(:, :)
1637 integer(c_int) :: cstge, nchan, nstat, ldwam
1638 real(wp),
pointer :: wamp(:, :)
1641 if (is_initialized_cl() /= 0)
then
1644 cstge = int(stage, c_int)
1645 nchan = int(moldat % nchan(irr), c_int)
1646 nstat = int(moldat % mnp1(irr), c_int)
1647 ldwam = int(
size(moldat % wamp(irr) % mat, 1), c_int)
1650 if (stage == 0)
then
1651 wamp => moldat % wamp(irr) % mat
1653 allocate (wamp(0, 0))
1657 call residr_cl(cstge, nchan, nstat, 0_c_int, -1._wp, moldat % eig(:, irr), etot, wamp, ldwam, wpw)
1660 if (stage /= 0)
then
1669 if (stage == 1)
then
1674 end subroutine calculate_r_matrix
1697 subroutine multiint (moldat, r0, Ei, esc, omega, ie, state, sb, dip, cache)
1699 use mpi_gbl,
only: mpi_xermsg
1703 type(moleculardata),
intent(in) :: moldat
1704 type(intermediatestate),
pointer,
intent(in) :: state
1707 complex(wp),
intent(inout) :: dip(:)
1708 real(wp),
allocatable,
intent(inout) :: omega(:)
1709 real(wp),
intent(in) :: Ei, esc, r0
1710 integer,
intent(in) :: ie, sb
1712 complex(wp),
allocatable :: k(:)
1713 integer,
allocatable :: l(:), m(:)
1715 real(wp) :: c, a, Ekf, ebase, echl, etarg
1716 integer :: nphot, mgvn, ichan, irr, ichl, irch, ntarg
1720 if (.not.
associated(state % parent))
then
1721 call mpi_xermsg(
'multidip_routines',
'multiint',
'Runtime error: unexpected parent state', 1, 1)
1726 nphot = state % order
1728 irr = findloc(moldat % mgvns, mgvn, 1)
1729 ebase = moldat % etarg(1)
1730 ntarg =
size(moldat % etarg)
1739 allocate (k(nphot + 1), l(nphot + 1), m(nphot))
1743 do ichan = 1,
size(dip)
1746 ichl = moldat % ichl(ichan, irr)
1747 etarg = moldat % etarg(ichl)
1748 echl = etarg - ebase
1752 k(1) = sqrt(2*abs(ekf));
if (ekf < 0) k(1) = k(1) *
imu
1753 l(1) = moldat % l2p(ichan, irr)
1757 irch = l(1)*ntarg + ichl
1758 dip(ichan) =
multiint_chain(moldat, r0, ei, esc - omega(nphot), omega, ie, c, 1, state, ichan, sb, k, l, m, &
1759 cache(ie) % next_pws(irch))
1761 dip(ichan) =
multiint_chain(moldat, r0, ei, esc - omega(nphot), omega, ie, c, 1, state, ichan, sb, k, l, m)
1797 recursive complex(wp) function multiint_chain (moldat, r0, Ei, esc, omega, ie, c, N, &
1798 state, ichanf, sb, k, l, m, cache)
result (integ)
1804 type(moleculardata),
intent(in) :: moldat
1805 type(intermediatestate),
pointer,
intent(in) :: state
1807 type(intermediatestate),
pointer :: parent
1809 complex(wp),
intent(inout) :: k(:)
1810 real(wp),
intent(inout) :: omega(:)
1811 integer,
intent(inout) :: l(:), m(:)
1812 real(wp),
intent(in) :: r0, ei, esc
1813 integer,
intent(in) :: ie, sb, n, ichanf
1815 complex(wp) :: ap, kr(n + 1)
1816 real(wp) :: z, c, a, ek, qion, qpws, ebase, etarg, echl
1817 integer :: mgvni, mgvnf, nchani, irri, irrf, ichani, ichl, irch, nphot, dcomp, lr(n + 1), mr(n), ntarg
1822 if (.not.
associated(state % parent))
return
1824 parent => state % parent
1825 nphot = parent % order
1826 ntarg =
size(moldat % etarg)
1827 ebase = moldat % etarg(1)
1829 z = moldat % nz - moldat % nelc
1830 dcomp = state % dcomp
1831 mgvnf = state % mgvn
1832 mgvni = parent % mgvn
1833 irrf = findloc(moldat % mgvns, mgvnf, 1)
1834 irri = findloc(moldat % mgvns, mgvni, 1)
1835 nchani = moldat % nchan(irri)
1838 do ichani = 1, nchani
1841 ichl = moldat % ichl(ichani, irri)
1842 etarg = moldat % etarg(ichl)
1843 echl = etarg - ebase
1847 l(n + 1) = moldat % l2p(ichani, irri)
1850 k(n + 1) = sqrt(2*abs(ek))
1851 if (ek < 0) k(n + 1) = k(n + 1) *
imu
1852 kr(1 : n + 1) = k(n + 1 : 1 : -1)
1853 lr(1 : n + 1) = l(n + 1 : 1 : -1)
1860 if (qion == 0 .and. qpws == 0) cycle
1863 ap = cmplx(parent % ap(ichani, 1, ie), parent % ap(ichani, 2, ie), wp)
1869 if (
allocated(cache % rchs_ion))
then
1870 irch = findloc(cache % rchs_ion, l(n + 1)*ntarg + ichl, 1)
1874 print
'(/,a,4(i0,a))',
'Error: Missing integral in cache for channel pair ', ichanf,
' (irr ', irrf, &
1875 ') - ', ichani,
' (irr ', irri,
')!'
1876 print
'(7x,a,*(1x,i0))',
'Available reduced channels in cache:', cache % rchs_ion
1877 print
'(7x,3(a,i0),a)',
'Needed reduced channel: ', l(n + 1)*ntarg + ichl, &
1878 ' (ichl = ', ichl,
', l = ', l(n + 1),
')'
1881 integ = integ + qion * ap * cache % vals_ion((3 - sb)/2, irch)
1885 print
'(/,a,4(i0,a))',
'Error: Missing integral chain for channel pair ', ichanf,
' (irr ', irrf, &
1886 ') - ', ichani,
' (irr ', irri,
')!'
1887 print
'(7x,a,*(1x,i0))',
'Available reduced channels in cache:', cache % rchs_ion
1888 print
'(7x,3(a,i0),a)',
'Needed reduced channel: ', l(n + 1)*ntarg + ichl, &
1889 ' (ichl = ', ichl,
', l = ', l(n + 1),
')'
1892 integ = integ + qion *
multiint_chain(moldat, r0, ei, esc - omega(nphot), omega, &
1893 ie, c, n + 1, parent, ichani, sb, k, l, m, &
1894 cache % next_ion(irch))
1899 if (ap /= 0) integ = integ + qion * ap *
nested_cgreen_integ(z, a, r0, c, n, +1, sb, mr, lr, kr)
1900 if (nphot > 0) integ = integ + qion *
multiint_chain(moldat, r0, ei, esc - omega(nphot), omega, &
1901 ie, c, n + 1, parent, ichani, sb, k, l, m)
1909 if (
allocated(cache % rchs_pws))
then
1910 irch = findloc(cache % rchs_pws, l(n + 1)*ntarg + ichl, 1)
1914 print
'(/,a,4(i0,a))',
'Error: Missing integral in cache for channel pair ', ichanf,
' (irr ', irrf, &
1915 ') - ', ichani,
' (irr ', irri,
')!'
1916 print
'(7x,a,*(1x,i0))',
'Available reduced channels in cache:', cache % rchs_pws
1917 print
'(7x,3(a,i0),a)',
'Needed reduced channel: ', l(n + 1)*ntarg + ichl, &
1918 ' (ichl = ', ichl,
', l = ', l(n + 1),
')'
1921 integ = integ + qpws * ap * cache % vals_pws((3 - sb)/2, irch)
1925 print
'(/,a,4(i0,a))',
'Error: Missing integral chain for channel pair ', ichanf,
' (irr ', irrf, &
1926 ') - ', ichani,
' (irr ', irri,
')!'
1927 print
'(7x,a,*(1x,i0))',
'Available reduced channels in cache:', cache % rchs_pws
1928 print
'(7x,3(a,i0),a)',
'Needed reduced channel: ', l(n + 1)*ntarg + ichl, &
1929 ' (ichl = ', ichl,
', l = ', l(n + 1),
')'
1932 integ = integ + qpws *
multiint_chain(moldat, r0, ei, esc - omega(nphot), omega, &
1933 ie, c, n + 1, parent, ichani, sb, k, l, m, &
1934 cache % next_pws(irch))
1939 if (ap /= 0) integ = integ + qpws * ap *
nested_cgreen_integ(z, a, r0, c, n, +1, sb, mr, lr, kr)
1940 if (nphot > 0) integ = integ + qpws *
multiint_chain(moldat, r0, ei, esc - omega(nphot), omega, &
1941 ie, c, n + 1, parent, ichani, sb, k, l, m)
1970 type(moleculardata),
intent(in) :: moldat
1971 integer,
intent(in) :: dcomp, irrf, irri, ichanf, ichani
1973 integer :: itargi, itargf, li, lf, mi, mf
1975 lf = moldat % l2p(ichanf, irrf); mf = moldat % m2p(ichanf, irrf); itargf = moldat % ichl(ichanf, irrf)
1976 li = moldat % l2p(ichani, irri); mi = moldat % m2p(ichani, irri); itargi = moldat % ichl(ichani, irri)
1978 if (lf /= li .or. mf /= mi)
then
1981 qion = moldat % crlv(itargf, itargi,
carti(dcomp))
2006 type(moleculardata),
intent(in) :: moldat
2007 integer,
intent(in) :: dcomp, irrf, irri, ichanf, ichani
2009 integer :: itargi, itargf, li, lf, mi, mf, ipwi, ipwf
2011 itargf = moldat % ichl(ichanf, irrf)
2012 itargi = moldat % ichl(ichani, irri)
2014 if (itargf /= itargi)
then
2017 lf = moldat % l2p(ichanf, irrf); mf = moldat % m2p(ichanf, irrf); ipwf = lf*(lf + 1) + mf + 1
2018 li = moldat % l2p(ichani, irri); mi = moldat % m2p(ichani, irri); ipwi = li*(li + 1) + mi + 1
2019 qpws = sqrt(4*
pi/3) * moldat % gaunt(ipwf, ipwi,
cartm(dcomp))
2061 type(moleculardata),
intent(in) :: moldat
2062 type(intermediatestate),
pointer,
intent(in) :: state
2063 type(intermediatestate),
pointer :: ptr, parent
2065 integer,
intent(in) :: order, erange(2)
2066 real(wp),
intent(in) :: escat(:), calc_Ei, first_IP, Ephoton(:)
2067 complex(wp),
intent(in) :: polar(:, :)
2068 integer :: nesc, ntarg, nchan, mxchan, lf, ichan, itarg, ie, irr, mgvn, mye, nirr, nene
2069 real(wp) :: Z, Ef, Ei, kf, sigma, Q
2070 complex(wp) :: d, ej
2071 complex(wp),
allocatable :: M(:, :, :)
2072 real(wp),
allocatable :: cs(:, :), omega(:)
2074 z = moldat % nz - moldat % nelc
2075 nirr =
size(moldat % mgvns)
2077 mxchan = maxval(moldat % nchan)
2078 ntarg =
size(moldat % etarg)
2085 nchan = moldat % nchan(irr)
2086 mxchan = max(mxchan, count(moldat % ichl(1:nchan, irr) <=
maxtarg))
2092 allocate (omega(order), m(mxchan, nene, 0:7), cs(2 + ntarg, nene))
2101 do while (
associated(ptr))
2102 if (ptr % order == order)
then
2105 ej = polar(ptr % dcomp, ptr % order)
2106 parent => ptr % parent
2107 do while (
associated(parent % parent))
2108 ej = ej * polar(parent % dcomp, parent % order)
2109 parent => parent % parent
2116 do ichan = 1,
size(ptr % dip, 1)
2117 d = ej * cmplx(ptr % dip(ichan, 1, mye), ptr % dip(ichan, 2, mye), wp)
2118 m(ichan, mye, ptr % mgvn) = m(ichan, mye, ptr % mgvn) + q * d
2139 mgvn = moldat % mgvns(irr)
2140 nchan = min(int(moldat % nchan(irr)), mxchan)
2142 lf = moldat % l2p(ichan, irr)
2143 ef = escat(ie) - moldat % etarg(moldat % ichl(ichan, irr)) + moldat % etarg(1)
2146 sigma =
cphase(z, lf, kf)
2147 m(ichan, mye, mgvn) = m(ichan, mye, mgvn) *
imu**(-lf) * (cos(sigma) +
imu*sin(sigma))
2153 cs(1, mye) = omega(1) * to_ev
2155 cs(2 + itarg, mye) = 0
2157 mgvn = moldat % mgvns(irr)
2158 nchan = min(int(moldat % nchan(irr)), mxchan)
2160 if (itarg == moldat % ichl(ichan, irr))
then
2161 d = m(ichan, mye, mgvn)
2162 cs(2 + itarg, mye) = cs(2 + itarg, mye) + real(d * conjg(d))
2167 cs(2, mye) = sum(cs(3:, mye))
2168 cs(2:, mye) = cs(2:, mye) * 2*
pi * (2*
pi*
alpha)**order * product(omega)
2204 subroutine calculate_asymmetry_parameters (moldat, order, state, escat, calc_Ei, first_IP, Ephoton, raw, erange, p, &
2211 character(len=*),
intent(in) :: raw
2212 type(moleculardata),
intent(in) :: moldat
2213 type(intermediatestate),
pointer,
intent(in) :: state
2214 type(intermediatestate),
pointer :: ptr, parent
2216 integer,
intent(in) :: order, erange(2), p(:), lu_pw_dipoles
2217 real(wp),
intent(in) :: escat(:), calc_Ei, first_IP, Ephoton(:)
2219 integer :: nesc, ii, li, mi, nchain, ichain
2220 integer :: ntarg, ichan, ie, mye, irr, L, nene, maxl, pw
2221 integer,
allocatable :: chains(:, :)
2222 real(wp),
allocatable :: omega(:), cs(:, :)
2223 complex(wp),
allocatable :: M_xyz(:, :, :, :), M_xyz_no_phase(:, :, :, :), M_sph(:, :, :, :), beta(:, :)
2225 real(wp) :: Z, Ek, k, sigma, Ei, Q
2226 character(len=50) :: filename
2228 z = moldat % nz - moldat % nelc
2231 maxl = maxval(moldat % l2p)
2232 ntarg =
size(moldat % etarg)
2237 maxl = maxval(moldat % l2p, moldat % ichl <=
maxtarg)
2243 do while (
associated(ptr))
2244 if (ptr % order == order)
then
2250 allocate (omega(order), chains(order, nchain), cs(ntarg, nene), beta(2 + ntarg, nesc), &
2251 m_xyz(nene, (maxl + 1)**2, nchain, ntarg), &
2252 m_sph(nene, (maxl + 1)**2, nchain, ntarg))
2258 if (order == 1)
then
2259 allocate(m_xyz_no_phase(nene, (maxl + 1)**2, nchain, ntarg))
2269 do while (
associated(ptr))
2270 if (ptr % order == order)
then
2273 irr = findloc(moldat % mgvns, ptr % mgvn, 1)
2278 do while (
associated(parent % parent))
2279 chains(parent % order, ichain) = mod(1 + parent % dcomp, 3) - 1
2280 parent => parent % parent
2284 do ichan = 1,
size(ptr % dip, 1)
2285 ii = moldat % ichl(ichan, irr)
2286 li = moldat % l2p(ichan, irr)
2287 mi = moldat % m2p(ichan, irr)
2288 pw = li*li + li + mi + 1
2292 ek = escat(ie) - moldat % etarg(ii) + moldat % etarg(1)
2296 d = cmplx(ptr % dip(ichan, 1, mye), ptr % dip(ichan, 2, mye), wp)
2297 if (.not. d == d) d = 0
2298 m_xyz(mye, pw, ichain, ii) =
imu**(-li) * (cos(sigma) +
imu*sin(sigma)) * q * d
2299 if (order == 1) m_xyz_no_phase(mye, pw, ichain, ii) = q * d
2309 if (order == 1)
then
2313 if (raw ==
'xyz' .or. raw ==
'both')
then
2320 if (raw ==
'sph' .or. raw ==
'both')
then
2327 print
'(/,A,I0,A,*(1x,I0))',
'Evaluating asymmetry parameter for L = ', l,
', p =', p(1:order)
2338 beta(1, mye) = omega(1) * to_ev
2339 beta(2:, mye) = beta(2:, mye) * 2*
pi * (2*
pi*
alpha)**order * product(abs(omega))
2341 cs(:, mye) = real(beta(3:, mye))
2342 beta(2, mye) = sum(cs(:, mye))
2344 where (cs(:, mye) > 0)
2345 beta(3:, mye) = beta(3:, mye) / cs(:, mye)
2352 write (filename,
'(A,I0,A,I0,A)')
'gen_', order,
'photo_beta_', l,
'.txt'
2369 use dipelm_special_functions,
only: sph_basis_transform_elm
2371 complex(wp),
allocatable,
intent(in) :: M_xyz(:, :, :, :)
2372 complex(wp),
allocatable,
intent(inout) :: M_sph(:, :, :, :)
2373 integer,
intent(in) :: maxl, chains(:, :)
2375 integer :: order, ntarg, nchain, i, ii, l, mi, mj, pwi, pwj, ichain, jchain
2378 order =
size(chains, 1)
2379 nchain =
size(chains, 2)
2380 ntarg =
size(m_xyz, 4)
2385 do ichain = 1, nchain
2386 do jchain = 1, nchain
2390 cpl = conjg(sph_basis_transform_elm(l, mj, mi,
'Slm'))
2392 cpl = cpl * sph_basis_transform_elm(1, chains(i, jchain), chains(i, ichain),
'Slm')
2394 pwi = l*l + l + mi + 1
2395 pwj = l*l + l + mj + 1
2396 m_sph(:, pwj, jchain, ii) = m_sph(:, pwj, jchain, ii) + cpl * m_xyz(:, pwi, ichain, ii)
2417 use mpi_gbl,
only: mpi_reduceall_inplace_sum_wp
2421 complex(wp),
allocatable,
intent(inout) :: beta(:, :)
2422 complex(wp),
allocatable,
intent(in) :: M1(:, :, :, :), M2(:, :, :, :)
2423 integer,
intent(in) :: L, maxl, chains1(:, :), chains2(:, :), ntarg, nesc, p(:)
2426 real(wp),
allocatable :: T(:, :, :, :), buffer(:)
2427 integer :: ie, mye, itarg, idx, li, mi, lj, mj, pwi, pwj, ichain, jchain, nchain1, nchain2, order1, order2
2428 integer :: qi(size(chains1, 1)), qj(size(chains2, 1))
2430 if (any(abs(p) > 1))
then
2431 print
'(/,A,I0)',
'calculate_quadratic_dipole_sph: lab-frame polarisation p out of range', p
2436 order1 =
size(chains1, 1); nchain1 =
size(chains1, 2)
2437 order2 =
size(chains2, 1); nchain2 =
size(chains2, 2)
2439 if (order1 /= order2)
then
2440 print
'(A)',
'WARNING: calculate_quadratic_dipole_sph is implemented only equal absorption orders'
2444 allocate (t((maxl + 1)**2, (maxl + 1)**2, nchain1, nchain2))
2448 do jchain = 1, nchain2
2449 do ichain = 1, nchain1
2450 do pwj = 1, (maxl + 1)**2
2451 do pwi = 1, (maxl + 1)**2
2452 t(pwi, pwj, ichain, jchain) = 0
2461 do idx =
myproc, (maxl + 1)**4 * nchain1 * nchain2,
nprocs
2464 pwi = 1 + (idx - 1) / (nchain2 * nchain1 * (maxl + 1)**2)
2465 pwj = 1 + mod((idx - 1) / (nchain2 * nchain1), (maxl + 1)**2)
2466 ichain = 1 + mod((idx - 1) / nchain2, nchain1)
2467 jchain = 1 + mod( idx - 1, nchain2)
2470 li = floor(sqrt(pwi - 1._wp))
2471 mi = pwi - li*li - li - 1
2472 qi = chains1(:, ichain)
2475 lj = floor(sqrt(pwj - 1._wp))
2476 mj = pwj - lj*lj - lj - 1
2477 qj = chains2(:, jchain)
2479 t(pwi, pwj, ichain, jchain) =
beta_contraction_tensor(l, order1, p, li, mi, qi, lj, mj, qj)
2484 buffer = reshape(t, [
size(t)])
2485 call mpi_reduceall_inplace_sum_wp(buffer,
size(buffer))
2486 t = reshape(buffer, shape(t))
2491 do idx = 1, ntarg * (maxl + 1)**4 * nchain1 * nchain2
2494 itarg = 1 + (idx - 1) / (nchain2 * nchain1 * (maxl + 1)**4)
2495 pwi = 1 + mod((idx - 1) / (nchain2 * nchain1 * (maxl + 1)**2), (maxl + 1)**2)
2496 pwj = 1 + mod((idx - 1) / (nchain2 * nchain1), (maxl + 1)**2)
2497 ichain = 1 + mod((idx - 1) / nchain2, nchain1)
2498 jchain = 1 + mod( idx - 1, nchain2)
2501 li = floor(sqrt(pwi - 1._wp))
2502 mi = pwi - li*li - li - 1
2505 lj = floor(sqrt(pwj - 1._wp))
2506 mj = pwj - lj*lj - lj - 1
2511 mm = conjg(m1(mye, pwi, ichain, itarg)) * m2(mye, pwj, jchain, itarg)
2512 beta(2 + itarg, mye) = beta(2 + itarg, mye) + t(pwi, pwj, ichain, jchain) * mm
2535 complex(wp),
allocatable,
intent(inout) :: beta(:, :)
2536 complex(wp),
allocatable,
intent(in) :: M1(:, :, :, :), M2(:, :, :, :)
2537 integer,
intent(in) :: L, maxl, chains1(:, :), chains2(:, :), ntarg, nesc
2541 integer :: ie, mye, itarg, pwi, qi(size(chains1, 1)), qj(size(chains2, 1)), ichain, jchain
2546 print
'(A)',
'WARNING: calculate_quadratic_dipole_xyz is implemented only for L = 0'
2553 do ichain = 1,
size(chains1, 2)
2554 do jchain = 1,
size(chains2, 2)
2555 qi = chains1(:, ichain)
2556 qj = chains2(:, jchain)
2558 do pwi = 1, (maxl + 1)**2
2563 mm = conjg(m1(mye, pwi, ichain, itarg)) * m2(mye, pwi, jchain, itarg)
2564 beta(2 + itarg, mye) = beta(2 + itarg, mye) + t * mm
Special integrals needed by MULTIDIP.
complex(wp) function nested_cgreen_integ(z, a, r0, c, n, sa, sb, m, l, k)
Multi-dimensional integral of Coulomb-Hankel and Coulomb-Green functions and powers.
I/O routines used by MULTIDIP.
subroutine read_bndcoeffs(bnd, ei, lubnd, mgvn0, stot0)
Read inner bound wave function coefficients.
subroutine read_wfncoeffs(ak, lusct)
Read wave function coefficients from files.
subroutine apply_boundary_amplitudes(moldat, irr, transp, x, y)
Multiply by boundary amplitudes.
subroutine scale_boundary_amplitudes(moldat, irr, v, vw)
Scale boundary amplitudes matrix by a diagonal matrix.
subroutine write_rsolve_dipoles(moldat, m, chains, escat, lu_pw_dipoles)
Write transition dipole moments in RSOLVE format.
subroutine get_diptrans(moldat, i, iidip, ifdip)
Return dipole transition descriptors.
subroutine write_cross_section(cs, nesc, erange, filename)
Write cross sections to a file.
subroutine write_raw_dipoles(m, chains, nesc, stem)
Write raw transition dipole moments.
subroutine apply_dipole_matrix(moldat, component, irrpair, transp, nf, nn, x, y)
Multiply by dipole matrix.
subroutine read_molecular_data(moldat, filename, mpiio, read_wmat2)
Read RMT molecular_data file.
subroutine read_kmatrices(km, lukmt, nkset)
Read K-matrix files.
subroutine write_partial_wave_moments(moldat, m, nesc, suffix)
Write partial wave moments.
subroutine write_energy_grid(escat)
Write photoelectron energies to file.
Routines related to outer region asymptotic channels.
subroutine test_outer_expansion(filename, moldat, irr, ck, ap, etot)
Evaluate wfn in channels for inside and outside of the R-matrix sphere.
subroutine evaluate_fundamental_solutions(moldat, r, irr, nopen, ek, s, c, sp, cp, sqrtknorm)
Evaluate asymptotic solutions at boundary.
Hard-coded parameters of MULTIDIP.
logical extend_istate
Continue initial state from the known inner region expansion outwards.
subroutine read_input_namelist(input, order, lusct, lukmt, lubnd, nkset, polar, omega, verbose, rmt_data, first_ip, rasym, raw, erange, mpiio, gpu, lab_polar, lu_pw_dipoles)
logical closed_interm
Consider weakly closed channel in intermediate states (unfinished!)
logical custom_kmatrices
Ignore RSOLVE K-matrices and calculate them from scratch.
integer num_integ_algo
Numerical integration mode (1 = Romberg, 2 = Levin)
integer, dimension(3), parameter carti
Position of a Cartesian coordinate in the real spherical basis (y, z, x).
character(len=1), dimension(3), parameter compt
logical cache_integrals
Cache Coulomb-Green integrals in memory (but disables some threading)
complex(wp), parameter imu
complex(wp), parameter cone
real(wp) closed_range
Energy interval (a.u.) before threshold for inclusion of closed channels.
real(wp), parameter rzero
integer maxtarg
Maximal number of target states to calculate dipoles for (0 = all)
real(wp), parameter alpha
Fine structure constant.
integer, dimension(3), parameter cartm
Real spherical harmonic m-value corresponding to given a Cartesian coord.
complex(wp), parameter czero
integer, parameter nmaxphotons
The limit on number of photons is nested_cgreen_integ
real(wp) function channel_coupling_ion(moldat, dcomp, irrf, irri, ichanf, ichani)
Ion channel dipole coupling.
subroutine solve_intermediate_state(moldat, order, ephoton, icomp, s, cache, mgvnn, mgvn1, mgvn2, km, state, verbose, calc_ei, first_ip, r0, erange)
Calculate intermediate photoionisation state.
subroutine test_final_expansion(filename, moldat, irr, nopen, etot, ek, sp, cp, kmat, tmat)
Write radially sampled final wave-function to file.
subroutine calculate_photon_energies(first_ip, escat, etarg, ei, ephoton, omega)
Adjust ionization potential and calculate energy of each photon.
subroutine calculate_quadratic_dipole_sph(beta, l, maxl, chains1, chains2, ntarg, nesc, m1, m2, p)
Evaluate asymmetry parameter for given total L in the spherical basis.
recursive subroutine precompute_integral_cache_block(integral_cache, moldat, pws_coupled, ion_coupled, order, omega, escat, r0, rchs, ms, ks, ls)
Precompute outer radial integrals (implementation)
recursive subroutine print_integral_cache_block(cache, ntarg, level, chain)
Print precomputed integrals.
subroutine reset_timer(t, dt)
Get current time stamp.
logical, parameter test_expansion
subroutine calculate_quadratic_dipole_xyz(beta, l, maxl, chains1, chains2, ntarg, nesc, m1, m2)
Evaluate asymmetry parameter for given total L in the Cartesian basis.
subroutine extract_dipole_elements(moldat, order, ephoton, icomp, s, cache, mgvnn, mgvn1, mgvn2, km, ak, state, verbose, calc_ei, first_ip, r0, erange)
Calculate dipole elements from intermediate and final states.
subroutine multiint(moldat, r0, ei, esc, omega, ie, state, sb, dip, cache)
Evaluate the correction dipole integral for all orders.
subroutine print_integral_cache(cache, erange, ntarg)
Print precomputed integrals.
recursive complex(wp) function multiint_chain(moldat, r0, ei, esc, omega, ie, c, n, state, ichanf, sb, k, l, m, cache)
Calculate dipole correction integrals at given absorption depth.
real(wp) function channel_coupling_pws(moldat, dcomp, irrf, irri, ichanf, ichani)
Partial wave channel dipole coupling.
subroutine print_transition_header(state)
Prints a one-line summary of the transition.
subroutine setup_initial_state(states, moldat, irr, lubnd, ei)
Construct initial state.
subroutine multidip_driver(order, moldat, km, ak, lubnd, omega, polar, verbose, first_ip, r0, raw, erange, p, lu_pw_dipoles)
Central computation routine.
subroutine convert_xyz_to_sph(m_xyz, m_sph, maxl, chains)
Change coordiantes.
subroutine precompute_integral_cache(integral_cache, moldat, esc, nphot, r0, erange, calc_ei, first_ip, ephoton, verbose)
Precompute outer radial integrals (driver)
subroutine calculate_asymmetry_parameters(moldat, order, state, escat, calc_ei, first_ip, ephoton, raw, erange, p, lu_pw_dipoles)
Calculate cross sections and asymmetry parameters.
subroutine calculate_pw_transition_elements(moldat, order, state, escat, calc_ei, first_ip, ephoton, polar, erange)
Calculate partial wave dipoles, oriented dipoles and cross sections.
subroutine multidip_main
MULTIDIP main subroutine.
Special functions and objects used by MULTIDIP.
real(wp) function beta_contraction_tensor(j, n, p, li, mi, qi, lj, mj, qj)
Angular part of the beta parameters.
subroutine solve_complex_system(n, a, x, y)
Solve system of equations with complex matrix.
real(wp) recursive function cartesian_vector_component_product_average(q)
Return Cartesian invariant.
real(wp) function cphase(z, l, k)
Coulomb phase.
subroutine coul(z, l, ek, r, f, fp, g, gp)
Coulomb functions.
subroutine run_tests
Numerical unit tests.
Multi-photon integral cache.