Advertisement
Guest User

janaf.py - code to calculate janaf thermodynamics, broken

a guest
Dec 31st, 2015
325
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.23 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. import sys, scipy, os, re, math, random
  4. from scipy.optimize import minimize
  5.  
  6. if len(sys.argv) != 5:
  7. print "Usage: janaf.py <file> <minimum_temp> <common_temp> <maximum_temp>"
  8. sys.exit(1)
  9.  
  10. R = 8.314459848 # J/K/mol
  11.  
  12. low = float(sys.argv[2])
  13. common = float(sys.argv[3])
  14. high = float(sys.argv[4])
  15.  
  16. def read(category):
  17. lines = open(sys.argv[1]).readlines()
  18. state = "Searching"
  19. data = []
  20. data2 = []
  21. index = 0
  22. name = "UNKNOWN"
  23. for line in lines:
  24. if state == "Searching":
  25. if re.match('^\s*"name":\s*"%s",\s*\n$' % category, line):
  26. state = "values"
  27. else:
  28. match = re.match('^\s*"chemicalFormula":\s*"(.*)",\s*\n$', line)
  29. if match:
  30. name = match.group(1)
  31. elif state == "values":
  32. if re.match('^\s*"name":\s*"Temperature",\s*\n$', line):
  33. state = "temperatures"
  34. else:
  35. match = re.match('^\s*"value":\s*"(-?\d*\.?\d+)"\n$', line)
  36. if match:
  37. data.append(float(match.group(1)))
  38. elif state == "temperatures":
  39. if re.match('^\s*"name":\s*".*",\s*\n$', line):
  40. break
  41. else:
  42. match = re.match('^\s*"value":\s*"(-?\d*\.?\d+)"\n$', line)
  43. if match:
  44. data2.append( (float(match.group(1)), data[index]) )
  45. index += 1
  46. else:
  47. print "Unknown state!"
  48. sys.exit(1)
  49. return data2, name
  50.  
  51. tmp = read("Specific heat capacity")
  52. specific_heat = tmp[0]
  53. name = tmp[1]
  54. enthalpy = read("Relative standard enthalpy")[0]
  55. entropy = read("Standard entropy")[0]
  56.  
  57. elements = {
  58. "Al" : 26.98153851111,
  59. "O" : 15.9994049,
  60. "H" : 1.00794,
  61. }
  62. molweight = 0.0;
  63. matches = re.findall('(Al|O|H)(\d*)', name)
  64. for match in matches:
  65. count = 1
  66. if match[1] != "":
  67. count = float(match[1])
  68. molweight += elements[match[0]] * count
  69.  
  70. low_point = len(specific_heat)
  71. for i in range(len(specific_heat)):
  72. if specific_heat[i][0] >= low - 0.000001:
  73. low_point = i
  74. low_value = specific_heat[i][1]
  75. break
  76.  
  77. common_point = len(specific_heat)
  78. for i in range(len(specific_heat)):
  79. if specific_heat[i][0] >= common - 0.000001:
  80. common_point = i
  81. common_value = specific_heat[i][1]
  82. break
  83.  
  84. high_point = len(specific_heat)
  85. for i in range(len(specific_heat)):
  86. if specific_heat[i][0] >= high - 0.000001:
  87. high_point = i
  88. high_value = specific_heat[i][1]
  89. break
  90.  
  91. dataset_low = specific_heat[low_point:common_point] + ([specific_heat[common_point]] * 9)
  92. dataset_high = ([specific_heat[common_point]] * 10) + specific_heat[common_point:high_point]
  93.  
  94. entropy_low = len(entropy)
  95. entropy_common = len(entropy)
  96. entropy_high = len(entropy)
  97. for i in range(len(specific_heat)):
  98. if entropy_low == len(entropy):
  99. if entropy[i][0] >= low - 0.000001:
  100. entropy_low = entropy[i][1]
  101. elif entropy_common == len(entropy):
  102. if entropy[i][0] >= common - 0.000001:
  103. entropy_common = entropy[i][1]
  104. else:
  105. if entropy[i][0] >= high - 0.000001:
  106. entropy_high = entropy[i][1]
  107. break
  108.  
  109. enthalpy_low = len(enthalpy)
  110. enthalpy_common = len(enthalpy)
  111. enthalpy_high = len(enthalpy)
  112. for i in range(len(specific_heat)):
  113. if enthalpy_low == len(enthalpy):
  114. if enthalpy[i][0] >= low - 0.000001:
  115. enthalpy_low = enthalpy[i][1]
  116. elif enthalpy_common == len(enthalpy):
  117. if enthalpy[i][0] >= common - 0.000001:
  118. enthalpy_common = enthalpy[i][1]
  119. else:
  120. if enthalpy[i][0] >= high - 0.000001:
  121. enthalpy_high = enthalpy[i][1]
  122. break
  123.  
  124. def evaluate(a, dataset, verbose = False):
  125. total_error = 0.0
  126. for i in dataset:
  127. T = i[0]
  128. x = R * ((((a[4]*T + a[3])*T + a[2])*T + a[1])*T + a[0])
  129. if x < 0:
  130. return 999999999999999.9
  131. error = math.pow(math.fabs(x - i[1]), 2)
  132. total_error += error
  133. if verbose:
  134. print " %f: %6f/%6f (%f)" % (T, x, i[1], math.fabs(x - i[1]))
  135. return total_error
  136.  
  137. def optimize(dataset):
  138. params = [1e1, 8e-3, 6e-6, 4e-9, 2e-12]
  139. best = evaluate(params, dataset)
  140. i = 0
  141. while i < 60 * math.sqrt(best):
  142. # print "Cycle %d" % i
  143. trial = list(params)
  144. while True:
  145. if random.random() < math.pow(1.0 / (len(trial) + 1), 0.4):
  146. break
  147. choice = random.randrange(len(trial))
  148. trial[choice] += trial[choice] * math.pow(random.random()/(random.random() + 0.0000001), 0.3) - trial[choice] * math.pow(random.random()/(random.random() + 0.0000001), 0.3)
  149. trial[choice] *= math.pow(random.random()/(random.random() + 0.2), 0.3)
  150. res = minimize(evaluate, list(trial), method='Nelder-Mead', args=(dataset,), options={"maxiter": 1000})
  151. val = evaluate(res.x, dataset)
  152. # print "%f, %f" % (val, best)
  153. if val < best:
  154. best = val
  155. params = list(res.x)
  156. # print "", params
  157. i += 1
  158. return best, params
  159.  
  160. low_results = optimize(dataset_low)
  161. high_results = optimize(dataset_high)
  162.  
  163. sys.stderr.write("Errors: low=%f, high=%f\n" % (low_results[0], high_results[0]))
  164.  
  165. #H2
  166. #high_results = (0, [2.99142, 0.000700064, -5.63383e-08, -9.23158e-12, 1.58275e-15])
  167. #low_results = (0, [3.29812, 0.000824944, -8.14302e-07, -9.47543e-11, 4.13487e-13])
  168. #print "Should be: -835.034 -1.35511 / -1012.52 -3.29409"
  169.  
  170. #HCl
  171. #high_results = (0, [2.75534, 0.00147358, -4.97125e-07, 8.10866e-11, -5.07206e-15]);
  172. #low_results = (0, [3.33853, 0.00126821, -3.66692e-06, 4.70399e-09, -1.83601e-12]);
  173. #print "Should be: -11918.1 6.51512 / -12131.5 3.19355"
  174.  
  175. #SiC
  176. #high_results = (0, [5.02427, -0.000492089, 3.10931e-07, -6.90134e-11, 5.21573e-15]);
  177. #low_results = (0, [2.42781, 0.00955193, -2.79663e-06, -1.36001e-08, 9.19632e-12]);
  178. #print "Should be: 85310.3 -2.4788 / 85465.1 9.17925"
  179.  
  180. low_enthalpy = None
  181. for entry in enthalpy:
  182. if entry[0] >= common - 0.000001:
  183. if entry[0] <= common + 0.000001:
  184. low_enthalpy = entry[1]
  185. break
  186. else:
  187. print "ERROR - enthalpy-low not found: %f, %f" % (common, entry[0])
  188. sys.exit(1)
  189.  
  190. high_enthalpy = None
  191. for entry in enthalpy:
  192. if entry[0] >= high - 0.000001:
  193. if entry[0] <= high + 0.000001:
  194. high_enthalpy = entry[1]
  195. break
  196. else:
  197. print "ERROR - enthalpy-high not found: %f, %f" % (high, entry[0])
  198. sys.exit(1)
  199.  
  200. low_enthalpy *= 1000 # kJ -> J
  201. high_enthalpy *= 1000 #
  202.  
  203. T = common
  204. a = low_results[1]
  205. calculated_low_enthalpy = R * ((((a[4]*T/5 + a[3]/4)*T + a[2]/3)*T + a[1]/2)*T + a[0])*T
  206. T = high
  207. a = high_results[1]
  208. calculated_high_enthalpy = R * ((((a[4]*T/5 + a[3]/4)*T + a[2]/3)*T + a[1]/2)*T + a[0])*T
  209.  
  210. #print calculated_high_enthalpy, high_enthalpy, (calculated_high_enthalpy - high_enthalpy)
  211.  
  212. low_enthalpy_offset = (low_enthalpy - calculated_low_enthalpy) / R
  213. high_enthalpy_offset = (high_enthalpy - calculated_high_enthalpy) / R
  214.  
  215. low_entropy_val = None
  216. for entry in entropy:
  217. if entry[0] >= low - 0.000001:
  218. if entry[0] <= low + 0.000001:
  219. low_entropy_val = entry[1]
  220. break
  221. else:
  222. print "ERROR - entropy-low not found: %f, %f" % (low, entry[0])
  223. sys.exit(1)
  224.  
  225. common_entropy_val = None
  226. for entry in entropy:
  227. if entry[0] >= common - 0.000001:
  228. if entry[0] <= common + 0.000001:
  229. common_entropy_val = entry[1]
  230. break
  231. else:
  232. print "ERROR - entropy-high not found: %f, %f" % (common, entry[0])
  233. sys.exit(1)
  234.  
  235. high_entropy_val = None
  236. for entry in entropy:
  237. if entry[0] >= high - 0.000001:
  238. if entry[0] <= high + 0.000001:
  239. high_entropy_val = entry[1]
  240. break
  241. else:
  242. print "ERROR - entropy-high not found: %f, %f" % (high, entry[0])
  243. sys.exit(1)
  244.  
  245. T1 = common
  246. T2 = low
  247. a = low_results[1]
  248. calculated_low_entropy = R*(a[4]*(math.pow(T1, 4) - math.pow(T2, 4))/4 + a[3] * (math.pow(T1, 3) - math.pow(T2, 3))/3 + a[2] * (math.pow(T1, 2) - math.pow(T2, 2))/2 + a[1] * (T1 - T2)+a[0] * math.log(T1 / T2))
  249. T1 = high
  250. T2 = common
  251. a = high_results[1]
  252. calculated_high_entropy = R*(a[4]*(math.pow(T1, 4) - math.pow(T2, 4))/4 + a[3] * (math.pow(T1, 3) - math.pow(T2, 3))/3 + a[2] * (math.pow(T1, 2) - math.pow(T2, 2))/2 + a[1] * (T1 - T2)+a[0] * math.log(T1 / T2))
  253.  
  254. low_entropy = common_entropy_val - low_entropy_val
  255. high_entropy = high_entropy_val - common_entropy_val
  256.  
  257. #print calculated_high_entropy, high_entropy, (calculated_high_entropy - high_entropy)
  258.  
  259. low_entropy_offset = (low_entropy - calculated_low_entropy) / R / -(1.0/common - 1.0/low)
  260. high_entropy_offset = (high_entropy - calculated_high_entropy) / R / -(1.0/high - 1.0/common)
  261.  
  262. print "%s" % name
  263. print "{"
  264. print " specie"
  265. print " {"
  266. print " nMoles 1;"
  267. print " molWeight %s;" % molweight
  268. print " }"
  269. print " thermodynamics"
  270. print " {"
  271. print " Tlow %f;" % low
  272. print " Thigh %f;" % high
  273. print " Tcommon %f;" % common
  274. print " highCpCoeffs ( %g %g %g %g %g %g %g );" % (high_results[1][0], high_results[1][1], high_results[1][2], high_results[1][3], high_results[1][4], high_enthalpy_offset, high_entropy_offset)
  275. print " lowCpCoeffs ( %g %g %g %g %g %g %g );" % (low_results[1][0], low_results[1][1], low_results[1][2], low_results[1][3], low_results[1][4], low_enthalpy_offset, low_entropy_offset)
  276. print " }"
  277. print " transport"
  278. print " {"
  279. print " As 1.67212e-06;"
  280. print " Ts 170.672;"
  281. print " }"
  282. print "}"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement