|
| 1 | + module metal_sphere |
| 2 | + |
| 3 | + use, intrinsic :: iso_c_binding |
| 4 | + |
| 5 | + implicit none |
| 6 | + |
| 7 | + public greens_function |
| 8 | + |
| 9 | + private |
| 10 | + |
| 11 | + contains |
| 12 | + |
| 13 | + subroutine greens_function(epssol, epsre, epsim, radius, & |
| 14 | + ps, p1, p2, greenre, greenim) bind(c, name='greens_function') |
| 15 | + |
| 16 | +! Passed variables |
| 17 | + real(c_double), intent(in) :: epssol, epsre, epsim, radius |
| 18 | + real(c_double), intent(in) :: p1(*), p2(*), ps(*) |
| 19 | + real(c_double), intent(out) :: greenre, greenim |
| 20 | +! Local variables |
| 21 | + complex(16) :: gsfera, green, eps2, ui |
| 22 | + |
| 23 | + ui = (0.0, 1.0) |
| 24 | + eps2 = epsre + epsim * ui |
| 25 | + green = gsfera(epssol, eps2, ps(1), ps(2), ps(3), radius, & |
| 26 | + p1(1), p1(2), p1(3), & |
| 27 | + p2(1), p2(2), p2(3)) |
| 28 | + greenre = real(real(green)) |
| 29 | + greenim = real(aimag(green)) |
| 30 | + |
| 31 | + end subroutine greens_function |
| 32 | + |
| 33 | + complex(16) function gsfera(eps, eps2, xs, ys, zs, rs, & |
| 34 | + xi, yi, zi, xj, yj, zj) |
| 35 | +! Passed variables |
| 36 | + real(8), intent(in) :: eps |
| 37 | + complex(16), intent(in) :: eps2 |
| 38 | + real(8), intent(in) :: xs, ys, zs, rs ! Sphere center and radius |
| 39 | + real(8), intent(in) :: xi, yi, zi ! Source point |
| 40 | + real(8), intent(in) :: xj, yj, zj ! Probe point |
| 41 | +! Local variables |
| 42 | + complex(16) :: coefl |
| 43 | + real(8) :: di, dj |
| 44 | + real(8) :: dim, xim, yim, zim, qim ! Image quantities |
| 45 | + real(8) :: gc, cost, aa, arg, argl, gsfera2 |
| 46 | + integer :: maxl, l, m |
| 47 | + |
| 48 | +!lf print *, eps,eps2 |
| 49 | +!lf print *, 'Sphere', xs,ys,zs,rs |
| 50 | +!lf print *, 'Source', xi,yi,zi |
| 51 | +!lf print *, 'Probe ', xj,yj,zj |
| 52 | + di = sqrt((xi - xs)**2 + (yi - ys)**2 + (zi - zs)**2) |
| 53 | + dj = sqrt((xj - xs)**2 + (yj - ys)**2 + (zj - zs)**2) |
| 54 | + dim = rs**2 / di |
| 55 | + xim = dim * (xi - xs) / (di + xs) |
| 56 | + yim = dim * (yi - ys) / (di + ys) |
| 57 | + zim = dim * (zi - zs) / (di + zs) |
| 58 | + qim = rs / di |
| 59 | + gc = qim / sqrt((xj - xim)**2 + (yj - yim)**2 + (zj - zim)**2) |
| 60 | + gc = gc - qim / sqrt((xj - xs)**2 + (yj - ys)**2 + (zj - zs)**2) |
| 61 | + cost = (xj - xs) * (xi - xs) + (yj - ys) * (yi - ys) + (zj - zs) * (zi - zs) |
| 62 | + cost = cost / (di * dj) |
| 63 | + aa = (rs * rs / (di * dj))**4. |
| 64 | + maxl = int(800. / (abs(eps2 + eps))**0.4 * aa) |
| 65 | + maxl = max(maxl, 10) |
| 66 | +!lf write (6,*) "maxl",maxl |
| 67 | + arg = rs * rs / (di * dj) |
| 68 | + argl = rs / (di * dj) |
| 69 | + gsfera2 = 0.0d0 |
| 70 | + m = 0 |
| 71 | + do l = 1, maxl |
| 72 | + argl = argl * arg |
| 73 | + coefl = (eps2 - eps) * float(l) / ((eps2 + eps) * float(l) + 1.0d0) |
| 74 | + coefl = coefl - (eps2 - eps) / (eps2 + eps) |
| 75 | + gsfera = gsfera + coefl * argl * legendre_polynomial(l, m, cost) |
| 76 | + enddo |
| 77 | + gsfera = gsfera + gc * (eps2- eps) / (eps2 + eps) |
| 78 | +!lf: WARNING: sign change and divided by epsilon of solvent!!!!!! |
| 79 | + gsfera = -gsfera / eps |
| 80 | +! DEBUGGING STUFF |
| 81 | +! arg = rs * rs / (di * dj) |
| 82 | +! argl = rs / (di * dj) |
| 83 | +! gsfera = 0.0d0 |
| 84 | +! m = 0 |
| 85 | +! do l = 1, 5000 |
| 86 | +! argl = argl * arg |
| 87 | +! coefl = (eps2 - eps) * float(l) / ((eps2 + eps) * float(l) + 1.0d0) |
| 88 | +! gsfera = gsfera + coefl * argl * legendre_polynomial(l, m, cost) |
| 89 | +! enddo |
| 90 | +!lf write (6, *) "gsfera2", gsfera |
| 91 | + end |
| 92 | + |
| 93 | + real(8) function legendre_polynomial(l, m, x) |
| 94 | +! Computes the associated Legendre polynomial P_l^m(x) |
| 95 | +! Passed variables |
| 96 | + integer, intent(in) :: l, m |
| 97 | + real(8), intent(in) :: x |
| 98 | +! Local variables |
| 99 | + integer :: i, ll |
| 100 | + real(8) :: fact, pll, pmm, pmmp1, somx2 |
| 101 | + |
| 102 | + pmm = 1.0d0 |
| 103 | + if (m .gt. 0) then |
| 104 | + somx2 = sqrt((1.0 - x) * (1.0 + x)) |
| 105 | + fact = 1.0d0 |
| 106 | + do i = 1, m |
| 107 | + pmm = -pmm * fact * somx2 |
| 108 | + fact = fact + 2.0d0 |
| 109 | + enddo |
| 110 | + endif |
| 111 | + if (l .eq. m) then |
| 112 | + legendre_polynomial = pmm |
| 113 | + else |
| 114 | + pmmp1 = x * (2 * m + 1) * pmm |
| 115 | + if (l .eq. m + 1) then |
| 116 | + legendre_polynomial = pmmp1 |
| 117 | + else |
| 118 | + do ll = m + 2, l |
| 119 | + pll = (x * (2.0 * ll - 1) * pmmp1 - (ll + m - 1) * pmm) / (ll - m) |
| 120 | + pmm = pmmp1 |
| 121 | + pmmp1 = pll |
| 122 | + enddo |
| 123 | + legendre_polynomial = pll |
| 124 | + endif |
| 125 | + endif |
| 126 | + |
| 127 | + end function legendre_polynomial |
| 128 | + |
| 129 | + end module metal_sphere |
0 commit comments