Chemicals#

class Chemicals(chemicals, cache=None)[source]#

Create a Chemicals object that contains Chemical objects as attributes.

Parameters:
  • chemicals (Iterable[str or Chemical]) –

    Strings should be one of the following [-]:
    • Name, in IUPAC form or common form or an alias registered in PubChem

    • InChI name, prefixed by ‘InChI=1S/’ or ‘InChI=1/’

    • InChI key, prefixed by ‘InChIKey=’

    • PubChem CID, prefixed by ‘PubChem=’

    • SMILES (prefix with ‘SMILES=’ to ensure smiles parsing)

    • CAS number

  • cache (bool, optional) – Whether or not to use cached chemicals.

Examples

Create a Chemicals object from chemical identifiers:

>>> from thermosteam import Chemicals
>>> chemicals = Chemicals(['Water', 'Ethanol'], cache=True)
>>> chemicals
Chemicals([Water, Ethanol])

All chemicals are stored as attributes:

>>> chemicals.Water, chemicals.Ethanol
(Chemical('Water'), Chemical('Ethanol'))

Chemicals can also be accessed as items:

>>> chemicals = Chemicals(['Water', 'Ethanol', 'Propane'], cache=True)
>>> chemicals['Ethanol']
Chemical('Ethanol')
>>> chemicals['Propane', 'Water']
[Chemical('Propane'), Chemical('Water')]

A Chemicals object can be extended with more chemicals:

>>> from thermosteam import Chemical
>>> Methanol = Chemical('Methanol')
>>> chemicals.append(Methanol)
>>> chemicals
Chemicals([Water, Ethanol, Propane, Methanol])
>>> new_chemicals = Chemicals(['Hexane', 'Octanol'], cache=True)
>>> chemicals.extend(new_chemicals)
>>> chemicals
Chemicals([Water, Ethanol, Propane, Methanol, Hexane, Octanol])

Chemical objects cannot be repeated:

>>> chemicals.append(chemicals.Water)
Traceback (most recent call last):
ValueError: Water already defined in chemicals
>>> chemicals.extend(chemicals['Ethanol', 'Octanol'])
Traceback (most recent call last):
ValueError: Ethanol already defined in chemicals

A Chemicals object can only contain Chemical objects:

>>> chemicals.append(10)
Traceback (most recent call last):
TypeError: only 'Chemical' objects can be appended, not 'int'

You can check whether a Chemicals object contains a given chemical:

>>> 'Water' in chemicals
True
>>> chemicals.Water in chemicals
True
>>> 'Butane' in chemicals
False

An attempt to access a non-existent chemical raises an UndefinedChemicalAlias error:

>>> chemicals['Butane']
Traceback (most recent call last):
UndefinedChemicalAlias: 'Butane'
copy()[source]#

Return a copy.

append(chemical)[source]#

Append a Chemical.

extend(chemicals)[source]#

Extend with more Chemical objects.

compile(skip_checks=False)[source]#

Cast as a CompiledChemicals object.

Parameters:

skip_checks (bool, optional) – Whether to skip checks for missing or invalid properties.

Warning

If checks are skipped, certain features in thermosteam (e.g. phase equilibrium) cannot be guaranteed to function properly.

Examples

Compile ethanol and water chemicals:

>>> import thermosteam as tmo
>>> chemicals = tmo.Chemicals(['Water', 'Ethanol'])
>>> chemicals.compile()
>>> chemicals
CompiledChemicals([Water, Ethanol])

Attempt to compile chemicals with missing properties:

>>> Substance = tmo.Chemical('Substance', search_db=False)
>>> chemicals = tmo.Chemicals([Substance])
>>> chemicals.compile()
Traceback (most recent call last):
RuntimeError: Substance is missing key thermodynamic properties
(V, S, H, Cn, Psat, Tb and Hvap); use the `<Chemical>.get_missing_properties()`
to check all missing properties

Compile chemicals with missing properties (skipping checks) and note how certain features do not work:

