MultiStream#

A MultiStream object represents a material flow with multiple phases in a chemical process.

class MultiStream(ID='', flow=(), T=298.15, P=101325.0, phases=None, units=None, price=0, total_flow=None, thermo=None, characterization_factors=None, vlle=False, **phase_flows)[source]#

Create a MultiStream object that defines material flow rates for multiple phases along with its thermodynamic state. Thermodynamic and transport properties of a stream are available as properties, while thermodynamic equilbrium (e.g. VLE, and bubble and dew points) are available as methods.

Parameters:
  • ID (str, optional) – A unique identification. If ID is None, stream will not be registered. If no ID is given, stream will be registered with a unique ID.

  • flow (Sequence, optional) – All flow rates corresponding to phases by row and chemical IDs by column.

  • T (float, optional) – Temperature [K]. Defaults to 298.15.

  • P (float, optional) – Pressure [Pa]. Defaults to 101325.

  • phases (Sequence`[:py:class:`str], optional) – Tuple denoting the phases present. Defaults to (‘g’, ‘l’).

  • units (str, optional) – Flow rate units of measure (only mass, molar, and volumetric flow rates are valid). Defaults to ‘kmol/hr’.

  • price (float, optional) – Price per unit mass [USD/kg]. Defaults to 0.

  • total_flow (float, optional) – Total flow rate.

  • thermo (Thermo, optional) – Thermodynamic equilibrium package. Defaults to thermosteam.settings.get_thermo().

  • vlle (bool, optional) – Whether to run rigorous phase equilibrium to determine phases. Defaults to False.

  • **phase_flow (tuple[str, float]) – phase-(ID, flow) pairs.

Examples

Before creating streams, first set the chemicals:

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol'], cache=True)

Create a multi phase stream, defining the thermodynamic condition and flow rates:

>>> s1 = tmo.MultiStream(ID='s1',T=298.15, P=101325,
...                      l=[('Water', 20), ('Ethanol', 10)], units='kg/hr')
>>> s1.show(flow='kg/hr') # Use the show method to select units of display
MultiStream: s1
phases: ('g', 'l'), T: 298.15 K, P: 101325 Pa
flow (kg/hr): (l) Water    20
                  Ethanol  10

The temperature and pressure are stored as attributes:

>>> (s1.T, s1.P)
(298.15, 101325.0)

Unlike Stream objects, the mol attribute does not store data, it simply returns the total flow rate of each chemical. Setting an element of the array raises an error to prevent the wrong assumption that the data is linked:

>>> s1.mol
sparse([1.11 , 0.217])
>>> s1.mol[0] = 1
Traceback (most recent call last):
ValueError: assignment destination is read-only

All flow rates are stored in the imol attribute:

>>> s1.imol.show() # Molar flow rates [kmol/hr]
MolarFlowIndexer (kmol/hr):
 (l) Water     1.11
     Ethanol   0.2171
>>> # Index a single chemical in the liquid phase
>>> s1.imol['l', 'Water']
1.1101
>>> # Index multiple chemicals in the liquid phase
>>> s1.imol['l', ('Ethanol', 'Water')]
array([0.217, 1.11 ])
>>> # Index the vapor phase
>>> s1.imol['g']
sparse([0., 0.])
>>> # Index flow of chemicals summed across all phases
>>> s1.imol['Ethanol', 'Water']
array([0.217, 1.11 ])

Note that overall chemical flows in MultiStream objects cannot be set like with Stream objects:

>>> # s1.imol['Ethanol', 'Water'] = [1, 0]
Traceback (most recent call last):
IndexError: multiple phases present; must include phase key to set chemical data

Chemical flows must be set by phase:

>>> s1.imol['l', ('Ethanol', 'Water')] = [1, 0]

The most convinient way to get and set flow rates is through the get_flow and set_flow methods:

>>> # Set flow
>>> key = ('l', 'Water')
>>> s1.set_flow(1, 'gpm', key)
>>> s1.get_flow('gpm', key)
1.0
>>> # Set multiple flows
>>> key = ('l', ('Ethanol', 'Water'))
>>> s1.set_flow([10, 20], 'kg/hr', key)
>>> s1.get_flow('kg/hr', key)
array([10., 20.])

Chemical flows across all phases can be retrieved if no phase is given:

>>> s1.get_flow('kg/hr', ('Ethanol', 'Water'))
array([10., 20.])

However, setting chemical data requires the phase to be specified:

>>> s1.set_flow([10, 20], 'kg/hr', ('Ethanol', 'Water'))
Traceback (most recent call last):
IndexError: multiple phases present; must include phase key to set chemical data

Note that for both Stream and MultiStream objects, mol, imol, and get_flow return chemical flows across all phases when given only chemical IDs.

Vapor-liquid equilibrium can be performed by setting 2 degrees of freedom from the following list:

  • T - Temperature [K]

  • P - Pressure [Pa]

  • V - Vapor fraction

  • H - Enthalpy [kJ/hr]

>>> s1.vle(P=101325, T=365)

Each phase can be accessed separately too:

>>> s1['l'].show()
Stream:
phase: 'l', T: 365 K, P: 101325 Pa
flow (kmol/hr): Water    0.617
                Ethanol  0.0238
>>> s1['g'].show()
Stream:
phase: 'g', T: 365 K, P: 101325 Pa
flow (kmol/hr): Water    0.493
                Ethanol  0.193

Note that the phase cannot be changed:

>>> s1['g'].phase = 'l'
Traceback (most recent call last):
AttributeError: phase is locked
reset_flow(total_flow=None, units=None, phases=None, **phase_flows)[source]#

Convinience method for resetting flow rate data.

Examples

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol'], cache=True)
>>> s1 = tmo.MultiStream('s1', l=[('Water', 1)])
>>> s1.reset_flow(g=[('Ethanol', 1)], phases='lgs', units='kg/hr', total_flow=2)
>>> s1.show('cwt')
MultiStream: s1
phases: ('g', 'l', 's'), T: 298.15 K, P: 101325 Pa
composition (%): (g) Ethanol  100
                     -------  2 kg/hr
reset_cache()[source]#

Reset cache regarding equilibrium methods.

get_flow(units, key=Ellipsis)[source]#

Return an array of flow rates in requested units.

Parameters:
  • units (str) – Units of measure.

  • key

    Index key as (phase, IDs), phase, or IDs where:

    • phase is a str, ellipsis, or missing.

    • IDs is a str, Sequence[str], ellipisis, or missing.

Examples

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol'], cache=True)
>>> s1 = tmo.MultiStream('s1', l=[('Water', 20), ('Ethanol', 10)], units='kg/hr')
>>> s1.get_flow('kg/hr', ('l', 'Water'))
20.0
>>> s1.get_flow('kg/hr')
sparse([20., 10.])
set_flow(data, units, key=Ellipsis)[source]#

Set flow rates in given units.

Parameters:
  • data (NDArray[float] | float) – Flow rate data.

  • units (str) – Units of measure.

  • key

    Index key as (phase, IDs), phase, or IDs where:

    • phase is a str, ellipsis, or missing.

    • IDs is a str, Sequence[str], ellipisis, or missing.

Examples

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol'], cache=True)
>>> s1 = tmo.MultiStream('s1', l=[('Water', 20), ('Ethanol', 10)], units='kg/hr')
>>> s1.set_flow(10, 'kg/hr', ('l', 'Water'))
>>> s1.get_flow('kg/hr', ('l', 'Water'))
10.0
property phases: tuple[str, ...]#

All phases avaiable.

property mol: ndarray[Any, dtype[float]]#

Chemical molar flow rates (total of all phases).

property mass: ndarray[Any, dtype[float]]#

Chemical mass flow rates (total of all phases).

property vol: ndarray[Any, dtype[float]]#

Chemical volumetric flow rates (total of all phases).

property H: float#

Enthalpy flow rate [kJ/hr].

property h: float#

Specific enthalpy in kJ/kmol.

property S: float#

Absolute entropy flow rate [kJ/hr].

property vapor_fraction: float#

Molar vapor fraction.

property liquid_fraction: float#

Molar liquid fraction.

property solid_fraction: float#

Molar solid fraction.

split_to(s1, s2, split, energy_balance=True)[source]#

Split molar flow rate from this stream to two others given the split fraction or an array of split fractions.

Examples

>>> import thermosteam as tmo
>>> chemicals = tmo.Chemicals(['Water', 'Ethanol'], cache=True)
>>> tmo.settings.set_thermo(chemicals)
>>> s = tmo.Stream('s', Water=20, Ethanol=10, units='kg/hr')
>>> s.phases = ('l', 'g')
>>> s1 = tmo.Stream('s1')
>>> s2 = tmo.Stream('s2')
>>> split = chemicals.kwarray(dict(Water=0.5, Ethanol=0.1))
>>> s.split_to(s1, s2, split)
>>> s1.show(flow='kg/hr')
MultiStream: s1
phases: ('g', 'l'), T: 298.15 K, P: 101325 Pa
flow (kg/hr): (l) Water    10
                  Ethanol  1
>>> s2.show(flow='kg/hr')
MultiStream: s2
phases: ('g', 'l'), T: 298.15 K, P: 101325 Pa
flow (kg/hr): (l) Water    10
                  Ethanol  9
copy_like(other)[source]#

Copy all conditions of another stream.

Examples

