pyrestoolbox 3.7.3__tar.gz → 3.7.4__tar.gz

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 (197) hide show
  1. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/PKG-INFO +3 -2
  2. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/README.rst +2 -1
  3. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyproject.toml +1 -1
  4. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/brine/__init__.py +1 -0
  5. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/brine/_lib_vle_engine.py +11 -7
  6. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/brine/brine.py +84 -12
  7. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/brine/pr_vphi.py +17 -12
  8. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/brine/vphi_route.py +21 -19
  9. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/brine.rst +271 -49
  10. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/changelist.rst +14 -0
  11. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/.github/workflows/build-wheels.yml +0 -0
  12. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/.github/workflows/tests.yml +0 -0
  13. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/.gitignore +0 -0
  14. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/Cargo.lock +0 -0
  15. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/Cargo.toml +0 -0
  16. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/LICENSE +0 -0
  17. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/MANIFEST.in +0 -0
  18. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/ResToolbox/privacy_policy.md +0 -0
  19. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/benchmark_batch.py +0 -0
  20. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/benchmark_rust_vs_python.py +0 -0
  21. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/benchmark_viscosity.py +0 -0
  22. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/benchmark_zfactor.py +0 -0
  23. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/benchmarks/_bench_worker.py +0 -0
  24. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/benchmarks/bench_acceleration.py +0 -0
  25. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/build_pure_python.py +0 -0
  26. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/mcp/DEPLOYMENT.md +0 -0
  27. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/mcp/Dockerfile +0 -0
  28. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/mcp/README.md +0 -0
  29. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/mcp/pyproject.toml +0 -0
  30. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/mcp/pyrestoolbox_mcp/__init__.py +0 -0
  31. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/mcp/pyrestoolbox_mcp/serialize.py +0 -0
  32. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/mcp/pyrestoolbox_mcp/server.py +0 -0
  33. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/mcp/tests/test_server.py +0 -0
  34. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyresToolbox_rust_acceleration_instructions.md +0 -0
  35. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/__init__.py +0 -0
  36. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/_accelerator.py +0 -0
  37. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/brine/_lib_dielectric.py +0 -0
  38. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/brine/_lib_maoduan_viscosity.py +0 -0
  39. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/brine/_lib_pitzer_params.py +0 -0
  40. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/brine/_lib_salting_library.py +0 -0
  41. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/brine/appelo_volumes.py +0 -0
  42. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/brine/iapws_viscosity.py +0 -0
  43. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/brine/jones_dole_viscosity.py +0 -0
  44. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/brine/kestin_nacl_viscosity.py +0 -0
  45. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/brine/viscosity_route.py +0 -0
  46. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/classes/__init__.py +0 -0
  47. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/classes/classes.py +0 -0
  48. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/constants/__init__.py +0 -0
  49. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/constants/constants.py +0 -0
  50. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/dca/__init__.py +0 -0
  51. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/dca/dca.py +0 -0
  52. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/dca.rst +0 -0
  53. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/examples.ipynb +0 -0
  54. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/gas.rst +0 -0
  55. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/img/bot.png +0 -0
  56. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/img/bot_PVTO.png +0 -0
  57. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/img/bot_img.png +0 -0
  58. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/img/dry_gas.png +0 -0
  59. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/img/grid_sat_df.png +0 -0
  60. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/img/influence.png +0 -0
  61. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/img/properties_df.png +0 -0
  62. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/img/sgof.png +0 -0
  63. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/img/swof.png +0 -0
  64. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/index.rst +0 -0
  65. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/layer.rst +0 -0
  66. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/library.rst +0 -0
  67. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/matbal.rst +0 -0
  68. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/nodal.rst +0 -0
  69. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/nodal_examples.ipynb +0 -0
  70. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/nodal_hydrate_demo.ipynb +0 -0
  71. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/oil.rst +0 -0
  72. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/plyasunov.rst +0 -0
  73. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/recommend.rst +0 -0
  74. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/sensitivity.rst +0 -0
  75. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/docs/simtools.rst +0 -0
  76. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/gas/__init__.py +0 -0
  77. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/gas/_hydrate.py +0 -0
  78. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/gas/gas.py +0 -0
  79. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/layer/__init__.py +0 -0
  80. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/layer/layer.py +0 -0
  81. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/library/__init__.py +0 -0
  82. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/library/component_library.xlsx +0 -0
  83. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/library/library.py +0 -0
  84. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/matbal/__init__.py +0 -0
  85. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/matbal/matbal.py +0 -0
  86. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/nodal/__init__.py +0 -0
  87. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/nodal/nodal.py +0 -0
  88. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/oil/__init__.py +0 -0
  89. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/oil/_compressibility.py +0 -0
  90. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/oil/_constants.py +0 -0
  91. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/oil/_correlations.py +0 -0
  92. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/oil/_density.py +0 -0
  93. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/oil/_harmonize.py +0 -0
  94. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/oil/_pvt_class.py +0 -0
  95. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/oil/_rate.py +0 -0
  96. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/oil/_separator.py +0 -0
  97. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/oil/_tables.py +0 -0
  98. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/oil/_utils.py +0 -0
  99. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/plyasunov/__init__.py +0 -0
  100. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/plyasunov/iapws_if97.py +0 -0
  101. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/plyasunov/plyasunov_model.py +0 -0
  102. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/plyasunov/water_properties.py +0 -0
  103. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/recommend/__init__.py +0 -0
  104. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/recommend/recommend.py +0 -0
  105. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/sensitivity/__init__.py +0 -0
  106. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/sensitivity/sensitivity.py +0 -0
  107. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/shared_fns/__init__.py +0 -0
  108. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/shared_fns/shared_fns.py +0 -0
  109. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/simtools/__init__.py +0 -0
  110. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/simtools/_aquifer.py +0 -0
  111. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/simtools/_decks.py +0 -0
  112. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/simtools/_pvt_tables.py +0 -0
  113. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/simtools/_relperm.py +0 -0
  114. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/simtools/_vfp.py +0 -0
  115. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/simtools/simtools.py +0 -0
  116. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/validate/__init__.py +0 -0
  117. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox/validate/validate.py +0 -0
  118. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox-mcp-0.1.0.zip +0 -0
  119. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/pyrestoolbox-mcp-email.txt +0 -0
  120. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/CONSOLIDATED.md +0 -0
  121. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/README.md +0 -0
  122. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/api_ux/_summary.md +0 -0
  123. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/api_ux/brine.md +0 -0
  124. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/api_ux/dca.md +0 -0
  125. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/api_ux/gas.md +0 -0
  126. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/api_ux/layer.md +0 -0
  127. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/api_ux/matbal.md +0 -0
  128. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/api_ux/nodal.md +0 -0
  129. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/api_ux/oil.md +0 -0
  130. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/api_ux/plyasunov.md +0 -0
  131. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/api_ux/recommend.md +0 -0
  132. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/api_ux/sensitivity.md +0 -0
  133. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/api_ux/simtools.md +0 -0
  134. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/correctness/_summary.md +0 -0
  135. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/correctness/brine.md +0 -0
  136. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/correctness/dca.md +0 -0
  137. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/correctness/gas.md +0 -0
  138. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/correctness/layer.md +0 -0
  139. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/correctness/matbal.md +0 -0
  140. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/correctness/nodal.md +0 -0
  141. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/correctness/oil.md +0 -0
  142. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/correctness/plyasunov.md +0 -0
  143. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/correctness/recommend.md +0 -0
  144. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/correctness/sensitivity.md +0 -0
  145. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/correctness/simtools.md +0 -0
  146. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/review-2026-06-10.md +0 -0
  147. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/tech_debt/_summary.md +0 -0
  148. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/tech_debt/brine.md +0 -0
  149. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/tech_debt/dca.md +0 -0
  150. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/tech_debt/gas.md +0 -0
  151. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/tech_debt/layer.md +0 -0
  152. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/tech_debt/matbal.md +0 -0
  153. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/tech_debt/nodal.md +0 -0
  154. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/tech_debt/oil.md +0 -0
  155. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/tech_debt/plyasunov.md +0 -0
  156. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/tech_debt/recommend.md +0 -0
  157. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/tech_debt/sensitivity.md +0 -0
  158. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/reviews/tech_debt/simtools.md +0 -0
  159. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/setup.cfg +0 -0
  160. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/setup.py +0 -0
  161. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/bessel.rs +0 -0
  162. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/critical_properties/mod.rs +0 -0
  163. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/dca/hyperbolic.rs +0 -0
  164. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/dca/mod.rs +0 -0
  165. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/dca/ransac.rs +0 -0
  166. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/gas_viscosity/mod.rs +0 -0
  167. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/gwr.rs +0 -0
  168. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/lib.rs +0 -0
  169. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/matbal/mod.rs +0 -0
  170. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/matbal/objective.rs +0 -0
  171. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/oil/density.rs +0 -0
  172. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/oil/mod.rs +0 -0
  173. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/pseudopressure.rs +0 -0
  174. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/spycher_pruess/mod.rs +0 -0
  175. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/spycher_pruess/solubility.rs +0 -0
  176. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vle/alpha.rs +0 -0
  177. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vle/bip.rs +0 -0
  178. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vle/components.rs +0 -0
  179. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vle/eos.rs +0 -0
  180. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vle/flash.rs +0 -0
  181. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vle/fugacity.rs +0 -0
  182. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vle/k_init.rs +0 -0
  183. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vle/mod.rs +0 -0
  184. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vle/rachford_rice.rs +0 -0
  185. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vlp/constants.rs +0 -0
  186. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vlp/friction.rs +0 -0
  187. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vlp/holdup_bb.rs +0 -0
  188. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vlp/holdup_gray.rs +0 -0
  189. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vlp/holdup_wg.rs +0 -0
  190. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vlp/ift.rs +0 -0
  191. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vlp/march.rs +0 -0
  192. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vlp/mod.rs +0 -0
  193. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vlp/pvt_helpers.rs +0 -0
  194. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/vlp/static_column.rs +0 -0
  195. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/src/zfactor/mod.rs +0 -0
  196. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/zstar_residual_plots.py +0 -0
  197. {pyrestoolbox-3.7.3 → pyrestoolbox-3.7.4}/zstar_vs_z_comparison.zip +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyrestoolbox
3
- Version: 3.7.3
3
+ Version: 3.7.4
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Rust
6
6
  Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
@@ -55,6 +55,7 @@ Includes functions to perform calculations including;
55
55
  - Generation of AQUTAB include file influence functions for use in ECLIPSE
56
56
  - Creation of Corey, LET and Jerauld relative permeability tables in Eclipse format, with curve fitting support
57
57
  - Calculation of Methane, CO2 and multicomponent gas saturated brine properties (Soreide-Whitson VLE)
58
+ - Multi-salt gas-free brine viscosity: IAPWS-2008 water, an ion-additive salt ratio over any combination of Na, K, Mg, Ca, Sr, Ba, Cl, Br, sulfate and carbonate, and a measured pressure factor
58
59
  - Method recommendation engine for selecting appropriate correlations based on fluid composition
59
60
  - Sensitivity analysis with parameter sweeps and tornado charts
60
61
 
@@ -127,7 +128,7 @@ Module List
127
128
  * - `library <https://github.com/mwburgoyne/pyResToolbox/blob/main/pyrestoolbox/docs/library.rst>`_
128
129
  - Return critical parameters for typical single components
129
130
  * - `brine <https://github.com/mwburgoyne/pyResToolbox/blob/main/pyrestoolbox/docs/brine.rst>`_
