TidalPy 0.7.5__cp314-cp314-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. TidalPy/Extending/__init__.py +9 -0
  2. TidalPy/Extending/burnman/__init__.py +10 -0
  3. TidalPy/Extending/burnman/build.py +196 -0
  4. TidalPy/Extending/burnman/burnman_defaultc.py +21 -0
  5. TidalPy/Extending/burnman/burnman_layer.py +408 -0
  6. TidalPy/Extending/burnman/burnman_world.py +119 -0
  7. TidalPy/Extending/burnman/conversion.py +13 -0
  8. TidalPy/Extending/burnman/defaults.py +8 -0
  9. TidalPy/Extending/burnman/material/__init__.py +0 -0
  10. TidalPy/Extending/burnman/material/custom/__init__.py +10 -0
  11. TidalPy/Extending/burnman/material/custom/constant.py +96 -0
  12. TidalPy/Extending/burnman/material/custom/ice.py +182 -0
  13. TidalPy/Extending/burnman/material/custom/pyrite.py +29 -0
  14. TidalPy/Extending/burnman/material/helper.py +115 -0
  15. TidalPy/Extending/burnman/package.py +47 -0
  16. TidalPy/Material/__init__.py +0 -0
  17. TidalPy/Material/eos/__init__.pxd +8 -0
  18. TidalPy/Material/eos/__init__.py +0 -0
  19. TidalPy/Material/eos/eos_solution.cp314-win_amd64.pyd +0 -0
  20. TidalPy/Material/eos/eos_solution.pxd +93 -0
  21. TidalPy/Material/eos/eos_solution.pyx +2 -0
  22. TidalPy/Material/eos/eos_solution_.cpp +402 -0
  23. TidalPy/Material/eos/eos_solution_.hpp +123 -0
  24. TidalPy/Material/eos/methods/__init__.pxd +1 -0
  25. TidalPy/Material/eos/methods/__init__.py +0 -0
  26. TidalPy/Material/eos/methods/interpolate.cp314-win_amd64.pyd +0 -0
  27. TidalPy/Material/eos/methods/interpolate.pxd +21 -0
  28. TidalPy/Material/eos/methods/interpolate.pyx +70 -0
  29. TidalPy/Material/eos/ode.cp314-win_amd64.pyd +0 -0
  30. TidalPy/Material/eos/ode.pxd +24 -0
  31. TidalPy/Material/eos/ode.pyx +69 -0
  32. TidalPy/Material/eos/solver.cp314-win_amd64.pyd +0 -0
  33. TidalPy/Material/eos/solver.pxd +23 -0
  34. TidalPy/Material/eos/solver.pyx +279 -0
  35. TidalPy/RadialSolver/__init__.pxd +2 -0
  36. TidalPy/RadialSolver/__init__.py +4 -0
  37. TidalPy/RadialSolver/boundaries/__init__.py +0 -0
  38. TidalPy/RadialSolver/boundaries/boundaries.cp314-win_amd64.pyd +0 -0
  39. TidalPy/RadialSolver/boundaries/boundaries.pxd +17 -0
  40. TidalPy/RadialSolver/boundaries/boundaries.pyx +186 -0
  41. TidalPy/RadialSolver/boundaries/surface_bc.cp314-win_amd64.pyd +0 -0
  42. TidalPy/RadialSolver/boundaries/surface_bc.pxd +8 -0
  43. TidalPy/RadialSolver/boundaries/surface_bc.pyx +163 -0
  44. TidalPy/RadialSolver/collapse/__init__.py +0 -0
  45. TidalPy/RadialSolver/collapse/collapse.cp314-win_amd64.pyd +0 -0
  46. TidalPy/RadialSolver/collapse/collapse.pxd +22 -0
  47. TidalPy/RadialSolver/collapse/collapse.pyx +175 -0
  48. TidalPy/RadialSolver/constants.cp314-win_amd64.pyd +0 -0
  49. TidalPy/RadialSolver/constants.pxd +3 -0
  50. TidalPy/RadialSolver/constants.pyx +7 -0
  51. TidalPy/RadialSolver/derivatives/__init__.py +0 -0
  52. TidalPy/RadialSolver/derivatives/odes.cp314-win_amd64.pyd +0 -0
  53. TidalPy/RadialSolver/derivatives/odes.pxd +71 -0
  54. TidalPy/RadialSolver/derivatives/odes.pyx +788 -0
  55. TidalPy/RadialSolver/helpers.cp314-win_amd64.pyd +0 -0
  56. TidalPy/RadialSolver/helpers.pyx +570 -0
  57. TidalPy/RadialSolver/interfaces/__init__.py +0 -0
  58. TidalPy/RadialSolver/interfaces/interfaces.cp314-win_amd64.pyd +0 -0
  59. TidalPy/RadialSolver/interfaces/interfaces.pxd +18 -0
  60. TidalPy/RadialSolver/interfaces/interfaces.pyx +316 -0
  61. TidalPy/RadialSolver/interfaces/reversed.cp314-win_amd64.pyd +0 -0
  62. TidalPy/RadialSolver/interfaces/reversed.pxd +21 -0
  63. TidalPy/RadialSolver/interfaces/reversed.pyx +197 -0
  64. TidalPy/RadialSolver/love.cp314-win_amd64.pyd +0 -0
  65. TidalPy/RadialSolver/love.pxd +6 -0
  66. TidalPy/RadialSolver/love.pyx +30 -0
  67. TidalPy/RadialSolver/love_.cpp +33 -0
  68. TidalPy/RadialSolver/love_.hpp +7 -0
  69. TidalPy/RadialSolver/matrix.cp314-win_amd64.pyd +0 -0
  70. TidalPy/RadialSolver/matrix.pxd +25 -0
  71. TidalPy/RadialSolver/matrix.pyx +522 -0
  72. TidalPy/RadialSolver/matrix_types/__init__.py +1 -0
  73. TidalPy/RadialSolver/matrix_types/solid_matrix.cp314-win_amd64.pyd +0 -0
  74. TidalPy/RadialSolver/matrix_types/solid_matrix.pxd +13 -0
  75. TidalPy/RadialSolver/matrix_types/solid_matrix.pyx +372 -0
  76. TidalPy/RadialSolver/rs_solution.cp314-win_amd64.pyd +0 -0
  77. TidalPy/RadialSolver/rs_solution.pxd +105 -0
  78. TidalPy/RadialSolver/rs_solution.pyx +597 -0
  79. TidalPy/RadialSolver/rs_solution_.cpp +193 -0
  80. TidalPy/RadialSolver/rs_solution_.hpp +78 -0
  81. TidalPy/RadialSolver/shooting.cp314-win_amd64.pyd +0 -0
  82. TidalPy/RadialSolver/shooting.pxd +42 -0
  83. TidalPy/RadialSolver/shooting.pyx +976 -0
  84. TidalPy/RadialSolver/solver.cp314-win_amd64.pyd +0 -0
  85. TidalPy/RadialSolver/solver.pxd +48 -0
  86. TidalPy/RadialSolver/solver.pyx +836 -0
  87. TidalPy/RadialSolver/starting/__init__.py +0 -0
  88. TidalPy/RadialSolver/starting/common.cp314-win_amd64.pyd +0 -0
  89. TidalPy/RadialSolver/starting/common.pxd +12 -0
  90. TidalPy/RadialSolver/starting/common.pyx +159 -0
  91. TidalPy/RadialSolver/starting/driver.cp314-win_amd64.pyd +0 -0
  92. TidalPy/RadialSolver/starting/driver.pxd +22 -0
  93. TidalPy/RadialSolver/starting/driver.pyx +229 -0
  94. TidalPy/RadialSolver/starting/kamata.cp314-win_amd64.pyd +0 -0
  95. TidalPy/RadialSolver/starting/kamata.pxd +58 -0
  96. TidalPy/RadialSolver/starting/kamata.pyx +577 -0
  97. TidalPy/RadialSolver/starting/saito.cp314-win_amd64.pyd +0 -0
  98. TidalPy/RadialSolver/starting/saito.pxd +6 -0
  99. TidalPy/RadialSolver/starting/saito.pyx +47 -0
  100. TidalPy/RadialSolver/starting/takeuchi.cp314-win_amd64.pyd +0 -0
  101. TidalPy/RadialSolver/starting/takeuchi.pxd +37 -0
  102. TidalPy/RadialSolver/starting/takeuchi.pyx +430 -0
  103. TidalPy/WorldPack/WorldPack.zip +0 -0
  104. TidalPy/__init__.py +73 -0
  105. TidalPy/cache.py +71 -0
  106. TidalPy/configurations.py +251 -0
  107. TidalPy/constants.cp314-win_amd64.pyd +0 -0
  108. TidalPy/constants.pxd +74 -0
  109. TidalPy/constants.pyx +151 -0
  110. TidalPy/cooling/__init__.py +19 -0
  111. TidalPy/cooling/cooling.py +288 -0
  112. TidalPy/cooling/cooling_models.py +185 -0
  113. TidalPy/defaultc.py +467 -0
  114. TidalPy/dynamics/__init__.py +15 -0
  115. TidalPy/dynamics/dual_dissipation.py +165 -0
  116. TidalPy/dynamics/single_dissipation.py +174 -0
  117. TidalPy/exceptions.py +230 -0
  118. TidalPy/initialize.py +105 -0
  119. TidalPy/logger.py +179 -0
  120. TidalPy/numba_scipy/__init__.py +7 -0
  121. TidalPy/numba_scipy/special/__init__.py +3 -0
  122. TidalPy/numba_scipy/special/overloads.py +25 -0
  123. TidalPy/numba_scipy/special/signatures.py +96 -0
  124. TidalPy/orbit/__init__.py +4 -0
  125. TidalPy/orbit/averaging.py +318 -0
  126. TidalPy/output.py +38 -0
  127. TidalPy/paths.py +171 -0
  128. TidalPy/radiogenics/__init__.py +11 -0
  129. TidalPy/radiogenics/radiogenic_models.py +123 -0
  130. TidalPy/radiogenics/radiogenics.py +320 -0
  131. TidalPy/rheology/__init__.py +14 -0
  132. TidalPy/rheology/base.cp314-win_amd64.pyd +0 -0
  133. TidalPy/rheology/base.pxd +33 -0
  134. TidalPy/rheology/base.pyx +138 -0
  135. TidalPy/rheology/complex_compliance/__init__.py +17 -0
  136. TidalPy/rheology/complex_compliance/complex_compliance.py +231 -0
  137. TidalPy/rheology/complex_compliance/compliance_models.py +655 -0
  138. TidalPy/rheology/models.cp314-win_amd64.pyd +0 -0
  139. TidalPy/rheology/models.pxd +36 -0
  140. TidalPy/rheology/models.pyx +282 -0
  141. TidalPy/rheology/partial_melt/__init__.py +19 -0
  142. TidalPy/rheology/partial_melt/melting_models.py +204 -0
  143. TidalPy/rheology/partial_melt/partialmelt.py +371 -0
  144. TidalPy/rheology/rheology.py +396 -0
  145. TidalPy/rheology/viscosity/__init__.py +22 -0
  146. TidalPy/rheology/viscosity/viscosity.py +169 -0
  147. TidalPy/rheology/viscosity/viscosity_models.py +162 -0
  148. TidalPy/stellar/__init__.py +15 -0
  149. TidalPy/stellar/insolation.py +170 -0
  150. TidalPy/stellar/stellar.py +53 -0
  151. TidalPy/structures/__init__.py +5 -0
  152. TidalPy/structures/helpers/__init__.py +0 -0
  153. TidalPy/structures/helpers/orbit_config.py +96 -0
  154. TidalPy/structures/layers/__init__.py +18 -0
  155. TidalPy/structures/layers/basic.py +501 -0
  156. TidalPy/structures/layers/gas.py +46 -0
  157. TidalPy/structures/layers/helper.py +106 -0
  158. TidalPy/structures/layers/physics.py +660 -0
  159. TidalPy/structures/orbit/__init__.py +5 -0
  160. TidalPy/structures/orbit/base.py +1619 -0
  161. TidalPy/structures/orbit/physics.py +586 -0
  162. TidalPy/structures/physical.py +967 -0
  163. TidalPy/structures/world_builder/__init__.py +3 -0
  164. TidalPy/structures/world_builder/config_handler.py +104 -0
  165. TidalPy/structures/world_builder/iterative_builder.py +156 -0
  166. TidalPy/structures/world_builder/world_builder.py +268 -0
  167. TidalPy/structures/world_types/__init__.py +28 -0
  168. TidalPy/structures/world_types/basic.py +928 -0
  169. TidalPy/structures/world_types/gas.py +40 -0
  170. TidalPy/structures/world_types/layered.py +517 -0
  171. TidalPy/structures/world_types/stellar.py +95 -0
  172. TidalPy/structures/world_types/tidal.py +466 -0
  173. TidalPy/tides/__init__.py +23 -0
  174. TidalPy/tides/ctl_funcs/__init__.py +11 -0
  175. TidalPy/tides/ctl_funcs/ctl_funcs.py +53 -0
  176. TidalPy/tides/dissipation.py +56 -0
  177. TidalPy/tides/eccentricity_funcs/__init__.py +177 -0
  178. TidalPy/tides/eccentricity_funcs/orderl2.py +848 -0
  179. TidalPy/tides/eccentricity_funcs/orderl3.py +879 -0
  180. TidalPy/tides/eccentricity_funcs/orderl4.py +1023 -0
  181. TidalPy/tides/eccentricity_funcs/orderl5.py +1161 -0
  182. TidalPy/tides/eccentricity_funcs/orderl6.py +1309 -0
  183. TidalPy/tides/eccentricity_funcs/orderl7.py +1451 -0
  184. TidalPy/tides/heating.py +52 -0
  185. TidalPy/tides/inclination_funcs/__init__.py +73 -0
  186. TidalPy/tides/inclination_funcs/orderl2.py +56 -0
  187. TidalPy/tides/inclination_funcs/orderl3.py +62 -0
  188. TidalPy/tides/inclination_funcs/orderl4.py +74 -0
  189. TidalPy/tides/inclination_funcs/orderl5.py +88 -0
  190. TidalPy/tides/inclination_funcs/orderl6.py +102 -0
  191. TidalPy/tides/inclination_funcs/orderl7.py +116 -0
  192. TidalPy/tides/love1d.py +159 -0
  193. TidalPy/tides/methods/__init__.py +3 -0
  194. TidalPy/tides/methods/base.py +867 -0
  195. TidalPy/tides/methods/global_approx.py +464 -0
  196. TidalPy/tides/methods/layered.py +331 -0
  197. TidalPy/tides/modes/__init__.py +2 -0
  198. TidalPy/tides/modes/collapse_modes.py +107 -0
  199. TidalPy/tides/modes/mode_calc_helper/__init__.py +110 -0
  200. TidalPy/tides/modes/mode_calc_helper/eccen_calc_orderl2.py +274 -0
  201. TidalPy/tides/modes/mode_calc_helper/eccen_calc_orderl3.py +260 -0
  202. TidalPy/tides/modes/mode_calc_helper/eccen_calc_orderl4.py +270 -0
  203. TidalPy/tides/modes/mode_calc_helper/eccen_calc_orderl5.py +280 -0
  204. TidalPy/tides/modes/mode_calc_helper/eccen_calc_orderl6.py +290 -0
  205. TidalPy/tides/modes/mode_calc_helper/eccen_calc_orderl7.py +300 -0
  206. TidalPy/tides/modes/mode_calc_helper/inclin_calc_orderl2.py +60 -0
  207. TidalPy/tides/modes/mode_calc_helper/inclin_calc_orderl3.py +62 -0
  208. TidalPy/tides/modes/mode_calc_helper/inclin_calc_orderl4.py +64 -0
  209. TidalPy/tides/modes/mode_calc_helper/inclin_calc_orderl5.py +66 -0
  210. TidalPy/tides/modes/mode_calc_helper/inclin_calc_orderl6.py +68 -0
  211. TidalPy/tides/modes/mode_calc_helper/inclin_calc_orderl7.py +70 -0
  212. TidalPy/tides/modes/mode_manipulation.py +465 -0
  213. TidalPy/tides/modes/modes.py +147 -0
  214. TidalPy/tides/modes/multilayer_modes.py +535 -0
  215. TidalPy/tides/multilayer/__init__.py +7 -0
  216. TidalPy/tides/multilayer/displacements.py +76 -0
  217. TidalPy/tides/multilayer/heating.cp314-win_amd64.pyd +0 -0
  218. TidalPy/tides/multilayer/heating.pxd +16 -0
  219. TidalPy/tides/multilayer/heating.pyx +237 -0
  220. TidalPy/tides/multilayer/sensitivity.cp314-win_amd64.pyd +0 -0
  221. TidalPy/tides/multilayer/sensitivity.pxd +21 -0
  222. TidalPy/tides/multilayer/sensitivity.pyx +335 -0
  223. TidalPy/tides/multilayer/stress_strain.py +209 -0
  224. TidalPy/tides/potential/__init__.py +18 -0
  225. TidalPy/tides/potential/nsr_med_eccen_gen_obliquity.py +476 -0
  226. TidalPy/tides/potential/nsr_med_eccen_med_obliquity.py +391 -0
  227. TidalPy/tides/potential/nsr_med_eccen_no_obliquity.py +311 -0
  228. TidalPy/tides/potential/nsr_modes_low_eccen_gen_obliquity.py +425 -0
  229. TidalPy/tides/potential/nsr_modes_med_eccen_gen_obliquity.py +507 -0
  230. TidalPy/tides/potential/nsr_modes_med_eccen_med_obliquity.py +414 -0
  231. TidalPy/tides/potential/nsr_modes_med_eccen_no_obliquity.py +324 -0
  232. TidalPy/tides/potential/synchronous_low_e.py +128 -0
  233. TidalPy/tides/universal_coeffs.py +74 -0
  234. TidalPy/toolbox/__init__.py +2 -0
  235. TidalPy/toolbox/quick_tides.py +725 -0
  236. TidalPy/utilities/__init__.py +0 -0
  237. TidalPy/utilities/arrays/__init__.py +0 -0
  238. TidalPy/utilities/arrays/interp.pxd +25 -0
  239. TidalPy/utilities/arrays/interp.pyx +2 -0
  240. TidalPy/utilities/arrays/interp_.cpp +321 -0
  241. TidalPy/utilities/arrays/interp_.hpp +30 -0
  242. TidalPy/utilities/classes/__init__.py +8 -0
  243. TidalPy/utilities/classes/base.py +14 -0
  244. TidalPy/utilities/classes/base_x.cp314-win_amd64.pyd +0 -0
  245. TidalPy/utilities/classes/base_x.pxd +5 -0
  246. TidalPy/utilities/classes/base_x.pyx +29 -0
  247. TidalPy/utilities/classes/config/__init__.py +3 -0
  248. TidalPy/utilities/classes/config/config.py +426 -0
  249. TidalPy/utilities/classes/model/__init__.py +2 -0
  250. TidalPy/utilities/classes/model/functional_utils.py +98 -0
  251. TidalPy/utilities/classes/model/model.py +450 -0
  252. TidalPy/utilities/classes/model/model_utils.py +119 -0
  253. TidalPy/utilities/conversions/__init__.py +10 -0
  254. TidalPy/utilities/conversions/conversions.py +182 -0
  255. TidalPy/utilities/conversions/conversions_x.cp314-win_amd64.pyd +0 -0
  256. TidalPy/utilities/conversions/conversions_x.pxd +37 -0
  257. TidalPy/utilities/conversions/conversions_x.pyx +214 -0
  258. TidalPy/utilities/conversions/timing.py +34 -0
  259. TidalPy/utilities/dictionary_utils.py +191 -0
  260. TidalPy/utilities/dimensions/__init__.py +0 -0
  261. TidalPy/utilities/dimensions/nondimensional.cp314-win_amd64.pyd +0 -0
  262. TidalPy/utilities/dimensions/nondimensional.pxd +18 -0
  263. TidalPy/utilities/dimensions/nondimensional.pyx +94 -0
  264. TidalPy/utilities/dimensions/nondimensional_.hpp +13 -0
  265. TidalPy/utilities/exoplanets/__init__.py +1 -0
  266. TidalPy/utilities/exoplanets/data_download.py +135 -0
  267. TidalPy/utilities/graphics/__init__.py +10 -0
  268. TidalPy/utilities/graphics/global_map.py +329 -0
  269. TidalPy/utilities/graphics/grid_plot.py +763 -0
  270. TidalPy/utilities/graphics/multilayer/RN08-Data.csv +52 -0
  271. TidalPy/utilities/graphics/multilayer/T05-Data.csv +1 -0
  272. TidalPy/utilities/graphics/multilayer/__init__.py +1 -0
  273. TidalPy/utilities/graphics/multilayer/yplot.py +249 -0
  274. TidalPy/utilities/graphics/phasespace_plot.py +158 -0
  275. TidalPy/utilities/graphics/planet_plot.py +308 -0
  276. TidalPy/utilities/integration/__init__.py +170 -0
  277. TidalPy/utilities/integration/cyrk_helper.py +41 -0
  278. TidalPy/utilities/integration/julia_helper.py +134 -0
  279. TidalPy/utilities/integration/numbalsoda_helper.py +38 -0
  280. TidalPy/utilities/integration/scipy_helper.py +28 -0
  281. TidalPy/utilities/io/__init__.py +0 -0
  282. TidalPy/utilities/io/pathing.py +38 -0
  283. TidalPy/utilities/io/progress.py +57 -0
  284. TidalPy/utilities/math/__init__.pxd +5 -0
  285. TidalPy/utilities/math/__init__.py +0 -0
  286. TidalPy/utilities/math/complex.cp314-win_amd64.pyd +0 -0
  287. TidalPy/utilities/math/complex.pxd +43 -0
  288. TidalPy/utilities/math/complex.pyx +496 -0
  289. TidalPy/utilities/math/numba_special.py +64 -0
  290. TidalPy/utilities/math/numerics.cp314-win_amd64.pyd +0 -0
  291. TidalPy/utilities/math/numerics.pxd +8 -0
  292. TidalPy/utilities/math/numerics.pyx +37 -0
  293. TidalPy/utilities/math/special.cp314-win_amd64.pyd +0 -0
  294. TidalPy/utilities/math/special.pxd +1 -0
  295. TidalPy/utilities/math/special.pyx +81 -0
  296. TidalPy/utilities/multiprocessing/__init__.py +24 -0
  297. TidalPy/utilities/multiprocessing/multiprocessing.py +473 -0
  298. TidalPy/utilities/numpy_helper/__init__.py +3 -0
  299. TidalPy/utilities/numpy_helper/array_other.py +129 -0
  300. TidalPy/utilities/numpy_helper/array_shape.py +92 -0
  301. TidalPy/utilities/performance/__init__.py +19 -0
  302. TidalPy/utilities/performance/memory.py +53 -0
  303. TidalPy/utilities/performance/numba.py +75 -0
  304. TidalPy/utilities/performance/special/__init__.py +1 -0
  305. TidalPy/utilities/performance/special/factorial.py +28 -0
  306. TidalPy/utilities/spherical_helper/__init__.py +4 -0
  307. TidalPy/utilities/spherical_helper/mass.py +62 -0
  308. TidalPy/utilities/spherical_helper/volume.py +126 -0
  309. TidalPy/utilities/string_helper/__init__.py +2 -0
  310. TidalPy/utilities/string_helper/string_helper.py +120 -0
  311. TidalPy/utilities/types.py +30 -0
  312. TidalPy/utilities/types_x.cp314-win_amd64.pyd +0 -0
  313. TidalPy/utilities/types_x.pxd +3 -0
  314. TidalPy/utilities/types_x.pyx +2 -0
  315. tidalpy-0.7.5.dist-info/DELVEWHEEL +2 -0
  316. tidalpy-0.7.5.dist-info/METADATA +339 -0
  317. tidalpy-0.7.5.dist-info/RECORD +322 -0
  318. tidalpy-0.7.5.dist-info/WHEEL +5 -0
  319. tidalpy-0.7.5.dist-info/entry_points.txt +2 -0
  320. tidalpy-0.7.5.dist-info/licenses/LICENSE.md +179 -0
  321. tidalpy-0.7.5.dist-info/top_level.txt +1 -0
  322. tidalpy.libs/msvcp140-a4c2229bdc2a2a630acdc095b4d86008.dll +0 -0