Copy data from another stream with the same property package:

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol'], cache=True)
>>> s1 = tmo.MultiStream('s1', l=[('Water', 20), ('Ethanol', 10)], units='kg/hr')
>>> s2 = tmo.Stream('s2', Water=2, units='kg/hr')
>>> s1.copy_like(s2)
>>> s1.show(flow='kg/hr')
MultiStream: s1
phases: ('g', 'l'), T: 298.15 K, P: 101325 Pa
flow (kg/hr): (l) Water  2

Copy data from another stream with a different property package:

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol'], cache=True)
>>> s1 = tmo.MultiStream('s1', l=[('Water', 20), ('Ethanol', 10)], units='kg/hr')
>>> tmo.settings.set_thermo(['Water'], cache=True)
>>> s2 = tmo.Stream('s2', Water=2, units='kg/hr')
>>> s1.copy_like(s2)
>>> s1.show(flow='kg/hr')
MultiStream: s1
phases: ('g', 'l'), T: 298.15 K, P: 101325 Pa
flow (kg/hr): (l) Water  2
copy_flow(other, phase=Ellipsis, IDs=Ellipsis, *, remove=False, exclude=False)[source]#

Copy flow rates of another stream to self.

Parameters:
  • other (Stream) – Flow rates will be copied from here.

  • IDs (Sequence`[:py:class:`str] | str, optional) – Chemical IDs. Defaults to all chemicals.

  • remove (bool, optional) – If True, copied chemicals will be removed from stream.

  • exclude (bool, optional) – If True, exclude designated chemicals when copying.

Notes

Works just like <Stream>.copy_flow, but the phase must be specified.

Examples

Initialize streams:

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol'], cache=True)
>>> s1 = tmo.MultiStream('s1', l=[('Water', 20), ('Ethanol', 10)], units='kg/hr')
>>> s2 = tmo.MultiStream('s2')

Copy all flows:

>>> s2.copy_flow(s1)
>>> s2.show(flow='kg/hr')
MultiStream: s2
phases: ('g', 'l'), T: 298.15 K, P: 101325 Pa
flow (kg/hr): (l) Water    20
                  Ethanol  10

Reset and copy just water flow:

>>> s2.empty()
>>> s2.copy_flow(s1, IDs='Water')
>>> s2.show(flow='kg/hr')
MultiStream: s2
phases: ('g', 'l'), T: 298.15 K, P: 101325 Pa
flow (kg/hr): (l) Water  20

Reset and copy all flows except water:

>>> s2.empty()
>>> s2.copy_flow(s1, IDs='Water', exclude=True)
>>> s2.show(flow='kg/hr')
MultiStream: s2
phases: ('g', 'l'), T: 298.15 K, P: 101325 Pa
flow (kg/hr): (l) Ethanol  10

Cut and paste flows:

>>> s2.copy_flow(s1, remove=True)
>>> s2.show(flow='kg/hr')
MultiStream: s2
phases: ('g', 'l'), T: 298.15 K, P: 101325 Pa
flow (kg/hr): (l) Water    20
                  Ethanol  10
>>> s1.show()
MultiStream: s1
phases: ('g', 'l'), T: 298.15 K, P: 101325 Pa
 flow: 0

The other stream can also be a single phase stream (doesn’t have to be a MultiStream object):

Initialize streams:

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol'], cache=True)
>>> s1 = tmo.Stream('s1', Water=20, Ethanol=10, units='kg/hr')
>>> s2 = tmo.MultiStream('s2')

Copy all flows:

>>> s2.copy_flow(s1)
>>> s2.show(flow='kg/hr')
MultiStream: s2
phases: ('g', 'l'), T: 298.15 K, P: 101325 Pa
flow (kg/hr): (l) Water    20
                  Ethanol  10

Reset and copy just water flow:

>>> s2.empty()
>>> s2.copy_flow(s1, IDs='Water')
>>> s2.show(flow='kg/hr')
MultiStream: s2
phases: ('g', 'l'), T: 298.15 K, P: 101325 Pa
flow (kg/hr): (l) Water  20

Reset and copy all flows except water:

>>> s2.empty()
>>> s2.copy_flow(s1, IDs='Water', exclude=True)
>>> s2.show(flow='kg/hr')
MultiStream: s2
phases: ('g', 'l'), T: 298.15 K, P: 101325 Pa
flow (kg/hr): (l) Ethanol  10

Cut and paste flows:

>>> s2.copy_flow(s1, remove=True)
>>> s2.show(flow='kg/hr')
MultiStream: s2
phases: ('g', 'l'), T: 298.15 K, P: 101325 Pa
flow (kg/hr): (l) Water    20
                  Ethanol  10
>>> s1.show()
Stream: s1
phase: 'l', T: 298.15 K, P: 101325 Pa
flow: 0
get_normalized_mol(IDs)[source]#

