<commit_before># -*- coding: utf-8 -*-
'''Chemical Engineering Design Library (ChEDL). Utilities for process modeling.
Copyright (C) 2019, 2020 <NAME> <<EMAIL>>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

This module contains classes and functions for performing flash calculations.

For reporting bugs, adding feature requests, or submitting pull requests,
please use the `GitHub issue tracker <https://github.com/CalebBell/thermo/>`_.

.. contents:: :local:

Main Interfaces
===============

Pure Components
---------------
.. autoclass:: FlashPureVLS
   :show-inheritance:
   :members: __init__
   :exclude-members: __init__

Vapor-Liquid Systems
--------------------
.. autoclass:: FlashVL
   :show-inheritance:
   :members: __init__
   :exclude-members: __init__

Vapor and Multiple Liquid Systems
---------------------------------
.. autoclass:: FlashVLN
   :show-inheritance:
   :members: __init__
   :exclude-members: __init__

Base Flash Class
----------------
.. autoclass:: Flash
   :show-inheritance:
   :members: flash, plot_TP
   :exclude-members:


Specific Flash Algorithms
=========================
It is recommended to use the Flash classes, which are designed to have generic
interfaces. The implemented specific flash algorithms may be changed in the
future, but reading their source code may be helpful for instructive purposes.

'''

__all__ = ['Flash']

from fluids.constants import R
from thermo.equilibrium import EquilibriumState
from thermo.phase_identification import identify_sort_phases
from thermo.utils import has_matplotlib
from fluids.numerics import logspace, linspace, numpy as np
from chemicals.utils import log10, floor
from thermo import phases

spec_to_iter_vars = {
     (True, False, False, True, False, False) : ('T', 'H', 'P'), # Iterating on P is slow, derivatives look OK
     # (True, False, False, True, False, False) : ('T', 'H', 'V'), # Iterating on P is slow, derivatives look OK
     (True, False, False, False, True, False) : ('T', 'S', 'P'),
     (True, False, False, False, False, True) : ('T', 'U', 'V'),

     (False, True, False, True, False, False) : ('P', 'H', 'T'),
     (False, True, False, False, True, False) : ('P', 'S', 'T'),
     (False, True, False, False, False, True) : ('P', 'U', 'T'),

     (False, False, True, True, False, False) : ('V', 'H', 'P'), # TODO: change these ones to iterate on T?
     (False, False, True, False, True, False) : ('V', 'S', 'P'),
     (False, False, True, False, False, True) : ('V', 'U', 'P'),
}

spec_to_iter_vars_backup =  {
    (True, False, False, True, False, False) : ('T', 'H', 'V'),
    (True, False, False, False, True, False) : ('T', 'S', 'V'),
    (True, False, False, False, False, True) : ('T', 'U', 'P'),

    (False, True, False, True, False, False) : ('P', 'H', 'V'),
    (False, True, False, False, True, False) : ('P', 'S', 'V'),
    (False, True, False, False, False, True) : ('P', 'U', 'V'),

    (False, False, True, True, False, False) : ('V', 'H', 'T'),
    (False, False, True, False, True, False) : ('V', 'S', 'T'),
    (False, False, True, False, False, True) : ('V', 'U', 'T'),
}

empty_flash_conv = {'iterations': 0, 'err': 0.0, 'stab_guess_name': None}
one_in_list = [1.0]
empty_list = []