>>> chemicals.compile(skip_checks=True)
>>> tmo.settings.set_thermo(chemicals)
>>> s = tmo.Stream('s', Substance=10)
>>> s.rho
Traceback (most recent call last):
RuntimeError: No liquid molar volume method selected for
component with CASRN 'Substance'
class CompiledChemicals(chemicals, cache=None)[source]#

Create a CompiledChemicals object that contains Chemical objects as attributes.

Parameters:
  • chemicals (Iterable[str or Chemical]) –

    Strings should be one of the following [-]:
    • Name, in IUPAC form or common form or an alias registered in PubChem

    • InChI name, prefixed by ‘InChI=1S/’ or ‘InChI=1/’

    • InChI key, prefixed by ‘InChIKey=’

    • PubChem CID, prefixed by ‘PubChem=’

    • SMILES (prefix with ‘SMILES=’ to ensure smiles parsing)

    • CAS number

  • cache (optional) – Whether or not to use cached chemicals.

tuple#

All compiled chemicals.

Type:

tuple[Chemical]

size#

Number of chemicals.

Type:

int

IDs#

IDs of all chemicals.

Type:

tuple[str]

CASs#

CASs of all chemicals

Type:

tuple[str]

MW#

MWs of all chemicals.

Type:

1d ndarray

Hf#

Heats of formation of all chemicals.

Type:

1d ndarray

Hc#

Heats of combustion of all chemicals.

Type:

1d ndarray

vle_chemicals#

Chemicals that may have vapor and liquid phases.

Type:

tuple[Chemical]

lle_chemicals#

Chemicals that may have two liquid phases.

Type:

tuple[Chemical]

heavy_chemicals#

Chemicals that are only present in liquid or solid phases.

Type:

tuple[Chemical]

light_chemicals#

IDs of chemicals that are only present in gas phases.

Type:

tuple[Chemical]

Examples

Create a CompiledChemicals object from chemical identifiers

>>> from thermosteam import CompiledChemicals, Chemical
>>> chemicals = CompiledChemicals(['Water', 'Ethanol'], cache=True)
>>> chemicals
CompiledChemicals([Water, Ethanol])

All chemicals are stored as attributes:

>>> chemicals.Water, chemicals.Ethanol
(Chemical('Water'), Chemical('Ethanol'))

Note that because they are compiled, the append and extend methods do not work:

>>> Propane = Chemical('Propane', cache=True)
>>> chemicals.append(Propane)
Traceback (most recent call last):
TypeError: 'CompiledChemicals' object is read-only

You can check whether a Chemicals object contains a given chemical:

>>> 'Water' in chemicals
True
>>> chemicals.Water in chemicals
True
>>> 'Butane' in chemicals
False
compile(skip_checks=False)[source]#

Do nothing, CompiledChemicals objects are already compiled.

define_group(name, IDs, composition=None, wt=False)[source]#

Define a group of chemicals.

Parameters:
  • name (str) – Name of group.

  • IDs (List[str]) – IDs of chemicals in the group.

  • composition (List[float], optional) – Default composition of chemical group.

  • wt (bool, optional) – Whether composition is given by weight. Defaults to False.

Examples

Create a chemical group and get the index:

>>> import thermosteam as tmo
>>> chemicals = tmo.CompiledChemicals(['Water', 'Methanol', 'Ethanol'], cache=True)
>>> chemicals.define_group('Alcohol', ['Methanol', 'Ethanol'], composition=[0.5, 0.5])
>>> chemicals.get_index('Alcohol')
[1, 2]
>>> chemicals.get_index(('Water', 'Alcohol'))
[0, [1, 2]]

By defining a chemical group, you can conveniently use indexers to retrieve the total value of the group:

