diff --git a/.github/workflows/cont_int.yml b/.github/workflows/cont_int.yml index c4103575..6def774a 100644 --- a/.github/workflows/cont_int.yml +++ b/.github/workflows/cont_int.yml @@ -1,181 +1,181 @@ name: CI on: - pull_request: - branches: - - main - types: [opened, synchronize, reopened, ready_for_review, review_requested] + push: + branches: + - '*' + pull_request: + branches: + - main + types: [opened, synchronize, reopened, ready_for_review, review_requested] + schedule: + - cron: '0 0 * * *' jobs: - build: - runs-on: ubuntu-latest - defaults: - run: - shell: bash -el {0} - - steps: - - name: Checkout T3 - uses: actions/checkout@v3 - - - name: Clean Ubuntu Image - uses: kfir4444/free-disk-space@main - with: - # This may remove tools actually needed - currently does not - tool-cache: true - android: true - dotnet: true - haskell: true - large-packages: true - swap-storage: true - - - name: Cache RMG - id: cache-rmg - uses: actions/cache@v2 - with: - path: RMG-Py - key: ${{ runner.os }}-rmg-main - restore-keys: | - ${{ runner.os }}-rmg- - - name: Debug RMG Cache - run: | - echo "cache hit: ${{ steps.cache-rmg.outputs.cache-hit }}" - - name: Checkout RMG - if: steps.cache-rmg.outputs.cache-hit != 'true' - uses: actions/checkout@v3 - with: - repository: ReactionMechanismGenerator/RMG-Py - path: RMG-Py - ref: main - fetch-depth: 1 - - - name: Cache RMG-database - id: cache-rmg-db - uses: actions/cache@v2 - with: - path: RMG-database - key: ${{ runner.os }}-rmgdb-main - restore-keys: | - ${{ runner.os }}-rmgdb- - - name: Checkout RMG-database - if: steps.cache-rmg-db.outputs.cache-hit != 'true' - uses: actions/checkout@v3 - with: - repository: ReactionMechanismGenerator/RMG-database - path: RMG-database - ref: main - fetch-depth: 1 + build: + runs-on: ubuntu-latest + defaults: + run: + shell: bash -el {0} + + steps: + - name: Checkout T3 + uses: actions/checkout@v3 + + - name: Clean Ubuntu Image + uses: kfir4444/free-disk-space@main + with: + # This may remove tools actually needed - currently does not + tool-cache: true + android: true + dotnet: true + haskell: true + large-packages: true + swap-storage: true + + - name: Cache RMG-Py + id: cache-rmg-py + uses: actions/cache@v2 + with: + path: RMG-Py + key: ${{ runner.os }}-rmg-main + restore-keys: | + ${{ runner.os }}-rmg- + + - name: Checkout RMG-py + if: steps.cache-rmg-py.outputs.cache-hit != 'true' + uses: actions/checkout@v3 + with: + repository: ReactionMechanismGenerator/RMG-Py + path: RMG-Py + ref: main + fetch-depth: 1 + + - name: Cache RMG-database + id: cache-rmg-db + uses: actions/cache@v2 + with: + path: RMG-database + key: ${{ runner.os }}-rmgdb-main + restore-keys: | + ${{ runner.os }}-rmgdb- + + - name: Checkout RMG-database + if: steps.cache-rmg-db.outputs.cache-hit != 'true' + uses: actions/checkout@v3 + with: + repository: ReactionMechanismGenerator/RMG-database + path: RMG-database + ref: main + fetch-depth: 1 - - name: Cache ARC - id: cache-arc - uses: actions/cache@v2 - with: - path: ARC - key: ${{ runner.os }}-arc-main - restore-keys: | - ${{ runner.os }}-arc- - - name: Checkout ARC - if: steps.cache-arc.outputs.cache-hit != 'true' - uses: actions/checkout@v3 - with: - repository: ReactionMechanismGenerator/ARC - path: ARC - ref: main - fetch-depth: 1 - - - name: Cache Conda Packages - uses: actions/cache@v2 - env: - CACHE_NUMBER: 0 - with: - path: ~/conda_pkgs_dir - key: - ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-${{ hashFiles('environment.yml') }}-t3 - - - name: Setup RMG-Py Env - uses: conda-incubator/setup-miniconda@v3.0.1 - with: - miniforge-variant: Mambaforge - miniforge-version: latest - activate-environment: rmg_env - use-mamba: true - - - name: Cache RMG-Py env - uses: actions/cache@v2 - with: - path: ${{ env.CONDA }}/envs/rmg_env - key: - conda-${{ runner.os }}--${{ runner.arch }}-rmgpyenv-${{ env.CACHE_NUMBER}} - env: - # Increase this value to reset cache if etc/example-environment.yml has not changed - CACHE_NUMBER: 3 - id: cache-rmgpy-env - - name: Update environment - run: mamba env update -n rmg_env -f RMG-Py/environment.yml - if: steps.cache-rmgpy-env.outputs.cache-hit != 'true' - - - name: Cythonize RMG-Py - run: | - cd RMG-Py - conda activate rmg_env - make clean - make - echo "PYTHONPATH=$(pwd):$PYTHONPATH" >> $GITHUB_ENV - echo "PATH=$(pwd):$PATH" >> $GITHUB_ENV - echo "export rmgpy_path=$(pwd)" >> $GITHUB_ENV - echo "PYTHONPATH=$(pwd):$PYTHONPATH" >> ~/.bashrc - echo "PATH=$(pwd):$PATH" >> ~/.bashrc - echo "export rmgpy_path=$(pwd)" >> ~/.bashrc - - - name: Install RMS Julia - run: julia -e 'using Pkg; Pkg.add(PackageSpec(name="PyCall",rev="master"));Pkg.build("PyCall");Pkg.add(PackageSpec(name="ReactionMechanismSimulator",rev="main")); using ReactionMechanismSimulator;' - - - name: Install PyCall RMG_ENV - run: python -c "import julia; julia.install(); import diffeqpy; diffeqpy.install()" - - - name: Install ARC ENV - run: | - cd ARC - mamba env create -f environment.yml - conda activate arc_env - echo "export arc_path=$(pwd)" >> $GITHUB_ENV - echo "PYTHONPATH=$(pwd):$PYTHONPATH" >> $GITHUB_ENV - echo "PATH=$(pwd):$PATH" >> $GITHUB_ENV - echo "PYTHONPATH=$(pwd):$PYTHONPATH" >> ~/.bashrc - echo "PATH=$(pwd):$PATH" >> ~/.bashrc - echo "export arc_path=$(pwd)" >> ~/.bashrc - cd .. - - - name: Install xtb - run: | - mamba create -n xtb_env python=3.7 -c conda-forge -y - conda activate xtb_env - mamba install -c conda-forge xtb=6.3.3 -y - mamba install -c anaconda pyyaml -y - - - name: Install T3 - run: | - mamba env create -f environment.yml - - - name: Install CodeCov - run: | - conda activate t3_env - mamba install -c conda-forge codecov - mamba install -c conda-forge pytest-cov - - - name: Run T3 Tests - shell: bash -el {0} - run: | - source ~/.bashrc - conda activate t3_env - make test - codecov --token=${{ secrets.CODECOV_TOKEN }} - - - name: Code Coverage - uses: codecov/codecov-action@v3 - with: - token: ${{ secrets.CODECOV_TOKEN }} - file: ./coverage.xml - flags: unittests - name: codecov-umbrella - verbose: true - fail_ci_if_error: true + - name: Cache ARC + id: cache-arc + uses: actions/cache@v2 + with: + path: ARC + key: ${{ runner.os }}-arc-main + restore-keys: | + ${{ runner.os }}-arc- + + - name: Checkout ARC + if: steps.cache-arc.outputs.cache-hit != 'true' + uses: actions/checkout@v3 + with: + repository: ReactionMechanismGenerator/ARC + path: ARC + ref: no_ase + fetch-depth: 1 + + - name: Setup ARC paths + run: | + cd ARC + echo "PYTHONPATH=$(pwd):$PYTHONPATH" >> $GITHUB_ENV + echo "PATH=$(pwd):$PATH" >> $GITHUB_ENV + echo "export arc_path=$(pwd)" >> $GITHUB_ENV + echo "PYTHONPATH=$(pwd):$PYTHONPATH" >> ~/.bashrc + echo "PATH=$(pwd):$PATH" >> ~/.bashrc + echo "export arc_path=$(pwd)" >> ~/.bashrc + + - name: Cache Packages + uses: actions/cache@v2 + env: + CACHE_NUMBER: 0 + with: + path: ~/conda_pkgs_dir + key: + ${{ runner.os }}-conda-${{ env.CACHE_NUMBER }}-${{ hashFiles('environment.yml') }} + + - name: Setup ARC Env + uses: conda-incubator/setup-miniconda@v2 + with: + miniforge-variant: Mambaforge + miniforge-version: latest + activate-environment: arc_env + use-mamba: true + + - name: Cache RMG-Py env + uses: actions/cache@v2 + with: + path: ${{ env.CONDA }}/envs/rmg_env + key: + conda-${{ runner.os }}--${{ runner.arch }}-rmgpyenv-${{ env.CACHE_NUMBER}} + env: + # Increase this value to reset cache if etc/example-environment.yml has not changed + CACHE_NUMBER: 3 + id: cache-rmgpy-env + - name: Update environment + run: mamba env update -n rmg_env -f RMG-Py/environment.yml + if: steps.cache-rmgpy-env.outputs.cache-hit != 'true' + + - name: Cythonize RMG-Py + run: | + cd RMG-Py + conda activate rmg_env + git fetch origin no_qm + git checkout no_qm + make clean + make + julia -e 'using Pkg; Pkg.add("PyCall");Pkg.build("PyCall");Pkg.add(PackageSpec(name="ReactionMechanismSimulator",rev="main")); using ReactionMechanismSimulator;' + python -c "import julia; julia.install(); import diffeqpy; diffeqpy.install()" + echo "PYTHONPATH=$(pwd):$PYTHONPATH" >> $GITHUB_ENV + echo "PATH=$(pwd):$PATH" >> $GITHUB_ENV + echo "export rmgpy_path=$(pwd)" >> $GITHUB_ENV + echo "PYTHONPATH=$(pwd):$PYTHONPATH" >> ~/.bashrc + echo "PATH=$(pwd):$PATH" >> ~/.bashrc + echo "export rmgpy_path=$(pwd)" >> ~/.bashrc + + - name: Install xtb + run: | + mamba create -n xtb_env python=3.7 -c conda-forge -y + conda activate xtb_env + mamba install -c conda-forge xtb=6.3.3 -y + mamba install -c anaconda pyyaml -y + + - name: Install T3 + run: | + mamba env create -f environment.yml + + - name: Install CodeCov + run: | + conda activate t3_env + mamba install -c conda-forge codecov + mamba install -c conda-forge pytest-cov + + - name: Run T3 Tests + shell: bash -el {0} + run: | + source ~/.bashrc + conda activate t3_env + make test + codecov --token=${{ secrets.CODECOV_TOKEN }} + + - name: Code Coverage + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: ./coverage.xml + flags: unittests + name: codecov-umbrella + verbose: true + fail_ci_if_error: true diff --git a/environment.yml b/environment.yml index 39864b76..d1676669 100644 --- a/environment.yml +++ b/environment.yml @@ -1,41 +1,64 @@ name: t3_env channels: + - defaults + - rmg - conda-forge + - cantera + - anaconda dependencies: - - python=3.7 - - pydot - - cantera=2.6 - - ca-certificates - - openssl - - ipython - - pyyaml - - rdkit >=2022.09.1 - - quantities >=0.13.0 - - certifi - - rmg::pyrdl - - scipy >=1.7.3 - - mkl - - scikit-learn >=1.0.2 - - mpmath >=1.3.0 + - cairo + - cairocffi + - cantera::cantera=2.6 + - conda-forge::cclib >=1.7.0 + - rmg::chemprop - coolprop - - rmg::pydqed + - coverage + - cython >=0.25.2 + - ffmpeg + - rmg::gprof2dot + - graphviz + - h5py + - jinja2 + - jupyter + - rmg::lpsolve55 + - markupsafe + - matplotlib >=1.5 + - conda-forge::mopac + - mpmath + - rmg::muq2 + - networkx + - rmg::numdifftools + - numpy==1.20.1 + - conda-forge::openbabel >= 3 + - pandas - psutil - - rmg::pydas - - cclib >=1.7.2 - - openbabel >=3.1.1 - - lpsolve55 - - numdifftools >=0.9.41 - - qcelemental >=0.25.1 - - paramiko - - py3dmol - - numpy >=1.21.6 - - ase + - rmg::pydas >=1.0.2 + - pydot + - rmg::pydqed >=1.0.1 + - pymongo + - pyparsing + - rmg::pyrdl + - python >=3.7 + - pyyaml + - rmg::quantities + - rmg::rdkit >=2020.03.3.0 + - scikit-learn + - scipy + - rmg::symmetry + - xlrd - xlwt - - networkx + - anaconda::sphinx_rtd_theme + - anaconda::paramiko >=2.6.0 + - conda-forge::py3dmol >= 0.8.0 + - conda-forge::ase >=3.15.0, <=3.22.1 + - anaconda::ipython + - anaconda::sphinx + - anaconda::sphinxcontrib-jsmath + - conda-forge::qcelemental - mako - - pytest - - rmg::symmetry - - matplotlib + - pytables + - anaconda::pytest + - conda-forge::pytest-cov - mkdocs-material >=5.1.7 - mkdocs-material-extensions - mock diff --git a/tests/test_fix_cantera.py b/tests/test_fix_cantera.py deleted file mode 100644 index 891440d4..00000000 --- a/tests/test_fix_cantera.py +++ /dev/null @@ -1,170 +0,0 @@ -#!/usr/bin/env python3 -# encoding: utf-8 - -""" -t3 tests test_flux module -""" - -import os -import shutil - -from t3.common import t3_path, DATA_BASE_PATH -from tests.common import copy_model -import t3.utils.fix_cantera as fix - - -def test_fix_cantera_1(): - """Test fixing a Cantera file, case 1.""" - model_path = os.path.join(DATA_BASE_PATH, 'models', 'dups', '1_test_fix_cantera.yaml') - shutil.copyfile(os.path.join(DATA_BASE_PATH, 'models', 'dups', '1.yaml'), model_path) - done = fix.fix_cantera(model_path) - assert done is True - os.remove(model_path) - os.remove(model_path + '.bak') - - -def test_fix_cantera_2(): - """Test fixing a Cantera file, case 2.""" - model_path = os.path.join(DATA_BASE_PATH, 'models', 'dups', '2_test_fix_cantera.yaml') - shutil.copyfile(os.path.join(DATA_BASE_PATH, 'models', 'dups', '2.yaml'), model_path) - done = fix.fix_cantera(model_path) - assert done is True - os.remove(model_path) - os.remove(model_path + '.bak') - - -def test_fix_cantera_NH3(): - """Test fixing a Cantera file, NH3 case.""" - model_path = os.path.join(DATA_BASE_PATH, 'models', 'dups', 'NH3_test_fix_cantera.yaml') - shutil.copyfile(os.path.join(DATA_BASE_PATH, 'models', 'dups', 'NH3.yaml'), model_path) - done = fix.fix_cantera(model_path) - assert done is True - os.remove(model_path) - os.remove(model_path + '.bak') - - -def test_fix_undeclared_duplicate_reactions(): - """Test fixing undeclared duplicate reactions.""" - model_path_1 = os.path.join(DATA_BASE_PATH, 'models', 'dups', '1_test_fix_undeclared_duplicate_reactions.yaml') - shutil.copyfile(os.path.join(DATA_BASE_PATH, 'models', 'dups', '1.yaml'), model_path_1) - tb_1 = fix.get_traceback(model_path_1) - model_path_2 = copy_model(os.path.join(DATA_BASE_PATH, 'models', 'dups', '1.yaml')) - fix.fix_undeclared_duplicate_reactions(model_path_2, tb_1) - tb = fix.get_traceback(model_path_2) - assert tb is None - os.remove(model_path_1) - os.remove(model_path_2) - - -def test_get_traceback(): - """Test getting a traceback.""" - model_path = os.path.join(DATA_BASE_PATH, 'models', 'HOCHO.yaml') - tb = fix.get_traceback(model_path) - assert tb is None - - model_path = copy_model(os.path.join(DATA_BASE_PATH, 'models', 'dups', '1.yaml'), name='C') - shutil.copyfile(os.path.join(DATA_BASE_PATH, 'models', 'dups', '1.yaml'), model_path) - tb = fix.get_traceback(model_path) - expected_tb = f"""in get_traceback - ct.Solution(model_path) - File "build/python/cantera/base.pyx", line 71, in cantera._cantera._SolutionBase.__cinit__ - File "build/python/cantera/base.pyx", line 128, in cantera._cantera._SolutionBase._cinit - File "build/python/cantera/base.pyx", line 215, in cantera._cantera._SolutionBase._init_yaml -cantera._cantera.CanteraError: -******************************************************************************* -InputFileError thrown by Kinetics::checkDuplicates: -Error on lines 72 and 87 of {t3_path}/tests/data/models/dups/temp_C_1.yaml: -Undeclared duplicate reactions detected: -Reaction 2: 2 HNO(63) <=> 2 HNO(T)(117) -Reaction 1: HNO(T)(117) <=> HNO(63) - -| Line | -| 67 | note: Epsilon & sigma estimated with Tc=544.31 K, Pc=43.8 bar (from -| 68 | Joback method) -| 69 | note: HNO(T)(117) -| 70 | -| 71 | reactions: -> 72 > - equation: HNO(63) + HNO(63) <=> HNO(T)(117) + HNO(T)(117) # Reaction 515 - ^ -| 73 | type: Chebyshev -| 74 | temperature-range: [500.0, 1600.0] -| 75 | pressure-range: [0.099 atm, 98.692 atm] -... -| 82 | - [8.737e-04, -2.09e-10, -1.281e-10, -6.01e-11] -| 83 | note: |- -| 84 | Reaction index: Chemkin #515; RMG #1957 -| 85 | PDep reaction: PDepNetwork #87 -| 86 | Flux pairs: HNO(63), HNO(T)(117); HNO(63), HNO(T)(117); -> 87 > - equation: HNO(T)(117) <=> HNO(63) # Reaction 561 - ^ -| 88 | type: Chebyshev -| 89 | temperature-range: [500.0, 1600.0] -| 90 | pressure-range: [0.099 atm, 98.692 atm] -******************************************************************************* - -""" - assert expected_tb in tb - os.remove(model_path) - - model_path = copy_model(os.path.join(DATA_BASE_PATH, 'models', 'dups', '2.yaml'), name='B') - tb = fix.get_traceback(model_path) - expected_tb = f"""in get_traceback - ct.Solution(model_path) - File "build/python/cantera/base.pyx", line 71, in cantera._cantera._SolutionBase.__cinit__ - File "build/python/cantera/base.pyx", line 128, in cantera._cantera._SolutionBase._cinit - File "build/python/cantera/base.pyx", line 215, in cantera._cantera._SolutionBase._init_yaml -cantera._cantera.CanteraError: -******************************************************************************* -InputFileError thrown by Kinetics::checkDuplicates: -Error on line 149 of {t3_path}/tests/data/models/dups/temp_B_2.yaml: -No duplicate found for declared duplicate reaction number 0 (NH2O(93) + O2(3) <=> HNO(T)(117) + HO2(10)) -| Line | -| 144 | note: Epsilon & sigma estimated with Tc=544.31 K, Pc=43.8 bar (from -| 145 | Joback method) -| 146 | note: HNO(T)(117) -| 147 | -| 148 | reactions: -> 149 > - equation: O2(3) + NH2O(93) <=> HO2(10) + HNO(T)(117) # Reaction 503 - ^ -| 150 | duplicate: true -| 151 | rate-constant: {{A: 4429.0, b: 2.578, Ea: 29.877}} -| 152 | note: |- -******************************************************************************* - -""" - assert expected_tb in tb - os.remove(model_path) - - -def test_get_dup_rxn_indices(): - """Test getting the reaction indices from the traceback.""" - model_path = copy_model(os.path.join(DATA_BASE_PATH, 'models', 'HOCHO.yaml')) - tb = fix.get_traceback(model_path) - rxns = fix.get_dup_rxn_indices(tb) - assert rxns == [] - os.remove(model_path) - - model_path = copy_model(os.path.join(DATA_BASE_PATH, 'models', 'dups', '1.yaml')) - tb = fix.get_traceback(model_path) - rxns = fix.get_dup_rxn_indices(tb) - assert rxns == [2, 1] - os.remove(model_path) - - -def test_get_mistakenly_marked_dup_rxns(): - """Test getting the reaction indices from the traceback.""" - model_path = copy_model(os.path.join(DATA_BASE_PATH, 'models', 'HOCHO.yaml')) - tb = fix.get_traceback(model_path) - rxns = fix.get_mistakenly_marked_dup_rxns(tb) - assert rxns == [] - os.remove(model_path) - - tb = 'No duplicate found for declared duplicate reaction number 51 (NH2O(93) + O2(3) <=> HNO(T)(117) + HO2(10))' - rxns = fix.get_mistakenly_marked_dup_rxns(tb) - assert rxns == [51] - - model_path = copy_model(os.path.join(DATA_BASE_PATH, 'models', 'dups', '2.yaml'), name='A') - tb = fix.get_traceback(model_path) - rxns = fix.get_mistakenly_marked_dup_rxns(tb) - assert rxns == [0] - os.remove(model_path) diff --git a/tests/test_flux.py b/tests/test_flux.py deleted file mode 100644 index d5b62091..00000000 --- a/tests/test_flux.py +++ /dev/null @@ -1,516 +0,0 @@ -#!/usr/bin/env python3 -# encoding: utf-8 - -""" -t3 tests test_flux module -""" - -import os -import shutil - -import cantera as ct -import numpy as np -import pydot - -from t3.common import DATA_BASE_PATH, SCRATCH_BASE_PATH -import t3.utils.flux as flux -from tests.common import almost_equal - - -def test_generate_flux(): - """Test generating flux diagrams.""" - model_path = os.path.join(DATA_BASE_PATH, 'models', 'HOCHO.yaml') - folder_path = os.path.join(SCRATCH_BASE_PATH, 'test_generate_flux_HOCHO') - observables = ['H(3)', 'HOCO(10)'] - flux.generate_flux(model_path=model_path, - folder_path=folder_path, - observables=observables, - times=[0.001], - composition={'HOCHO(1)': 0.2, 'N2': 0.98}, - T=1200, - P=1, - reactor_type='JSR', - explore_tol=0.95, - dead_end_tol=0.10, - generate_separate_diagrams_per_observable=False, - report_flux_ratio=True, - display_concentrations=True, - display_r_n_p=True, - fix_cantera_model=False, - ) - for fig in ['H(3)_0.001_s.png', 'HOCO(10)_0.001_s.png']: - assert os.path.isfile(os.path.join(folder_path, 'bar_ROPs', fig)) - for ex in ['dot', 'png']: - assert os.path.isfile(os.path.join(folder_path, 'flux_diagrams', f'flux_diagram_0.001_s.{ex}')) - - flux.generate_flux(model_path=model_path, - folder_path=folder_path, - observables=observables, - times=[0.001], - composition={'HOCHO(1)': 0.2, 'N2': 0.98}, - T=1200, - P=1, - reactor_type='JSR', - explore_tol=0.95, - dead_end_tol=0.10, - generate_separate_diagrams_per_observable=True, - report_flux_ratio=True, - display_concentrations=True, - display_r_n_p=True, - fix_cantera_model=False, - ) - for observable in observables: - for ex in ['dot', 'png']: - assert os.path.isfile(os.path.join(folder_path, 'flux_diagrams', observable, f'flux_diagram_0.001_s.{ex}')) - - -def test_get_profiles_from_simulation(): - """Test getting profiles from a simulation.""" - profiles = flux.get_profiles_from_simulation(model_path=os.path.join(DATA_BASE_PATH, 'models', 'HOCHO.yaml'), - reactor_type='JSR', - times=[0.5, 5], - composition={'HOCHO(1)': 1.0}, - T=1000, - P=1, - ) - assert len(profiles.keys()) == 2 - - -def test_get_rxn_stoichiometry(): - """Test getting the stoichiometry of all species in all reactions""" - model_path = os.path.join(DATA_BASE_PATH, 'models', 'HOCHO.yaml') - gas = ct.Solution(model_path) - stoichiometry = flux.get_rxn_stoichiometry(gas) - assert all(s == 0 for s in stoichiometry['N2']) - assert len(stoichiometry['H2(4)']) == 3933 - assert stoichiometry['H2(4)'][0] == 1.0 - assert stoichiometry['H2(4)'].count(1.0) == 134 - assert stoichiometry['H2(4)'].count(0) == 3783 - assert stoichiometry['H2(4)'].count(-1.0) == 16 - assert len(stoichiometry['CO(8)']) == 3933 - assert stoichiometry['CO(8)'][0] == 0 - assert stoichiometry['CO(8)'].count(1.0) == 272 - assert stoichiometry['CO(8)'].count(0) == 3484 - assert stoichiometry['CO(8)'].count(-1.0) == 169 - - -def test_run_jsr(): - """Test getting ROPs from a JSR reactor""" - model_path = os.path.join(DATA_BASE_PATH, 'models', 'HOCHO.yaml') - gas = ct.Solution(model_path) - profiles = flux.run_jsr(gas=gas, times=[0.5, 5], composition={'HOCHO(1)': 1.0}, T=1000, P=1) - keys = list(profiles.keys()) - assert len(keys) == 2 - assert 0.01 < keys[0] < 2.0 - assert 2.0 < keys[1] < 20 - assert almost_equal(profiles[keys[0]]['P'], 1.0e5, places=2) - assert almost_equal(profiles[keys[1]]['P'], 1.0e5, places=2) - assert profiles[keys[0]]['T'] == 1000.0 - assert isinstance(profiles[keys[0]]['X'], dict) - assert almost_equal(profiles[keys[0]]['X']['CO(8)'], 7.53994e-6) - assert almost_equal(profiles[keys[0]]['X']['HOCHO(1)'], 0.99998358) - assert len(profiles[keys[0]]['X']) == 152 - assert len(profiles[keys[0]]['ROPs']) == 152 - assert len(profiles[keys[0]]['ROPs']['H(3)']) == 842 - - -def test_get_top_rops(): - """Test getting the top ROPs for the observables""" - obervables = ['spc1', 'spc3'] - profiles = {0.5: {'ROPs': {'spc1': {'R1': 0.1, 'R2': 0.0002, 'R3': 0.3, 'R4': 0.00006, 'R5': -1e-16, - 'R6': -9, 'R7': 1e-16, 'R8': 0.6, 'R9': -0.9, 'R10': 2, - 'R11': 1e-22, 'R12': 0.5, 'R13': 0.4, 'R14': 0.33, - 'R15': -1e-10, 'R16': -0.008, 'R17': 1e-5, }, - 'spc2': {'R1': 0.1, 'R2': 0.004, 'R3': 0.3, 'R4': 6e-5, 'R5': -1e-11}, - 'spc3': {'R1': 0.1, 'R2': 0.0002, 'R3': 0.3, 'R4': 6e-5, 'R5': -1e-9}}}, - 5: {'ROPs': {'spc1': {'R1': 0.5, 'R2': 0.008, 'R3': 0.3, 'R4': 6e-5, 'R5': -1e-16, - 'R6': -6e-5, 'R7': -4, 'R8': 0.6, 'R9': -0.9, 'R10': 2, - 'R11': 1e-9, 'R12': 0.5, 'R13': 0.4, 'R14': 0.33, - 'R15': -1e-8, 'R16': -0.008, 'R17': 0.00001, }, - 'spc2': {'R1': 0.1, 'R2': 4e-3, 'R3': 0.3, 'R4': 7e-5, 'R5': -1e-7}, - 'spc3': {'R1': 0.1, 'R2': 6e-4, 'R3': 0.3, 'R4': 6e-5, 'R5': -1e-7}}}} - top_rops = flux.get_top_rops(profiles=profiles, observables=obervables) - assert top_rops == {0.5: {'spc1': {'R6': -9, 'R10': 2, 'R9': -0.9, 'R8': 0.6, 'R12': 0.5, - 'R13': 0.4, 'R14': 0.33, 'R3': 0.3, 'R1': 0.1}, - 'spc3': {'R3': 0.3, 'R1': 0.1}}, - 5: {'spc1': {'R7': -4, 'R10': 2, 'R9': -0.9, 'R8': 0.6, 'R1': 0.5, - 'R12': 0.5, 'R13': 0.4, 'R14': 0.33, 'R3': 0.3, 'R2': 0.008}, - 'spc3': {'R3': 0.3, 'R1': 0.1, 'R2': 0.0006}}} - - -def test_generate_top_rop_bar_figs_1(): - """Test generating ROP bar figures for a dummy profile""" - profiles = {0.5: {'ROPs': {'spc1': {'R1': 0.1, 'R2': 0.0002, 'R3': 0.3, 'R4': 0.00006, 'R5': -1e-16, - 'R6': -9, 'R7': 1e-16, 'R8': 0.6, 'R9': -0.9, 'R10': 2, - 'R11': 1e-22, 'R12': 0.5, 'R13': 0.4, 'R14': 0.33, - 'R15': -1e-10, 'R16': -0.008, 'R17': 1e-5, }, - 'spc2': {'R1': 0.1, 'R2': 0.004, 'R3': 0.3, 'R4': 6e-5, 'R5': -1e-11}, - 'spc3': {'HO2(5) + CO(7) <=> OH(4) + CO2(8)': 0.1, 'OH(4) + CO(7) <=> HOCO(9)': 0.0002, - 'OH(4) + CO(7) <=> OCHO(10)': 0.3, 'CH2O(11) (+M) <=> H2(3) + CO(7) (+M)': 6e-5, - 'H(2) + CH2O(11) <=> H(2) + H2(3) + CO(7)': -1e-9}}}, - 5: {'ROPs': {'spc1': {'R1': 0.5, 'R2': 0.008, 'R3': 0.3, 'R4': 6e-5, 'R5': -1e-16, - 'R6': -6e-5, 'R7': -4, 'R8': 0.6, 'R9': -0.9, 'R10': 2, - 'R11': 1e-9, 'R12': 0.5, 'R13': 0.4, 'R14': 0.33, - 'R15': -1e-8, 'R16': -0.008, 'R17': 0.00001, }, - 'spc2': {'R1': 0.1, 'R2': 4e-3, 'R3': 0.3, 'R4': 7e-5, 'R5': -1e-7}, - 'spc3': {'R1': 0.1, 'R2': 6e-4, 'R3': 0.3, 'R4': 6e-5, 'R5': -1e-7}}}} - observables = ['spc1', 'spc3'] - folder_path = os.path.join(SCRATCH_BASE_PATH, 'test_generate_top_rop_bar_figs_dummy') - flux.generate_top_rop_bar_figs(profiles=profiles, observables=observables, folder_path=folder_path) - for fig in ['spc1_0.5_s.png', 'spc1_5_s.png', 'spc3_0.5_s.png', 'spc3_5_s.png']: - assert os.path.isfile(os.path.join(folder_path, 'bar_ROPs', fig)) - - -def test_generate_top_rop_bar_figs_2(): - """Test generating ROP bar figures for formic acid pyrolysis""" - observables = ['HOCHO(1)', 'CO2(9)'] - times = [0.001] - profiles = flux.get_profiles_from_simulation(model_path=os.path.join(DATA_BASE_PATH, 'models', 'HOCHO.yaml'), - reactor_type='JSR', - times=times, - composition={'HOCHO(1)': 1.0}, - T=1000, - P=1, - ) - folder_path = os.path.join(SCRATCH_BASE_PATH, 'test_generate_top_rop_bar_figs_HOCHO_pyrolysis') - flux.generate_top_rop_bar_figs(profiles=profiles, observables=observables, folder_path=folder_path) - for fig in ['HOCHO(1)_0.001_s.png', 'CO2(9)_0.001_s.png']: - assert os.path.isfile(os.path.join(folder_path, 'bar_ROPs', fig)) - - -def test_create_digraph_HOCHO_pyrolysis(): - """Test creating a flux diagram of formic acid pyrolysis""" - observables = ['HOCHO(1)', 'CO2(9)'] - times = [0.001, 0.5] - profiles = flux.get_profiles_from_simulation(model_path=os.path.join(DATA_BASE_PATH, 'models', 'HOCHO.yaml'), - reactor_type='JSR', - times=times, - composition={'HOCHO(1)': 1.0}, - T=1000, - P=1, - ) - for i, (time, profile) in enumerate(profiles.items()): - flux_graph, nodes_to_explore, min_rop, max_rop = flux.get_flux_graph(profile=profile, observables=observables) - folder_path = os.path.join(SCRATCH_BASE_PATH, 'test_create_digraph_HOCHO_pyrolysis') - flux.create_digraph(flux_graph=flux_graph, - profile=profile, - observables=observables, - nodes_to_explore=nodes_to_explore, - time=time, - min_rop=min_rop, - max_rop=max_rop, - folder_path=folder_path, - ) - assert os.path.isfile(os.path.join(folder_path, f'flux_diagram_{times[i]}_s.dot')) - assert os.path.isfile(os.path.join(folder_path, f'flux_diagram_{times[i]}_s.png')) - - -def test_create_digraph_NH3(): - """Test creating a flux diagram of ammonia oxidation""" - observables = ['NH3(1)'] - profiles = flux.get_profiles_from_simulation(model_path=os.path.join(DATA_BASE_PATH, 'models', 'NH3.yaml'), - reactor_type='JSR', - times=[1e-2], - composition={'NH3(1)': 1.0, 'O2(3)': 0.75, 'N2(2)': 5.65}, - T=1500, - P=10, - ) - for time, profile in profiles.items(): - flux_graph, nodes_to_explore, min_rop, max_rop = flux.get_flux_graph(profile=profile, observables=observables) - folder_path = os.path.join(SCRATCH_BASE_PATH, 'test_create_digraph_NH3') - flux.create_digraph(flux_graph=flux_graph, - profile=profile, - observables=observables, - nodes_to_explore=nodes_to_explore, - time=1e-2, - min_rop=min_rop, - max_rop=max_rop, - folder_path=folder_path, - display_concentrations=False, - report_flux_ratio=False, - display_r_n_p=True, - ) - assert os.path.isfile(os.path.join(folder_path, 'flux_diagram_0.01_s.png')) - - -def test_create_digraph_N2H4(): - """Test creating a flux diagram of ammonia oxidation""" - observables = ['H4N2(1)'] - profiles = flux.get_profiles_from_simulation(model_path=os.path.join(DATA_BASE_PATH, 'models', 'N2H4.yaml'), - reactor_type='JSR', - times=[0.05], - composition={'H4N2(1)': 1}, - T=700, - P=0.001, - ) - for time, profile in profiles.items(): - flux_graph, nodes_to_explore, min_rop, max_rop = flux.get_flux_graph(profile=profile, observables=observables) - folder_path = os.path.join(SCRATCH_BASE_PATH, 'test_create_digraph_N2H4') - flux.create_digraph(flux_graph=flux_graph, - profile=profile, - observables=observables, - nodes_to_explore=nodes_to_explore, - time=0.005, - min_rop=min_rop, - max_rop=max_rop, - folder_path=folder_path, - display_concentrations=True, - report_flux_ratio=True, - display_r_n_p=True, - ) - assert os.path.isfile(os.path.join(folder_path, 'flux_diagram_0.005_s.png')) - - -def test_get_width(): - """Test getting the node or edge width for a given concentration or ROP value.""" - for x in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]: - assert almost_equal(flux.get_width(x=x, x_min=0, x_max=10, log_scale=False), 0.38 * x + 0.2) - assert almost_equal(flux.get_width(x=2, x_min=2, x_max=10, log_scale=False), 0.2) - assert almost_equal(flux.get_width(x=6, x_min=2, x_max=10, log_scale=False), 2.1) - assert almost_equal(flux.get_width(x=10, x_min=2, x_max=10, log_scale=False), 4) - - for x in [1e-12, 1e-10, 1e-8, 1e-6, 1e-4, 1e-2]: - assert almost_equal(flux.get_width(x=x, x_min=1e-12, x_max=1e-2, log_scale=True), 0.165 * np.log(x) + 4.76, places=2) - assert almost_equal(flux.get_width(x=1e-8, x_min=1e-8, x_max=1e-2, log_scale=True), 0.2) - assert almost_equal(flux.get_width(x=1e-5, x_min=1e-8, x_max=1e-2, log_scale=True), 2.1, places=1) - assert almost_equal(flux.get_width(x=1e-2, x_min=1e-8, x_max=1e-2, log_scale=True), 4) - - assert almost_equal(flux.get_width(x=-1, x_min=2e-18, x_max=1, log_scale=True), 4) - assert almost_equal(flux.get_width(x=-0.089, x_min=2e-18, x_max=1, log_scale=True), 3.77, places=2) - - -def test_get_rxn_in_relevant_direction(): - """Test getting a reaction string in the direction where the species in one of the reactants.""" - rxn = 'HCO(12) (+M) <=> H(2) + CO(7) (+M)' - spc = 'HCO(12)' - new_rxn = flux.get_rxn_in_relevant_direction(rxn=rxn, spc=spc) - assert new_rxn == 'HCO(12) (+M) <=> H(2) + CO(7) (+M)' - spc = 'H(2)' - new_rxn = flux.get_rxn_in_relevant_direction(rxn=rxn, spc=spc) - assert new_rxn == 'H(2) + CO(7) (+M) <=> HCO(12) (+M)' - - rxn = 'HO2(5) + CO2(8) <=> O(18) + CHO3(765)' - spc = 'CHO3(765)' - new_rxn = flux.get_rxn_in_relevant_direction(rxn=rxn, spc=spc) - assert new_rxn == 'O(18) + CHO3(765) <=> HO2(5) + CO2(8)' - spc = 'CO2(8)' - new_rxn = flux.get_rxn_in_relevant_direction(rxn=rxn, spc=spc) - assert new_rxn == 'HO2(5) + CO2(8) <=> O(18) + CHO3(765)' - - -def test_get_node(): - """Test getting a node from a pydot graph or creating one.""" - graph = pydot.Dot(graph_type='digraph') - node_a = pydot.Node(name='Node A', style='filled', fillcolor='#DCE5F4') - node_b = pydot.Node(name='Node B') - node_c = pydot.Node(name='Node C') - node_d = pydot.Node(name='Node D') - graph.add_node(node_a) - graph.add_node(node_b) - graph.add_node(node_c) - graph.add_node(node_d) - graph.add_edge(pydot.Edge(node_a, node_b)) - graph.add_edge(pydot.Edge(node_b, node_c)) - graph.add_edge(pydot.Edge(node_c, node_d)) - nodes = {'Node A': node_a, - 'Node B': node_b, - 'Node C': node_c, - 'Node D': node_d} - for name, node in nodes.items(): - assert flux.get_node(graph=graph, label=name, nodes=nodes) == node - assert isinstance(flux.get_node(graph=graph, label='Node E', nodes=nodes), pydot.Node) - node_f = flux.get_node(graph=graph, label='Node F', nodes=nodes, observables=['Node F']) - assert isinstance(node_f, pydot.Node) - assert node_f.to_string() == '"Node F" [fillcolor="#DCE5F4", fontsize=8, style=filled, xlabel=""];' - - -def test_get_flux_graph(): - """Test getting a normalized flux profile and generating a flux graph.""" - profiles = flux.get_profiles_from_simulation(model_path=os.path.join(DATA_BASE_PATH, 'models', 'HOCHO.yaml'), - reactor_type='JSR', - times=[0.001, 5], - composition={'HOCHO(1)': 1.0}, - T=1000, - P=1, - ) - for i, (time, profile) in enumerate(profiles.items()): - flux_graph, nodes_to_explore, min_rop, max_rop = flux.get_flux_graph(profile=profile, observables=['HOCHO(1)', 'CO2(9)']) - if i == 0: - assert nodes_to_explore == {'CO(8)', 'H2O(17)', 'H2(4)'} - assert almost_equal(min_rop, 3.27e-21, ratio=100) - assert almost_equal(max_rop, 0.001326, places=5) - assert list(flux_graph.keys()) == ['CO2(9)', 'HOCHO(1)', 'H2(4)', 'H2O(17)', 'CO(8)'] - assert flux_graph['CO2(9)']['2 HOCO(10) <=> CO2(9) + HOCHO(1)'][0] == ['2 HOCO(10)'] - assert almost_equal(flux_graph['CO2(9)']['2 HOCO(10) <=> CO2(9) + HOCHO(1)'][1], -1.73922e-15, ratio=100) - all_rop_values = list() - for rxn_dict in flux_graph.values(): - for rxn, value in rxn_dict.items(): - all_rop_values.append(value[1]) - assert any(abs(v) == 1 for v in all_rop_values) - - profiles = flux.get_profiles_from_simulation(model_path=os.path.join(DATA_BASE_PATH, 'models', 'N2H4.yaml'), - reactor_type='JSR', - times=[0.05], - composition={'H4N2(1)': 1.0}, - T=1200, - P=1, - ) - for i, (time, profile) in enumerate(profiles.items()): - assert almost_equal(profile['P'], 1e5, places=2) # Pa - assert almost_equal(profile['T'], 1200) - assert len(profile['ROPs']) == 36 - flux_graph, nodes_to_explore, min_rop, max_rop = flux.get_flux_graph(profile=profile, observables=['H4N2(1)']) - if i == 0: - assert nodes_to_explore == {'H2(4)', '2 H3N2(6)', 'ammonia(9)', 'H(3)', 'H2N2(7)', '2 NH2(5)', - 'HN2(10)', 'N2(2)', 'NH2(5)', 'H3N2(6)'} - assert almost_equal(min_rop, 3.27e-21, ratio=100) - assert almost_equal(max_rop, 20.3659, places=3) - assert list(flux_graph.keys()) == ['H4N2(1)', 'NH2(5)', 'HN2(10)', 'H(3)', 'H2N2(7)', 'H2(4)', 'ammonia(9)', 'H3N2(6)'] - assert flux_graph['H4N2(1)']['H4N2(1) + NH2(5) <=> H3N2(6) + ammonia(9)'][0] == ['H3N2(6)', 'ammonia(9)'] - assert almost_equal(flux_graph['H4N2(1)']['H4N2(1) + NH2(5) <=> H3N2(6) + ammonia(9)'][1], -1.0) - all_rop_values = list() - for rxn_dict in flux_graph.values(): - for rxn, value in rxn_dict.items(): - all_rop_values.append(value[1]) - assert any(abs(v) == 1 for v in all_rop_values) - - -def test_get_opposite_rxn_species(): - """Test getting the species on the opposite side of a reaction.""" - rxn = 'HCO(12) (+M) <=> H(2) + CO(7) (+M)' - assert flux.get_opposite_rxn_species(rxn=rxn, spc='HCO(12)') == ['H(2)', 'CO(7)'] - assert flux.get_opposite_rxn_species(rxn=rxn, spc='H(2)') == ['HCO(12)'] - assert flux.get_opposite_rxn_species(rxn=rxn, spc='CO(7)') == ['HCO(12)'] - - rxn = 'HO2(5) + CO2(8) <=> O(18) + CHO3(765)' - assert flux.get_opposite_rxn_species(rxn=rxn, spc='HO2(5)') == ['O(18)', 'CHO3(765)'] - assert flux.get_opposite_rxn_species(rxn=rxn, spc='O(18)') == ['HO2(5)', 'CO2(8)'] - assert flux.get_opposite_rxn_species(rxn=rxn, spc='CHO3(765)') == ['HO2(5)', 'CO2(8)'] - - rxn = 'H(3) + HO2(6) + M <=> H2O2(18) + M' - assert flux.get_opposite_rxn_species(rxn=rxn, spc='HO2(6)') == ['H2O2(18)'] - assert flux.get_opposite_rxn_species(rxn=rxn, spc='H(3)') == ['H2O2(18)'] - assert flux.get_opposite_rxn_species(rxn=rxn, spc='H2O2(18)') == ['H(3)', 'HO2(6)'] - - rxn = 'HO2 + NO <=> NO2 + OH' - assert flux.get_opposite_rxn_species(rxn=rxn, spc='HO2') == ['NO2', 'OH'] - assert flux.get_opposite_rxn_species(rxn=rxn, spc='NO') == ['NO2', 'OH'] - assert flux.get_opposite_rxn_species(rxn=rxn, spc='NO2') == ['HO2', 'NO'] - assert flux.get_opposite_rxn_species(rxn=rxn, spc='OH') == ['HO2', 'NO'] - - -def test_count_species_in_well(): - """Test counting a species in a well""" - assert flux.count_species_in_well(well='H2O + H + H', spc='H2O') == 1 - assert flux.count_species_in_well(well='H2O + H + H', spc='H') == 2 - assert flux.count_species_in_well(well='H2O + H + H', spc='H2') == 0 - assert flux.count_species_in_well(well='HO2 + NO', spc='NO') == 1 - assert flux.count_species_in_well(well='NO2 + OH', spc='NO') == 0 - - -def test_get_other_reactants_and_products(): - """Test getting the reactants and products other than a given species.""" - rxn = 'HCO(12) (+M) <=> H(2) + CO(7) (+M)' - rs, ps = flux.get_other_reactants_and_products(rxn=rxn, spcs=['HCO(12)', 'H(2)']) - assert rs == '' - assert ps == '- CO(7)' - rs, ps = flux.get_other_reactants_and_products(rxn=rxn, spcs=['CO(7)', 'HCO(12)']) - assert rs == '+ H(2)' - assert ps == '' - rs, ps = flux.get_other_reactants_and_products(rxn=rxn, spcs=['H(2)', 'HCO(12)']) - assert rs == '+ CO(7)' - assert ps == '' - - rxn = 'OH(4) + HOCO(9) <=> H2O(13) + CO2(8)' - rs, ps = flux.get_other_reactants_and_products(rxn=rxn, spcs=['OH(4)', 'H2O(13)']) - assert rs == '+ HOCO(9)' - assert ps == '- CO2(8)' - rs, ps = flux.get_other_reactants_and_products(rxn=rxn, spcs=['CO2(8)', 'HOCO(9)']) - assert rs == '+ H2O(13)' - assert ps == '- OH(4)' - - rxn = 'H(2) + H(2) + M <=> H2(3) + M' - rs, ps = flux.get_other_reactants_and_products(rxn=rxn, spcs=['H(2)', 'H2(3)']) - assert rs == '' - assert ps == '' - rs, ps = flux.get_other_reactants_and_products(rxn=rxn, spcs=['H2(3)', 'H(2)']) - assert rs == '' - assert ps == '' - - rxn = 'H(2) + H(2) + H2(3) <=> H2(3) + H2(3)' - rs, ps = flux.get_other_reactants_and_products(rxn=rxn, spcs=['H(2)', 'H2(3)']) - assert rs == '' - assert ps == '' - rs, ps = flux.get_other_reactants_and_products(rxn=rxn, spcs=['H2(3)', 'H(2)']) - assert rs == '' - assert ps == '' - - rxn = 'O(18) + HOCHO(1) => OH(4) + OH(4) + CO(7)' - rs, ps = flux.get_other_reactants_and_products(rxn=rxn, spcs=['O(18)', 'OH(4)']) - assert rs == '+ HOCHO(1)' - assert ps == '- CO(7)' - rs, ps = flux.get_other_reactants_and_products(rxn=rxn, spcs=['HOCHO(1)', 'CO(7)']) - assert rs == '+ O(18)' - assert ps == '- OH(4) - OH(4)' - rs, ps = flux.get_other_reactants_and_products(rxn=rxn, spcs=['OH(4)', 'HOCHO(1)']) - assert rs == '+ CO(7)' - assert ps == '- O(18)' - rs, ps = flux.get_other_reactants_and_products(rxn=rxn, spcs=['CO(7)', 'O(18)']) - assert rs == '+ OH(4) + OH(4)' - assert ps == '- HOCHO(1)' - - rxn = 'CO2(8) + HOCHO(1) <=> 2 HOCO(9)' - rs, ps = flux.get_other_reactants_and_products(rxn=rxn, spcs=['CO2(8)', 'HOCO(9)']) - assert rs == '+ HOCHO(1)' - assert ps == '' - rs, ps = flux.get_other_reactants_and_products(rxn=rxn, spcs=['HOCO(9)', 'HOCHO(1)']) - assert rs == '' - assert ps == '- CO2(8)' - - -def test_unpack_stoichiometry(): - """Test unpacking stoichiometric coefficients from labels.""" - labels = ['2 A', 'B', '3 C'] - labels, multipliers = flux.unpack_stoichiometry(labels=labels) - assert labels == ['A', 'B', 'C'] - assert multipliers == [2, 1, 3] - - labels = ['2 HOCO(9)'] - labels, multipliers = flux.unpack_stoichiometry(labels=labels) - assert labels == ['HOCO(9)'] - assert multipliers == [2] - - -def test_continue_exploring(): - """Test determining whether to continue exploring a species based on its ROP""" - rops = {'R1': 1.0, - 'R2': 1e-6, - 'R3': 2.5, - 'R4': 1e-18, - 'R5': -1e-24} - assert flux.continue_exploring(rops) is False - rops = {'R1': 1.0, - 'R2': 1e-6, - 'R3': -2.5, - 'R4': 1e-18, - 'R5': -1e-24} - assert flux.continue_exploring(rops) is True - - -def test_almost_equal(): - """Test the almost_equal help function""" - assert almost_equal(1, 1) - assert not almost_equal(1, 2) - assert almost_equal(0.00010, 0.00013) - assert almost_equal(0.0010, 0.0013, places=3) - assert not almost_equal(0.0010, 0.0013) - assert almost_equal(1e-15, 1e-22) - assert not almost_equal(1e-15, 1e-22, places=16) - assert almost_equal(1, 2, ratio=10) - assert almost_equal(1e-5, 1e-6, ratio=100) - assert almost_equal(1e-6, 1e-5, ratio=100) - - -def teardown_module(): - """teardown any state that was previously setup with a setup_module method.""" - shutil.rmtree(SCRATCH_BASE_PATH, ignore_errors=True) diff --git a/tests/test_simulate_adapters/test_cantera_constantHP.py b/tests/test_simulate_adapters/test_cantera_constantHP.py deleted file mode 100644 index 3d2b8740..00000000 --- a/tests/test_simulate_adapters/test_cantera_constantHP.py +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/env python3 -# encoding: utf-8 - -""" -t3 tests test_cantera_constantHP module -""" - -import os -import shutil - -from t3.common import SIMULATE_DATA_BASE_PATH -from tests.common import run_minimal -from t3.simulate.cantera_constantHP import CanteraConstantHP - - -TEST_DIR = os.path.join(SIMULATE_DATA_BASE_PATH, 'cantera_simulator_test') - - -def test_set_up_no_sa(): - """ - Simulate RMG's minimal example without SA. By setting observable_list = list(), no SA is run. - """ - t3 = run_minimal(project_directory=TEST_DIR) - t3.set_paths() - cantera_simulator_adapter = CanteraConstantHP(t3=t3.t3, - rmg=t3.rmg, - paths=t3.paths, - logger=t3.logger, - atol=t3.rmg['model']['atol'], - rtol=t3.rmg['model']['rtol'], - observable_list=list(), - ) - cantera_simulator_adapter.simulate() - # check that there are over 20 time steps (as an arbitrary number) to indicate that the solver completed - time = cantera_simulator_adapter.all_data[0][0].data - assert len(time) > 20 - - -def test_get_sa_coefficients(): - """ - Simulate RMG's minimal example with SA. - Then run the `get_sa_coefficients()` method to test that Cantera correctly performed SA. - """ - t3 = run_minimal(project_directory=TEST_DIR) - t3.set_paths() - observable_list = ['OH', 'H'] - cantera_simulator_adapter = CanteraConstantHP(t3=t3.t3, - rmg=t3.rmg, - paths=t3.paths, - logger=t3.logger, - atol=t3.rmg['model']['atol'], - rtol=t3.rmg['model']['rtol'], - observable_list=observable_list, - sa_atol=t3.t3['sensitivity']['atol'], - sa_rtol=t3.t3['sensitivity']['rtol'], - ) - cantera_simulator_adapter.simulate() - sa_dict = cantera_simulator_adapter.get_sa_coefficients() - # check that there are over 20 time steps (as an arbitrary number) to indicate that the solver completed - assert len(sa_dict['time']) > 20 - # check that there are SA data for the 2 requested species - assert len(sa_dict['kinetics']) == 2 - assert len(sa_dict['thermo']) == 2 - - -def test_get_idt_by_T(): - """ - Calculate the ignition delay time for RMG's minimal example. Check that the dictionary found an idt. - """ - t3 = run_minimal(project_directory=TEST_DIR) - t3.set_paths() - cantera_simulator_adapter = CanteraConstantHP(t3=t3.t3, - rmg=t3.rmg, - paths=t3.paths, - logger=t3.logger, - atol=t3.rmg['model']['atol'], - rtol=t3.rmg['model']['rtol'], - observable_list=list(), - ) - cantera_simulator_adapter.simulate() - idt_dict = cantera_simulator_adapter.get_idt_by_T() - assert len(idt_dict['idt']) == 1 - assert len(idt_dict['idt_index']) == 1 - - -def test_find_equilibrium(): - """ - Find equilibrium mole fractions of RMG's minimal example. - """ - t3 = run_minimal(project_directory=TEST_DIR) - t3.set_paths() - cantera_simulator_adapter = CanteraConstantHP(t3=t3.t3, - rmg=t3.rmg, - paths=t3.paths, - logger=t3.logger, - atol=t3.rmg['model']['atol'], - rtol=t3.rmg['model']['rtol'], - observable_list=list(), - ) - cantera_simulator_adapter.conditions - equilibrium_dictionaries = cantera_simulator_adapter.find_equilibrium('TP') - assert len(equilibrium_dictionaries[0].keys()) == 8 - - -def test_get_t50(): - """ - Find half life of give species from RMG's minimal example. - """ - t3 = run_minimal(project_directory=TEST_DIR) - t3.set_paths() - cantera_simulator_adapter = CanteraConstantHP(t3=t3.t3, - rmg=t3.rmg, - paths=t3.paths, - logger=t3.logger, - atol=t3.rmg['model']['atol'], - rtol=t3.rmg['model']['rtol'], - observable_list=list(), - ) - cantera_simulator_adapter.simulate() - t50_list = cantera_simulator_adapter.get_t50('H2(1)') - assert len(t50_list) == 1 - - -def teardown_module(): - """ - A method that is run after all unit tests in this class. - Delete all project directories created during these unit tests - """ - log_archive = os.path.join(TEST_DIR, 'log_archive') - dirs = [log_archive] - for dir in dirs: - if os.path.isdir(dir): - shutil.rmtree(dir, ignore_errors=True) - files = [os.path.join(TEST_DIR, 't3.log')] - for file in files: - if os.path.isfile(file): - os.remove(file) diff --git a/tests/test_simulate_adapters/test_cantera_constantTP.py b/tests/test_simulate_adapters/test_cantera_constantTP.py deleted file mode 100755 index d363ea03..00000000 --- a/tests/test_simulate_adapters/test_cantera_constantTP.py +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/env python3 -# encoding: utf-8 - -""" -t3 tests test_cantera_constantTP module -""" - -import os -import shutil - -from t3.common import SIMULATE_DATA_BASE_PATH -from tests.common import run_minimal -from t3.simulate.cantera_constantTP import CanteraConstantTP - - -TEST_DIR = os.path.join(SIMULATE_DATA_BASE_PATH, 'cantera_simulator_test') - - -def test_set_up_no_sa(): - """ - Simulate RMG's minimal example without SA. By setting observable_list = list(), no SA is run. - """ - t3 = run_minimal(project_directory=TEST_DIR) - t3.set_paths() - cantera_simulator_adapter = CanteraConstantTP(t3=t3.t3, - rmg=t3.rmg, - paths=t3.paths, - logger=t3.logger, - atol=t3.rmg['model']['atol'], - rtol=t3.rmg['model']['rtol'], - observable_list=list(), - ) - cantera_simulator_adapter.simulate() - # check that there are over 20 time steps (as an arbitrary number) to indicate that the solver completed - time = cantera_simulator_adapter.all_data[0][0].data - assert len(time) > 20 - - -def test_get_sa_coefficients(): - """ - Simulate RMG's minimal example with SA. - Then run the `get_sa_coefficients()` method to test that Cantera correctly performed SA. - """ - t3 = run_minimal(project_directory=TEST_DIR) - t3.set_paths() - observable_list = ['OH', 'H'] - cantera_simulator_adapter = CanteraConstantTP(t3=t3.t3, - rmg=t3.rmg, - paths=t3.paths, - logger=t3.logger, - atol=t3.rmg['model']['atol'], - rtol=t3.rmg['model']['rtol'], - observable_list=observable_list, - sa_atol=t3.t3['sensitivity']['atol'], - sa_rtol=t3.t3['sensitivity']['rtol'], - ) - cantera_simulator_adapter.simulate() - sa_dict = cantera_simulator_adapter.get_sa_coefficients() - # check that there are over 20 time steps (as an arbitrary number) to indicate that the solver completed - assert len(sa_dict['time']) > 20 - # check that there are SA data for the 2 requested species - assert len(sa_dict['kinetics']) == 2 - assert len(sa_dict['thermo']) == 2 - - -def test_get_idt_by_T(): - """ - Calculate the ignition delay time for RMG's minimal example. - Since this adapter simulates at constant T, this method returns a dictionary whose values are empty lists. - """ - t3 = run_minimal(project_directory=TEST_DIR) - t3.set_paths() - cantera_simulator_adapter = CanteraConstantTP(t3=t3.t3, - rmg=t3.rmg, - paths=t3.paths, - logger=t3.logger, - atol=t3.rmg['model']['atol'], - rtol=t3.rmg['model']['rtol'], - observable_list=list(), - ) - cantera_simulator_adapter.simulate() - idt_dict = cantera_simulator_adapter.get_idt_by_T() - assert len(idt_dict['idt']) == 0 - assert len(idt_dict['idt_index']) == 0 - - -def test_find_equilibrium(): - """ - Find equilibrium mole fractions of RMG's minimal example. - """ - t3 = run_minimal(project_directory=TEST_DIR) - t3.set_paths() - cantera_simulator_adapter = CanteraConstantTP(t3=t3.t3, - rmg=t3.rmg, - paths=t3.paths, - logger=t3.logger, - atol=t3.rmg['model']['atol'], - rtol=t3.rmg['model']['rtol'], - observable_list=list(), - ) - cantera_simulator_adapter.conditions - equilibrium_dictionaries = cantera_simulator_adapter.find_equilibrium('TP') - assert len(equilibrium_dictionaries[0].keys()) == 8 - - -def test_get_t50(): - """ - Find half life of give species from RMG's minimal example. - """ - t3 = run_minimal(project_directory=TEST_DIR) - t3.set_paths() - cantera_simulator_adapter = CanteraConstantTP(t3=t3.t3, - rmg=t3.rmg, - paths=t3.paths, - logger=t3.logger, - atol=t3.rmg['model']['atol'], - rtol=t3.rmg['model']['rtol'], - observable_list=list(), - ) - cantera_simulator_adapter.simulate() - t50_list = cantera_simulator_adapter.get_t50('H2(1)') - assert len(t50_list) == 1 - - -def teardown_module(): - """ - A method that is run after all unit tests in this class. - Delete all project directories created during these unit tests - """ - log_archive = os.path.join(TEST_DIR, 'log_archive') - dirs = [log_archive] - for dir in dirs: - if os.path.isdir(dir): - shutil.rmtree(dir, ignore_errors=True) - files = [os.path.join(TEST_DIR, 't3.log')] - for file in files: - if os.path.isfile(file): - os.remove(file) diff --git a/tests/test_simulate_adapters/test_cantera_constantUV.py b/tests/test_simulate_adapters/test_cantera_constantUV.py deleted file mode 100644 index 6a0576f9..00000000 --- a/tests/test_simulate_adapters/test_cantera_constantUV.py +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/env python3 -# encoding: utf-8 - -""" -t3 tests test_cantera_constantUV module -""" - -import os -import shutil - -from t3.common import SIMULATE_DATA_BASE_PATH -from tests.common import run_minimal -from t3.simulate.cantera_constantUV import CanteraConstantUV - - -TEST_DIR = os.path.join(SIMULATE_DATA_BASE_PATH, 'cantera_simulator_test') - - -def test_set_up_no_sa(): - """ - Simulate RMG's minimal example without SA. By setting observable_list = list(), no SA is run. - """ - t3 = run_minimal(project_directory=TEST_DIR) - t3.set_paths() - cantera_simulator_adapter = CanteraConstantUV(t3=t3.t3, - rmg=t3.rmg, - paths=t3.paths, - logger=t3.logger, - atol=t3.rmg['model']['atol'], - rtol=t3.rmg['model']['rtol'], - observable_list=list(), - ) - cantera_simulator_adapter.simulate() - # check that there are over 20 time steps (as an arbitrary number) to indicate that the solver completed - time = cantera_simulator_adapter.all_data[0][0].data - assert len(time) > 20 - - -def test_get_sa_coefficients(): - """ - Simulate RMG's minimal example with SA. - Then run the `get_sa_coefficients()` method to test that Cantera correctly performed SA. - """ - t3 = run_minimal(project_directory=TEST_DIR) - t3.set_paths() - observable_list = ['OH', 'H'] - cantera_simulator_adapter = CanteraConstantUV(t3=t3.t3, - rmg=t3.rmg, - paths=t3.paths, - logger=t3.logger, - atol=t3.rmg['model']['atol'], - rtol=t3.rmg['model']['rtol'], - observable_list=observable_list, - sa_atol=t3.t3['sensitivity']['atol'], - sa_rtol=t3.t3['sensitivity']['rtol'], - ) - cantera_simulator_adapter.simulate() - sa_dict = cantera_simulator_adapter.get_sa_coefficients() - # check that there are over 20 time steps (as an arbitrary number) to indicate that the solver completed - assert len(sa_dict['time']) > 20 - # check that there are SA data for the 2 requested species - assert len(sa_dict['kinetics']) == 2 - assert len(sa_dict['thermo']) == 2 - - -def test_get_idt_by_T(): - """ - Calculate the ignition delay time for RMG's minimal example. Check that the dictionary found an idt. - """ - t3 = run_minimal(project_directory=TEST_DIR) - t3.set_paths() - cantera_simulator_adapter = CanteraConstantUV(t3=t3.t3, - rmg=t3.rmg, - paths=t3.paths, - logger=t3.logger, - atol=t3.rmg['model']['atol'], - rtol=t3.rmg['model']['rtol'], - observable_list=list(), - ) - cantera_simulator_adapter.simulate() - idt_dict = cantera_simulator_adapter.get_idt_by_T() - assert len(idt_dict['idt']) == 1 - assert len(idt_dict['idt_index']) == 1 - - -def test_find_equilibrium(): - """ - Find equilibrium mole fractions of RMG's minimal example. - """ - t3 = run_minimal(project_directory=TEST_DIR) - t3.set_paths() - cantera_simulator_adapter = CanteraConstantUV(t3=t3.t3, - rmg=t3.rmg, - paths=t3.paths, - logger=t3.logger, - atol=t3.rmg['model']['atol'], - rtol=t3.rmg['model']['rtol'], - observable_list=list(), - ) - cantera_simulator_adapter.conditions - equilibrium_dictionaries = cantera_simulator_adapter.find_equilibrium('TP') - assert len(equilibrium_dictionaries[0].keys()) == 8 - - -def test_get_t50(): - """ - Find half life of give species from RMG's minimal example. - """ - t3 = run_minimal(project_directory=TEST_DIR) - t3.set_paths() - cantera_simulator_adapter = CanteraConstantUV(t3=t3.t3, - rmg=t3.rmg, - paths=t3.paths, - logger=t3.logger, - atol=t3.rmg['model']['atol'], - rtol=t3.rmg['model']['rtol'], - observable_list=list(), - ) - cantera_simulator_adapter.simulate() - t50_list = cantera_simulator_adapter.get_t50('H2(1)') - assert len(t50_list) == 1 - - -def teardown_module(): - """ - A method that is run after all unit tests in this class. - Delete all project directories created during these unit tests - """ - log_archive = os.path.join(TEST_DIR, 'log_archive') - dirs = [log_archive] - for dir in dirs: - if os.path.isdir(dir): - shutil.rmtree(dir, ignore_errors=True) - files = [os.path.join(TEST_DIR, 't3.log')] - for file in files: - if os.path.isfile(file): - os.remove(file)