Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cantera Units #991

Merged
merged 41 commits into from Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
6cfd088
Implement unit conversion file into Cantera
hallaali Mar 3, 2021
6dabf1a
Create test_units.py
hallaali Mar 19, 2021
594e50f
Create Python examples with units
hallaali Apr 15, 2021
b7051d4
fix tests and update unit examples
hallaali Apr 29, 2021
e7a59fa
Refactor PureFluid derived classes as functions
bryanwweber Apr 30, 2021
b1fbaf0
Refactor setter and getter templates for units
bryanwweber Apr 30, 2021
8bf0fbb
Use numpy.isclose to compare array Quantities
bryanwweber Apr 30, 2021
94c5908
Add critical_density units
bryanwweber Apr 30, 2021
4952189
Fix up tests for units module
bryanwweber Apr 30, 2021
b347d0a
fix capitalization error
hallaali May 3, 2021
0755513
add pint dependency to CI
bryanwweber May 29, 2022
4a03313
Update rankine_units.py
hallaali May 5, 2021
3944c32
[Doc] Add default python_module key into env
bryanwweber May 28, 2022
f3667ab
[Units] Add application-level registry
bryanwweber May 29, 2022
7ae626e
[Cython] Fix setuptools warning about data
bryanwweber Sep 24, 2022
590ebde
[Cython] Move units package to with_units
bryanwweber Sep 24, 2022
443ad26
[Examples] Add example keywords for units
bryanwweber Sep 24, 2022
0f43463
[CI] Run examples from installed wheel
bryanwweber Sep 26, 2022
cde23e3
[Cython] Fix a typo in an error message
bryanwweber Oct 12, 2022
2effd6d
[Test] Add branch coverage to Python
bryanwweber Oct 12, 2022
abd8b4b
[Units] Pass through kwargs in constructor
bryanwweber Oct 12, 2022
cf4c134
[Units] Refactor setter to use a loop
bryanwweber Oct 12, 2022
dfec96f
Missing a license header
bryanwweber Oct 12, 2022
db403b4
[Units/Test] Refactor test suite to use pytest
bryanwweber Oct 12, 2022
7e89b03
Refactor dimensions tests
bryanwweber Oct 17, 2022
966a249
Address review line comments
bryanwweber Oct 23, 2022
9d1b533
[Units] Add documentation
bryanwweber Oct 29, 2022
12a6cb4
[Units] Add tests that all properties are implemented
bryanwweber Oct 30, 2022
1ae4556
Fix testing and docs build failures
bryanwweber Oct 30, 2022
e6941bf
[CI] Add --pre option to sample installation step
bryanwweber Oct 31, 2022
6b554c7
[CI] Don't use PyPI index when installing Cantera
bryanwweber Nov 1, 2022
582ef72
[CI] Fix example installation
bryanwweber Nov 7, 2022
085480c
Remove some tabs
bryanwweber Mar 25, 2023
e382c2a
Apply suggestions from code review
bryanwweber Apr 22, 2023
094d5fa
Move building the units interface to a Scons extension
bryanwweber Apr 23, 2023
0f9167b
General cleanups
bryanwweber Apr 23, 2023
5396e79
Fix one problem with building the sdist
bryanwweber Apr 23, 2023
7459ec3
Address a bunch of review comments
bryanwweber Apr 23, 2023
ee8bdb6
Address comments about tests
bryanwweber Apr 23, 2023
3ba8aec
Docs and AUTHORS
bryanwweber Apr 24, 2023
644bc79
Add a bit more docs
bryanwweber Apr 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
62 changes: 30 additions & 32 deletions .github/workflows/main.yml
Expand Up @@ -53,7 +53,7 @@ jobs:
# h5py is optional; some versions don't have binaries (yet)
run: |
python3 -m pip install ruamel.yaml scons==3.1.2 numpy cython pandas pytest \
pytest-github-actions-annotate-failures
pytest-github-actions-annotate-failures pint
python3 -m pip install h5py
- name: Build Cantera
run: |
Expand All @@ -70,6 +70,13 @@ jobs:
- name: Test Cantera
run:
python3 `which scons` test show_long_tests=yes verbose_tests=yes --debug=time
- name: Save the wheel file to install Cantera
uses: actions/upload-artifact@v3
with:
path: build/python/dist/Cantera*.whl
retention-days: 2
name: cantera-wheel-${{ matrix.python-version }}-${{ matrix.os }}
if-no-files-found: error

