pyrestoolbox 3.8.1__tar.gz → 3.8.3__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.
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/.github/workflows/tests.yml +26 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/Cargo.lock +1 -1
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/Cargo.toml +1 -1
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/PKG-INFO +2 -2
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/README.rst +1 -1
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/mcp/Dockerfile +1 -1
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/mcp/pyproject.toml +2 -2
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/mcp/pyrestoolbox_mcp/server.py +24 -14
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/mcp/tests/test_server.py +41 -10
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyproject.toml +1 -1
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/_lib_salting_library.py +1 -1
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/_lib_vle_engine.py +206 -79
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/brine.py +31 -10
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/pr_vphi.py +10 -2
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/vphi_route.py +2 -1
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/constants/constants.py +3 -2
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/brine.rst +59 -13
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/changelist.rst +14 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/gas.rst +110 -26
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/matbal.rst +4 -1
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/nodal.rst +2 -2
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/recommend.rst +10 -4
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/gas/_hydrate.py +7 -3
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/gas/gas.py +139 -122
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/matbal/matbal.py +6 -3
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/nodal/nodal.py +6 -7
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/plyasunov/plyasunov_model.py +1 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/recommend/recommend.py +11 -6
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/shared_fns/shared_fns.py +4 -12
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/bessel.rs +5 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/critical_properties/mod.rs +8 -4
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/gas_viscosity/mod.rs +29 -24
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/pseudopressure.rs +14 -14
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/bip.rs +23 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/components.rs +9 -4
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/flash.rs +178 -9
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/k_init.rs +13 -1
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/zfactor/mod.rs +67 -53
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/.github/complexity-baseline.json +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/.github/scripts/check_complexity.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/.github/workflows/build-wheels.yml +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/.gitignore +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/LICENSE +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/MANIFEST.in +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/ResToolbox/privacy_policy.md +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/build_pure_python.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/clippy.toml +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/mcp/README.md +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/mcp/pyrestoolbox_mcp/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/mcp/pyrestoolbox_mcp/serialize.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/_accelerator.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/_lib_dielectric.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/_lib_maoduan_viscosity.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/_lib_pitzer_params.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/appelo_volumes.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/iapws_viscosity.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/jones_dole_viscosity.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/kestin_nacl_viscosity.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/viscosity_route.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/classes/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/classes/classes.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/constants/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/dca/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/dca/dca.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/dca.rst +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/examples.ipynb +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/bot.png +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/bot_PVTO.png +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/bot_img.png +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/dry_gas.png +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/grid_sat_df.png +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/influence.png +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/properties_df.png +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/sgof.png +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/swof.png +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/index.rst +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/layer.rst +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/library.rst +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/nodal_examples.ipynb +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/nodal_hydrate_demo.ipynb +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/oil.rst +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/plyasunov.rst +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/sensitivity.rst +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/simtools.rst +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/gas/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/layer/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/layer/layer.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/library/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/library/component_library.xlsx +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/library/library.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/matbal/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/nodal/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_compressibility.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_constants.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_correlations.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_density.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_harmonize.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_pvt_class.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_rate.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_separator.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_tables.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_utils.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/plyasunov/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/plyasunov/iapws_if97.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/plyasunov/water_properties.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/recommend/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/sensitivity/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/sensitivity/sensitivity.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/shared_fns/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/_aquifer.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/_decks.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/_pvt_tables.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/_relperm.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/_vfp.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/simtools.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/validate/__init__.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/pyrestoolbox/validate/validate.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/setup.cfg +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/setup.py +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/brine_visc/mod.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/brine_visc/salt.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/brine_visc/water.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/dca/hyperbolic.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/dca/mod.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/dca/ransac.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/gwr.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/lib.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/matbal/mod.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/matbal/objective.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/oil/density.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/oil/mod.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/spycher_pruess/mod.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/spycher_pruess/solubility.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/alpha.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/eos.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/fugacity.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/mod.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vle/rachford_rice.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/constants.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/friction.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/holdup_bb.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/holdup_gray.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/holdup_wg.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/ift.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/march.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/mod.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/pvt_helpers.rs +0 -0
- {pyrestoolbox-3.8.1 → pyrestoolbox-3.8.3}/src/vlp/static_column.rs +0 -0
|
@@ -63,6 +63,32 @@ jobs:
|
|
|
63
63
|
- name: Run full test suite (Rust + parity)
|
|
64
64
|
run: python3 -m pytest pyrestoolbox/tests/ -q
|
|
65
65
|
|
|
66
|
+
# ── MCP server (separate distribution in mcp/) on both SDK majors ────
|
|
67
|
+
# The server picks FastMCP (1.x) or MCPServer (2.x) at import; test both so
|
|
68
|
+
# an SDK release that breaks either path fails here, not in a deployment.
|
|
69
|
+
test-mcp:
|
|
70
|
+
name: MCP server (${{ matrix.mcp }})
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
strategy:
|
|
73
|
+
fail-fast: false
|
|
74
|
+
matrix:
|
|
75
|
+
mcp: ["mcp>=1.2,<2", "mcp>=2,<3"]
|
|
76
|
+
steps:
|
|
77
|
+
- uses: actions/checkout@v5
|
|
78
|
+
|
|
79
|
+
- uses: actions/setup-python@v6
|
|
80
|
+
with:
|
|
81
|
+
python-version: "3.12"
|
|
82
|
+
|
|
83
|
+
- name: Install dependencies
|
|
84
|
+
run: pip install numpy scipy pandas tabulate openpyxl mpmath ilt-inversion pytest "${{ matrix.mcp }}"
|
|
85
|
+
|
|
86
|
+
# Library from the source tree (pure Python), server from mcp/.
|
|
87
|
+
- name: Run MCP tests
|
|
88
|
+
env:
|
|
89
|
+
PYRESTOOLBOX_NO_RUST: "1"
|
|
90
|
+
run: PYTHONPATH="$PWD:$PWD/mcp" python3 -m pytest mcp/tests/ -q
|
|
91
|
+
|
|
66
92
|
# ── Complexity ratchet (new code only; existing offenders baselined) ─
|
|
67
93
|
complexity:
|
|
68
94
|
name: Complexity ratchet
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyrestoolbox
|
|
3
|
-
Version: 3.8.
|
|
3
|
+
Version: 3.8.3
|
|
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+)
|
|
@@ -45,7 +45,7 @@ Includes functions to perform calculations including;
|
|
|
45
45
|
- Nodal analysis operating point determination
|
|
46
46
|
- Eclipse VFP table generation (VFPPROD and VFPINJ keywords)
|
|
47
47
|
- PVT Calculations for oil
|
|
48
|
-
- PVT calculation for gas, including up to 100% inerts for CO2, H2S, N2 and
|
|
48
|
+
- PVT calculation for gas, including up to 100% inerts for CO2, H2S, N2, H2 and He
|
|
49
49
|
- Gas caloric properties (enthalpy, Cp, Cv, Joule-Thomson coefficient) from the BNS tuned Peng Robinson EOS
|
|
50
50
|
- Gas hydrate formation prediction with thermodynamic inhibitor calculations
|
|
51
51
|
- Return critical parameters for typical components
|
|
@@ -20,7 +20,7 @@ Includes functions to perform calculations including;
|
|
|
20
20
|
- Nodal analysis operating point determination
|
|
21
21
|
- Eclipse VFP table generation (VFPPROD and VFPINJ keywords)
|
|
22
22
|
- PVT Calculations for oil
|
|
23
|
-
- PVT calculation for gas, including up to 100% inerts for CO2, H2S, N2 and
|
|
23
|
+
- PVT calculation for gas, including up to 100% inerts for CO2, H2S, N2, H2 and He
|
|
24
24
|
- Gas caloric properties (enthalpy, Cp, Cv, Joule-Thomson coefficient) from the BNS tuned Peng Robinson EOS
|
|
25
25
|
- Gas hydrate formation prediction with thermodynamic inhibitor calculations
|
|
26
26
|
- Return critical parameters for typical components
|
|
@@ -11,8 +11,8 @@ authors = [{name = "Mark W. Burgoyne", email = "mark.w.burgoyne@gmail.com"}]
|
|
|
11
11
|
keywords = ["mcp", "petroleum", "reservoir", "pyrestoolbox"]
|
|
12
12
|
requires-python = ">=3.10"
|
|
13
13
|
dependencies = [
|
|
14
|
-
"mcp>=1.2,<
|
|
15
|
-
"pyrestoolbox>=3.
|
|
14
|
+
"mcp>=1.2,<3",
|
|
15
|
+
"pyrestoolbox>=3.8.2",
|
|
16
16
|
]
|
|
17
17
|
readme = "README.md"
|
|
18
18
|
|
|
@@ -17,7 +17,12 @@ as MCP resources (docs://gas, docs://oil, ...).
|
|
|
17
17
|
import importlib
|
|
18
18
|
import inspect
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
try: # mcp >= 2 renamed FastMCP to MCPServer
|
|
21
|
+
from mcp.server.mcpserver import MCPServer as _MCPServer
|
|
22
|
+
_MCP_V2 = True
|
|
23
|
+
except ImportError: # mcp 1.x
|
|
24
|
+
from mcp.server.fastmcp import FastMCP as _MCPServer
|
|
25
|
+
_MCP_V2 = False
|
|
21
26
|
|
|
22
27
|
from pyrestoolbox_mcp.serialize import to_jsonable
|
|
23
28
|
|
|
@@ -37,7 +42,7 @@ ALLOWED_MODULES = {
|
|
|
37
42
|
"sensitivity": "Parameter sweeps and tornado analysis",
|
|
38
43
|
}
|
|
39
44
|
|
|
40
|
-
mcp =
|
|
45
|
+
mcp = _MCPServer(
|
|
41
46
|
"pyrestoolbox",
|
|
42
47
|
instructions=(
|
|
43
48
|
"Petroleum/reservoir engineering calculations from the pyrestoolbox "
|
|
@@ -250,7 +255,7 @@ def _construct(dotted, key, spec):
|
|
|
250
255
|
@mcp.tool()
|
|
251
256
|
def recommend_methods(sg: float = 0.65, co2: float = 0, h2s: float = 0,
|
|
252
257
|
n2: float = 0, h2: float = 0, api: float | None = None,
|
|
253
|
-
deviation: float = 0, well_type: str = "gas") -> dict:
|
|
258
|
+
deviation: float = 0, well_type: str = "gas", he: float = 0) -> dict:
|
|
254
259
|
"""Recommend correlation methods for a fluid/well, with rationale.
|
|
255
260
|
|
|
256
261
|
Composition fractions are molar. api: stock tank oil gravity (include to
|
|
@@ -263,7 +268,7 @@ def recommend_methods(sg: float = 0.65, co2: float = 0, h2s: float = 0,
|
|
|
263
268
|
from pyrestoolbox import recommend
|
|
264
269
|
recs = recommend.recommend_methods(sg=sg, co2=co2, h2s=h2s, n2=n2, h2=h2,
|
|
265
270
|
api=api, deviation=deviation,
|
|
266
|
-
well_type=well_type)
|
|
271
|
+
well_type=well_type, he=he)
|
|
267
272
|
return to_jsonable(recs)
|
|
268
273
|
|
|
269
274
|
|
|
@@ -291,12 +296,12 @@ def co2_brine_props(pres: float, temp: float, ppm: float = 0,
|
|
|
291
296
|
def sw_brine_props(pres: float, temp: float, ppm: float = 0,
|
|
292
297
|
y_CO2: float = 0, y_H2S: float = 0, y_N2: float = 0,
|
|
293
298
|
y_H2: float = 0, sg: float = 0.65, cw_sat: bool = False,
|
|
294
|
-
metric: bool = False) -> dict:
|
|
299
|
+
metric: bool = False, y_He: float = 0) -> dict:
|
|
295
300
|
"""Multicomponent gas-saturated brine properties (Soreide-Whitson VLE).
|
|
296
301
|
|
|
297
302
|
pres: pressure (psia, or barsa if metric=True). temp: temperature
|
|
298
303
|
(deg F, or deg C if metric=True). ppm: NaCl-equivalent salinity.
|
|
299
|
-
y_*: molar fractions of CO2/H2S/N2/H2 in the equilibrium gas; the
|
|
304
|
+
y_*: molar fractions of CO2/H2S/N2/H2/He in the equilibrium gas; the
|
|
300
305
|
remainder is hydrocarbon gas of specific gravity sg. Returns aqueous
|
|
301
306
|
composition, brine density/viscosity triplets, Rs, water content and
|
|
302
307
|
compressibilities.
|
|
@@ -304,7 +309,7 @@ def sw_brine_props(pres: float, temp: float, ppm: float = 0,
|
|
|
304
309
|
from pyrestoolbox import brine
|
|
305
310
|
sw = brine.SoreideWhitson(pres=pres, temp=temp, ppm=ppm, y_CO2=y_CO2,
|
|
306
311
|
y_H2S=y_H2S, y_N2=y_N2, y_H2=y_H2, sg=sg,
|
|
307
|
-
cw_sat=cw_sat, metric=metric)
|
|
312
|
+
cw_sat=cw_sat, metric=metric, y_He=y_He)
|
|
308
313
|
keys = ("x", "bDen", "bVis", "bw", "Rs", "Rs_total", "water_content",
|
|
309
314
|
"Cf_usat", "Cf_sat")
|
|
310
315
|
return {k: to_jsonable(getattr(sw, k, None)) for k in keys}
|
|
@@ -382,13 +387,18 @@ def build_parser():
|
|
|
382
387
|
|
|
383
388
|
def main():
|
|
384
389
|
args = build_parser().parse_args()
|
|
385
|
-
if args.transport
|
|
386
|
-
mcp.
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
390
|
+
if args.transport != "streamable-http":
|
|
391
|
+
mcp.run(transport=args.transport)
|
|
392
|
+
return
|
|
393
|
+
# stateless_http: independent request handling; no server-side session
|
|
394
|
+
# affinity needed behind a load balancer.
|
|
395
|
+
http = {"host": args.host, "port": args.port, "stateless_http": True}
|
|
396
|
+
if _MCP_V2:
|
|
397
|
+
mcp.run(transport=args.transport, **http)
|
|
398
|
+
else: # 1.x reads these from settings, not run()
|
|
399
|
+
for key, value in http.items():
|
|
400
|
+
setattr(mcp.settings, key, value)
|
|
401
|
+
mcp.run(transport=args.transport)
|
|
392
402
|
|
|
393
403
|
|
|
394
404
|
if __name__ == "__main__":
|
|
@@ -4,9 +4,9 @@ Run from the repo root:
|
|
|
4
4
|
PYTHONPATH=/home/mark/projects/pyResToolbox:/home/mark/projects/pyResToolbox/mcp \
|
|
5
5
|
python3 -m pytest mcp/tests/ -q
|
|
6
6
|
|
|
7
|
-
Most tests exercise the tool functions directly (
|
|
7
|
+
Most tests exercise the tool functions directly (the SDK's @tool decorator
|
|
8
8
|
returns the undecorated function). test_client_session_* run the full MCP
|
|
9
|
-
protocol over an in-process transport.
|
|
9
|
+
protocol over an in-process transport. The suite runs on mcp 1.x and 2.x.
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
import os
|
|
@@ -186,15 +186,19 @@ def test_fit_and_forecast_exponential():
|
|
|
186
186
|
|
|
187
187
|
# ------------------------------------------------- full MCP protocol session
|
|
188
188
|
|
|
189
|
+
def _in_memory_client():
|
|
190
|
+
"""In-process client session: mcp 2.x Client takes the server directly;
|
|
191
|
+
1.x needs the memory-stream helper and the low-level server."""
|
|
192
|
+
if srv._MCP_V2:
|
|
193
|
+
from mcp.client import Client
|
|
194
|
+
return Client(srv.mcp)
|
|
195
|
+
from mcp.shared.memory import create_connected_server_and_client_session
|
|
196
|
+
return create_connected_server_and_client_session(srv.mcp._mcp_server)
|
|
197
|
+
|
|
198
|
+
|
|
189
199
|
@pytest.mark.anyio
|
|
190
200
|
async def test_client_session_tools_and_resources():
|
|
191
|
-
|
|
192
|
-
from mcp.shared.memory import create_connected_server_and_client_session
|
|
193
|
-
except ImportError:
|
|
194
|
-
pytest.skip('mcp.shared.memory helper not available in this SDK version')
|
|
195
|
-
|
|
196
|
-
async with create_connected_server_and_client_session(
|
|
197
|
-
srv.mcp._mcp_server) as client:
|
|
201
|
+
async with _in_memory_client() as client:
|
|
198
202
|
tools = await client.list_tools()
|
|
199
203
|
names = {t.name for t in tools.tools}
|
|
200
204
|
assert {'list_functions', 'describe', 'call', 'recommend_methods',
|
|
@@ -204,7 +208,8 @@ async def test_client_session_tools_and_resources():
|
|
|
204
208
|
result = await client.call_tool(
|
|
205
209
|
'call', {'name': 'gas.gas_z',
|
|
206
210
|
'arguments': {'p': 2000, 'sg': 0.75, 'degf': 200}})
|
|
207
|
-
|
|
211
|
+
# 2.x result fields are snake_case
|
|
212
|
+
assert not (result.is_error if srv._MCP_V2 else result.isError)
|
|
208
213
|
assert '0.868265' in result.content[0].text
|
|
209
214
|
|
|
210
215
|
resources = await client.list_resources()
|
|
@@ -230,3 +235,29 @@ def test_cli_parser_defaults_and_http():
|
|
|
230
235
|
'--host', '0.0.0.0', '--port', '9000'])
|
|
231
236
|
assert (args.transport, args.host, args.port) == ('streamable-http',
|
|
232
237
|
'0.0.0.0', 9000)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def test_main_passes_http_settings_to_the_sdk(monkeypatch):
|
|
241
|
+
"""host, port and stateless_http reach the SDK: as run() keywords on
|
|
242
|
+
mcp 2.x, through mcp.settings on 1.x."""
|
|
243
|
+
calls = []
|
|
244
|
+
monkeypatch.setattr(srv.mcp, 'run', lambda **kw: calls.append(kw))
|
|
245
|
+
monkeypatch.setattr('sys.argv', ['pyrestoolbox-mcp', '--transport', 'streamable-http',
|
|
246
|
+
'--host', '0.0.0.0', '--port', '9000'])
|
|
247
|
+
srv.main()
|
|
248
|
+
want = {'host': '0.0.0.0', 'port': 9000, 'stateless_http': True}
|
|
249
|
+
if srv._MCP_V2:
|
|
250
|
+
assert calls == [dict(transport='streamable-http', **want)]
|
|
251
|
+
else:
|
|
252
|
+
assert calls == [{'transport': 'streamable-http'}]
|
|
253
|
+
assert {k: getattr(srv.mcp.settings, k) for k in want} == want
|
|
254
|
+
calls.clear()
|
|
255
|
+
monkeypatch.setattr('sys.argv', ['pyrestoolbox-mcp'])
|
|
256
|
+
srv.main()
|
|
257
|
+
assert calls == [{'transport': 'stdio'}]
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def test_sw_brine_props_helium():
|
|
261
|
+
out = srv.sw_brine_props(pres=3000, temp=150, ppm=50000, y_He=1.0)
|
|
262
|
+
assert out['x']['He'] > 0
|
|
263
|
+
assert out['bDen'][0] < out['bDen'][1]
|
|
@@ -4,7 +4,7 @@ build-backend = "maturin"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pyrestoolbox"
|
|
7
|
-
version = "3.8.
|
|
7
|
+
version = "3.8.3"
|
|
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"}]
|
|
@@ -26,7 +26,7 @@ LN10 = np.log(10.0) # 2.302585...
|
|
|
26
26
|
# ====================================================================
|
|
27
27
|
# Boiling points (K) for S&W gases
|
|
28
28
|
TB_K = {
|
|
29
|
-
'H2': 20.3, 'N2': 77.4, 'CO2': 194.7, 'H2S': 212.8, # H2S NBP 212.87 K (NIST)
|
|
29
|
+
'H2': 20.3, 'He': 4.2238, 'N2': 77.4, 'CO2': 194.7, 'H2S': 212.8, # H2S NBP 212.87 K (NIST)
|
|
30
30
|
'CH4': 111.6, 'C2H6': 184.6, 'C3H8': 231.1,
|
|
31
31
|
'iC4H10': 261.4, 'nC4H10': 272.7, 'iC5H12': 301.0,
|
|
32
32
|
'nC5H12': 309.2, 'nC6H14': 341.9, 'nC7H16': 371.6,
|