test_hydrogen.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. from sympy.core.numbers import (I, Rational, oo, pi)
  2. from sympy.core.singleton import S
  3. from sympy.core.symbol import symbols
  4. from sympy.functions.elementary.exponential import exp
  5. from sympy.functions.elementary.miscellaneous import sqrt
  6. from sympy.functions.elementary.trigonometric import (cos, sin)
  7. from sympy.integrals.integrals import integrate
  8. from sympy.simplify.simplify import simplify
  9. from sympy.physics.hydrogen import R_nl, E_nl, E_nl_dirac, Psi_nlm
  10. from sympy.testing.pytest import raises
  11. n, r, Z = symbols('n r Z')
  12. def feq(a, b, max_relative_error=1e-12, max_absolute_error=1e-12):
  13. a = float(a)
  14. b = float(b)
  15. # if the numbers are close enough (absolutely), then they are equal
  16. if abs(a - b) < max_absolute_error:
  17. return True
  18. # if not, they can still be equal if their relative error is small
  19. if abs(b) > abs(a):
  20. relative_error = abs((a - b)/b)
  21. else:
  22. relative_error = abs((a - b)/a)
  23. return relative_error <= max_relative_error
  24. def test_wavefunction():
  25. a = 1/Z
  26. R = {
  27. (1, 0): 2*sqrt(1/a**3) * exp(-r/a),
  28. (2, 0): sqrt(1/(2*a**3)) * exp(-r/(2*a)) * (1 - r/(2*a)),
  29. (2, 1): S.Half * sqrt(1/(6*a**3)) * exp(-r/(2*a)) * r/a,
  30. (3, 0): Rational(2, 3) * sqrt(1/(3*a**3)) * exp(-r/(3*a)) *
  31. (1 - 2*r/(3*a) + Rational(2, 27) * (r/a)**2),
  32. (3, 1): Rational(4, 27) * sqrt(2/(3*a**3)) * exp(-r/(3*a)) *
  33. (1 - r/(6*a)) * r/a,
  34. (3, 2): Rational(2, 81) * sqrt(2/(15*a**3)) * exp(-r/(3*a)) * (r/a)**2,
  35. (4, 0): Rational(1, 4) * sqrt(1/a**3) * exp(-r/(4*a)) *
  36. (1 - 3*r/(4*a) + Rational(1, 8) * (r/a)**2 - Rational(1, 192) * (r/a)**3),
  37. (4, 1): Rational(1, 16) * sqrt(5/(3*a**3)) * exp(-r/(4*a)) *
  38. (1 - r/(4*a) + Rational(1, 80) * (r/a)**2) * (r/a),
  39. (4, 2): Rational(1, 64) * sqrt(1/(5*a**3)) * exp(-r/(4*a)) *
  40. (1 - r/(12*a)) * (r/a)**2,
  41. (4, 3): Rational(1, 768) * sqrt(1/(35*a**3)) * exp(-r/(4*a)) * (r/a)**3,
  42. }
  43. for n, l in R:
  44. assert simplify(R_nl(n, l, r, Z) - R[(n, l)]) == 0
  45. def test_norm():
  46. # Maximum "n" which is tested:
  47. n_max = 2 # it works, but is slow, for n_max > 2
  48. for n in range(n_max + 1):
  49. for l in range(n):
  50. assert integrate(R_nl(n, l, r)**2 * r**2, (r, 0, oo)) == 1
  51. def test_psi_nlm():
  52. r=S('r')
  53. phi=S('phi')
  54. theta=S('theta')
  55. assert (Psi_nlm(1, 0, 0, r, phi, theta) == exp(-r) / sqrt(pi))
  56. assert (Psi_nlm(2, 1, -1, r, phi, theta)) == S.Half * exp(-r / (2)) * r \
  57. * (sin(theta) * exp(-I * phi) / (4 * sqrt(pi)))
  58. assert (Psi_nlm(3, 2, 1, r, phi, theta, 2) == -sqrt(2) * sin(theta) \
  59. * exp(I * phi) * cos(theta) / (4 * sqrt(pi)) * S(2) / 81 \
  60. * sqrt(2 * 2 ** 3) * exp(-2 * r / (3)) * (r * 2) ** 2)
  61. def test_hydrogen_energies():
  62. assert E_nl(n, Z) == -Z**2/(2*n**2)
  63. assert E_nl(n) == -1/(2*n**2)
  64. assert E_nl(1, 47) == -S(47)**2/(2*1**2)
  65. assert E_nl(2, 47) == -S(47)**2/(2*2**2)
  66. assert E_nl(1) == -S.One/(2*1**2)
  67. assert E_nl(2) == -S.One/(2*2**2)
  68. assert E_nl(3) == -S.One/(2*3**2)
  69. assert E_nl(4) == -S.One/(2*4**2)
  70. assert E_nl(100) == -S.One/(2*100**2)
  71. raises(ValueError, lambda: E_nl(0))
  72. def test_hydrogen_energies_relat():
  73. # First test exact formulas for small "c" so that we get nice expressions:
  74. assert E_nl_dirac(2, 0, Z=1, c=1) == 1/sqrt(2) - 1
  75. assert simplify(E_nl_dirac(2, 0, Z=1, c=2) - ( (8*sqrt(3) + 16)
  76. / sqrt(16*sqrt(3) + 32) - 4)) == 0
  77. assert simplify(E_nl_dirac(2, 0, Z=1, c=3) - ( (54*sqrt(2) + 81)
  78. / sqrt(108*sqrt(2) + 162) - 9)) == 0
  79. # Now test for almost the correct speed of light, without floating point
  80. # numbers:
  81. assert simplify(E_nl_dirac(2, 0, Z=1, c=137) - ( (352275361 + 10285412 *
  82. sqrt(1173)) / sqrt(704550722 + 20570824 * sqrt(1173)) - 18769)) == 0
  83. assert simplify(E_nl_dirac(2, 0, Z=82, c=137) - ( (352275361 + 2571353 *
  84. sqrt(12045)) / sqrt(704550722 + 5142706*sqrt(12045)) - 18769)) == 0
  85. # Test using exact speed of light, and compare against the nonrelativistic
  86. # energies:
  87. for n in range(1, 5):
  88. for l in range(n):
  89. assert feq(E_nl_dirac(n, l), E_nl(n), 1e-5, 1e-5)
  90. if l > 0:
  91. assert feq(E_nl_dirac(n, l, False), E_nl(n), 1e-5, 1e-5)
  92. Z = 2
  93. for n in range(1, 5):
  94. for l in range(n):
  95. assert feq(E_nl_dirac(n, l, Z=Z), E_nl(n, Z), 1e-4, 1e-4)
  96. if l > 0:
  97. assert feq(E_nl_dirac(n, l, False, Z), E_nl(n, Z), 1e-4, 1e-4)
  98. Z = 3
  99. for n in range(1, 5):
  100. for l in range(n):
  101. assert feq(E_nl_dirac(n, l, Z=Z), E_nl(n, Z), 1e-3, 1e-3)
  102. if l > 0:
  103. assert feq(E_nl_dirac(n, l, False, Z), E_nl(n, Z), 1e-3, 1e-3)
  104. # Test the exceptions:
  105. raises(ValueError, lambda: E_nl_dirac(0, 0))
  106. raises(ValueError, lambda: E_nl_dirac(1, -1))
  107. raises(ValueError, lambda: E_nl_dirac(1, 0, False))