pyrestoolbox 3.7.7__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.7.7 → pyrestoolbox-3.8.3}/.github/complexity-baseline.json +5 -8
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/.github/workflows/build-wheels.yml +4 -4
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/.github/workflows/tests.yml +30 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/.gitignore +3 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/Cargo.lock +1 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/Cargo.toml +1 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/PKG-INFO +18 -21
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/README.rst +16 -18
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/mcp/Dockerfile +1 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/mcp/README.md +12 -5
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/mcp/pyproject.toml +2 -2
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/mcp/pyrestoolbox_mcp/server.py +111 -17
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/mcp/tests/test_server.py +92 -12
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyproject.toml +2 -3
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/__init__.py +0 -2
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/_accelerator.py +20 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/_lib_salting_library.py +1 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/_lib_vle_engine.py +248 -102
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/brine.py +177 -67
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/pr_vphi.py +12 -4
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/vphi_route.py +2 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/constants/constants.py +3 -2
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/dca/dca.py +36 -22
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/brine.rst +74 -28
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/changelist.rst +85 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/dca.rst +1 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/gas.rst +206 -59
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/layer.rst +2 -2
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/matbal.rst +4 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/nodal.rst +53 -50
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/nodal_examples.ipynb +17 -19
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/nodal_hydrate_demo.ipynb +23 -26
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/oil.rst +7 -7
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/recommend.rst +10 -4
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/sensitivity.rst +1 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/simtools.rst +7 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/gas/_hydrate.py +55 -33
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/gas/gas.py +231 -161
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/layer/layer.py +1 -2
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/matbal/matbal.py +8 -4
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/nodal/nodal.py +309 -155
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_compressibility.py +9 -16
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_constants.py +12 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_correlations.py +39 -20
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_density.py +2 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_harmonize.py +15 -29
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_rate.py +2 -2
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_tables.py +7 -6
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_utils.py +17 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/plyasunov/plyasunov_model.py +13 -8
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/recommend/recommend.py +11 -6
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/shared_fns/shared_fns.py +66 -36
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/_decks.py +16 -13
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/_relperm.py +8 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/_vfp.py +41 -15
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/setup.cfg +0 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/setup.py +0 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/bessel.rs +5 -0
- pyrestoolbox-3.8.3/src/brine_visc/mod.rs +61 -0
- pyrestoolbox-3.8.3/src/brine_visc/salt.rs +149 -0
- pyrestoolbox-3.8.3/src/brine_visc/water.rs +157 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/critical_properties/mod.rs +8 -4
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/gas_viscosity/mod.rs +35 -26
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/lib.rs +5 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/oil/density.rs +25 -17
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/oil/mod.rs +1 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/pseudopressure.rs +14 -14
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/spycher_pruess/solubility.rs +70 -37
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vle/bip.rs +23 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vle/components.rs +9 -4
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vle/flash.rs +178 -9
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vle/k_init.rs +13 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vlp/constants.rs +5 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vlp/holdup_bb.rs +8 -3
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vlp/holdup_gray.rs +2 -2
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vlp/march.rs +48 -43
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vlp/mod.rs +19 -4
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vlp/pvt_helpers.rs +57 -13
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vlp/static_column.rs +2 -1
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/zfactor/mod.rs +83 -53
- pyrestoolbox-3.7.7/mcp/DEPLOYMENT.md +0 -53
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/.github/scripts/check_complexity.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/LICENSE +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/MANIFEST.in +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/ResToolbox/privacy_policy.md +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/build_pure_python.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/clippy.toml +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/mcp/pyrestoolbox_mcp/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/mcp/pyrestoolbox_mcp/serialize.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/_lib_dielectric.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/_lib_maoduan_viscosity.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/_lib_pitzer_params.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/appelo_volumes.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/iapws_viscosity.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/jones_dole_viscosity.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/kestin_nacl_viscosity.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/brine/viscosity_route.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/classes/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/classes/classes.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/constants/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/dca/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/examples.ipynb +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/bot.png +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/bot_PVTO.png +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/bot_img.png +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/dry_gas.png +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/grid_sat_df.png +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/influence.png +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/properties_df.png +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/sgof.png +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/img/swof.png +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/index.rst +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/library.rst +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/docs/plyasunov.rst +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/gas/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/layer/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/library/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/library/component_library.xlsx +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/library/library.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/matbal/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/nodal/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_pvt_class.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/oil/_separator.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/plyasunov/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/plyasunov/iapws_if97.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/plyasunov/water_properties.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/recommend/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/sensitivity/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/sensitivity/sensitivity.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/shared_fns/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/_aquifer.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/_pvt_tables.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/simtools/simtools.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/validate/__init__.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/pyrestoolbox/validate/validate.py +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/dca/hyperbolic.rs +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/dca/mod.rs +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/dca/ransac.rs +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/gwr.rs +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/matbal/mod.rs +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/matbal/objective.rs +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/spycher_pruess/mod.rs +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vle/alpha.rs +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vle/eos.rs +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vle/fugacity.rs +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vle/mod.rs +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vle/rachford_rice.rs +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vlp/friction.rs +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vlp/holdup_wg.rs +0 -0
- {pyrestoolbox-3.7.7 → pyrestoolbox-3.8.3}/src/vlp/ift.rs +0 -0
|
@@ -2,17 +2,15 @@
|
|
|
2
2
|
"pyrestoolbox/brine/_lib_vle_engine.py::SWBinaryVLE.calc_gas_solubility": 16,
|
|
3
3
|
"pyrestoolbox/brine/_lib_vle_engine.py::SWMultiComponentFlash.build_kij_matrix": 18,
|
|
4
4
|
"pyrestoolbox/brine/_lib_vle_engine.py::SWMultiComponentFlash.calc_equilibrium": 24,
|
|
5
|
-
"pyrestoolbox/brine/_lib_vle_engine.py::calc_gas_brine_equilibrium":
|
|
5
|
+
"pyrestoolbox/brine/_lib_vle_engine.py::calc_gas_brine_equilibrium": 23,
|
|
6
6
|
"pyrestoolbox/brine/brine.py::CO2_Brine_Mixture.__init__": 18,
|
|
7
|
-
"pyrestoolbox/brine/brine.py::SoreideWhitson.__init__":
|
|
7
|
+
"pyrestoolbox/brine/brine.py::SoreideWhitson.__init__": 27,
|
|
8
8
|
"pyrestoolbox/brine/brine.py::SoreideWhitson._calc_properties": 19,
|
|
9
|
-
"pyrestoolbox/brine/brine.py::brine_props":
|
|
10
|
-
"pyrestoolbox/dca/dca.py::
|
|
11
|
-
"pyrestoolbox/dca/dca.py::fit_decline_cum": 22,
|
|
9
|
+
"pyrestoolbox/brine/brine.py::brine_props": 17,
|
|
10
|
+
"pyrestoolbox/dca/dca.py::fit_decline_cum": 20,
|
|
12
11
|
"pyrestoolbox/dca/dca.py::forecast": 16,
|
|
13
12
|
"pyrestoolbox/dca/dca.py::hyp2_from_eur": 18,
|
|
14
13
|
"pyrestoolbox/gas/_hydrate.py::gas_hydrate": 26,
|
|
15
|
-
"pyrestoolbox/gas/gas.py::gas_ponz2p": 16,
|
|
16
14
|
"pyrestoolbox/gas/gas.py::gas_tc_pc": 16,
|
|
17
15
|
"pyrestoolbox/gas/gas.py::gas_ug": 16,
|
|
18
16
|
"pyrestoolbox/matbal/matbal.py::gas_matbal": 26,
|
|
@@ -20,11 +18,10 @@
|
|
|
20
18
|
"pyrestoolbox/nodal/nodal.py::Completion.__init__": 21,
|
|
21
19
|
"pyrestoolbox/nodal/nodal.py::_bb_flow_pattern": 18,
|
|
22
20
|
"pyrestoolbox/nodal/nodal.py::_prepare_flow_inputs": 16,
|
|
23
|
-
"pyrestoolbox/nodal/nodal.py::ipr_curve":
|
|
21
|
+
"pyrestoolbox/nodal/nodal.py::ipr_curve": 22,
|
|
24
22
|
"pyrestoolbox/nodal/nodal.py::operating_point": 18,
|
|
25
23
|
"pyrestoolbox/oil/_compressibility.py::oil_co": 16,
|
|
26
24
|
"pyrestoolbox/oil/_correlations.py::oil_pbub": 16,
|
|
27
|
-
"pyrestoolbox/oil/_harmonize.py::oil_harmonize": 16,
|
|
28
25
|
"pyrestoolbox/shared_fns/shared_fns.py::validate_pe_inputs": 43,
|
|
29
26
|
"pyrestoolbox/simtools/_decks.py::_crawl_deck_includes": 16,
|
|
30
27
|
"pyrestoolbox/simtools/_decks.py::ix_extract_problem_cells": 41,
|
|
@@ -45,7 +45,7 @@ jobs:
|
|
|
45
45
|
# Use maturin as the build frontend
|
|
46
46
|
CIBW_BUILD_FRONTEND: "build"
|
|
47
47
|
# Build for CPython 3.8-3.13 (last 5+ years of Python releases)
|
|
48
|
-
CIBW_BUILD: "
|
|
48
|
+
CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-* cp313-*"
|
|
49
49
|
# Skip 32-bit and musl (uncommon for scientific Python)
|
|
50
50
|
CIBW_SKIP: "*-win32 *-manylinux_i686 *-musllinux*"
|
|
51
51
|
# maturin needs Rust in the build container
|
|
@@ -80,9 +80,9 @@ jobs:
|
|
|
80
80
|
# missing OpenBLAS (this broke the v3.6.0 first build attempt - the
|
|
81
81
|
# skip is load-bearing, do not remove it). Linux import + full-suite
|
|
82
82
|
# coverage lives in .github/workflows/tests.yml instead.
|
|
83
|
-
# Also skip macOS (MPFR symbol issue) and
|
|
83
|
+
# Also skip macOS (MPFR symbol issue) and cp39 (dependency
|
|
84
84
|
# ilt-inversion may not have matching wheels on PyPI yet).
|
|
85
|
-
CIBW_TEST_SKIP: "*-manylinux* *-macosx*
|
|
85
|
+
CIBW_TEST_SKIP: "*-manylinux* *-macosx* cp39-*"
|
|
86
86
|
|
|
87
87
|
- uses: actions/upload-artifact@v6
|
|
88
88
|
with:
|
|
@@ -108,7 +108,7 @@ jobs:
|
|
|
108
108
|
uses: pypa/cibuildwheel@v2.23
|
|
109
109
|
env:
|
|
110
110
|
CIBW_BUILD_FRONTEND: "build"
|
|
111
|
-
CIBW_BUILD: "
|
|
111
|
+
CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-* cp313-*"
|
|
112
112
|
CIBW_ARCHS_MACOS: "x86_64"
|
|
113
113
|
CIBW_TEST_COMMAND: >
|
|
114
114
|
python -c "from pyrestoolbox._accelerator import get_status; s = get_status(); print(s); assert s['rust_available'], f'Rust not loaded: {s}'"
|
|
@@ -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
|
|
@@ -80,7 +106,7 @@ jobs:
|
|
|
80
106
|
- name: Check cyclomatic complexity against baseline
|
|
81
107
|
run: python3 .github/scripts/check_complexity.py
|
|
82
108
|
|
|
83
|
-
# ── Rust lint ratchet (clippy clean; any new warning fails)
|
|
109
|
+
# ── Rust lint ratchet (clippy clean; any new warning fails) and unit tests ─
|
|
84
110
|
rust-lint:
|
|
85
111
|
name: Clippy
|
|
86
112
|
runs-on: ubuntu-latest
|
|
@@ -96,3 +122,6 @@ jobs:
|
|
|
96
122
|
|
|
97
123
|
- name: Clippy
|
|
98
124
|
run: cargo clippy --all-targets -- -D warnings
|
|
125
|
+
|
|
126
|
+
- name: Rust unit tests
|
|
127
|
+
run: cargo test --release
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyrestoolbox
|
|
3
|
-
Version: 3.
|
|
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+)
|
|
@@ -12,7 +12,6 @@ Requires-Dist: tabulate
|
|
|
12
12
|
Requires-Dist: ilt-inversion
|
|
13
13
|
Requires-Dist: mpmath
|
|
14
14
|
Requires-Dist: gmpy2
|
|
15
|
-
Requires-Dist: python-flint
|
|
16
15
|
Requires-Dist: openpyxl
|
|
17
16
|
License-File: LICENSE
|
|
18
17
|
Summary: pyResToolbox - A collection of Reservoir Engineering Utilities
|
|
@@ -20,7 +19,7 @@ Keywords: restoolbox,petroleum,reservoir
|
|
|
20
19
|
Home-Page: https://github.com/mwburgoyne/pyResToolbox
|
|
21
20
|
Author-email: "Mark W. Burgoyne" <mark.w.burgoyne@gmail.com>
|
|
22
21
|
License: GPL-3.0-or-later
|
|
23
|
-
Requires-Python: >=3.
|
|
22
|
+
Requires-Python: >=3.9
|
|
24
23
|
Description-Content-Type: text/x-rst; charset=UTF-8
|
|
25
24
|
Project-URL: Homepage, https://github.com/mwburgoyne/pyResToolbox
|
|
26
25
|
|
|
@@ -35,7 +34,7 @@ A collection of Reservoir Engineering Utilities
|
|
|
35
34
|
This set of functions focuses on those that the author uses often while crafting programming solutions.
|
|
36
35
|
These are the scripts that are often copy/pasted from previous work - sometimes slightly modified - resulting in a trail of slightly different versions over the years. Some attempt has been made here to make this implementation flexible enough such that it can be relied on as-is going forward.
|
|
37
36
|
|
|
38
|
-
|
|
37
|
+
Modules: gas, oil, brine, nodal (VLP/IPR, VFP tables), simtools (black-oil, PVTW, rel-perm, aquifer and deck tools), dca (decline curves), matbal (material balance), layer, library, recommend and sensitivity. Every module accepts Eclipse METRIC units with ``metric=True``; the full documentation ships inside the package, and ``pyrestoolbox.docs_dir()`` returns its location for offline reading.
|
|
39
38
|
|
|
40
39
|
Includes functions to perform calculations including;
|
|
41
40
|
|
|
@@ -46,7 +45,7 @@ Includes functions to perform calculations including;
|
|
|
46
45
|
- Nodal analysis operating point determination
|
|
47
46
|
- Eclipse VFP table generation (VFPPROD and VFPINJ keywords)
|
|
48
47
|
- PVT Calculations for oil
|
|
49
|
-
- 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
|
|
50
49
|
- Gas caloric properties (enthalpy, Cp, Cv, Joule-Thomson coefficient) from the BNS tuned Peng Robinson EOS
|
|
51
50
|
- Gas hydrate formation prediction with thermodynamic inhibitor calculations
|
|
52
51
|
- Return critical parameters for typical components
|
|
@@ -289,13 +288,11 @@ Or creating black oil table information for oil
|
|
|
289
288
|
>>>
|
|
290
289
|
>>> plt.tight_layout()
|
|
291
290
|
>>> plt.show()
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
Stock Tank Gas Density: 0.052046870460837856 lb/cuft
|
|
296
|
-
Reservoir Water Density: 61.40223160167964 lb/cuft
|
|
291
|
+
Stock Tank Oil Density: 52.06448672566371 lb/cuft
|
|
292
|
+
Stock Tank Gas Density: 0.05204687045843109 lb/cuft
|
|
293
|
+
Reservoir Water Density: 61.37100825498743 lb/cuft
|
|
297
294
|
Reservoir Water Compressibility: 2.930237693350768e-06 1/psi
|
|
298
|
-
Reservoir Water Viscosity: 0.
|
|
295
|
+
Reservoir Water Viscosity: 0.36386395924173587 cP
|
|
299
296
|
|
|
300
297
|
.. image:: https://raw.githubusercontent.com/mwburgoyne/pyResToolbox/main/pyrestoolbox/docs/img/bot.png
|
|
301
298
|
:alt: Black Oil Properties
|
|
@@ -374,17 +371,17 @@ With ability to generate Live Oil PVTO style table data as well
|
|
|
374
371
|
>>> ..
|
|
375
372
|
>>> plt.show()
|
|
376
373
|
Pb (psia): 4500
|
|
377
|
-
Bob (rb/stb): 1.
|
|
378
|
-
Rsb (mscf/stb): 1.
|
|
379
|
-
Rsb Scaling Required:
|
|
380
|
-
Visob (cP): 0.
|
|
381
|
-
Cob (1/psi):
|
|
382
|
-
|
|
383
|
-
Stock Tank Oil Density: 52.
|
|
384
|
-
Stock Tank Gas Density: 0.
|
|
385
|
-
Reservoir Water Density: 61.
|
|
374
|
+
Bob (rb/stb): 1.5372158966466267
|
|
375
|
+
Rsb (mscf/stb): 1.137900924344287
|
|
376
|
+
Rsb Scaling Required: 1.0362710951888936
|
|
377
|
+
Visob (cP): 0.36663121233374113
|
|
378
|
+
Cob (1/psi): 2.0042955593519084e-05
|
|
379
|
+
|
|
380
|
+
Stock Tank Oil Density: 52.06448672566371 lb/cuft
|
|
381
|
+
Stock Tank Gas Density: 0.05204687045843109 lb/cuft
|
|
382
|
+
Reservoir Water Density: 61.37100825498743 lb/cuft
|
|
386
383
|
Reservoir Water Compressibility: 2.930237693350768e-06 1/psi
|
|
387
|
-
Reservoir Water Viscosity: 0.
|
|
384
|
+
Reservoir Water Viscosity: 0.36386395924173587 cP
|
|
388
385
|
|
|
389
386
|
.. image:: https://raw.githubusercontent.com/mwburgoyne/pyResToolbox/main/pyrestoolbox/docs/img/bot_PVTO.png
|
|
390
387
|
:alt: Live Oil Properties
|
|
@@ -9,7 +9,7 @@ A collection of Reservoir Engineering Utilities
|
|
|
9
9
|
This set of functions focuses on those that the author uses often while crafting programming solutions.
|
|
10
10
|
These are the scripts that are often copy/pasted from previous work - sometimes slightly modified - resulting in a trail of slightly different versions over the years. Some attempt has been made here to make this implementation flexible enough such that it can be relied on as-is going forward.
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Modules: gas, oil, brine, nodal (VLP/IPR, VFP tables), simtools (black-oil, PVTW, rel-perm, aquifer and deck tools), dca (decline curves), matbal (material balance), layer, library, recommend and sensitivity. Every module accepts Eclipse METRIC units with ``metric=True``; the full documentation ships inside the package, and ``pyrestoolbox.docs_dir()`` returns its location for offline reading.
|
|
13
13
|
|
|
14
14
|
Includes functions to perform calculations including;
|
|
15
15
|
|
|
@@ -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
|
|
@@ -263,13 +263,11 @@ Or creating black oil table information for oil
|
|
|
263
263
|
>>>
|
|
264
264
|
>>> plt.tight_layout()
|
|
265
265
|
>>> plt.show()
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
Stock Tank Gas Density: 0.052046870460837856 lb/cuft
|
|
270
|
-
Reservoir Water Density: 61.40223160167964 lb/cuft
|
|
266
|
+
Stock Tank Oil Density: 52.06448672566371 lb/cuft
|
|
267
|
+
Stock Tank Gas Density: 0.05204687045843109 lb/cuft
|
|
268
|
+
Reservoir Water Density: 61.37100825498743 lb/cuft
|
|
271
269
|
Reservoir Water Compressibility: 2.930237693350768e-06 1/psi
|
|
272
|
-
Reservoir Water Viscosity: 0.
|
|
270
|
+
Reservoir Water Viscosity: 0.36386395924173587 cP
|
|
273
271
|
|
|
274
272
|
.. image:: https://raw.githubusercontent.com/mwburgoyne/pyResToolbox/main/pyrestoolbox/docs/img/bot.png
|
|
275
273
|
:alt: Black Oil Properties
|
|
@@ -348,17 +346,17 @@ With ability to generate Live Oil PVTO style table data as well
|
|
|
348
346
|
>>> ..
|
|
349
347
|
>>> plt.show()
|
|
350
348
|
Pb (psia): 4500
|
|
351
|
-
Bob (rb/stb): 1.
|
|
352
|
-
Rsb (mscf/stb): 1.
|
|
353
|
-
Rsb Scaling Required:
|
|
354
|
-
Visob (cP): 0.
|
|
355
|
-
Cob (1/psi):
|
|
356
|
-
|
|
357
|
-
Stock Tank Oil Density: 52.
|
|
358
|
-
Stock Tank Gas Density: 0.
|
|
359
|
-
Reservoir Water Density: 61.
|
|
349
|
+
Bob (rb/stb): 1.5372158966466267
|
|
350
|
+
Rsb (mscf/stb): 1.137900924344287
|
|
351
|
+
Rsb Scaling Required: 1.0362710951888936
|
|
352
|
+
Visob (cP): 0.36663121233374113
|
|
353
|
+
Cob (1/psi): 2.0042955593519084e-05
|
|
354
|
+
|
|
355
|
+
Stock Tank Oil Density: 52.06448672566371 lb/cuft
|
|
356
|
+
Stock Tank Gas Density: 0.05204687045843109 lb/cuft
|
|
357
|
+
Reservoir Water Density: 61.37100825498743 lb/cuft
|
|
360
358
|
Reservoir Water Compressibility: 2.930237693350768e-06 1/psi
|
|
361
|
-
Reservoir Water Viscosity: 0.
|
|
359
|
+
Reservoir Water Viscosity: 0.36386395924173587 cP
|
|
362
360
|
|
|
363
361
|
.. image:: https://raw.githubusercontent.com/mwburgoyne/pyResToolbox/main/pyrestoolbox/docs/img/bot_PVTO.png
|
|
364
362
|
:alt: Live Oil Properties
|
|
@@ -66,8 +66,7 @@ pyrestoolbox-mcp --transport streamable-http --host 0.0.0.0 --port 8000
|
|
|
66
66
|
|
|
67
67
|
It is stateless (no session affinity needed behind a load balancer) and
|
|
68
68
|
serves the MCP endpoint at `/mcp`. A `Dockerfile` is included; put an API
|
|
69
|
-
gateway in front for authentication.
|
|
70
|
-
team one-pager.
|
|
69
|
+
gateway in front for authentication.
|
|
71
70
|
|
|
72
71
|
## Tests
|
|
73
72
|
|
|
@@ -80,8 +79,16 @@ PYTHONPATH=<repo>:<repo>/mcp python3 -m pytest mcp/tests/ -q
|
|
|
80
79
|
- Units default to oilfield (psia, deg F, ft, mD, cP); pass `metric: true`
|
|
81
80
|
where the function supports it. The plyasunov module is SI (K, MPa).
|
|
82
81
|
- The oil module is scalar-only; gas and brine functions accept lists.
|
|
83
|
-
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
- Gas rates are Mscf/d everywhere (sm3/d with `metric: true`).
|
|
83
|
+
- Functions that take objects are callable through `call` with those objects
|
|
84
|
+
written as JSON objects of their constructor keywords: `completion`
|
|
85
|
+
(`nodal.Completion`, with an optional `segments` list of `WellSegment`
|
|
86
|
+
objects), `reservoir`, `gas_pvt`, `oil_pvt`, `result` (the object a
|
|
87
|
+
`fit_decline` or `fit_ratio` call returned), `ratios`, and `func` as a
|
|
88
|
+
`'module.function'` name for `sensitivity.sweep`/`tornado`. For example
|
|
89
|
+
`call('nodal.fbhp', {"thp": 500, "well_type": "gas", "qg_mscfd": 5000,
|
|
90
|
+
"completion": {"tid": 2.441, "length": 10000, "tht": 100, "bht": 200}})`.
|
|
91
|
+
Classes themselves are not called directly; the one-shot wrapper tools
|
|
92
|
+
cover the common stateful workflows.
|
|
86
93
|
- File-writing simtools functions keep their `export=False` defaults, so
|
|
87
94
|
calls return table text rather than touching disk.
|
|
@@ -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 "
|
|
@@ -53,6 +58,10 @@ mcp = FastMCP(
|
|
|
53
58
|
"Fahrenheit value to `degf` with metric=True converts it twice and "
|
|
54
59
|
"returns a wrong answer silently. Standard volumes are always at "
|
|
55
60
|
"60 deg F and 14.696 psia, so metric sm3 is on that basis. "
|
|
61
|
+
"Gas rates are Mscf/d everywhere (sm3/d with metric=True). "
|
|
62
|
+
"Functions that take objects (Completion, Reservoir, GasPVT, OilPVT, "
|
|
63
|
+
"decline results) accept them through call() as JSON objects of their "
|
|
64
|
+
"constructor keywords; see the call tool description. "
|
|
56
65
|
"Full module documentation is available as docs:// resources."
|
|
57
66
|
),
|
|
58
67
|
)
|
|
@@ -147,8 +156,23 @@ def call(name: str, arguments: dict = {}) -> dict:
|
|
|
147
156
|
Correlation methods are strings (e.g. "zmethod": "DAK"); an invalid
|
|
148
157
|
method string returns an error listing the valid options. Gas and brine
|
|
149
158
|
functions accept lists for pressure-like inputs; oil functions are
|
|
150
|
-
scalar-only.
|
|
151
|
-
|
|
159
|
+
scalar-only. Gas rates are Mscf/d (sm3/d with metric=True).
|
|
160
|
+
|
|
161
|
+
Object arguments are passed as JSON objects of their constructor keywords
|
|
162
|
+
and built here (describe the class for its keywords):
|
|
163
|
+
completion -> nodal.Completion (a "segments" list of objects -> WellSegment)
|
|
164
|
+
reservoir -> nodal.Reservoir
|
|
165
|
+
gas_pvt -> gas.GasPVT
|
|
166
|
+
oil_pvt -> oil.OilPVT
|
|
167
|
+
result -> dca.DeclineResult (forecast) or dca.RatioResult (ratio_forecast);
|
|
168
|
+
pass the object a fit_decline / fit_ratio call returned
|
|
169
|
+
ratios -> {name: RatioResult object}
|
|
170
|
+
func -> a 'module.function' name (sensitivity.sweep / tornado); objects
|
|
171
|
+
inside base_kwargs are built by the same rules
|
|
172
|
+
e.g. call('nodal.fbhp', {"thp": 500, "well_type": "gas", "qg_mscfd": 5000,
|
|
173
|
+
"completion": {"tid": 2.441, "length": 10000, "tht": 100, "bht": 200}}).
|
|
174
|
+
Classes themselves cannot be called here; one-shot wrappers
|
|
175
|
+
(co2_brine_props, sw_brine_props, fit_and_forecast) cover the common cases.
|
|
152
176
|
"""
|
|
153
177
|
_, obj = _resolve(name)
|
|
154
178
|
if inspect.isclass(obj):
|
|
@@ -159,14 +183,79 @@ def call(name: str, arguments: dict = {}) -> dict:
|
|
|
159
183
|
)
|
|
160
184
|
if not callable(obj):
|
|
161
185
|
raise ValueError(f"{name} is not callable (it is {type(obj).__name__})")
|
|
162
|
-
result = obj(**arguments)
|
|
186
|
+
result = obj(**_build_objects(obj, arguments))
|
|
163
187
|
return {"result": to_jsonable(result)}
|
|
164
188
|
|
|
165
189
|
|
|
190
|
+
def _library_class(dotted: str):
|
|
191
|
+
module, cls = dotted.split(".")
|
|
192
|
+
return getattr(_get_module(module), cls)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
# Keyword -> library class built from a JSON object. The library names these
|
|
196
|
+
# parameters consistently, so one table covers every function that takes them.
|
|
197
|
+
_OBJECT_PARAMS = {
|
|
198
|
+
"completion": "nodal.Completion",
|
|
199
|
+
"reservoir": "nodal.Reservoir",
|
|
200
|
+
"gas_pvt": "gas.GasPVT",
|
|
201
|
+
"oil_pvt": "oil.OilPVT",
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def _build_objects(fn, arguments: dict) -> dict:
|
|
206
|
+
"""Turn JSON objects in `arguments` into the library objects fn expects.
|
|
207
|
+
|
|
208
|
+
Raises ValueError naming the parameter and class when construction fails,
|
|
209
|
+
so an agent learns which keywords to fix instead of an AttributeError from
|
|
210
|
+
deep inside the library.
|
|
211
|
+
"""
|
|
212
|
+
try:
|
|
213
|
+
annotations = {k: str(v.annotation) for k, v in inspect.signature(fn).parameters.items()}
|
|
214
|
+
except (TypeError, ValueError):
|
|
215
|
+
annotations = {}
|
|
216
|
+
out = {}
|
|
217
|
+
for key, value in arguments.items():
|
|
218
|
+
out[key] = _build_one(key, value, annotations.get(key, ""))
|
|
219
|
+
return out
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _build_one(key, value, annotation):
|
|
223
|
+
if key == "func" and isinstance(value, str):
|
|
224
|
+
_, fn = _resolve(value)
|
|
225
|
+
return fn
|
|
226
|
+
if key == "base_kwargs" and isinstance(value, dict):
|
|
227
|
+
return {k: _build_one(k, v, "") for k, v in value.items()}
|
|
228
|
+
if not isinstance(value, dict):
|
|
229
|
+
return value
|
|
230
|
+
if key == "ratios":
|
|
231
|
+
return {name: _construct("dca.RatioResult", key, spec) for name, spec in value.items()}
|
|
232
|
+
if key == "result":
|
|
233
|
+
dotted = "dca.RatioResult" if "RatioResult" in annotation else "dca.DeclineResult"
|
|
234
|
+
return _construct(dotted, key, value)
|
|
235
|
+
if key in _OBJECT_PARAMS:
|
|
236
|
+
if key == "completion" and isinstance(value.get("segments"), list):
|
|
237
|
+
value = dict(value, segments=[
|
|
238
|
+
_construct("nodal.WellSegment", "completion.segments", seg)
|
|
239
|
+
if isinstance(seg, dict) else seg for seg in value["segments"]])
|
|
240
|
+
return _construct(_OBJECT_PARAMS[key], key, value)
|
|
241
|
+
return value
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _construct(dotted, key, spec):
|
|
245
|
+
cls = _library_class(dotted)
|
|
246
|
+
try:
|
|
247
|
+
return cls(**spec)
|
|
248
|
+
except TypeError as exc:
|
|
249
|
+
raise ValueError(
|
|
250
|
+
f"Could not build {dotted} for '{key}' from {sorted(spec)}: {exc}. "
|
|
251
|
+
f"Use describe({dotted!r}) for its keywords."
|
|
252
|
+
) from exc
|
|
253
|
+
|
|
254
|
+
|
|
166
255
|
@mcp.tool()
|
|
167
256
|
def recommend_methods(sg: float = 0.65, co2: float = 0, h2s: float = 0,
|
|
168
257
|
n2: float = 0, h2: float = 0, api: float | None = None,
|
|
169
|
-
deviation: float = 0, well_type: str = "gas") -> dict:
|
|
258
|
+
deviation: float = 0, well_type: str = "gas", he: float = 0) -> dict:
|
|
170
259
|
"""Recommend correlation methods for a fluid/well, with rationale.
|
|
171
260
|
|
|
172
261
|
Composition fractions are molar. api: stock tank oil gravity (include to
|
|
@@ -179,7 +268,7 @@ def recommend_methods(sg: float = 0.65, co2: float = 0, h2s: float = 0,
|
|
|
179
268
|
from pyrestoolbox import recommend
|
|
180
269
|
recs = recommend.recommend_methods(sg=sg, co2=co2, h2s=h2s, n2=n2, h2=h2,
|
|
181
270
|
api=api, deviation=deviation,
|
|
182
|
-
well_type=well_type)
|
|
271
|
+
well_type=well_type, he=he)
|
|
183
272
|
return to_jsonable(recs)
|
|
184
273
|
|
|
185
274
|
|
|
@@ -207,12 +296,12 @@ def co2_brine_props(pres: float, temp: float, ppm: float = 0,
|
|
|
207
296
|
def sw_brine_props(pres: float, temp: float, ppm: float = 0,
|
|
208
297
|
y_CO2: float = 0, y_H2S: float = 0, y_N2: float = 0,
|
|
209
298
|
y_H2: float = 0, sg: float = 0.65, cw_sat: bool = False,
|
|
210
|
-
metric: bool = False) -> dict:
|
|
299
|
+
metric: bool = False, y_He: float = 0) -> dict:
|
|
211
300
|
"""Multicomponent gas-saturated brine properties (Soreide-Whitson VLE).
|
|
212
301
|
|
|
213
302
|
pres: pressure (psia, or barsa if metric=True). temp: temperature
|
|
214
303
|
(deg F, or deg C if metric=True). ppm: NaCl-equivalent salinity.
|
|
215
|
-
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
|
|
216
305
|
remainder is hydrocarbon gas of specific gravity sg. Returns aqueous
|
|
217
306
|
composition, brine density/viscosity triplets, Rs, water content and
|
|
218
307
|
compressibilities.
|
|
@@ -220,7 +309,7 @@ def sw_brine_props(pres: float, temp: float, ppm: float = 0,
|
|
|
220
309
|
from pyrestoolbox import brine
|
|
221
310
|
sw = brine.SoreideWhitson(pres=pres, temp=temp, ppm=ppm, y_CO2=y_CO2,
|
|
222
311
|
y_H2S=y_H2S, y_N2=y_N2, y_H2=y_H2, sg=sg,
|
|
223
|
-
cw_sat=cw_sat, metric=metric)
|
|
312
|
+
cw_sat=cw_sat, metric=metric, y_He=y_He)
|
|
224
313
|
keys = ("x", "bDen", "bVis", "bw", "Rs", "Rs_total", "water_content",
|
|
225
314
|
"Cf_usat", "Cf_sat")
|
|
226
315
|
return {k: to_jsonable(getattr(sw, k, None)) for k in keys}
|
|
@@ -298,13 +387,18 @@ def build_parser():
|
|
|
298
387
|
|
|
299
388
|
def main():
|
|
300
389
|
args = build_parser().parse_args()
|
|
301
|
-
if args.transport
|
|
302
|
-
mcp.
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
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)
|
|
308
402
|
|
|
309
403
|
|
|
310
404
|
if __name__ == "__main__":
|