clang-compiler:
name: LLVM/Clang with Python 3.8
Expand All @@ -96,7 +103,7 @@ jobs:
run: python3 -m pip install -U pip setuptools wheel
- name: Install Python dependencies
run: |
python3 -m pip install ruamel.yaml scons numpy cython pandas h5py pytest pytest-github-actions-annotate-failures
python3 -m pip install ruamel.yaml scons numpy cython pandas h5py pytest pytest-github-actions-annotate-failures pint
- name: Build Cantera
run: python3 `which scons` build env_vars=all
CXX=clang++-12 CC=clang-12 f90_interface=n extra_lib_dirs=/usr/lib/llvm/lib
Expand Down Expand Up @@ -147,7 +154,7 @@ jobs:
- name: Install Python dependencies
# h5py is optional; may fail if no wheel is present for a given OS/Python version
run: |
$PYTHON_CMD -m pip install ruamel.yaml numpy cython pandas pytest pytest-github-actions-annotate-failures
$PYTHON_CMD -m pip install ruamel.yaml numpy cython pandas pytest pytest-github-actions-annotate-failures pint
$PYTHON_CMD -m pip install h5py || true
- name: Install Python dependencies for GH Python
if: matrix.python-version == '3.11'
Expand Down Expand Up @@ -197,7 +204,7 @@ jobs:
- name: Install Python dependencies
run: |
python3 -m pip install ruamel.yaml scons numpy cython pandas scipy pytest h5py \
pytest-github-actions-annotate-failures pytest-cov gcovr
pytest-github-actions-annotate-failures pytest-cov gcovr pint
- name: Setup .NET Core SDK
uses: actions/setup-dotnet@v2
with:
Expand Down Expand Up @@ -293,7 +300,7 @@ jobs:
- name: Install Python dependencies
run: |
python3 -m pip install ruamel.yaml scons numpy cython sphinx\<4.0 jinja2\<3.1.0 \
sphinxcontrib-katex sphinxcontrib-matlabdomain sphinxcontrib-doxylink
sphinxcontrib-katex sphinxcontrib-matlabdomain sphinxcontrib-doxylink pint
- name: Build Cantera with documentation
run: python3 `which scons` build -j2 doxygen_docs=y sphinx_docs=y debug=n optimize=n use_pch=n
- name: Ensure 'scons help' options work
Expand Down Expand Up @@ -339,8 +346,9 @@ jobs:

run-examples:
name: Run the Python examples using bash
runs-on: ubuntu-20.04
runs-on: ${{ matrix.os }}
timeout-minutes: 60
needs: ["ubuntu-multiple-pythons"]
strategy:
matrix:
python-version: ['3.8', '3.10', '3.11']
Expand All @@ -349,10 +357,10 @@ jobs:
HDF5_LIBDIR: /usr/lib/x86_64-linux-gnu/hdf5/serial
HDF5_INCLUDEDIR: /usr/include/hdf5/serial
steps:
# We're not building Cantera here, we only need the checkout for the samples
# folder, so no need to do a recursive checkout
- uses: actions/checkout@v3
name: Checkout the repository
with:
submodules: recursive
- name: Setup Python
uses: actions/setup-python@v4
with:
Expand All @@ -361,35 +369,25 @@ jobs:
- name: Install Apt dependencies
run: |
sudo apt update
sudo apt install libboost-dev gfortran graphviz liblapack-dev libblas-dev \
gcc-9 g++-9 libhdf5-dev
sudo apt install graphviz
- name: Download the wheel artifact
uses: actions/download-artifact@v3
with:
name: cantera-wheel-${{ matrix.python-version }}-${{ matrix.os }}
path: dist
- name: Upgrade pip
run: python3 -m pip install -U pip setuptools wheel
- name: Install Python dependencies
run: |
python3 -m pip install ruamel.yaml scons numpy cython pandas matplotlib scipy h5py
- name: Build Cantera
# compile with GCC 9.4.0 on ubuntu-20.04 as an alternative to the default
# (GCC 7.5.0 is both default and oldest supported version)
# compile without native HDF5 support
run: python3 `which scons` build -j2 debug=n CC=gcc-9 CXX=g++-9
if: matrix.python-version != '3.10'
- name: Build Cantera (Python 3.10 with HDF)
# compile with GCC 9.4.0 on ubuntu-20.04 as an alternative to the default
# (GCC 7.5.0 is both default and oldest supported version)
# compile with native HDF5 support
run: |
python3 `which scons` build -j2 debug=n CC=gcc-9 CXX=g++-9 \
hdf_libdir=$HDF5_LIBDIR hdf_include=$HDF5_INCLUDEDIR
if: matrix.python-version == '3.10'
python3 -m pip install numpy ruamel.yaml h5py pandas matplotlib scipy pint
python3 -m pip install --pre --no-index --find-links dist cantera
- name: Run the examples
# See https://unix.stackexchange.com/a/392973 for an explanation of the -exec part
run: |
export LD_LIBRARY_PATH=build/lib
find samples/python -type f -iname "*.py" \
-exec sh -c 'for n; do echo "$n" | tee -a results.txt && python3 "$n" >> results.txt || exit 1; done' sh {} +
env:
PYTHONPATH: build/python
# The ignore setting here is due to a new warning introduced in Matplotlib==3.6.0
PYTHONWARNINGS: "error,ignore:warn_name_set_on_empty_Forward::pyparsing"
MPLBACKEND: Agg
Expand Down Expand Up @@ -434,7 +432,7 @@ jobs:
run: |
conda install -q sundials=${{ matrix.sundials-ver }} scons numpy ruamel.yaml \
cython boost-cpp fmt eigen yaml-cpp h5py pandas libgomp openblas pytest \
highfive
highfive pint
- name: Build Cantera
run: |
scons build system_fmt=y system_eigen=y system_yamlcpp=y system_sundials=y \
Expand Down Expand Up @@ -495,7 +493,7 @@ jobs:
# use boost-cpp rather than boost from conda-forge
# Install SCons >=4.4.0 to make sure that MSVC_TOOLSET_VERSION variable is present
run: |
mamba install -q '"scons>=4.4.0"' numpy cython ruamel.yaml boost-cpp eigen yaml-cpp h5py pandas pytest highfive
mamba install -q '"scons>=4.4.0"' numpy cython ruamel.yaml boost-cpp eigen yaml-cpp h5py pandas pytest highfive pint
shell: pwsh
- name: Build Cantera
run: scons build system_eigen=y system_yamlcpp=y system_highfive=y logging=debug
Expand Down Expand Up @@ -558,7 +556,7 @@ jobs:
- name: Install Python dependencies
run: |
python -m pip install -U pip setuptools wheel
python -m pip install '"scons<4.4.0"' pypiwin32 numpy ruamel.yaml cython pandas pytest pytest-github-actions-annotate-failures
python -m pip install '"scons<4.4.0"' pypiwin32 numpy ruamel.yaml cython pandas pytest pytest-github-actions-annotate-failures pint
- name: Restore Boost cache
uses: actions/cache@v3
id: cache-boost
Expand Down Expand Up @@ -622,7 +620,7 @@ jobs:
- name: Install Python dependencies
run: |
python3 -m pip install ruamel.yaml scons numpy cython pandas h5py pytest \
pytest-github-actions-annotate-failures
pytest-github-actions-annotate-failures pint
- name: Setup Intel oneAPI environment
run: |
source /opt/intel/oneapi/setvars.sh
Expand Down Expand Up @@ -669,7 +667,7 @@ jobs:
run: python3 -m pip install -U pip setuptools wheel
- name: Install Python dependencies
run: python3 -m pip install ruamel.yaml scons numpy cython h5py pandas pytest
pytest-github-actions-annotate-failures
pytest-github-actions-annotate-failures pint
- name: Setup Intel oneAPI environment
run: |
source /opt/intel/oneapi/setvars.sh
Expand Down Expand Up @@ -701,7 +699,7 @@ jobs:
- name: Install Python dependencies
run: |
python -m pip install -U pip setuptools wheel
python -m pip install scons pypiwin32 numpy ruamel.yaml cython h5py pandas pytest pytest-github-actions-annotate-failures
python -m pip install scons pypiwin32 numpy ruamel.yaml cython h5py pandas pytest pytest-github-actions-annotate-failures pint
- name: Restore Boost cache
uses: actions/cache@v3
id: cache-boost
Expand Down
1 change: 1 addition & 0 deletions AUTHORS
Expand Up @@ -6,6 +6,7 @@ tracker.