class Flash(object):
    r'''Base class for performing flash calculations. All Flash objects need
    to inherit from this, and common methods can be added to it.'''

    def __init_subclass__(cls):
        cls.__full_path__ = "%s.%s" %(cls.__module__, cls.__qualname__)

    def flash(self, zs=None, T=None, P=None, VF=None, SF=None, V=None, H=None,
              S=None, G=None, U=None, A=None, solution=None, hot_start=None,
              retry=False, dest=None):
        r'''Method to perform a flash calculation and return the result as an
        :obj:`EquilibriumState <thermo.equilibrium.EquilibriumState>` object.
        This generic interface allows flashes with any combination of valid
        specifications; if a flash is unimplemented and error will be raised.

        Parameters
        ----------
        zs : list[float], optional
            Mole fractions of each component, required unless there is only
            one component, [-]
        T : float, optional
            Temperature, [K]
        P : float, optional
            Pressure, [Pa]
        VF : float, optional
            Vapor fraction, [-]
        SF : float, optional
            Solid fraction, [-]
        V : float, optional
            Molar volume of the overall bulk, [m^3/mol]
        H : float, optional
            Molar enthalpy of the overall bulk, [J/mol]
        S : float, optional
            Molar entropy of the overall bulk, [J/(mol*K)]
        G : float, optional
            Molar Gibbs free energy of the overall bulk, [J/mol]
        U : float, optional
            Molar internal energy of the overall bulk, [J/mol]
        A : float, optional
            Molar Helmholtz energy of the overall bulk, [J/mol]
        solution : str or int, optional
           When multiple solutions exist, if more than one is found they will
           be sorted by T (and then P) increasingly; this number will index
           into the multiple solution array. Negative indexing is supported.
           'high' is an alias for 0, and 'low' an alias for -1. Setting this
           parameter may make a flash slower because in some cases more checks
           are performed. [-]
        hot_start : :obj:`EquilibriumState <thermo.equilibrium.EquilibriumState>`
            A previously converged flash or initial guessed state from which
            the flash can begin; this parameter can save time in some cases,
            [-]
        retry : bool
            Usually for flashes like UV or PH, there are multiple sets of
            possible iteration variables. For the UV case, the prefered
            iteration variable is P, so each iteration a PV solve is done on
            the phase; but equally the flash can be done iterating on
            `T`, where a TV solve is done on the phase each iteration.
            Depending on the tolerances, the flash type, the thermodynamic
            consistency of the phase, and other factors, it is possible the
            flash can fail. If `retry` is set to True, the alternate variable
            set will be iterated as a backup if the first flash fails. [-]
        dest : None or :obj:`EquilibriumState <thermo.equilibrium.EquilibriumState>` or :obj:`EquilibriumStream <thermo.stream.EquilibriumStream>`
            What type of object the flash result is set into; leave as None to
            obtain the normal `EquilibriumState` results, [-]

        Returns
        -------
        results : :obj:`EquilibriumState <thermo.equilibrium.EquilibriumState>`
            Equilibrium object containing the state of the phases after the
            flash calculation [-]

        Notes
        -----

        Examples
        --------
        '''
        if zs is None:
            if self.N == 1:
                zs = [1.0]
            else:
                raise ValueError("Composition missing for flash")
        constants, correlations = self.constants, self.correlations
        settings = self.settings
        if dest is None:
            dest = EquilibriumState
#        if self.N > 1 and 0:
#            for zi in zs:
#                if zi == 1.0:
#                    # Does not work - phases expect multiple components mole fractions
#                    return self.flash_pure.flash(zs=zs, T=T, P=P, VF=VF, SF=SF,
#                                           V=V, H=H, S=S, U=U, G=G, A=A,
#                                           solution=solution, retry=retry,
#                                           hot_start=hot_start)
        T_spec = T is not None
        P_spec = P is not None
        V_spec = V is not None
        H_spec = H is not None
        S_spec = S is not None
        U_spec = U is not None
        # Normally multiple solutions
        A_spec = A is not None
        G_spec = G is not None