130
- - Calculate suite of brine properties with variable methane, Calculate suite of CO2 saturated brine properties, Multicomponent gas-saturated brine (Soreide-Whitson VLE)
131
+ - Calculate suite of brine properties with variable methane, Calculate suite of CO2 saturated brine properties, Multicomponent gas-saturated brine (Soreide-Whitson VLE), multi-salt gas-free brine viscosity
131
132
  * - `layer <https://github.com/mwburgoyne/pyResToolbox/blob/main/pyrestoolbox/docs/layer.rst>`_
132
133
  - Lorenz coefficient from Beta value, Lorenz coefficient from flow fraction, Lorenz coefficient to flow fraction, Lorenz coefficient to permeability array
133
134
  * - `simtools <https://github.com/mwburgoyne/pyResToolbox/blob/main/pyrestoolbox/docs/simtools.rst>`_
@@ -29,6 +29,7 @@ Includes functions to perform calculations including;
29
29
  - Generation of AQUTAB include file influence functions for use in ECLIPSE
30
30
  - Creation of Corey, LET and Jerauld relative permeability tables in Eclipse format, with curve fitting support
31
31
  - Calculation of Methane, CO2 and multicomponent gas saturated brine properties (Soreide-Whitson VLE)
32
+ - Multi-salt gas-free brine viscosity: IAPWS-2008 water, an ion-additive salt ratio over any combination of Na, K, Mg, Ca, Sr, Ba, Cl, Br, sulfate and carbonate, and a measured pressure factor
32
33
  - Method recommendation engine for selecting appropriate correlations based on fluid composition
33
34
  - Sensitivity analysis with parameter sweeps and tornado charts
34
35
 
@@ -101,7 +102,7 @@ Module List
101
102
  * - `library <https://github.com/mwburgoyne/pyResToolbox/blob/main/pyrestoolbox/docs/library.rst>`_
102
103
  - Return critical parameters for typical single components
103
104
  * - `brine <https://github.com/mwburgoyne/pyResToolbox/blob/main/pyrestoolbox/docs/brine.rst>`_
104
- - Calculate suite of brine properties with variable methane, Calculate suite of CO2 saturated brine properties, Multicomponent gas-saturated brine (Soreide-Whitson VLE)
105
+ - Calculate suite of brine properties with variable methane, Calculate suite of CO2 saturated brine properties, Multicomponent gas-saturated brine (Soreide-Whitson VLE), multi-salt gas-free brine viscosity
105
106
  * - `layer <https://github.com/mwburgoyne/pyResToolbox/blob/main/pyrestoolbox/docs/layer.rst>`_
106
107
  - Lorenz coefficient from Beta value, Lorenz coefficient from flow fraction, Lorenz coefficient to flow fraction, Lorenz coefficient to permeability array
107
108
  * - `simtools <https://github.com/mwburgoyne/pyResToolbox/blob/main/pyrestoolbox/docs/simtools.rst>`_
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "pyrestoolbox"
7
- version = "3.7.3"
7
+ version = "3.7.4"
8
8
  description = "pyResToolbox - A collection of Reservoir Engineering Utilities"