Rounak Agarwal (@agarwalrounak)
David Akinpelu (@DavidAkinpelu), Louisiana State University
Halla Ali (@hallaali)
Emil Atz (@EmilAtz)
Jongyoon Bae (@jongyoonbae), Brown University
Philip Berndt
Expand Down
3 changes: 2 additions & 1 deletion SConstruct
Expand Up @@ -813,7 +813,7 @@ else:
config.add(config_options)
toolchain = ["default"]

env = Environment(tools=toolchain+["textfile", "subst", "recursiveInstall", "wix", "gch"],
env = Environment(tools=toolchain+["textfile", "subst", "recursiveInstall", "UnitsInterfaceBuilder", "wix", "gch"],
ENV={"PATH": os.environ["PATH"]},
toolchain=toolchain,
**extraEnvArgs)
Expand Down Expand Up @@ -1737,6 +1737,7 @@ elif env['python_package'] == 'n':

env['install_python_action'] = ''
env['python_module_loc'] = ''
env["python_module"] = None
env["ct_pyscriptdir"] = "<not installed>"

def check_module(name):
Expand Down
1 change: 1 addition & 0 deletions doc/example-keywords.txt
Expand Up @@ -41,5 +41,6 @@ thermodynamic cycle
thermodynamics
transport
tutorial
units
user-defined model
well-stirred reactor
6 changes: 3 additions & 3 deletions doc/sphinx/conf.py
Expand Up @@ -84,18 +84,18 @@ def escape_splats(app, what, name, obj, options, lines):
lines[i] = l.replace("*", r"\*")
app.connect('autodoc-process-docstring', escape_splats)


autoclass_content = 'both'

doxylink = {
'ct': (os.path.abspath('../../build/docs/Cantera.tag'),
'../../doxygen/html/')
'ct': (os.path.abspath('../../build/docs/Cantera.tag'),
'../../doxygen/html/')
}

intersphinx_mapping = {
'python': ('https://docs.python.org/3', None),
'pandas': ('https://pandas.pydata.org/pandas-docs/stable/', None),
'numpy': ('https://numpy.org/doc/stable/', None),
'pint': ('https://pint.readthedocs.io/en/stable/', None),
}

# Ensure that the primary domain is the Python domain, since we've added the
Expand Down
1 change: 1 addition & 0 deletions doc/sphinx/cython/index.rst
Expand Up @@ -15,4 +15,5 @@ Contents:
zerodim
onedim
constants
units
utilities
49 changes: 49 additions & 0 deletions doc/sphinx/cython/units.rst
@@ -0,0 +1,49 @@
.. py:currentmodule:: cantera.with_units

Python Interface With Units
===========================

This interface allows users to specify physical units associated with quantities.
To do so, this interface leverages the `pint <https://pint.readthedocs.io/en/stable/>`__
library to provide consistent unit conversion. Several examples of this interface can
be found in the ``samples/python`` folder in the
`root of the repository <https://github.com/Cantera/cantera/tree/main/samples/python>`__.
Examples that use this interface are suffixed with `_units`.

The overall goal is to provide a compatible implementation of the `cantera.Solution` and
`cantera.PureFluid` interfaces. Please see those pages for further documentation of the
available properties.

Solution with Units
-------------------

.. autoclass:: Solution
:no-members:
ischoegl marked this conversation as resolved.
Show resolved Hide resolved

PureFluid Phases With Units
---------------------------

The following convenience classes are available to create `PureFluid <PureFluid>`
objects with the indicated equation of state:

.. autoclass:: CarbonDioxide
:no-members:
.. autoclass:: Heptane
:no-members:
.. autoclass:: Hfc134a
:no-members:
.. autoclass:: Hydrogen
:no-members:
.. autoclass:: Methane
:no-members:
.. autoclass:: Nitrogen
:no-members:
.. autoclass:: Oxygen
:no-members:
.. autoclass:: Water
:no-members:

The full documentation for the `PureFluid <PureFluid>` class and its properties is here:

.. autoclass:: PureFluid
:no-members:
10 changes: 9 additions & 1 deletion interfaces/cython/SConscript
Expand Up @@ -3,6 +3,8 @@ import re
from pathlib import Path
from buildutils import *

from string import Template

Import('env', 'build', 'install')

localenv = env.Clone()
Expand Down Expand Up @@ -56,7 +58,7 @@ for pyxfile in multi_glob(localenv, "cantera", "pyx"):
cython_obj.append(obj)

copy_header = localenv.Command('#src/extensions/delegator.h', '#build/python/cantera/delegator.h',
Copy('$TARGET', '$SOURCE'))
Copy('$TARGET', '$SOURCE'))
ext_manager = localenv.SharedObject("#src/extensions/PythonExtensionManager.cpp")