<commit_msg>Add some very clear warnings<commit_after># -*- coding: utf-8 -*-
'''Chemical Engineering Design Library (ChEDL). Utilities for process modeling.
Copyright (C) 2019, 2020 <NAME> <<EMAIL>>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

This module contains classes and functions for performing flash calculations.

For reporting bugs, adding feature requests, or submitting pull requests,
please use the `GitHub issue tracker <https://github.com/CalebBell/thermo/>`_.

.. contents:: :local:

Main Interfaces
===============

Pure Components
---------------
.. autoclass:: FlashPureVLS
   :show-inheritance:
   :members: __init__
   :exclude-members: __init__

Vapor-Liquid Systems
--------------------
.. autoclass:: FlashVL
   :show-inheritance:
   :members: __init__
   :exclude-members: __init__

Vapor and Multiple Liquid Systems
---------------------------------
.. autoclass:: FlashVLN
   :show-inheritance:
   :members: __init__
   :exclude-members: __init__

Base Flash Class
----------------
.. autoclass:: Flash
   :show-inheritance:
   :members: flash, plot_TP
   :exclude-members:


Specific Flash Algorithms
=========================
It is recommended to use the Flash classes, which are designed to have generic
interfaces. The implemented specific flash algorithms may be changed in the
future, but reading their source code may be helpful for instructive purposes.

'''

__all__ = ['Flash']

from fluids.constants import R
from thermo.equilibrium import EquilibriumState
from thermo.phase_identification import identify_sort_phases
from thermo.utils import has_matplotlib
from fluids.numerics import logspace, linspace, numpy as np
from chemicals.utils import log10, floor
from thermo import phases

spec_to_iter_vars = {
     (True, False, False, True, False, False) : ('T', 'H', 'P'), # Iterating on P is slow, derivatives look OK
     # (True, False, False, True, False, False) : ('T', 'H', 'V'), # Iterating on P is slow, derivatives look OK
     (True, False, False, False, True, False) : ('T', 'S', 'P'),
     (True, False, False, False, False, True) : ('T', 'U', 'V'),

     (False, True, False, True, False, False) : ('P', 'H', 'T'),
     (False, True, False, False, True, False) : ('P', 'S', 'T'),
     (False, True, False, False, False, True) : ('P', 'U', 'T'),

     (False, False, True, True, False, False) : ('V', 'H', 'P'), # TODO: change these ones to iterate on T?
     (False, False, True, False, True, False) : ('V', 'S', 'P'),
     (False, False, True, False, False, True) : ('V', 'U', 'P'),
}

spec_to_iter_vars_backup =  {
    (True, False, False, True, False, False) : ('T', 'H', 'V'),
    (True, False, False, False, True, False) : ('T', 'S', 'V'),
    (True, False, False, False, False, True) : ('T', 'U', 'P'),

    (False, True, False, True, False, False) : ('P', 'H', 'V'),
    (False, True, False, False, True, False) : ('P', 'S', 'V'),
    (False, True, False, False, False, True) : ('P', 'U', 'V'),

    (False, False, True, True, False, False) : ('V', 'H', 'T'),
    (False, False, True, False, True, False) : ('V', 'S', 'T'),
    (False, False, True, False, False, True) : ('V', 'U', 'T'),
}

empty_flash_conv = {'iterations': 0, 'err': 0.0, 'stab_guess_name': None}
one_in_list = [1.0]
empty_list = []

