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
31 use blas_lapack_gbl,
only: blasint
32 use phys_const_gbl,
only: pi, imu
33 use precisn_gbl,
only: wp
37 real(wp),
parameter ::
rzero = 0
38 real(wp),
parameter ::
rone = 1
42 type, bind(c) :: gsl_sf_result
45 end type gsl_sf_result
49 function gsl_sf_lngamma_complex_e (zr, zi, lnr, arg) bind(C, name='gsl_sf_lngamma_complex_e')
50 use,
intrinsic :: iso_c_binding, only: c_int, c_double
52 real(c_double),
value :: zi, zr
53 type(gsl_sf_result) :: lnr, arg
54 integer(c_int) :: gsl_sf_lngamma_complex_e
55 end function gsl_sf_lngamma_complex_e
60 function gsl_sf_coulomb_wave_fg_e (eta, rho, l, k, F, Fp, G, Gp, expF, expG) bind(C, name='gsl_sf_coulomb_wave_FG_e')
61 use,
intrinsic :: iso_c_binding, only: c_int, c_double
63 real(c_double),
value :: eta, rho, l
64 integer(c_int),
value :: k
65 type(gsl_sf_result) :: f, fp, g, gp
66 real(c_double) :: expf, expg
67 integer(c_int) :: gsl_sf_coulomb_wave_fg_e
68 end function gsl_sf_coulomb_wave_fg_e
73 pure function gsl_sf_hyperg_u (a, b, x) bind(C, name='gsl_sf_hyperg_U')
74 use,
intrinsic :: iso_c_binding, only: c_double
75 real(c_double),
value :: a, b, x
76 real(c_double) :: gsl_sf_hyperg_u
77 end function gsl_sf_hyperg_u
86 real(wp) :: eta,
cphaz 92 subroutine coulfg (xx, eta1, xlmin, xlmax, fc, gc, fcp, gcp, mode1, kfn, ifail)
94 integer :: mode1, kfn, ifail
95 real(wp) :: xx, eta1, xlmin, xlmax, fc(*), gc(*), fcp(*), gcp(*)
101 subroutine couln (l, Z, ERy, r, U, Up, acc, efx, ierr, nlast, fnorm)
103 integer :: l, ierr, nlast
104 real(wp) :: Z, Ery, r, U, Up, acc, efx, fnorm
110 subroutine decay (k, l, r, U, Up, iwrite)
113 real(wp) :: k, r, U, Up
119 subroutine dgemm (transa, transb, m, n, k, alpha, A, lda, B, ldb, beta, C, ldc)
120 import real64, blasint
121 character(len=1) :: transa, transb
122 integer(blasint) :: m, n, k, lda, ldb, ldc
123 real(real64) :: A(lda, *), B(ldb, *), C(ldc, *), alpha, beta
129 subroutine dgemv (trans, m, n, alpha, A, lda, X, incx, beta, Y, incy)
130 import real64, blasint
131 character(len=1) :: trans
132 integer(blasint) :: m, n, incx, incy, lda
133 real(real64) :: A(lda, *), X(*), Y(*), alpha, beta
139 subroutine zgemv (trans, m, n, alpha, A, lda, X, incx, beta, Y, incy)
140 import real64, blasint
141 character(len=1) :: trans
142 integer(blasint) :: m, n, incx, incy, lda
143 complex(real64) :: A(lda, *), X(*), Y(*), alpha, beta
149 subroutine zgetrf (m, n, A, lda, ipiv, info)
150 import real64, blasint
151 integer(blasint) :: m, n, lda, ipiv(*), info
152 complex(real64) :: A(lda, *)
158 subroutine zgetrs (trans, n, nrhs, A, lda, ipiv, B, ldb, info)
159 import real64, blasint
160 character(len=1) :: trans
161 integer(blasint) :: n, nrhs, lda, ldb, info, ipiv(*)
162 complex(real64) :: A(lda, *), B(ldb, *)
168 subroutine zgetri (n, A, lda, ipiv, work, lwork, info)
169 import real64, blasint
170 integer(blasint) :: n, lda, ipiv(*), lwork, info
171 complex(real64) :: A(lda, *), work(*)
186 subroutine calculate_s_matrix (Km, Sm, nopen)
188 complex(wp),
allocatable,
intent(inout) :: Sm(:, :)
189 real(wp),
intent(in) :: Km(:, :)
190 integer,
intent(in) :: nopen
192 complex(wp),
allocatable :: IpiK(:, :), ImiK(:, :)
199 allocate (ipik(nchan, nchan), imik(nchan, nchan))
201 ipik = 0;
forall (i = 1:nchan) ipik(i, i) = 1
202 imik = 0;
forall (i = 1:nchan) imik(i, i) = 1
203 ipik(1:nopen, 1:nopen) = ipik(1:nopen, 1:nopen) + imu*km(1:nopen, 1:nopen)
204 imik(1:nopen, 1:nopen) = imik(1:nopen, 1:nopen) - imu*km(1:nopen, 1:nopen)
208 sm = matmul(ipik, imik)
210 end subroutine calculate_s_matrix
220 subroutine scatak (rmatr, eig, etot, w, Ek, l, Km, Ak)
222 complex(wp),
allocatable,
intent(inout) :: Ak(:,:)
223 real(wp),
intent(in) :: rmatr, eig(:), etot, Ek(:), w(:,:), Km(:,:)
224 integer,
intent(in) :: l(:)
226 complex(wp),
allocatable :: T(:,:)
227 real(wp),
allocatable :: V(:,:), TT(:,:,:), Sp(:,:), Cp(:,:), P(:), XX(:,:,:), wFp(:,:,:), k(:)
229 integer(blasint) :: i, j, nchan, nstat, nchan2, nopen, nopen2
230 real(wp) :: F, Fp, G, Gp
234 nopen = count(ek > 0)
239 allocate (v(nchan, nchan), t(nopen, nopen), sp(nchan, nchan), cp(nchan, nchan), tt(nchan, nopen, 2), &
240 xx(nchan, nopen, 2), wfp(nstat, nopen, 2))
242 t = 0; v = 0; sp = 0; cp = 0
245 forall (i = 1:nopen) t(i,i) = 1
246 t = t + imu*km(1:nopen, 1:nopen)
248 tt(1:nopen, 1:nopen, 1) =
real(T, wp)
249 tt(1:nopen, 1:nopen, 2) = aimag(t)
253 call coul(l(i), ek(i), rmatr, f, fp, g, gp)
254 v(i,i) = sqrt(2/(pi*k(i)))
260 call dgemm(
'N',
'N', nchan, nopen, nchan,
rone, cp, nchan, km, nchan,
rone, sp, nchan)
261 call dgemm(
'N',
'N', nchan, nopen2, nopen,
rone, sp, nchan, tt, nchan,
rzero, xx, nchan)
262 call dgemm(
'N',
'N', nchan, nopen2, nchan,
rone, v, nchan, xx, nchan,
rzero, tt, nchan)
263 call dgemm(
'T',
'N', nstat, nopen2, nchan,
rone, w, nchan, tt, nchan,
rzero, wfp, nstat)
264 p = 0.5 / (eig - etot)
266 ak(:, i) = p * cmplx(wfp(:, i, 1), wfp(:, i, 2), wp)
268 do i = nopen + 1, nchan
272 end subroutine scatak
282 real(wp) function cphase (l, k)
result (sigma)
284 integer,
intent(in) :: l
285 real(wp),
intent(in) :: k
287 type(gsl_sf_result) :: lnr, arg
288 integer(c_int) :: err
289 real(c_double) :: zr, zi
293 err = gsl_sf_lngamma_complex_e(zr, zi, lnr, arg)
296 sigma =
cphaz(l, -1/k, 0)
314 subroutine coul (l, Ek, r, F, Fp, G, Gp)
316 integer,
intent(in) :: l
317 real(wp),
intent(in) :: Ek, r
318 real(wp),
intent(inout) :: F, Fp, G, Gp
321 call coul_gsl(l, ek, r, f, fp, g, gp)
334 subroutine coul_gsl (l, Ek, r, F, Fp, G, Gp)
336 integer,
intent(in) :: l
337 real(wp),
intent(in) :: Ek, r
338 real(wp),
intent(inout) :: F, Fp, G, Gp
341 type(gsl_sf_result) :: resF, resFp, resG, resGp
342 real(c_double) :: expF, expG, eta, rho, lc, k, a, b, x, U, Up
343 integer(c_int) :: err, zero = 0
351 err = gsl_sf_coulomb_wave_fg_e(eta, rho, lc, zero, resf, resfp, resg, resgp, expf, expg)
362 u = gsl_sf_hyperg_u(a, b, x)
363 up = -2*k*a * gsl_sf_hyperg_u(a + 1, b + 1, x)
366 g = exp(-x/2) * x**(l + 1) * u
367 gp = exp(-x/2) * x**(l + 1) * (-k * u + (l + 1)/r * u + up)
384 integer,
intent(in) :: l
385 real(wp),
intent(in) :: Ek, r
386 real(wp),
intent(inout) :: F, Fp, G, Gp
388 integer :: ifail, mode = 1, kfn = 0, nterms, iwrite = 0
389 real(wp) :: fc(l + 1), gc(l + 1), fcp(l + 1), gcp(l + 1), lc, efx, fnorm, acc = 1e-10_wp, k
395 call coulfg(k*r, -z/k, lc, lc, fc, gc, fcp, gcp, mode, kfn, ifail)
403 call couln(l, z, 2*ek, r, g, gp, acc, efx, ifail, nterms, fnorm)
405 call decay(2*ek, l, r, g, gp, iwrite)
422 complex(wp),
allocatable,
intent(inout) :: T(:, :)
424 complex(wp),
allocatable :: work(:)
425 complex(wp) :: nwork(1)
427 integer(blasint),
allocatable :: ipiv(:)
428 integer(blasint) :: m, info, lwork
434 call zgetrf(m, m, t, m, ipiv, info)
438 call zgetri(m, t, m, ipiv, nwork, lwork, info)
439 lwork = int(nwork(1))
440 allocate (work(lwork))
443 call zgetri(m, t, m, ipiv, work, lwork, info)
457 complex(wp),
allocatable,
intent(inout) :: A(:, :)
458 real(wp),
allocatable,
intent(inout) :: X(:, :), Y(:, :)
459 integer,
intent(in) :: n
461 integer(blasint) :: m, info, nrhs, lda
462 integer(blasint),
allocatable :: ipiv(:)
463 complex(wp),
allocatable :: XX(:)
470 call zgetrf(m, m, a, lda, ipiv, info)
473 xx = cmplx(x(1:n, 1), x(1:n, 2), wp)
477 call zgetrs(
'N', m, nrhs, a, lda, ipiv, xx, m, info)
479 y(1:n, 1) =
real(XX, wp)
480 y(1:n, 2) = aimag(xx)
499 integer,
intent(inout) :: p(:)
500 integer :: i, j, k, n
512 forall (i = 1 : n) p(i) = i
528 if (p(i) < p(k))
then 530 do while (p(i) >= p(j))
533 call swap(p(i), p(j))
537 else if (i == 1)
then 552 subroutine swap (a, b)
554 integer,
intent(inout) :: a, b
572 integer,
intent(inout) :: a(:)
578 call swap(a(i), a(n + 1 - i))
600 complex(wp),
intent(inout) :: X, err
601 complex(wp),
intent(in) :: dX
subroutine coul_gsl(l, Ek, r, F, Fp, G, Gp)
Coulomb functions (GSL)
subroutine invert_matrix(T)
Invert a complex matrix.
subroutine kahan_add(X, dX, err)
Compensated summation.
subroutine reverse(a)
Reverse order of elements in array.
subroutine coul_ukrmol(l, Ek, r, F, Fp, G, Gp)
Coulomb functions (UKRmol)
logical function next_permutation(p)
Construct or advance permutation.
subroutine solve_complex_system(n, A, X, Y)
Solve system of equations with complex matrix.
real(wp) function cphase(l, k)
Coulomb phase.
Special functions and objects used by MULTIDIP.
subroutine swap(a, b)
Exchange value of two integers.
subroutine coul(l, Ek, r, F, Fp, G, Gp)
Coulomb functions.
real(wp), parameter rzero