hydrogen.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. from sympy.core.numbers import Float
  2. from sympy.core.singleton import S
  3. from sympy.functions.combinatorial.factorials import factorial
  4. from sympy.functions.elementary.exponential import exp
  5. from sympy.functions.elementary.miscellaneous import sqrt
  6. from sympy.functions.special.polynomials import assoc_laguerre
  7. from sympy.functions.special.spherical_harmonics import Ynm
  8. def R_nl(n, l, r, Z=1):
  9. """
  10. Returns the Hydrogen radial wavefunction R_{nl}.
  11. Parameters
  12. ==========
  13. n : integer
  14. Principal Quantum Number which is
  15. an integer with possible values as 1, 2, 3, 4,...
  16. l : integer
  17. ``l`` is the Angular Momentum Quantum Number with
  18. values ranging from 0 to ``n-1``.
  19. r :
  20. Radial coordinate.
  21. Z :
  22. Atomic number (1 for Hydrogen, 2 for Helium, ...)
  23. Everything is in Hartree atomic units.
  24. Examples
  25. ========
  26. >>> from sympy.physics.hydrogen import R_nl
  27. >>> from sympy.abc import r, Z
  28. >>> R_nl(1, 0, r, Z)
  29. 2*sqrt(Z**3)*exp(-Z*r)
  30. >>> R_nl(2, 0, r, Z)
  31. sqrt(2)*(-Z*r + 2)*sqrt(Z**3)*exp(-Z*r/2)/4
  32. >>> R_nl(2, 1, r, Z)
  33. sqrt(6)*Z*r*sqrt(Z**3)*exp(-Z*r/2)/12
  34. For Hydrogen atom, you can just use the default value of Z=1:
  35. >>> R_nl(1, 0, r)
  36. 2*exp(-r)
  37. >>> R_nl(2, 0, r)
  38. sqrt(2)*(2 - r)*exp(-r/2)/4
  39. >>> R_nl(3, 0, r)
  40. 2*sqrt(3)*(2*r**2/9 - 2*r + 3)*exp(-r/3)/27
  41. For Silver atom, you would use Z=47:
  42. >>> R_nl(1, 0, r, Z=47)
  43. 94*sqrt(47)*exp(-47*r)
  44. >>> R_nl(2, 0, r, Z=47)
  45. 47*sqrt(94)*(2 - 47*r)*exp(-47*r/2)/4
  46. >>> R_nl(3, 0, r, Z=47)
  47. 94*sqrt(141)*(4418*r**2/9 - 94*r + 3)*exp(-47*r/3)/27
  48. The normalization of the radial wavefunction is:
  49. >>> from sympy import integrate, oo
  50. >>> integrate(R_nl(1, 0, r)**2 * r**2, (r, 0, oo))
  51. 1
  52. >>> integrate(R_nl(2, 0, r)**2 * r**2, (r, 0, oo))
  53. 1
  54. >>> integrate(R_nl(2, 1, r)**2 * r**2, (r, 0, oo))
  55. 1
  56. It holds for any atomic number:
  57. >>> integrate(R_nl(1, 0, r, Z=2)**2 * r**2, (r, 0, oo))
  58. 1
  59. >>> integrate(R_nl(2, 0, r, Z=3)**2 * r**2, (r, 0, oo))
  60. 1
  61. >>> integrate(R_nl(2, 1, r, Z=4)**2 * r**2, (r, 0, oo))
  62. 1
  63. """
  64. # sympify arguments
  65. n, l, r, Z = map(S, [n, l, r, Z])
  66. # radial quantum number
  67. n_r = n - l - 1
  68. # rescaled "r"
  69. a = 1/Z # Bohr radius
  70. r0 = 2 * r / (n * a)
  71. # normalization coefficient
  72. C = sqrt((S(2)/(n*a))**3 * factorial(n_r) / (2*n*factorial(n + l)))
  73. # This is an equivalent normalization coefficient, that can be found in
  74. # some books. Both coefficients seem to be the same fast:
  75. # C = S(2)/n**2 * sqrt(1/a**3 * factorial(n_r) / (factorial(n+l)))
  76. return C * r0**l * assoc_laguerre(n_r, 2*l + 1, r0).expand() * exp(-r0/2)
  77. def Psi_nlm(n, l, m, r, phi, theta, Z=1):
  78. """
  79. Returns the Hydrogen wave function psi_{nlm}. It's the product of
  80. the radial wavefunction R_{nl} and the spherical harmonic Y_{l}^{m}.
  81. Parameters
  82. ==========
  83. n : integer
  84. Principal Quantum Number which is
  85. an integer with possible values as 1, 2, 3, 4,...
  86. l : integer
  87. ``l`` is the Angular Momentum Quantum Number with
  88. values ranging from 0 to ``n-1``.
  89. m : integer
  90. ``m`` is the Magnetic Quantum Number with values
  91. ranging from ``-l`` to ``l``.
  92. r :
  93. radial coordinate
  94. phi :
  95. azimuthal angle
  96. theta :
  97. polar angle
  98. Z :
  99. atomic number (1 for Hydrogen, 2 for Helium, ...)
  100. Everything is in Hartree atomic units.
  101. Examples
  102. ========
  103. >>> from sympy.physics.hydrogen import Psi_nlm
  104. >>> from sympy import Symbol
  105. >>> r=Symbol("r", positive=True)
  106. >>> phi=Symbol("phi", real=True)
  107. >>> theta=Symbol("theta", real=True)
  108. >>> Z=Symbol("Z", positive=True, integer=True, nonzero=True)
  109. >>> Psi_nlm(1,0,0,r,phi,theta,Z)
  110. Z**(3/2)*exp(-Z*r)/sqrt(pi)
  111. >>> Psi_nlm(2,1,1,r,phi,theta,Z)
  112. -Z**(5/2)*r*exp(I*phi)*exp(-Z*r/2)*sin(theta)/(8*sqrt(pi))
  113. Integrating the absolute square of a hydrogen wavefunction psi_{nlm}
  114. over the whole space leads 1.
  115. The normalization of the hydrogen wavefunctions Psi_nlm is:
  116. >>> from sympy import integrate, conjugate, pi, oo, sin
  117. >>> wf=Psi_nlm(2,1,1,r,phi,theta,Z)
  118. >>> abs_sqrd=wf*conjugate(wf)
  119. >>> jacobi=r**2*sin(theta)
  120. >>> integrate(abs_sqrd*jacobi, (r,0,oo), (phi,0,2*pi), (theta,0,pi))
  121. 1
  122. """
  123. # sympify arguments
  124. n, l, m, r, phi, theta, Z = map(S, [n, l, m, r, phi, theta, Z])
  125. # check if values for n,l,m make physically sense
  126. if n.is_integer and n < 1:
  127. raise ValueError("'n' must be positive integer")
  128. if l.is_integer and not (n > l):
  129. raise ValueError("'n' must be greater than 'l'")
  130. if m.is_integer and not (abs(m) <= l):
  131. raise ValueError("|'m'| must be less or equal 'l'")
  132. # return the hydrogen wave function
  133. return R_nl(n, l, r, Z)*Ynm(l, m, theta, phi).expand(func=True)
  134. def E_nl(n, Z=1):
  135. """
  136. Returns the energy of the state (n, l) in Hartree atomic units.
  137. The energy doesn't depend on "l".
  138. Parameters
  139. ==========
  140. n : integer
  141. Principal Quantum Number which is
  142. an integer with possible values as 1, 2, 3, 4,...
  143. Z :
  144. Atomic number (1 for Hydrogen, 2 for Helium, ...)
  145. Examples
  146. ========
  147. >>> from sympy.physics.hydrogen import E_nl
  148. >>> from sympy.abc import n, Z
  149. >>> E_nl(n, Z)
  150. -Z**2/(2*n**2)
  151. >>> E_nl(1)
  152. -1/2
  153. >>> E_nl(2)
  154. -1/8
  155. >>> E_nl(3)
  156. -1/18
  157. >>> E_nl(3, 47)
  158. -2209/18
  159. """
  160. n, Z = S(n), S(Z)
  161. if n.is_integer and (n < 1):
  162. raise ValueError("'n' must be positive integer")
  163. return -Z**2/(2*n**2)
  164. def E_nl_dirac(n, l, spin_up=True, Z=1, c=Float("137.035999037")):
  165. """
  166. Returns the relativistic energy of the state (n, l, spin) in Hartree atomic
  167. units.
  168. The energy is calculated from the Dirac equation. The rest mass energy is
  169. *not* included.
  170. Parameters
  171. ==========
  172. n : integer
  173. Principal Quantum Number which is
  174. an integer with possible values as 1, 2, 3, 4,...
  175. l : integer
  176. ``l`` is the Angular Momentum Quantum Number with
  177. values ranging from 0 to ``n-1``.
  178. spin_up :
  179. True if the electron spin is up (default), otherwise down
  180. Z :
  181. Atomic number (1 for Hydrogen, 2 for Helium, ...)
  182. c :
  183. Speed of light in atomic units. Default value is 137.035999037,
  184. taken from http://arxiv.org/abs/1012.3627
  185. Examples
  186. ========
  187. >>> from sympy.physics.hydrogen import E_nl_dirac
  188. >>> E_nl_dirac(1, 0)
  189. -0.500006656595360
  190. >>> E_nl_dirac(2, 0)
  191. -0.125002080189006
  192. >>> E_nl_dirac(2, 1)
  193. -0.125000416028342
  194. >>> E_nl_dirac(2, 1, False)
  195. -0.125002080189006
  196. >>> E_nl_dirac(3, 0)
  197. -0.0555562951740285
  198. >>> E_nl_dirac(3, 1)
  199. -0.0555558020932949
  200. >>> E_nl_dirac(3, 1, False)
  201. -0.0555562951740285
  202. >>> E_nl_dirac(3, 2)
  203. -0.0555556377366884
  204. >>> E_nl_dirac(3, 2, False)
  205. -0.0555558020932949
  206. """
  207. n, l, Z, c = map(S, [n, l, Z, c])
  208. if not (l >= 0):
  209. raise ValueError("'l' must be positive or zero")
  210. if not (n > l):
  211. raise ValueError("'n' must be greater than 'l'")
  212. if (l == 0 and spin_up is False):
  213. raise ValueError("Spin must be up for l==0.")
  214. # skappa is sign*kappa, where sign contains the correct sign
  215. if spin_up:
  216. skappa = -l - 1
  217. else:
  218. skappa = -l
  219. beta = sqrt(skappa**2 - Z**2/c**2)
  220. return c**2/sqrt(1 + Z**2/(n + skappa + beta)**2/c**2) - c**2