@@ -0,0 +1,9 @@
1
+ extended_configs = dict()
2
+
3
+ from TidalPy.utilities.dictionary_utils import nested_merge
4
+ from TidalPy.Extending.burnman import burnman_installed
5
+
6
+ # Add any extension configs to the extended config dict which will be added to the tidalpy configs
7
+ if burnman_installed:
8
+ from TidalPy.Extending.burnman.burnman_defaultc import default_burnman_configs
9
+ extended_configs = nested_merge(extended_configs, default_burnman_configs)
@@ -0,0 +1,10 @@
1
+ from .package import burnman as burnman
2
+ from .package import Material as Material
3
+ from .package import Mineral as Mineral
4
+ from .package import material_property as material_property
5
+ from .package import dictionarize_formula as dictionarize_formula
6
+ from .package import formula_mass as formula_mass
7
+ from .package import burnman_installed as burnman_installed
8
+
9
+ from .build import build_burnman_world as build_burnman_world
10
+ from .burnman_world import BurnManWorld as BurnManWorld
@@ -0,0 +1,196 @@
1
+ from typing import Tuple
2
+
3
+ import numpy as np
4
+
5
+ from TidalPy.exceptions import BadValueError, ParameterMissingError, ParameterValueError
6
+ from TidalPy.utilities.types import float_eps
7
+ from TidalPy.Extending.burnman.package import burnman, burnman_installed
8
+ from TidalPy.Extending.burnman.defaults import default_burnman_layer_params
9
+ from TidalPy.Extending.burnman.material.helper import find_material
10
+
11
+ from TidalPy.logger import get_logger
12
+ log = get_logger("TidalPy")
13
+
14
+
15
+ def build_layer(layer_name: str, layer_config: dict, burnman_verbose: str = False) -> burnman.Layer:
16
+ """ Build a Burnman layer
17
+
18
+ Parameters
19
+ ----------
20
+ layer_name : str
21
+ Name of the layer
22
+ layer_config : dict
23
+ Dictionary of layer configurations used to initialize the layer
24
+ burnman_verbose : bool, default = False
25
+ Determines the verboseness of the BurnMan package.
26
+
27
+ Returns
28
+ -------
29
+ layer : burnman.Layer
30
+ An initialized burnman layer
31
+ """
32
+
33
+ # Record information
34
+ log.debug(f'Burnman layer {layer_name} being built.')
35
+ if not burnman_installed:
36
+ log.debug("Burnman install not found.")
37
+ raise ImportError('Burnman package not found.')
38
+
39
+ # Load in defaults
40
+ layer_config = {**default_burnman_layer_params, **layer_config}
41
+
42
+ # Check for missing parameters
43
+ for param_name in ['radii', 'material', 'material_source', 'temperature_mode']:
44
+ if param_name not in layer_config:
45
+ raise ParameterMissingError(f'BurnMan Layer requires parameter: {param_name}')
46
+
47
+ material = layer_config['material']
48
+ material_source = layer_config['material_source']
49
+
50
+ # Determine if the material is a composite or not
51
+ composite = False
52
+ if type(layer_config['material']) in [list, tuple]:
53
+ log.debug(f'Composite material encountered for layer: {layer_name}.')
54
+ composite = True
55
+
56
+ if composite:
57
+ try:
58
+ material_fractions = layer_config['material_fractions']
59
+ except KeyError:
60
+ raise ParameterMissingError("Multiple materials provided but no material_fraction's were given.")
61
+ if type(material_fractions) not in [list, tuple]:
62
+ raise ParameterValueError('Material fractions must be provided as a list or tuple.')
63
+ if type(material_source) not in [list, tuple]:
64
+ raise ParameterValueError('Multiple materials provided with only one source.')
65
+ if len(material) != len(material_source):
66
+ raise ParameterValueError('Number of composite materials is not the same as number of material sources.')
67
+ if len(material) != len(material_fractions):
68
+ raise ParameterValueError('Number of composite materials is not the same as number of material fractions.')
69
+
70
+ if type(material_fractions) is tuple:
71
+ # Burnman only supports lists for this
72
+ material_fractions = list(material_fractions)
73
+
74
+ material_instances = list()
75
+ for mat_name, mat_source in zip(material, material_source):
76
+ # Find BurnMan material based on material and source name
77
+ material_class = find_material(mat_name, mat_source)
78
+ material_instances.append(material_class())
79
+
80
+ # Build composite material
81
+ init_material = burnman.Composite(material_instances, material_fractions)
82
+
83
+ else:
84
+ # Find BurnMan material based on material and source name
85
+ material_class = find_material(layer_config['material'], layer_config['material_source'])
86
+
87
+ # Initialize material
88
+ init_material = material_class()
89
+
90
+ # Make layer and load in material
91
+ radii = layer_config['radii']
92
+ layer = burnman.Layer(name=layer_name, radii=radii, verbose=burnman_verbose)
93
+ layer.set_material(init_material)
94
+
95
+ # Don't keep radii in the config, otherwise it will save to the json file as a large list
96
+ del layer_config['radii']
97
+
98
+ # Load in temperature model
99
+ if layer_config['temperature_mode'] == 'adiabatic':
100
+ if layer_config.get('temperature_top', None) is None:
101
+ layer.set_temperature_mode('adiabatic')
102
+ else:
103
+ layer.set_temperature_mode('adiabatic', temperature_top=layer_config['temperature_top'])
104
+ elif layer_config['temperature_mode'] == 'user-defined':
105
+ layer.set_temperature_mode('user-defined', layer_config['temperature_fixed'] * np.ones_like(radii))
106
+ else:
107
+ layer.set_temperature_mode(layer_config['temperature_mode'])
108
+
109
+ return layer
110
+
111
+
112
+ def build_burnman_world(planet_config: dict, verbose: bool = False) -> Tuple[burnman.Planet, Tuple[burnman.Layer, ...]]:
113
+ """ Builds a BurnMan planet from a provided configuration dictionary.
114
+
115
+ Parameters
116
+ ----------
117
+ planet_config : dict
118
+ Dictionary of planet configurations used to initialize layers and the planet.
119
+ verbose : bool = False
120
+ If True, BurnMan will print more information to console.
121
+
122
+ Returns
123
+ -------
124
+ burnman_world : burnman.Planet
125
+ An initialized and built burnman planet class
126
+ burnman_layers : Tuple[burnman.Layer, ...]
127
+ An ordered list of initialized burnman layers
128
+ """
129
+
130
+ log.debug(f"Building BurnMan world: {planet_config['name']}")
131
+
132
+ if not burnman_installed:
133
+ log.debug("Burnman install not found.")
134
+ raise ImportError('Burnman package not found.')
135
+
136
+ # Store Layer information
137
+ try:
138
+ layers = planet_config['layers']
139
+ except KeyError:
140
+ raise ParameterMissingError('BurnMan Planet must have at least one layer.')
141
+
142
+ # Set defaults if none are provided
143
+ last_layer_radius = 0.
144
+ for layer_i, (layer_name, layer_config_user) in enumerate(layers.items()):
145
+
146
+ log.debug(f"Initializing layer: {layer_name}")
147
+
148
+ # Check if layer has must-have parameters
149
+ for param_name in ['type', 'material', 'radius']:
150
+ if param_name not in layer_config_user:
151
+ raise ParameterMissingError(f'BurnMan Layer requires parameter: {param_name}')
152
+
153
+ # Load in defaults for non-required parameters if not present
154
+ layer_config = {**default_burnman_layer_params, **layer_config_user}
155
+
156
+ # Load in calculated parameters
157
+ if 'thickness' not in layer_config:
158
+ if layer_i == 0:
159
+ layer_config['thickness'] = layer_config['radius']
160
+ else:
161
+ layer_config['thickness'] = layer_config['radius'] - last_layer_radius
162
+ layer_config['radius_upper'] = layer_config['radius']
163
+ layer_config['radius_lower'] = layer_config['radius_upper'] - layer_config['thickness']
164
+ layer_config['radii'] = np.linspace(
165
+ layer_config['radius_lower'], layer_config['radius_upper'],
166
+ layer_config['slices'], endpoint=True
167
+ )
168
+
169
+ # Check for physical consistency
170
+ if layer_config['thickness'] <= float_eps:
171
+ raise BadValueError('Layer thickness must be non-zero')
172
+ if layer_i > 0:
173
+ if layer_config['radius_lower'] != last_layer_radius:
174
+ raise BadValueError('Layers must stack on top of one another')
175
+
176
+ last_layer_radius = layer_config['radius']
177
+ # Put the new config back into the layers storage
178
+ layers[layer_name] = layer_config
179
+
180
+ # Build BurnMan layers
181
+ log.debug("Building BurnMan Layers")
182
+ burnman_layers_byname = {layer_name: build_layer(layer_name, layer_data) for layer_name, layer_data in
183
+ layers.items()}
184
+ burnman_layers = [burnman_layers_byname[layer_name] for layer_name in layers]
185
+
186
+ # Build BurnMan Planet
187
+ log.debug(f"Initializing BurnMan Planet for {planet_config['name']}")
188
+ burnman_world = burnman.Planet(planet_config['name'], burnman_layers, verbose=verbose)
189
+ # Note: This section can be slow!
190
+ burnman_world.make()
191
+ log.debug('BurnMan world construction completed')
192
+
193
+ # Change layer list to tuple to emphasize that these should not change or mutate
194
+ burnman_layers = tuple(burnman_layers)
195
+
196
+ return burnman_world, burnman_layers
@@ -0,0 +1,21 @@
1
+ default_burnman_configs = {
2
+ 'worlds': {
3
+ 'types': {
4
+ 'burnman': {
5
+ 'name' : 'unknown_world_burnman_type',
6
+ 'store_tides_config_in_world' : True,
7
+ 'force_spin_sync' : True,
8
+ 'equilibrium_insolation_model' : 'williams',
9
+ 'fraction_internal_heating_to_surface': 1.0,
10
+ 'emissivity' : 0.9,
11
+ 'albedo' : 0.3,
12
+ 'use_real_moi' : True,
13
+ 'tides_on' : True,
14
+ 'surface_pressure' : 0.,
15
+ 'slices' : None,
16
+ 'bm_interpolation_method' : 'mid', # Options: mid, avg, median
17
+ 'bm_interpolation_n' : 100
18
+ }
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,408 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ burnman_installed = True
4
+ try:
5
+ import burnman
6
+ except ImportError:
7
+ burnman_installed = False
8
+ # Build fake class so type checking passes.
9
+ class burnman:
10
+ Planet = None
11
+ Layer = None
12
+ Material = None
13
+
14
+ import numpy as np
15
+
16
+
17
+ import TidalPy
18
+ from TidalPy.exceptions import (AttributeNotSetError, ImproperPropertyHandling, UnknownTidalPyConfigValue)
19
+ from TidalPy.utilities.numpy_helper.array_other import find_nearest
20
+ from TidalPy.utilities.types import FloatArray
21
+ from TidalPy.structures.layers.physics import PhysicsLayer
22
+ from TidalPy.Extending.burnman.conversion import burnman_property_name_conversion, burnman_property_value_conversion
23
+
24
+ from TidalPy.logger import get_logger
25
+ log = get_logger("TidalPy")
26
+
27
+ if TYPE_CHECKING:
28
+ from .burnman_world import BurnManWorld
29
+
30
+
31
+ class BurnmanLayer(PhysicsLayer):
32
+ """ BurnmanLayer
33
+ Layer object to store parameters calculated by the Burnman software. Additionally it contains properties and
34
+ functionality that matches the TidalPy `PhysicsLayer`.
35
+
36
+
37
+ See Also
38
+ --------
39
+ TidalPy.structures.layers.PhysicsLayer
40
+ """
41
+
42
+ layer_class = 'burnman'
43
+
44
+ def __init__(
45
+ self, layer_name: str, layer_index: int, world: 'BurnManWorld', layer_config: dict,
46
+ is_top_layer: bool, initialize: bool = True
47
+ ):
48
+ """ Burnman layer constructor
49
+
50
+ Parameters
51
+ ----------
52
+ layer_name : str
53
+ User-friendly name of layer.
54
+ layer_index : int
55
+ Location of layer within a world (0 indicates center-most).
56
+ world : LayeredWorldType
57
+ World instance where layer was initialized in.
58
+ layer_config : dict
59
+ Layer's user-provided configurations.
60
+ is_top_layer : bool
61
+ If `True`, this layer is the top-most layer.
62
+ initialize : bool = True
63
+ If `True`, then the Layer's reinit is called at the end of the constructor.
64
+ """
65
+
66
+ if not burnman_installed:
67
+ log.warning('Burnman package not found. BurnmanLayer will have limited functionality.')
68
+
69
+ super().__init__(layer_name, layer_index, world, layer_config, is_top_layer, initialize=False)
70
+
71
+ # BurnmanLayer is built on the BurnMan API and layer system.
72
+ # Pull out BurnMan parameters
73
+ burnman_layer = self.world.bm_layers[layer_index]
74
+ self._bm_layer = burnman_layer
75
+ self._bm_material = burnman_layer.material
76
+
77
+ # Other state variables that will be initialized later
78
+ self._bm_mid_index = None
79
+ self._persistent_pressure = None
80
+ self.interp_func = None
81
+
82
+ # Material Properties set by BurnMan
83
+ self.interp_temperature_range = np.linspace(
84
+ *tuple(self.config['interp_temperature_range']),
85
+ self.world.config['bm_interpolation_n']
86
+ )
87
+ self._interp_prop_data_lookup = dict()
88
+
89
+ if initialize:
90
+ self.reinit(initial_init=initialize)
91
+
92
+ def reinit(self, initial_init: bool = False, initialize_geometry: bool = False):
93
+ """ Reinitialize the physical object by pulling in any potentially new configurations
94
+
95
+ Parameters
96
+ ----------
97
+ initial_init : bool = False
98
+ Set to `True` for the first time an instance is created.
99
+ set_by_burnman : bool = False
100
+ Set to `True` if a Burnman layer/world constructor is calling reinit
101
+ initialize_geometry : bool = False
102
+ Set to `True` if the set_geometry method should be called from within reinit
103
+ """
104
+
105
+ if initial_init or initialize_geometry:
106
+ # Find how many slices
107
+ self._num_slices = len(self.bm_layer.radii)
108
+
109
+ # Find which slice index is nearest to the middle of the layer (as determined by the radius/thickness)
110
+ thickness = self.bm_layer.thickness
111
+ self._bm_mid_index = find_nearest(self.bm_layer.radii, self.bm_layer.radii - (thickness / 2.))
112
+
113
+ # Setup geometry
114
+ self.set_geometry(radius=self.bm_layer.outer_radius, mass=self.bm_layer.mass, thickness=thickness)
115
+
116
+ # Call the standard reinit for the physics layer
117
+ super().reinit(initial_init, initialize_geometry=False)
118
+
119
+ # Build lookup tables
120
+ self._build_material_property_interpolation()
121
+
122
+ def set_state(
123
+ self, temperature: FloatArray = None, pressure: FloatArray = None, viscosity: FloatArray = None,
124
+ shear_modulus: FloatArray = None
125
+ ):
126
+ """ Set the layer's state properties
127
+
128
+ Parameters
129
+ ----------
130
+ temperature : FloatArray = None
131
+ New dynamic temperature for the layer [K].
132
+ pressure : FloatArray = None
133
+ New dynamic pressure for the layer [Pa].
134
+ viscosity : FloatArray = None
135
+ The new viscosity of the layer in [Pa s]
136
+ shear_modulus : FloatArray = None
137
+ The new shear modulus of the layer in [Pa]
138
+
139
+ """
140
+
141
+ # Check if the pressure or temperature of the layer has changed.
142
+ temperature_change = temperature is not None
143
+
144
+ # TODO: pressure_change is currently unused (see TODO below).
145
+ # pressure_change = pressure is not None
146
+
147
+ if temperature_change:
148
+ # Update material properties interpolated by burnman.
149
+
150
+ # TODO: Current limitations:
151
+ # - No material properties change when the pressure changes.
152
+ # - Future: Build another look up table for pressure?
153
+ # - Does not make calls to Burnman's EOS calculator for temperature changes, instead a lookup table is
154
+ # used to find pre-calculated values for the material properties.
155
+ # - Generally this should be okay for small temperature changes, but the larger the delta-temp the
156
+ # larger the error will be.
157
+ # - Recalculating the EOS can be computationally expensive, especially once it is wrapped within a bunch
158
+ # of TidalPy methods. This may be a major limitation to TidalPy's future development.
159
+ # - Workaround: the user can access the burnman layer and planet to manually update the EOS, but changes
160
+ # won't propagate into the TidalPy methods (as of writing).
161
+
162
+ # Set new material properties based on BurnMan Interpolation
163
+ for prop_name, prop_data in self._interp_prop_data_lookup.items():
164
+ setattr(self, prop_name, np.interp(temperature, self.interp_temperature_range, prop_data))
165
+ self.thermal_diffusivity = self.thermal_conductivity / (self.density * self.specific_heat)
166
+
167
+ # Set the new state properties in the layer.
168
+ super().set_state(temperature=temperature, pressure=pressure, viscosity=viscosity, shear_modulus=shear_modulus)
169
+
170
+ def set_geometry(
171
+ self, radius: float = None, mass: float = None, thickness: float = None,
172
+ mass_below: float = 0., update_state_geometry: bool = True, build_slices: bool = True
173
+ ):
174
+ """ Calculates and sets the layer's physical parameters based on user provided input.
175
+
176
+ For a BurnmanLayer almost all of the geometry is set by the results of the burnman evaluation.
177
+
178
+ Assumptions
179
+ -----------
180
+ Spherical Geometry
181
+
182
+ Parameters
183
+ ----------
184
+ radius : float = None
185
+ Outer radius of object [m]
186
+ mass : float = None
187
+ Mass of object [kg]
188
+ thickness : float = None
189
+ Thickness of the object [m]
190
+ mass_below : float = 0.
191
+ Mass below this object (only applicable for shell-like structures)
192
+ Used in gravity and pressure calculations
193
+ update_state_geometry : bool = True
194
+ Update the class' state geometry
195
+ build_slices : bool = True
196
+ If True, method will attempt to calculate gravities, densities, etc. for each slice.
197
+
198
+ """
199
+
200
+ # Set the physical properties
201
+ self._radius = self.bm_layer.outer_radius
202
+ self._thickness = self.bm_layer.thickness
203
+ self._radius_middle = self.radius - (self.thickness / 2.)
204
+ self._radius_inner = self.radius - self.thickness
205
+ self._volume = (4. / 3.) * np.pi * (self.radius**3 - self.radius_inner**3)
206
+ self._surface_area_outer = 4. * np.pi * self.radius**2
207
+ self._surface_area_middle = 4. * np.pi * self.radius_middle**2
208
+ self._surface_area_inner = 4. * np.pi * self.radius_inner**2
209
+
210
+ # Set the mass properties
211
+ self._mass = self.bm_layer.mass
212
+ self._density_bulk = self.mass / self.volume
213
+ if self.layer_below is None:
214
+ layer_below_mass = 0.
215
+ else:
216
+ layer_below_mass = self.layer_below.mass
217
+ self._mass_below = layer_below_mass
218
+
219
+ # Set slice physical properties
220
+ # For Burnman layers we want to skip the first step, we will do this for all items pulled from BM.
221
+ # But we want to keep the same number of shells. So we will perform an interpolation to expand from the
222
+ # Burnman values
223
+ bm_radii = self.bm_layer.radii
224
+ self._radii = np.linspace(bm_radii[1], bm_radii[-1], self.num_slices)
225
+ self._depths = self.radius - self._radii
226
+ self._sa_slices = 4. * np.pi * self.radii**2
227
+ self._volume_slices = np.zeros_like(self._radii)
228
+ self._volume_slices[0] = (4. / 3.) * np.pi * (self.radii[0]**3 - self.radius_inner**3)
229
+ self._volume_slices[1:] = (4. / 3.) * np.pi * (self.radii[1:]**3 - self.radii[:-1]**3)
230
+
231
+ # Set slice mass properties
232
+ self._density_slices = np.interp(self.radii, bm_radii, self.bm_layer.density)
233
+ self._gravity_slices = np.interp(self.radii, bm_radii, self.bm_layer.gravity)
234
+ self._pressure_slices = np.interp(self.radii, bm_radii, self.bm_layer.pressures)
235
+ self._mass_slices = self.density_slices * self.volume_slices
236
+
237
+ # Mass below each slice is equal to slice masses + and mass below this physical object
238
+ self._mass_below_slices = np.asarray(
239
+ [self.mass_below + sum(self.mass_slices[:i + 1]) for i in range(self.num_slices)]
240
+ )
241
+
242
+ # For BurnmanLayer, assume everything is calculated by BurnMan.
243
+ # Override some of the items set by the set_geometry method.
244
+ if self.world.config['bm_interpolation_method'] == 'mid':
245
+ self._pressure_middle = self.bm_layer.pressures[self._bm_mid_index]
246
+ self._density_middle = self.bm_layer.density[self._bm_mid_index]
247
+ self._gravity_middle = self.bm_layer.gravity[self._bm_mid_index]
248
+ self.interp_func = lambda array: array[self._bm_mid_index]
249
+ elif self.world.config['bm_interpolation_method'] == 'avg':
250
+ self._pressure_middle = np.average(self.bm_layer.pressures)
251
+ self._density_middle = np.average(self.bm_layer.density)
252
+ self._gravity_middle = np.average(self.bm_layer.gravity)
253
+ self.interp_func = np.average
254
+ elif self.world.config['bm_interpolation_method'] == 'median':
255
+ self._pressure_middle = np.median(self.bm_layer.pressures)
256
+ self._density_middle = np.median(self.bm_layer.density)
257
+ self._gravity_middle = np.median(self.bm_layer.gravity)
258
+ self.interp_func = np.median
259
+ else:
260
+ raise UnknownTidalPyConfigValue
261
+
262
+ # Set up a pressure that will persist if the layer's state is cleared
263
+ self._persistent_pressure = np.copy(self.pressure)
264
+
265
+ # Update state properties
266
+ # Note: these are not actually accessible without using the protected getter.
267
+ # Instead, the regular getter method pulls from the BurnMan layer directly (they have been inner-scoped)
268
+ # These definitions below are set just so that the protected properties still hold a value.
269
+ self._temperature_outer = self.bm_layer.temperatures[-1]
270
+ self._temperature_inner = self.bm_layer.temperatures[0]
271
+ self._density_outer = self.bm_layer.density[-1]
272
+ self._density_inner = self.bm_layer.density[0]
273
+ self._gravity_outer = self.bm_layer.gravity[-1]
274
+ self._gravity_inner = self.bm_layer.gravity[0]
275
+ self._pressure_outer = self.bm_layer.pressures[-1]
276
+ self._pressure_inner = self.bm_layer.pressures[0]
277
+
278
+ # Make a call to the parent methods set_geometry method, but update_state_geometry=False will prevent them from
279
+ # changing the geometry that was set above.
280
+ super().set_geometry(
281
+ self.radius, self.mass, self.thickness, mass_below=layer_below_mass,
282
+ update_state_geometry=False, build_slices=False
283
+ )
284
+
285
+ def set_static_pressure(
286
+ self, pressure_above: float = None, build_slices: bool = True,
287
+ called_from_burnman: bool = True
288
+ ):
289
+ """ Sets the static pressure for the physical structure.
290
+
291
+ `Static` here indicates that this is not a dynamic pressure used in many calculations. The static pressure can
292
+ be used in place of the dynamic pressure, but that is not always the case.
293
+
294
+ Parameters
295
+ ----------
296
+ pressure_above : float = None
297
+ Pressure above this structure. If this is a layer, then it is the pressure at the base of the overlying
298
+ layer. If it is the upper-most layer or a world, then it may be the surface pressure.
299
+ build_slices : bool = True
300
+ If `True`, method will find the pressure at each slice of the physical object.
301
+ called_from_burnman : bool = False
302
+ Set to `True` if called from a burnman layer/world.
303
+ """
304
+ log.debug('Static pressure method called from burnman layer - skipping update.')
305
+ # super().set_static_pressure(pressure_above, build_slices)
306
+
307
+ def geotherm(self, avg_temperature: float = None):
308
+ """ Calculates layer's geotherm based on an average temperature (or layer's current temperature)
309
+
310
+ Returns
311
+ -------
312
+ temperature_profile : np.ndarray
313
+ numpy array of the adiabatic temperature profile
314
+ """
315
+
316
+ if avg_temperature is None:
317
+ avg_temperature = self.temperature
318
+
319
+ temperature_profile = \
320
+ burnman.geotherm.adiabatic(self.bm_layer.pressures, avg_temperature, self.bm_layer.material)
321
+
322
+ # We again want to shrink the temperature domain to match the radii which only take [1:] of the Burnman version.
323
+ bm_radii = self.bm_layer.radii
324
+ temperature_profile = np.interp(self.radii, bm_radii, temperature_profile)
325
+
326
+ return temperature_profile
327
+
328
+ def _build_material_property_interpolation(self):
329
+ """ Interpolates material properties based on a fixed pressure and a suggested temperature range.
330
+
331
+ Using the BurnMan package's equation of states, this function will build interpolated lookup tables for several
332
+ material properties. These lookup tables are functions of only temperature; pressure is assumed to not
333
+ change significantly in a TidalPy simulation. However, the machinery to change properties based on
334
+ pressure is built into BurnMan and can be accessed via the layer's reference to the Burnman layer:
335
+ self.bm_material.evaluate
336
+
337
+ The specific constant pressure used in building the lookup table is set by the layer configuration. See the
338
+ variable 'bm_interpolation_method' in TidalPy's main configurations.py
339
+
340
+ Conversions between BurnMan and TidalPy property names are also performed here. Some conversions require a
341
+ transition from molar to specific.
342
+
343
+ The final interpolated lookup table is stored in the self._interp_prop_data_lookup which is used in the
344
+ temperature.setter
345
+ """
346
+
347
+ log.debug(f'Building Burnman material property lookup tables for {self}.')
348
+
349
+ if self.pressure is None:
350
+ raise AttributeNotSetError
351
+
352
+ self._interp_prop_data_lookup = dict()
353
+ interp_properties = ['bulk_modulus', 'thermal_expansion', 'specific_heat']
354
+ bm_properties = [burnman_property_name_conversion[interp_prop] for interp_prop in interp_properties]
355
+
356
+ # We will use the fixed pressure to calculate the various parameters at all the temperature ranges
357
+ # These results will then be used in an interpolation for whenever self.temperature changes
358
+ pressures = self.pressure * np.ones_like(self.interp_temperature_range)
359
+ property_results = self.bm_material.evaluate(bm_properties, pressures, self.interp_temperature_range)
360
+
361
+ for interp_prop, prop_result in zip(interp_properties, property_results):
362
+
363
+ # Perform any unit or other conversions needed to interface BurnMan to TidalPy
364
+ conversion_type = burnman_property_value_conversion.get(interp_prop, None)
365
+ if conversion_type is not None:
366
+ if conversion_type == 'molar':
367
+ # Convert the parameter from a molar value to a specific value
368
+ prop_result = prop_result / self.bm_material.molar_mass
369
+ else:
370
+ raise KeyError
371
+
372
+ self._interp_prop_data_lookup[interp_prop] = np.asarray(prop_result)
373
+
374
+ # State properties
375
+ @property
376
+ def bm_layer(self) -> burnman.Layer:
377
+ return self._bm_layer
378
+
379
+ @bm_layer.setter
380
+ def bm_layer(self, value):
381
+ raise ImproperPropertyHandling('Can not change burnman layer information after layer has been initialized.')
382
+
383
+ @property
384
+ def bm_material(self) -> burnman.Material:
385
+ return self._bm_material
386
+
387
+ @bm_material.setter
388
+ def bm_material(self, value):
389
+ raise ImproperPropertyHandling('Can not change burnman layer information after layer has been initialized.')
390
+
391
+ @property
392
+ def pressure(self):
393
+ """ Layer's dynamic pressure used in calculations """
394
+ # If there is no user provided pressure, use the one set by burnman
395
+ if self._pressure is None:
396
+ return self.pressure_middle
397
+ else:
398
+ return self._pressure
399
+
400
+ @pressure.setter
401
+ def pressure(self, new_pressure: FloatArray):
402
+ self.set_pressure(new_pressure)
403
+
404
+ # Add burnman layer type to known layer types
405
+ log.debug('Adding BurnmanLayer to known layer classes.')
406
+ TidalPy.structures.layers.known_layer_classes['burnman'] = BurnmanLayer
407
+ log.debug('Adding BurnmanLayer to known layer classes (by world type).')
408
+ TidalPy.structures.layers.layers_class_by_world_class['burnman'] = BurnmanLayer