PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/rmgpy/statmech/conformerTest.py

https://github.com/jwallen/RMG-Py
Python | 281 lines | 166 code | 25 blank | 90 comment | 10 complexity | c9e0d2886baefa3f69ede3c36529d79c MD5 | raw file
  1. #!/usr/bin/env python
  2. # encoding: utf-8
  3. ################################################################################
  4. #
  5. # RMG - Reaction Mechanism Generator
  6. #
  7. # Copyright (c) 2002-2009 Prof. William H. Green (whgreen@mit.edu) and the
  8. # RMG Team (rmg_dev@mit.edu)
  9. #
  10. # Permission is hereby granted, free of charge, to any person obtaining a
  11. # copy of this software and associated documentation files (the "Software"),
  12. # to deal in the Software without restriction, including without limitation
  13. # the rights to use, copy, modify, merge, publish, distribute, sublicense,
  14. # and/or sell copies of the Software, and to permit persons to whom the
  15. # Software is furnished to do so, subject to the following conditions:
  16. #
  17. # The above copyright notice and this permission notice shall be included in
  18. # all copies or substantial portions of the Software.
  19. #
  20. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  21. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  23. # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  24. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  25. # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  26. # DEALINGS IN THE SOFTWARE.
  27. #
  28. ################################################################################
  29. """
  30. This script contains unit tests of the :mod:`rmgpy.statmech.conformer` module.
  31. """
  32. import unittest
  33. import math
  34. import numpy
  35. import scipy.interpolate
  36. from rmgpy.statmech import Conformer, IdealGasTranslation, NonlinearRotor, HarmonicOscillator, \
  37. LinearRotor, HinderedRotor
  38. import rmgpy.constants as constants
  39. ################################################################################
  40. class TestConformer(unittest.TestCase):
  41. """
  42. Contains unit tests of the :class:`Conformer` class.
  43. """
  44. def setUp(self):
  45. """
  46. A function run before each unit test in this class.
  47. """
  48. self.ethylene = Conformer(
  49. E0 = (0.0,"kJ/mol"),
  50. modes = [
  51. IdealGasTranslation(mass=(28.03,"amu")),
  52. NonlinearRotor(inertia=([3.41526,16.6498,20.065],"amu*angstrom^2"), symmetry=4),
  53. HarmonicOscillator(frequencies=([828.397,970.652,977.223,1052.93,1233.55,1367.56,1465.09,1672.25,3098.46,3111.7,3165.79,3193.54],"cm^-1")),
  54. ],
  55. spinMultiplicity = 1,
  56. opticalIsomers = 1,
  57. )
  58. self.oxygen = Conformer(
  59. E0 = (0.0,"kJ/mol"),
  60. modes = [
  61. IdealGasTranslation(mass=(31.99,"amu")),
  62. LinearRotor(inertia=(11.6056,"amu*angstrom^2"), symmetry=2),
  63. HarmonicOscillator(frequencies=([1621.54],"cm^-1")),
  64. ],
  65. spinMultiplicity = 3,
  66. opticalIsomers = 1,
  67. )
  68. # The following data is for ethane at the CBS-QB3 level
  69. self.coordinates = numpy.array([
  70. [ 0.0000, 0.0000, 0.0000],
  71. [ -0.0000, -0.0000, 1.0936],
  72. [ 1.0430, -0.0000, -0.3288],
  73. [ -0.4484, 0.9417, -0.3288],
  74. [ -0.7609, -1.2051, -0.5580],
  75. [ -0.7609, -1.2051, -1.6516],
  76. [ -0.3125, -2.1468, -0.2292],
  77. [ -1.8039, -1.2051, -0.2293],
  78. ])
  79. self.number = numpy.array([6, 1, 1, 1, 6, 1, 1, 1])
  80. self.mass = numpy.array([12, 1.007825, 1.007825, 1.007825, 12, 1.007825, 1.007825, 1.007825])
  81. self.E0 = -93.5097
  82. self.conformer = Conformer(
  83. E0 = (self.E0,"kJ/mol"),
  84. modes = [
  85. IdealGasTranslation(mass=(30.0469,"amu")),
  86. NonlinearRotor(inertia=([6.27071,25.3832,25.3833],"amu*angstrom^2"), symmetry=6),
  87. HarmonicOscillator(frequencies=([818.917,819.479,987.099,1206.76,1207.05,1396,1411.35,1489.73,1489.95,1492.49,1492.66,2995.36,2996.06,3040.77,3041,3065.86,3066.02],"cm^-1")),
  88. HinderedRotor(inertia=(1.56768,"amu*angstrom^2"), symmetry=3, barrier=(2.69401,"kcal/mol"), quantum=False, semiclassical=False),
  89. ],
  90. spinMultiplicity = 1,
  91. opticalIsomers = 1,
  92. coordinates = (self.coordinates,"angstrom"),
  93. number = self.number,
  94. mass = (self.mass,"amu"),
  95. )
  96. def test_getPartitionFunction_ethylene(self):
  97. """
  98. Test the StatMech.getPartitionFunction() method for ethylene.
  99. """
  100. Tlist = numpy.array([300,500,1000,1500,2000])
  101. Qexplist = numpy.array([4.05311e+09, 4.19728e+10, 2.82309e+12, 7.51135e+13, 1.16538e+15])
  102. for T, Qexp in zip(Tlist, Qexplist):
  103. Qact = self.ethylene.getPartitionFunction(T)
  104. self.assertAlmostEqual(Qexp, Qact, delta=1e-4*Qexp)
  105. def test_getHeatCapacity_ethylene(self):
  106. """
  107. Test the StatMech.getHeatCapacity() method for ethylene.
  108. """
  109. Tlist = numpy.array([300,500,1000,1500,2000])
  110. Cvexplist = numpy.array([5.11186, 7.40447, 11.1659, 13.1221, 14.1617]) * constants.R
  111. for T, Cvexp in zip(Tlist, Cvexplist):
  112. Cvact = self.ethylene.getHeatCapacity(T)
  113. self.assertAlmostEqual(Cvexp, Cvact, 3)
  114. def test_getEnthalpy_ethylene(self):
  115. """
  116. Test the StatMech.getEnthalpy() method for ethylene.
  117. """
  118. Tlist = numpy.array([300,500,1000,1500,2000])
  119. Hexplist = numpy.array([4.23129, 5.04826, 7.27337, 8.93167, 10.1223]) * constants.R * Tlist
  120. for T, Hexp in zip(Tlist, Hexplist):
  121. Hact = self.ethylene.getEnthalpy(T)
  122. self.assertAlmostEqual(Hexp, Hact, delta=1e-4*Hexp)
  123. def test_getEntropy_ethylene(self):
  124. """
  125. Test the StatMech.getEntropy() method for ethylene.
  126. """
  127. Tlist = numpy.array([300,500,1000,1500,2000])
  128. Sexplist = numpy.array([26.3540, 29.5085, 35.9422, 40.8817, 44.8142]) * constants.R
  129. for T, Sexp in zip(Tlist, Sexplist):
  130. Sact = self.ethylene.getEntropy(T)
  131. self.assertAlmostEqual(Sexp, Sact, 3)
  132. def test_getSumOfStates_ethylene(self):
  133. """
  134. Test the StatMech.getSumOfStates() method for ethylene.
  135. """
  136. Elist = numpy.arange(0, 5000*11.96, 2*11.96)
  137. sumStates = self.ethylene.getSumOfStates(Elist)
  138. densStates = self.ethylene.getDensityOfStates(Elist)
  139. for n in range(10, len(Elist)):
  140. self.assertTrue(0.8 < numpy.sum(densStates[0:n+1]) / sumStates[n] < 1.25, '{0} != {1}'.format(numpy.sum(densStates[0:n+1]), sumStates[n]))
  141. def test_getDensityOfStates_ethylene(self):
  142. """
  143. Test the StatMech.getDensityOfStates() method for ethylene.
  144. """
  145. Elist = numpy.arange(0, 5000*11.96, 2*11.96)
  146. densStates = self.ethylene.getDensityOfStates(Elist)
  147. T = 100
  148. Qact = numpy.sum(densStates * numpy.exp(-Elist / constants.R / T))
  149. Qexp = self.ethylene.getPartitionFunction(T)
  150. self.assertAlmostEqual(Qexp, Qact, delta=1e-1*Qexp)
  151. def test_getPartitionFunction_oxygen(self):
  152. """
  153. Test the StatMech.getPartitionFunction() method for oxygen.
  154. """
  155. Tlist = numpy.array([300,500,1000,1500,2000])
  156. Qexplist = numpy.array([1.55584e+09, 9.38339e+09, 1.16459e+11, 5.51016e+11, 1.72794e+12])
  157. for T, Qexp in zip(Tlist, Qexplist):
  158. Qact = self.oxygen.getPartitionFunction(T)
  159. self.assertAlmostEqual(Qexp, Qact, delta=1e-4*Qexp)
  160. def test_getHeatCapacity_oxygen(self):
  161. """
  162. Test the StatMech.getHeatCapacity() method for oxygen.
  163. """
  164. Tlist = numpy.array([300,500,1000,1500,2000])
  165. Cvexplist = numpy.array([3.52538, 3.70877, 4.14751, 4.32063, 4.39392]) * constants.R
  166. for T, Cvexp in zip(Tlist, Cvexplist):
  167. Cvact = self.oxygen.getHeatCapacity(T)
  168. self.assertAlmostEqual(Cvexp, Cvact, 3)
  169. def test_getEnthalpy_oxygen(self):
  170. """
  171. Test the StatMech.getEnthalpy() method for oxygen.
  172. """
  173. Tlist = numpy.array([300,500,1000,1500,2000])
  174. Hexplist = numpy.array([3.50326, 3.54432, 3.75062, 3.91623, 4.02765]) * constants.R * Tlist
  175. for T, Hexp in zip(Tlist, Hexplist):
  176. Hact = self.oxygen.getEnthalpy(T)
  177. self.assertAlmostEqual(Hexp, Hact, delta=1e-4*Hexp)
  178. def test_getEntropy_oxygen(self):
  179. """
  180. Test the StatMech.getEntropy() method for oxygen.
  181. """
  182. Tlist = numpy.array([300,500,1000,1500,2000])
  183. Sexplist = numpy.array([24.6685, 26.5065, 29.2314, 30.9513, 32.2056]) * constants.R
  184. for T, Sexp in zip(Tlist, Sexplist):
  185. Sact = self.oxygen.getEntropy(T)
  186. self.assertAlmostEqual(Sexp, Sact, 3)
  187. def test_getSumOfStates_oxygen(self):
  188. """
  189. Test the StatMech.getSumOfStates() method for oxygen.
  190. """
  191. Elist = numpy.arange(0, 5000*11.96, 2*11.96)
  192. sumStates = self.oxygen.getSumOfStates(Elist)
  193. densStates = self.oxygen.getDensityOfStates(Elist)
  194. for n in range(10, len(Elist)):
  195. self.assertTrue(0.8 < numpy.sum(densStates[0:n+1]) / sumStates[n] < 1.25, '{0} != {1}'.format(numpy.sum(densStates[0:n+1]), sumStates[n]))
  196. def test_getDensityOfStates_oxygen(self):
  197. """
  198. Test the StatMech.getDensityOfStates() method for oxygen.
  199. """
  200. Elist = numpy.arange(0, 5000*11.96, 2*11.96)
  201. densStates = self.oxygen.getDensityOfStates(Elist)
  202. T = 100
  203. Qact = numpy.sum(densStates * numpy.exp(-Elist / constants.R / T))
  204. Qexp = self.oxygen.getPartitionFunction(T)
  205. self.assertAlmostEqual(Qexp, Qact, delta=1e-1*Qexp)
  206. def test_getTotalMass(self):
  207. """
  208. Test the Conformer.getTotalMass() method.
  209. """
  210. self.assertAlmostEqual(self.conformer.getTotalMass()*constants.Na*1000., numpy.sum(self.mass), 6)
  211. def test_getCenterOfMass(self):
  212. """
  213. Test the Conformer.getCenterOfMass() method.
  214. """
  215. cm = self.conformer.getCenterOfMass()
  216. self.assertAlmostEqual(cm[0]*1e10, -0.38045, 4)
  217. self.assertAlmostEqual(cm[1]*1e10, -0.60255, 4)
  218. self.assertAlmostEqual(cm[2]*1e10, -0.27900, 4)
  219. def test_getMomentOfInertiaTensor(self):
  220. """
  221. Test the Conformer.getMomentOfInertiaTensor() method.
  222. """
  223. I = self.conformer.getMomentOfInertiaTensor()
  224. self.assertAlmostEqual(I[0,0]*constants.Na*1e23, 20.65968, 4)
  225. self.assertAlmostEqual(I[0,1]*constants.Na*1e23, -7.48115, 4)
  226. self.assertAlmostEqual(I[0,2]*constants.Na*1e23, -3.46416, 4)
  227. self.assertAlmostEqual(I[1,0]*constants.Na*1e23, -7.48115, 4)
  228. self.assertAlmostEqual(I[1,1]*constants.Na*1e23, 13.53472, 4)
  229. self.assertAlmostEqual(I[1,2]*constants.Na*1e23, -5.48630, 4)
  230. self.assertAlmostEqual(I[2,0]*constants.Na*1e23, -3.46416, 4)
  231. self.assertAlmostEqual(I[2,1]*constants.Na*1e23, -5.48630, 4)
  232. self.assertAlmostEqual(I[2,2]*constants.Na*1e23, 22.84296, 4)
  233. def test_getPrincipalMomentsOfInertia(self):
  234. """
  235. Test the Conformer.getPrincipalMomentsOfInertia() method.
  236. """
  237. I, V = self.conformer.getPrincipalMomentsOfInertia()
  238. self.assertAlmostEqual(I[0]*constants.Na*1e23, 6.27074, 4)
  239. self.assertAlmostEqual(I[1]*constants.Na*1e23, 25.38321, 3)
  240. self.assertAlmostEqual(I[2]*constants.Na*1e23, 25.38341, 3)
  241. print V
  242. self.assertAlmostEqual(V[0,0], 0.497140, 4)
  243. self.assertAlmostEqual(V[0,1], -0.610114, 4)
  244. self.assertAlmostEqual(V[0,2], -0.616938, 4)
  245. self.assertAlmostEqual(V[1,0], 0.787360, 4)
  246. self.assertAlmostEqual(V[1,1], 0.018454, 4)
  247. self.assertAlmostEqual(V[1,2], 0.616218, 4)
  248. self.assertAlmostEqual(V[2,0], 0.364578, 4)
  249. self.assertAlmostEqual(V[2,1], 0.792099, 4)
  250. self.assertAlmostEqual(V[2,2], -0.489554, 4)
  251. def test_getInternalReducedMomentOfInertia(self):
  252. """
  253. Test the Conformer.getInternalReducedMomentOfInertia() method.
  254. """
  255. I = self.conformer.getInternalReducedMomentOfInertia(pivots=[1,5], top1=[1,2,3,4])
  256. self.assertAlmostEqual(I*constants.Na*1e23, 1.56768, 4)