MultiStream

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

class thermosteam.MultiStream(ID='', flow=(), T=298.15, P=101325.0, phases=('g', 'l'), units=None, thermo=None, price=0, **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) – 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=() (2d array) – All flow rates corresponding to phases by row and chemical IDs by column.

  • thermo=None (Thermo) – Thermodynamic equilibrium package. Defaults to thermosteam.settings.get_thermo().

  • units='kmol/hr' (str) – Flow rate units of measure (only mass, molar, and volumetric flow rates are valid).

  • phases (tuple['g', 'l', 's', 'G', 'L', 'S']) – Tuple denoting the phases present. Defaults to (‘g’, ‘l’).

  • T=298.15 (float) – Temperature [K].

  • P=101325 (float) – Pressure [Pa].

  • price=0 (float) – Price per unit mass [USD/kg].

  • **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
array([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.1101687012358397
>>> # Index multiple chemicals in the liquid phase
>>> s1.imol['l', ('Ethanol', 'Water')]
array([0.217, 1.11 ])
>>> # Index the vapor phase
>>> s1.imol['g']
array([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.619
                 Ethanol  0.0238
>>> s1['g'].show()
Stream:
 phase: 'g', T: 365 K, P: 101325 Pa
 flow (kmol/hr): Water    0.491
                 Ethanol  0.193

Note that the phase cannot be changed:

>>> s1['g'].phase = 'l'
Traceback (most recent call last):
AttributeError: phase is locked
get_flow(units, key=Ellipsis)[source]

Return an array of flow rates in requested units.

Parameters
  • units (str) – Units of measure.

  • key (tuple(phase, IDs), phase, or IDs) –

    • phase: str, ellipsis, or missing.

    • IDs: str, tuple(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
set_flow(data, units, key=Ellipsis)[source]

Set flow rates in given units.

Parameters
  • data (1d ndarray or float) – Flow rate data.

  • units (str) – Units of measure.

  • key (tuple(phase, IDs), phase, or IDs) –

    • phase: str, ellipsis, or missing.

    • IDs: str, tuple(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

[Array] Chemical molar flow rates (total of all phases).

property mass

[Array] Chemical mass flow rates (total of all phases).

property vol

[Array] Chemical volumetric flow rates (total of all phases).

property H

[float] Enthalpy flow rate in kJ/hr.

property S

[float] Absolute entropy flow rate in kJ/hr.

property C

[float] Heat capacity flow rate in kJ/hr.

property F_vol

[float] Total volumetric flow rate in m3/hr.

property Hvap

[float] Enthalpy of vaporization flow rate in kJ/hr.

property vapor_fraction

Molar vapor fraction.

property liquid_fraction

Molar liquid fraction.

property solid_fraction

Molar solid fraction.

property V

[float] Molar volume [m^3/mol].

property kappa

[float] Thermal conductivity [W/m/k].

property Cn

[float] Molar heat capacity [J/mol/K].

property mu

[float] Hydrolic viscosity [Pa*s].

property sigma

[float] Surface tension [N/m].

property epsilon

[float] Relative permittivity [-].

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.

  • phase (str or Ellipsis) –

  • IDs=None (iterable[str], defaults to all chemicals.) – Chemical IDs.

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

  • exclude=False (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 (tuple[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 (tuple[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 (tuple[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 (tuple[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 (tuple[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 (tuple[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)[source]

Return concentration of given chemicals in kmol/m3.

Parameters

IDs (tuple[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.671,  4.266])
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 phase

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)])