Summary
CoolProp v8.0.0 (a nanobind-based rewrite of the Python interface, abi3 wheels, link-free State shim) is heading to a beta. I tested PDSim against the v8 wheel and the good news first:
PDSim builds and runs full simulations on CoolProp v8 with zero source changes. It compiles cleanly against v8's frozen cimport surface (CoolProp.State / CoolProp.constants_header), and complete quasi-steady-state cycles converge with correct physics:
| Example |
Result on v8 |
examples/recip_compressor.py |
mdot 8.139 g/s, vol-eff 65.2%, adiabatic-eff 90.7% |
examples/simple_example.py |
mdot 0.504 g/s, vol-eff 88.7%, adiabatic-eff 100.6% |
CoolProp.State (the v8 capsule shim) drives the entire ODE inner loop. So the CoolProp coupling itself is fine. The only blockers were on the PDSim side:
1. The coolprop==7.1.0 pin blocks v8
pyproject.toml pins coolprop==7.1.0 in both [build-system].requires and [project].dependencies. That means:
pip install pdsim will downgrade a user already on v8, and
- building PDSim resolves CoolProp 7.1.0 under build isolation regardless of what's installed.
To test v8 I had to build --no-build-isolation and force-reinstall v8 afterward.
Suggested fix: loosen the pin to a range that admits v8, e.g. coolprop>=7.1 (or coolprop>=8.0.0b1 to opt into the beta with pip install --pre). v8's cimport surface (State.pxd, constants_header.pxd) and get_include_directory() are all present, so the build needs no other change.
2. numpy 2.x incompatibilities (independent of CoolProp)
PDSim uses several numpy-1 APIs removed in numpy 2.0, which break the examples on a modern numpy:
np.trapz — removed in numpy 2.0 (renamed np.trapezoid). Hit in PDSim/core/core.py _postprocess_flows (~L415: np.trapz(mdot, self.t[0:self.Ntheta])). Breaks recip_compressor.py in post-processing.
- size-1 array → Python scalar — numpy 2 no longer auto-converts a 1-element array to a scalar. Assigning to a
cdef double geoVals attribute raises TypeError: only 0-dimensional arrays can be converted to Python scalars. Hit in PDSim/scroll/common_scroll_geo.pxd (geoVals setter, e.g. xa_arc2.__set__) via symm_scroll_geo.setDiscGeo. This kills scroll_compressor.py in geometry setup, before CoolProp is involved.
Suggested fix: np.trapz → np.trapezoid (with a fallback shim for numpy<2 if you still support it), and ensure scalars (float(x) / x.item()) are passed into the cdef double geoVals setters. (As a stopgap, pinning numpy<2 also works.)
Why this matters now
CoolProp v8 is recruiting beta testers, and PDSim is the flagship downstream consumer. With the pin loosened and the numpy-2 fixes in, testers could pip install --pre both and run these examples directly. Happy to send PRs for either fix.
(Tested 2026-06-09 against a local CoolProp v8 nanobind wheel; PDSim @ main 2.15.)
Summary
CoolProp v8.0.0 (a nanobind-based rewrite of the Python interface, abi3 wheels, link-free
Stateshim) is heading to a beta. I tested PDSim against the v8 wheel and the good news first:PDSim builds and runs full simulations on CoolProp v8 with zero source changes. It compiles cleanly against v8's frozen cimport surface (
CoolProp.State/CoolProp.constants_header), and complete quasi-steady-state cycles converge with correct physics:examples/recip_compressor.pyexamples/simple_example.pyCoolProp.State(the v8 capsule shim) drives the entire ODE inner loop. So the CoolProp coupling itself is fine. The only blockers were on the PDSim side:1. The
coolprop==7.1.0pin blocks v8pyproject.tomlpinscoolprop==7.1.0in both[build-system].requiresand[project].dependencies. That means:pip install pdsimwill downgrade a user already on v8, andTo test v8 I had to build
--no-build-isolationand force-reinstall v8 afterward.Suggested fix: loosen the pin to a range that admits v8, e.g.
coolprop>=7.1(orcoolprop>=8.0.0b1to opt into the beta withpip install --pre). v8's cimport surface (State.pxd,constants_header.pxd) andget_include_directory()are all present, so the build needs no other change.2. numpy 2.x incompatibilities (independent of CoolProp)
PDSim uses several numpy-1 APIs removed in numpy 2.0, which break the examples on a modern numpy:
np.trapz— removed in numpy 2.0 (renamednp.trapezoid). Hit inPDSim/core/core.py_postprocess_flows(~L415:np.trapz(mdot, self.t[0:self.Ntheta])). Breaksrecip_compressor.pyin post-processing.cdef doublegeoVals attribute raisesTypeError: only 0-dimensional arrays can be converted to Python scalars. Hit inPDSim/scroll/common_scroll_geo.pxd(geoVals setter, e.g.xa_arc2.__set__) viasymm_scroll_geo.setDiscGeo. This killsscroll_compressor.pyin geometry setup, before CoolProp is involved.Suggested fix:
np.trapz→np.trapezoid(with a fallback shim for numpy<2 if you still support it), and ensure scalars (float(x)/x.item()) are passed into thecdef doublegeoVals setters. (As a stopgap, pinningnumpy<2also works.)Why this matters now
CoolProp v8 is recruiting beta testers, and PDSim is the flagship downstream consumer. With the pin loosened and the numpy-2 fixes in, testers could
pip install --preboth and run these examples directly. Happy to send PRs for either fix.(Tested 2026-06-09 against a local CoolProp v8 nanobind wheel; PDSim @
main2.15.)