cython_obj.extend(ext_manager)
Expand Down Expand Up @@ -107,6 +109,12 @@ for f in (multi_glob(localenv, 'cantera', 'py') +
multi_glob(localenv, 'cantera/*', 'py')):
localenv.Depends(mod, f)

units = localenv.UnitsInterfaceBuilder(
"cantera/with_units/solution.py",
"cantera/with_units/solution.py.in",
)
localenv.Depends(mod, units)

# Determine installation path and install the Python module
install_cmd = ["$python_cmd_esc", "-m", "pip", "install"]
user_install = False
Expand Down
2 changes: 1 addition & 1 deletion interfaces/cython/cantera/thermo.pyx
Expand Up @@ -1960,7 +1960,7 @@ cdef class PureFluid(ThermoPhase):
def __set__(self, Q):
if (self.P >= self.critical_pressure or
abs(self.P-self.P_sat)/self.P > 1e-4):
raise ValueError('Cannot set vapor quality outside the'
raise ValueError('Cannot set vapor quality outside the '
'two-phase region')
self.thermo.setState_Psat(self.P, Q)

Expand Down
12 changes: 12 additions & 0 deletions interfaces/cython/cantera/with_units/__init__.py
@@ -0,0 +1,12 @@
# This file is part of Cantera. See License.txt in the top-level directory or
# at https://cantera.org/license.txt for license and copyright information.

# This code to set the application registry has to come before any code that wants to
# use the registry is imported. In particular, it has to come before any of our code
# that uses units!
from pint import UnitRegistry, set_application_registry
cantera_units_registry = UnitRegistry()
set_application_registry(cantera_units_registry)

# Now we can import our code
from .solution import *