9
9
  license = {text = "GPL-3.0-or-later"}
10
10
  authors = [{name = "Mark W. Burgoyne", email = "mark.w.burgoyne@gmail.com"}]
@@ -1,4 +1,5 @@
1
1
  from .brine import *
2
+ from .brine import recommended_method # which entry point to use, and why
2
3
  from . import pr_vphi
3
4
  from .pr_vphi import V2_inf as V_phi_pr
4
5
  from . import vphi_route
@@ -37,10 +37,14 @@ RACHFORD-RICE SOLVER:
37
37
 
38
38
  References:
39
39
  - Soreide & Whitson, Fluid Phase Equilibria 77 (1992) 217-240 + Errata
40
+ - Burgoyne & Nielsen, Fluid Phase Equilibria (2026) 114824,
41
+ doi:10.1016/j.fluid.2026.114824 - the refreshed framework implemented here;
42
+ "this work" in comments below refers to this paper. Includes the H2
43
+ correlations (A=-14.59, B=2.184, C=0.365, kij_NA=0.468), the CH4 rational
44
+ form (A=-2.1642, B=1.7325, C=0.2105, MC-3 alpha), the embedded salinity
45
+ BIPs and the H2S salting-out treatment.
40
46
  - Yan et al., Fluid Phase Equilibria 298 (2011) 180-189 (improved CO2)
41
47
  - Nielsen & Lia, Fluid Phase Equilibria (2022) - Robust RR solver
42
- - This work (H2 correlations): A=-14.59, B=2.184, C=0.365, kij_NA=0.468
43
- - This work (CH4 rational): A=-2.1642, B=1.7325, C=0.2105 (MC-3 alpha)
44
48
 
45
49
  Author: Mark Burgoyne, Markus H. Nielsen
46
50
  Date: 2025-2026
@@ -366,7 +370,7 @@ _SW_GASES_WITH_EMBEDDED_SALINITY = {
366
370
  GASES_WITH_EMBEDDED_SALINITY = _SW_GASES_WITH_EMBEDDED_SALINITY
367
371
 
368
372
 
369
- # --- Proposed freshwater kij_AQ (Paper 2, MC-3 alpha) ---
373
+ # --- Proposed freshwater kij_AQ (Burgoyne & Nielsen 2026, MC-3 alpha) ---
370
374
  def kij_aq_co2_proposed(T_K: float, salinity_molal: float = 0.0) -> float:
371
375
  """CO2: cubic in T(K), n=614, MAE=0.0119 (MC-3 alpha)."""
372
376
  return -1.5127 + 9.4980e-3*T_K - 2.1680e-5*T_K**2 + 1.8500e-8*T_K**3
@@ -380,7 +384,7 @@ def kij_aq_n2_proposed(T_K: float, salinity_molal: float = 0.0) -> float:
380
384
  return -1.6669 + 3.447873e-3 * T_K
381
385
 
382
386
  def kij_aq_h2_proposed(T_K: float, salinity_molal: float = 0.0) -> float:
383
- """H2: rational, n=162, MAE=0.0400 (Paper 2 MC-3 coefficients)."""
387
+ """H2: rational, n=162, MAE=0.0400 (Burgoyne & Nielsen 2026 MC-3 coefficients)."""
384
388
  Tr = T_K / 33.145
385
389
  return (-14.6157 + Tr) / (3.5494 + 0.2230 * Tr)
386
390
 
@@ -513,7 +517,7 @@ KIJ_AQ_FUNCTIONS: Dict[str, Callable] = KIJ_AQ_PROPOSED
513
517
 
514
518
 
515
519
  # =============================================================================
516
- # Embedded Salinity BIP Parameters (Paper 2, all 8 gases)
520
+ # Embedded Salinity BIP Parameters (Burgoyne & Nielsen 2026, all 8 gases)
517
521
  # =============================================================================
518
522
  # Form: kij(T,m) = kij_fw(T) + (a0 + a1*Tr + a2*Tr^2)*m [+ (b0 + b1*Tr)*m^2 for CO2]
519
523
  # Tr = T/Tc for each gas. Fitted with MC-3 alpha + proposed kij_fw.
@@ -1446,7 +1450,7 @@ class SWBinaryVLE:
1446
1450
  params=EMBEDDED_SALINITY_PARAMS_DROPIN[self.gas])
1447
1451
  kij_aq = kij_fw + delta
1448
1452
  else:
1449
- # Use Paper 2 embedded delta (proposed framework)
1453
+ # Use Burgoyne & Nielsen 2026 embedded delta (proposed framework)
1450
1454
  delta = calc_embedded_delta_kij(self.gas, T_K, self.salinity)
1451
1455
  kij_aq = kij_fw + delta
1452
1456
  x_gas = self._calc_x_with_kij(T_K, P_Pa, kij_aq)