>>> # Single phase stream case
>>> tmo.settings.set_thermo(chemicals)
>>> s1 = tmo.Stream(ID='s1', Water=2)
>>> s1.imol['Alcohol']
0
>>> s1.imol['Methanol', 'Ethanol'] = [2., 1.]
>>> s1.imol['Water', 'Alcohol']
array([2., 3.])
>>> # Multi-phase stream case
>>> s2 = tmo.Stream(ID='s2', Water=2, Methanol=1, Ethanol=1)
>>> s2.vle(V=0.5, P=101325)
>>> s2.imol['Alcohol']
2.0
>>> s2.imol['l', 'Alcohol']
0.6793
>>> s2.imol['l', ('Water', 'Alcohol')]
array([1.321, 0.679])

Because groups are defined with a composition we can set values by groups as well:

>>> s1.imol['Alcohol'] = 3.
>>> s1.imol['Ethanol', 'Methanol']
array([1.5, 1.5])
>>> s1.imol['Water', 'Alcohol'] = [3., 1.]
>>> s1.imol['Water', 'Ethanol', 'Methanol']
array([3. , 0.5, 0.5])
>>> s2.imol['l', 'Alcohol'] = 1.
>>> s2.imol['l', ('Ethanol', 'Methanol')]
array([0.5, 0.5])

For SplitIndexer objects, which reflect the separation of chemicals in two streams, group names correspond to nested indexes (without a composition):

>>> # Create a split-indexer
>>> indexer = chemicals.isplit(0.7)
>>> indexer.show()
SplitIndexer:
 Water     0.7
 Methanol  0.7
 Ethanol   0.7
>>> # Normal index
>>> indexer['Alcohol'] = [0.50, 0.80] # Methanol and ethanol
>>> indexer['Alcohol']
array([0.5, 0.8])
>>> # Broadcasted index
>>> indexer['Alcohol'] = 0.9
>>> indexer['Alcohol']
array([0.9, 0.9])
>>> # Nested index
>>> indexer['Water', 'Alcohol'] = [0.2, [0.6, 0.7]]
>>> indexer['Water', 'Alcohol']
array([0.2, array([0.6, 0.7])], dtype=object)
>>> # Broadcasted and nested index
>>> indexer['Water', 'Alcohol'] = [0.2, 0.8]
>>> indexer['Water', 'Alcohol']
array([0.2, array([0.8, 0.8])], dtype=object)

This feature allows splits to be easily defined for groups of chemicals in BioSTEAM.

property chemical_groups: frozenset[str]#

All defined chemical groups.

refresh_constants()[source]#

Refresh constant arrays according to their chemical values, including the molecular weight, heats of formation, and heats of combustion.

get_combustion_reactions()[source]#

Return a ParallelReactions object with all defined combustion reactions.

Examples

>>> chemicals = CompiledChemicals(['H2O', 'Methanol', 'Ethanol', 'CO2', 'O2'], cache=True)
>>> rxns = chemicals.get_combustion_reactions()
>>> rxns.show()
ParallelReaction (by mol):
index  stoichiometry                     reactant    X[%]
[0]    Methanol + 1.5 O2 -> 2 H2O + CO2  Methanol  100.00
[1]    Ethanol + 3 O2 -> 3 H2O + 2 CO2   Ethanol   100.00
property formula_array#

An array describing the formulas of all chemicals. Each column is a chemical and each row an element. Rows are ordered by atomic number.

Examples

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Ethanol', 'Propane'], cache=True)
>>> chemicals.formula_array.sum(0)
array([ 3.,  9., 11.])
get_parsable_alias(ID)[source]#

Return an alias of the given chemical identifier that can be parsed by Python as a variable name

Parameters:

ID (str) – Chemical identifier.

Examples

Get parsable alias of 2,3-Butanediol:

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['2,3-Butanediol'], cache=True)
>>> chemicals.get_parsable_alias('2,3-Butanediol')
'C4H10O2'
get_parsable_synonym(ID)#

Return an alias of the given chemical identifier that can be parsed by Python as a variable name

Parameters:

ID (str) – Chemical identifier.

Examples

Get parsable alias of 2,3-Butanediol:

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['2,3-Butanediol'], cache=True)
>>> chemicals.get_parsable_alias('2,3-Butanediol')
'C4H10O2'
get_aliases(ID)[source]#

Return all aliases of a chemical.

Parameters:

ID (str) – Chemical identifier.

Examples

Get all aliases of water:

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water'], cache=True)
>>> aliases = chemicals.get_aliases('Water')
>>> aliases.sort()
>>> aliases
['7732-18-5', 'H2O', 'Water', 'oxidane', 'water']
get_synonyms(ID)#

Return all aliases of a chemical.

Parameters:

ID (str) – Chemical identifier.

Examples

Get all aliases of water:

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water'], cache=True)
>>> aliases = chemicals.get_aliases('Water')
>>> aliases.sort()
>>> aliases
['7732-18-5', 'H2O', 'Water', 'oxidane', 'water']
set_alias(ID, alias)[source]#

Set a new alias for a chemical.

Parameters:
  • ID (str) – Chemical identifier.

  • alias (str) – New identifier for chemical.

Examples

Set new alias for water:

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Ethanol'], cache=True)
>>> chemicals.set_alias('Water', 'H2O')
>>> chemicals.H2O is chemicals.Water
True

Note that you cannot use one alias for two chemicals:

>>> chemicals.set_alias('Ethanol', 'H2O')
Traceback (most recent call last):
ValueError: alias 'H2O' already in use by Chemical('Water')
set_synonym(ID, alias)#

Set a new alias for a chemical.

Parameters:
  • ID (str) – Chemical identifier.

  • alias (str) – New identifier for chemical.

Examples

Set new alias for water:

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Ethanol'], cache=True)
>>> chemicals.set_alias('Water', 'H2O')
>>> chemicals.H2O is chemicals.Water
True

Note that you cannot use one alias for two chemicals:

>>> chemicals.set_alias('Ethanol', 'H2O')
Traceback (most recent call last):
ValueError: alias 'H2O' already in use by Chemical('Water')
zeros()[source]#

Return an array of zeros with entries that correspond to the orded chemical IDs.

Examples

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Ethanol'], cache=True)
>>> chemicals.zeros()
array([0., 0.])
ones()[source]#

Return an array of ones with entries that correspond to the ordered chemical IDs.

Examples

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Ethanol'], cache=True)
>>> chemicals.ones()
array([1., 1.])
kwarray(ID_data)[source]#

Return an array with entries that correspond to the ordered chemical IDs.

Parameters:

ID_data (dict[str, float]) – ID-data pairs.

Examples

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Ethanol'], cache=True)
>>> chemicals.kwarray(dict(Water=2))
array([2., 0.])
array(IDs, data)[source]#

Return an array with entries that correspond to the ordered chemical IDs.

Parameters:
  • IDs (iterable) – Compound IDs.

  • data (array_like) – Data corresponding to IDs.

Examples

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Ethanol'], cache=True)
>>> chemicals.array(['Water'], [2])
array([2., 0.])
iarray(IDs, data)[source]#

Return a chemical indexer.

Parameters:
  • IDs (iterable) – Chemical IDs.

  • data (array_like) – Data corresponding to IDs.

Examples

Create a chemical indexer from chemical IDs and data:

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Methanol', 'Ethanol'], cache=True)
>>> indexer = chemicals.iarray(['Water', 'Ethanol'], [2., 1.])
>>> indexer.show()
ChemicalIndexer:
 Water    2
 Ethanol  1

Note that indexers allow for computationally efficient indexing using identifiers:

>>> indexer['Ethanol', 'Water']
array([1., 2.])
>>> indexer['Ethanol']
1.0
ikwarray(ID_data)[source]#

Return a chemical indexer.

Parameters:

ID_data (Dict[str: float]) – Chemical ID-value pairs.

Examples

Create a chemical indexer from chemical IDs and data:

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Methanol', 'Ethanol'], cache=True)
>>> indexer = chemicals.ikwarray(dict(Water=2., Ethanol=1.))
>>> indexer.show()
ChemicalIndexer:
 Water    2
 Ethanol  1

Note that chemical indexers allow for computationally efficient indexing using identifiers:

>>> indexer['Ethanol', 'Water']
array([1., 2.])
>>> indexer['Ethanol']
1.0
isplit(split, order=None)[source]#

Create a SplitIndexer object that represents chemical splits.

Parameters:
  • split (Should be one of the following) –

    • [float] Split fraction

    • [array_like] Componentwise split

    • [dict] ID-split pairs

  • order=None (Iterable[str], options) – Chemical order of split. Defaults to biosteam.settings.chemicals.IDs

Examples

From a dictionary:

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Methanol', 'Ethanol'], cache=True)
>>> indexer = chemicals.isplit(dict(Water=0.5, Ethanol=1.))
>>> indexer.show()
SplitIndexer:
 Water    0.5
 Ethanol  1

From iterable given the order:

>>> indexer = chemicals.isplit([0.5, 1], ['Water', 'Ethanol'])
>>> indexer.show()
SplitIndexer:
 Water    0.5
 Ethanol  1

From a fraction:

>>> indexer = chemicals.isplit(0.75)
>>> indexer.show()
SplitIndexer:
 Water     0.75
 Methanol  0.75
 Ethanol   0.75

From an iterable (assuming same order as the Chemicals object):

>>> indexer = chemicals.isplit([0.5, 0, 1])
>>> indexer.show()
SplitIndexer:
 Water    0.5
 Ethanol  1
index(ID)[source]#

Return index of specified chemical.

Parameters:

ID (str) – Chemical identifier.

Examples

Index by ID:

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Ethanol'])
>>> chemicals.index('Water')
0

Indices by CAS number:

>>> chemicals.index('7732-18-5')
0
indices(IDs)[source]#

Return indices of specified chemicals.

Parameters:

IDs (iterable) – Chemical identifiers.

Examples

Indices by ID:

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Ethanol'])
>>> chemicals.indices(['Water', 'Ethanol'])
[0, 1]

Indices by CAS number:

>>> chemicals.indices(['7732-18-5', '64-17-5'])
[0, 1]
available_indices(IDs)[source]#

Return indices of all chemicals available.

Parameters:

IDs (iterable[str] or str) – Chemical identifiers.

Notes

CAS numbers are also supported.

Examples

Get available indices from IDs:

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Ethanol'], cache=True)
>>> IDs = ('Water', 'Ethanol', 'Octane')
>>> chemicals.available_indices(IDs)
[0, 1]
get_index(IDs)[source]#

Return index/indices of specified chemicals.

Parameters:

IDs (iterable[str] or str) – Chemical identifiers.

Notes

CAS numbers are also supported.

Examples

Get multiple indices with a tuple/list of IDs:

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Ethanol'], cache=True)
>>> IDs = ('Water', 'Ethanol')
>>> chemicals.get_index(IDs)
[0, 1]

Get a single index with a string:

>>> chemicals.get_index('Ethanol')
1

An Ellipsis returns a slice:

>>> chemicals.get_index(...)
slice(None, None, None)

Collections (without an order) raise an error:

>>> chemicals.get_index({'Water', 'Ethanol'})
Traceback (most recent call last):
TypeError: only strings, sequences, and ellipsis are valid index keys
get_vle_indices(nonzeros)[source]#

Return indices of species in vapor-liquid equilibrium given an array dictating whether or not the chemicals are present.

Examples

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Methanol', 'Ethanol'])
>>> data = chemicals.kwarray(dict(Water=2., Ethanol=1.))
>>> chemicals.get_vle_indices(data[data!=0])
[1, 2]
get_lle_indices(nonzeros)[source]#

Return indices of species in liquid-liquid equilibrium given an array dictating whether or not the chemicals are present.

Examples

>>> from thermosteam import CompiledChemicals
>>> chemicals = CompiledChemicals(['Water', 'Methanol', 'Ethanol'])
>>> data = chemicals.kwarray(dict(Water=2., Ethanol=1.))
>>> chemicals.get_lle_indices(data[data!=0])
[1, 2]
append(*args, **kwargs)#

Append a Chemical.

extend(*args, **kwargs)#

Extend with more Chemical objects.