class Flash(object):
    r'''Base class for performing flash calculations. All Flash objects need
    to inherit from this, and common methods can be added to it.'''

    def __init_subclass__(cls):
        cls.__full_path__ = "%s.%s" %(cls.__module__, cls.__qualname__)

    def flash(self, zs=None, T=None, P=None, VF=None, SF=None, V=None, H=None,
              S=None, G=None, U=None, A=None, solution=None, hot_start=None,
              retry=False, dest=None):
        r'''Method to perform a flash calculation and return the result as an
        :obj:`EquilibriumState <thermo.equilibrium.EquilibriumState>` object.
        This generic interface allows flashes with any combination of valid
        specifications; if a flash is unimplemented and error will be raised.

        Parameters
        ----------
        zs : list[float], optional
            Mole fractions of each component, required unless there is only
            one component, [-]
        T : float, optional
            Temperature, [K]
        P : float, optional
            Pressure, [Pa]
        VF : float, optional
            Vapor fraction, [-]
        SF : float, optional
            Solid fraction, [-]
        V : float, optional
            Molar volume of the overall bulk, [m^3/mol]
        H : float, optional
            Molar enthalpy of the overall bulk, [J/mol]
        S : float, optional
            Molar entropy of the overall bulk, [J/(mol*K)]
        G : float, optional
            Molar Gibbs free energy of the overall bulk, [J/mol]
        U : float, optional
            Molar internal energy of the overall bulk, [J/mol]
        A : float, optional
            Molar Helmholtz energy of the overall bulk, [J/mol]
        solution : str or int, optional
           When multiple solutions exist, if more than one is found they will
           be sorted by T (and then P) increasingly; this number will index
           into the multiple solution array. Negative indexing is supported.
           'high' is an alias for 0, and 'low' an alias for -1. Setting this
           parameter may make a flash slower because in some cases more checks
           are performed. [-]
        hot_start : :obj:`EquilibriumState <thermo.equilibrium.EquilibriumState>`
            A previously converged flash or initial guessed state from which
            the flash can begin; this parameter can save time in some cases,
            [-]
        retry : bool
            Usually for flashes like UV or PH, there are multiple sets of
            possible iteration variables. For the UV case, the prefered
            iteration variable is P, so each iteration a PV solve is done on
            the phase; but equally the flash can be done iterating on
            `T`, where a TV solve is done on the phase each iteration.
            Depending on the tolerances, the flash type, the thermodynamic
            consistency of the phase, and other factors, it is possible the
            flash can fail. If `retry` is set to True, the alternate variable
            set will be iterated as a backup if the first flash fails. [-]
        dest : None or :obj:`EquilibriumState <thermo.equilibrium.EquilibriumState>` or :obj:`EquilibriumStream <thermo.stream.EquilibriumStream>`
            What type of object the flash result is set into; leave as None to
            obtain the normal `EquilibriumState` results, [-]

        Returns
        -------
        results : :obj:`EquilibriumState <thermo.equilibrium.EquilibriumState>`
            Equilibrium object containing the state of the phases after the
            flash calculation [-]

        Notes
        -----
        
        .. warning::
            Not all flash specifications have a unique solution. Not all flash
            specifications will converge, whether from a bad model, bad inputs,
            or simply a lack of convergence by the implemented algorithms.
            You are welcome to submit these cases to the author but the library
            is provided AS IS, with NO SUPPORT.

        .. warning::
            Convergence of a flash may be impaired by providing `hot_start`. 
            If reliability is desired, do not use this parameter.

        .. warning::
            The most likely thermodynamic methods to converge are 
            thermodynamically consistent ones. This means e.g. an ideal liquid
            and an ideal gas; or an equation of state for both
            phases. Mixing thermodynamic models increases the possibility of
            multiple solutions, discontinuities, and other not-fun issues for
            the algorithms.

        Examples
        --------
        '''
        if zs is None:
            if self.N == 1:
                zs = [1.0]
            else:
                raise ValueError("Composition missing for flash")
        constants, correlations = self.constants, self.correlations
        settings = self.settings
        if dest is None:
            dest = EquilibriumState
#        if self.N > 1 and 0:
#            for zi in zs:
#                if zi == 1.0:
#                    # Does not work - phases expect multiple components mole fractions
#                    return self.flash_pure.flash(zs=zs, T=T, P=P, VF=VF, SF=SF,
#                                           V=V, H=H, S=S, U=U, G=G, A=A,
#                                           solution=solution, retry=retry,
#                                           hot_start=hot_start)
        T_spec = T is not None
        P_spec = P is not None
        V_spec = V is not None
        H_spec = H is not None
        S_spec = S is not None
        U_spec = U is not None
        # Normally multiple solutions
        A_spec = A is not None
        G_spec = G is not None

{'fraction_non_alphanumeric': 0.10976572782311135, 'fraction_numerical': 0.0027375625164516976, 'mean_word_length': 2.448175712470503, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 23, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '91421', 'n_tokens_mistral': 5283, 'n_tokens_neox': 5078, 'n_words': 2245}