@@ -1702,7 +1706,7 @@ def get_gas_gas_bip(gas_a: str, gas_b: str) -> float:
1702
1706
 
1703
1707
  _SW_KVALUE_PARAMS = {
1704
1708
  # Light gases: Cross form [a, b, c, d, e, f]
1705
- # Fitted using proposed Paper 2 freshwater kij_AQ forms (Feb 2026)
1709
+ # Fitted using proposed Burgoyne & Nielsen 2026 freshwater kij_AQ forms (Feb 2026)
1706
1710
  'H2': [6.4295, 25.5844, -0.5985, -50.0000, -0.0007, -3.2598],
1707
1711
  'CO2': [-5.9974, 26.3804, -0.9380, -16.3941, 0.0607, 0.3688],
1708
1712
  'N2': [1.4998, 36.4929, -0.6419, -50.0000, 0.0110, -0.6328],
@@ -367,7 +367,15 @@ def brine_props(p: float = None, degf: float = None, wt: float = None, ch4_sat:
367
367
  # Superseded the Mao-Duan chain in 3.7.3; NaCl viscosities move by 0.34%
368
368
  # mean and 1.36% max, which is the route change rather than a regression.
369
369
  # Mao-Duan remains available as route='mao_duan' for reproducibility.
370
- ub_tpm = _brine_viscosity(degk, Mpa, m=m) # cP
370
+ ub_tpm = _brine_viscosity(degk, Mpa, m=m) # cP, gas-free
371
+
372
+ # Dissolved-CH4 viscosity correction, applied from 3.7.4. This function had
373
+ # returned the GAS-FREE viscosity for a brine it reports as methane
374
+ # saturated, which understated the measured effect (Ostermann 1985: +3 to 6%)
375
+ # by the full size of that effect. mch4 is the dissolved molality from
376
+ # Eqs 4.15-4.18; the correction is a function of mole fraction.
377
+ ub_tpm = ub_tpm * ch4_viscosity_factor(
378
+ degk, ch4_mole_fraction_from_molality(mch4))
371
379
 
372
380
  bw = Bw # rb/stb (dimensionless ratio, same in both unit systems)
373
381
  lden = rhobtpbch4 # sg (g/cm3)
@@ -1322,11 +1330,14 @@ def make_pvtw_table(*args, **kwargs):
1322
1330
  # (1969) AIChE J 15:272. Murphy & Gaines report viscosity ratios but no mole
1323
1331
  # fractions; taking x_H2S from Soreide-Whitson instead put it 4.5 to 9.2% high
1324
1332
  # against Burgess & Germann, and since a scales as 1/x it biased the coefficient
1325
- # low by the same amount. Implied coefficients on the correct basis are 2.31,
1326
- # 1.54, 1.98, 1.31 and 0.27; the adopted value is the mean of the four below
1327
- # 35 degC. Was 1.64 (S&W basis), and 1.50 before the primary source was read.
1328
- _IC_A_H2S = 1.79 # Murphy & Gaines Table IV on Burgess & Germann solubility
1329
- _IC_B = 1.0134 # Islam-Carlson exponent
1333
+ # low by the same amount. Implied coefficients on the correct basis are 2.20,
1334
+ # 1.47, 1.89, 1.25 and 0.26; the adopted value is the mean of the four below
1335
+ # 35 degC. Exponent set to UNITY 2026-07-31: the prior 1.0134 was borrowed
1336
+ # from Islam-Carlson's CO2 fit and never fitted to H2S, and the five points
1337
+ # cannot distinguish exponents (RMS 1.740 vs 1.738 pp). Was 1.79 with the
1338
+ # borrowed exponent, 1.64 (S&W basis), and 1.50 before the primary source
1339
+ # was read.
1340
+ _H2S_A = 1.70 # Murphy & Gaines Table IV on Burgess & Germann solubility
1330
1341
 
1331
1342
  # Calabrese et al. (2019) Eq. 25 CO2 viscosity increment (JCED 64:3831):
1332
1343
  # ln(mu/mu_brine) = e1 * exp(-e2*(T_K/T0 - 1)) * x_CO2
@@ -1363,6 +1374,31 @@ _CH4_A = 1.71739196e-03
1363
1374
  _CH4_B = 1239.77535 # K
1364
1375
  _CH4_K = 1.52860547e-03 # half-saturation mole fraction
1365
1376
 
1377
+ _MW_H2O = 18.015268
1378
+
1379
+
1380
+ def ch4_viscosity_factor(T_K, x_ch4):
1381
+ """Dissolved-CH4 viscosity multiplier, Ostermann (1985) SPE 14211.
1382
+
1383
+ x_ch4 is the dissolved mole fraction on the SALT-FREE basis, which is what
1384
+ the S&W flash returns and what the fit was performed against.
1385
+
1386
+ Shared by SoreideWhitson and brine_props so the two cannot diverge. Before
1387
+ 3.7.4 brine_props applied no CH4 viscosity correction at all: it returned the
1388
+ gas-free viscosity for a brine it simultaneously reported as methane
1389
+ saturated, understating the measured effect by 3 to 6 percent.
1390
+ """
1391
+ if x_ch4 <= 0.0:
1392
+ return 1.0
1393
+ return 1.0 + _CH4_A * np.exp(_CH4_B / T_K) * x_ch4 / (_CH4_K + x_ch4)
1394
+
1395
+
1396
+ def ch4_mole_fraction_from_molality(m_ch4):
1397
+ """Dissolved CH4 molality (mol/kg water) -> salt-free mole fraction."""
1398
+ if m_ch4 <= 0.0:
1399
+ return 0.0
1400
+ return m_ch4 / (m_ch4 + 1000.0 / _MW_H2O)
1401
+
1366
1402
  # HC component molecular weights for SG-based splitting
1367
1403
  _MW_C1 = 16.043
1368
1404
  _MW_C2 = 30.069
@@ -1404,8 +1440,10 @@ from pyrestoolbox.brine._lib_vle_engine import calc_gas_brine_equilibrium as _ca
1404
1440
 
1405
1441
 
1406
1442
  class SoreideWhitson:
1407
- """ Soreide-Whitson (1992) VLE model for multicomponent gas solubility in water/brine,
1408
- with Garcia/Plyasunov density corrections and calibrated viscosity corrections.
1443
+ """ Soreide-Whitson VLE model for multicomponent gas solubility in water/brine,
1444
+ using by default the refreshed BIP relationships of Burgoyne & Nielsen (2026),
1445
+ Fluid Phase Equilibria 114824, doi:10.1016/j.fluid.2026.114824, with
1446
+ mass-balance density corrections and calibrated viscosity corrections.
1409
1447
 
1410
1448
  Uses the S&W VLE engine for gas-brine equilibrium calculations, supporting
1411
1449
  multicomponent gas mixtures containing: C1, C2, C3, nC4, CO2, H2S, N2, H2.
@@ -1439,7 +1477,8 @@ class SoreideWhitson:
1439
1477
  sg: Gas specific gravity — used to estimate HC split among C1-C4 (default 0.65)
1440
1478
  metric: Boolean for units (True=metric, False=oilfield). Default False.
1441
1479
  cw_sat: If True, also calculate saturated compressibility (default False)
1442
- framework: VLE framework. 'proposed' (default, Soreide-Whitson 1992 re-fit),
1480
+ framework: VLE framework. 'proposed' (default, the Burgoyne & Nielsen 2026
1481
+ refreshed Soreide-Whitson BIPs, doi:10.1016/j.fluid.2026.114824),
1443
1482
  'sw_original' (original 1992 published), or 'dropin' (fitted to PR-EOS with
1444
1483
  brine-aware water alpha). Affects kij and ks correlations.
1445
1484
  salinity_method: How salinity enters the flash. 'gamma_phi' (default, Sechenov
@@ -1897,10 +1936,10 @@ class SoreideWhitson:
1897
1936
  T_K = (degf - 32.0) / 1.8 + 273.15
1898
1937
  vis_factor *= np.exp(_CAL_E1 * np.exp(-_CAL_E2 * (T_K / _CAL_T0 - 1.0)) * x_i)
1899
1938
  elif gas_upper == 'H2S':
1900
- vis_factor *= (1.0 + _IC_A_H2S * x_i ** _IC_B)
1939
+ vis_factor *= (1.0 + _H2S_A * x_i)
1901
1940
  elif gas_upper == 'CH4':
1902
1941
  T_K = (degf - 32.0) / 1.8 + 273.15
1903
- vis_factor *= 1.0 + _CH4_A * np.exp(_CH4_B / T_K) * x_i / (_CH4_K + x_i)
1942
+ vis_factor *= ch4_viscosity_factor(T_K, x_i)
1904
1943
  # C2H6, N2, H2, C3H8, nC4H10: no correction (factor *= 1.0)
1905
1944
 
1906
1945
  vis_gas_brine = vis_base_cP * vis_factor
@@ -1986,4 +2025,37 @@ class SoreideWhitson:
1986
2025
  else:
1987
2026
  rho_p1_gcc = rho_brine_p1_gcc
1988
2027
 
1989
- self.Cf_usat = 1.0 - rho_gas_brine_gcc / rho_p1_gcc # 1/bar
2028
+ self.Cf_usat = 1.0 - rho_gas_brine_gcc / rho_p1_gcc # 1/bar
2029
+
2030
+ # ============================================================================
2031
+ # Single recommended entry point
2032
+ # ============================================================================
2033
+
2034
+ _BRINE_METHODS = {
2035
+ 'co2': ('CO2_Brine_Mixture', 'Spycher-Pruess mutual solubility'),
2036
+ 'sw': ('SoreideWhitson', 'Soreide-Whitson multicomponent PR flash'),
2037
+ 'ch4': ('brine_props', 'Duan-Mao/McCain Ch. 4 methane solubility'),
2038
+ }
2039
+
2040
+
2041
+ def recommended_method(y_CO2=0.0, y_H2S=0.0, y_N2=0.0, y_H2=0.0, ch4_only=False):
2042
+ """Which brine entry point to use for a given equilibrium gas, and why.
2043
+
2044
+ The three entry points are not interchangeable wrappers: they carry three
2045
+ different SOLUBILITY models, and each is the better choice somewhere. This
2046
+ returns the recommendation rather than hiding it, because which model
2047
+ produced a number is part of the answer.
2048
+
2049
+ Returns (function name, solubility model, reason).
2050
+ """
2051
+ others = float(y_H2S) + float(y_N2) + float(y_H2)
2052
+ if float(y_CO2) >= 1.0 - 1e-12 and others <= 1e-12:
2053
+ return _BRINE_METHODS['co2'] + (
2054
+ 'pure CO2: Spycher-Pruess scores 3.7% MARE against Yan (2011) '
2055
+ 'where the S&W flash scores 8.3%',)
2056
+ if ch4_only and others <= 1e-12 and float(y_CO2) <= 1e-12:
2057
+ return _BRINE_METHODS['ch4'] + (
2058
+ 'methane only, in oilfield units, following McCain Ch. 4; use '
2059
+ 'SoreideWhitson instead if you want the S&W flash or any other gas',)
2060
+ return _BRINE_METHODS['sw'] + (
2061
+ 'any gas mixture, or any gas other than pure CO2',)
@@ -110,7 +110,7 @@ VSHIFT = {
110
110
  'CH4': -0.109632,
111
111
  'CO2': -0.037913,
112
112
  'H2S': -0.078975,
113
- 'N2': -0.155288,
113
+ 'N2': -0.176510,
114
114
  'H2': -0.177625,
115
115
  'C2H6': -0.073142,
116
116
  # C3H8 added 2026-07-25. NOT fitted to a densimetric data set, because none
@@ -208,15 +208,19 @@ def _check(gas, T, P):
208
208
 
209
209
  def V2_inf_raw(gas, T, P, m_nacl=0.0):
210
210
  """Unshifted V2inf from the exact EOS relation, cm3/mol. No range guard."""
211
- V = v_water_liquid(T, P, m_nacl)
211
+ # The two derivatives of V2 = -(dP/dn2)/(dP/dV) are evaluated ANALYTICALLY
212
+ # at n1 = 1, n2 = 0, V = v_w (closed forms: manuscript Appendix B).
213
+ # Switched from finite differences 2026-07-31; the difference evaluation
214
+ # agrees to 4e-5 cm3/mol, its truncation error.
215
+ v = v_water_liquid(T, P, m_nacl)
212
216
  kij = _SW.get_kij_aq(_SW_NAME.get(gas, gas), T, m_nacl)
213
- # dP/dn2 at fixed T, V, n1: one-sided, because n2 = 0 is the boundary
214
- h = 1e-7
215
- dPdn2 = (_P_mix(T, V, 1.0, h, gas, kij, m_nacl)
216
- - _P_mix(T, V, 1.0, 0.0, gas, kij, m_nacl)) / h
217
- dV = V * 1e-7
218
- dPdV = (_P_mix(T, V + dV, 1.0, 0.0, gas, kij, m_nacl)
219
- - _P_mix(T, V - dV, 1.0, 0.0, gas, kij, m_nacl)) / (2.0 * dV)
217
+ a1, b1 = _ab('H2O', T, m_nacl)
218
+ a2, b2 = _ab(gas, T)
219
+ a12 = np.sqrt(a1 * a2) * (1.0 - kij)
220
+ D = v * v + 2.0 * b1 * v - b1 * b1
221
+ dPdn2 = (R * T / (v - b1) + R * T * b2 / (v - b1) ** 2
222
+ - (2.0 * a12 * D - 2.0 * a1 * b2 * (v - b1)) / D ** 2)
223
+ dPdV = -R * T / (v - b1) ** 2 + 2.0 * a1 * (v + b1) / D ** 2
220
224
  return -dPdn2 / dPdV
221
225
 
222
226
 
@@ -228,9 +232,10 @@ def V2_inf(gas, T, P, m_nacl=0.0, s=None):
228
232
  T: K, within T_MIN..T_MAX and above the water saturation pressure
229
233
  P: MPa, up to P_MAX
230
234
  m_nacl: NaCl molality. Enters the S&W water alpha and kij only; there is
231
- NO salinity term on the volume shift, consistent with the project's
232
- decision that a salt effect on V_phi is real but not applied
233
- (see salt_effect_vphi.py). Leave at 0 for the calibrated behaviour.
235
+ NO salinity term on the volume shift. The salt effect on V_phi
236
+ is applied one level up (vphi_route, as a relative fraction since
237
+ 2026-07-30), never here, so there is no double counting. Leave at
238
+ 0 for the calibrated behaviour.
234
239
  s: override the dimensionless volume shift (for refitting).
235
240
 
236
241
  Returns:
@@ -42,26 +42,27 @@ DEFAULT_ROUTE = "auto"
42
42
 
43
43
 
44
44
  # ---------------------------------------------------------------- salt effect
45
- # ADOPTED 2026-07-25. V_phi falls with salinity. This term is fixed ENTIRELY
46
- # from direct measurement, with no parameter fitted to any brine-density data:
47
- # Tiepel & Gubbins (1972) dilatometry, 15 apparent molar volumes over five gases
48
- # and four electrolytes, every one negative, fitted as
49
- # dV = -a*m/(1 + b*m), a = 0.5914, b = 0.0416 [cm3/mol, m in mol/kg]
50
- # giving -0.57 at 1 molal and -2.45 at 5 molal. Enns, O'Sullivan & Smith and
51
- # Heusler & Gaiser agree on sign and magnitude. It is the conservative end of
52
- # the available range, so it under-corrects rather than over-corrects.
45
+ # ADOPTED 2026-07-25 as an absolute additive term; FORM CHANGED to RELATIVE
46
+ # 2026-07-30. V_phi falls with salinity. The dimensionless fraction is fixed
47
+ # ENTIRELY from direct measurement, with no parameter fitted to any
48
+ # brine-density data: the seven Tiepel & Gubbins (1972) KCl dilatometry points,
49
+ # fitted as (generated by brine_props/code/relative_salt_shift.py)
50
+ # V_eff = V_phi(T,P) * (1 + g(m)), g(m) = -c*m/(1 + d*m)
51
+ # giving -1.56% at 1 molal and -5.85% at 5 molal. Enns and O'Sullivan & Smith
52
+ # agree on sign and size; the magnitude is known to about a factor of two
53
+ # (O'Sullivan NaCl shallower, Tiepel KCl at this value).
53
54
  #
54
55
  # The EOS's own salinity response (via the S&W water alpha and kij) is only
55
56
  # -0.03 to -0.07 cm3/mol per molal, an order of magnitude too small and linear
56
57
  # where the measurements saturate. It is therefore not used, and this term
57
58
  # carries the whole effect, so there is no double counting.
58
- SALT_A, SALT_B = 0.5914, 0.0416
59
+ SALT_C, SALT_D = 0.017009386, 0.090684173 # 8 sig digits, generated - do not retype
59
60
 
60
61
 
61
- def salt_shift(m_nacl: float) -> float:
62
- """Change in V_phi from dissolved salt, cm3/mol. Gas-generic, always <= 0."""
62
+ def salt_fraction(m_nacl: float) -> float:
63
+ """Fractional change in V_phi from dissolved salt. Gas-generic, always <= 0."""
63
64
  m = max(float(m_nacl), 0.0)
64
- return -SALT_A * m / (1.0 + SALT_B * m)
65
+ return -SALT_C * m / (1.0 + SALT_D * m)
65
66
 
66
67
 
67
68
  def pr_applicable(gas: str, T: float, P: float) -> bool:
@@ -90,17 +91,18 @@ def V_phi(gas: str, T: float, P: float, route: str = DEFAULT_ROUTE,
90
91
  P: pressure, MPa
91
92
  route: 'auto' uses PR where calibrated and Plyasunov elsewhere; 'pr'
92
93
  forces PR and raises outside its box; 'plyasunov' forces A12inf.
93
- m_nacl: NaCl molality. Applies the literature-anchored salt shift; it is
94
- NOT passed to the EOS, whose own salinity response is far too small.
95
- salt_effect: set False to recover the pre-2026-07-25 freshwater V_phi.
94
+ m_nacl: NaCl molality. Applies the literature-anchored relative salt
95
+ fraction; it is NOT passed to the EOS, whose own salinity response
96
+ is far too small.
97
+ salt_effect: set False to recover the freshwater V_phi.
96
98
  """
97
99
  if route not in ROUTES:
98
100
  raise ValueError(f"route must be one of {ROUTES}, got {route!r}")
99
- dV = salt_shift(m_nacl) if salt_effect else 0.0
101
+ f = 1.0 + (salt_fraction(m_nacl) if salt_effect else 0.0)
100
102
  if route == "plyasunov":
101
- return float(_plyasunov_V_phi(gas, T, P)) + dV
103
+ return float(_plyasunov_V_phi(gas, T, P)) * f
102
104
  if route == "pr":
103
- return float(_pr.V2_inf(gas, T, P)) + dV
105
+ return float(_pr.V2_inf(gas, T, P)) * f
104
106
  base = (float(_pr.V2_inf(gas, T, P)) if pr_applicable(gas, T, P)
105
107
  else float(_plyasunov_V_phi(gas, T, P)))
106
- return base + dV
108
+ return base * f