propax 0.1.0__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.
- propax-0.1.0/LICENSE +21 -0
- propax-0.1.0/PKG-INFO +247 -0
- propax-0.1.0/README.md +208 -0
- propax-0.1.0/pyproject.toml +94 -0
- propax-0.1.0/setup.cfg +4 -0
- propax-0.1.0/src/propax/__init__.py +12 -0
- propax-0.1.0/src/propax/build_tables.py +244 -0
- propax-0.1.0/src/propax/core/__init__.py +3 -0
- propax-0.1.0/src/propax/core/_state.py +122 -0
- propax-0.1.0/src/propax/core/config.py +205 -0
- propax-0.1.0/src/propax/core/domain.py +38 -0
- propax-0.1.0/src/propax/core/flash/__init__.py +52 -0
- propax-0.1.0/src/propax/core/flash/dispatch.py +176 -0
- propax-0.1.0/src/propax/core/flash/results.py +93 -0
- propax-0.1.0/src/propax/core/flash/single_phase.py +548 -0
- propax-0.1.0/src/propax/core/flash/tables.py +52 -0
- propax-0.1.0/src/propax/core/flash/two_phase.py +311 -0
- propax-0.1.0/src/propax/core/interface.py +646 -0
- propax-0.1.0/src/propax/core/interp.py +313 -0
- propax-0.1.0/src/propax/core/saturation.py +179 -0
- propax-0.1.0/src/propax/core/tolerances.py +170 -0
- propax-0.1.0/src/propax/fluids/__init__.py +0 -0
- propax-0.1.0/src/propax/fluids/_registry.py +84 -0
- propax-0.1.0/src/propax/fluids/data/1-butene.json +961 -0
- propax-0.1.0/src/propax/fluids/data/acetone.json +1356 -0
- propax-0.1.0/src/propax/fluids/data/argon.json +1722 -0
- propax-0.1.0/src/propax/fluids/data/benzene.json +866 -0
- propax-0.1.0/src/propax/fluids/data/carbonmonoxide.json +956 -0
- propax-0.1.0/src/propax/fluids/data/carbonylsulfide.json +703 -0
- propax-0.1.0/src/propax/fluids/data/cis-2-butene.json +886 -0
- propax-0.1.0/src/propax/fluids/data/cyclohexane.json +633 -0
- propax-0.1.0/src/propax/fluids/data/cyclopentane.json +598 -0
- propax-0.1.0/src/propax/fluids/data/cyclopropane.json +593 -0
- propax-0.1.0/src/propax/fluids/data/d4.json +737 -0
- propax-0.1.0/src/propax/fluids/data/d5.json +1948 -0
- propax-0.1.0/src/propax/fluids/data/deuterium.json +440 -0
- propax-0.1.0/src/propax/fluids/data/dichloroethane.json +1758 -0
- propax-0.1.0/src/propax/fluids/data/diethylether.json +590 -0
- propax-0.1.0/src/propax/fluids/data/dimethylcarbonate.json +1776 -0
- propax-0.1.0/src/propax/fluids/data/dimethylether.json +836 -0
- propax-0.1.0/src/propax/fluids/data/ethane.json +1734 -0
- propax-0.1.0/src/propax/fluids/data/ethanol.json +1246 -0
- propax-0.1.0/src/propax/fluids/data/ethylbenzene.json +918 -0
- propax-0.1.0/src/propax/fluids/data/ethylene.json +1471 -0
- propax-0.1.0/src/propax/fluids/data/ethyleneoxide.json +743 -0
- propax-0.1.0/src/propax/fluids/data/heavywater.json +1889 -0
- propax-0.1.0/src/propax/fluids/data/helium.json +912 -0
- propax-0.1.0/src/propax/fluids/data/hfe143m.json +858 -0
- propax-0.1.0/src/propax/fluids/data/hydrogen.json +592 -0
- propax-0.1.0/src/propax/fluids/data/hydrogenchloride.json +793 -0
- propax-0.1.0/src/propax/fluids/data/hydrogensulfide.json +560 -0
- propax-0.1.0/src/propax/fluids/data/isobutane.json +1372 -0
- propax-0.1.0/src/propax/fluids/data/isobutene.json +886 -0
- propax-0.1.0/src/propax/fluids/data/isohexane.json +762 -0
- propax-0.1.0/src/propax/fluids/data/isopentane.json +1110 -0
- propax-0.1.0/src/propax/fluids/data/krypton.json +650 -0
- propax-0.1.0/src/propax/fluids/data/m-xylene.json +1687 -0
- propax-0.1.0/src/propax/fluids/data/md2m.json +795 -0
- propax-0.1.0/src/propax/fluids/data/md3m.json +795 -0
- propax-0.1.0/src/propax/fluids/data/md4m.json +737 -0
- propax-0.1.0/src/propax/fluids/data/mdm.json +596 -0
- propax-0.1.0/src/propax/fluids/data/methane.json +1709 -0
- propax-0.1.0/src/propax/fluids/data/methyllinoleate.json +802 -0
- propax-0.1.0/src/propax/fluids/data/methyllinolenate.json +702 -0
- propax-0.1.0/src/propax/fluids/data/methyloleate.json +702 -0
- propax-0.1.0/src/propax/fluids/data/methylpalmitate.json +701 -0
- propax-0.1.0/src/propax/fluids/data/methylstearate.json +701 -0
- propax-0.1.0/src/propax/fluids/data/mm.json +818 -0
- propax-0.1.0/src/propax/fluids/data/n-butane.json +1221 -0
- propax-0.1.0/src/propax/fluids/data/n-decane.json +735 -0
- propax-0.1.0/src/propax/fluids/data/n-dodecane.json +1940 -0
- propax-0.1.0/src/propax/fluids/data/n-hexane.json +797 -0
- propax-0.1.0/src/propax/fluids/data/n-nonane.json +865 -0
- propax-0.1.0/src/propax/fluids/data/n-octane.json +866 -0
- propax-0.1.0/src/propax/fluids/data/n-pentane.json +799 -0
- propax-0.1.0/src/propax/fluids/data/n-perfluorobutane.json +732 -0
- propax-0.1.0/src/propax/fluids/data/n-perfluorohexane.json +592 -0
- propax-0.1.0/src/propax/fluids/data/n-perfluoropentane.json +592 -0
- propax-0.1.0/src/propax/fluids/data/n-propane.json +1462 -0
- propax-0.1.0/src/propax/fluids/data/neon.json +597 -0
- propax-0.1.0/src/propax/fluids/data/neopentane.json +782 -0
- propax-0.1.0/src/propax/fluids/data/nitrogen.json +1430 -0
- propax-0.1.0/src/propax/fluids/data/nitrousoxide.json +730 -0
- propax-0.1.0/src/propax/fluids/data/novec649.json +1483 -0
- propax-0.1.0/src/propax/fluids/data/o-xylene.json +1761 -0
- propax-0.1.0/src/propax/fluids/data/orthodeuterium.json +440 -0
- propax-0.1.0/src/propax/fluids/data/orthohydrogen.json +590 -0
- propax-0.1.0/src/propax/fluids/data/oxygen.json +1422 -0
- propax-0.1.0/src/propax/fluids/data/p-xylene.json +1903 -0
- propax-0.1.0/src/propax/fluids/data/paradeuterium.json +438 -0
- propax-0.1.0/src/propax/fluids/data/parahydrogen.json +596 -0
- propax-0.1.0/src/propax/fluids/data/propylene.json +1427 -0
- propax-0.1.0/src/propax/fluids/data/propyleneglycol.json +1212 -0
- propax-0.1.0/src/propax/fluids/data/propyne.json +600 -0
- propax-0.1.0/src/propax/fluids/data/r11.json +1024 -0
- propax-0.1.0/src/propax/fluids/data/r1123.json +723 -0
- propax-0.1.0/src/propax/fluids/data/r113.json +1133 -0
- propax-0.1.0/src/propax/fluids/data/r1130(e).json +795 -0
- propax-0.1.0/src/propax/fluids/data/r1132(e).json +1308 -0
- propax-0.1.0/src/propax/fluids/data/r114.json +402 -0
- propax-0.1.0/src/propax/fluids/data/r115.json +677 -0
- propax-0.1.0/src/propax/fluids/data/r116.json +959 -0
- propax-0.1.0/src/propax/fluids/data/r12.json +877 -0
- propax-0.1.0/src/propax/fluids/data/r1224ydz.json +1993 -0
- propax-0.1.0/src/propax/fluids/data/r123.json +1053 -0
- propax-0.1.0/src/propax/fluids/data/r1233zd(e).json +1566 -0
- propax-0.1.0/src/propax/fluids/data/r1234yf.json +933 -0
- propax-0.1.0/src/propax/fluids/data/r1234ze(e).json +1836 -0
- propax-0.1.0/src/propax/fluids/data/r1234ze(z).json +1397 -0
- propax-0.1.0/src/propax/fluids/data/r124.json +914 -0
- propax-0.1.0/src/propax/fluids/data/r1243zf.json +1690 -0
- propax-0.1.0/src/propax/fluids/data/r13.json +401 -0
- propax-0.1.0/src/propax/fluids/data/r1336mzz(e).json +877 -0
- propax-0.1.0/src/propax/fluids/data/r1336mzz(z).json +1637 -0
- propax-0.1.0/src/propax/fluids/data/r134a.json +868 -0
- propax-0.1.0/src/propax/fluids/data/r13i1.json +832 -0
- propax-0.1.0/src/propax/fluids/data/r14.json +742 -0
- propax-0.1.0/src/propax/fluids/data/r141b.json +839 -0
- propax-0.1.0/src/propax/fluids/data/r142b.json +962 -0
- propax-0.1.0/src/propax/fluids/data/r143a.json +858 -0
- propax-0.1.0/src/propax/fluids/data/r152a.json +855 -0
- propax-0.1.0/src/propax/fluids/data/r161.json +1759 -0
- propax-0.1.0/src/propax/fluids/data/r21.json +600 -0
- propax-0.1.0/src/propax/fluids/data/r218.json +704 -0
- propax-0.1.0/src/propax/fluids/data/r22.json +1887 -0
- propax-0.1.0/src/propax/fluids/data/r227ea.json +1294 -0
- propax-0.1.0/src/propax/fluids/data/r23.json +781 -0
- propax-0.1.0/src/propax/fluids/data/r236ea.json +1549 -0
- propax-0.1.0/src/propax/fluids/data/r236fa.json +1193 -0
- propax-0.1.0/src/propax/fluids/data/r245ca.json +731 -0
- propax-0.1.0/src/propax/fluids/data/r245fa.json +1682 -0
- propax-0.1.0/src/propax/fluids/data/r32.json +1609 -0
- propax-0.1.0/src/propax/fluids/data/r365mfc.json +1471 -0
- propax-0.1.0/src/propax/fluids/data/r40.json +579 -0
- propax-0.1.0/src/propax/fluids/data/r404a.json +1076 -0
- propax-0.1.0/src/propax/fluids/data/r407c.json +1628 -0
- propax-0.1.0/src/propax/fluids/data/r41.json +703 -0
- propax-0.1.0/src/propax/fluids/data/r410a.json +793 -0
- propax-0.1.0/src/propax/fluids/data/r507a.json +990 -0
- propax-0.1.0/src/propax/fluids/data/rc318.json +598 -0
- propax-0.1.0/src/propax/fluids/data/ses36.json +585 -0
- propax-0.1.0/src/propax/fluids/data/sulfurdioxide.json +602 -0
- propax-0.1.0/src/propax/fluids/data/sulfurhexafluoride.json +1023 -0
- propax-0.1.0/src/propax/fluids/data/tetrahydrofuran.json +740 -0
- propax-0.1.0/src/propax/fluids/data/toluene.json +842 -0
- propax-0.1.0/src/propax/fluids/data/trans-2-butene.json +840 -0
- propax-0.1.0/src/propax/fluids/data/vinylchloride.json +1762 -0
- propax-0.1.0/src/propax/fluids/data/xenon.json +668 -0
- propax-0.1.0/src/propax/fluids/generic/__init__.py +17 -0
- propax-0.1.0/src/propax/fluids/generic/conductivity/__init__.py +2 -0
- propax-0.1.0/src/propax/fluids/generic/conductivity/rational_polynomial.py +154 -0
- propax-0.1.0/src/propax/fluids/generic/conductivity/schema_cond.py +185 -0
- propax-0.1.0/src/propax/fluids/generic/conductivity/slots.py +266 -0
- propax-0.1.0/src/propax/fluids/generic/eos/__init__.py +1 -0
- propax-0.1.0/src/propax/fluids/generic/eos/helmholtz.py +345 -0
- propax-0.1.0/src/propax/fluids/generic/eos/mixture_terms.py +4 -0
- propax-0.1.0/src/propax/fluids/generic/eos/pure_terms.py +424 -0
- propax-0.1.0/src/propax/fluids/generic/eos/schema_eos.py +167 -0
- propax-0.1.0/src/propax/fluids/generic/transport_registry.py +138 -0
- propax-0.1.0/src/propax/fluids/generic/viscosity/__init__.py +2 -0
- propax-0.1.0/src/propax/fluids/generic/viscosity/rainwater_friend.py +95 -0
- propax-0.1.0/src/propax/fluids/generic/viscosity/schema_visc.py +198 -0
- propax-0.1.0/src/propax/fluids/generic/viscosity/slots.py +249 -0
- propax-0.1.0/src/propax/fluids/schema.py +132 -0
- propax-0.1.0/src/propax/make_fluid.py +110 -0
- propax-0.1.0/src/propax/py.typed +0 -0
- propax-0.1.0/src/propax/utils/__init__.py +0 -0
- propax-0.1.0/src/propax/utils/build_utils/__init__.py +32 -0
- propax-0.1.0/src/propax/utils/build_utils/assemble.py +608 -0
- propax-0.1.0/src/propax/utils/build_utils/dome.py +166 -0
- propax-0.1.0/src/propax/utils/build_utils/helpers.py +128 -0
- propax-0.1.0/src/propax/utils/build_utils/single_phase.py +65 -0
- propax-0.1.0/src/propax/utils/exact/__init__.py +31 -0
- propax-0.1.0/src/propax/utils/exact/constants.py +69 -0
- propax-0.1.0/src/propax/utils/exact/critical.py +261 -0
- propax-0.1.0/src/propax/utils/exact/curve.py +116 -0
- propax-0.1.0/src/propax/utils/exact/fit.py +214 -0
- propax-0.1.0/src/propax/utils/exact/precision.py +57 -0
- propax-0.1.0/src/propax/utils/exact/superancillary.py +297 -0
- propax-0.1.0/src/propax/utils/make_utils/__init__.py +3 -0
- propax-0.1.0/src/propax/utils/make_utils/build.py +321 -0
- propax-0.1.0/src/propax/utils/make_utils/conductivity.py +138 -0
- propax-0.1.0/src/propax/utils/make_utils/coverage.py +241 -0
- propax-0.1.0/src/propax/utils/make_utils/eos.py +290 -0
- propax-0.1.0/src/propax/utils/make_utils/source.py +99 -0
- propax-0.1.0/src/propax/utils/make_utils/viscosity.py +120 -0
- propax-0.1.0/src/propax/utils/numerics.py +26 -0
- propax-0.1.0/src/propax/utils/solvers.py +165 -0
- propax-0.1.0/src/propax/utils/types.py +7 -0
- propax-0.1.0/src/propax.egg-info/PKG-INFO +247 -0
- propax-0.1.0/src/propax.egg-info/SOURCES.txt +201 -0
- propax-0.1.0/src/propax.egg-info/dependency_links.txt +1 -0
- propax-0.1.0/src/propax.egg-info/requires.txt +23 -0
- propax-0.1.0/src/propax.egg-info/top_level.txt +1 -0
- propax-0.1.0/tests/test_contracts.py +46 -0
- propax-0.1.0/tests/test_custom_transport.py +184 -0
- propax-0.1.0/tests/test_fluid_files.py +65 -0
- propax-0.1.0/tests/test_residuals.py +102 -0
- propax-0.1.0/tests/test_roundtrip.py +84 -0
- propax-0.1.0/tests/test_saturation.py +82 -0
- propax-0.1.0/tests/test_supported_pairs.py +77 -0
- propax-0.1.0/tests/test_tolerances.py +22 -0
- propax-0.1.0/tests/test_transcription.py +106 -0
propax-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Emmanuel Benichou
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
propax-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: propax
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Differentiable CoolProp-style fluid properties in pure JAX, driven by fluid definition files.
|
|
5
|
+
Author: Emmanuel Benichou
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: repository, https://github.com/cziffras/propax
|
|
8
|
+
Keywords: thermodynamics,equation-of-state,jax,fluid-properties,coolprop
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
16
|
+
Requires-Python: >=3.12
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: equinox>=0.13.2
|
|
20
|
+
Requires-Dist: jax<0.9,>=0.8.1
|
|
21
|
+
Requires-Dist: jaxtyping>=0.2.36
|
|
22
|
+
Requires-Dist: lineax>=0.0.7
|
|
23
|
+
Requires-Dist: numpy>=2.0
|
|
24
|
+
Requires-Dist: optimistix>=0.0.11
|
|
25
|
+
Requires-Dist: pydantic>=2.12.4
|
|
26
|
+
Provides-Extra: build
|
|
27
|
+
Requires-Dist: scipy>=1.11; extra == "build"
|
|
28
|
+
Provides-Extra: coolprop
|
|
29
|
+
Requires-Dist: coolprop>=6.6.0; extra == "coolprop"
|
|
30
|
+
Requires-Dist: mpmath>=1.3; extra == "coolprop"
|
|
31
|
+
Provides-Extra: notebooks
|
|
32
|
+
Requires-Dist: matplotlib>=3.10; extra == "notebooks"
|
|
33
|
+
Requires-Dist: plotly>=6.5; extra == "notebooks"
|
|
34
|
+
Requires-Dist: ipykernel>=7.1; extra == "notebooks"
|
|
35
|
+
Provides-Extra: test
|
|
36
|
+
Requires-Dist: pytest; extra == "test"
|
|
37
|
+
Requires-Dist: coolprop>=6.6.0; extra == "test"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# **PROPAX**
|
|
41
|
+
|
|
42
|
+
[](https://github.com/cziffras/propax/actions/workflows/ci.yml)
|
|
43
|
+
[](https://github.com/cziffras/propax/blob/main/LICENSE)
|
|
44
|
+
[](https://github.com/cziffras/propax/blob/main/pyproject.toml)
|
|
45
|
+
|
|
46
|
+
<p align="center">
|
|
47
|
+
<img src="https://raw.githubusercontent.com/cziffras/propax/main/imgs/cp_propax.png" alt="illustration" width="400">
|
|
48
|
+
</p>
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
Many thermodynamics simulations could make use of an easy-to-use CoolProp-like interface that
|
|
53
|
+
is fully differentiable and compatible with the greater JAX ecosystem. It is exactly what `propax` is : written in pure JAX, fully differentiable, jittable and vmappable thermodynamics without any `pure_callback` running on CPU/GPU in both 32 and 64 bits precision !
|
|
54
|
+
|
|
55
|
+
Additionally `propax` aims at being transparent and theoretically solid, EOS parameters are taken from litterature for reproducibility and comparability but
|
|
56
|
+
most physical constants (saturation properties, critical point...) are recomputed
|
|
57
|
+
offline so that all values do perfectly match the EOS structure and nothing remains hidden.
|
|
58
|
+
|
|
59
|
+
## To what extent does this work rely on CoolProp ?
|
|
60
|
+
|
|
61
|
+
Other similar projects (see [jaxprop](https://github.com/turbo-sim/jaxprop)) are essentially wrapping CoolProp itself and expose it via `jax.pure_callback()`. While making CoolProp calls possible in JAX-written code, this causes two distinct issues :
|
|
62
|
+
- CoolProp calls are still performed on CPU which blocks any different hardware usage (GPU, TPU...)
|
|
63
|
+
- Calls made on CPU causes different performance costs : numpy array conversion, latency due to data movements between CPU Host memory and GPU memory and suboptimality of XLA optimization of your code among others...
|
|
64
|
+
|
|
65
|
+
This is the reason why I made the choice to write `propax` as an alternative to wrappers without sacrificing the precision reached by iterative solvers (one could have implemented a simple interpolation of CoolProp tables in JAX, however the cost in memory is heavy and precision is dubious mostly for what it comes to derivatives computed via autodiff which are smoothed by any interpolation while they can sometimes be extremely small already).
|
|
66
|
+
|
|
67
|
+
In `propax`, the EOS coefficients are transcribed index by index from the
|
|
68
|
+
published correlation, and everything else is solved from them :
|
|
69
|
+
|
|
70
|
+
- The critical point : is not the published value, it is the point
|
|
71
|
+
where the correlation itself has `dP/drho = d2P/drho2 = 0`.
|
|
72
|
+
- The saturation curve : is a Chebyshev superancillary, fitted offline in
|
|
73
|
+
extended precision (mpmath) against equal pressure and equal fugacity, not
|
|
74
|
+
against CoolProp.
|
|
75
|
+
|
|
76
|
+
The offline machinery lives in `utils/exact/` and is documented in
|
|
77
|
+
`docs/superancillary.md`.
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
## Making a fluid
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
pip install "propax[coolprop]" # CoolProp + mpmath, dev-time only
|
|
84
|
+
python -m propax.make_fluid Argon # transcribe the EOS, then fit its saturation curve
|
|
85
|
+
python -m propax.utils.make_utils.coverage # what is convertible, and what blocks the rest
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The converter copies the Helmholtz coefficients (machine-precision
|
|
89
|
+
EOS), checks the result back against CoolProp to 1e-9, and checks each transport
|
|
90
|
+
block to 1e-6. Please note that a correlation it cannot reproduce from published coefficients
|
|
91
|
+
is omitted, never approximated. In that case, the option `--transport-scaffold`
|
|
92
|
+
keeps the property instead of dropping it leaving each slot hardcoded in `CoolProp` with a placeholder and its reference in the litterature so you can implement it.
|
|
93
|
+
|
|
94
|
+
126 of CoolProp's 136 pure fluids convert today, and the package ships the ones that do, so
|
|
95
|
+
`pip install propax` is all you need for them. The saturation fit costs minutes per fluid, so the
|
|
96
|
+
catalogue is generated once on CI by `.github/workflows/catalogue.yml` and committed rather than
|
|
97
|
+
rebuilt by everyone. `make_fluid` above stays useful for checking one, for changing one, and for
|
|
98
|
+
a fluid CoolProp gains after a release. Ten fluids are blocked, five by a residual term family
|
|
99
|
+
and five by an ideal-gas one, that are to be implemented soon :
|
|
100
|
+
|
|
101
|
+
| Blocked | Fluids | Missing family |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| residual | water, CO₂ | `ResidualHelmholtzNonAnalytic` (Span–Wagner critical terms) |
|
|
104
|
+
| residual | ammonia | `ResidualHelmholtzGaoB` |
|
|
105
|
+
| residual | methanol | `ResidualHelmholtzDoubleExponential` |
|
|
106
|
+
| residual | R125 | `ResidualHelmholtzLemmon2005` |
|
|
107
|
+
| ideal | D6, n-heptane | `IdealGasHelmholtzCP0AlyLee` |
|
|
108
|
+
| ideal | air, fluorine | `IdealGasHelmholtzPlanckEinsteinGeneralized` |
|
|
109
|
+
| ideal | n-undecane | `CP0PolyT` with `t = -1` (integrates to `tau*ln(tau)`) |
|
|
110
|
+
|
|
111
|
+
Transport is the sparser half. Families **not yet supported**,
|
|
112
|
+
verified against the `model`/`type` tags in
|
|
113
|
+
[CoolProp's fluid definition files](https://github.com/CoolProp/CoolProp/tree/master/dev/fluids):
|
|
114
|
+
|
|
115
|
+
| Part | Family | Blocks e.g. | Source |
|
|
116
|
+
|--------------|------------------------------------------------------------------------|--------------------------------------|--------|
|
|
117
|
+
| Visc./cond. | extended corresponding states (ECS); CoolProp's fallback for fluids with no dedicated correlation | siloxanes, most refrigerants | [Huber, Laesecke & Perkins 2003](https://doi.org/10.1021/ie0300880) |
|
|
118
|
+
| Viscosity | friction theory higher-order term | several alkanes | [Quiñones-Cisneros et al. 2000](https://doi.org/10.1016/S0378-3812(00)00474-X) |
|
|
119
|
+
| Viscosity | Chung et al. corresponding-states | minor fluids | [Chung et al. 1988](https://doi.org/10.1021/ie00076a024) |
|
|
120
|
+
| Visc./cond. | hardcoded per-fluid schemes (IAPWS water, Laesecke CO₂, hard-sphere alkanes) | water, CO₂ (viscosity), n-hexane, n-heptane | [Huber et al. 2009](https://doi.org/10.1063/1.3088050); [Laesecke & Muzny 2017](https://doi.org/10.1063/1.4977429); [Michailidou et al. 2013](https://doi.org/10.1063/1.4818980) |
|
|
121
|
+
| EOS | cubic (SRK, Peng–Robinson) and PC-SAFT | quick approximate fluids, mixtures | [Soave 1972](https://doi.org/10.1016/0009-2509(72)80096-4); [Peng & Robinson 1976](https://doi.org/10.1021/i160057a011); [Gross & Sadowski 2001](https://doi.org/10.1021/ie0003887) |
|
|
122
|
+
|
|
123
|
+
More will be supported soon too (ECS is planned first). Today 16 fluids are usable end to end (EOS **and** viscosity
|
|
124
|
+
**and** conductivity); every one of the 126 gives density, energies and cp/cv.
|
|
125
|
+
|
|
126
|
+
## Interpolation tables
|
|
127
|
+
|
|
128
|
+
The runtime solvers (`Interface.flash`) are bracketed and iterative,
|
|
129
|
+
so they are robust and precise but somewhat slow (still 2.5 times the speed of `CoolProp.PropsSI`).
|
|
130
|
+
To tackle this `propax`implements bicubic interpolation with tunable precision (tunable floating point
|
|
131
|
+
precision, tunable tolerance, absolutely no `CoolProp` dependency, derivatives
|
|
132
|
+
via autodiff which also allows for bicubics to be a lot more precise) :
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
python -m propax.build_tables hydrogen --target 1e-5 # only the fluids you use
|
|
136
|
+
python -m propax.build_tables --list # what the cache holds, and its size
|
|
137
|
+
python -m propax.build_tables --remove argon # free one fluid
|
|
138
|
+
python -m propax.build_tables --clear # free everything
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
A fluid's tables cost a few hundred MB, which is why these, unlike the fluid
|
|
142
|
+
definitions, are built on demand rather than shipped: name the ones you need.
|
|
143
|
+
Tables land in `~/.cache/propax/<fluid>/` and `PROPAX_TABLE_DIR` (or
|
|
144
|
+
`--table-dir`) moves the cache anywhere you want.
|
|
145
|
+
|
|
146
|
+
Tables are built natively with the package's own solvers, and `--target`
|
|
147
|
+
adaptively shrinks / widens the computation grids to match a tolerance (with 1e-5 by default) while
|
|
148
|
+
being the lightest possible. A table is not meant to meet high precision
|
|
149
|
+
requirements anyway, by design it suits float32-compatible tolerances (~1e-5 to
|
|
150
|
+
~1e-7 rtol); when you need more, `flash` needs no table at all.
|
|
151
|
+
|
|
152
|
+
## More on performance
|
|
153
|
+
|
|
154
|
+
What makes JAX both great to use and difficult to optimize is its vectorization mechanism. `jax.vmap(func)` returns a vectorized version of a scalar function, this must however not be confused with C++ vectorization. JAX performs SIMD/SIMT operations, when solving 100K flashs at once the slowest solve pins down all of the others, slowing down a lot the computations, while C++ vectorization (or standard CPU multi-threading) processes each element independently. This must be kept in mind if you are seeking performance increase. Performance measurements are plotted in
|
|
155
|
+
[tutorials/explore.ipynb](https://github.com/cziffras/propax/blob/main/tutorials/explore.ipynb), which also walks through the
|
|
156
|
+
phase envelope, a `c_p` field and the Joule–Thomson inversion curve.
|
|
157
|
+
|
|
158
|
+
## Usage
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
import jax
|
|
162
|
+
jax.config.update("jax_enable_x64", True) # required, before anything else
|
|
163
|
+
from propax import Interface
|
|
164
|
+
props = Interface.create("n-propane")
|
|
165
|
+
|
|
166
|
+
# accurate: bracketed solve, no table needed (works across the biphasic dome by
|
|
167
|
+
# doing automatic phase detection and runs at various speeds across flash types)
|
|
168
|
+
state, converged = props.flash("P", 2e5, "H", 3e5)
|
|
169
|
+
|
|
170
|
+
# fast: bicubic table lookup only, once you have built the tables
|
|
171
|
+
state = props.fast_flash("D", 2.0, "U", 4e5)
|
|
172
|
+
|
|
173
|
+
# direct EOS evaluation (single phase)
|
|
174
|
+
state = props.props_rhoT(2.0, 300.0)
|
|
175
|
+
|
|
176
|
+
# and it differentiates, of course
|
|
177
|
+
dT_dP = jax.grad(lambda p: props.flash("P", p, "H", 3e5)[0]["T"])(2e5)
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Note that `propax` can be used by simply passing floats (traditionally considered as static inputs in JAX) without triggering `jit` recompile allowing `CoolProp`-like usage for users that are not used to JAX. Obviously it itself naturally composes with `jax.jit`, `jax.vmap` and `jax.grad`.
|
|
181
|
+
|
|
182
|
+
Two conventions worth knowing : `flash` returns `(state, converged)` and you
|
|
183
|
+
are meant to look at the flag, and a two-phase state comes back with `cv` and `cp`
|
|
184
|
+
set to NaN, because they are genuinely undefined there (temperature is pinned
|
|
185
|
+
while heat is added) and I would rather say so than return a lever-rule number
|
|
186
|
+
that looks like an answer.
|
|
187
|
+
|
|
188
|
+
## Install & discover
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
pip install propax
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
That is the whole runtime: JAX and nothing else of substance. The extras are
|
|
195
|
+
dev-time only, and neither is imported by the runtime :
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
pip install "propax[coolprop]" # CoolProp + mpmath, to transcribe new fluids
|
|
199
|
+
pip install "propax[build]" # scipy, to build interpolation tables
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
From source instead, to run the tests or serve the docs :
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
git clone https://github.com/cziffras/propax && cd propax
|
|
206
|
+
uv sync --extra test
|
|
207
|
+
uv run pytest
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Documentation renders from the docstrings, so `uv run mkdocs serve` gives you
|
|
211
|
+
the browsable version of `docs/reference.md`.
|
|
212
|
+
|
|
213
|
+
The theory, from the first principles up, is in `docs/` :
|
|
214
|
+
`eos.md` for the Helmholtz formulation,
|
|
215
|
+
`flash.md` for the flashes and why each bracket is valid,
|
|
216
|
+
`superancillary.md` for the Chebyshev machinery and the
|
|
217
|
+
critical expansion, `transport.md` for the viscosity and
|
|
218
|
+
conductivity families.
|
|
219
|
+
|
|
220
|
+
## Tests
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
python -m pytest tests/ -v
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
The CoolProp-based tests are skipped unless CoolProp is installed
|
|
227
|
+
(`uv sync --extra coolprop`); CoolProp is only ever used as a test oracle and
|
|
228
|
+
is never imported by the runtime.
|
|
229
|
+
|
|
230
|
+
## Roadmap: what's coming next ?
|
|
231
|
+
|
|
232
|
+
### Extended corresponding states
|
|
233
|
+
|
|
234
|
+
Described above : the coefficients are published, the reference fluids are already
|
|
235
|
+
exact here, and it is the difference between 16 fluids usable end to end and most
|
|
236
|
+
of the refrigerant catalogue.
|
|
237
|
+
|
|
238
|
+
### Mixtures
|
|
239
|
+
|
|
240
|
+
The next big extension is the standard multi-fluid Helmholtz mixture
|
|
241
|
+
model of [GERG-2008 (Kunz & Wagner 2012)](https://doi.org/10.1021/je300655b),
|
|
242
|
+
the formulation used by REFPROP and
|
|
243
|
+
[CoolProp's mixture backend](http://www.coolprop.org/fluid_properties/Mixtures.html) ([relevant documentation](https://coolprop.org/fluid_properties/Mixtures.html#theoretical-description)):
|
|
244
|
+
|
|
245
|
+
## License
|
|
246
|
+
|
|
247
|
+
MIT.
|
propax-0.1.0/README.md
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# **PROPAX**
|
|
2
|
+
|
|
3
|
+
[](https://github.com/cziffras/propax/actions/workflows/ci.yml)
|
|
4
|
+
[](https://github.com/cziffras/propax/blob/main/LICENSE)
|
|
5
|
+
[](https://github.com/cziffras/propax/blob/main/pyproject.toml)
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<img src="https://raw.githubusercontent.com/cziffras/propax/main/imgs/cp_propax.png" alt="illustration" width="400">
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
Many thermodynamics simulations could make use of an easy-to-use CoolProp-like interface that
|
|
14
|
+
is fully differentiable and compatible with the greater JAX ecosystem. It is exactly what `propax` is : written in pure JAX, fully differentiable, jittable and vmappable thermodynamics without any `pure_callback` running on CPU/GPU in both 32 and 64 bits precision !
|
|
15
|
+
|
|
16
|
+
Additionally `propax` aims at being transparent and theoretically solid, EOS parameters are taken from litterature for reproducibility and comparability but
|
|
17
|
+
most physical constants (saturation properties, critical point...) are recomputed
|
|
18
|
+
offline so that all values do perfectly match the EOS structure and nothing remains hidden.
|
|
19
|
+
|
|
20
|
+
## To what extent does this work rely on CoolProp ?
|
|
21
|
+
|
|
22
|
+
Other similar projects (see [jaxprop](https://github.com/turbo-sim/jaxprop)) are essentially wrapping CoolProp itself and expose it via `jax.pure_callback()`. While making CoolProp calls possible in JAX-written code, this causes two distinct issues :
|
|
23
|
+
- CoolProp calls are still performed on CPU which blocks any different hardware usage (GPU, TPU...)
|
|
24
|
+
- Calls made on CPU causes different performance costs : numpy array conversion, latency due to data movements between CPU Host memory and GPU memory and suboptimality of XLA optimization of your code among others...
|
|
25
|
+
|
|
26
|
+
This is the reason why I made the choice to write `propax` as an alternative to wrappers without sacrificing the precision reached by iterative solvers (one could have implemented a simple interpolation of CoolProp tables in JAX, however the cost in memory is heavy and precision is dubious mostly for what it comes to derivatives computed via autodiff which are smoothed by any interpolation while they can sometimes be extremely small already).
|
|
27
|
+
|
|
28
|
+
In `propax`, the EOS coefficients are transcribed index by index from the
|
|
29
|
+
published correlation, and everything else is solved from them :
|
|
30
|
+
|
|
31
|
+
- The critical point : is not the published value, it is the point
|
|
32
|
+
where the correlation itself has `dP/drho = d2P/drho2 = 0`.
|
|
33
|
+
- The saturation curve : is a Chebyshev superancillary, fitted offline in
|
|
34
|
+
extended precision (mpmath) against equal pressure and equal fugacity, not
|
|
35
|
+
against CoolProp.
|
|
36
|
+
|
|
37
|
+
The offline machinery lives in `utils/exact/` and is documented in
|
|
38
|
+
`docs/superancillary.md`.
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
## Making a fluid
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
pip install "propax[coolprop]" # CoolProp + mpmath, dev-time only
|
|
45
|
+
python -m propax.make_fluid Argon # transcribe the EOS, then fit its saturation curve
|
|
46
|
+
python -m propax.utils.make_utils.coverage # what is convertible, and what blocks the rest
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The converter copies the Helmholtz coefficients (machine-precision
|
|
50
|
+
EOS), checks the result back against CoolProp to 1e-9, and checks each transport
|
|
51
|
+
block to 1e-6. Please note that a correlation it cannot reproduce from published coefficients
|
|
52
|
+
is omitted, never approximated. In that case, the option `--transport-scaffold`
|
|
53
|
+
keeps the property instead of dropping it leaving each slot hardcoded in `CoolProp` with a placeholder and its reference in the litterature so you can implement it.
|
|
54
|
+
|
|
55
|
+
126 of CoolProp's 136 pure fluids convert today, and the package ships the ones that do, so
|
|
56
|
+
`pip install propax` is all you need for them. The saturation fit costs minutes per fluid, so the
|
|
57
|
+
catalogue is generated once on CI by `.github/workflows/catalogue.yml` and committed rather than
|
|
58
|
+
rebuilt by everyone. `make_fluid` above stays useful for checking one, for changing one, and for
|
|
59
|
+
a fluid CoolProp gains after a release. Ten fluids are blocked, five by a residual term family
|
|
60
|
+
and five by an ideal-gas one, that are to be implemented soon :
|
|
61
|
+
|
|
62
|
+
| Blocked | Fluids | Missing family |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| residual | water, CO₂ | `ResidualHelmholtzNonAnalytic` (Span–Wagner critical terms) |
|
|
65
|
+
| residual | ammonia | `ResidualHelmholtzGaoB` |
|
|
66
|
+
| residual | methanol | `ResidualHelmholtzDoubleExponential` |
|
|
67
|
+
| residual | R125 | `ResidualHelmholtzLemmon2005` |
|
|
68
|
+
| ideal | D6, n-heptane | `IdealGasHelmholtzCP0AlyLee` |
|
|
69
|
+
| ideal | air, fluorine | `IdealGasHelmholtzPlanckEinsteinGeneralized` |
|
|
70
|
+
| ideal | n-undecane | `CP0PolyT` with `t = -1` (integrates to `tau*ln(tau)`) |
|
|
71
|
+
|
|
72
|
+
Transport is the sparser half. Families **not yet supported**,
|
|
73
|
+
verified against the `model`/`type` tags in
|
|
74
|
+
[CoolProp's fluid definition files](https://github.com/CoolProp/CoolProp/tree/master/dev/fluids):
|
|
75
|
+
|
|
76
|
+
| Part | Family | Blocks e.g. | Source |
|
|
77
|
+
|--------------|------------------------------------------------------------------------|--------------------------------------|--------|
|
|
78
|
+
| Visc./cond. | extended corresponding states (ECS); CoolProp's fallback for fluids with no dedicated correlation | siloxanes, most refrigerants | [Huber, Laesecke & Perkins 2003](https://doi.org/10.1021/ie0300880) |
|
|
79
|
+
| Viscosity | friction theory higher-order term | several alkanes | [Quiñones-Cisneros et al. 2000](https://doi.org/10.1016/S0378-3812(00)00474-X) |
|
|
80
|
+
| Viscosity | Chung et al. corresponding-states | minor fluids | [Chung et al. 1988](https://doi.org/10.1021/ie00076a024) |
|
|
81
|
+
| Visc./cond. | hardcoded per-fluid schemes (IAPWS water, Laesecke CO₂, hard-sphere alkanes) | water, CO₂ (viscosity), n-hexane, n-heptane | [Huber et al. 2009](https://doi.org/10.1063/1.3088050); [Laesecke & Muzny 2017](https://doi.org/10.1063/1.4977429); [Michailidou et al. 2013](https://doi.org/10.1063/1.4818980) |
|
|
82
|
+
| EOS | cubic (SRK, Peng–Robinson) and PC-SAFT | quick approximate fluids, mixtures | [Soave 1972](https://doi.org/10.1016/0009-2509(72)80096-4); [Peng & Robinson 1976](https://doi.org/10.1021/i160057a011); [Gross & Sadowski 2001](https://doi.org/10.1021/ie0003887) |
|
|
83
|
+
|
|
84
|
+
More will be supported soon too (ECS is planned first). Today 16 fluids are usable end to end (EOS **and** viscosity
|
|
85
|
+
**and** conductivity); every one of the 126 gives density, energies and cp/cv.
|
|
86
|
+
|
|
87
|
+
## Interpolation tables
|
|
88
|
+
|
|
89
|
+
The runtime solvers (`Interface.flash`) are bracketed and iterative,
|
|
90
|
+
so they are robust and precise but somewhat slow (still 2.5 times the speed of `CoolProp.PropsSI`).
|
|
91
|
+
To tackle this `propax`implements bicubic interpolation with tunable precision (tunable floating point
|
|
92
|
+
precision, tunable tolerance, absolutely no `CoolProp` dependency, derivatives
|
|
93
|
+
via autodiff which also allows for bicubics to be a lot more precise) :
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
python -m propax.build_tables hydrogen --target 1e-5 # only the fluids you use
|
|
97
|
+
python -m propax.build_tables --list # what the cache holds, and its size
|
|
98
|
+
python -m propax.build_tables --remove argon # free one fluid
|
|
99
|
+
python -m propax.build_tables --clear # free everything
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
A fluid's tables cost a few hundred MB, which is why these, unlike the fluid
|
|
103
|
+
definitions, are built on demand rather than shipped: name the ones you need.
|
|
104
|
+
Tables land in `~/.cache/propax/<fluid>/` and `PROPAX_TABLE_DIR` (or
|
|
105
|
+
`--table-dir`) moves the cache anywhere you want.
|
|
106
|
+
|
|
107
|
+
Tables are built natively with the package's own solvers, and `--target`
|
|
108
|
+
adaptively shrinks / widens the computation grids to match a tolerance (with 1e-5 by default) while
|
|
109
|
+
being the lightest possible. A table is not meant to meet high precision
|
|
110
|
+
requirements anyway, by design it suits float32-compatible tolerances (~1e-5 to
|
|
111
|
+
~1e-7 rtol); when you need more, `flash` needs no table at all.
|
|
112
|
+
|
|
113
|
+
## More on performance
|
|
114
|
+
|
|
115
|
+
What makes JAX both great to use and difficult to optimize is its vectorization mechanism. `jax.vmap(func)` returns a vectorized version of a scalar function, this must however not be confused with C++ vectorization. JAX performs SIMD/SIMT operations, when solving 100K flashs at once the slowest solve pins down all of the others, slowing down a lot the computations, while C++ vectorization (or standard CPU multi-threading) processes each element independently. This must be kept in mind if you are seeking performance increase. Performance measurements are plotted in
|
|
116
|
+
[tutorials/explore.ipynb](https://github.com/cziffras/propax/blob/main/tutorials/explore.ipynb), which also walks through the
|
|
117
|
+
phase envelope, a `c_p` field and the Joule–Thomson inversion curve.
|
|
118
|
+
|
|
119
|
+
## Usage
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
import jax
|
|
123
|
+
jax.config.update("jax_enable_x64", True) # required, before anything else
|
|
124
|
+
from propax import Interface
|
|
125
|
+
props = Interface.create("n-propane")
|
|
126
|
+
|
|
127
|
+
# accurate: bracketed solve, no table needed (works across the biphasic dome by
|
|
128
|
+
# doing automatic phase detection and runs at various speeds across flash types)
|
|
129
|
+
state, converged = props.flash("P", 2e5, "H", 3e5)
|
|
130
|
+
|
|
131
|
+
# fast: bicubic table lookup only, once you have built the tables
|
|
132
|
+
state = props.fast_flash("D", 2.0, "U", 4e5)
|
|
133
|
+
|
|
134
|
+
# direct EOS evaluation (single phase)
|
|
135
|
+
state = props.props_rhoT(2.0, 300.0)
|
|
136
|
+
|
|
137
|
+
# and it differentiates, of course
|
|
138
|
+
dT_dP = jax.grad(lambda p: props.flash("P", p, "H", 3e5)[0]["T"])(2e5)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Note that `propax` can be used by simply passing floats (traditionally considered as static inputs in JAX) without triggering `jit` recompile allowing `CoolProp`-like usage for users that are not used to JAX. Obviously it itself naturally composes with `jax.jit`, `jax.vmap` and `jax.grad`.
|
|
142
|
+
|
|
143
|
+
Two conventions worth knowing : `flash` returns `(state, converged)` and you
|
|
144
|
+
are meant to look at the flag, and a two-phase state comes back with `cv` and `cp`
|
|
145
|
+
set to NaN, because they are genuinely undefined there (temperature is pinned
|
|
146
|
+
while heat is added) and I would rather say so than return a lever-rule number
|
|
147
|
+
that looks like an answer.
|
|
148
|
+
|
|
149
|
+
## Install & discover
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
pip install propax
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
That is the whole runtime: JAX and nothing else of substance. The extras are
|
|
156
|
+
dev-time only, and neither is imported by the runtime :
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
pip install "propax[coolprop]" # CoolProp + mpmath, to transcribe new fluids
|
|
160
|
+
pip install "propax[build]" # scipy, to build interpolation tables
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
From source instead, to run the tests or serve the docs :
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
git clone https://github.com/cziffras/propax && cd propax
|
|
167
|
+
uv sync --extra test
|
|
168
|
+
uv run pytest
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Documentation renders from the docstrings, so `uv run mkdocs serve` gives you
|
|
172
|
+
the browsable version of `docs/reference.md`.
|
|
173
|
+
|
|
174
|
+
The theory, from the first principles up, is in `docs/` :
|
|
175
|
+
`eos.md` for the Helmholtz formulation,
|
|
176
|
+
`flash.md` for the flashes and why each bracket is valid,
|
|
177
|
+
`superancillary.md` for the Chebyshev machinery and the
|
|
178
|
+
critical expansion, `transport.md` for the viscosity and
|
|
179
|
+
conductivity families.
|
|
180
|
+
|
|
181
|
+
## Tests
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
python -m pytest tests/ -v
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
The CoolProp-based tests are skipped unless CoolProp is installed
|
|
188
|
+
(`uv sync --extra coolprop`); CoolProp is only ever used as a test oracle and
|
|
189
|
+
is never imported by the runtime.
|
|
190
|
+
|
|
191
|
+
## Roadmap: what's coming next ?
|
|
192
|
+
|
|
193
|
+
### Extended corresponding states
|
|
194
|
+
|
|
195
|
+
Described above : the coefficients are published, the reference fluids are already
|
|
196
|
+
exact here, and it is the difference between 16 fluids usable end to end and most
|
|
197
|
+
of the refrigerant catalogue.
|
|
198
|
+
|
|
199
|
+
### Mixtures
|
|
200
|
+
|
|
201
|
+
The next big extension is the standard multi-fluid Helmholtz mixture
|
|
202
|
+
model of [GERG-2008 (Kunz & Wagner 2012)](https://doi.org/10.1021/je300655b),
|
|
203
|
+
the formulation used by REFPROP and
|
|
204
|
+
[CoolProp's mixture backend](http://www.coolprop.org/fluid_properties/Mixtures.html) ([relevant documentation](https://coolprop.org/fluid_properties/Mixtures.html#theoretical-description)):
|
|
205
|
+
|
|
206
|
+
## License
|
|
207
|
+
|
|
208
|
+
MIT.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
build-backend = "setuptools.build_meta"
|
|
3
|
+
requires = ["setuptools>=61.0"]
|
|
4
|
+
|
|
5
|
+
[dependency-groups]
|
|
6
|
+
dev = [
|
|
7
|
+
"ipykernel>=7.1.0",
|
|
8
|
+
"ipython>=9.7.0",
|
|
9
|
+
"jupyter>=1.1.1",
|
|
10
|
+
"prek>=0.2",
|
|
11
|
+
"pyright==1.1.411",
|
|
12
|
+
"pytest>=8.4.2",
|
|
13
|
+
"ruff==0.15.20",
|
|
14
|
+
"toml-sort>=0.24"
|
|
15
|
+
]
|
|
16
|
+
docs = [
|
|
17
|
+
"mkdocs-material>=9.5",
|
|
18
|
+
"mkdocstrings[python]>=0.27"
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[project]
|
|
22
|
+
authors = [{name = "Emmanuel Benichou"}]
|
|
23
|
+
classifiers = [
|
|
24
|
+
"Development Status :: 3 - Alpha",
|
|
25
|
+
"Intended Audience :: Science/Research",
|
|
26
|
+
"Programming Language :: Python :: 3.12",
|
|
27
|
+
"Programming Language :: Python :: 3.13",
|
|
28
|
+
"Topic :: Scientific/Engineering :: Physics",
|
|
29
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
30
|
+
"Topic :: Scientific/Engineering :: Mathematics"
|
|
31
|
+
]
|
|
32
|
+
dependencies = [
|
|
33
|
+
"equinox>=0.13.2",
|
|
34
|
+
"jax>=0.8.1,<0.9", # equinox/jax compat, see diffrax#717 for the lower bound
|
|
35
|
+
"jaxtyping>=0.2.36",
|
|
36
|
+
"lineax>=0.0.7",
|
|
37
|
+
"numpy>=2.0",
|
|
38
|
+
"optimistix>=0.0.11",
|
|
39
|
+
"pydantic>=2.12.4"
|
|
40
|
+
]
|
|
41
|
+
description = "Differentiable CoolProp-style fluid properties in pure JAX, driven by fluid definition files."
|
|
42
|
+
keywords = ["thermodynamics", "equation-of-state", "jax", "fluid-properties", "coolprop"]
|
|
43
|
+
license = "MIT"
|
|
44
|
+
license-files = ["LICENSE"]
|
|
45
|
+
name = "propax"
|
|
46
|
+
readme = "README.md"
|
|
47
|
+
requires-python = ">=3.12"
|
|
48
|
+
urls = {repository = "https://github.com/cziffras/propax"}
|
|
49
|
+
version = "0.1.0"
|
|
50
|
+
|
|
51
|
+
[project.optional-dependencies]
|
|
52
|
+
build = [
|
|
53
|
+
"scipy>=1.11"
|
|
54
|
+
]
|
|
55
|
+
coolprop = [
|
|
56
|
+
"coolprop>=6.6.0",
|
|
57
|
+
"mpmath>=1.3"
|
|
58
|
+
]
|
|
59
|
+
notebooks = [
|
|
60
|
+
"matplotlib>=3.10",
|
|
61
|
+
"plotly>=6.5",
|
|
62
|
+
"ipykernel>=7.1"
|
|
63
|
+
]
|
|
64
|
+
test = [
|
|
65
|
+
"pytest",
|
|
66
|
+
"coolprop>=6.6.0"
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
[tool.pyright]
|
|
70
|
+
include = ["src", "tests"]
|
|
71
|
+
|
|
72
|
+
[tool.pytest.ini_options]
|
|
73
|
+
testpaths = ["tests"]
|
|
74
|
+
|
|
75
|
+
[tool.ruff]
|
|
76
|
+
extend-exclude = ["*.ipynb"]
|
|
77
|
+
|
|
78
|
+
[tool.ruff.lint]
|
|
79
|
+
ignore = [
|
|
80
|
+
"E501",
|
|
81
|
+
"F722"
|
|
82
|
+
]
|
|
83
|
+
select = ["E", "F", "I"]
|
|
84
|
+
unfixable = ["F401"]
|
|
85
|
+
|
|
86
|
+
[tool.ruff.lint.per-file-ignores]
|
|
87
|
+
"__init__.py" = ["F401"]
|
|
88
|
+
|
|
89
|
+
[tool.setuptools.package-data]
|
|
90
|
+
"propax" = ["py.typed"]
|
|
91
|
+
"propax.fluids" = ["data/*.json"]
|
|
92
|
+
|
|
93
|
+
[tool.setuptools.packages.find]
|
|
94
|
+
where = ["src"]
|
propax-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from .core import Interface
|
|
2
|
+
from .fluids.generic import (
|
|
3
|
+
register_conductivity_residual,
|
|
4
|
+
register_viscosity_higher_order,
|
|
5
|
+
)
|
|
6
|
+
|
|
7
|
+
# restrain what can be imported if user enters `from propax import *`
|
|
8
|
+
__all__ = [
|
|
9
|
+
"Interface",
|
|
10
|
+
"register_viscosity_higher_order",
|
|
11
|
+
"register_conductivity_residual",
|
|
12
|
+
]
|