All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
The keepachangelog package is used by the
release workflow to parse release entries in this file.
gcm.gani.decomposefor automatically decomposing a SMILES string into Gani first- and second-order groups with RDKit SMARTS patterns, returning a single-rowDataFrameof group counts.fl-decomp-smilescommand-line tool that decomposes SMILES strings (given directly with--smiles/--nameor from a CSV with--input) using the selected--method(currentlygani) and prints the counts or writes them to CSV with--out.fuellib.DEFAULT_DATA_DIRexposing the path of the bundledfuellib/datadirectory.- Tests comparing RDKit decompositions of the reference compounds with
refGani.csvand coveringfl-decomp-smiles.
- Automated Gani decompositions must be verified. For indene, the non-aromatic C=C bond is categorized as a
CHgroup.
- Updated naming consistencies in
data/. tutorials-basic.rst,tutorials-cli.rst,gcm.rst, andsourcecode.rstdocument automatic SMILES decomposition andfl-decomp-smiles.
Fuel.flash_pointfor component flash points, selecting the Alqaheem or Alibakhshi correlation viacorrelation(default"Alibakhshi").Fuel.mixture_freeze_point,Fuel.mixture_flash_point,Fuel.mixture_heat_of_combustion,Fuel.mixture_yield_sooting_index, andFuel.mixture_derived_cetane_numberwrappers around the correspondingcorrelate.mixturefunctions.Fuel.mixture_flash_pointselects the correlation viacorrelation(default"Alibakhshi") and the mixing rule viamixing_rule(default"Liaw").
- Breaking:
correlate.components.flash_point_alibashkiandcorrelate.mixture.flash_point_alibashkiwere renamed toflash_point_alibakhshito correct the spelling of Alibakhshi. fuelprops.rstdocuments the newFuelflash point, freeze point, heat of combustion, yield sooting index, and derived cetane number methods.
- Documentation builds now use Python 3.12 and retry package downloads, preventing failures caused by transient package-index connection resets.
correlate.mixture.heat_of_combustionnow converts component lower heating values to J/kg so the mixture result is returned in J/kg as documented; its return type is now annotated as a scalar quantity.
release.ymlnow validates that the release version exists inCHANGELOG.mdbefore proceeding with the release workflow.
- Actions updated to new versions to avoid deprecation warnings
- GitHub Releases created by
release.ymlnow use thev{version}title format, matching their generated tags.
- A maintainer-dispatched GitHub Actions release workflow (
release.yml) that validates the version and changelog, reruns tests, builds and verifies package artifacts, publishes to PyPI using trusted publishing, and creates the corresponding Git tag and GitHub release.
- Documented the maintainer-gated release process, including manual release PR preparation and the required GitHub and PyPI security configuration.
- Package distributions now automatically include every
fuellibsubpackage and the bundled fuel-data and GCM CSV resources required at runtime.
gcm.boehmwith accompanyingboehm.csvfor Boehm (2022) fusion entropy (dS_fus) parameters by hydrocarbon family (n-alkane,isoalkane,alkene,monocycloalkane,dicycloalkane,tricycloalkane,alkylbenzene,cycloaromatic,diaromatic).rdk.mol.has_fused_ringsandrdk.mol.count_aromatic_ringsfor structural analysis of molecules.flash_point_alqaheem,flash_point_alibashki, andlower_heating_valuetocorrelate.components.freeze_point_boehm,flash_point_alqaheem,flash_point_alibashki, andheat_of_combustiontocorrelate.mixture.- Baseline values for FreezePoint, FlashPoint, and HeatOfCombustion.
constants.gas_constant(ideal gas constant, R = 8.31446 J/(mol*K)).Fuel.YSIandFuel.DCNcached properties returning reference Yield Sooting Index and derived cetane number values; aValueErrorlisting the compounds is raised if any value is missing.yield_sooting_indexandderived_cetane_numbermixture correlations.Fuel.propData(aDataFrameofpropertiesData/{name}.csv, orNoneif no file exists),Fuel.gcData,Fuel.compoundsData(matchedrefCompounds.csvrows), andFuel.ganiDecomp(matchedrefGani.csvrows).refCompoundsPathandrefGaniPatharguments toFuel.__init__for supplying custom reference tables. If a file is not found infuelDataDir, a message is printed and the default file infuellib/datais used.- Private
fuellib._reference_dataloaders that resolve reference-table paths and merge bundled and custom compound/Gani reference data. - Cached properties
Fuel.Gf_stp,Fuel.dS_fus,Fuel.RD_coeffs(tuple ofrd_A,rd_B,rd_D), andFuel.phi, replacingFuel.get_propertylookups. .scratch/added to.gitignore.ruffrulesF401andF841to prevent unused imports and variables; existing violations were fixed automatically.- Documentation and references (
fuelprops.rst,gcm.rst,refs.bib) for the new freeze point, flash point, heat of combustion, yield sooting index, and derived cetane number correlations and for the reference data.
- Custom
refCompounds.csvandrefGani.csvfiles now augment the bundled reference tables rather than replace them. Custom compound rows override bundled rows with the same InChI; custom Gani rows override bundled rows with the sameReference Compound. TheCommon_Namecolumn inrefGani.csvwas renamed toReference Compound. propertiesData.csv files store Temperature vs. Value entries in individual rows rather than in a matrix format to enable non-Temperature dependent properties to be stored (e.g., "FreezePoint", "FlashPoint", ...) by setting Temp to "NaN".test_accuracy.pyandgenerate_baseline.pyupdated to respect this change;test_accuracy.pyimportsmethod_mapfrombaselinePredictions.generate_baselineso that the same methods are used to generate and test predictions, and reads known values asBaseline_Value - Baseline_Error(Baseline_Erroris prediction minus known).- Baseline predictions stored in
tests/baselinePredictions/mixture_baseline.csvrather than individual per-fuel files.
- Breaking: the fuel data layout was flattened.
fuellib/datanow directly containsgcData/,propertiesData/,refCompounds.csv,refGani.csv, andfuel_metadata.yaml(previously nested indata/fuelData/anddata/fuelData/groupDecompositionData/).gcData/{name}_init.csvrenamed togcData/{name}.csv; GCxGC files require aWeight %column and aReference Compoundand/orSMILEScolumn (GC-BinandPelePhysics Keyare optional).refCompounds.csvis now a single wide table (Family,Carbon Number,Reference Compound,SMILES, then{Property}_Value,_Error,_Units,_Source,_NotesforTc,Pc,Vc,Tm,Tb,Hf_STP,Hv_STP,Vm_STP,Omega,YSI, andDCN) replacingfuelData/refCompounds.csv(compound names, SMILES, and PelePhysics keys).groupDecompositionData/refCompounds.csvrenamed torefGani.csv; per-fuel decomposition files were removed. Each GCxGC row is matched torefCompounds.csvandrefGani.csvbyReference Compoundname (case-insensitive), then by the InChI of itsSMILES. AValueErrorlisting unmatched rows is raised otherwise.
- Breaking:
Fuel.__init__(name, fuelDataDir=None, refCompoundsPath=None, refGaniPath=None, *, useRefProperties=True);decompNamewas removed, the keyword-onlyuseRefPropertiesargument (defaultTrue) toggles the use of reference data, andfuelDataDiracceptsstr | Pathand defaults tofuellib/data;Fuel.fuelDataDiris now aPath.fuel_metadata.yamlis no longer read byFuel. - Breaking:
Fuel.Tc,Pc,Vc,Tm,Tb,Hf_stp(wasHf),Hv_stp,Vm_stp, andomegause reference values fromrefCompounds.csv(converted to the property's units) where available and fall back to the Gani prediction otherwise or whenuseRefProperties=False. These properties, along withGf_stp(wasGf),Cp_stp,Cp_B,Cp_C,Lv_stp,epsilonByKB, andsigma, are now lazily evaluated cached properties instead of being computed in__init__. Fuel.Y_0,Fuel.compounds,Fuel.smiles, andFuel.pelephysics_keysare attributes set at initialization;Fuel.compoundsnow contains the matched reference compound names (e.g.,n-heptane) instead of the GCxGC labels.gcm.boehm.dS_fusreads the hydrocarbon family fromfuel.compoundsData["Family"]instead of classifying molecules with RDKit.correlate.componentsandcorrelate.mixtureuseFuelattributes (Tb,phi,Hf_stp,Hv_stp,RD_coeffs,dS_fus) rather thanFuel.get_property.fl-plt-compandfl-plt-propsread measured data fromFuel.propData; the exporters use theGC-Bincolumn for compound names when it is present.fl-fuelslists fuels fromgcData/{name}.csv(previously*_init.csv);fuel_metadata.yamlis optional and only used for source information (decomp_nameandprops_dataentries were removed).tests/test_hc_identification.pyandtutorials/hefaBlends.pyupdated for the new data layout andFuelsignature.fuellib.get_fueldata_dir()and the exporters' default data directory now point tofuellib/data.fuellib.datais no longer a Python package; it is a plain data directory, and its layer was removed from the[tool.importlinter]contract.- Documentation (
tutorials-basic,tutorials-custom-fuels,fuelprops,gcm,sourcecode, exporter and CLI tutorials) and thecustomFuel.pyanddecompose_cg.pytutorials updated for the new data layout andFuelAPI. - Suppress non-critical
RDKitwarnings.
Fuel.get_property,Fuel.gcm_properties,Fuel.gani_decomp,Fuel.gcxgc_data,Fuel.inchi, and theFuel.fuelDataGcDir,fuelDataDecompDir,fuelDataPropsDir,groupDecompFile,gcxgcFile, andgcmTableFileattributes.fuellib.get_gcmtable_dirand thegcmTableDatadirectory (Gani coefficients are read fromfuellib/gcm/gani.csv).fuellib.get_fueldata_decomp_dir,fuellib.get_metadata_decomp_name,fuellib.get_metadata_props_data, and the-decomp/--fuel_decomp_name(fl-export-pele) and-decomp/--decomp_name(fl-plt-comp,fl-plt-props) options, along with thedecomp_nameargument ofplot_compositionandplot_mixture_properties.tests/get_pred_and_data.py; the accuracy tests and baseline generator readFuel.propDatadirectly.
fl-plt-comppasses numeric weight-fraction magnitudes to Pandas, avoiding aUnitStrippedWarningwhen building composition plots.import-lintercontract allowsfuellib.rdkto importfuellib.utils.- Updated
mixture_baseline.csvto includederived cetane number.
fuellib.correlatemodule for performing component- or mixture-wise correlations.- Algorithms from legacy definitions (e.g.
Fuel.density(...)) moved to appropriatecorrelationsubmodules; original API maintained by wrapping new definitions. comp_idxremoved from function parameters; retained inFuel.{function}for maintaining API.- Function names renamed to be more descriptive (no abbreviations, include equation author if available):
correlate.module.fully_typed_out_equation_name{_author}mixture_function_name->mixture.function_name(module name implicitly addsmixtureto function call).
- Algorithms from legacy definitions (e.g.
- Recent module additions to
importlintercontract.lint-importstask added topyproject.tomlandlefthook.yaml.
- Rules to
ruff.tomlenforcing code format quality:- INP001:
__init__.pyrequired in submodules. - I001: require organized import block.
- RUF022: "dunder" (
__all__) must be sorted. - F403: prohibit wildcard imports (
from module import *). - F405: prohibit names possibly fetched from wildcard imports.
- INP001:
Yiis an optional parameter infuellib.correlate.mixturefunctions; defaults tofuel.Y_0.correlate.mixturefunction strings withfunction(fuel, Yi, T, ...)->function(fuel, T, Yi, ...)to be consistent with function strings incorrelate.components(function(fuel, T, ...)) and ensure that optional parameters are listed after non-optional.
[tool.importlinter]now ignores imports underif TYPE_CHECKING: ....
fuellib.rdkmodule wrapping RDKit for molecule-level structural analysis and property calculations:rdk.molprovidesfrom_smiles()/smiles(),from_inchi()/inchi(),hill_formula(),atom_counts(),has_aromatic(),has_ring(),has_double_bond(),has_branch(), andmolecular_weight().Fuel.smiles,Fuel.rdkit_mols(cached RDKitMolobjects built fromFuel.smiles) for working with RDKittests/test_fuel.pycovering RDKit-backedFuel.nC,Fuel.nH,Fuel.MW, andFuel.formulasfor single- and multi-compound fuels.tests/test_accuracy.py::TestFuelMWAccuracyverifyingFuel.mean_molecular_weightagainst expected values forheptaneandposf10325.- Excluded
.venv/fromlefthookpre-commit checks.
- BREAKING:
Fuel.MW,Fuel.nC,Fuel.nH,Fuel.hc_type,Fuel.fam, andFuel.formulasare now derived from RDKit molecule parsing of each compound'sSMILESstring (viafuellib.rdk.mol) instead of from the Gani group-decomposition matrix (Nij) or thegani.MWGCM property, removing the need for hand-tuned alkyl/olefinic/aromatic group index ranges inFuel.__init__. - Added SMILES in
gcDataCSVs: (decane_init.csv,dodecane_init.csv,hefa-came_init.csv,hefa-mfat_init.csv,hefa-tall_init.csv,heptane-decane_init.csv,heptane_init.csv,jet-a_init.csv,posf10264_init.csv,posf10289_init.csv,posf10325_init.csv,posf11498_init.csv,posf4658_init.csv). - Fixed
tests/baselinePredictions/generate_baseline.pyto understand recent package changes.- Regenerated
baselinePredictionswith new values.
- Regenerated
- Increased minimum test coverage to 45% to prevent regression (PR coverage is at 47.28%).
- Individual test suites in the
ci.ymluse--no-covto prevent failing from module-level undercoverage.
- Individual test suites in the
Fuel.Nijattribute and thegani.MWGCM property (fuellib.gcm.gani.MW), superseded by RDKit-derivedFuel.MW.MWrow fromfuellib/gcm/gani.csv.
gcmmodule providing an extensible framework for Group Contribution Method (GCM) property predictions, decoupling property formulas fromFuel.core.PropertyProtocol: runtime-checkable protocol defining the(fuel: Fuel) -> types.Quantity1Dsignature required of any GCM property function.core.GCM: a named collection of property functions withregister_property(),list_property_fns(),get_property()(case-insensitive, raisesValueErrorlisting available properties on a miss),predict(), andpredict_all().core.GCMRegistry: class-level registry ofGCMinstances, withregister(),list_methods(), and case-insensitiveget_gcm().gcm.ganiimplementing the Constantinou-Gani (and extended) method: loads group-contribution coefficients fromgcm.gani.csvand registers 18 property functions (Tc,Pc,Vc,Tb,Tm,Hf,Gf,Hv_stp,omega,Vm_stp,Cp_stp,Cp_B,Cp_C,rd_A,rd_B,rd_D,alibakhshi_phi,MW) against aganiGCMRegistryentry, replacing formulas previously duplicated inline infuel.__init__.
fuel.gani_decomp()builds a fuel's group-decomposition matrix for the Gani method by reading the group decomposition file and validating that all offuel.compoundsare present (raisingValueErrorlisting any missing compounds).- Cached
fuel.gcm_propertiesproperty that pre-computes predictions from every registered GCM method (viaGCMRegistry) for aFuelinstance. fuel.get_property(method, property_name)for case-insensitive lookup of a GCM prediction fromfuel.gcm_properties, raisingKeyErrorif either the method or property is unregistered.tests/test_gcm.pycovering thegcmmodule (core.GCM,core.GCMRegistry, and allgcm.ganiproperty functions), including registration, error handling, and decomposition-matrix column resorting/partial-group-coverage behavior ingani._get_decomp(columns are reindexed to the canonical group order and any group missing from a fuel's decomposition is zero-filled instead of erroring).docs/gcm.rstdocumenting thegcmabstraction:core.PropertyProtocol,core.GCM, andcore.GCMRegistry; how theganimethod is registered on top of them; how to register new properties/methods; and the newfuel.gani_decomp(),fuel.gcm_properties, andfuel.get_property()members. Duplicates the GCM property table/equations fromfuelprops.rstfor convenience. Linked into the docs toctree (index.rst) and API listing (sourcecode.rst).taskipyfor shortcuts to commondevtasks.- Documentation for
development.rstpointing to developer-specific tools.
ruffnow selectsE501so the existingline-length = 88setting is actually enforced (previously configured but not checked).- Reduced line lengths to 88 in pre-existing violations, including reflowed
docstrings in
fuel.py.
- Renamed compound identifiers (not the
Compoundcolumn header) indecane.csv,dodecane.csv,hefa.csv,heptane.csv, andheptane-decane.csvto match the respective gcxgc names (e.g.NC10H22->n-C10) and dropped redundant annotations (e.g.C07-Isoparaffin (lower put as same)->C07-Isoparaffin). fuel.num_compoundsevaluates the length offuel.compounds.fuel.compounds/fuel.num_compoundsare now derived fromdf_gcxgc["Compound"]beforeNijis read, rather than from the decomposition file's shape.
- Unnecessary assignment of integers in
fuel.__init__for indexing NumPy arrays when determining families and hydrocarbon types (e.g.aromatics,branching,cyclos,olefinsand theirnum_*counterparts), in favor of inline slice bounds. - Check for number of columns (
num_groups/minimum first-order group count) in gani decomposition infuel.__init__made unnecessary by new methods. - Redundant computation of gani properties in
fuel.__init__(previously computed twice — once for validation, once for storage — now computed once via thegcmabstraction).
- Pint-backed unit support through the public
fuellib.Unitsregistry. PintScalarandPintArraytype aliases for unit-aware property values.- Pixi task automation (
fmt,lint,types,imports,test,pre-commit,docs-build,docs-clean) so common dev workflows run viapixi run <task>. - New dev dependencies:
ruff,ty,pytest-cov,lefthook,import-linter, anduvfor a faster local pip/venv workflow. keepachangelogdependency for maintaining thisCHANGELOG.mdin the Keep a Changelog format.- Lefthook pre-commit suite (
lefthook.yaml) runningfmt→lint→types→test→check-cleanon commit. Theimport-lintercheck is not yet wired into pre-commit since the layering contract (fuellib.fuel/fuellib.gcm/fuellib.comp) will fail broadly until the codebase is reorganized to match it; run it manually viapixi run importsin the meantime. - Coverage reporting via
pytest-cov, with a temporaryfail_under = 1threshold, to be raised as test coverage improves. - Function string type hints to definitions in the
fuelandconvertmodules.@overloaddecorators onconvertfunctions to ensure the proper types are tracked.
utils/module exportingtypesandUnitsto organize FuelLib utilities.ruff.tomlto thoroughly defineruffbehavior.Unitsclass wrapping quantity-providing dependencies, such aspintorunxt, based on their availability.sphinx-autodoc-typehintsto eliminate redundancy between function signatures and docstrings (not yet implemented).TypeAliasto type aliases intypesmodule.@overloaddecorators toutility.mixing_ruleto addresstyerrors.- Sphinx-parsable type annotations and docstrings to
Fuelattributes. - Templates defining
classandmoduledocumentation behavior.classtemplate separates attributes from methods and provides tables with links to each definition.moduletemplate provides a table of all methods in the module & links to each definition.
- Docstrings to all public modules.
- BREAKING: Fuel properties and temperature-dependent calculations now use Pint
Quantityvalues. Supply dimensional inputs with units and use.to(unit).magnitudeonly when serializing or plotting. - Updated property plotting, exporters, tutorials, tests, and baseline data for the unit-aware API.
- Converge exports now always use MKS units; the
-u/--unitsoption was removed. - The Converge
-m/--export-mixand Pele-m,-pp, and-psatoptions are action flags that are enabled by their presence. - Replaced Black with Ruff + ty:
ruff format/ruff checknow handle formatting and linting, andty checkhandles static type checking;fl-formatnow shells out toruff format. - Bumped
requires-pythonto>=3.12,<3.14(from>=3.8); CI now runs on Python 3.12. - CI's
Formattingjob (previouslypsf/black) now runsruff format --check,ruff check, andty check. - BREAKING:
fuellib.fuel.fuel->fuellib.fuel.Fuelto conform with PEP 8 naming conventions and prevent thefuel(module) vs.fuel(class) namespace clash. - Moved
Unitsto thetypesmodule to facilitate future optional dependencies. Arrayaliases no longer specify dtype to lax type checking and reduce size of type annotations in documents.ruff.tomlignoresdocs,cli,exporters,_data_locator, andtutorials.fuel.get_row()->fuel._get_row()to avoid documenting inner utility functions.
- Removed Black as a dev dependency.
- Redundant type hints in docstrings.
- Redundant attribute definitions on the
Fuelclass. test_source_docstringsin favor ofruffenforcing docstring rules.
- Pele exports now default
particles.dep_fuel_speciesto the emitted fuel-species names, including when-ppselects PelePhysics keys;-depcontinues to override those names. - Addressed 40+ Ruff linting errors across the codebase:
- B023: Fixed lambda variable binding in test loops by capturing loop variables with default parameters (15 fixes in
tests/test_api.py). - SIM102: Combined nested
ifstatements usingandoperator (7 fixes acrosstests/test_hc_identification.pyandtests/test_source_docstrings.py). - BLE001: Replaced overly broad
except Exceptionclauses with specific exception types (4 fixes infuellib/__init__.py,fuellib/exporters/pele.py,tests/test_exporters.py). - PLW1510: Added explicit
check=Falseargument tosubprocess.run()calls (2 fixes intests/test_exporters.py,tests/test_utilities.py). - RUF059: Prefixed unused unpacked variables with underscore (2 fixes in
tests/test_utilities.py). - DTZ005: Added timezone argument to
datetime.now()call infuellib/exporters/pele.py. - UP036: Updated outdated Python version check in
fuellib/_data_locator.py. - PLC0206: Fixed dictionary iteration to use
.items()intests/baselinePredictions/generate_baseline.py.
- B023: Fixed lambda variable binding in test loops by capturing loop variables with default parameters (15 fixes in
- Addressed 10+ ty typing errors across the codebase.
test_api.pynow takes a flexible approach to ensuring the user interface remains consistent across versions without enforcing overly strict rules.- Converted docstrings in
fuel,convert, andutilitymodules toGooglestyle (fromsphinx) to enableruffformatting and checking.docs/conf.pyupdated to parseGooglestyle docstrings.
- Ran
ruff check . --fixto auto-format simple violations (e.g., dictionary formatting, docstring empty lines, ...).
- New CLI commands:
fl-C2K,fl-K2C,fl-C2F,fl-F2C,fl-F2K,fl-K2F(temperature conversions),fl-eps2K(Lennard-Jones epsilon to characteristic temperature),fl-export-converge,fl-export-pele(CFD export),fl-plt-comp,fl-plt-props(plotting), andfl-fuels(list available fuels). fuellib/cli/subpackage containing all command-line tools.test_exporters.py: integration tests for export commands.test_utilities.pyandtest_hc_identification.py: unit tests for utility functions and hydrocarbon classification logic.
- Split monolithic
FuelLib.pyintoconstants.py,convert.py,utility.py, andfuel.py. - Renamed
sourcepackage tofuelliband addedpyproject.tomlfor distribution via pip and conda, with proper entry point configuration. - Switched to editable/development installs (
pip install -e .andpip install -e '.[dev]'). - Simplified CI exporter job from 8 individual steps to a single
test_exporters.pycall. - Updated
sourcecode.rstto reflect the new file organization. - Breaking: functions moved from the
fuellibnamespace to submodules:fl.C2K()→fl.convert.C2K(),fl.mixing_rule()→fl.utility.mixing_rule().fl.k_Bstill works, butfl.constants.k_Bis recommended.
- Fixed CSV file path in
fuelprops.rst:../../fuelData/→../fuellib/data/fuelData/. - Fixed GitHub Actions failures related to decomposition metadata.
- Fixed error handling for Jet A and cycloaromatic compounds.
- Feature 1
- Feature 2...
- Fix 1
- Fix 2...
- Change 1
- Change 2...