Return normalized molar fractions of given chemicals. The sum of the result is always 1.

Parameters:

IDs (Sequence`[:py:class:`str]) – IDs of chemicals to be normalized.

Examples

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol', 'Methanol'], cache=True)
>>> s1 = tmo.MultiStream('s1', l=[('Water', 20), ('Ethanol', 10), ('Methanol', 10)], units='kmol/hr')
>>> s1.get_normalized_mol(('Water', 'Ethanol'))
array([0.667, 0.333])
get_normalized_vol(IDs)[source]#

Return normalized mass fractions of given chemicals. The sum of the result is always 1.

Parameters:

IDs (Sequence`[:py:class:`str]) – IDs of chemicals to be normalized.

Examples

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol', 'Methanol'], cache=True)
>>> s1 = tmo.MultiStream('s1', l=[('Water', 20), ('Ethanol', 10), ('Methanol', 10)], units='m3/hr')
>>> s1.get_normalized_vol(('Water', 'Ethanol'))
array([0.667, 0.333])
get_normalized_mass(IDs)[source]#

Return normalized mass fractions of given chemicals. The sum of the result is always 1.

Parameters:

IDs (Sequence`[:py:class:`str]) – IDs of chemicals to be normalized.

Examples

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol', 'Methanol'], cache=True)
>>> s1 = tmo.MultiStream('s1', l=[('Water', 20), ('Ethanol', 10), ('Methanol', 10)], units='kg/hr')
>>> s1.get_normalized_mass(('Water', 'Ethanol'))
array([0.667, 0.333])
get_molar_composition(IDs)[source]#

Return molar composition of given chemicals.

Parameters:

IDs (Sequence`[:py:class:`str]) – IDs of chemicals.

Examples

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol', 'Methanol'], cache=True)
>>> s1 = tmo.MultiStream('s1', l=[('Water', 20), ('Ethanol', 10), ('Methanol', 10)], units='kmol/hr')
>>> s1.get_molar_composition(('Water', 'Ethanol'))
array([0.5 , 0.25])
get_mass_composition(IDs)[source]#

Return mass composition of given chemicals.

Parameters:

IDs (Sequence`[:py:class:`str]) – IDs of chemicals.

Examples

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol', 'Methanol'], cache=True)
>>> s1 = tmo.MultiStream('s1', l=[('Water', 20), ('Ethanol', 10), ('Methanol', 10)], units='kg/hr')
>>> s1.get_mass_composition(('Water', 'Ethanol'))
array([0.5 , 0.25])
get_volumetric_composition(IDs)[source]#

Return volumetric composition of given chemicals.

Parameters:

IDs (Sequence`[:py:class:`str]) – IDs of chemicals.

Examples

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol', 'Methanol'], cache=True)
>>> s1 = tmo.MultiStream('s1', l=[('Water', 20), ('Ethanol', 10), ('Methanol', 10)], units='m3/hr')
>>> s1.get_volumetric_composition(('Water', 'Ethanol'))
array([0.5 , 0.25])
get_concentration(phase, IDs, units=None)[source]#

Return concentration of given chemicals in kmol/m3.

Parameters:
  • phase (str)

  • IDs (Sequence`[:py:class:`str] | str) – IDs of chemicals.

Examples

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol', 'Methanol'], cache=True)
>>> s1 = tmo.MultiStream('s1', l=[('Water', 20), ('Ethanol', 10), ('Methanol', 10)], units='m3/hr')
>>> s1.get_concentration('l', ('Water', 'Ethanol'))
array([27.673,  4.261])
>>> s1.get_concentration('l', ('Water', 'Ethanol'), 'g/L')
array([498.532, 196.291])
property vle: VLE#

An object that can perform vapor-liquid equilibrium on the stream.

property lle: LLE#

An object that can perform liquid-liquid equilibrium on the stream.

property sle: SLE#

An object that can perform solid-liquid equilibrium on the stream.

as_stream()[source]#

Convert MultiStream to Stream.

property ID#

Unique identification (str). If set as ‘’, it will choose a default ID.

reduce_phases()[source]#

Remove empty phases.

property phase: str#

Phase of stream.

print()[source]#

Print in a format that you can use recreate the stream.

Examples

>>> import thermosteam as tmo
>>> tmo.settings.set_thermo(['Water', 'Ethanol'], cache=True)
>>> s1 = tmo.MultiStream(ID='s1',T=298.15, P=101325,
...                      l=[('Water', 20), ('Ethanol', 10)], units='kg/hr')
>>> s1.print()
MultiStream(ID='s1', phases=('g', 'l'), T=298.15, P=101325, l=[('Water', 1.11), ('Ethanol', 0.2171)])