[iapws] 13/16: new upstream 1.2
Alastair McKinstry
mckinstry at moszumanska.debian.org
Thu Apr 20 10:51:09 UTC 2017
This is an automated email from the git hooks/post-receive script.
mckinstry pushed a commit to branch debian/master
in repository iapws.
commit b34da5371eae7b16dbacf4b8f4303df9e845bfaa
Author: Alastair McKinstry <mckinstry at debian.org>
Date: Thu Apr 20 11:45:40 2017 +0100
new upstream 1.2
---
PKG-INFO | 349 ++---
README.rst | 343 +----
iapws.egg-info/PKG-INFO | 349 ++---
iapws.egg-info/SOURCES.txt | 3 +
iapws/__init__.py | 12 +-
iapws/_iapws.py | 1460 +++++++++++++++++---
iapws/_utils.py | 216 +++
iapws/ammonia.py | 891 +++++++++++++
iapws/humidAir.py | 983 ++++++++++++++
iapws/iapws08.py | 634 +++++++--
iapws/iapws95.py | 2155 ++++++++++++++++++++----------
iapws/iapws97.py | 3163 +++++++++++++++++++++++++++++++++-----------
setup.cfg | 1 -
13 files changed, 7942 insertions(+), 2617 deletions(-)
diff --git a/PKG-INFO b/PKG-INFO
index f189454..d8d6fbe 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,23 +1,49 @@
Metadata-Version: 1.1
Name: iapws
-Version: 1.1.3
+Version: 1.2
Summary: Python implementation of standards from The InternationalAssociation for the Properties of Water and Steam
Home-page: https://github.com/jjgomera/iapws
Author: jjgomera
Author-email: jjgomera at gmail.com
License: gpl v3
-Download-URL: https://github.com/jjgomera/iapws/tarball/v1.1.3
-Description: iapws
+Download-URL: https://github.com/jjgomera/iapws/tarball/v1.2
+Description: .. image:: https://api.travis-ci.org/jjgomera/iapws.svg?branch=master
+ :target: https://travis-ci.org/jjgomera/iapws
+ :alt: Build Status
+
+ .. image:: https://ci.appveyor.com/api/projects/status/a128sh8e50cjsiya?svg=true
+ :target: https://ci.appveyor.com/project/jjgomera/iapws
+ :alt: Windows Build Status
+
+ .. image:: https://coveralls.io/repos/github/jjgomera/iapws/badge.svg?branch=master
+ :target: https://coveralls.io/github/jjgomera/iapws?branch=master
+ :alt: coveralls.io analysis
+
+ .. image:: https://codecov.io/gh/jjgomera/iapws/branch/master/graph/badge.svg
+ :target: https://codecov.io/gh/jjgomera/iapws
+ :alt: codecov.io analysis
+
+ .. image:: https://landscape.io/github/jjgomera/iapws/master/landscape.svg?style=flat
+ :target: https://landscape.io/github/jjgomera/iapws/master
+ :alt: Code Health
+
+ .. image:: http://readthedocs.org/projects/iapws/badge/?version=latest
+ :target: http://iapws.readthedocs.io/en/latest/?badge=latest
+ :alt: Documentation Status
+
+ iapws
=====
- Python implementation of standard from IAPWS (http://www.iapws.org/release.html). The available standard are::
+ Python implementation of standard from IAPWS (http://www.iapws.org/release.html). The module implements the full set of standards, including::
IAPWS-IF97
IAPWS-95
IAPWS-06 for Ice
IAPWS-08 for seawater
IAPWS-05 for Heavy water
+ ...
+
dependences
--------------------
@@ -28,92 +54,30 @@ Description: iapws
install
--------------------
- In debian you can find in official repositories in testing and sid. In stable you can install using pip::
+ In debian you can find in official repositories in jessie, testing and sid. In ubuntu it's in official repositories from ubuntu saucy (13.10). In other system you can install using pip::
pip install iapws
+
+ or directly cloning the github repository::
- In ubuntu it's in official repositories from ubuntu saucy (13.10)
-
- In other SO you can download from its webpage in `pypi <http://pypi.python.org/pypi/iapws>`_ and unzipped in python folder dist-packages. This is the recommended options to have the latest version.
-
-
- TODO
- --------------------
+ git clone https://github.com/jjgomera/iapws.git
- Improve convergence in two phase region for IAPWS95 and D2O class
+ and adding the folder to a python path. This is the recommended option to have the latest version.
- IAPWS-IF97
+ documentation
--------------------
+
+ To see the full documentation of package, see `readthedocs <http://iapws.readthedocs.io/>`__
- Class to model a state for liquid water or steam with the Industrial Formulation IAPWS-IF97
+ .. inclusion-marker-do-not-remove
- Incoming properties:
+ For a rapid usage demostration, see this examples
- * T, Temperature, K
- * P, Pressure, MPa
- * h, Specific enthalpy, kJ/kg
- * s, Specific entropy, kJ/kg·K
- * x, Quality, [-]
-
- Definitions options:
-
- * T, P (Not valid for two-phases region)
- * P, h
- * P, s
- * h, s
- * T, x (Only for two-phases region)
- * P, x (Only for two-phases region)
-
- Properties:
-
- * P, Pressure, MPa
- * T, Temperature, K
- * g, Specific Gibbs free energy, kJ/kg
- * a, Specific Helmholtz free energy, kJ/kg
- * v, Specific volume, m³/kg
- * rho, Density, kg/m³
- * x, quality, [-]
- * h, Specific enthalpy, kJ/kg
- * u, Specific internal energy, kJ/kg
- * s, Specific entropy, kJ/kg·K
- * cp, Specific isobaric heat capacity, kJ/kg·K
- * cv, Specific isochoric heat capacity, kJ/kg·K
- * Z, Compression factor. [-]
- * gamma, Isoentropic exponent, [-]
- * alfav, Isobaric cubic expansion coefficient, 1/K
- * kt, Isothermal compressibility, 1/MPa
- * alfap, Relative pressure coefficient, 1/K
- * betap, Isothermal stress coefficient, kg/m³
- * joule, Joule-Thomson coefficient, K/MPa
- * deltat, Isothermal throttling coefficient, kJ/kg·MPa
- * region, Region
-
- * v0, Ideal specific volume, m³/kg
- * u0, Ideal specific internal energy, kJ/kg
- * h0, Ideal specific enthalpy, kJ/kg
- * s0, Ideal specific entropy, kJ/kg·K
- * a0, Ideal specific Helmholtz free energy, kJ/kg
- * g0, Ideal specific Gibbs free energy, kJ/kg
- * cp0, Ideal specific isobaric heat capacity, kJ/kg·K
- * cv0, Ideal specific isochoric heat capacity, kJ/kg·K
- * w0, Ideal speed of sound, m/s
- * gamma0, Ideal isoentropic exponent [-]
-
- * w, Speed of sound, m/s
- * mu, Dynamic viscosity, Pa·s
- * nu, Kinematic viscosity, m²/s
- * k, Thermal conductivity, W/m·K
- * alfa, Thermal diffusivity, m²/s
- * sigma, Surface tension, N/m
- * epsilon, Dielectric constant, [-]
- * n, Refractive index, [-]
- * Prandt, Prandtl number, [-]
- * Tr, Reduced temperature, [-]
- * Pr, Reduced pressure, [-]
+ IAPWS-IF97
- Usage::
+ .. code:: python
from iapws import IAPWS97
sat_steam=IAPWS97(P=1,x=1) #saturated steam with known P
@@ -121,221 +85,60 @@ Description: iapws
steam=IAPWS97(P=2.5, T=500) #steam with known P and T
print(sat_steam.h, sat_liquid.h, steam.h) #calculated enthalpies
-
-
+
IAPWS-95
- --------------------------------
-
- Class to model a state for liquid water or steam with the general and scientific formulation IAPWS-95
-
- Incoming properties:
-
- * T, Temperature, K
- * P, Pressure, MPa
- * rho, Density, kg/m3
- * v, Specific volume, m3/kg
- * h, Specific enthalpy, kJ/kg
- * s, Specific entropy, kJ/kg·K
- * x, Quality, [-]
- * l, Optional parameter to light wavelength for Refractive index, mm
-
- rho and v are equivalent, only one can be defined
- Definitions options:
-
- * T, P (Not valid for two-phases region)
- * T, rho
- * T, h
- * T, s
- * T, u
- * P, rho
- * P, h
- * P, s
- * P, u
- * rho, h
- * rho, s
- * rho, u
- * h, s
- * h, u
- * s, u
- * T, x (Only for two-phases region)
- * P, x (Only for two-phases region) Very slow
-
- Properties:
-
- * P, Pressure, MPa
- * Pr, Reduced pressure, [-]
- * T, Temperature, K
- * Tr, Reduced temperature, [-]
- * x, Quality, [-]
- * v, Specific volume, m³/kg
- * rho, Density, kg/m³
- * h, Specific enthalpy, kJ/kg
- * s, Specific entropy, kJ/kg·K
- * u, Specific internal energy, kJ/kg
- * g, Specific Gibbs free energy, kJ/kg
- * a, Specific Helmholtz free energy, kJ/kg
- * cp, Specific isobaric heat capacity, kJ/kg·K
- * cv, Specific isochoric heat capacity, kJ/kg·K
- * cp_cv, Heat capacity ratio, [-]
- * w, Speed of sound, m/s
- * Z, Compression factor, [-]
- * fi, Fugacity coefficient, [-]
- * f, Fugacity, MPa
- * gamma, Isoentropic exponent, [-]
-
- * alfav, Thermal expansion coefficient (Volume expansivity), 1/K
- * kappa, Isothermal compressibility, 1/MPa
- * alfap, Relative pressure coefficient, 1/K
- * betap, Isothermal stress coefficient, kg/m³
- * betas, Isoentropic temperature-pressure coefficient, [-]
- * joule, Joule-Thomson coefficient, K/MPa
- * Gruneisen, Gruneisen parameter, [-]
- * virialB, Second virial coefficient, m³/kg
- * virialC, Third virial coefficient, m⁶/kg²
- * dpdT_rho, Derivatives, dp/dT at constant rho, MPa/K
- * dpdrho_T, Derivatives, dp/drho at constant T, MPa·m³/kg
- * drhodT_P, Derivatives, drho/dT at constant P, kg/m³·K
- * drhodP_T, Derivatives, drho/dP at constant T, kg/m³·MPa
- * dhdT_rho, Derivatives, dh/dT at constant rho, kJ/kg·K
- * dhdP_T, Isothermal throttling coefficient, kJ/kg·MPa
- * dhdT_P, Derivatives, dh/dT at constant P, kJ/kg·K
- * dhdrho_T, Derivatives, dh/drho at constant T, kJ·m³/kg²
- * dhdrho_P, Derivatives, dh/drho at constant P, kJ·m³/kg²
- * dhdP_rho, Derivatives, dh/dP at constant rho, kJ/kg·MPa
- * kt, Isothermal Expansion Coefficient, [-]
- * ks, Adiabatic Compressibility, 1/MPa
- * Ks, Adiabatic bulk modulus, MPa
- * Kt, Isothermal bulk modulus, MPa
-
- * Hvap, Vaporization heat, kJ/kg
- * Z_rho, (Z-1) over the density, m³/kg
- * IntP, Internal pressure, MPa
- * invT, Negative reciprocal temperature, 1/K
- * hInput, Specific heat input, kJ/kg
-
- * mu, Dynamic viscosity, Pa·s
- * nu, Kinematic viscosity, m²/s
- * k, Thermal conductivity, W/m·K
- * sigma, Surface tension, N/m
- * alfa, Thermal diffusivity, m²/s
- * Pramdt, Prandtl number, [-]
- * epsilon, Dielectric constant, [-]
- * n, Refractive index, [-]
-
- * v0, Ideal gas Specific volume, m³/kg
- * rho0, Ideal gas Density, kg/m³
- * h0, Ideal gas Specific enthalpy, kJ/kg
- * u0, Ideal gas Specific internal energy, kJ/kg
- * s0, Ideal gas Specific entropy, kJ/kg·K
- * a0, Ideal gas Specific Helmholtz free energy, kJ/kg
- * g0, Ideal gas Specific Gibbs free energy, kJ/kg
- * cp0, Ideal gas Specific isobaric heat capacity, kJ/kg·K
- * cv0, Ideal gas Specific isochoric heat capacity, kJ/kg·K
- * cp0_cv, Ideal gas Heat capacity ratio, [-]
- * gamma0, Ideal gas Isoentropic exponent, [-]
-
-
- Usage::
+
+ .. code:: python
from iapws import IAPWS95
sat_steam=IAPWS95(P=1,x=1) #saturated steam with known P
sat_liquid=IAPWS95(T=370, x=0) #saturated liquid with known T
steam=IAPWS95(P=2.5, T=500) #steam with known P and T
print(sat_steam.h, sat_liquid.h, steam.h) #calculated enthalpies
+
+
+ IAPWS-05 for Heavy water
+
+ .. code:: python
+
+ from iapws import D2O
+ sat_liquid=D2O(T=370, x=0) #saturated liquid with known T
+ print(sat_liquid.h) #calculated enthalpy
-
IAPWS-06 for Ice Ih
- --------------------------------------------
-
- There is too implemented a function to calculate properties of ice Ih from 2009 revision, in this case only let temperature and pressure as input for calculate properties, the function return a dict with properties available:
-
- * P, Pressure, MPa
- * T, Temperature, K
- * v, Specific volume, m³/kg
- * rho, Density, kg/m³
- * g, Specific Gibbs free energy, kJ/kg
- * a, Specific Helmholtz free energy, kJ/kg
- * h, Specific enthalpy, kJ/kg
- * u, Specific internal energy, kJ/kg
- * s, Specific entropy, kJ/kg·K
- * cp, Specific isobaric heat capacity, kJ/kg·K
- * alfa, Cubic expansion coefficient, 1/K
- * beta, Pressure coefficient, MPa/K
- * kt, Isothermal compressibility, MPa
- * ks, Isentropic compressibility, MPa
-
- Usage::
-
+ .. code:: python
+
from iapws import _Ice
ice=_Ice(273.15, 0.101325) #Ice at normal melting point
print(ice["rho"]) #Calculated density
-
- IAPWS-05 for Heavy water
- --------------------------------------------
-
- Same properties as for IAPWS-95
- Reference state set at liquid at normal boiling point (1 atm)
- Usage::
+ IAPWS-08 for seawater
- from iapws import D2O
- sat_liquid=D2O(T=370, x=0) #saturated liquid with known T
- print(sat_liquid.h) #calculated enthalpy
+ .. code:: python
-
- IAPWS-08 for seawater
- --------------------------------------------
-
- Incoming properties:
-
- * T: Temperature, K
- * P: Pressure, MPa
- * S: Salinity, kg/kg
-
- S is the Reference-Composition Salinity as defined in Millero, F.J., R. Feistel, D.G. Wright and T.J. McDougall, "The composition of Standard Seawater and the definition of the Reference-Composition Salinity Scale", Deep-Sea Res. I 55, 50 (2008).
-
- Calculated properties:
-
- * T: Temperature, K
- * P: Pressure, MPa
- * rho: Density, kg/m³
- * v: Specific volume, m³/kg
- * h: Specific enthalpy, kJ/kg
- * s: Specific entropy, kJ/kg·K
- * u: Specific internal energy, kJ/kg
- * g: Specific Gibbs free energy, kJ/kg
- * a: Specific Helmholtz free energy, kJ/kg
- * cp: Specific isobaric heat capacity, kJ/kg·K
-
- * gt: Derivative Gibbs energy with temperature, kJ/kg·K
- * gp: Derivative Gibbs energy with pressure, m³/kg
- * gtt: Derivative Gibbs energy with temperature square, kJ/kg·K²
- * gtp: Derivative Gibbs energy with pressure and temperature, m³/kg·K
- * gpp: Derivative Gibbs energy with temperature square, m³/kg·MPa
- * gs: Derivative Gibbs energy with salinity, kJ/kg
- * gsp: Derivative Gibbs energy with salinity and pressure, m³/kg
-
- * alfa: Thermal expansion coefficient, 1/K
- * betas: Isentropic temperature-pressure coefficient, K/MPa
- * kt: Isothermal compressibility, 1/MPa
- * ks: Isentropic compressibility, 1/MPa
- * w: Sound Speed, m/s
-
- * mu: Relative chemical potential, kJ/kg
- * muw: Chemical potential of H2O, kJ/kg
- * mus: Chemical potential of sea salt, kJ/kg
- * osm: Osmotic coefficient, [-]
- * haline: Haline contraction coefficient, kg/kg
-
-
- Usage::
-
from iapws import SeaWater
state = SeaWater(T=300, P=0.101325, S=0.001) #Seawater with 0.1% Salinity
- print(state.cp) # Get cp
+ print(state.cp) # Get cp
+
+
+ TODO
+ ====
+
+ * FIXME: Electrolytic conductiviy
+ * TODO: Improve convergence in two phase region for IAPWS95 and D2O class
+ * TODO: Implement SBTL method for fast calculation
+ * TODO: Implement TTSE method for fast calculation
+
+ Ammonia-water mixture:
+
+ * FIXME: Ammonia-water mixture residual helmholtz. The values are good, bad difer by 1%
+ * TODO: Add equilibrium routine
+
+ I've tried to test all code and use all values for computer verification the standards give, but anyway the code can have hidden problem.
+ For any suggestions, comments, bugs ... you can usage the `github issue section <https://github.com/jjgomera/iapws/issues>`__, or contact directly with me at `email <jjgomera at gmail.com>`__.
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
diff --git a/README.rst b/README.rst
index e97406b..c700feb 100644
--- a/README.rst
+++ b/README.rst
@@ -1,14 +1,40 @@
+.. image:: https://api.travis-ci.org/jjgomera/iapws.svg?branch=master
+ :target: https://travis-ci.org/jjgomera/iapws
+ :alt: Build Status
+
+.. image:: https://ci.appveyor.com/api/projects/status/a128sh8e50cjsiya?svg=true
+ :target: https://ci.appveyor.com/project/jjgomera/iapws
+ :alt: Windows Build Status
+
+.. image:: https://coveralls.io/repos/github/jjgomera/iapws/badge.svg?branch=master
+ :target: https://coveralls.io/github/jjgomera/iapws?branch=master
+ :alt: coveralls.io analysis
+
+.. image:: https://codecov.io/gh/jjgomera/iapws/branch/master/graph/badge.svg
+ :target: https://codecov.io/gh/jjgomera/iapws
+ :alt: codecov.io analysis
+
+.. image:: https://landscape.io/github/jjgomera/iapws/master/landscape.svg?style=flat
+ :target: https://landscape.io/github/jjgomera/iapws/master
+ :alt: Code Health
+
+.. image:: http://readthedocs.org/projects/iapws/badge/?version=latest
+ :target: http://iapws.readthedocs.io/en/latest/?badge=latest
+ :alt: Documentation Status
+
iapws
=====
-Python implementation of standard from IAPWS (http://www.iapws.org/release.html). The available standard are::
+Python implementation of standard from IAPWS (http://www.iapws.org/release.html). The module implements the full set of standards, including::
IAPWS-IF97
IAPWS-95
IAPWS-06 for Ice
IAPWS-08 for seawater
IAPWS-05 for Heavy water
+ ...
+
dependences
--------------------
@@ -19,92 +45,30 @@ dependences
install
--------------------
-In debian you can find in official repositories in testing and sid. In stable you can install using pip::
+In debian you can find in official repositories in jessie, testing and sid. In ubuntu it's in official repositories from ubuntu saucy (13.10). In other system you can install using pip::
pip install iapws
+
+or directly cloning the github repository::
-In ubuntu it's in official repositories from ubuntu saucy (13.10)
-
-In other SO you can download from its webpage in `pypi <http://pypi.python.org/pypi/iapws>`_ and unzipped in python folder dist-packages. This is the recommended options to have the latest version.
-
-
-TODO
---------------------
+ git clone https://github.com/jjgomera/iapws.git
-Improve convergence in two phase region for IAPWS95 and D2O class
+and adding the folder to a python path. This is the recommended option to have the latest version.
-IAPWS-IF97
+documentation
--------------------
+
+To see the full documentation of package, see `readthedocs <http://iapws.readthedocs.io/>`__
-Class to model a state for liquid water or steam with the Industrial Formulation IAPWS-IF97
+.. inclusion-marker-do-not-remove
-Incoming properties:
+For a rapid usage demostration, see this examples
-* T, Temperature, K
-* P, Pressure, MPa
-* h, Specific enthalpy, kJ/kg
-* s, Specific entropy, kJ/kg·K
-* x, Quality, [-]
-
-Definitions options:
-
-* T, P (Not valid for two-phases region)
-* P, h
-* P, s
-* h, s
-* T, x (Only for two-phases region)
-* P, x (Only for two-phases region)
-
-Properties:
-
-* P, Pressure, MPa
-* T, Temperature, K
-* g, Specific Gibbs free energy, kJ/kg
-* a, Specific Helmholtz free energy, kJ/kg
-* v, Specific volume, m³/kg
-* rho, Density, kg/m³
-* x, quality, [-]
-* h, Specific enthalpy, kJ/kg
-* u, Specific internal energy, kJ/kg
-* s, Specific entropy, kJ/kg·K
-* cp, Specific isobaric heat capacity, kJ/kg·K
-* cv, Specific isochoric heat capacity, kJ/kg·K
-* Z, Compression factor. [-]
-* gamma, Isoentropic exponent, [-]
-* alfav, Isobaric cubic expansion coefficient, 1/K
-* kt, Isothermal compressibility, 1/MPa
-* alfap, Relative pressure coefficient, 1/K
-* betap, Isothermal stress coefficient, kg/m³
-* joule, Joule-Thomson coefficient, K/MPa
-* deltat, Isothermal throttling coefficient, kJ/kg·MPa
-* region, Region
-
-* v0, Ideal specific volume, m³/kg
-* u0, Ideal specific internal energy, kJ/kg
-* h0, Ideal specific enthalpy, kJ/kg
-* s0, Ideal specific entropy, kJ/kg·K
-* a0, Ideal specific Helmholtz free energy, kJ/kg
-* g0, Ideal specific Gibbs free energy, kJ/kg
-* cp0, Ideal specific isobaric heat capacity, kJ/kg·K
-* cv0, Ideal specific isochoric heat capacity, kJ/kg·K
-* w0, Ideal speed of sound, m/s
-* gamma0, Ideal isoentropic exponent [-]
-
-* w, Speed of sound, m/s
-* mu, Dynamic viscosity, Pa·s
-* nu, Kinematic viscosity, m²/s
-* k, Thermal conductivity, W/m·K
-* alfa, Thermal diffusivity, m²/s
-* sigma, Surface tension, N/m
-* epsilon, Dielectric constant, [-]
-* n, Refractive index, [-]
-* Prandt, Prandtl number, [-]
-* Tr, Reduced temperature, [-]
-* Pr, Reduced pressure, [-]
+IAPWS-IF97
-Usage::
+.. code:: python
from iapws import IAPWS97
sat_steam=IAPWS97(P=1,x=1) #saturated steam with known P
@@ -112,218 +76,57 @@ Usage::
steam=IAPWS97(P=2.5, T=500) #steam with known P and T
print(sat_steam.h, sat_liquid.h, steam.h) #calculated enthalpies
-
-
+
IAPWS-95
---------------------------------
-
-Class to model a state for liquid water or steam with the general and scientific formulation IAPWS-95
-
-Incoming properties:
-
-* T, Temperature, K
-* P, Pressure, MPa
-* rho, Density, kg/m3
-* v, Specific volume, m3/kg
-* h, Specific enthalpy, kJ/kg
-* s, Specific entropy, kJ/kg·K
-* x, Quality, [-]
-* l, Optional parameter to light wavelength for Refractive index, mm
-
-rho and v are equivalent, only one can be defined
-Definitions options:
-
-* T, P (Not valid for two-phases region)
-* T, rho
-* T, h
-* T, s
-* T, u
-* P, rho
-* P, h
-* P, s
-* P, u
-* rho, h
-* rho, s
-* rho, u
-* h, s
-* h, u
-* s, u
-* T, x (Only for two-phases region)
-* P, x (Only for two-phases region) Very slow
-
-Properties:
-
-* P, Pressure, MPa
-* Pr, Reduced pressure, [-]
-* T, Temperature, K
-* Tr, Reduced temperature, [-]
-* x, Quality, [-]
-* v, Specific volume, m³/kg
-* rho, Density, kg/m³
-* h, Specific enthalpy, kJ/kg
-* s, Specific entropy, kJ/kg·K
-* u, Specific internal energy, kJ/kg
-* g, Specific Gibbs free energy, kJ/kg
-* a, Specific Helmholtz free energy, kJ/kg
-* cp, Specific isobaric heat capacity, kJ/kg·K
-* cv, Specific isochoric heat capacity, kJ/kg·K
-* cp_cv, Heat capacity ratio, [-]
-* w, Speed of sound, m/s
-* Z, Compression factor, [-]
-* fi, Fugacity coefficient, [-]
-* f, Fugacity, MPa
-* gamma, Isoentropic exponent, [-]
-
-* alfav, Thermal expansion coefficient (Volume expansivity), 1/K
-* kappa, Isothermal compressibility, 1/MPa
-* alfap, Relative pressure coefficient, 1/K
-* betap, Isothermal stress coefficient, kg/m³
-* betas, Isoentropic temperature-pressure coefficient, [-]
-* joule, Joule-Thomson coefficient, K/MPa
-* Gruneisen, Gruneisen parameter, [-]
-* virialB, Second virial coefficient, m³/kg
-* virialC, Third virial coefficient, m⁶/kg²
-* dpdT_rho, Derivatives, dp/dT at constant rho, MPa/K
-* dpdrho_T, Derivatives, dp/drho at constant T, MPa·m³/kg
-* drhodT_P, Derivatives, drho/dT at constant P, kg/m³·K
-* drhodP_T, Derivatives, drho/dP at constant T, kg/m³·MPa
-* dhdT_rho, Derivatives, dh/dT at constant rho, kJ/kg·K
-* dhdP_T, Isothermal throttling coefficient, kJ/kg·MPa
-* dhdT_P, Derivatives, dh/dT at constant P, kJ/kg·K
-* dhdrho_T, Derivatives, dh/drho at constant T, kJ·m³/kg²
-* dhdrho_P, Derivatives, dh/drho at constant P, kJ·m³/kg²
-* dhdP_rho, Derivatives, dh/dP at constant rho, kJ/kg·MPa
-* kt, Isothermal Expansion Coefficient, [-]
-* ks, Adiabatic Compressibility, 1/MPa
-* Ks, Adiabatic bulk modulus, MPa
-* Kt, Isothermal bulk modulus, MPa
-
-* Hvap, Vaporization heat, kJ/kg
-* Z_rho, (Z-1) over the density, m³/kg
-* IntP, Internal pressure, MPa
-* invT, Negative reciprocal temperature, 1/K
-* hInput, Specific heat input, kJ/kg
-
-* mu, Dynamic viscosity, Pa·s
-* nu, Kinematic viscosity, m²/s
-* k, Thermal conductivity, W/m·K
-* sigma, Surface tension, N/m
-* alfa, Thermal diffusivity, m²/s
-* Pramdt, Prandtl number, [-]
-* epsilon, Dielectric constant, [-]
-* n, Refractive index, [-]
-
-* v0, Ideal gas Specific volume, m³/kg
-* rho0, Ideal gas Density, kg/m³
-* h0, Ideal gas Specific enthalpy, kJ/kg
-* u0, Ideal gas Specific internal energy, kJ/kg
-* s0, Ideal gas Specific entropy, kJ/kg·K
-* a0, Ideal gas Specific Helmholtz free energy, kJ/kg
-* g0, Ideal gas Specific Gibbs free energy, kJ/kg
-* cp0, Ideal gas Specific isobaric heat capacity, kJ/kg·K
-* cv0, Ideal gas Specific isochoric heat capacity, kJ/kg·K
-* cp0_cv, Ideal gas Heat capacity ratio, [-]
-* gamma0, Ideal gas Isoentropic exponent, [-]
-
-
-Usage::
+
+.. code:: python
from iapws import IAPWS95
sat_steam=IAPWS95(P=1,x=1) #saturated steam with known P
sat_liquid=IAPWS95(T=370, x=0) #saturated liquid with known T
steam=IAPWS95(P=2.5, T=500) #steam with known P and T
print(sat_steam.h, sat_liquid.h, steam.h) #calculated enthalpies
+
+
+IAPWS-05 for Heavy water
+
+.. code:: python
+
+ from iapws import D2O
+ sat_liquid=D2O(T=370, x=0) #saturated liquid with known T
+ print(sat_liquid.h) #calculated enthalpy
-
IAPWS-06 for Ice Ih
---------------------------------------------
-
-There is too implemented a function to calculate properties of ice Ih from 2009 revision, in this case only let temperature and pressure as input for calculate properties, the function return a dict with properties available:
-
-* P, Pressure, MPa
-* T, Temperature, K
-* v, Specific volume, m³/kg
-* rho, Density, kg/m³
-* g, Specific Gibbs free energy, kJ/kg
-* a, Specific Helmholtz free energy, kJ/kg
-* h, Specific enthalpy, kJ/kg
-* u, Specific internal energy, kJ/kg
-* s, Specific entropy, kJ/kg·K
-* cp, Specific isobaric heat capacity, kJ/kg·K
-* alfa, Cubic expansion coefficient, 1/K
-* beta, Pressure coefficient, MPa/K
-* kt, Isothermal compressibility, MPa
-* ks, Isentropic compressibility, MPa
-
-Usage::
-
+.. code:: python
+
from iapws import _Ice
ice=_Ice(273.15, 0.101325) #Ice at normal melting point
print(ice["rho"]) #Calculated density
-
-IAPWS-05 for Heavy water
---------------------------------------------
-
-Same properties as for IAPWS-95
-Reference state set at liquid at normal boiling point (1 atm)
-Usage::
+IAPWS-08 for seawater
- from iapws import D2O
- sat_liquid=D2O(T=370, x=0) #saturated liquid with known T
- print(sat_liquid.h) #calculated enthalpy
+.. code:: python
-
-IAPWS-08 for seawater
---------------------------------------------
-
-Incoming properties:
-
-* T: Temperature, K
-* P: Pressure, MPa
-* S: Salinity, kg/kg
-
-S is the Reference-Composition Salinity as defined in Millero, F.J., R. Feistel, D.G. Wright and T.J. McDougall, "The composition of Standard Seawater and the definition of the Reference-Composition Salinity Scale", Deep-Sea Res. I 55, 50 (2008).
-
-Calculated properties:
-
-* T: Temperature, K
-* P: Pressure, MPa
-* rho: Density, kg/m³
-* v: Specific volume, m³/kg
-* h: Specific enthalpy, kJ/kg
-* s: Specific entropy, kJ/kg·K
-* u: Specific internal energy, kJ/kg
-* g: Specific Gibbs free energy, kJ/kg
-* a: Specific Helmholtz free energy, kJ/kg
-* cp: Specific isobaric heat capacity, kJ/kg·K
-
-* gt: Derivative Gibbs energy with temperature, kJ/kg·K
-* gp: Derivative Gibbs energy with pressure, m³/kg
-* gtt: Derivative Gibbs energy with temperature square, kJ/kg·K²
-* gtp: Derivative Gibbs energy with pressure and temperature, m³/kg·K
-* gpp: Derivative Gibbs energy with temperature square, m³/kg·MPa
-* gs: Derivative Gibbs energy with salinity, kJ/kg
-* gsp: Derivative Gibbs energy with salinity and pressure, m³/kg
-
-* alfa: Thermal expansion coefficient, 1/K
-* betas: Isentropic temperature-pressure coefficient, K/MPa
-* kt: Isothermal compressibility, 1/MPa
-* ks: Isentropic compressibility, 1/MPa
-* w: Sound Speed, m/s
-
-* mu: Relative chemical potential, kJ/kg
-* muw: Chemical potential of H2O, kJ/kg
-* mus: Chemical potential of sea salt, kJ/kg
-* osm: Osmotic coefficient, [-]
-* haline: Haline contraction coefficient, kg/kg
-
-
-Usage::
-
from iapws import SeaWater
state = SeaWater(T=300, P=0.101325, S=0.001) #Seawater with 0.1% Salinity
- print(state.cp) # Get cp
+ print(state.cp) # Get cp
+
+
+TODO
+====
+
+* FIXME: Electrolytic conductiviy
+* TODO: Improve convergence in two phase region for IAPWS95 and D2O class
+* TODO: Implement SBTL method for fast calculation
+* TODO: Implement TTSE method for fast calculation
+
+Ammonia-water mixture:
+
+* FIXME: Ammonia-water mixture residual helmholtz. The values are good, bad difer by 1%
+* TODO: Add equilibrium routine
+
+I've tried to test all code and use all values for computer verification the standards give, but anyway the code can have hidden problem.
+For any suggestions, comments, bugs ... you can usage the `github issue section <https://github.com/jjgomera/iapws/issues>`__, or contact directly with me at `email <jjgomera at gmail.com>`__.
diff --git a/iapws.egg-info/PKG-INFO b/iapws.egg-info/PKG-INFO
index f189454..d8d6fbe 100644
--- a/iapws.egg-info/PKG-INFO
+++ b/iapws.egg-info/PKG-INFO
@@ -1,23 +1,49 @@
Metadata-Version: 1.1
Name: iapws
-Version: 1.1.3
+Version: 1.2
Summary: Python implementation of standards from The InternationalAssociation for the Properties of Water and Steam
Home-page: https://github.com/jjgomera/iapws
Author: jjgomera
Author-email: jjgomera at gmail.com
License: gpl v3
-Download-URL: https://github.com/jjgomera/iapws/tarball/v1.1.3
-Description: iapws
+Download-URL: https://github.com/jjgomera/iapws/tarball/v1.2
+Description: .. image:: https://api.travis-ci.org/jjgomera/iapws.svg?branch=master
+ :target: https://travis-ci.org/jjgomera/iapws
+ :alt: Build Status
+
+ .. image:: https://ci.appveyor.com/api/projects/status/a128sh8e50cjsiya?svg=true
+ :target: https://ci.appveyor.com/project/jjgomera/iapws
+ :alt: Windows Build Status
+
+ .. image:: https://coveralls.io/repos/github/jjgomera/iapws/badge.svg?branch=master
+ :target: https://coveralls.io/github/jjgomera/iapws?branch=master
+ :alt: coveralls.io analysis
+
+ .. image:: https://codecov.io/gh/jjgomera/iapws/branch/master/graph/badge.svg
+ :target: https://codecov.io/gh/jjgomera/iapws
+ :alt: codecov.io analysis
+
+ .. image:: https://landscape.io/github/jjgomera/iapws/master/landscape.svg?style=flat
+ :target: https://landscape.io/github/jjgomera/iapws/master
+ :alt: Code Health
+
+ .. image:: http://readthedocs.org/projects/iapws/badge/?version=latest
+ :target: http://iapws.readthedocs.io/en/latest/?badge=latest
+ :alt: Documentation Status
+
+ iapws
=====
- Python implementation of standard from IAPWS (http://www.iapws.org/release.html). The available standard are::
+ Python implementation of standard from IAPWS (http://www.iapws.org/release.html). The module implements the full set of standards, including::
IAPWS-IF97
IAPWS-95
IAPWS-06 for Ice
IAPWS-08 for seawater
IAPWS-05 for Heavy water
+ ...
+
dependences
--------------------
@@ -28,92 +54,30 @@ Description: iapws
install
--------------------
- In debian you can find in official repositories in testing and sid. In stable you can install using pip::
+ In debian you can find in official repositories in jessie, testing and sid. In ubuntu it's in official repositories from ubuntu saucy (13.10). In other system you can install using pip::
pip install iapws
+
+ or directly cloning the github repository::
- In ubuntu it's in official repositories from ubuntu saucy (13.10)
-
- In other SO you can download from its webpage in `pypi <http://pypi.python.org/pypi/iapws>`_ and unzipped in python folder dist-packages. This is the recommended options to have the latest version.
-
-
- TODO
- --------------------
+ git clone https://github.com/jjgomera/iapws.git
- Improve convergence in two phase region for IAPWS95 and D2O class
+ and adding the folder to a python path. This is the recommended option to have the latest version.
- IAPWS-IF97
+ documentation
--------------------
+
+ To see the full documentation of package, see `readthedocs <http://iapws.readthedocs.io/>`__
- Class to model a state for liquid water or steam with the Industrial Formulation IAPWS-IF97
+ .. inclusion-marker-do-not-remove
- Incoming properties:
+ For a rapid usage demostration, see this examples
- * T, Temperature, K
- * P, Pressure, MPa
- * h, Specific enthalpy, kJ/kg
- * s, Specific entropy, kJ/kg·K
- * x, Quality, [-]
-
- Definitions options:
-
- * T, P (Not valid for two-phases region)
- * P, h
- * P, s
- * h, s
- * T, x (Only for two-phases region)
- * P, x (Only for two-phases region)
-
- Properties:
-
- * P, Pressure, MPa
- * T, Temperature, K
- * g, Specific Gibbs free energy, kJ/kg
- * a, Specific Helmholtz free energy, kJ/kg
- * v, Specific volume, m³/kg
- * rho, Density, kg/m³
- * x, quality, [-]
- * h, Specific enthalpy, kJ/kg
- * u, Specific internal energy, kJ/kg
- * s, Specific entropy, kJ/kg·K
- * cp, Specific isobaric heat capacity, kJ/kg·K
- * cv, Specific isochoric heat capacity, kJ/kg·K
- * Z, Compression factor. [-]
- * gamma, Isoentropic exponent, [-]
- * alfav, Isobaric cubic expansion coefficient, 1/K
- * kt, Isothermal compressibility, 1/MPa
- * alfap, Relative pressure coefficient, 1/K
- * betap, Isothermal stress coefficient, kg/m³
- * joule, Joule-Thomson coefficient, K/MPa
- * deltat, Isothermal throttling coefficient, kJ/kg·MPa
- * region, Region
-
- * v0, Ideal specific volume, m³/kg
- * u0, Ideal specific internal energy, kJ/kg
- * h0, Ideal specific enthalpy, kJ/kg
- * s0, Ideal specific entropy, kJ/kg·K
- * a0, Ideal specific Helmholtz free energy, kJ/kg
- * g0, Ideal specific Gibbs free energy, kJ/kg
- * cp0, Ideal specific isobaric heat capacity, kJ/kg·K
- * cv0, Ideal specific isochoric heat capacity, kJ/kg·K
- * w0, Ideal speed of sound, m/s
- * gamma0, Ideal isoentropic exponent [-]
-
- * w, Speed of sound, m/s
- * mu, Dynamic viscosity, Pa·s
- * nu, Kinematic viscosity, m²/s
- * k, Thermal conductivity, W/m·K
- * alfa, Thermal diffusivity, m²/s
- * sigma, Surface tension, N/m
- * epsilon, Dielectric constant, [-]
- * n, Refractive index, [-]
- * Prandt, Prandtl number, [-]
- * Tr, Reduced temperature, [-]
- * Pr, Reduced pressure, [-]
+ IAPWS-IF97
- Usage::
+ .. code:: python
from iapws import IAPWS97
sat_steam=IAPWS97(P=1,x=1) #saturated steam with known P
@@ -121,221 +85,60 @@ Description: iapws
steam=IAPWS97(P=2.5, T=500) #steam with known P and T
print(sat_steam.h, sat_liquid.h, steam.h) #calculated enthalpies
-
-
+
IAPWS-95
- --------------------------------
-
- Class to model a state for liquid water or steam with the general and scientific formulation IAPWS-95
-
- Incoming properties:
-
- * T, Temperature, K
- * P, Pressure, MPa
- * rho, Density, kg/m3
- * v, Specific volume, m3/kg
- * h, Specific enthalpy, kJ/kg
- * s, Specific entropy, kJ/kg·K
- * x, Quality, [-]
- * l, Optional parameter to light wavelength for Refractive index, mm
-
- rho and v are equivalent, only one can be defined
- Definitions options:
-
- * T, P (Not valid for two-phases region)
- * T, rho
- * T, h
- * T, s
- * T, u
- * P, rho
- * P, h
- * P, s
- * P, u
- * rho, h
- * rho, s
- * rho, u
- * h, s
- * h, u
- * s, u
- * T, x (Only for two-phases region)
- * P, x (Only for two-phases region) Very slow
-
- Properties:
-
- * P, Pressure, MPa
- * Pr, Reduced pressure, [-]
- * T, Temperature, K
- * Tr, Reduced temperature, [-]
- * x, Quality, [-]
- * v, Specific volume, m³/kg
- * rho, Density, kg/m³
- * h, Specific enthalpy, kJ/kg
- * s, Specific entropy, kJ/kg·K
- * u, Specific internal energy, kJ/kg
- * g, Specific Gibbs free energy, kJ/kg
- * a, Specific Helmholtz free energy, kJ/kg
- * cp, Specific isobaric heat capacity, kJ/kg·K
- * cv, Specific isochoric heat capacity, kJ/kg·K
- * cp_cv, Heat capacity ratio, [-]
- * w, Speed of sound, m/s
- * Z, Compression factor, [-]
- * fi, Fugacity coefficient, [-]
- * f, Fugacity, MPa
- * gamma, Isoentropic exponent, [-]
-
- * alfav, Thermal expansion coefficient (Volume expansivity), 1/K
- * kappa, Isothermal compressibility, 1/MPa
- * alfap, Relative pressure coefficient, 1/K
- * betap, Isothermal stress coefficient, kg/m³
- * betas, Isoentropic temperature-pressure coefficient, [-]
- * joule, Joule-Thomson coefficient, K/MPa
- * Gruneisen, Gruneisen parameter, [-]
- * virialB, Second virial coefficient, m³/kg
- * virialC, Third virial coefficient, m⁶/kg²
- * dpdT_rho, Derivatives, dp/dT at constant rho, MPa/K
- * dpdrho_T, Derivatives, dp/drho at constant T, MPa·m³/kg
- * drhodT_P, Derivatives, drho/dT at constant P, kg/m³·K
- * drhodP_T, Derivatives, drho/dP at constant T, kg/m³·MPa
- * dhdT_rho, Derivatives, dh/dT at constant rho, kJ/kg·K
- * dhdP_T, Isothermal throttling coefficient, kJ/kg·MPa
- * dhdT_P, Derivatives, dh/dT at constant P, kJ/kg·K
- * dhdrho_T, Derivatives, dh/drho at constant T, kJ·m³/kg²
- * dhdrho_P, Derivatives, dh/drho at constant P, kJ·m³/kg²
- * dhdP_rho, Derivatives, dh/dP at constant rho, kJ/kg·MPa
- * kt, Isothermal Expansion Coefficient, [-]
- * ks, Adiabatic Compressibility, 1/MPa
- * Ks, Adiabatic bulk modulus, MPa
- * Kt, Isothermal bulk modulus, MPa
-
- * Hvap, Vaporization heat, kJ/kg
- * Z_rho, (Z-1) over the density, m³/kg
- * IntP, Internal pressure, MPa
- * invT, Negative reciprocal temperature, 1/K
- * hInput, Specific heat input, kJ/kg
-
- * mu, Dynamic viscosity, Pa·s
- * nu, Kinematic viscosity, m²/s
- * k, Thermal conductivity, W/m·K
- * sigma, Surface tension, N/m
- * alfa, Thermal diffusivity, m²/s
- * Pramdt, Prandtl number, [-]
- * epsilon, Dielectric constant, [-]
- * n, Refractive index, [-]
-
- * v0, Ideal gas Specific volume, m³/kg
- * rho0, Ideal gas Density, kg/m³
- * h0, Ideal gas Specific enthalpy, kJ/kg
- * u0, Ideal gas Specific internal energy, kJ/kg
- * s0, Ideal gas Specific entropy, kJ/kg·K
- * a0, Ideal gas Specific Helmholtz free energy, kJ/kg
- * g0, Ideal gas Specific Gibbs free energy, kJ/kg
- * cp0, Ideal gas Specific isobaric heat capacity, kJ/kg·K
- * cv0, Ideal gas Specific isochoric heat capacity, kJ/kg·K
- * cp0_cv, Ideal gas Heat capacity ratio, [-]
- * gamma0, Ideal gas Isoentropic exponent, [-]
-
-
- Usage::
+
+ .. code:: python
from iapws import IAPWS95
sat_steam=IAPWS95(P=1,x=1) #saturated steam with known P
sat_liquid=IAPWS95(T=370, x=0) #saturated liquid with known T
steam=IAPWS95(P=2.5, T=500) #steam with known P and T
print(sat_steam.h, sat_liquid.h, steam.h) #calculated enthalpies
+
+
+ IAPWS-05 for Heavy water
+
+ .. code:: python
+
+ from iapws import D2O
+ sat_liquid=D2O(T=370, x=0) #saturated liquid with known T
+ print(sat_liquid.h) #calculated enthalpy
-
IAPWS-06 for Ice Ih
- --------------------------------------------
-
- There is too implemented a function to calculate properties of ice Ih from 2009 revision, in this case only let temperature and pressure as input for calculate properties, the function return a dict with properties available:
-
- * P, Pressure, MPa
- * T, Temperature, K
- * v, Specific volume, m³/kg
- * rho, Density, kg/m³
- * g, Specific Gibbs free energy, kJ/kg
- * a, Specific Helmholtz free energy, kJ/kg
- * h, Specific enthalpy, kJ/kg
- * u, Specific internal energy, kJ/kg
- * s, Specific entropy, kJ/kg·K
- * cp, Specific isobaric heat capacity, kJ/kg·K
- * alfa, Cubic expansion coefficient, 1/K
- * beta, Pressure coefficient, MPa/K
- * kt, Isothermal compressibility, MPa
- * ks, Isentropic compressibility, MPa
-
- Usage::
-
+ .. code:: python
+
from iapws import _Ice
ice=_Ice(273.15, 0.101325) #Ice at normal melting point
print(ice["rho"]) #Calculated density
-
- IAPWS-05 for Heavy water
- --------------------------------------------
-
- Same properties as for IAPWS-95
- Reference state set at liquid at normal boiling point (1 atm)
- Usage::
+ IAPWS-08 for seawater
- from iapws import D2O
- sat_liquid=D2O(T=370, x=0) #saturated liquid with known T
- print(sat_liquid.h) #calculated enthalpy
+ .. code:: python
-
- IAPWS-08 for seawater
- --------------------------------------------
-
- Incoming properties:
-
- * T: Temperature, K
- * P: Pressure, MPa
- * S: Salinity, kg/kg
-
- S is the Reference-Composition Salinity as defined in Millero, F.J., R. Feistel, D.G. Wright and T.J. McDougall, "The composition of Standard Seawater and the definition of the Reference-Composition Salinity Scale", Deep-Sea Res. I 55, 50 (2008).
-
- Calculated properties:
-
- * T: Temperature, K
- * P: Pressure, MPa
- * rho: Density, kg/m³
- * v: Specific volume, m³/kg
- * h: Specific enthalpy, kJ/kg
- * s: Specific entropy, kJ/kg·K
- * u: Specific internal energy, kJ/kg
- * g: Specific Gibbs free energy, kJ/kg
- * a: Specific Helmholtz free energy, kJ/kg
- * cp: Specific isobaric heat capacity, kJ/kg·K
-
- * gt: Derivative Gibbs energy with temperature, kJ/kg·K
- * gp: Derivative Gibbs energy with pressure, m³/kg
- * gtt: Derivative Gibbs energy with temperature square, kJ/kg·K²
- * gtp: Derivative Gibbs energy with pressure and temperature, m³/kg·K
- * gpp: Derivative Gibbs energy with temperature square, m³/kg·MPa
- * gs: Derivative Gibbs energy with salinity, kJ/kg
- * gsp: Derivative Gibbs energy with salinity and pressure, m³/kg
-
- * alfa: Thermal expansion coefficient, 1/K
- * betas: Isentropic temperature-pressure coefficient, K/MPa
- * kt: Isothermal compressibility, 1/MPa
- * ks: Isentropic compressibility, 1/MPa
- * w: Sound Speed, m/s
-
- * mu: Relative chemical potential, kJ/kg
- * muw: Chemical potential of H2O, kJ/kg
- * mus: Chemical potential of sea salt, kJ/kg
- * osm: Osmotic coefficient, [-]
- * haline: Haline contraction coefficient, kg/kg
-
-
- Usage::
-
from iapws import SeaWater
state = SeaWater(T=300, P=0.101325, S=0.001) #Seawater with 0.1% Salinity
- print(state.cp) # Get cp
+ print(state.cp) # Get cp
+
+
+ TODO
+ ====
+
+ * FIXME: Electrolytic conductiviy
+ * TODO: Improve convergence in two phase region for IAPWS95 and D2O class
+ * TODO: Implement SBTL method for fast calculation
+ * TODO: Implement TTSE method for fast calculation
+
+ Ammonia-water mixture:
+
+ * FIXME: Ammonia-water mixture residual helmholtz. The values are good, bad difer by 1%
+ * TODO: Add equilibrium routine
+
+ I've tried to test all code and use all values for computer verification the standards give, but anyway the code can have hidden problem.
+ For any suggestions, comments, bugs ... you can usage the `github issue section <https://github.com/jjgomera/iapws/issues>`__, or contact directly with me at `email <jjgomera at gmail.com>`__.
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
diff --git a/iapws.egg-info/SOURCES.txt b/iapws.egg-info/SOURCES.txt
index 9b35027..203c3ee 100644
--- a/iapws.egg-info/SOURCES.txt
+++ b/iapws.egg-info/SOURCES.txt
@@ -4,6 +4,9 @@ README.rst
setup.py
iapws/__init__.py
iapws/_iapws.py
+iapws/_utils.py
+iapws/ammonia.py
+iapws/humidAir.py
iapws/iapws08.py
iapws/iapws95.py
iapws/iapws97.py
diff --git a/iapws/__init__.py b/iapws/__init__.py
index cc03d07..93ee4f9 100644
--- a/iapws/__init__.py
+++ b/iapws/__init__.py
@@ -2,10 +2,12 @@
# -*- coding: utf-8 -*-
-from .iapws97 import IAPWS97
-from .iapws95 import IAPWS95, D2O
-from .iapws08 import SeaWater
-from ._iapws import (_Ice, _Sublimation_Pressure, _Melting_Pressure,
+from ._iapws import (_Ice, _Sublimation_Pressure, _Melting_Pressure, # noqa
_Viscosity, _ThCond, _Tension, _Dielectric, _Refractive)
+from .iapws97 import IAPWS97 # noqa
+from .iapws95 import IAPWS95, D2O # noqa
+from .iapws08 import SeaWater # noqa
+from .humidAir import HumidAir # noqa
+from .ammonia import H2ONH3 # noqa
-__version__ = "1.1.3"
+__version__ = "1.2"
diff --git a/iapws/_iapws.py b/iapws/_iapws.py
index fdcaf1d..a688f12 100644
--- a/iapws/_iapws.py
+++ b/iapws/_iapws.py
@@ -1,69 +1,117 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
-
-###############################################################################
-# Several IAPWS standards
-###############################################################################
+"""
+Miscelaneous IAPWS standards
+"""
from __future__ import division
-from math import log, exp, tan, atan, acos, sin, pi
from cmath import log as log_c
+from math import log, exp, tan, atan, acos, sin, pi, log10
+import warnings
+
+from scipy.optimize import minimize
+
+from ._utils import deriv_H
# Constants
-Rm = 8.31451 # kJ/kmol·K
-M = 18.015257 # kg/kmol
+M = 18.015268 # g/mol
R = 0.461526 # kJ/kg·K
+
+# Table 1 from Release on the Values of Temperature, Pressure and Density of
+# Ordinary and Heavy Water Substances at their Respective Critical Points
Tc = 647.096 # K
Pc = 22.064 # MPa
rhoc = 322. # kg/m³
+Tc_D2O = 643.847 # K
+Pc_D2O = 21.671 # MPa
+rhoc_D2O = 356 # kg/m³
+
Tt = 273.16 # K
Pt = 611.657e-6 # MPa
Tb = 373.1243 # K
-Dipole = 1.855 # Debye
f_acent = 0.3443
+# IAPWS, Guideline on the Use of Fundamental Physical Constants and Basic
+# Constants of Water, http://www.iapws.org/relguide/fundam.pdf
+Dipole = 1.85498 # Debye
+
# IAPWS-06 for Ice
def _Ice(T, P):
- """Basic equation for Ice Ih
-
- >>> "%.9f" % _Ice(100,100)["rho"]
- '941.678203297'
- >>> "%.9f" % _Ice(100,100)["h"]
- '-483.491635676'
- >>> "%.11f" % _Ice(100,100)["s"]
- '-2.61195122589'
- >>> "%.11f" % _Ice(273.152519,0.101325)["a"]
- '-0.00918701567'
- >>> "%.9f" % _Ice(273.152519,0.101325)["u"]
- '-333.465403393'
- >>> "%.11f" % _Ice(273.152519,0.101325)["cp"]
- '2.09671391024'
- >>> "%.15f" % _Ice(273.16,611.657e-6)["alfav"]
- '0.000159863102566'
- >>> "%.11f" % _Ice(273.16,611.657e-6)["beta"]
- '1.35714764659'
- >>> "%.11e" % _Ice(273.16,611.657e-6)["kt"]
- '1.17793449348e-04'
- >>> "%.11e" % _Ice(273.16,611.657e-6)["ks"]
- '1.14161597779e-04'
+ """Basic state equation for Ice Ih
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ prop : dict
+ Dict with calculated properties of ice. The available properties are:
+
+ * rho: Density [kg/m³]
+ * h: Specific enthalpy [kJ/kg]
+ * u: Specific internal energy [kJ/kg]
+ * a: Specific Helmholtz energy [kJ/kg]
+ * g: Specific Gibbs energy [kJ/kg]
+ * s: Specific entropy [kJ/kgK]
+ * cp: Specific isobaric heat capacity [kJ/kgK]
+ * alfav: Cubic expansion coefficient [1/K]
+ * beta: Pressure coefficient [MPa/K]
+ * xkappa: Isothermal compressibility [1/MPa]
+ * ks: Isentropic compressibility [1/MPa]
+ * gt: [∂g/∂T]P
+ * gtt: [∂²g/∂T²]P
+ * gp: [∂g/∂P]T
+ * gpp: [∂²g/∂P²]T
+ * gtp: [∂²g/∂T∂P]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * T ≤ 273.16
+ * P ≤ 208.566
+ * State below the melting and sublimation lines
+
+ Examples
+ --------
+ >>> st1 = _Ice(100, 100)
+ >>> st1["rho"], st1["h"], st1["s"]
+ 941.678203297 -483.491635676 -2.61195122589
+ >>> st2 = _Ice(273.152519,0.101325)
+ >>> st2["a"], st2["u"], st2["cp"]
+ -0.00918701567 -333.465403393 2.09671391024
+ >>> st3 = _Ice(273.16,611.657e-6)
+ >>> st3["alfav"], st3["beta"], st3["xkappa"], st3["ks"]
+ 0.000159863102566 1.35714764659 1.17793449348e-04 1.14161597779e-04
+
+ References
+ ----------
+ IAPWS, Revised Release on the Equation of State 2006 for H2O Ice Ih
+ September 2009, http://iapws.org/relguide/Ice-2009.html
"""
# Check input in range of validity
- if P < Pt:
- Psub = _Sublimation_Pressure(T)
- if Psub > P:
- # Zone Gas
- raise NotImplementedError("Incoming out of bound")
+ if T > 273.16:
+ # No Ice Ih stable
+ warnings.warn("Metastable ice")
elif P > 208.566:
# Ice Ih limit upper pressure
raise NotImplementedError("Incoming out of bound")
- else:
- Pmel = _Melting_Pressure(T, P)
+ elif P < Pt:
+ Psub = _Sublimation_Pressure(T)
+ if Psub > P:
+ # Zone Gas
+ warnings.warn("Metastable ice in vapor region")
+ elif 251.165 < T:
+ Pmel = _Melting_Pressure(T)
if Pmel < P:
# Zone Liquid
- raise NotImplementedError("Incoming out of bound")
+ warnings.warn("Metastable ice in liquid region")
Tr = T/Tt
Pr = P/Pt
@@ -130,25 +178,439 @@ def _Ice(T, P):
propiedades["a"] = g-P*gp
propiedades["alfav"] = gtp/gp
propiedades["beta"] = -gtp/gpp
- propiedades["kt"] = -gpp/gp
+ propiedades["xkappa"] = -gpp/gp
propiedades["ks"] = (gtp**2-gtt*gpp)/gp/gtt
return propiedades
+# IAPWS-08 for Liquid water at 0.1 MPa
+def _Liquid(T, P=0.1):
+ """Supplementary release on properties of liquid water at 0.1 MPa
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+ optional, although this relation is for P=0.1MPa, can be extrapoled at
+ pressure 0.3MPa
+
+ Returns
+ -------
+ prop : dict
+ Dict with calculated properties of water. The available properties are:
+
+ * h: Specific enthalpy [kJ/kg]
+ * u: Specific internal energy [kJ/kg]
+ * a: Specific Helmholtz energy [kJ/kg]
+ * g: Specific Gibbs energy [kJ/kg]
+ * s: Specific entropy [kJ/kgK]
+ * cp: Specific isobaric heat capacity [kJ/kgK]
+ * cv: Specific isochoric heat capacity [kJ/kgK]
+ * w: Speed of sound [m/s²]
+ * rho: Density [kg/m³]
+ * v: Specific volume [m³/kg]
+ * vt: [∂v/∂T]P [m³/kgK]
+ * vtt: [∂²v/∂T²]P [m³/kgK²]
+ * vp: [∂v/∂P]T [m³/kg/MPa]
+ * vtp: [∂²v/∂T∂P] [m³/kg/MPa]
+ * alfav: Cubic expansion coefficient [1/K]
+ * xkappa : Isothermal compressibility [1/MPa]
+ * ks: Isentropic compressibility [1/MPa]
+ * mu: Viscosity [mPas]
+ * k: Thermal conductivity [W/mK]
+ * epsilon: Dielectric constant [-]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 253.15 ≤ T ≤ 383.15
+ * 0.1 ≤ P ≤ 0.3
+
+ Examples
+ --------
+ >>> st1 = _Liquid(260)
+ >>> st1["rho"], st1["h"], st1["s"]
+ 997.0683602710492 -55.86223174460868 -0.20998554842619535
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Properties of Liquid Water at 0.1
+ MPa, http://www.iapws.org/relguide/LiquidWater.html
+ """
+ # Check input in range of validity
+ if T <= 253.15 or T >= 383.15 or P < 0.1 or P > 0.3:
+ raise NotImplementedError("Incoming out of bound")
+ elif P != 0.1:
+ # Raise a warning if the P value is extrapolated
+ warnings.warn("Using extrapolated values")
+
+ R = 0.46151805 # kJ/kgK
+ Po = 0.1
+ Tr = 10
+ tau = T/Tr
+ alfa = Tr/(593-T)
+ beta = Tr/(T-232)
+
+ a = [None, -1.661470539e5, 2.708781640e6, -1.557191544e8, None,
+ 1.93763157e-2, 6.74458446e3, -2.22521604e5, 1.00231247e8,
+ -1.63552118e9, 8.32299658e9, -7.5245878e-6, -1.3767418e-2,
+ 1.0627293e1, -2.0457795e2, 1.2037414e3]
+ b = [None, -8.237426256e-1, 1.908956353, -2.017597384, 8.546361348e-1,
+ 5.78545292e-3, -1.53195665E-2, 3.11337859e-2, -4.23546241e-2,
+ 3.38713507e-2, -1.19946761e-2, -3.1091470e-6, 2.8964919e-5,
+ -1.3112763e-4, 3.0410453e-4, -3.9034594e-4, 2.3403117e-4,
+ -4.8510101e-5]
+ c = [None, -2.452093414e2, 3.869269598e1, -8.983025854]
+ n = [None, 4, 5, 7, None, None, 4, 5, 7, 8, 9, 1, 3, 5, 6, 7]
+ m = [None, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6, 1, 3, 4, 5, 6, 7, 9]
+
+ suma1 = sum([a[i]*alfa**n[i] for i in range(1, 4)])
+ suma2 = sum([b[i]*beta**m[i] for i in range(1, 5)])
+ go = R*Tr*(c[1]+c[2]*tau+c[3]*tau*log(tau)+suma1+suma2)
+
+ suma1 = sum([a[i]*alfa**n[i] for i in range(6, 11)])
+ suma2 = sum([b[i]*beta**m[i] for i in range(5, 11)])
+ vo = R*Tr/Po/1000*(a[5]+suma1+suma2)
+
+ suma1 = sum([a[i]*alfa**n[i] for i in range(11, 16)])
+ suma2 = sum([b[i]*beta**m[i] for i in range(11, 18)])
+ vpo = R*Tr/Po**2/1000*(suma1+suma2)
+
+ suma1 = sum([n[i]*a[i]*alfa**(n[i]+1) for i in range(1, 4)])
+ suma2 = sum([m[i]*b[i]*beta**(m[i]+1) for i in range(1, 5)])
+ so = -R*(c[2]+c[3]*(1+log(tau))+suma1-suma2)
+
+ suma1 = sum([n[i]*(n[i]+1)*a[i]*alfa**(n[i]+2) for i in range(1, 4)])
+ suma2 = sum([m[i]*(m[i]+1)*b[i]*beta**(m[i]+2) for i in range(1, 5)])
+ cpo = -R*(c[3]+tau*suma1+tau*suma2)
+
+ suma1 = sum([n[i]*a[i]*alfa**(n[i]+1) for i in range(6, 11)])
+ suma2 = sum([m[i]*b[i]*beta**(m[i]+1) for i in range(5, 11)])
+ vto = R/Po/1000*(suma1-suma2)
+
+ # This properties are only neccessary for computing thermodynamic
+ # properties at pressures different from 0.1 MPa
+ suma1 = sum([n[i]*(n[i]+1)*a[i]*alfa**(n[i]+2) for i in range(6, 11)])
+ suma2 = sum([m[i]*(m[i]+1)*b[i]*beta**(m[i]+2) for i in range(5, 11)])
+ vtto = R/Tr/Po/1000*(suma1+suma2)
+
+ suma1 = sum([n[i]*a[i]*alfa**(n[i]+1) for i in range(11, 16)])
+ suma2 = sum([m[i]*b[i]*beta**(m[i]+1) for i in range(11, 18)])
+ vpto = R/Po**2/1000*(suma1-suma2)
+
+ if P != 0.1:
+ go += vo*(P-0.1)
+ so -= vto*(P-0.1)
+ cpo -= T*vtto*(P-0.1)
+ vo -= vpo*(P-0.1)
+ vto += vpto*(P-0.1)
+ vppo = 3.24e-10*R*Tr/0.1**3
+ vpo += vppo*(P-0.1)
+
+ h = go+T*so
+ u = h-P*vo
+ a = go-P*vo
+ cv = cpo+T*vto**2/vpo
+ xkappa = -vpo/vo
+ alfa = vto/vo
+ ks = -(T*vto**2/cpo+vpo)/vo
+ w = (-vo**2*1e9/(vpo*1e3+T*vto**2*1e6/cpo))**0.5
+
+ propiedades = {}
+ propiedades["g"] = go
+ propiedades["T"] = T
+ propiedades["P"] = P
+ propiedades["v"] = vo
+ propiedades["vt"] = vto
+ propiedades["vp"] = vpo
+ propiedades["vpt"] = vpto
+ propiedades["vtt"] = vtto
+ propiedades["rho"] = 1/vo
+ propiedades["h"] = h
+ propiedades["s"] = so
+ propiedades["cp"] = cpo
+ propiedades["cv"] = cv
+ propiedades["u"] = u
+ propiedades["a"] = a
+ propiedades["xkappa"] = xkappa
+ propiedades["alfav"] = vto/vo
+ propiedades["ks"] = ks
+ propiedades["w"] = w
+
+ # Viscosity correlation, Eq 7
+ a = [None, 280.68, 511.45, 61.131, 0.45903]
+ b = [None, -1.9, -7.7, -19.6, -40]
+ T_ = T/300
+ mu = sum([a[i]*T_**b[i] for i in range(1, 5)])/1e6
+ propiedades["mu"] = mu
+
+ # Thermal conductivity correlation, Eq 8
+ c = [None, 1.6630, -1.7781, 1.1567, -0.432115]
+ d = [None, -1.15, -3.4, -6.0, -7.6]
+ k = sum([c[i]*T_**d[i] for i in range(1, 5)])
+ propiedades["k"] = k
+
+ # Dielectric constant correlation, Eq 9
+ e = [None, -43.7527, 299.504, -399.364, 221.327]
+ f = [None, -0.05, -1.47, -2.11, -2.31]
+ epsilon = sum([e[i]*T_**f[i] for i in range(1, 5)])
+ propiedades["epsilon"] = epsilon
+
+ return propiedades
+
+
+# IAPWS-15 for supercooled liquid water
+def _Supercooled(T, P):
+ """Guideline on thermodynamic properties of supercooled water
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ prop : dict
+ Dict with calculated properties of water. The available properties are:
+
+ * L: Ordering field [-]
+ * x: Mole fraction of low-density structure [-]
+ * rho: Density [kg/m³]
+ * s: Specific entropy [kJ/kgK]
+ * h: Specific enthalpy [kJ/kg]
+ * u: Specific internal energy [kJ/kg]
+ * a: Specific Helmholtz energy [kJ/kg]
+ * g: Specific Gibbs energy [kJ/kg]
+ * alfap: Thermal expansion coefficient [1/K]
+ * xkappa : Isothermal compressibility [1/MPa]
+ * cp: Specific isobaric heat capacity [kJ/kgK]
+ * cv: Specific isochoric heat capacity [kJ/kgK]
+ * w: Speed of sound [m/s²]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * Tm ≤ T ≤ 300
+ * 0 < P ≤ 1000
+
+ The minimum temperature in range of validity is the melting temperature, it
+ depend of pressure
+
+ Examples
+ --------
+ >>> liq = _Supercooled(235.15, 0.101325)
+ >>> liq["rho"], liq["cp"], liq["w"]
+ 968.09999 5.997563 1134.5855
+
+ References
+ ----------
+ IAPWS, Guideline on Thermodynamic Properties of Supercooled Water,
+ http://iapws.org/relguide/Supercooled.html
+ """
+
+ # Check input in range of validity
+ if P < 198.9:
+ Tita = T/235.15
+ Ph = 0.1+228.27*(1-Tita**6.243)+15.724*(1-Tita**79.81)
+ if P < Ph or T > 300:
+ raise NotImplementedError("Incoming out of bound")
+ else:
+ Th = 172.82+0.03718*P+3.403e-5*P**2-1.573e-8*P**3
+ if T < Th or T > 300 or P > 1000:
+ raise NotImplementedError("Incoming out of bound")
+
+ # Parameters, Table 1
+ Tll = 228.2
+ rho0 = 1081.6482
+ R = 0.461523087
+ pi0 = 300e3/rho0/R/Tll
+ omega0 = 0.5212269
+ L0 = 0.76317954
+ k0 = 0.072158686
+ k1 = -0.31569232
+ k2 = 5.2992608
+
+ # Reducing parameters, Eq 2
+ tau = T/Tll-1
+ p = P*1000/rho0/R/Tll
+ tau_ = tau+1
+ p_ = p+pi0
+
+ # Eq 3
+ ci = [-8.1570681381655, 1.2875032, 7.0901673598012, -3.2779161e-2,
+ 7.3703949e-1, -2.1628622e-1, -5.1782479, 4.2293517e-4, 2.3592109e-2,
+ 4.3773754, -2.9967770e-3, -9.6558018e-1, 3.7595286, 1.2632441,
+ 2.8542697e-1, -8.5994947e-1, -3.2916153e-1, 9.0019616e-2,
+ 8.1149726e-2, -3.2788213]
+ ai = [0, 0, 1, -0.2555, 1.5762, 1.6400, 3.6385, -0.3828, 1.6219, 4.3287,
+ 3.4763, 5.1556, -0.3593, 5.0361, 2.9786, 6.2373, 4.0460, 5.3558,
+ 9.0157, 1.2194]
+ bi = [0, 1, 0, 2.1051, 1.1422, 0.9510, 0, 3.6402, 2.0760, -0.0016, 2.2769,
+ 0.0008, 0.3706, -0.3975, 2.9730, -0.3180, 2.9805, 2.9265, 0.4456,
+ 0.1298]
+ di = [0, 0, 0, -0.0016, 0.6894, 0.0130, 0.0002, 0.0435, 0.0500, 0.0004,
+ 0.0528, 0.0147, 0.8584, 0.9924, 1.0041, 1.0961, 1.0228, 1.0303,
+ 1.6180, 0.5213]
+ phir = phirt = phirp = phirtt = phirtp = phirpp = 0
+ for c, a, b, d in zip(ci, ai, bi, di):
+ phir += c*tau_**a*p_**b*exp(-d*p_)
+ phirt += c*a*tau_**(a-1)*p_**b*exp(-d*p_)
+ phirp += c*tau_**a*p_**(b-1)*(b-d*p_)*exp(-d*p_)
+ phirtt += c*a*(a-1)*tau_**(a-2)*p_**b*exp(-d*p_)
+ phirtp += c*a*tau_**(a-1)*p_**(b-1)*(b-d*p_)*exp(-d*p_)
+ phirpp += c*tau_**a*p_**(b-2)*((d*p_-b)**2-b)*exp(-d*p_)
+
+ # Eq 5
+ K1 = ((1+k0*k2+k1*(p-k2*tau))**2-4*k0*k1*k2*(p-k2*tau))**0.5
+ K2 = (1+k2**2)**0.5
+
+ # Eq 6
+ omega = 2+omega0*p
+
+ # Eq 4
+ L = L0*K2/2/k1/k2*(1+k0*k2+k1*(p+k2*tau)-K1)
+
+ # Define interval of solution, Table 4
+ if omega < 10/9*(log(19)-L):
+ xmin = 0.049
+ xmax = 0.5
+ elif 10/9*(log(19)-L) <= omega < 50/49*(log(99)-L):
+ xmin = 0.0099
+ xmax = 0.051
+ else:
+ xmin = 0.99*exp(-50/49*L-omega)
+ xmax = min(1.1*exp(-L-omega), 0.0101)
+
+ def f(x):
+ return abs(L+log(x/(1-x))+omega*(1-2*x))
+
+ x = minimize(f, ((xmin+xmax)/2,), bounds=((xmin, xmax),))["x"][0]
+
+ # Eq 12
+ fi = 2*x-1
+ Xi = 1/(2/(1-fi**2)-omega)
+
+ # Derivatives, Table 3
+ Lt = L0*K2/2*(1+(1-k0*k2+k1*(p-k2*tau))/K1)
+ Lp = L0*K2*(K1+k0*k2-k1*p+k1*k2*tau-1)/2/k2/K1
+ Ltt = -2*L0*K2*k0*k1*k2**2/K1**3
+ Ltp = 2*L0*K2*k0*k1*k2/K1**3
+ Lpp = -2*L0*K2*k0*k1/K1**3
+
+ prop = {}
+ prop["L"] = L
+ prop["x"] = x
+
+ # Eq 13
+ prop["rho"] = rho0/((tau+1)/2*(omega0/2*(1-fi**2)+Lp*(fi+1))+phirp)
+
+ # Eq 1
+ prop["g"] = phir+(tau+1)*(x*L+x*log(x)+(1-x)*log(1-x)+omega*x*(1-x))
+
+ # Eq 14
+ prop["s"] = -R*((tau+1)/2*Lt*(fi+1) +
+ (x*L+x*log(x)+(1-x)*log(1-x)+omega*x*(1-x))+phirt)
+
+ # Basic derived state properties
+ prop["h"] = prop["g"]+T*prop["s"]
+ prop["u"] = prop["h"]+P/prop["rho"]
+ prop["a"] = prop["u"]-T*prop["s"]
+
+ # Eq 15
+ prop["xkappa"] = prop["rho"]/rho0**2/R*1000/Tll*(
+ (tau+1)/2*(Xi*(Lp-omega0*fi)**2-(fi+1)*Lpp)-phirpp)
+ prop["alfap"] = prop["rho"]/rho0/Tll*(
+ Ltp/2*(tau+1)*(fi+1) + (omega0*(1-fi**2)/2+Lp*(fi+1))/2 -
+ (tau+1)*Lt/2*Xi*(Lp-omega0*fi) + phirtp)
+ prop["cp"] = -R*(tau+1)*(Lt*(fi+1)+(tau+1)/2*(Ltt*(fi+1)-Lt**2*Xi)+phirtt)
+
+ # Eq 16
+ prop["cv"] = prop["cp"]-T*prop["alfap"]**2/prop["rho"]/prop["xkappa"]*1e3
+
+ # Eq 17
+ prop["w"] = (prop["rho"]*prop["xkappa"]*1e-6*prop["cv"]/prop["cp"])**-0.5
+ return prop
+
+
def _Sublimation_Pressure(T):
- """Sublimation Pressure correlation"""
- Tita = T/Tt
- suma = 0
- a = [-0.212144006e2, 0.273203819e2, -0.61059813e1]
- expo = [0.333333333e-2, 1.20666667, 1.70333333]
- for ai, expi in zip(a, expo):
- suma += ai*Tita**expi
- return exp(suma/Tita)*Pt
-
-
-def _Melting_Pressure(T, P):
- """Melting Pressure correlation"""
- if P < 208.566 and 251.165 <= T <= 273.16:
+ """Sublimation Pressure correlation
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ P : float
+ Pressure at sublimation line [MPa]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 50 ≤ T ≤ 273.16
+
+ Examples
+ --------
+ >>> _Sublimation_Pressure(230)
+ 8.947352740189152e-06
+
+ References
+ ----------
+ IAPWS, Revised Release on the Pressure along the Melting and Sublimation
+ Curves of Ordinary Water Substance, http://iapws.org/relguide/MeltSub.html.
+ """
+ if 50 <= T <= 273.16:
+ Tita = T/Tt
+ suma = 0
+ a = [-0.212144006e2, 0.273203819e2, -0.61059813e1]
+ expo = [0.333333333e-2, 1.20666667, 1.70333333]
+ for ai, expi in zip(a, expo):
+ suma += ai*Tita**expi
+ return exp(suma/Tita)*Pt
+ else:
+ raise NotImplementedError("Incoming out of bound")
+
+
+def _Melting_Pressure(T, ice="Ih"):
+ """Melting Pressure correlation
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ ice: string
+ Type of ice: Ih, III, V, VI, VII.
+ Below 273.15 is a mandatory input, the ice Ih is the default value.
+ Above 273.15, the ice type is unnecesary.
+
+ Returns
+ -------
+ P : float
+ Pressure at sublimation line [MPa]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 251.165 ≤ T ≤ 715
+
+ Examples
+ --------
+ >>> _Melting_Pressure(260)
+ 8.947352740189152e-06
+ >>> _Melting_Pressure(254, "III")
+ 268.6846466336108
+
+ References
+ ----------
+ IAPWS, Revised Release on the Pressure along the Melting and Sublimation
+ Curves of Ordinary Water Substance, http://iapws.org/relguide/MeltSub.html.
+ """
+ if ice == "Ih" and 251.165 <= T <= 273.16:
# Ice Ih
Tref = Tt
Pref = Pt
@@ -159,32 +621,33 @@ def _Melting_Pressure(T, P):
for ai, expi in zip(a, expo):
suma += ai*(1-Tita**expi)
P = suma*Pref
- elif 208.566 < P < 350.1 and 251.165 < T <= 256.164:
+ elif ice == "III" and 251.165 < T <= 256.164:
# Ice III
Tref = 251.165
Pref = 208.566
Tita = T/Tref
P = Pref*(1-0.299948*(1-Tita**60.))
- elif 350.1 < P < 632.4 and 256.164 < T <= 273.31:
+ elif (ice == "V" and 256.164 < T <= 273.15) or 273.15 < T <= 273.31:
# Ice V
Tref = 256.164
Pref = 350.100
Tita = T/Tref
P = Pref*(1-1.18721*(1-Tita**8.))
- elif 632.4 < P < 2216 and 273.31 < T <= 355:
+ elif 273.31 < T <= 355:
# Ice VI
Tref = 273.31
Pref = 632.400
Tita = T/Tref
P = Pref*(1-1.07476*(1-Tita**4.6))
- elif 2216 < P and 355. < T <= 715:
+ elif 355. < T <= 715:
# Ice VII
Tref = 355
Pref = 2216.000
Tita = T/Tref
P = Pref*exp(1.73683*(1-1./Tita)-0.544606e-1*(1-Tita**5) +
0.806106e-7*(1-Tita**22))
-
+ else:
+ raise NotImplementedError("Incoming out of bound")
return P
@@ -192,138 +655,266 @@ def _Melting_Pressure(T, P):
def _Viscosity(rho, T, fase=None, drho=None):
"""Equation for the Viscosity
- >>> "%.12f" % _Viscosity(997.047435,298.15)
- '0.000890022551'
- >>> "%.13f" % _Viscosity(54.9921814,873.15)
- '0.0000339743835'
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+ fase: dict
+ phase properties
+ drho: float
+ [∂ρ/∂P]T at reference state,
+ optional for calculate critical enhancement
+
+ Returns
+ -------
+ mu : float
+ Viscosity [Pa·s]
+
+ Examples
+ --------
+ >>> _Viscosity(998, 298.15)
+ 0.0008897351001498108
+ >>> _Viscosity(600, 873.15)
+ 7.743019522728247e-05
+
+ References
+ ----------
+ IAPWS, Release on the IAPWS Formulation 2008 for the Viscosity of Ordinary
+ Water Substance, http://www.iapws.org/relguide/viscosity.html
"""
Tr = T/Tc
Dr = rho/rhoc
- no = [1.67752, 2.20462, 0.6366564, -0.241605]
- suma = 0
- for i in range(4):
- suma += no[i]/Tr**i
- fi0 = 100*Tr**0.5/suma
-
- I = [0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6]
- J = [0, 1, 2, 3, 0, 1, 2, 3, 5, 0, 1, 2, 3, 4, 0, 1, 0, 3, 4, 3, 5]
- nr = [0.520094, 0.850895e-1, -0.108374e1, -0.289555, 0.222531, 0.999115,
- 0.188797e1, 0.126613e1, 0.120573, -0.281378, -0.906851, -0.772479,
- -0.489837, -0.257040, 0.161913, 0.257399, -0.325372e-1, 0.698452e-1,
- 0.872102e-2, -0.435673e-2, -0.593264e-3]
- suma = 0
- for i in range(21):
- suma += nr[i]*(Dr-1)**I[i]*(1/Tr-1)**J[i]
- fi1 = exp(Dr*suma)
+ # Eq 11
+ H = [1.67752, 2.20462, 0.6366564, -0.241605]
+ mu0 = 100*Tr**0.5/sum([Hi/Tr**i for i, Hi in enumerate(H)])
+
+ # Eq 12
+ I = [0, 1, 2, 3, 0, 1, 2, 3, 5, 0, 1, 2, 3, 4, 0, 1, 0, 3, 4, 3, 5]
+ J = [0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6]
+ Hij = [0.520094, 0.850895e-1, -0.108374e1, -0.289555, 0.222531, 0.999115,
+ 0.188797e1, 0.126613e1, 0.120573, -0.281378, -0.906851, -0.772479,
+ -0.489837, -0.257040, 0.161913, 0.257399, -0.325372e-1, 0.698452e-1,
+ 0.872102e-2, -0.435673e-2, -0.593264e-3]
+ mu1 = exp(Dr*sum([(1/Tr-1)**i*H*(Dr-1)**j for i, j, H in zip(I, J, Hij)]))
+
+ # Critical enhancement
if fase and drho:
qc = 1/1.9
qd = 1/1.1
+ # Eq 21
DeltaX = Pc*Dr**2*(fase.drhodP_T/rho-drho/rho*1.5/Tr)
if DeltaX < 0:
DeltaX = 0
+
+ # Eq 20
X = 0.13*(DeltaX/0.06)**(0.63/1.239)
+
if X <= 0.3817016416:
+ # Eq 15
Y = qc/5*X*(qd*X)**5*(1-qc*X+(qc*X)**2-765./504*(qd*X)**2)
+
else:
- Fid = acos((1+qd**2*X**2)**-0.5)
- w = abs((qc*X-1)/(qc*X+1))**0.5*tan(Fid/2)
+ Fid = acos((1+qd**2*X**2)**-0.5) # Eq 17
+ w = abs((qc*X-1)/(qc*X+1))**0.5*tan(Fid/2) # Eq 19
+
+ # Eq 18
if qc*X > 1:
Lw = log((1+w)/(1-w))
else:
Lw = 2*atan(abs(w))
+
+ # Eq 16
Y = sin(3*Fid)/12-sin(2*Fid)/4/qc/X+(1-5/4*(qc*X)**2)/(
qc*X)**2*sin(Fid)-((1-3/2*(qc*X)**2)*Fid-abs((
qc*X)**2-1)**1.5*Lw)/(qc*X)**3
- fi2 = exp(0.068*Y)
+
+ # Eq 14
+ mu2 = exp(0.068*Y)
else:
- fi2 = 1
- return fi0*fi1*fi2*1e-6
+ mu2 = 1
+
+ # Eq 10
+ mu = mu0*mu1*mu2
+ return mu*1e-6
def _ThCond(rho, T, fase=None, drho=None):
"""Equation for the thermal conductivity
- >>> "%.9f" % _ThCond(997.047435,298.15)
- '0.606515826'
- >>> "%.10f" % _ThCond(26.0569558,873.15)
- '0.0870480934'
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+ fase: dict
+ phase properties
+ drho: float
+ [∂ρ/∂P]T at reference state,
+ optional for calculate critical enhancement
+
+ Returns
+ -------
+ k : float
+ Thermal conductivity [W/mK]
+
+ Examples
+ --------
+ >>> _ThCond(998, 298.15)
+ 0.6077128675880629
+ >>> _ThCond(0, 873.15)
+ 0.07910346589648833
+
+ References
+ ----------
+ IAPWS, Release on the IAPWS Formulation 2011 for the Thermal Conductivity
+ of Ordinary Water Substance, http://www.iapws.org/relguide/ThCond.html
"""
- d = rho/322.
- Tr = T/647.096
+ d = rho/rhoc
+ Tr = T/Tc
+ # Eq 16
no = [2.443221e-3, 1.323095e-2, 6.770357e-3, -3.454586e-3, 4.096266e-4]
- suma = 0
- for i in range(5):
- suma += no[i]/Tr**i
- L0 = Tr**0.5/suma
-
- nij = [
- [1.60397357, -0.646013523, 0.111443906, 0.102997357, -0.0504123634,
- 0.00609859258],
- [2.33771842, -2.78843778, 1.53616167, -0.463045512, 0.0832827019,
- -0.00719201245],
- [2.19650529, -4.54580785, 3.55777244, -1.40944978, 0.275418278,
- -0.0205938816],
- [-1.21051378, 1.60812989, -0.621178141, 0.0716373224, 0, 0],
- [-2.7203370, 4.57586331, -3.18369245, 1.1168348, -0.19268305,
- 0.012913842]]
- suma = 0
- for i in range(len(nij)):
- suma2 = 0
- for j in range(len(nij[i])):
- suma2 += nij[i][j]*(d-1)**j
- suma += (1/Tr-1)**i*suma2
- L1 = exp(d*suma)
-
- L2 = 0
- if fase and drho:
+ k0 = Tr**0.5/sum([n/Tr**i for i, n in enumerate(no)])
+
+ # Eq 17
+ I = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4,
+ 4, 4, 4, 4, 4]
+ J = [0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 0,
+ 1, 2, 3, 4, 5]
+ nij = [1.60397357, -0.646013523, 0.111443906, 0.102997357, -0.0504123634,
+ 0.00609859258, 2.33771842, -2.78843778, 1.53616167, -0.463045512,
+ 0.0832827019, -0.00719201245, 2.19650529, -4.54580785, 3.55777244,
+ -1.40944978, 0.275418278, -0.0205938816, -1.21051378, 1.60812989,
+ -0.621178141, 0.0716373224, -2.7203370, 4.57586331, -3.18369245,
+ 1.1168348, -0.19268305, 0.012913842]
+ k1 = exp(d*sum([(1/Tr-1)**i*n*(d-1)**j for i, j, n in zip(I, J, nij)]))
+
+ # Critical enhancement
+ if fase:
R = 0.46151805
- DeltaX = Pc*d**2*(fase.drhodP_T/rho-drho/rho*1.5/Tr)
+ if not drho:
+ # Industrial formulation
+ # Eq 25
+ if d <= 0.310559006:
+ ai = [6.53786807199516, -5.61149954923348, 3.39624167361325,
+ -2.27492629730878, 10.2631854662709, 1.97815050331519]
+ elif d <= 0.776397516:
+ ai = [6.52717759281799, -6.30816983387575, 8.08379285492595,
+ -9.82240510197603, 12.1358413791395, -5.54349664571295]
+ elif d <= 1.242236025:
+ ai = [5.35500529896124, -3.96415689925446, 8.91990208918795,
+ -12.0338729505790, 9.19494865194302, -2.16866274479712]
+ elif d <= 1.863354037:
+ ai = [1.55225959906681, 0.464621290821181, 8.93237374861479,
+ -11.0321960061126, 6.16780999933360, -0.965458722086812]
+ else:
+ ai = [1.11999926419994, 0.595748562571649, 9.88952565078920,
+ -10.3255051147040, 4.66861294457414, -0.503243546373828]
+ drho = 1/sum([a*d**i for i, a in enumerate(ai)])*rhoc/Pc
+
+ DeltaX = d*(Pc/rhoc*fase.drhodP_T-Pc/rhoc*drho*1.5/Tr)
if DeltaX < 0:
DeltaX = 0
- X = 0.13*(DeltaX/0.06)**(0.63/1.239)
- y = X/0.4
+
+ X = 0.13*(DeltaX/0.06)**(0.63/1.239) # Eq 22
+ y = X/0.4 # Eq 20
+
+ # Eq 19
if y < 1.2e-7:
Z = 0
else:
Z = 2/pi/y*(((1-1/fase.cp_cv)*atan(y)+y/fase.cp_cv)-(
1-exp(-1/(1/y+y**2/3/d**2))))
- L2 = 177.8514*d*fase.cp/R*Tr/fase.mu*1e-6*Z
- return 1e-3*(L0*L1+L2)
+
+ # Eq 18
+ k2 = 177.8514*d*fase.cp/R*Tr/fase.mu*1e-6*Z
+
+ else:
+ # No critical enhancement
+ k2 = 0
+
+ # Eq 10
+ k = k0*k1+k2
+ return 1e-3*k
def _Tension(T):
"""Equation for the surface tension
- >>> "%.10f" % _Tension(300)
- '0.0716859625'
- >>> "%.10f" % _Tension(450)
- '0.0428914992'
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ sigma : float
+ Surface tension [N/m]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 248.15 ≤ T ≤ 647
+ * Estrapolate to -25ºC in supercooled liquid metastable state
+
+ Examples
+ --------
+ >>> _Tension(300)
+ 0.0716859625
+ >>> _Tension(450)
+ 0.0428914992
+
+ References
+ ----------
+ IAPWS, Revised Release on Surface Tension of Ordinary Water Substance
+ June 2014, http://www.iapws.org/relguide/Surf-H2O.html
"""
- Tr = T/Tc
- if 273.15 <= T < Tc:
+ if 248.15 <= T <= Tc:
+ Tr = T/Tc
return 1e-3*(235.8*(1-Tr)**1.256*(1-0.625*(1-Tr)))
else:
- return 0
+ raise NotImplementedError("Incoming out of bound")
def _Dielectric(rho, T):
"""Equation for the Dielectric constant
- >>> "%.7f" % _Dielectric(999.242866, 298.15)
- '78.5907250'
- >>> "%.8f" % _Dielectric(26.0569558, 873.15)
- '1.12620970'
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ epsilon : float
+ Dielectric constant [-]
+
+ Examples
+ --------
+ >>> _Dielectric(999.242866, 298.15)
+ 78.5907250
+ >>> _Dielectric(26.0569558, 873.15)
+ 1.12620970
+
+ References
+ ----------
+ IAPWS, Release on the Static Dielectric Constant of Ordinary Water
+ Substance for Temperatures from 238 K to 873 K and Pressures up to 1000
+ MPa, http://www.iapws.org/relguide/Dielec.html
"""
k = 1.380658e-23
Na = 6.0221367e23
alfa = 1.636e-40
epsilon0 = 8.854187817e-12
mu = 6.138e-30
- M = 0.018015268
d = rho/rhoc
Tr = Tc/T
@@ -337,8 +928,8 @@ def _Dielectric(rho, T):
g = 1+n[11]*d/(Tc/228/Tr-1)**1.2
for i in range(11):
g += n[i]*d**I[i]*Tr**J[i]
- A = Na*mu**2*rho*g/M/epsilon0/k/T
- B = Na*alfa*rho/3/M/epsilon0
+ A = Na*mu**2*rho*g/M*1000/epsilon0/k/T
+ B = Na*alfa*rho/3/M*1000/epsilon0
e = (1+A+5*B+(9+2*A+18*B+A**2+10*A*B+9*B**2)**0.5)/4/(1-B)
return e
@@ -346,11 +937,44 @@ def _Dielectric(rho, T):
def _Refractive(rho, T, l=0.5893):
"""Equation for the refractive index
- >>> "%.8f" % _Refractive(997.047435, 298.15, 0.2265)
- '1.39277824'
- >>> "%.8f" % _Refractive(30.4758534, 773.15, 0.5893)
- '1.00949307'
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+ l : float, optional
+ Light Wavelength [μm]
+
+ Returns
+ -------
+ n : float
+ Refractive index [-]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 0 ≤ ρ ≤ 1060
+ * 261.15 ≤ T ≤ 773.15
+ * 0.2 ≤ λ ≤ 1.1
+
+ Examples
+ --------
+ >>> _Refractive(997.047435, 298.15, 0.2265)
+ 1.39277824
+ >>> _Refractive(30.4758534, 773.15, 0.5893)
+ 1.00949307
+
+ References
+ ----------
+ IAPWS, Release on the Refractive Index of Ordinary Water Substance as a
+ Function of Wavelength, Temperature and Pressure,
+ http://www.iapws.org/relguide/rindex.pdf
"""
+ # Check input parameters
+ if rho < 0 or rho > 1060 or T < 261.15 or T > 773.15 or l < 0.2 or l > 1.1:
+ raise NotImplementedError("Incoming out of bound")
+
Lir = 5.432937
Luv = 0.229202
d = rho/1000.
@@ -363,86 +987,486 @@ def _Refractive(rho, T, l=0.5893):
return ((2*A+1)/(1-A))**0.5
-def getphase(Tc, Pc, T, P, x, region):
- """Return fluid phase"""
- if P > Pc and T > Tc:
- phase = "Supercritical fluid"
- elif T > Tc:
- phase = "Gas"
- elif P > Pc:
- phase = "Compressible liquid"
- elif P == Pc and T == Tc:
- phase = "Critical point"
- elif region == 4 and x == 1:
- phase = "Saturated vapor"
- elif region == 4 and x == 0:
- phase = "Saturated liquid"
- elif region == 4:
- phase = "Two phases"
- elif x == 1:
- phase = "Vapour"
- elif x == 0:
- phase = "Liquid"
+def _Kw(rho, T):
+ """Equation for the ionization constant of ordinary water
+
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ pKw : float
+ Ionization constant in -log10(kw) [-]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 0 ≤ ρ ≤ 1250
+ * 273.15 ≤ T ≤ 1073.15
+
+ Examples
+ --------
+ >>> _Kw(1000, 300)
+ 13.906565
+
+ References
+ ----------
+ IAPWS, Release on the Ionization Constant of H2O,
+ http://www.iapws.org/relguide/Ionization.pdf
+ """
+ # Check input parameters
+ if rho < 0 or rho > 1250 or T < 273.15 or T > 1073.15:
+ raise NotImplementedError("Incoming out of bound")
+
+ # The internal method of calculation use rho in g/cm³
+ d = rho/1000.
+
+ # Water molecular weight different
+ Mw = 18.015268
+
+ gamma = [6.1415e-1, 4.825133e4, -6.770793e4, 1.01021e7]
+ pKg = 0
+ for i, g in enumerate(gamma):
+ pKg += g/T**i
+
+ Q = d*exp(-0.864671+8659.19/T-22786.2/T**2*d**(2./3))
+ pKw = -12*(log10(1+Q)-Q/(Q+1)*d*(0.642044-56.8534/T-0.375754*d)) + \
+ pKg+2*log10(Mw/1000)
+ return pKw
+
+
+def _Conductivity(rho, T):
+ """Equation for the electrolytic conductivity of liquid and dense
+ supercrítical water
+
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ K : float
+ Electrolytic conductivity [S/m]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 600 ≤ ρ ≤ 1200
+ * 273.15 ≤ T ≤ 1073.15
+
+ Examples
+ --------
+ >>> _Conductivity(1000, 373.15)
+ 1.13
+
+ References
+ ----------
+ IAPWS, Electrolytic Conductivity (Specific Conductance) of Liquid and Dense
+ Supercritical Water from 0°C to 800°C and Pressures up to 1000 MPa,
+ http://www.iapws.org/relguide/conduct.pdf
+ """
+ # FIXME: Dont work
+ rho_ = rho/1000
+ kw = 10**-_Kw(rho, T)
+
+ A = [1850., 1410., 2.16417e-6, 1.81609e-7, -1.75297e-9, 7.20708e-12]
+ B = [16., 11.6, 3.26e-4, -2.3e-6, 1.1e-8]
+ t = T-273.15
+
+ Loo = A[0]-1/(1/A[1]+sum([A[i+2]*t**(i+1) for i in range(4)])) # Eq 5
+ rho_h = B[0]-1/(1/B[1]+sum([B[i+2]*t**(i+1) for i in range(3)])) # Eq 6
+
+ # Eq 4
+ L_o = (rho_h-rho_)*Loo/rho_h
+
+ # Eq 1
+ k = 100*1e-3*L_o*kw**0.5*rho_
+ return k
+
+
+# Heavy water transport properties
+def _D2O_Viscosity(rho, T):
+ """Equation for the Viscosity of heavy water
+
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ mu : float
+ Viscosity [Pa·s]
+
+ Examples
+ --------
+ >>> _D2O_Viscosity(998, 298.15)
+ 0.0008897351001498108
+ >>> _D2O_Viscosity(600, 873.15)
+ 7.743019522728247e-05
+
+ References
+ ----------
+ IAPWS, Revised Release on Viscosity and Thermal Conductivity of Heavy
+ Water Substance, http://www.iapws.org/relguide/TransD2O-2007.pdf
+ """
+ Tr = T/643.847
+ rhor = rho/358.0
+
+ no = [1.0, 0.940695, 0.578377, -0.202044]
+ fi0 = Tr**0.5/sum([n/Tr**i for i, n in enumerate(no)])
+
+ Li = [0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 0, 1, 2, 5, 0, 1, 2, 3, 0, 1, 3,
+ 5, 0, 1, 5, 3]
+ Lj = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
+ 4, 5, 5, 5, 6]
+ Lij = [0.4864192, -0.2448372, -0.8702035, 0.8716056, -1.051126,
+ 0.3458395, 0.3509007, 1.315436, 1.297752, 1.353448, -0.2847572,
+ -1.037026, -1.287846, -0.02148229, 0.07013759, 0.4660127,
+ 0.2292075, -0.4857462, 0.01641220, -0.02884911, 0.1607171,
+ -.009603846, -.01163815, -.008239587, 0.004559914, -0.003886659]
+
+ arr = [lij*(1./Tr-1)**i*(rhor-1)**j for i, j, lij in zip(Li, Lj, Lij)]
+ fi1 = exp(rhor*sum(arr))
+
+ return 55.2651e-6*fi0*fi1
+
+
+def _D2O_ThCond(rho, T):
+ """Equation for the thermal conductivity of heavy water
+
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ k : float
+ Thermal conductivity [W/mK]
+
+ Examples
+ --------
+ >>> _D2O_ThCond(998, 298.15)
+ 0.6077128675880629
+ >>> _D2O_ThCond(0, 873.15)
+ 0.07910346589648833
+
+ References
+ ----------
+ IAPWS, Revised Release on Viscosity and Thermal Conductivity of Heavy
+ Water Substance, http://www.iapws.org/relguide/TransD2O-2007.pdf
+ """
+ rhor = rho/358
+ Tr = T/643.847
+ tau = Tr/(abs(Tr-1.1)+1.1)
+
+ no = [1.0, 37.3223, 22.5485, 13.0465, 0.0, -2.60735]
+ Lo = sum([Li*Tr**i for i, Li in enumerate(no)])
+
+ nr = [483.656, -191.039, 73.0358, -7.57467]
+ Lr = -167.31*(1-exp(-2.506*rhor))+sum(
+ [Li*rhor**(i+1) for i, Li in enumerate(nr)])
+
+ f1 = exp(0.144847*Tr-5.64493*Tr**2)
+ f2 = exp(-2.8*(rhor-1)**2)-0.080738543*exp(-17.943*(rhor-0.125698)**2)
+ f3 = 1+exp(60*(tau-1)+20)
+ f4 = 1+exp(100*(tau-1)+15)
+ Lc = 35429.6*f1*f2*(1+f2**2*(5e9*f1**4/f3+3.5*f2/f4))
+
+ Ll = -741.112*f1**1.2*(1-exp(-(rhor/2.5)**10))
+
+ return 0.742128e-3*(Lo+Lr+Lc+Ll)
+
+
+def _D2O_Tension(T):
+ """Equation for the surface tension of heavy water
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ sigma : float
+ Surface tension [N/m]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 269.65 ≤ T ≤ 643.847
+
+ Examples
+ --------
+ >>> _D2O_Tension(298.15)
+ 0.07186
+ >>> _D2O_Tension(573.15)
+ 0.01399
+
+ References
+ ----------
+ IAPWS, Release on Surface Tension of Heavy Water Substance,
+ http://www.iapws.org/relguide/surfd2o.pdf
+ """
+ Tr = T/643.847
+ if 269.65 <= T < 643.847:
+ return 1e-3*(238*(1-Tr)**1.25*(1-0.639*(1-Tr)))
else:
- phase = "Unknown"
- return phase
-
-
-class _fase(object):
- """Class to implement a null phase"""
- v = None
- rho = None
-
- h = None
- s = None
- u = None
- a = None
- g = None
-
- cp = None
- cv = None
- cp_cv = None
- w = None
- Z = None
- fi = None
- f = None
-
- mu = None
- k = None
- nu = None
- Prandt = None
- epsilon = None
- alfa = None
- n = None
-
- alfap = None
- betap = None
- joule = None
- Gruneisen = None
- alfav = None
- kappa = None
- betas = None
- gamma = None
- Kt = None
- kt = None
- Ks = None
- ks = None
- dpdT_rho = None
- dpdrho_T = None
- drhodT_P = None
- drhodP_T = None
- dhdT_rho = None
- dhdT_P = None
- dhdrho_T = None
- dhdrho_P = None
- dhdP_T = None
- dhdP_rho = None
-
- Z_rho = None
- IntP = None
- hInput = None
-
-
-if __name__ == "__main__":
- import doctest
- doctest.testmod()
+ raise NotImplementedError("Incoming out of bound")
+
+
+def _Henry(T, gas, liquid="H2O"):
+ """Equation for the calculation of Henry's constant
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ gas : string
+ Name of gas to calculate solubility
+ liquid : string
+ Name of liquid solvent, can be H20 (default) or D2O
+
+ Returns
+ -------
+ kw : float
+ Henry's constant [MPa]
+
+ Notes
+ -----
+ The gas availables for H2O solvent are:
+ He, Ne, Ar, Kr, Xe, H2, N2, O2, CO, CO2, H2S, CH4, C2H6, SF6
+ For D2O as solvent:
+ He, Ne, Ar, Kr, Xe, D2, CH4
+
+ Examples
+ --------
+ >>> _Henry(500, "He")
+ 1.1973
+ >>> _Henry(300, "D2", "D2O")
+ 1.6594
+
+ References
+ ----------
+ IAPWS, Guideline on the Henry's Constant and Vapor-Liquid Distribution
+ Constant for Gases in H2O and D2O at High Temperatures,
+ http://www.iapws.org/relguide/HenGuide.html
+ """
+ if liquid == "D2O":
+ gas += "(D2O)"
+
+ limit = {
+ "He": (273.21, 553.18),
+ "Ne": (273.20, 543.36),
+ "Ar": (273.19, 568.36),
+ "Kr": (273.19, 525.56),
+ "Xe": (273.22, 574.85),
+ "H2": (273.15, 636.09),
+ "N2": (278.12, 636.46),
+ "O2": (274.15, 616.52),
+ "CO": (278.15, 588.67),
+ "CO2": (274.19, 642.66),
+ "H2S": (273.15, 533.09),
+ "CH4": (275.46, 633.11),
+ "C2H6": (275.44, 473.46),
+ "SF6": (283.14, 505.55),
+ "He(D2O)": (288.15, 553.18),
+ "Ne(D2O)": (288.18, 549.96),
+ "Ar(D2O)": (288.30, 583.76),
+ "Kr(D2O)": (288.19, 523.06),
+ "Xe(D2O)": (295.39, 574.85),
+ "D2(D2O)": (288.17, 581.00),
+ "CH4(D2O)": (288.16, 517.46)}
+
+ # Check input parameters
+ if liquid != "D2O" and liquid != "H2O":
+ raise NotImplementedError("Solvent liquid unsupported")
+ if gas not in limit:
+ raise NotImplementedError("Gas unsupported")
+
+ Tmin, Tmax = limit[gas]
+ if T < Tmin or T > Tmax:
+ warnings.warn("Temperature out of data of correlation")
+
+ if liquid == "D2O":
+ Tc = 643.847
+ Pc = 21.671
+ else:
+ Tc = 647.096
+ Pc = 22.064
+
+ Tr = T/Tc
+ tau = 1-Tr
+
+ # Eq 4
+ if liquid == "H2O":
+ ai = [-7.85951783, 1.84408259, -11.7866497, 22.6807411, -15.9618719,
+ 1.80122502]
+ bi = [1, 1.5, 3, 3.5, 4, 7.5]
+ else:
+ ai = [-7.896657, 24.73308, -27.81128, 9.355913, -9.220083]
+ bi = [1, 1.89, 2, 3, 3.6]
+ ps = Pc*exp(1/Tr*sum([a*tau**b for a, b in zip(ai, bi)]))
+
+ # Select values from Table 2
+ par = {
+ "He": (-3.52839, 7.12983, 4.47770),
+ "Ne": (-3.18301, 5.31448, 5.43774),
+ "Ar": (-8.40954, 4.29587, 10.52779),
+ "Kr": (-8.97358, 3.61508, 11.29963),
+ "Xe": (-14.21635, 4.00041, 15.60999),
+ "H2": (-4.73284, 6.08954, 6.06066),
+ "N2": (-9.67578, 4.72162, 11.70585),
+ "O2": (-9.44833, 4.43822, 11.42005),
+ "CO": (-10.52862, 5.13259, 12.01421),
+ "CO2": (-8.55445, 4.01195, 9.52345),
+ "H2S": (-4.51499, 5.23538, 4.42126),
+ "CH4": (-10.44708, 4.66491, 12.12986),
+ "C2H6": (-19.67563, 4.51222, 20.62567),
+ "SF6": (-16.56118, 2.15289, 20.35440),
+ "He(D2O)": (-0.72643, 7.02134, 2.04433),
+ "Ne(D2O)": (-0.91999, 5.65327, 3.17247),
+ "Ar(D2O)": (-7.17725, 4.48177, 9.31509),
+ "Kr(D2O)": (-8.47059, 3.91580, 10.69433),
+ "Xe(D2O)": (-14.46485, 4.42330, 15.60919),
+ "D2(D2O)": (-5.33843, 6.15723, 6.53046),
+ "CH4(D2O)": (-10.01915, 4.73368, 11.75711)}
+ A, B, C = par[gas]
+
+ # Eq 3
+ kh = ps*exp(A/Tr+B*tau**0.355/Tr+C*Tr**-0.41*exp(tau))
+ return kh
+
+
+def _Kvalue(T, gas, liquid="H2O"):
+ """Equation for the vapor-liquid distribution constant
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ gas : string
+ Name of gas to calculate solubility
+ liquid : string
+ Name of liquid solvent, can be H20 (default) or D2O
+
+ Returns
+ -------
+ kd : float
+ Vapor-liquid distribution constant [-]
+
+ Notes
+ -----
+ The gas availables for H2O solvent are:
+ He, Ne, Ar, Kr, Xe, H2, N2, O2, CO, CO2, H2S, CH4, C2H6, SF6
+ For D2O as solvent:
+ He, Ne, Ar, Kr, Xe, D2, CH4
+
+ Examples
+ --------
+ >>> _Kvalue(600, "He")
+ 3.8019
+ >>> _Kvalue(300, "D2", "D2O")
+ 14.3520
+
+ References
+ ----------
+ IAPWS, Guideline on the Henry's Constant and Vapor-Liquid Distribution
+ Constant for Gases in H2O and D2O at High Temperatures,
+ http://www.iapws.org/relguide/HenGuide.html
+ """
+ if liquid == "D2O":
+ gas += "(D2O)"
+
+ limit = {
+ "He": (273.21, 553.18),
+ "Ne": (273.20, 543.36),
+ "Ar": (273.19, 568.36),
+ "Kr": (273.19, 525.56),
+ "Xe": (273.22, 574.85),
+ "H2": (273.15, 636.09),
+ "N2": (278.12, 636.46),
+ "O2": (274.15, 616.52),
+ "CO": (278.15, 588.67),
+ "CO2": (274.19, 642.66),
+ "H2S": (273.15, 533.09),
+ "CH4": (275.46, 633.11),
+ "C2H6": (275.44, 473.46),
+ "SF6": (283.14, 505.55),
+ "He(D2O)": (288.15, 553.18),
+ "Ne(D2O)": (288.18, 549.96),
+ "Ar(D2O)": (288.30, 583.76),
+ "Kr(D2O)": (288.19, 523.06),
+ "Xe(D2O)": (295.39, 574.85),
+ "D2(D2O)": (288.17, 581.00),
+ "CH4(D2O)": (288.16, 517.46)}
+
+ # Check input parameters
+ if liquid != "D2O" and liquid != "H2O":
+ raise NotImplementedError("Solvent liquid unsupported")
+ if gas not in limit:
+ raise NotImplementedError("Gas unsupported")
+
+ Tmin, Tmax = limit[gas]
+ if T < Tmin or T > Tmax:
+ warnings.warn("Temperature out of data of correlation")
+
+ if liquid == "D2O":
+ Tc = 643.847
+ else:
+ Tc = 647.096
+
+ Tr = T/Tc
+ tau = 1-Tr
+
+ # Eq 6
+ if liquid == "H2O":
+ ci = [1.99274064, 1.09965342, -0.510839303, -1.75493479, -45.5170352,
+ -6.7469445e5]
+ di = [1/3, 2/3, 5/3, 16/3, 43/3, 110/3]
+ q = -0.023767
+ else:
+ ci = [2.7072, 0.58662, -1.3069, -45.663]
+ di = [0.374, 1.45, 2.6, 12.3]
+ q = -0.024552
+ f = sum([c*tau**d for c, d in zip(ci, di)])
+
+ # Select values from Table 2
+ par = {"He": (2267.4082, -2.9616, -3.2604, 7.8819),
+ "Ne": (2507.3022, -38.6955, 110.3992, -71.9096),
+ "Ar": (2310.5463, -46.7034, 160.4066, -118.3043),
+ "Kr": (2276.9722, -61.1494, 214.0117, -159.0407),
+ "Xe": (2022.8375, 16.7913, -61.2401, 41.9236),
+ "H2": (2286.4159, 11.3397, -70.7279, 63.0631),
+ "N2": (2388.8777, -14.9593, 42.0179, -29.4396),
+ "O2": (2305.0674, -11.3240, 25.3224, -15.6449),
+ "CO": (2346.2291, -57.6317, 204.5324, -152.6377),
+ "CO2": (1672.9376, 28.1751, -112.4619, 85.3807),
+ "H2S": (1319.1205, 14.1571, -46.8361, 33.2266),
+ "CH4": (2215.6977, -0.1089, -6.6240, 4.6789),
+ "C2H6": (2143.8121, 6.8859, -12.6084, 0),
+ "SF6": (2871.7265, -66.7556, 229.7191, -172.7400),
+ "He(D2O)": (2293.2474, -54.7707, 194.2924, -142.1257),
+ "Ne(D2O)": (2439.6677, -93.4934, 330.7783, -243.0100),
+ "Ar(D2O)": (2269.2352, -53.6321, 191.8421, -143.7659),
+ "Kr(D2O)": (2250.3857, -42.0835, 140.7656, -102.7592),
+ "Xe(D2O)": (2038.3656, 68.1228, -271.3390, 207.7984),
+ "D2(D2O)": (2141.3214, -1.9696, 1.6136, 0),
+ "CH4(D2O)": (2216.0181, -40.7666, 152.5778, -117.7430)}
+ E, F, G, H = par[gas]
+
+ # Eq 5
+ kd = exp(q*F+E/T*f+(F+G*tau**(2./3)+H*tau)*exp((273.15-T)/100))
+ return kd
diff --git a/iapws/_utils.py b/iapws/_utils.py
new file mode 100644
index 0000000..2ec6191
--- /dev/null
+++ b/iapws/_utils.py
@@ -0,0 +1,216 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""
+Miscelaneous utilities
+"""
+
+from __future__ import division
+
+
+def getphase(Tc, Pc, T, P, x, region):
+ """Return fluid phase string name
+
+ Parameters
+ ----------
+ Tc : float
+ Critical temperature [K]
+ Pc : float
+ Critical pressure [MPa]
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+ x : float
+ Quality [-]
+ region: integer
+ Region number, specific to IAPWS97 region definition
+
+ Returns
+ -------
+ phase : string
+ Phase name
+ """
+ # Avoid round problem
+ P = round(P, 8)
+ T = round(T, 8)
+ if P > Pc and T > Tc:
+ phase = "Supercritical fluid"
+ elif T > Tc:
+ phase = "Gas"
+ elif P > Pc:
+ phase = "Compressible liquid"
+ elif P == Pc and T == Tc:
+ phase = "Critical point"
+ elif region == 4 and x == 1:
+ phase = "Saturated vapor"
+ elif region == 4 and x == 0:
+ phase = "Saturated liquid"
+ elif region == 4:
+ phase = "Two phases"
+ elif x == 1:
+ phase = "Vapour"
+ elif x == 0:
+ phase = "Liquid"
+ return phase
+
+
+class _fase(object):
+ """Class to implement a null phase"""
+ v = None
+ rho = None
+
+ h = None
+ s = None
+ u = None
+ a = None
+ g = None
+
+ cp = None
+ cv = None
+ cp_cv = None
+ w = None
+ Z = None
+ fi = None
+ f = None
+
+ mu = None
+ k = None
+ nu = None
+ Prandt = None
+ epsilon = None
+ alfa = None
+ n = None
+
+ alfap = None
+ betap = None
+ joule = None
+ Gruneisen = None
+ alfav = None
+ kappa = None
+ betas = None
+ gamma = None
+ Kt = None
+ kt = None
+ Ks = None
+ ks = None
+ dpdT_rho = None
+ dpdrho_T = None
+ drhodT_P = None
+ drhodP_T = None
+ dhdT_rho = None
+ dhdT_P = None
+ dhdrho_T = None
+ dhdrho_P = None
+ dhdP_T = None
+ dhdP_rho = None
+
+ Z_rho = None
+ IntP = None
+ hInput = None
+
+
+def deriv_H(state, z, x, y, fase):
+ """Calculate generic partial derivative: (∂z/∂x)y from a fundamental
+ helmholtz free energy equation of state
+
+ Parameters
+ ----------
+ state : any python object
+ Only need define P and T properties
+ x, y, z : string
+ Name of variables of derivate, can be: P, T, v, rho, u, h, s, g, a
+ fase : any python object
+ Define other phase properties v, cv, alfap, s, betap
+
+ Returns
+ -------
+ deriv : float
+ ∂z/∂x|y
+
+ References
+ ----------
+ IAPWS, Revised Advisory Note No. 3: Thermodynamic Derivatives from IAPWS
+ Formulations, http://www.iapws.org/relguide/Advise3.pdf
+ """
+ # We use the relation between rho and v and his partial derivative
+ # ∂v/∂b|c = -1/ρ² ∂ρ/∂b|c
+ # ∂a/∂v|c = -ρ² ∂a/∂ρ|c
+ mul = 1
+ if z == "rho":
+ mul = -fase.rho**2
+ z = "v"
+ if x == "rho":
+ mul = -1/fase.rho**2
+ x = "v"
+ if y == "rho":
+ y = "v"
+
+ dT = {"P": state.P*1000*fase.alfap,
+ "T": 1,
+ "v": 0,
+ "u": fase.cv,
+ "h": fase.cv+state.P*1000*fase.v*fase.alfap,
+ "s": fase.cv/state.T,
+ "g": state.P*1000*fase.v*fase.alfap-fase.s,
+ "a": -fase.s}
+ dv = {"P": -state.P*1000*fase.betap,
+ "T": 0,
+ "v": 1,
+ "u": state.P*1000*(state.T*fase.alfap-1),
+ "h": state.P*1000*(state.T*fase.alfap-fase.v*fase.betap),
+ "s": state.P*1000*fase.alfap,
+ "g": -state.P*1000*fase.v*fase.betap,
+ "a": -state.P*1000}
+ deriv = (dv[z]*dT[y]-dT[z]*dv[y])/(dv[x]*dT[y]-dT[x]*dv[y])
+ return mul*deriv
+
+
+def deriv_G(state, z, x, y, fase):
+ """Calculate generic partial derivative: (∂z/∂x)y from a fundamental
+ Gibbs free energy equation of state
+
+ Parameters
+ ----------
+ state : any python object
+ Only need define P and T properties
+ x, y, z : string
+ Name of variables of derivate, can be: P, T, v, rho, u, h, s, g, a
+ fase : any python object
+ Define other phase properties v, cp, alfav, s, xkappa
+
+ Returns
+ -------
+ deriv : float
+ ∂z/∂x|y
+
+ References
+ ----------
+ IAPWS, Revised Advisory Note No. 3: Thermodynamic Derivatives from IAPWS
+ Formulations, http://www.iapws.org/relguide/Advise3.pdf
+ """
+ mul = 1
+ if z == "rho":
+ mul = -fase.rho**2
+ z = "v"
+ if x == "rho":
+ mul = -1/fase.rho**2
+ x = "v"
+
+ dT = {"P": 0,
+ "T": 1,
+ "v": fase.v*fase.alfav,
+ "u": fase.cp-state.P*1000*fase.v*fase.alfav,
+ "h": fase.cp,
+ "s": fase.cp/state.T,
+ "g": -fase.s,
+ "a": -state.P*1000*fase.v*fase.alfav-fase.s}
+ dP = {"P": 1,
+ "T": 0,
+ "v": -fase.v*fase.xkappa,
+ "u": fase.v*(state.P*1000*fase.xkappa-state.T*fase.alfav),
+ "h": fase.v*(1-state.T*fase.alfav),
+ "s": -fase.v*fase.alfav,
+ "g": fase.v,
+ "a": state.P*1000*fase.v*fase.xkappa}
+ deriv = (dP[z]*dT[y]-dT[z]*dP[y])/(dP[x]*dT[y]-dT[x]*dP[y])
+ return mul*deriv
diff --git a/iapws/ammonia.py b/iapws/ammonia.py
new file mode 100644
index 0000000..bfb5ae2
--- /dev/null
+++ b/iapws/ammonia.py
@@ -0,0 +1,891 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""
+Guideline on the IAPWS Formulation 2001 for the Thermodynamic Properties of
+Ammonia-Water Mistures
+"""
+
+
+from __future__ import division
+from math import exp, log, pi
+import warnings
+
+from scipy.constants import Boltzmann as kb
+from scipy.optimize import fsolve
+from .iapws95 import MEoS, IAPWS95
+
+
+class NH3(MEoS):
+ """Multiparameter equation of state for ammonia"""
+ name = "ammonia"
+ CASNumber = "7664-41-7"
+ formula = "NH3"
+ synonym = "R-717"
+ rhoc = 225.
+ Tc = 405.40
+ Pc = 11333.0 # kPa
+ M = 17.03026 # g/mol
+ Tt = 195.495
+ Tb = 239.823
+ f_acent = 0.25601
+ momentoDipolar = 1.470
+
+ Fi0 = {"ao_log": [1, -1],
+ "pow": [0, 1, 1./3, -1.5, -1.75],
+ "ao_pow": [-15.81502, 4.255726, 11.47434, -1.296211, 0.5706757],
+ "ao_exp": [], "titao": [],
+ "ao_hyp": [], "hyp": []}
+
+ _constants = {
+ "R": 8.314471,
+
+ "nr1": [-0.1858814e01, 0.4554431e-1, 0.7238548, 0.1229470e-1,
+ 0.2141882e-10],
+ "d1": [1, 2, 1, 4, 15],
+ "t1": [1.5, -0.5, 0.5, 1., 3.],
+
+ "nr2": [-0.1430020e-1, 0.3441324, -0.2873571, 0.2352589e-4,
+ -0.3497111e-1, 0.1831117e-2, 0.2397852e-1, -0.4085375e-1,
+ 0.2379275, -0.3548972e-1, -0.1823729, 0.2281556e-1,
+ -0.6663444e-2, -0.8847486e-2, 0.2272635e-2, -0.5588655e-3],
+ "d2": [3, 3, 1, 8, 2, 8, 1, 1, 2, 3, 2, 4, 3, 1, 2, 4],
+ "t2": [0, 3, 4, 4, 5, 5, 3, 6, 8, 8, 10, 10, 5, 7.5, 15, 30],
+ "c2": [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3],
+ "gamma2": [1]*16}
+
+ _melting = {"eq": 1, "Tref": Tt, "Pref": 1000,
+ "Tmin": Tt, "Tmax": 700.0,
+ "a1": [], "exp1": [], "a2": [], "exp2": [],
+ "a3": [0.2533125e4], "exp3": [1]}
+
+ _surf = {"sigma": [0.1028, -0.09453], "exp": [1.211, 5.585]}
+ _Pv = {
+ "eq": 5,
+ "ao": [-0.70993e1, -0.24330e1, 0.87591e1, -0.64091e1, -0.21185e1],
+ "exp": [1., 1.5, 1.7, 1.95, 4.2]}
+ _rhoL = {
+ "eq": 1,
+ "ao": [0.34488e2, -0.12849e3, 0.17382e3, -0.10699e3, 0.30339e2],
+ "exp": [0.58, 0.75, 0.9, 1.1, 1.3]}
+ _rhoG = {
+ "eq": 3,
+ "ao": [-.38435, -4.0846, -6.6634, -0.31881e2, 0.21306e3, -0.24648e3],
+ "exp": [0.218, 0.55, 1.5, 3.7, 5.5, 5.8]}
+
+ def _visco(self, rho, T, fase=None):
+ """Equation for the Viscosity
+
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ mu : float
+ Viscosity [Pa·s]
+
+ References
+ ----------
+ Fenghour, A., Wakeham, W.A., Vesovic, V., Watson, J.T.R., Millat, J.,
+ and Vogel, E., The viscosity of ammonia, J. Phys. Chem. Ref. Data 24,
+ 1649 (1995). doi:10.1063/1.555961
+ """
+ ek = 386
+ sigma = 0.2957
+
+ rho = rho/self.M
+ T_ = T/ek
+
+ # Eq 4
+ a = [4.99318220, -0.61122364, 0.0, 0.18535124, -0.11160946]
+ omega = exp(sum([ai*log(T_)**i for i, ai in enumerate(a)]))
+
+ # Eq 2, Zero-Density Limit
+ muo = 2.1357*(T*self.M)**0.5/sigma**2/omega
+
+ # Eq 8, Viscosity virial coefficient
+ cv = [-0.17999496e1, 0.46692621e2, -0.53460794e3, 0.33604074e4,
+ -0.13019164e5, 0.33414230e5, -0.58711743e5, 0.71426686e5,
+ -0.59834012e5, 0.33652741e5, -0.1202735e5, 0.24348205e4,
+ -0.20807957e3]
+ Bn = 0.6022137*sigma**3*sum([c*T_**(-i/2) for i, c in enumerate(cv)])
+ # Eq 7
+ mub = Bn*muo*rho
+
+ # Eq 10
+ dij = [2.19664285e-1, -0.83651107e-1, 0.17366936e-2, -0.64250359e-2,
+ 1.67668649e-4, -1.49710093e-4, 0.77012274e-4]
+ ji = [2, 4, 0, 1, 2, 3, 4]
+ ii = [2, 2, 3, 3, 4, 4, 4]
+ mur = sum([d/T_**j*rho**i for d, j, i in zip(dij, ji, ii)])
+
+ # Eq 1
+ mu = muo + mub + mur
+ return mu*1e-6
+
+ def _thermo(self, rho, T, fase):
+ """Equation for the thermal conductivity
+
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+ fase: dict
+ phase properties
+
+ Returns
+ -------
+ k : float
+ Thermal conductivity [W/mK]
+
+ References
+ ----------
+ Tufeu, R., Ivanov, D.Y., Garrabos, Y., and Le Neindre, B., Thermal
+ conductivity of ammonia in a large temperature and pressure range
+ including the critical region, Ber. Bunsenges. Phys. Chem., 88:422-427,
+ 1984. doi:10.1002/bbpc.19840880421
+ """
+ # The paper use a diferent rhoc value to the EoS
+ rhoc = 235
+
+ if rho == rhoc and T == self.Tc:
+ warnings.warn("Thermal conductiviy undefined in critical point")
+ return None
+
+ # Eq 6
+ no = [0.3589e-1, -0.1750e-3, 0.4551e-6, 0.1685e-9, -0.4828e-12]
+ Lo = sum([n*T**i for i, n in enumerate(no)])
+
+ # Eq 7
+ nb = [0.16207e-3, 0.12038e-5, -0.23139e-8, 0.32749e-11]
+ L_ = sum([n*rho**(i+1) for i, n in enumerate(nb)])
+
+ # Critical enchancement
+ t = abs(T-405.4)/405.4
+ dPT = 1e5*(2.18-0.12/exp(17.8*t))
+ nb = 1e-5*(2.6+1.6*t)
+
+ DL = 1.2*kb*T**2/6/pi/nb/(1.34e-10/t**0.63*(1+t**0.5))*dPT**2 * \
+ 0.423e-8/t**1.24*(1+t**0.5/0.7)
+
+ # Add correction for entire range of temperature, Eq 10
+ DL *= exp(-36*t**2)
+
+ X = 0.61*rhoc+16.5*log(t)
+ if rho > 0.6*rhoc:
+ # Eq 11
+ DL *= X**2/(X**2+(rho-0.96*rhoc)**2)
+ else:
+ # Eq 14
+ DL = X**2/(X**2+(0.6*rhoc-0.96*rhoc)**2)
+ DL *= rho**2/(0.6*rhoc)**2
+
+ # Eq 5
+ k = Lo+L_+DL
+ return k
+
+
+class H2ONH3(object):
+ """
+ Water-Ammonia mixture class with complete functionality
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+ rho : float
+ Density [kg/m³]
+ v : float
+ Specific volume [m³/kg]
+ A : float
+ Mass fraction of dry air in humid air [kg/kg]
+ xa : float
+ Mole fraction of dry air in humid air [-]
+ W : float
+ Mass fraction of water in humid air [kg/kg]
+ xw : float
+ Mole fraction of water in humid air [-]
+
+ Notes
+ -----
+ * It needs two incoming properties of T, P, rho.
+ * v as a alternate input parameter to rho
+ * For composition need one of A, xa, W, xw.
+
+ Returns
+ -------
+ The calculated instance has the following properties:
+ * P: Pressure [MPa]
+ * T: Temperature [K]
+ * g: Specific Gibbs free energy [kJ/kg]
+ * a: Specific Helmholtz free energy [kJ/kg]
+ * v: Specific volume [m³/kg]
+ * rho: Density [kg/m³]
+ * h: Specific enthalpy [kJ/kg]
+ * u: Specific internal energy [kJ/kg]
+ * s: Specific entropy [kJ/kg·K]
+ * cp: Specific isobaric heat capacity [kJ/kg·K]
+ * w: Speed of sound [m/s]
+
+ * alfav: Isobaric cubic expansion coefficient [1/K]
+ * betas: Isoentropic temperature-pressure coefficient [-]
+ * xkappa: Isothermal Expansion Coefficient [-]
+ * ks: Adiabatic Compressibility [1/MPa]
+
+ * A: Mass fraction of dry air in humid air [kg/kg]
+ * xa: Mole fraction of dry air in humid air [-]
+ * W: Mass fraction of water in humid air [kg/kg]
+ * xw: Mole fraction of water in humid air [-]
+ * mu: Relative chemical potential [kJ/kg]
+ * muw: Chemical potential of water [kJ/kg]
+ * M: Molar mass of humid air [g/mol]
+ * HR: Humidity ratio [-]
+ * xa: Mole fraction of dry air [-]
+ * xw: Mole fraction of water [-]
+ * xa_sat: Mole fraction of dry air at saturation state [-]
+ * RH: Relative humidity
+ """
+ kwargs = {"T": 0.0,
+ "P": 0.0,
+ "rho": 0.0,
+ "v": 0.0,
+ "x": None
+ }
+ status = 0
+ msg = "Undefined"
+
+ def __init__(self, **kwargs):
+ """Constructor, define common constant and initinialice kwargs"""
+ self.kwargs = H2ONH3.kwargs.copy()
+ self.__call__(**kwargs)
+
+ def __call__(self, **kwargs):
+ """Make instance callable to can add input parameter one to one"""
+ # Check alernate input parameters
+ if kwargs.get("v", 0):
+ kwargs["rho"] = 1./kwargs["v"]
+ del kwargs["v"]
+
+ self.kwargs.update(kwargs)
+
+ if self.calculable:
+ self.status = 1
+ self.calculo()
+ self.msg = ""
+
+ @property
+ def calculable(self):
+ """Check if inputs are enough to define state"""
+ self._mode = ""
+ if self.kwargs["T"] and self.kwargs["P"]:
+ self._mode = "TP"
+ elif self.kwargs["T"] and self.kwargs["rho"]:
+ self._mode = "Trho"
+ elif self.kwargs["P"] and self.kwargs["rho"]:
+ self._mode = "Prho"
+
+ # Composition definition
+ self._composition = ""
+ if self.kwargs["x"] is not None:
+ self._composition = "x"
+
+ return bool(self._mode) and bool(self._composition)
+
+ def calculo(self):
+ """Calculate procedure"""
+ T = self.kwargs["T"]
+ rho = self.kwargs["rho"]
+ P = self.kwargs["P"]
+
+ # Composition alternate definition
+ if self._composition == "z":
+ z = self.kwargs["z"]
+
+ # Thermodynamic definition
+ if self._mode == "TP":
+ def f(rho):
+ fav = self._fav(T, rho, A)
+ return rho**2*fav["fird"]/1000-P
+ rho = fsolve(f, 1)[0]
+ elif self._mode == "Prho":
+ def f(T):
+ fav = self._fav(T, rho, A)
+ return rho**2*fav["fird"]/1000-P
+ T = fsolve(f, 300)[0]
+
+
+ prop = self._prop(rho, T, z)
+ self.T = T
+ self.rho = rho
+ self.v = 1/rho
+ self.P = prop["P"]
+ self.u = prop["u"]
+ self.s = prop["s"]
+ self.h = prop["h"]
+ self.g = prop["g"]
+ self.a = prop["a"]
+
+ self.cp = prop["cp"]
+ self.cv = prop["cv"]
+ self.w = prop["w"]
+
+ self.fugH2O = prop["fugH2O"]
+ self.fugNH3 = prop["fugNH3"]
+
+ # def derivative(self, z, x, y):
+ # """Wrapper derivative for custom derived properties
+ # where x, y, z can be: P, T, v, rho, u, h, s, g, a"""
+ # return deriv_G(self, z, x, y, self)
+
+ def _eq(self, rho, T, z):
+ def f(parr):
+ rhol, rhov, x, y = parr
+ propl = self._prop(rhol, T, x)
+ propv = self._prop(rhov, T, y)
+
+ return (propl["P"]-propv["P"],
+ (1-x)*propl["fugH2O"]-(1-y)*propv["fugH2O"],
+ x*propl["fugNH3"]-y*propv["fugNH3"],)
+
+
+
+
+
+
+ # # TODO: Add equilibrium routine
+ # """Procedure for calculate the composition in saturation state
+
+ # Parameters
+ # ----------
+ # T : float
+ # Temperature [K]
+ # P : float
+ # Pressure [MPa]
+
+ # Returns
+ # -------
+ # Asat : float
+ # Saturation mass fraction of dry air in humid air [kg/kg]
+ # """
+ # if T <= 273.16:
+ # ice = _Ice(T, P)
+ # gw = ice["g"]
+ # rho = ice["rho"]
+ # else:
+ # water = IAPWS95(T=T, P=P)
+ # gw = water.g
+ # rho = water.rho
+
+ # def f(a):
+ # fa = self._fav(T, rho, a)
+ # muw = fa["fir"]+rho*fa["fird"]-a*fa["fira"]
+ # return gw-muw
+ # Asat = fsolve(f, 0.9)[0]
+ # return Asat
+
+ def _Flash(self, T, P, z):
+ """Flash calculation
+ Ref Naji - Conventional and rapid flash claculations"""
+
+ # Generation of trial pahse composition using Wilson correlation
+ k_h2o = IAPWS95.Pc/P*exp(5.373*(1.+IAPWS95.f_acent)*(1.-IAPWS95.Tc/T))
+ k_nh3 = NH3.Pc/P*exp(5.373*(1.+NH3.f_acent)*(1.-NH3.Tc/T))
+
+ def Rachford(beta):
+ return z*(k_nh3-1)/(1-beta*(1-k_nh3)) + \
+ (1-z)*(k_h2o-1)/(1-beta*(1-k_h2o))
+
+ bubble = Rachford(0)
+ dew = Rachford(1)
+ if bubble < 0:
+ # beta < 0, only liquid phase
+ x = z
+ y = z*k_nh3/(bubble+1)
+ beta = 0
+ elif dew >= 0:
+ # beta > 1, only vapor phase
+ x = z/k_nh3/(1-dew)
+ y = z
+ beta = 1
+ else:
+ beta = 0.5
+ while True:
+ betao = beta
+ solucion = fsolve(Rachford, betao, full_output=True)
+ if solucion[2]!=1:
+ print(solucion)
+ break
+ else:
+ beta = solucion[0][0]
+
+ xi=[]
+ yi=[]
+ for zi, ki in zip(self.fraccion, Ki):
+ xi.append(float(zi/(1-x+x*ki)))
+ yi.append(float(zi*ki/(1-x+x*ki)))
+
+ tital=self._fug(self.Z[1], xi)
+ titav=self._fug(self.Z[0], yi)
+ fiv=[z*t*self.P for z, t in zip(yi, titav)]
+ fil=[z*t*self.P for z, t in zip(xi, tital)]
+ #criterio de convergencia Eq 21
+ if sum([abs(l/v-1) for l, v in zip(fil, fiv)])< 1e-14 and abs(x-xo) < 1e-10:
+ break
+ else:
+ Ki=[l/v for l, v in zip(tital, titav)]
+
+ if x < 0:
+ x = 0
+ elif x > 1:
+ x = 1
+
+ return x, xi, yi, Ki
+
+
+ def _Bubble_T(self):
+ def f(T):
+ eq=self.__class__(T, self.P.atm, self.mezcla)
+ return sum([k*x for k, x in zip(eq.Ki, self.fraccion)])-1.
+
+ T=fsolve(f, self.T)
+ return unidades.Temperature(T)
+
+ def _Bubble_P(self):
+ def f(P):
+ eq=self.__class__(self.T, P, self.mezcla)
+ return sum([k*x for k, x in zip(eq.Ki, self.fraccion)])-1.
+
+ P=fsolve(f, self.P.atm)
+ return unidades.Pressure(P, "atm")
+
+ def _Dew_T(self):
+ def f(T):
+ eq=self.__class__(T, self.P.atm, self.mezcla)
+ return 1./sum([x/k for k, x in zip(eq.Ki, self.fraccion)])-1.
+
+ T=fsolve(f, self.T)
+ return unidades.Temperature(T)
+
+ def _Dew_P(self):
+ def f(P):
+ eq=self.__class__(self.T, P, self.mezcla)
+ return sum([x/k for k, x in zip(eq.Ki, self.fraccion)])-1.
+
+ P=fsolve(f, self.P.atm)
+ return unidades.Pressure(P, "atm")
+
+
+
+ def _bubbleP(self, T, xl):
+ def f(parr):
+ rhol, rhov, xv = parr
+ propl = self._prop(rhol, T, xl)
+ propv = self._prop(rhov, T, xv)
+ K_h2o = propv["fugH2O"]/propl["fugH2O"]
+ K_nh3 = propv["fugNH3"]/propl["fugNH3"]
+
+ return (propl["P"]-propv["P"],
+ xl*propl["fugNH3"]-xv*propv["fugNH3"],
+ K_nh3*xl+K_h2o*(1-xl)-1)
+ rhol, rhov, xv = fsolve(f, (5, 0.01, 1))
+ print(f([rhol, rhov, xv]))
+
+ prop = {}
+ prop["T"] = T
+ liq = self._prop(rhol, T, xl)
+ prop["P"] = liq["P"]
+ prop["rhol"] = rhol
+ prop["rhov"] = rhov
+ prop["xl"] = xl
+ prop["xv"] = xv
+ print(prop)
+ return prop
+
+ def _prop(self, rho, T, x):
+ """Thermodynamic properties of ammonia-water mixtures
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ rho : float
+ Density [kg/m³]
+ x : float
+ Mole fraction of ammonia in mixture [mol/mol]
+
+ Returns
+ -------
+ prop : dictionary with thermodynamic properties of humid air
+ M: Mixture molecular mass [g/mol]
+ P: Pressure [MPa]
+ u: Specific internal energy [kJ/kg]
+ s: Specific entropy [kJ/kgK]
+ h: Specific enthalpy [kJ/kg]
+ a: Specific Helmholtz energy [kJ/kg]
+ g: Specific gibbs energy [kJ/kg]
+ cv: Specific isochoric heat capacity [kJ/kgK]
+ cp: Specific isobaric heat capacity [kJ/kgK]
+ w: Speed of sound [m/s]
+ fugH2O: Fugacity of water [-]
+ fugNH3: Fugacity of ammonia [-]
+
+ References
+ ----------
+ IAPWS, Guideline on the IAPWS Formulation 2001 for the Thermodynamic
+ Properties of Ammonia-Water Mixtures,
+ http://www.iapws.org/relguide/nh3h2o.pdf, Table 4
+ """
+ # FIXME: The values are good, bad difer by 1%, a error I can find
+ # In Pressure happen and only use fird
+
+ M = (1-x)*IAPWS95.M + x*NH3.M
+ R = 8.314471/M
+
+ phio = self._phi0(rho, T, x)
+ fio = phio["fio"]
+ tau0 = phio["tau"]
+ fiot = phio["fiot"]
+ fiott = phio["fiott"]
+
+ phir = self._phir(rho, T, x)
+ fir = phir["fir"]
+ tau = phir["tau"]
+ delta = phir["delta"]
+ firt = phir["firt"]
+ firtt = phir["firtt"]
+ fird = phir["fird"]
+ firdd = phir["firdd"]
+ firdt = phir["firdt"]
+ F = phir["F"]
+
+ prop = {}
+ Z = 1 + delta*fird
+ prop["M"] = M
+ prop["P"] = Z*R*T*rho/1000
+ prop["u"] = R*T*(tau0*fiot + tau*firt)
+ prop["s"] = R*(tau0*fiot + tau*firt - fio - fir)
+ prop["h"] = R*T*(1+delta*fird+tau0*fiot+tau*firt)
+ prop["g"] = prop["h"]-T*prop["s"]
+ prop["a"] = prop["u"]-T*prop["s"]
+ cvR = -tau0**2*fiott - tau**2*firtt
+ prop["cv"] = R*cvR
+ prop["cp"] = R*(cvR+(1+delta*fird-delta*tau*firdt)**2 /
+ (1+2*delta*fird+delta**2*firdd))
+ prop["w"] = (R*T*1000*(1+2*delta*fird+delta**2*firdd +
+ (1+delta*fird-delta*tau*firdt)**2 / cvR))**0.5
+ prop["fugH2O"] = Z*exp(fir+delta*fird-x*F)
+ prop["fugNH3"] = Z*exp(fir+delta*fird+(1-x)*F)
+ return prop
+
+ def _phi0(self, rho, T, x):
+ """Ideal gas Helmholtz energy of binary mixtures and derivatives
+
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+ x : float
+ Mole fraction of ammonia in mixture [mol/mol]
+
+ Returns
+ -------
+ prop : dictionary with ideal adimensional helmholtz energy and deriv
+ tau: the adimensional temperature variable [-]
+ delta: the adimensional density variable [-]
+ fio [-]
+ fiot: [∂fio/∂τ]δ [-]
+ fiod: [∂fio/∂δ]τ [-]
+ fiott: [∂²fio/∂τ²]δ [-]
+ fiodt: [∂²fio/∂τ∂δ] [-]
+ fiodd: [∂²fio/∂δ²]τ [-]
+
+ References
+ ----------
+ IAPWS, Guideline on the IAPWS Formulation 2001 for the Thermodynamic
+ Properties of Ammonia-Water Mixtures,
+ http://www.iapws.org/relguide/nh3h2o.pdf, Eq 2
+ """
+ # Define reducing parameters for mixture model
+ M = (1-x)*IAPWS95.M + x*NH3.M
+ tau = 500/T
+ delta = rho/15/M
+
+ # Table 2
+ Fi0 = {
+ "log_water": 3.006320,
+ "ao_water": [-7.720435, 8.649358],
+ "pow_water": [0, 1],
+ "ao_exp": [0.012436, 0.97315, 1.279500, 0.969560, 0.248730],
+ "titao": [1.666, 4.578, 10.018, 11.964, 35.600],
+ "log_nh3": -1.0,
+ "ao_nh3": [-16.444285, 4.036946, 10.69955, -1.775436, 0.82374034],
+ "pow_nh3": [0, 1, 1/3, -3/2, -7/4]}
+
+ fiod = 1/delta
+ fiodd = -1/delta**2
+ fiodt = 0
+ fiow = fiotw = fiottw = 0
+ fioa = fiota = fiotta = 0
+
+ # Water section
+ if x < 1:
+ fiow = Fi0["log_water"]*log(tau) + log(1-x)
+ fiotw = Fi0["log_water"]/tau
+ fiottw = -Fi0["log_water"]/tau**2
+ for n, t in zip(Fi0["ao_water"], Fi0["pow_water"]):
+ fiow += n*tau**t
+ if t != 0:
+ fiotw += t*n*tau**(t-1)
+ if t not in [0, 1]:
+ fiottw += n*t*(t-1)*tau**(t-2)
+ for n, t in zip(Fi0["ao_exp"], Fi0["titao"]):
+ fiow += n*log(1-exp(-tau*t))
+ fiotw += n*t*((1-exp(-t*tau))**-1-1)
+ fiottw -= n*t**2*exp(-t*tau)*(1-exp(-t*tau))**-2
+
+ # ammonia section
+ if x > 0:
+ fioa = Fi0["log_nh3"]*log(tau) + log(x)
+ fiota = Fi0["log_nh3"]/tau
+ fiotta = -Fi0["log_nh3"]/tau**2
+ for n, t in zip(Fi0["ao_nh3"], Fi0["pow_nh3"]):
+ fioa += n*tau**t
+ if t != 0:
+ fiota += t*n*tau**(t-1)
+ if t not in [0, 1]:
+ fiotta += n*t*(t-1)*tau**(t-2)
+
+ prop = {}
+ prop["tau"] = tau
+ prop["delta"] = delta
+ prop["fio"] = log(delta) + (1-x)*fiow + x*fioa
+ prop["fiot"] = (1-x)*fiotw + x*fiota
+ prop["fiott"] = (1-x)*fiottw + x*fiotta
+ prop["fiod"] = fiod
+ prop["fiodd"] = fiodd
+ prop["fiodt"] = fiodt
+ return prop
+
+ def _phir(self, rho, T, x):
+ """Residual contribution to the free Helmholtz energy
+
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+ x : float
+ Mole fraction of ammonia in mixture [mol/mol]
+
+ Returns
+ -------
+ prop : dictionary with residual adimensional helmholtz energy and deriv
+ tau: the adimensional temperature variable [-]
+ delta: the adimensional density variable [-]
+ fir [-]
+ firt: [∂fir/∂τ]δ,x [-]
+ fird: [∂fir/∂δ]τ,x [-]
+ firtt: [∂²fir/∂τ²]δ,x [-]
+ firdt: [∂²fir/∂τ∂δ]x [-]
+ firdd: [∂²fir/∂δ²]τ,x [-]
+ firx: [∂fir/∂x]τ,δ [-]
+ F: Function for fugacity calculation [-]
+
+ References
+ ----------
+ IAPWS, Guideline on the IAPWS Formulation 2001 for the Thermodynamic
+ Properties of Ammonia-Water Mixtures,
+ http://www.iapws.org/relguide/nh3h2o.pdf, Eq 3
+ """
+
+ # Temperature reducing value, Eq 4
+ Tc12 = 0.9648407/2*(IAPWS95.Tc+NH3.Tc)
+ Tn = (1-x)**2*IAPWS95.Tc + x**2*NH3.Tc + 2*x*(1-x**1.125455)*Tc12
+ dTnx = -2*IAPWS95.Tc*(1-x) + 2*x*NH3.Tc + 2*Tc12*(1-x**1.125455) - \
+ 2*Tc12*1.12455*x**1.12455
+
+ # Density reducing value, Eq 5
+ b = 0.8978069
+ rhoc12 = 1/(1.2395117/2*(1/IAPWS95.rhoc+1/NH3.rhoc))
+ rhon = 1/((1-x)**2/IAPWS95.rhoc + x**2/NH3.rhoc +
+ 2*x*(1-x**b)/rhoc12)
+ drhonx = -(2*b*x**b/rhoc12 + 2*(1-x**b)/rhoc12 +
+ 2*x/NH3.rhoc - 2*(1-x)/IAPWS95.rhoc)/(
+ 2*x*(1-x**b)/rhoc12 + x**2/NH3.rhoc +
+ (1-x)**2/IAPWS95.rhoc)**2
+
+ tau = Tn/T
+ delta = rho/rhon
+
+ water = IAPWS95()
+ phi1 = water._phir(tau, delta)
+
+ ammonia = NH3()
+ phi2 = ammonia._phir(tau, delta)
+
+ Dphi = self._Dphir(tau, delta, x)
+
+ prop = {}
+ prop["tau"] = tau
+ prop["delta"] = delta
+ prop["fir"] = (1-x)*phi1["fir"] + x*phi2["fir"] + Dphi["fir"]
+ prop["firt"] = (1-x)*phi1["firt"] + x*phi2["firt"] + Dphi["firt"]
+ prop["firtt"] = (1-x)*phi1["firtt"] + x*phi2["firtt"] + Dphi["firtt"]
+ prop["fird"] = (1-x)*phi1["fird"] + x*phi2["fird"] + Dphi["fird"]
+ prop["firdd"] = (1-x)*phi1["firdd"] + x*phi2["firdd"] + Dphi["firdd"]
+ prop["firdt"] = (1-x)*phi1["firdt"] + x*phi2["firdt"] + Dphi["firdt"]
+ prop["firx"] = -phi1["fir"] + phi2["fir"] + Dphi["firx"]
+ prop["F"] = prop["firx"] - delta/rhon*drhonx*prop["fird"] + \
+ tau/Tn*dTnx*prop["firt"]
+ return prop
+
+ def _Dphir(self, tau, delta, x):
+ """Departure function to the residual contribution to the free
+ Helmholtz energy
+
+ Parameters
+ ----------
+ tau : float
+ Adimensional temperature [-]
+ delta : float
+ Adimensional density [-]
+ x : float
+ Mole fraction of ammonia in mixture [mol/mol]
+
+ Returns
+ -------
+ prop : dictionary with departure contribution to the residual
+ adimensional helmholtz energy and deriv
+ fir [-]
+ firt: [∂Δfir/∂τ]δ,x [-]
+ fird: [∂Δfir/∂δ]τ,x [-]
+ firtt: [∂²Δfir/∂τ²]δ,x [-]
+ firdt: [∂²Δfir/∂τ∂δ]x [-]
+ firdd: [∂²Δfir/∂δ²]τ,x [-]
+ firx: [∂Δfir/∂x]τ,δ [-]
+
+ References
+ ----------
+ IAPWS, Guideline on the IAPWS Formulation 2001 for the Thermodynamic
+ Properties of Ammonia-Water Mixtures,
+ http://www.iapws.org/relguide/nh3h2o.pdf, Eq 8
+ """
+ fx = x*(1-x**0.5248379)
+ dfx = 1-1.5248379*x**0.5248379
+
+ # Polinomial terms
+ n = -1.855822e-2
+ t = 1.5
+ d = 4
+ fir = n*delta**d*tau**t
+ fird = n*d*delta**(d-1)*tau**t
+ firdd = n*d*(d-1)*delta**(d-2)*tau**t
+ firt = n*t*delta**d*tau**(t-1)
+ firtt = n*t*(t-1)*delta**d*tau**(t-2)
+ firdt = n*t*d*delta**(d-1)*tau**(t-1)
+ firx = dfx*n*delta**d*tau**t
+
+ # Exponential terms
+ nr2 = [5.258010e-2, 3.552874e-10, 5.451379e-6, -5.998546e-13,
+ -3.687808e-6]
+ t2 = [0.5, 6.5, 1.75, 15, 6]
+ d2 = [5, 15, 12, 12, 15]
+ c2 = [1, 1, 1, 1, 2]
+ for n, d, t, c in zip(nr2, d2, t2, c2):
+ fir += n*delta**d*tau**t*exp(-delta**c)
+ fird += n*exp(-delta**c)*delta**(d-1)*tau**t*(d-c*delta**c)
+ firdd += n*exp(-delta**c)*delta**(d-2)*tau**t * \
+ ((d-c*delta**c)*(d-1-c*delta**c)-c**2*delta**c)
+ firt += n*t*delta**d*tau**(t-1)*exp(-delta**c)
+ firtt += n*t*(t-1)*delta**d*tau**(t-2)*exp(-delta**c)
+ firdt += n*t*delta**(d-1)*tau**(t-1)*(d-c*delta**c)*exp(
+ -delta**c)
+ firx += dfx*n*delta**d*tau**t*exp(-delta**c)
+
+ # Exponential terms with composition
+ nr3 = [0.2586192, -1.368072e-8, 1.226146e-2, -7.181443e-2, 9.970849e-2,
+ 1.0584086e-3, -0.1963687]
+ t3 = [-1, 4, 3.5, 0, -1, 8, 7.5]
+ d3 = [4, 15, 4, 5, 6, 10, 6]
+ c3 = [1, 1, 1, 1, 2, 2, 2]
+ for n, d, t, c in zip(nr3, d3, t3, c3):
+ fir += x*n*delta**d*tau**t*exp(-delta**c)
+ fird += x*n*exp(-delta**c)*delta**(d-1)*tau**t*(d-c*delta**c)
+ firdd += x*n*exp(-delta**c)*delta**(d-2)*tau**t * \
+ ((d-c*delta**c)*(d-1-c*delta**c)-c**2*delta**c)
+ firt += x*n*t*delta**d*tau**(t-1)*exp(-delta**c)
+ firtt += x*n*t*(t-1)*delta**d*tau**(t-2)*exp(-delta**c)
+ firdt += x*n*t*delta**(d-1)*tau**(t-1)*(d-c*delta**c)*exp(
+ -delta**c)
+ firx += x*dfx*n*delta**d*tau**t*exp(-delta**c)
+
+ n = -0.7777897
+ t = 4
+ d = 2
+ c = 2
+ fir += x**2*n*delta**d*tau**t*exp(-delta**c)
+ fird += x**2*n*exp(-delta**c)*delta**(d-1)*tau**t*(d-c*delta**c)
+ firdd += x**2*n*exp(-delta**c)*delta**(d-2)*tau**t * \
+ ((d-c*delta**c)*(d-1-c*delta**c)-c**2*delta**c)
+ firt += x**2*n*t*delta**d*tau**(t-1)*exp(-delta**c)
+ firtt += x**2*n*t*(t-1)*delta**d*tau**(t-2)*exp(-delta**c)
+ firdt += x**2*n*t*delta**(d-1)*tau**(t-1)*(d-c*delta**c)*exp(
+ -delta**c)
+ firx += x**2*dfx*n*delta**d*tau**t*exp(-delta**c)
+
+ prop = {}
+ prop["fir"] = fir*fx
+ prop["firt"] = firt*fx
+ prop["firtt"] = firtt*fx
+ prop["fird"] = fird*fx
+ prop["firdd"] = firdd*fx
+ prop["firdt"] = firdt*fx
+ prop["firx"] = firx
+ return prop
+
+
+def Ttr(x):
+ """Equation for the triple point of ammonia-water mixture
+
+ Parameters
+ ----------
+ x : float
+ Mole fraction of ammonia in mixture [mol/mol]
+
+ Returns
+ -------
+ Ttr : float
+ Triple point temperature [K]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 0 ≤ x ≤ 1
+
+ References
+ ----------
+ IAPWS, Guideline on the IAPWS Formulation 2001 for the Thermodynamic
+ Properties of Ammonia-Water Mixtures,
+ http://www.iapws.org/relguide/nh3h2o.pdf, Eq 9
+ """
+ if 0 <= x <= 0.33367:
+ Ttr = 273.16*(1-0.3439823*x-1.3274271*x**2-274.973*x**3)
+ elif 0.33367 < x <= 0.58396:
+ Ttr = 193.549*(1-4.987368*(x-0.5)**2)
+ elif 0.58396 < x <= 0.81473:
+ Ttr = 194.38*(1-4.886151*(x-2/3)**2+10.37298*(x-2/3)**3)
+ elif 0.81473 < x <= 1:
+ Ttr = 195.495*(1-0.323998*(1-x)-15.87560*(1-x)**4)
+ else:
+ raise NotImplementedError("Incoming out of bound")
+ return Ttr
diff --git a/iapws/humidAir.py b/iapws/humidAir.py
new file mode 100644
index 0000000..ed0c048
--- /dev/null
+++ b/iapws/humidAir.py
@@ -0,0 +1,983 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""
+Guideline on the IAPWS Formulation 2001 for the Thermodynamic Properties of
+Ammonia-Water Mistures
+"""
+
+
+from __future__ import division
+from math import exp, log, pi, atan
+import warnings
+
+from scipy.optimize import fsolve
+
+from ._iapws import M as Mw
+from ._iapws import _Ice
+from ._utils import deriv_G
+from .iapws95 import MEoS, IAPWS95
+
+
+Ma = 28.96546 # g/mol
+R = 8.314472 # J/molK
+
+
+def _virial(T):
+ """Virial equations for humid air
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ prop : float
+ dictionary with critical coefficient
+ Baa: Second virial coefficient of dry air [m³/mol]
+ Baw: Second air-water cross virial coefficient [m³/mol]
+ Bww: Second virial coefficient of water [m³/mol]
+ Caaa: Third virial coefficient of dry air [m⁶/mol]
+ Caaw: Third air-water cross virial coefficient [m⁶/mol]
+ Caww: Third air-water cross virial coefficient [m⁶/mol]
+ Cwww: Third virial coefficient of dry air [m⁶/mol]
+ Bawt: dBaw/dT [m³/molK]
+ Bawtt: d²Baw/dT² [m³/molK²]
+ Caawt: dCaaw/dT [m⁶/molK]
+ Caawtt: d²Caaw/dT² [m⁶/molK²]
+ Cawwt: dCaww/dT [m⁶/molK]
+ Cawwtt: d²Caww/dT² [m⁶/molK²]
+
+ Raises
+ ------
+ Warning : If T isn't in range of validity
+ * Baa: 60 ≤ T ≤ 2000
+ * Baw: 130 ≤ T ≤ 2000
+ * Bww: 130 ≤ T ≤ 1273
+ * Caaa: 60 ≤ T ≤ 2000
+ * Caaw: 193 ≤ T ≤ 493
+ * Caww: 173 ≤ T ≤ 473
+ * Cwww: 130 ≤ T ≤ 1273
+
+ Examples
+ --------
+ >>> _virial(200)["Baa"]
+ -3.92722567e-5
+
+ References
+ ----------
+ IAPWS, Guideline on a Virial Equation for the Fugacity of H2O in Humid Air,
+ http://www.iapws.org/relguide/VirialFugacity.html
+ IAPWS, Guideline on an Equation of State for Humid Air in Contact with
+ Seawater and Ice, Consistent with the IAPWS Formulation 2008 for the
+ Thermodynamic Properties of Seawater, Table 10,
+ http://www.iapws.org/relguide/SeaAir.html
+ """
+ # Check input parameters
+ if T < 60 or T > 2000:
+ warnings.warn("Baa out of validity range")
+ if T < 130 or T > 2000:
+ warnings.warn("Baw out of validity range")
+ if T < 130 or T > 1273:
+ warnings.warn("Bww out of validity range")
+ if T < 60 or T > 2000:
+ warnings.warn("Caaa out of validity range")
+ if T < 193 or T > 493:
+ warnings.warn("Caaw out of validity range")
+ if T < 173 or T > 473:
+ warnings.warn("Caww out of validity range")
+ if T < 130 or T > 1273:
+ warnings.warn("Cwww out of validity range")
+
+ T_ = T/100
+ tau = IAPWS95.Tc/T
+
+ # Table 1
+ # Reorganizated to easy use in equations
+ tb = [-0.5, 0.875, 1, 4, 6, 12, 7]
+ nb = [0.12533547935523e-1, 0.78957634722828e1, -0.87803203303561e1,
+ -0.66856572307965, 0.20433810950965, -0.66212605039687e-4,
+ -0.10793600908932]
+ bc = [0.5, 0.75, 1, 5, 1, 9, 10]
+ nc = [0.31802509345418, -0.26145533859358, -0.19232721156002,
+ -0.25709043003438, 0.17611491008752e-1, 0.22132295167546,
+ -0.40247669763528]
+ bc2 = [4, 6, 12]
+ nc2 = [-0.66856572307965, 0.20433810950965, -0.66212605039687e-4]
+
+ # Table 2
+ ai = [3.5, 3.5]
+ bi = [0.85, 0.95]
+ Bi = [0.2, 0.2]
+ ni = [-0.14874640856724, 0.31806110878444]
+ Ci = [28, 32]
+ Di = [700, 800]
+ Ai = [0.32, 0.32]
+ betai = [0.3, 0.3]
+
+ # Eq 5
+ sum1 = sum([n*tau**t for n, t in zip(nb, tb)])
+ sum2 = 0
+ for n, b, B, A, C, D in zip(ni, bi, Bi, Ai, Ci, Di):
+ sum2 += n*((A+1-tau)**2+B)**b*exp(-C-D*(tau-1)**2)
+ Bww = Mw/IAPWS95.rhoc*(sum1+sum2)
+
+ # Eq 6
+ sum1 = sum([n*tau**t for n, t in zip(nc, bc)])
+ sum2 = sum([n*tau**t for n, t in zip(nc2, bc2)])
+ sum3 = 0
+ for a, b, B, n, C, D, A, beta in zip(ai, bi, Bi, ni, Ci, Di, Ai, betai):
+ Tita = A+1-tau
+ sum3 += n*(C*(Tita**2+B)-b*(A*Tita/beta+B*a))*(Tita**2+B)**(b-1) * \
+ exp(-C-D*(tau-1)**2)
+ Cwww = 2*(Mw/IAPWS95.rhoc)**2*(sum1-sum2+2*sum3)
+
+ # Table 3
+ ai = [0.482737e-3, 0.105678e-2, -0.656394e-2, 0.294442e-1, -0.319317e-1]
+ bi = [-10.728876, 34.7802, -38.3383, 33.406]
+ ci = [66.5687, -238.834, -176.755]
+ di = [-0.237, -1.048, -3.183]
+
+ Baw = 1e-6*sum([c*T_**d for c, d in zip(ci, di)]) # Eq 7
+ Caaw = 1e-6*sum([a/T_**i for i, a in enumerate(ai)]) # Eq 8
+ Caww = -1e-6*exp(sum([b/T_**i for i, b in enumerate(bi)])) # Eq 9
+
+ # Eq T56
+ Bawt = 1e-6*T_/T*sum([c*d*T_**(d-1) for c, d in zip(ci, di)])
+ # Eq T57
+ Bawtt = 1e-6*T_**2/T**2*sum(
+ [c*d*(d-1)*T_**(d-2) for c, d in zip(ci, di)])
+ # Eq T59
+ Caawt = -1e-6*T_/T*sum([i*a*T_**(-i-1) for i, a in enumerate(ai)])
+ # Eq T60
+ Caawtt = 1e-6*T_**2/T**2*sum(
+ [i*(i+1)*a*T_**(-i-2) for i, a in enumerate(ai)])
+ # Eq T62
+ Cawwt = 1e-6*T_/T*sum([i*b*T_**(-i-1) for i, b in enumerate(bi)]) * \
+ exp(sum([b/T_**i for i, b in enumerate(bi)]))
+ # Eq T63
+ Cawwtt = -1e-6*T_**2/T**2*((
+ sum([i*(i+1)*b*T_**(-i-2) for i, b in enumerate(bi)]) +
+ sum([i*b*T_**(-i-1) for i, b in enumerate(bi)])**2) *
+ exp(sum([b/T_**i for i, b in enumerate(bi)])))
+
+ # Table 4
+ # Reorganizated to easy use in equations
+ ji = [0, 0.33, 1.01, 1.6, 3.6, 3.5]
+ ni = [0.118160747229, 0.713116392079, -0.161824192067e1, -0.101365037912,
+ -0.146629609713, 0.148287891978e-1]
+ tau = 132.6312/T
+
+ Baa = 1/10.4477*sum([n*tau**j for j, n in zip(ji, ni)]) # Eq 10
+ Caaa = 2/10.4477**2*(0.714140178971e-1+0.101365037912*tau**1.6) # Eq 11
+
+ prop = {}
+ prop["Baa"] = Baa/1000
+ prop["Baw"] = Baw
+ prop["Bww"] = Bww/1000
+ prop["Caaa"] = Caaa/1e6
+ prop["Caaw"] = Caaw
+ prop["Caww"] = Caww
+ prop["Cwww"] = Cwww/1e6
+ prop["Bawt"] = Bawt
+ prop["Bawtt"] = Bawtt
+ prop["Caawt"] = Caawt
+ prop["Caawtt"] = Caawtt
+ prop["Cawwt"] = Cawwt
+ prop["Cawwtt"] = Cawwtt
+ return prop
+
+
+def _fugacity(T, P, x):
+ """Fugacity equation for humid air
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+ x : float
+ Mole fraction of water-vapor [-]
+
+ Returns
+ -------
+ fv : float
+ fugacity coefficient [MPa]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in range of validity
+ * 193 ≤ T ≤ 473
+ * 0 ≤ P ≤ 5
+ * 0 ≤ x ≤ 1
+ Really the xmax is the xsaturation but isn't implemented
+
+ Examples
+ --------
+ >>> _fugacity(300, 1, 0.1)
+ 0.0884061686
+
+ References
+ ----------
+ IAPWS, Guideline on a Virial Equation for the Fugacity of H2O in Humid Air,
+ http://www.iapws.org/relguide/VirialFugacity.html
+ """
+ # Check input parameters
+ if T < 193 or T > 473 or P < 0 or P > 5 or x < 0 or x > 1:
+ raise(NotImplementedError("Input not in range of validity"))
+
+ R = 8.314462 # J/molK
+
+ # Virial coefficients
+ vir = _virial(T)
+
+ # Eq 3
+ beta = x*(2-x)*vir["Bww"]+(1-x)**2*(2*vir["Baw"]-vir["Baa"])
+
+ # Eq 4
+ gamma = x**2*(3-2*x)*vir["Cwww"] + \
+ (1-x)**2*(6*x*vir["Caww"]+3*(1-2*x)*vir["Caaw"]-2*(1-x)*vir["Caaa"]) +\
+ (x**2*vir["Bww"]+2*x*(1-x)*vir["Baw"]+(1-x)**2*vir["Baa"]) * \
+ (x*(3*x-4)*vir["Bww"]+2*(1-x)*(3*x-2)*vir["Baw"]+3*(1-x)**2*vir["Baa"])
+
+ # Eq 2
+ fv = x*P*exp(beta*P*1e6/R/T+0.5*gamma*(P*1e6/R/T)**2)
+ return fv
+
+
+class MEoSBlend(MEoS):
+ """Special meos class to im:plement pseudocomponent blend and defining its
+ ancillary dew and bubble point"""
+ @classmethod
+ def _dewP(cls, T):
+ """Using ancillary equation return the pressure of dew point"""
+ c = cls._blend["dew"]
+ Tj = cls._blend["Tj"]
+ Pj = cls._blend["Pj"]
+ Tita = 1-T/Tj
+
+ suma = 0
+ for i, n in zip(c["i"], c["n"]):
+ suma += n*Tita**(i/2.)
+ P = Pj*exp(Tj/T*suma)
+ return P
+
+ @classmethod
+ def _bubbleP(cls, T):
+ """Using ancillary equation return the pressure of bubble point"""
+ c = cls._blend["bubble"]
+ Tj = cls._blend["Tj"]
+ Pj = cls._blend["Pj"]
+ Tita = 1-T/Tj
+
+ suma = 0
+ for i, n in zip(c["i"], c["n"]):
+ suma += n*Tita**(i/2.)
+ P = Pj*exp(Tj/T*suma)
+ return P
+
+
+class Air(MEoSBlend):
+ """Multiparameter equation of state for Air as pseudocomponent"""
+ name = "air"
+ CASNumber = "1"
+ formula = "N2+Ar+O2"
+ synonym = "R-729"
+ rhoc = 10.4477*Ma
+ Tc = 132.6306
+ Pc = 3786.0 # kPa
+ M = Ma
+ Tt = 59.75
+ Tb = 78.903
+ f_acent = 0.0335
+ momentoDipolar = 0.0
+
+ Fi0 = {"ao_log": [1, 2.490888032],
+ "pow": [-3, -2, -1, 0, 1, 1.5],
+ "ao_pow": [0.6057194e-7, -0.210274769e-4, -0.158860716e-3,
+ 9.7450251743948, 10.0986147428912, -0.19536342e-3],
+ "ao_exp": [0.791309509, 0.212236768],
+ "titao": [25.36365, 16.90741],
+ "ao_exp2": [-0.197938904],
+ "titao2": [87.31279],
+ "sum2": [2./3]
+ }
+
+ _constants = {
+ "R": 8.31451,
+ "Tref": 132.6312, "rhoref": 10.4477*Ma,
+
+ "nr1": [0.118160747229, 0.713116392079, -0.161824192067e1,
+ 0.714140178971e-1, -0.865421396646e-1, 0.134211176704,
+ 0.112626704218e-1, -0.420533228842e-1, 0.349008431982e-1,
+ 0.164957183186e-3],
+ "d1": [1, 1, 1, 2, 3, 3, 4, 4, 4, 6],
+ "t1": [0, 0.33, 1.01, 0, 0, 0.15, 0, 0.2, 0.35, 1.35],
+
+ "nr2": [-0.101365037912, -0.173813690970, -0.472103183731e-1,
+ -0.122523554253e-1, -0.146629609713, -0.316055879821e-1,
+ 0.233594806142e-3, 0.148287891978e-1, -0.938782884667e-2],
+ "d2": [1, 3, 5, 6, 1, 3, 11, 1, 3],
+ "t2": [1.6, 0.8, 0.95, 1.25, 3.6, 6, 3.25, 3.5, 15],
+ "c2": [1, 1, 1, 1, 2, 2, 2, 3, 3],
+ "gamma2": [1]*9}
+
+ _blend = {
+ "Tj": 132.6312, "Pj": 3.78502,
+ "dew": {"i": [1, 2, 5, 8],
+ "n": [-0.1567266, -5.539635, 0.7567212, -3.514322]},
+ "bubble": {"i": [1, 2, 3, 4, 5, 6],
+ "n": [0.2260724, -7.080499, 5.700283, -12.44017, 17.81926,
+ -10.81364]}}
+
+ _melting = {"eq": 1, "Tref": Tb, "Pref": 5.265,
+ "Tmin": 59.75, "Tmax": 2000.0,
+ "a1": [1, 0.354935e5, -0.354935e5],
+ "exp1": [0, 0.178963e1, 0],
+ "a2": [], "exp2": [], "a3": [], "exp3": []}
+ _surf = {"sigma": [0.03046], "exp": [1.28]}
+ _rhoG = {
+ "eq": 3,
+ "ao": [-0.20466e1, -0.4752e1, -0.13259e2, -0.47652e2],
+ "exp": [0.41, 1, 2.8, 6.5]}
+ _Pv = {
+ "ao": [-0.1567266, -0.5539635e1, 0.7567212, -0.3514322e1],
+ "exp": [0.5, 1, 2.5, 4]}
+
+ @classmethod
+ def _Liquid_Density(cls, T):
+ """Auxiliary equation for the density or saturated liquid
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ rho : float
+ Saturated liquid density [kg/m³]
+ """
+ Tc = 132.6312
+ rhoc = 10.4477*cls.M
+ Ni = [44.3413, -240.073, 285.139, -88.3366]
+ ti = [0.65, 0.85, 0.95, 1.1]
+ Tita = 1-T/Tc
+ suma = 1
+ for n, t in zip(Ni, ti):
+ suma += n*Tita**t
+ suma -= 0.892181*log(T/Tc)
+ rho = suma*rhoc
+ return rho
+
+ @staticmethod
+ def _visco(rho, T, fase=None):
+ """Equation for the Viscosity
+
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ mu : float
+ Viscosity [Pa·s]
+
+ References
+ ----------
+ Lemmon, E.W. and Jacobsen, R.T., Viscosity and Thermal Conductivity
+ Equations for Nitrogen, Oxygen, Argon, and Air, Int. J. Thermophys.,
+ 25:21-69, 2004. doi:10.1023/B:IJOT.0000022327.04529.f3
+ """
+ ek = 103.3
+ sigma = 0.36
+ M = 28.9586
+ rhoc = 10.4477*M
+ tau = 132.6312/T
+ delta = rho/rhoc
+
+ b = [0.431, -0.4623, 0.08406, 0.005341, -0.00331]
+ T_ = log(T/ek)
+ suma = 0
+ for i, bi in enumerate(b):
+ suma += bi*T_**i
+ omega = exp(suma)
+
+ # Eq 2
+ muo = 0.0266958*(M*T)**0.5/(sigma**2*omega)
+
+ n_poly = [10.72, 1.122, 0.002019, -8.876, -0.02916]
+ t_poly = [.2, .05, 2.4, .6, 3.6]
+ d_poly = [1, 4, 9, 1, 8]
+ l_poly = [0, 0, 0, 1, 1]
+ g_poly = [0, 0, 0, 1, 1]
+
+ # Eq 3
+ mur = 0
+ for n, t, d, l, g in zip(n_poly, t_poly, d_poly, l_poly, g_poly):
+ mur += n*tau**t*delta**d*exp(-g*delta**l)
+
+ # Eq 1
+ mu = muo+mur
+ return mu*1e-6
+
+ def _thermo(self, rho, T, fase=None):
+ """Equation for the thermal conductivity
+
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+ fase: dict
+ phase properties
+
+ Returns
+ -------
+ k : float
+ Thermal conductivity [W/mK]
+
+ References
+ ----------
+ Lemmon, E.W. and Jacobsen, R.T., Viscosity and Thermal Conductivity
+ Equations for Nitrogen, Oxygen, Argon, and Air, Int. J. Thermophys.,
+ 25:21-69, 2004. doi:10.1023/B:IJOT.0000022327.04529.f3
+ """
+ ek = 103.3
+ sigma = 0.36
+ M = 28.9586
+ rhoc = 10.4477*M
+ tau = 132.6312/T
+ delta = rho/rhoc
+
+ b = [0.431, -0.4623, 0.08406, 0.005341, -0.00331]
+ T_ = log(T/ek)
+ suma = 0
+ for i, bi in enumerate(b):
+ suma += bi*T_**i
+ omega = exp(suma)
+
+ # Eq 2
+ muo = 0.0266958*(M*T)**0.5/(sigma**2*omega)
+
+ # Eq 5
+ N = [1.308, 1.405, -1.036]
+ t = [-1.1, -0.3]
+ lo = N[0]*muo+N[1]*tau**t[0]+N[2]*tau**t[1]
+
+ n_poly = [8.743, 14.76, -16.62, 3.793, -6.142, -0.3778]
+ t_poly = [0.1, 0, 0.5, 2.7, 0.3, 1.3]
+ d_poly = [1, 2, 3, 7, 7, 11]
+ g_poly = [0, 0, 1, 1, 1, 1]
+ l_poly = [0, 0, 2, 2, 2, 2]
+
+ # Eq 6
+ lr = 0
+ for n, t, d, l, g in zip(n_poly, t_poly, d_poly, l_poly, g_poly):
+ lr += n*tau**t*delta**d*exp(-g*delta**l)
+
+ lc = 0
+ # FIXME: Tiny desviation in the test in paper, 0.06% at critical point
+ if fase:
+ qd = 0.31
+ Gamma = 0.055
+ Xio = 0.11
+ Tref = 265.262
+ k = 1.380658e-23 # J/K
+
+ # Eq 11
+ X = self.Pc*1e-3*rho/rhoc**2*fase.drhodP_T
+
+ ref = Air()
+ st = ref._Helmholtz(rho, Tref)
+ drho = 1e3/self.R/Tref/(1+2*delta*st["fird"]+delta**2*st["firdd"])
+
+ Xref = self.Pc*1e-3*rho/rhoc**2*drho
+
+ # Eq 10
+ bracket = X-Xref*Tref/T
+ if bracket > 0:
+ Xi = Xio*(bracket/Gamma)**(0.63/1.2415)
+
+ Xq = Xi/qd
+ # Eq 8
+ Omega = 2/pi*((fase.cp-fase.cv)/fase.cp*atan(Xq) +
+ fase.cv/fase.cp*(Xq))
+ # Eq 9
+ Omega0 = 2/pi*(1-exp(-1/(1/Xq+Xq**2/3*rhoc**2/rho**2)))
+
+ # Eq 7
+ lc = rho*fase.cp*k*1.01*T/6/pi/Xi/fase.mu*(Omega-Omega0)*1e15
+ else:
+ lc = 0
+
+ # Eq 4
+ k = lo+lr+lc
+
+ return k*1e-3
+
+
+class HumidAir(object):
+ """
+ Humid air class with complete functionality
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+ rho : float
+ Density [kg/m³]
+ v : float
+ Specific volume [m³/kg]
+ A : float
+ Mass fraction of dry air in humid air [kg/kg]
+ xa : float
+ Mole fraction of dry air in humid air [-]
+ W : float
+ Mass fraction of water in humid air [kg/kg]
+ xw : float
+ Mole fraction of water in humid air [-]
+
+ Notes
+ -----
+ * It needs two incoming properties of T, P, rho.
+ * v as a alternate input parameter to rho
+ * For composition need one of A, xa, W, xw.
+
+ Returns
+ -------
+ The calculated instance has the following properties:
+ * P: Pressure [MPa]
+ * T: Temperature [K]
+ * g: Specific Gibbs free energy [kJ/kg]
+ * a: Specific Helmholtz free energy [kJ/kg]
+ * v: Specific volume [m³/kg]
+ * rho: Density [kg/m³]
+ * h: Specific enthalpy [kJ/kg]
+ * u: Specific internal energy [kJ/kg]
+ * s: Specific entropy [kJ/kg·K]
+ * cp: Specific isobaric heat capacity [kJ/kg·K]
+ * w: Speed of sound [m/s]
+
+ * alfav: Isobaric cubic expansion coefficient [1/K]
+ * betas: Isoentropic temperature-pressure coefficient [-]
+ * xkappa: Isothermal Expansion Coefficient [-]
+ * ks: Adiabatic Compressibility [1/MPa]
+
+ * A: Mass fraction of dry air in humid air [kg/kg]
+ * xa: Mole fraction of dry air in humid air [-]
+ * W: Mass fraction of water in humid air [kg/kg]
+ * xw: Mole fraction of water in humid air [-]
+ * mu: Relative chemical potential [kJ/kg]
+ * muw: Chemical potential of water [kJ/kg]
+ * M: Molar mass of humid air [g/mol]
+ * HR: Humidity ratio [-]
+ * xa: Mole fraction of dry air [-]
+ * xw: Mole fraction of water [-]
+ * xa_sat: Mole fraction of dry air at saturation state [-]
+ * RH: Relative humidity
+ """
+ kwargs = {"T": 0.0,
+ "P": 0.0,
+ "rho": 0.0,
+ "v": 0.0,
+ "A": None,
+ "xa": None,
+ "W": None,
+ "xw": None}
+ status = 0
+ msg = "Undefined"
+
+ def __init__(self, **kwargs):
+ """Constructor, define common constant and initinialice kwargs"""
+ self.kwargs = HumidAir.kwargs.copy()
+ self.__call__(**kwargs)
+
+ def __call__(self, **kwargs):
+ """Make instance callable to can add input parameter one to one"""
+ # Check alernate input parameters
+ if kwargs.get("v", 0):
+ kwargs["rho"] = 1./kwargs["v"]
+ del kwargs["v"]
+ if kwargs.get("W", 0):
+ kwargs["A"] = 1-kwargs["W"]
+ del kwargs["W"]
+ if kwargs.get("xw", 0):
+ kwargs["xa"] = 1-kwargs["xw"]
+ del kwargs["xw"]
+
+ self.kwargs.update(kwargs)
+
+ if self.calculable:
+ self.status = 1
+ self.calculo()
+ self.msg = ""
+
+ @property
+ def calculable(self):
+ """Check if inputs are enough to define state"""
+ self._mode = ""
+ if self.kwargs["T"] and self.kwargs["P"]:
+ self._mode = "TP"
+ elif self.kwargs["T"] and self.kwargs["rho"]:
+ self._mode = "Trho"
+ elif self.kwargs["P"] and self.kwargs["rho"]:
+ self._mode = "Prho"
+
+ # Composition definition
+ self._composition = ""
+ if self.kwargs["A"] is not None:
+ self._composition = "A"
+ elif self.kwargs["xa"] is not None:
+ self._composition = "xa"
+
+ return bool(self._mode) and bool(self._composition)
+
+ def calculo(self):
+ """Calculate procedure"""
+ T = self.kwargs["T"]
+ rho = self.kwargs["rho"]
+ P = self.kwargs["P"]
+
+ # Composition alternate definition
+ if self._composition == "A":
+ A = self.kwargs["A"]
+ elif self._composition == "xa":
+ xa = self.kwargs["xa"]
+ A = xa/(1-(1-xa)*(1-Mw/Ma))
+
+ # Thermodynamic definition
+ if self._mode == "TP":
+ def f(rho):
+ fav = self._fav(T, rho, A)
+ return rho**2*fav["fird"]/1000-P
+ rho = fsolve(f, 1)[0]
+ elif self._mode == "Prho":
+ def f(T):
+ fav = self._fav(T, rho, A)
+ return rho**2*fav["fird"]/1000-P
+ T = fsolve(f, 300)[0]
+
+ # General calculation procedure
+ fav = self._fav(T, rho, A)
+
+ # Common thermodynamic properties
+ prop = self._prop(T, rho, fav)
+ self.T = T
+ self.rho = rho
+ self.v = 1/rho
+ self.P = prop["P"]
+ self.s = prop["s"]
+ self.cp = prop["cp"]
+ self.h = prop["h"]
+ self.g = prop["g"]
+ self.u = self.h-self.P*1000*self.v
+ self.alfav = prop["alfav"]
+ self.betas = prop["betas"]
+ self.xkappa = prop["xkappa"]
+ self.ks = prop["ks"]
+ self.w = prop["w"]
+
+ # Coligative properties
+ coligative = self._coligative(rho, A, fav)
+ self.A = A
+ self.W = 1-A
+ self.mu = coligative["mu"]
+ self.muw = coligative["muw"]
+ self.M = coligative["M"]
+ self.HR = coligative["HR"]
+ self.xa = coligative["xa"]
+ self.xw = coligative["xw"]
+ self.Pv = (1-self.xa)*self.P
+
+ # Saturation related properties
+ A_sat = self._eq(self.T, self.P)
+ self.xa_sat = A_sat*Mw/Ma/(1-A_sat*(1-Mw/Ma))
+ self.RH = (1-self.xa)/(1-self.xa_sat)
+
+ def derivative(self, z, x, y):
+ """Wrapper derivative for custom derived properties
+ where x, y, z can be: P, T, v, rho, u, h, s, g, a"""
+ return deriv_G(self, z, x, y, self)
+
+ def _eq(self, T, P):
+ """Procedure for calculate the composition in saturation state
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ Asat : float
+ Saturation mass fraction of dry air in humid air [kg/kg]
+ """
+ if T <= 273.16:
+ ice = _Ice(T, P)
+ gw = ice["g"]
+ rho = ice["rho"]
+ else:
+ water = IAPWS95(T=T, P=P)
+ gw = water.g
+ rho = water.rho
+
+ def f(a):
+ fa = self._fav(T, rho, a)
+ muw = fa["fir"]+rho*fa["fird"]-a*fa["fira"]
+ return gw-muw
+ Asat = fsolve(f, 0.9)[0]
+ return Asat
+
+ def _prop(self, T, rho, fav):
+ """Thermodynamic properties of humid air
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ rho : float
+ Density [kg/m³]
+ fav : dict
+ dictionary with helmholtz energy and derivatives
+
+ Returns
+ -------
+ prop : dictionary with thermodynamic properties of humid air
+ P: Pressure [MPa]
+ s: Specific entropy [kJ/kgK]
+ cp: Specific isobaric heat capacity [kJ/kgK]
+ h: Specific enthalpy [kJ/kg]
+ g: Specific gibbs energy [kJ/kg]
+ alfav: Thermal expansion coefficient [1/K]
+ betas: Isentropic T-P coefficient [K/MPa]
+ xkappa: Isothermal compressibility [1/MPa]
+ ks: Isentropic compressibility [1/MPa]
+ w: Speed of sound [m/s]
+
+ References
+ ----------
+ IAPWS, Guideline on an Equation of State for Humid Air in Contact with
+ Seawater and Ice, Consistent with the IAPWS Formulation 2008 for the
+ Thermodynamic Properties of Seawater, Table 5,
+ http://www.iapws.org/relguide/SeaAir.html
+ """
+ prop = {}
+ prop["P"] = rho**2*fav["fird"]/1000 # Eq T1
+ prop["s"] = -fav["firt"] # Eq T2
+ prop["cp"] = -T*fav["firtt"]+T*rho*fav["firdt"]**2/( # Eq T3
+ 2*fav["fird"]+rho*fav["firdd"])
+ prop["h"] = fav["fir"]-T*fav["firt"]+rho*fav["fird"] # Eq T4
+ prop["g"] = fav["fir"]+rho*fav["fird"] # Eq T5
+ prop["alfav"] = fav["firdt"]/(2*fav["fird"]+rho*fav["firdd"]) # Eq T6
+ prop["betas"] = 1000*fav["firdt"]/rho/( # Eq T7
+ rho*fav["firdt"]**2-fav["firtt"]*(2*fav["fird"]+rho*fav["firdd"]))
+ prop["xkappa"] = 1e3/(rho**2*(2*fav["fird"]+rho*fav["firdd"])) # Eq T8
+ prop["ks"] = 1000*fav["firtt"]/rho**2/( # Eq T9
+ fav["firtt"]*(2*fav["fird"]+rho*fav["firdd"])-rho*fav["firdt"]**2)
+ prop["w"] = (rho**2*1000*(fav["firtt"]*fav["firdd"]-fav["firdt"]**2) /
+ fav["firtt"]+2*rho*fav["fird"]*1000)**0.5 # Eq T10
+ return prop
+
+ def _coligative(self, rho, A, fav):
+ """Miscelaneous properties of humid air
+
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ A : float
+ Mass fraction of dry air in humid air [kg/kg]
+ fav : dict
+ dictionary with helmholtz energy and derivatives
+
+ Returns
+ -------
+ prop : dictionary with calculated properties
+ mu: Relative chemical potential [kJ/kg]
+ muw: Chemical potential of water [kJ/kg]
+ M: Molar mass of humid air [g/mol]
+ HR: Humidity ratio [-]
+ xa: Mole fraction of dry air [-]
+ xw: Mole fraction of water [-]
+
+ References
+ ----------
+ IAPWS, Guideline on an Equation of State for Humid Air in Contact with
+ Seawater and Ice, Consistent with the IAPWS Formulation 2008 for the
+ Thermodynamic Properties of Seawater, Table 12,
+ http://www.iapws.org/relguide/SeaAir.html
+ """
+ prop = {}
+ prop["mu"] = fav["fira"]
+ prop["muw"] = fav["fir"]+rho*fav["fird"]-A*fav["fira"]
+ prop["M"] = 1/((1-A)/Mw+A/Ma)
+ prop["HR"] = 1/A-1
+ prop["xa"] = A*Mw/Ma/(1-A*(1-Mw/Ma))
+ prop["xw"] = 1-prop["xa"]
+ return prop
+
+ def _fav(self, T, rho, A):
+ """Specific Helmholtz energy of humid air and derivatives
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ rho : float
+ Density [kg/m³]
+ A : float
+ Mass fraction of dry air in humid air [kg/kg]
+
+ Returns
+ -------
+ prop : dictionary with helmholtz energy and derivatives
+ fir [kJ/kg]
+ fira: [∂fav/∂A]T,ρ [kJ/kg]
+ firt: [∂fav/∂T]A,ρ [kJ/kgK]
+ fird: [∂fav/∂ρ]A,T [kJ/m³kg²]
+ firaa: [∂²fav/∂A²]T,ρ [kJ/kg]
+ firat: [∂²fav/∂A∂T]ρ [kJ/kgK]
+ firad: [∂²fav/∂A∂ρ]T [kJ/m³kg²]
+ firtt: [∂²fav/∂T²]A,ρ [kJ/kgK²]
+ firdt: [∂²fav/∂T∂ρ]A [kJ/m³kg²K]
+ firdd: [∂²fav/∂ρ²]A,T [kJ/m⁶kg³]
+
+ References
+ ----------
+ IAPWS, Guideline on an Equation of State for Humid Air in Contact with
+ Seawater and Ice, Consistent with the IAPWS Formulation 2008 for the
+ Thermodynamic Properties of Seawater, Table 6,
+ http://www.iapws.org/relguide/SeaAir.html
+ """
+ water = IAPWS95()
+ rhov = (1-A)*rho
+ fv = water._derivDimensional(rhov, T)
+
+ air = Air()
+ rhoa = A*rho
+ fa = air._derivDimensional(rhoa, T)
+
+ fmix = self._fmix(T, rho, A)
+
+ prop = {}
+ # Eq T11
+ prop["fir"] = (1-A)*fv["fir"] + A*fa["fir"] + fmix["fir"]
+ # Eq T12
+ prop["fira"] = -fv["fir"]-rhov*fv["fird"]+fa["fir"] + \
+ rhoa*fa["fird"]+fmix["fira"]
+ # Eq T13
+ prop["firt"] = (1-A)*fv["firt"]+A*fa["firt"]+fmix["firt"]
+ # Eq T14
+ prop["fird"] = (1-A)**2*fv["fird"]+A**2*fa["fird"]+fmix["fird"]
+ # Eq T15
+ prop["firaa"] = rho*(2*fv["fird"]+rhov*fv["firdd"] +
+ 2*fa["fird"]+rhoa*fa["firdd"])+fmix["firaa"]
+ # Eq T16
+ prop["firat"] = -fv["firt"]-rhov*fv["firdt"]+fa["firt"] + \
+ rhoa*fa["firdt"]+fmix["firat"]
+ # Eq T17
+ prop["firad"] = -(1-A)*(2*fv["fird"]+rhov*fv["firdd"]) + \
+ A*(2*fa["fird"]+rhoa*fa["firdd"])+fmix["firad"]
+ # Eq T18
+ prop["firtt"] = (1-A)*fv["firtt"]+A*fa["firtt"]+fmix["firtt"]
+ # Eq T19
+ prop["firdt"] = (1-A)**2*fv["firdt"]+A**2*fa["firdt"]+fmix["firdt"]
+ # Eq T20
+ prop["firdd"] = (1-A)**3*fv["firdd"]+A**3*fa["firdd"]+fmix["firdd"]
+ return prop
+
+ def _fmix(self, T, rho, A):
+ """Specific Helmholtz energy of air-water interaction
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ rho : float
+ Density [kg/m³]
+ A : float
+ Mass fraction of dry air in humid air [kg/kg]
+
+ Returns
+ -------
+ prop : dictionary with helmholtz energy and derivatives
+ fir
+ fira: [∂fmix/∂A]T,ρ
+ firt: [∂fmix/∂T]A,ρ
+ fird: [∂fmix/∂ρ]A,T
+ firaa: [∂²fmix/∂A²]T,ρ
+ firat: [∂²fmix/∂A∂T]ρ
+ firad: [∂²fmix/∂A∂ρ]T
+ firtt: [∂²fmix/∂T²]A,ρ
+ firdt: [∂²fmix/∂T∂ρ]A
+ firdd: [∂²fmix/∂ρ²]A,T
+
+ References
+ ----------
+ IAPWS, Guideline on an Equation of State for Humid Air in Contact with
+ Seawater and Ice, Consistent with the IAPWS Formulation 2008 for the
+ Thermodynamic Properties of Seawater, Table 10,
+ http://www.iapws.org/relguide/SeaAir.html
+ """
+ Ma = Air.M/1000
+ Mw = IAPWS95.M/1000
+ vir = _virial(T)
+ Baw = vir["Baw"]
+ Bawt = vir["Bawt"]
+ Bawtt = vir["Bawtt"]
+ Caaw = vir["Caaw"]
+ Caawt = vir["Caawt"]
+ Caawtt = vir["Caawtt"]
+ Caww = vir["Caww"]
+ Cawwt = vir["Cawwt"]
+ Cawwtt = vir["Cawwtt"]
+
+ # Eq T45
+ f = 2*A*(1-A)*rho*R*T/Ma/Mw*(Baw+3*rho/4*(A/Ma*Caaw+(1-A)/Mw*Caww))
+ # Eq T46
+ fa = 2*rho*R*T/Ma/Mw*((1-2*A)*Baw+3*rho/4*(
+ A*(2-3*A)/Ma*Caaw+(1-A)*(1-3*A)/Mw*Caww))
+ # Eq T47
+ ft = 2*A*(1-A)*rho*R/Ma/Mw*(
+ Baw+T*Bawt+3*rho/4*(A/Ma*(Caaw+T*Caawt)+(1-A)/Mw*(Caww+T*Cawwt)))
+ # Eq T48
+ fd = A*(1-A)*R*T/Ma/Mw*(2*Baw+3*rho*(A/Ma*Caaw+(1-A)/Mw*Caww))
+ # Eq T49
+ faa = rho*R*T/Ma/Mw*(-4*Baw+3*rho*((1-3*A)/Ma*Caaw-(2-3*A)/Mw*Caww))
+ # Eq T50
+ fat = 2*rho*R/Ma/Mw*(1-2*A)*(Baw+T*Bawt)+3*rho**2*R/2/Ma/Mw*(
+ A*(2-3*A)/Ma*(Caaw+T*Caawt)+(1-A)*(1-3*A)/Mw*(Caww+T*Cawwt))
+ # Eq T51
+ fad = 2*R*T/Ma/Mw*((1-2*A)*Baw+3/2*rho*(
+ A*(2-3*A)/Ma*Caaw+(1-A)*(1-3*A)/Mw*Caww))
+ # Eq T52
+ ftt = 2*A*(1-A)*rho*R/Ma/Mw*(2*Bawt+T*Bawtt+3*rho/4*(
+ A/Ma*(2*Caawt+T*Caawtt)+(1-A)/Mw*(2*Cawwt+T*Cawwtt)))
+ # Eq T53
+ ftd = 2*A*(1-A)*R/Ma/Mw*(Baw+T*Bawt+3*rho/2*(
+ A/Ma*(Caaw+T*Caawt)+(1-A)/Mw*(Caww+T*Cawwt)))
+ # Eq T54
+ fdd = 3*A*(1-A)*R*T/Ma/Mw*(A/Ma*Caaw+(1-A)/Mw*Caww)
+
+ prop = {}
+ prop["fir"] = f/1000
+ prop["fira"] = fa/1000
+ prop["firt"] = ft/1000
+ prop["fird"] = fd/1000
+ prop["firaa"] = faa/1000
+ prop["firat"] = fat/1000
+ prop["firad"] = fad/1000
+ prop["firtt"] = ftt/1000
+ prop["firdt"] = ftd/1000
+ prop["firdd"] = fdd/1000
+ return prop
diff --git a/iapws/iapws08.py b/iapws/iapws08.py
index c2dbe2f..0a1820a 100644
--- a/iapws/iapws08.py
+++ b/iapws/iapws08.py
@@ -1,14 +1,19 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
-
-###############################################################################
-# IAPWS for seawater
-###############################################################################
+"""
+IAPWS standard for Seawater IAPWS08
+"""
from __future__ import division
-from math import log
+from math import exp, log
+import warnings
+
+from scipy.optimize import fsolve
from .iapws95 import IAPWS95
+from .iapws97 import IAPWS97, _Region1, _Region2
+from ._iapws import _ThCond, Tc, Pc, rhoc, _Ice
+from ._utils import deriv_G
# Constants
@@ -25,46 +30,119 @@ To = 273.15
class SeaWater(object):
"""
Class to model seawater with standard IAPWS-08
- Incoming properties:
- T - Temperature, K
- P - Pressure, MPa
- S - Salinity, kg/kg
-
- Calculated properties:
- T: Temperature, K
- P: Pressure, MPa
- rho: Density, kg/m³
- v: Specific volume, m³/kg
- h: Specific enthalpy, kJ/kg
- s: Specific entropy, kJ/kg·K
- u: Specific internal energy, kJ/kg
- g: Specific Gibbs free energy, kJ/kg
- a: Specific Helmholtz free energy, kJ/kg
- cp: Specific isobaric heat capacity, kJ/kg·K
-
- gt: Derivative Gibbs energy with temperature, kJ/kg·K
- gp: Derivative Gibbs energy with pressure, m³/kg
- gtt: Derivative Gibbs energy with temperature square, kJ/kg·K²
- gtp: Derivative Gibbs energy with pressure and temperature, m³/kg·K
- gpp: Derivative Gibbs energy with temperature square, m³/kg·MPa
- gs: Derivative Gibbs energy with salinity, kJ/kg
- gsp: Derivative Gibbs energy with salinity and pressure, m³/kg
-
- alfa: Thermal expansion coefficient, 1/K
- betas: Isentropic temperature-pressure coefficient, K/MPa
- kt: Isothermal compressibility, 1/MPa
- ks: Isentropic compressibility, 1/MPa
- w: Sound Speed, m/s
-
- mu: Relative chemical potential, kJ/kg
- muw: Chemical potential of H2O, kJ/kg
- mus: Chemical potential of sea salt, kJ/kg
- osm: Osmotic coefficient, [-]
- haline: Haline contraction coefficient, kg/kg
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+ S : float
+ Salinity [kg/kg]
+
+ fast : Boolean, default False
+ Use the Supplementary release SR7-09 to speed up the calculation
+ IF97 : Boolean, default False
+ Use the Advisory Note No. 5 with industrial formulation
+
+ Returns
+ -------
+ rho : float
+ Density [kg/m³]
+ v : float
+ Specific volume [m³/kg]
+ h : float
+ Specific enthalpy [kJ/kg]
+ s : float
+ Specific entropy [kJ/kg·K]
+ u : float
+ Specific internal energy [kJ/kg]
+ g : float
+ Specific Gibbs free energy [kJ/kg]
+ a : float
+ Specific Helmholtz free energy [kJ/kg]
+ cp : float
+ Specific isobaric heat capacity [kJ/kg·K]
+ cv : float
+ Specific isochoric heat capacity [kJ/kg·K]
+ gt : float
+ Derivative Gibbs energy with temperature [kJ/kg·K]
+ gp : float
+ Derivative Gibbs energy with pressure [m³/kg]
+ gtt : float
+ Derivative Gibbs energy with temperature square [kJ/kg·K²]
+ gtp : float
+ Derivative Gibbs energy with pressure and temperature [m³/kg·K]
+ gpp : float
+ Derivative Gibbs energy with temperature square [m³/kg·MPa]
+ gs : float
+ Derivative Gibbs energy with salinity [kJ/kg]
+ gsp : float
+ Derivative Gibbs energy with salinity and pressure [m³/kg]
+ alfav : float
+ Thermal expansion coefficient [1/K]
+ betas : float
+ Isentropic temperature-pressure coefficient [K/MPa]
+ xkappa : float
+ Isothermal compressibility [1/MPa]
+ ks : float
+ Isentropic compressibility [1/MPa]
+ w : float
+ Sound Speed [m/s]
+
+ m : float
+ Molality of seawater [mol/kg]
+ mu : float
+ Relative chemical potential [kJ/kg]
+ muw : float
+ Chemical potential of H2O [kJ/kg]
+ mus : float
+ Chemical potential of sea salt [kJ/kg]
+ osm : float
+ Osmotic coefficient, [-]
+ haline : float
+ Haline contraction coefficient [kg/kg]
+
+ Raises
+ ------
+ Warning : If input isn't in limit
+ * 261 ≤ T ≤ 353
+ * 0 < P ≤ 100
+ * 0 ≤ S ≤ 0.12
+
+ References
+ ----------
+ IAPWS, Release on the IAPWS Formulation 2008 for the Thermodynamic
+ Properties of Seawater, http://www.iapws.org/relguide/Seawater.html
+
+ IAPWS, Supplementary Release on a Computationally Efficient Thermodynamic
+ Formulation for Liquid Water for Oceanographic Use,
+ http://www.iapws.org/relguide/OceanLiquid.html
+
+ IAPWS, Guideline on the Thermal Conductivity of Seawater,
+ http://www.iapws.org/relguide/Seawater-ThCond.html
+
+ IAPWS, Revised Advisory Note No. 3: Thermodynamic Derivatives from IAPWS
+ Formulations, http://www.iapws.org/relguide/Advise3.pdf
+
+ IAPWS, Advisory Note No. 5: Industrial Calculation of the Thermodynamic
+ Properties of Seawater, http://www.iapws.org/relguide/Advise5.html
+
+ Examples
+ --------
+ >>> salt = iapws.SeaWater(T=300, P=1, S=0.04)
+ >>> salt.rho
+ 1026.7785717245113
+ >>> salt.gs
+ 88.56221805501536
+ >>> salt.haline
+ 0.7311487666026304
"""
kwargs = {"T": 0.0,
"P": 0.0,
- "S": None}
+ "S": None,
+ "fast": False,
+ "IF97": False}
status = 0
msg = "Undefined"
@@ -89,8 +167,13 @@ class SeaWater(object):
P = self.kwargs["P"]
S = self.kwargs["S"]
- m = S/(1-S)/Ms
- pw = self._water(T, P)
+ self.m = S/(1-S)/Ms
+ if self.kwargs["fast"] and T <= 313.15:
+ pw = self._waterSupp(T, P)
+ elif self.kwargs["IF97"]:
+ pw = self._waterIF97(T, P)
+ else:
+ pw = self._water(T, P)
ps = self._saline(T, P, S)
prop = {}
@@ -104,21 +187,41 @@ class SeaWater(object):
self.v = prop["gp"]
self.s = -prop["gt"]
self.cp = -T*prop["gtt"]
+ self.cv = T*(prop["gtp"]**2/prop["gpp"]-prop["gtt"])
self.h = prop["g"]-T*prop["gt"]
self.u = prop["g"]-T*prop["gt"]-P*1000*prop["gp"]
self.a = prop["g"]-P*1000*prop["gp"]
- self.alfa = prop["gtp"]/prop["gp"]
+ self.alfav = prop["gtp"]/prop["gp"]
self.betas = -prop["gtp"]/prop["gtt"]
- self.kt = -prop["gpp"]/prop["gp"]
- self.ks = (prop["gtp"]**2-prop["gt"]*prop["gpp"])/prop["gp"]/prop["gtt"]
+ self.xkappa = -prop["gpp"]/prop["gp"]
+ self.ks = (prop["gtp"]**2-prop["gt"]*prop["gpp"])/prop["gp"] / \
+ prop["gtt"]
self.w = prop["gp"]*(prop["gtt"]*1000/(prop["gtp"]**2 -
prop["gtt"]*1000*prop["gpp"]*1e-6))**0.5
- self.mu = prop["gs"]
- self.muw = prop["g"]-S*prop["gs"]
- self.mus = prop["g"]+(1-S)*prop["gs"]
- self.osm = -(ps["g"]-S*prop["gs"])/m/Rm/T
- self.haline = -prop["gsp"]/prop["gp"]
+ try:
+ kw = _ThCond(1/pw["gp"], T)
+ self.k = _ThCond_SeaWater(T, P, S)+kw
+ except NotImplementedError:
+ self.k = None
+
+ if S:
+ self.mu = prop["gs"]
+ self.muw = prop["g"]-S*prop["gs"]
+ self.mus = prop["g"]+(1-S)*prop["gs"]
+ self.osm = -(ps["g"]-S*prop["gs"])/self.m/Rm/T
+ self.haline = -prop["gsp"]/prop["gp"]
+ else:
+ self.mu = None
+ self.muw = None
+ self.mus = None
+ self.osm = None
+ self.haline = None
+
+ def derivative(self, z, x, y):
+ """Wrapper derivative for custom derived properties
+ where x, y, z can be: P, T, v, u, h, s, g, a"""
+ return deriv_G(self, z, x, y, self)
@classmethod
def _water(cls, T, P):
@@ -136,8 +239,79 @@ class SeaWater(object):
return prop
@classmethod
+ def _waterIF97(cls, T, P):
+ water = IAPWS97(P=P, T=T)
+ betas = water.derivative("T", "P", "s", water)
+ prop = {}
+ prop["g"] = water.h-T*water.s
+ prop["gt"] = -water.s
+ prop["gp"] = 1./water.rho
+ prop["gtt"] = -water.cp/T
+ prop["gtp"] = betas*water.cp/T
+ prop["gpp"] = -1e6/(water.rho*water.w)**2-betas**2*1e3*water.cp/T
+ prop["gs"] = 0
+ prop["gsp"] = 0
+ return prop
+
+ @classmethod
+ def _waterSupp(cls, T, P):
+ """Get properties of pure water using the supplementary release SR7-09,
+ Table4 pag 6"""
+ tau = (T-273.15)/40
+ pi = (P-0.101325)/100
+
+ J = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3,
+ 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7]
+ K = [0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2,
+ 3, 4, 5, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 0, 1]
+ G = [0.101342743139674e3, 0.100015695367145e6, -0.254457654203630e4,
+ 0.284517778446287e3, -0.333146754253611e2, 0.420263108803084e1,
+ -0.546428511471039, 0.590578347909402e1, -0.270983805184062e3,
+ 0.776153611613101e3, -0.196512550881220e3, 0.289796526294175e2,
+ -0.213290083518327e1, -0.123577859330390e5, 0.145503645404680e4,
+ -0.756558385769359e3, 0.273479662323528e3, -0.555604063817218e2,
+ 0.434420671917197e1, 0.736741204151612e3, -0.672507783145070e3,
+ 0.499360390819152e3, -0.239545330654412e3, 0.488012518593872e2,
+ -0.166307106208905e1, -0.148185936433658e3, 0.397968445406972e3,
+ -0.301815380621876e3, 0.152196371733841e3, -0.263748377232802e2,
+ 0.580259125842571e2, -0.194618310617595e3, 0.120520654902025e3,
+ -0.552723052340152e2, 0.648190668077221e1, -0.189843846514172e2,
+ 0.635113936641785e2, -0.222897317140459e2, 0.817060541818112e1,
+ 0.305081646487967e1, -0.963108119393062e1]
+
+ g, gt, gp, gtt, gtp, gpp = 0, 0, 0, 0, 0, 0
+ for j, k, gi in zip(J, K, G):
+ g += gi*tau**j*pi**k
+ if j >= 1:
+ gt += gi*j*tau**(j-1)*pi**k
+ if k >= 1:
+ gp += k*gi*tau**j*pi**(k-1)
+ if j >= 2:
+ gtt += j*(j-1)*gi*tau**(j-2)*pi**k
+ if j >= 1 and k >= 1:
+ gtp += j*k*gi*tau**(j-1)*pi**(k-1)
+ if k >= 2:
+ gpp += k*(k-1)*gi*tau**j*pi**(k-2)
+
+ prop = {}
+ prop["g"] = g*1e-3
+ prop["gt"] = gt/40*1e-3
+ prop["gp"] = gp/100*1e-6
+ prop["gtt"] = gtt/40**2*1e-3
+ prop["gtp"] = gtp/40/100*1e-6
+ prop["gpp"] = gpp/100**2*1e-6
+ prop["gs"] = 0
+ prop["gsp"] = 0
+ return prop
+
+ @classmethod
def _saline(cls, T, P, S):
"""Eq 4"""
+
+ # Check input in range of validity
+ if T <= 261 or T > 353 or P <= 0 or P > 100 or S < 0 or S > 0.12:
+ warnings.warn("Incoming out of bound")
+
S_ = 0.03516504*40/35
X = (S/S_)**0.5
tau = (T-273.15)/40
@@ -176,27 +350,30 @@ class SeaWater(object):
-0.792001547211682e1]
g, gt, gp, gtt, gtp, gpp, gs, gsp = 0, 0, 0, 0, 0, 0, 0, 0
- for i, j, k, gi in zip(I, J, K, G):
- if i == 1:
- g += gi*X**2*log(X)*tau**j*pi**k
- gs += gi*(2*log(X)+1)*tau**j*pi**k
- else:
- g += gi*X**i*tau**j*pi**k
- gs += i*gi*X**(i-2)*tau**j*pi**k
- if j >= 1:
+
+ # Calculate only for some salinity
+ if S != 0:
+ for i, j, k, gi in zip(I, J, K, G):
if i == 1:
- gt += gi*X**2*log(X)*j*tau**(j-1)*pi**k
+ g += gi*X**2*log(X)*tau**j*pi**k
+ gs += gi*(2*log(X)+1)*tau**j*pi**k
else:
- gt += gi*X**i*j*tau**(j-1)*pi**k
- if k >= 1:
- gp += k*gi*X**i*tau**j*pi**(k-1)
- gsp += i*k*gi*X**(i-2)*tau**j*pi**(k-1)
- if j >= 2:
- gtt += j*(j-1)*gi*X**i*tau**(j-2)*pi**k
- if j >= 1 and k >= 1:
- gtp += j*k*gi*X**i*tau**(j-1)*pi**(k-1)
- if k >= 2:
- gpp += k*(k-1)*gi*X**i*tau**j*pi**(k-2)
+ g += gi*X**i*tau**j*pi**k
+ gs += i*gi*X**(i-2)*tau**j*pi**k
+ if j >= 1:
+ if i == 1:
+ gt += gi*X**2*log(X)*j*tau**(j-1)*pi**k
+ else:
+ gt += gi*X**i*j*tau**(j-1)*pi**k
+ if k >= 1:
+ gp += k*gi*X**i*tau**j*pi**(k-1)
+ gsp += i*k*gi*X**(i-2)*tau**j*pi**(k-1)
+ if j >= 2:
+ gtt += j*(j-1)*gi*X**i*tau**(j-2)*pi**k
+ if j >= 1 and k >= 1:
+ gtp += j*k*gi*X**i*tau**(j-1)*pi**(k-1)
+ if k >= 2:
+ gpp += k*(k-1)*gi*X**i*tau**j*pi**(k-2)
prop = {}
prop["g"] = g*1e-3
@@ -209,6 +386,315 @@ class SeaWater(object):
prop["gsp"] = gsp/S_/2/100*1e-6
return prop
-if __name__ == "__main__":
- import doctest
- doctest.testmod()
+
+def _Tb(P, S):
+ """Procedure to calculate the boiling temperature of seawater
+
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ S : float
+ Salinity [kg/kg]
+
+ Returns
+ -------
+ Tb : float
+ Boiling temperature [K]
+
+ References
+ ----------
+ IAPWS, Advisory Note No. 5: Industrial Calculation of the Thermodynamic
+ Properties of Seawater, http://www.iapws.org/relguide/Advise5.html, Eq 7
+ """
+ def f(T):
+ pw = _Region1(T, P)
+ gw = pw["h"]-T*pw["s"]
+
+ pv = _Region2(T, P)
+ gv = pv["h"]-T*pv["s"]
+
+ ps = SeaWater._saline(T, P, S)
+ return -ps["g"]+S*ps["gs"]-gw+gv
+
+ Tb = fsolve(f, 300)[0]
+ return Tb
+
+
+def _Tf(P, S):
+ """Procedure to calculate the freezing temperature of seawater
+
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ S : float
+ Salinity [kg/kg]
+
+ Returns
+ -------
+ Tf : float
+ Freezing temperature [K]
+
+ References
+ ----------
+ IAPWS, Advisory Note No. 5: Industrial Calculation of the Thermodynamic
+ Properties of Seawater, http://www.iapws.org/relguide/Advise5.html, Eq 12
+ """
+ def f(T):
+ T = float(T)
+ pw = _Region1(T, P)
+ gw = pw["h"]-T*pw["s"]
+
+ gih = _Ice(T, P)["g"]
+
+ ps = SeaWater._saline(T, P, S)
+ return -ps["g"]+S*ps["gs"]-gw+gih
+
+ Tf = fsolve(f, 300)[0]
+ return Tf
+
+
+def _Triple(S):
+ """Procedure to calculate the triple point pressure and temperature for
+ seawater
+
+ Parameters
+ ----------
+ S : float
+ Salinity [kg/kg]
+
+ Returns
+ -------
+ Tt : float
+ Triple point temperature [K]
+ Pt: float
+ Triple point pressure [MPa]
+
+ References
+ ----------
+ IAPWS, Advisory Note No. 5: Industrial Calculation of the Thermodynamic
+ Properties of Seawater, http://www.iapws.org/relguide/Advise5.html, Eq 7
+ """
+ def f(parr):
+ T, P = parr
+ pw = _Region1(T, P)
+ gw = pw["h"]-T*pw["s"]
+
+ pv = _Region2(T, P)
+ gv = pv["h"]-T*pv["s"]
+
+ gih = _Ice(T, P)["g"]
+ ps = SeaWater._saline(T, P, S)
+
+ return -ps["g"]+S*ps["gs"]-gw+gih, -ps["g"]+S*ps["gs"]-gw+gv
+
+ Tt, Pt = fsolve(f, [273, 6e-4])
+
+ prop = {}
+ prop["Tt"] = Tt
+ prop["Pt"] = Pt
+ return prop
+
+
+def _OsmoticPressure(T, P, S):
+ """Procedure to calculate the osmotic pressure of seawater
+
+ Parameters
+ ----------
+ T : float
+ Tmperature [K]
+ P : float
+ Pressure [MPa]
+ S : float
+ Salinity [kg/kg]
+
+ Returns
+ -------
+ Posm : float
+ Osmotic pressure [MPa]
+
+ References
+ ----------
+ IAPWS, Advisory Note No. 5: Industrial Calculation of the Thermodynamic
+ Properties of Seawater, http://www.iapws.org/relguide/Advise5.html, Eq 15
+ """
+ pw = _Region1(T, P)
+ gw = pw["h"]-T*pw["s"]
+
+ def f(Posm):
+ pw2 = _Region1(T, P+Posm)
+ gw2 = pw2["h"]-T*pw2["s"]
+ ps = SeaWater._saline(T, P+Posm, S)
+ return -ps["g"]+S*ps["gs"]-gw+gw2
+
+ Posm = fsolve(f, 0)[0]
+ return Posm
+
+
+def _ThCond_SeaWater(T, P, S):
+ """Equation for the thermal conductivity of seawater
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+ S : float
+ Salinity [kg/kg]
+
+ Returns
+ -------
+ k : float
+ Thermal conductivity excess relative to that of the pure water [W/mK]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 273.15 ≤ T ≤ 523.15
+ * 0 ≤ P ≤ 140
+ * 0 ≤ S ≤ 0.17
+
+ Examples
+ --------
+ >>> _ThCond_Seawater(293.15, 0.1, 0.035)
+ -0.00418604
+
+ References
+ ----------
+ IAPWS, Guideline on the Thermal Conductivity of Seawater,
+ http://www.iapws.org/relguide/Seawater-ThCond.html
+ """
+ # Check input parameters
+ if T < 273.15 or T > 523.15 or P < 0 or P > 140 or S < 0 or S > 0.17:
+ raise NotImplementedError("Incoming out of bound")
+
+ # Eq 4
+ a1 = -7.180891e-5+1.831971e-7*P
+ a2 = 1.048077e-3-4.494722e-6*P
+
+ # Eq 5
+ b1 = 1.463375e-1+9.208586e-4*P
+ b2 = -3.086908e-3+1.798489e-5*P
+
+ a = a1*exp(a2*(T-273.15)) # Eq 2
+ b = b1*exp(b2*(T-273.15)) # Eq 3
+
+ # Eq 1
+ DL = a*(1000*S)**(1+b)
+ return DL
+
+
+def _solNa2SO4(T, mH2SO4, mNaCl):
+ """Equation for the solubility of sodium sulfate in aqueous mixtures of
+ sodium chloride and sulfuric acid
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ mH2SO4 : float
+ Molality of sufuric acid [mol/kg(water)]
+ mNaCl : float
+ Molality of sodium chloride [mol/kg(water)]
+
+ Returns
+ -------
+ S : float
+ Molal solutility of sodium sulfate [mol/kg(water)]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 523.15 ≤ T ≤ 623.15
+ * 0 ≤ mH2SO4 ≤ 0.75
+ * 0 ≤ mNaCl ≤ 2.25
+
+ Examples
+ --------
+ >>> _solNa2SO4(523.15, 0.25, 0.75)
+ 2.68
+
+ References
+ ----------
+ IAPWS, Solubility of Sodium Sulfate in Aqueous Mixtures of Sodium Chloride
+ and Sulfuric Acid from Water to Concentrated Solutions,
+ http://www.iapws.org/relguide/na2so4.pdf
+ """
+ # Check input parameters
+ if T < 523.15 or T > 623.15 or mH2SO4 < 0 or mH2SO4 > 0.75 or \
+ mNaCl < 0 or mNaCl > 2.25:
+ raise NotImplementedError("Incoming out of bound")
+
+ A00 = -0.8085987*T+81.4613752+0.10537803*T*log(T)
+ A10 = 3.4636364*T-281.63322-0.46779874*T*log(T)
+ A20 = -6.0029634*T+480.60108+0.81382854*T*log(T)
+ A30 = 4.4540258*T-359.36872-0.60306734*T*log(T)
+ A01 = 0.4909061*T-46.556271-0.064612393*T*log(T)
+ A02 = -0.002781314*T+1.722695+0.0000013319698*T*log(T)
+ A03 = -0.014074108*T+0.99020227+0.0019397832*T*log(T)
+ A11 = -0.87146573*T+71.808756+0.11749585*T*log(T)
+
+ S = A00 + A10*mH2SO4 + A20*mH2SO4**2 + A30*mH2SO4**3 + A01*mNaCl + \
+ A02*mNaCl**2 + A03*mNaCl**3 + A11*mH2SO4*mNaCl
+
+ return S
+
+
+def _critNaCl(x):
+ """Equation for the critical locus of aqueous solutions of sodium chloride
+
+ Parameters
+ ----------
+ x : float
+ Mole fraction of NaCl [-]
+
+ Returns
+ -------
+ Tc: critical temperature [K]
+ Pc: critical pressure [MPa]
+ rhoc: critical density [kg/m³]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 0 ≤ x ≤ 0.12
+
+ Examples
+ --------
+ >>> _critNaCl(0.1)
+ 975.571016
+
+ References
+ ----------
+ IAPWS, Revised Guideline on the Critical Locus of Aqueous Solutions of
+ Sodium Chloride, http://www.iapws.org/relguide/critnacl.html
+ """
+ # Check input parameters
+ if x < 0 or x > 0.12:
+ raise NotImplementedError("Incoming out of bound")
+
+ T1 = Tc*(1 + 2.3e1*x - 3.3e2*x**1.5 - 1.8e3*x**2)
+ T2 = Tc*(1 + 1.757e1*x - 3.026e2*x**1.5 + 2.838e3*x**2 - 1.349e4*x**2.5 +
+ 3.278e4*x**3 - 3.674e4*x**3.5 + 1.437e4*x**4)
+ f1 = (abs(10000*x-10-1)-abs(10000*x-10+1))/4+0.5
+ f2 = (abs(10000*x-10+1)-abs(10000*x-10-1))/4+0.5
+
+ # Eq 1
+ tc = f1*T1+f2*T2
+
+ # Eq 7
+ rc = rhoc*(1 + 1.7607e2*x - 2.9693e3*x**1.5 + 2.4886e4*x**2 -
+ 1.1377e5*x**2.5 + 2.8847e5*x**3 - 3.8195e5*x**3.5 +
+ 2.0633e5*x**4)
+
+ # Eq 8
+ DT = tc-Tc
+ pc = Pc*(1+9.1443e-3*DT+5.1636e-5*DT**2-2.5360e-7*DT**3+3.6494e-10*DT**4)
+
+ prop = {}
+ prop["Tc"] = tc
+ prop["rhoc"] = rc
+ prop["Pc"] = pc
+ return prop
diff --git a/iapws/iapws95.py b/iapws/iapws95.py
index 0770345..a8e76af 100644
--- a/iapws/iapws95.py
+++ b/iapws/iapws95.py
@@ -1,118 +1,148 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
+"""
+Implemented multiparameter equation of state as a Helmholtz free energy
+ * IAPWS-95 implementation
+ * Heavy water formulation 2005
+"""
-###############################################################################
-# Implemented multiparameter equation of state
-# o IAPWS-95 implementation
-# o Heavy water formulation 2005
-###############################################################################
+from __future__ import division
+from itertools import product
+import warnings
-from scipy import exp, log
+from scipy import exp, log, ndarray
from scipy.optimize import fsolve
-from ._iapws import _fase, getphase
+from .iapws97 import _TSat_P, IAPWS97
+from ._iapws import M, Tc, Pc, rhoc, Tc_D2O, Pc_D2O, rhoc_D2O
from ._iapws import _Viscosity, _ThCond, _Dielectric, _Refractive, _Tension
-from .iapws97 import _TSat_P
+from ._iapws import _D2O_Viscosity, _D2O_ThCond, _D2O_Tension
+from ._utils import _fase, getphase, deriv_H
class MEoS(_fase):
"""
- General implementation of multiparameter equation of state
- From this derived all child class specified per individual compounds
-
- Incoming properties:
- T - Temperature, K
- P - Pressure, MPa
- rho - Density, kg/m3
- v - Specific volume, m3/kg
- h - Specific enthalpy, kJ/kg
- s - Specific entropy, kJ/kg·K
- u - Specific internal energy, kJ/kg·K
- x - Quality
- l - Opcional parameter to light wavelength for Refractive index
-
- It needs two incoming properties
-
- Calculated properties:
- P - Pressure, MPa
- Pr - Reduce pressure
- T - Temperature, K
- Tr - Reduced temperature
- x - Quality
- v - Specific volume, m³/kg
- rho - Density, kg/m³
- h - Specific enthalpy, kJ/kg
- s - Specific entropy, kJ/kg·K
- u - Specific internal energy, kJ/kg
- g - Specific Gibbs free energy, kJ/kg
- a - Specific Helmholtz free energy, kJ/kg
- cp - Specific isobaric heat capacity, kJ/kg·K
- cv - Specific isochoric heat capacity, kJ/kg·K
- cp_cv - Heat capacity ratio
- w - Speed of sound, m/s
- Z - Compression factor
- fi - Fugacity coefficient
- f - Fugacity, MPa
- gamma - Isoentropic exponent
- Hvap - Vaporization heat, kJ/kg
- alfav - Thermal expansion coefficient (Volume expansivity), 1/K
- kappa - Isothermal compressibility, 1/MPa
- alfap - Relative pressure coefficient, 1/K
- betap - Isothermal stress coefficient, kg/m³
- betas - Isoentropic temperature-pressure coefficient
- joule - Joule-Thomson coefficient, K/MPa
- Gruneisen - Gruneisen parameter
- virialB - Second virial coefficient, m³/kg
- virialC - Third virial coefficient, m⁶/kg²
- dpdT_rho - Derivatives, dp/dT at constant rho, MPa/K
- dpdrho_T - Derivatives, dp/drho at constant T, MPa·m³/kg
- drhodT_P - Derivatives, drho/dT at constant P, kg/m³·K
- drhodP_T - Derivatives, drho/dP at constant T, kg/m³·MPa
- dhdT_rho - Derivatives, dh/dT at constant rho, kJ/kg·K
- dhdP_T - Isothermal throttling coefficient, kJ/kg·MPa
- dhdT_P - Derivatives, dh/dT at constant P, kJ/kg·K
- dhdrho_T - Derivatives, dh/drho at constant T, kJ·m³/kg²
- dhdrho_P - Derivatives, dh/drho at constant P, kJ·m³/kg²
- dhdP_rho - Derivatives, dh/dP at constant rho, kJ/kg·MPa
- kt - Isothermal Expansion Coefficient
- ks - Adiabatic Compressibility, 1/MPa
- Ks - Adiabatic bulk modulus, MPa
- Kt - Isothermal bulk modulus, MPa
-
- Z_rho - (Z-1) over the density, m³/kg
- IntP - Internal pressure
- invT - Negative reciprocal temperature
- hInput - Specific heat input, kJ/kg
- mu - Dynamic viscosity, Pa·s
- nu - Kinematic viscosity, m²/s
- k - Thermal conductivity, W/m·K
- sigma - Surface tension, N/m
- alfa - Thermal diffusivity, m²/s
- Pramdt - Prandtl number
- epsilon - Dielectric constant
- n - Refractive index
-
- v0 - Ideal gas Specific volume, m³/kg
- rho0 - Ideal gas Density, kg/m³
- h0 - Ideal gas Specific enthalpy, kJ/kg
- u0 - Ideal gas Specific internal energy, kJ/kg
- s0 - Ideal gas Specific entropy, kJ/kg·K
- a0 - Ideal gas Specific Helmholtz free energy, kJ/kg
- g0 - Ideal gas Specific Gibbs free energy, kJ/kg
- cp0 - Ideal gas Specific isobaric heat capacity, kJ/kg·K
- cv0 - Ideal gas Specific isochoric heat capacity, kJ/kg·K
- cp0_cv - Ideal gas Heat capacity ratio
- gamma0 - Ideal gas Isoentropic exponent
-
+ General implementation of multiparameter equation of state. From this
+ derived all child class specified per individual compounds
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+ rho : float
+ Density [kg/m³]
+ v : float
+ Specific volume [m³/kg]
+ h : float
+ Specific enthalpy [kJ/kg]
+ s : float
+ Specific entropy [kJ/kgK]
+ u : float
+ Specific internal energy [kJ/kg]
+ x : float
+ Vapor quality [-]
+
+ l : float, optional
+ Wavelength of light, for refractive index [nm]
+ rho0 : float, optional
+ Initial value of density, to improve iteration [kg/m³]
+ T0 : float, optional
+ Initial value of temperature, to improve iteration [K]
+ x0 : Initial value of vapor quality, necessary in bad input pair definition
+ where there are two valid solution (T-h, T-s)
+
+ Notes
+ -----
+ * It needs two incoming properties of T, P, rho, h, s, u.
+ * v as a alternate input parameter to rho
+ * T-x, P-x, preferred input pair to specified a point in two phases region
+
+ Returns
+ -------
+ The calculated instance has the following properties:
+ * P: Pressure [MPa]
+ * T: Temperature [K]
+ * x: Vapor quality [-]
+ * g: Specific Gibbs free energy [kJ/kg]
+ * a: Specific Helmholtz free energy [kJ/kg]
+ * v: Specific volume [m³/kg]
+ * r: Density [kg/m³]
+ * h: Specific enthalpy [kJ/kg]
+ * u: Specific internal energy [kJ/kg]
+ * s: Specific entropy [kJ/kg·K]
+ * cp: Specific isobaric heat capacity [kJ/kg·K]
+ * cv: Specific isochoric heat capacity [kJ/kg·K]
+ * cp_cv: Heat capacity ratio, [-]
+ * Z: Compression factor [-]
+ * fi: Fugacity coefficient [-]
+ * f: Fugacity [MPa]
+ * gamma: Isoentropic exponent [-]
+
+ * alfav: Isobaric cubic expansion coefficient [1/K]
+ * kappa: Isothermal compressibility [1/MPa]
+ * kappas: Adiabatic compresibility [1/MPa]
+ * alfap: Relative pressure coefficient [1/K]
+ * betap: Isothermal stress coefficient [kg/m³]
+ * joule: Joule-Thomson coefficient [K/MPa]
+
+ * betas: Isoentropic temperature-pressure coefficient [-]
+ * Gruneisen: Gruneisen parameter [-]
+ * virialB: Second virial coefficient [m³/kg]
+ * virialC: Third virial coefficient [m⁶/kg²]
+ * dpdT_rho: Derivatives, dp/dT at constant rho [MPa/K]
+ * dpdrho_T: Derivatives, dp/drho at constant T [MPa·m³/kg]
+ * drhodT_P: Derivatives, drho/dT at constant P [kg/m³·K]
+ * drhodP_T: Derivatives, drho/dP at constant T [kg/m³·MPa]
+ * dhdT_rho: Derivatives, dh/dT at constant rho [kJ/kg·K]
+ * dhdP_T: Isothermal throttling coefficient [kJ/kg·MPa]
+ * dhdT_P: Derivatives, dh/dT at constant P [kJ/kg·K]
+ * dhdrho_T: Derivatives, dh/drho at constant T [kJ·m³/kg²]
+ * dhdrho_P: Derivatives, dh/drho at constant P [kJ·m³/kg²]
+ * dhdP_rho: Derivatives, dh/dP at constant rho [kJ/kg·MPa]
+ * kt: Isothermal Expansion Coefficient [-]
+ * ks: Adiabatic Compressibility [1/MPa]
+ * Ks: Adiabatic bulk modulus [MPa]
+ * Kt: Isothermal bulk modulus [MPa]
+
+ * v0: Ideal specific volume [m³/kg]
+ * rho0: Ideal gas density [kg/m³]
+ * u0: Ideal specific internal energy [kJ/kg]
+ * h0: Ideal specific enthalpy [kJ/kg]
+ * s0: Ideal specific entropy [kJ/kg·K]
+ * a0: Ideal specific Helmholtz free energy [kJ/kg]
+ * g0: Ideal specific Gibbs free energy [kJ/kg]
+ * cp0: Ideal specific isobaric heat capacity [kJ/kg·K]
+ * cv0: Ideal specific isochoric heat capacity [kJ/kg·K]
+ * w0: Ideal speed of sound [m/s]
+ * gamma0: Ideal isoentropic exponent [-]
+
+ * w: Speed of sound [m/s]
+ * mu: Dynamic viscosity [Pa·s]
+ * nu: Kinematic viscosity [m²/s]
+ * k: Thermal conductivity [W/m·K]
+ * alfa: Thermal diffusivity [m²/s]
+ * sigma: Surface tension [N/m]
+ * epsilon: Dielectric constant [-]
+ * n: Refractive index [-]
+ * Prandt: Prandtl number [-]
+ * Pr: Reduced Pressure [-]
+ * Tr: Reduced Temperature [-]
+ * Hvap: Vaporization heat [kJ/kg]
+ * Svap: Vaporization entropy [kJ/kg·K]
+
+ * Z_rho: (Z-1) over the density [m³/kg]
+ * IntP: Internal pressure [MPa]
+ * invT: Negative reciprocal temperature [1/K]
+ * hInput: Specific heat input [kJ/kg]
"""
-
CP = None
- _surface = None
- _vapor_Pressure = None
- _liquid_Density = None
- _vapor_Density = None
+ _Pv = None
+ _rhoL = None
+ _rhoG = None
kwargs = {"T": 0.0,
"P": 0.0,
@@ -122,13 +152,16 @@ class MEoS(_fase):
"s": None,
"u": None,
"x": None,
- "l": 0.5893}
+ "l": 0.5893,
+ "rho0": None,
+ "T0": None,
+ "x0": 0.5}
status = 0
msg = "Undefined"
def __init__(self, **kwargs):
"""Constructor, define common constant and initinialice kwargs"""
- self.R = self._constants["R"]/self.M
+ self.R = self._constants["R"]/self._constants.get("M", self.M)
self.Zc = self.Pc/self.rhoc/self.R/self.Tc
self.kwargs = MEoS.kwargs.copy()
self.__call__(**kwargs)
@@ -141,9 +174,25 @@ class MEoS(_fase):
self.kwargs.update(kwargs)
if self.calculable:
- self.status = 1
- self.calculo()
- self.msg = ""
+ try:
+ self.status = 1
+ self.calculo()
+ self.msg = ""
+ except RuntimeError as err:
+ self.status = 0
+ self.msg = err.args[0]
+ raise(err)
+
+ # Add msg for extrapolation state
+ if self.name == "water" and 130 <= self.T < 273.15:
+ self.msg = "Extrapolated state"
+ self.status = 3
+ warnings.warn("Using extrapolated values")
+ elif self.name == "water" and 50 <= self.T < 130:
+ self.msg = "Extrapolated state using Low-Temperature extension"
+ self.status = 3
+ warnings.warn("Using extrapolated values and Low-Temperature"
+ "extension")
@property
def calculable(self):
@@ -179,7 +228,6 @@ class MEoS(_fase):
self._mode = "hu"
elif self.kwargs["s"] is not None and self.kwargs["u"] is not None:
self._mode = "su"
-
elif self.kwargs["T"] and self.kwargs["x"] is not None:
self._mode = "Tx"
elif self.kwargs["P"] and self.kwargs["x"] is not None:
@@ -191,85 +239,200 @@ class MEoS(_fase):
T = self.kwargs["T"]
rho = self.kwargs["rho"]
P = self.kwargs["P"]
- v = self.kwargs["v"]
s = self.kwargs["s"]
h = self.kwargs["h"]
u = self.kwargs["u"]
x = self.kwargs["x"]
- self.R = self._constants["R"]/self.M
+ # Initial values
+ T0 = self.kwargs["T0"]
+ rho0 = self.kwargs["rho0"]
+
+ if T0 or rho0:
+ To = T0
+ rhoo = rho0
+ elif self.name == "air":
+ To = 300
+ rhoo = 1e-3
+ else:
+ try:
+ st0 = IAPWS97(**self.kwargs)
+ except NotImplementedError:
+ To = 300
+ rhoo = 900
+ else:
+ if st0.status:
+ To = st0.T
+ rhoo = st0.rho
+ else:
+ To = 300
+ rhoo = 900
+
+ self.R = self._constants["R"]/self._constants.get("M", self.M)
propiedades = None
- if v and not rho:
- rho = 1./v
if x is None:
# Method with iteration necessary to get x
if self._mode == "TP":
- if T < self.Tc and P < self.Pc and \
- self._Vapor_Pressure(T) < P:
- rhoo = self._Liquid_Density(T)
- elif T < self.Tc and P < self.Pc:
- rhoo = self._Vapor_Density(T)
- else:
- rhoo = self.rhoc*3
+ try:
+ if self.name == "air":
+ raise ValueError
+ st0 = IAPWS97(**self.kwargs)
+ rhoo = st0.rho
+ except NotImplementedError:
+ if rho0:
+ rhoo = rho0
+ elif T < self.Tc and P < self.Pc and \
+ self._Vapor_Pressure(T) < P:
+ rhoo = self._Liquid_Density(T)
+ elif T < self.Tc and P < self.Pc:
+ rhoo = self._Vapor_Density(T)
+ else:
+ rhoo = self.rhoc*3
+ except ValueError:
+ rhoo = 1e-3
rho = fsolve(
- lambda rho: self._Helmholtz(rho, T)["P"]-P*1000, rhoo)
+ lambda rho: self._Helmholtz(rho, T)["P"]-P*1000, rhoo)[0]
elif self._mode == "Th":
- rhol = self._Liquid_Density(T)
- rhov = self._Vapor_Density(T)
- hv = self._Helmholtz(rhov, T)["h"]
- if h > hv:
- rhoo = rhov
+ def f(rho):
+ return self._Helmholtz(rho, T)["h"]-h
+
+ if T >= self.Tc:
+ rhoo = self.rhoc
+ rho = fsolve(f, rhoo)[0]
else:
- rhoo = 1000
- rho = fsolve(lambda rho: self._Helmholtz(rho, T)["h"]-h, rhoo)
+ x0 = self.kwargs["x0"]
+ rhov = self._Vapor_Density(T)
+ rhol = self._Liquid_Density(T)
+ hl = self._Helmholtz(rhol, T)["h"]
+ hv = self._Helmholtz(rhov, T)["h"]
+ if x0 not in (0, 1) and hl <= h <= hv:
+ rhol, rhov, Ps = self._saturation(T)
+ vapor = self._Helmholtz(rhov, T)
+ liquido = self._Helmholtz(rhol, T)
+ hv = vapor["h"]
+ hl = liquido["h"]
+ x = (h-hl)/(hv-hl)
+ rho = 1/(x/rhov+(1-x)/rhol)
+ P = Ps/1000
+ else:
+ if h > hv:
+ rhoo = rhov
+ else:
+ rhoo = rhol
+ rho = fsolve(f, rhoo)[0]
elif self._mode == "Ts":
- rhol = self._Liquid_Density(T)
- rhov = self._Vapor_Density(T)
- sv = self._Helmholtz(rhov, T)["s"]
- if s > sv:
- rhoo = rhov
+ def f(rho):
+ if rho < 0:
+ rho = 1e-20
+ return self._Helmholtz(rho, T)["s"]-s
+
+ if T >= self.Tc:
+ rhoo = self.rhoc
+ rho = fsolve(f, rhoo)[0]
else:
- rhoo = 1000
- rho = fsolve(lambda rho: self._Helmholtz(rho, T)["s"]-s, rhoo)
+ rhov = self._Vapor_Density(T)
+ rhol = self._Liquid_Density(T)
+ sl = self._Helmholtz(rhol, T)["s"]
+ sv = self._Helmholtz(rhov, T)["s"]
+ if sl <= s <= sv:
+ rhol, rhov, Ps = self._saturation(T)
+ vapor = self._Helmholtz(rhov, T)
+ liquido = self._Helmholtz(rhol, T)
+ sv = vapor["s"]
+ sl = liquido["s"]
+ x = (s-sl)/(sv-sl)
+ rho = 1/(x/rhov+(1-x)/rhol)
+ P = Ps/1000
+ else:
+ if s > sv:
+ rhoo = rhov
+ else:
+ rhoo = rhol
+ rho = fsolve(f, rhoo)[0]
elif self._mode == "Tu":
- rhol = self._Liquid_Density(T)
- rhov = self._Vapor_Density(T)
- Ps = self._Vapor_Pressure(T)
- vapor = self._Helmholtz(rhov, T)
- uv = vapor["h"]-Ps*vapor["v"]
- if u > uv:
- rhoo = rhov
- else:
- rhoo = 1000
+ def f(rho):
+ prop = self._Helmholtz(rho, T)
+ return prop["h"]-prop["P"]/rho-u
- def funcion(rho):
- par = self._Helmholtz(rho, T)
- return par["h"]-par["P"]*par["v"]-u
- rho = fsolve(funcion, rhoo)
+ if T >= self.Tc:
+ rhoo = self.rhoc
+ rho = fsolve(f, rhoo)[0]
+ else:
+ rhov = self._Vapor_Density(T)
+ rhol = self._Liquid_Density(T)
+ vapor = self._Helmholtz(rhov, T)
+ liquido = self._Helmholtz(rhol, T)
+ uv = vapor["h"]-vapor["P"]/rhov
+ ul = liquido["h"]-liquido["P"]/rhol
+ if ul <= u <= uv:
+ rhol, rhov, Ps = self._saturation(T)
+ vapor = self._Helmholtz(rhov, T)
+ liquido = self._Helmholtz(rhol, T)
+ uv = vapor["h"]-vapor["P"]/rhov
+ ul = liquido["h"]-liquido["P"]/rhol
+ x = (u-ul)/(uv-ul)
+ rho = 1/(x/rhov-(1-x)/rhol)
+ P = Ps/1000
+ else:
+ if u > uv:
+ rhoo = rhov
+ else:
+ rhoo = rhol
+ rho = fsolve(f, rhoo)[0]
elif self._mode == "Prho":
- T = fsolve(lambda T: self._Helmholtz(rho, T)["P"]-P*1000, 600)
+ T = fsolve(
+ lambda T: self._Helmholtz(rho, T)["P"]-P*1000, To)[0]
rhol = self._Liquid_Density(T)
rhov = self._Vapor_Density(T)
- if T[0] == 600 or rhov <= rho <= rhol:
- def funcion(T):
- rhol, rhov, Ps = self._saturation(T)
- return Ps-P*1000
- T = fsolve(funcion, 600)
+ if T == To or rhov <= rho <= rhol:
+
+ def f(parr):
+ T, rhol, rhog = parr
+ deltaL = rhol/self.rhoc
+ deltaG = rhog/self.rhoc
+ liquido = self._Helmholtz(rhol, T)
+ vapor = self._Helmholtz(rhog, T)
+ Jl = rhol*(1+deltaL*liquido["fird"])
+ Jv = rhog*(1+deltaG*vapor["fird"])
+ K = liquido["fir"]-vapor["fir"]
+ Ps = self.R*T*rhol*rhog/(rhol-rhog)*(
+ liquido["fir"]-vapor["fir"]+log(rhol/rhog))
+ return (Jl-Jv,
+ Jl*(1/rhog-1/rhol)-log(rhol/rhog)-K,
+ Ps - P*1000)
+
+ for to in [To, 300, 400, 500, 600]:
+ rhoLo = self._Liquid_Density(to)
+ rhoGo = self._Vapor_Density(to)
+ sol = fsolve(f, [to, rhoLo, rhoGo], full_output=True)
+ T, rhoL, rhoG = sol[0]
+ x = (1./rho-1/rhoL)/(1/rhoG-1/rhoL)
+ if sol[2] == 1 and 0 <= x <= 1 and \
+ sum(abs(sol[1]["fvec"])) < 1e-5:
+ break
+
+ if sum(abs(sol[1]["fvec"])) > 1e-5:
+ raise(RuntimeError(sol[3]))
+
+ liquido = self._Helmholtz(rhoL, T)
+ vapor = self._Helmholtz(rhoG, T)
+ P = self.R*T*rhoL*rhoG/(rhoL-rhoG)*(
+ liquido["fir"]-vapor["fir"]+log(rhoL/rhoG))/1000
elif self._mode == "Ph":
def funcion(parr):
par = self._Helmholtz(parr[0], parr[1])
return par["P"]-P*1000, par["h"]-h
- rho, T = fsolve(funcion, [1000, 300])
+ rho, T = fsolve(funcion, [rhoo, To])
rhol = self._Liquid_Density(T)
rhov = self._Vapor_Density(T)
- if rho == 1000 or rhov <= rho <= rhol:
+ if rho == rhoo or rhov <= rho <= rhol:
def funcion(parr):
rho, T = parr
rhol, rhov, Ps = self._saturation(T)
@@ -278,15 +441,26 @@ class MEoS(_fase):
x = (1./rho-1/rhol)/(1/rhov-1/rhol)
return Ps-P*1000, vapor["h"]*x+liquido["h"]*(1-x)-h
rho, T = fsolve(funcion, [2., 500.])
+ rhol, rhov, Ps = self._saturation(T)
+ vapor = self._Helmholtz(rhov, T)
+ liquido = self._Helmholtz(rhol, T)
+ hv = vapor["h"]
+ hl = liquido["h"]
+ x = (h-hl)/(hv-hl)
elif self._mode == "Ps":
- def funcion(parr):
- par = self._Helmholtz(parr[0], parr[1])
- return par["P"]-P*1000, par["s"]-s
- rho, T = fsolve(funcion, [2., 400])
- rhol = self._Liquid_Density(T)
- rhov = self._Vapor_Density(T)
- if rho == 2. or rhov <= rho <= rhol:
+ try:
+ x0 = st0.x
+ except NameError:
+ x0 = None
+
+ if x0 is None or x0 == 0 or x0 == 1:
+ def funcion(parr):
+ par = self._Helmholtz(parr[0], parr[1])
+ return par["P"]-P*1000, par["s"]-s
+ rho, T = fsolve(funcion, [rhoo, To])
+
+ else:
def funcion(parr):
rho, T = parr
rhol, rhov, Ps = self._saturation(T)
@@ -295,15 +469,23 @@ class MEoS(_fase):
x = (1./rho-1/rhol)/(1/rhov-1/rhol)
return Ps-P*1000, vapor["s"]*x+liquido["s"]*(1-x)-s
rho, T = fsolve(funcion, [2., 500.])
+ rhol, rhov, Ps = self._saturation(T)
+ vapor = self._Helmholtz(rhov, T)
+ liquido = self._Helmholtz(rhol, T)
+ sv = vapor["s"]
+ sl = liquido["s"]
+ x = (s-sl)/(sv-sl)
elif self._mode == "Pu":
def funcion(parr):
- par = self._Helmholtz(parr[0], parr[1])
- return par["h"]-par["P"]*par["v"]-u, par["P"]-P*1000
- rho, T = fsolve(funcion, [1000, 600])
+ rho, T = parr
+ par = self._Helmholtz(rho, T)
+ return par["h"]-par["P"]/rho-u, par["P"]-P*1000
+ sol = fsolve(funcion, [rhoo, To], full_output=True)
+ rho, T = sol[0]
rhol = self._Liquid_Density(T)
rhov = self._Vapor_Density(T)
- if rho == 1000 or rhov <= rho <= rhol:
+ if rho == rhoo or sol[2] != 1:
def funcion(parr):
rho, T = parr
rhol, rhov, Ps = self._saturation(T)
@@ -314,56 +496,136 @@ class MEoS(_fase):
x = (1./rho-1/rhol)/(1/rhov-1/rhol)
return Ps-P*1000, vu*x+lu*(1-x)-u
rho, T = fsolve(funcion, [2., 500.])
+ rhol, rhov, Ps = self._saturation(T)
+ vapor = self._Helmholtz(rhov, T)
+ liquido = self._Helmholtz(rhol, T)
+ uv = vapor["h"]-Ps/rhov
+ ul = liquido["h"]-Ps/rhol
+ x = (u-ul)/(uv-ul)
elif self._mode == "rhoh":
- T = fsolve(lambda T: self._Helmholtz(rho, T)["h"]-h, 600)
+ T = fsolve(lambda T: self._Helmholtz(rho, T)["h"]-h, To)[0]
rhol = self._Liquid_Density(T)
rhov = self._Vapor_Density(T)
- if T[0] == 600 or rhov <= rho <= rhol:
- def funcion(T):
- rhol, rhov, Ps = self._saturation(T)
- vapor = self._Helmholtz(rhov, T)
+ if T == To or rhov <= rho <= rhol:
+ def f(parr):
+ T, rhol, rhog = parr
+ deltaL = rhol/self.rhoc
+ deltaG = rhog/self.rhoc
liquido = self._Helmholtz(rhol, T)
- x = (1./rho-1/rhol)/(1/rhov-1/rhol)
- return vapor["h"]*x+liquido["h"]*(1-x)-h
- T = fsolve(funcion, 500.)
+ vapor = self._Helmholtz(rhog, T)
+ Jl = rhol*(1+deltaL*liquido["fird"])
+ Jv = rhog*(1+deltaG*vapor["fird"])
+ K = liquido["fir"]-vapor["fir"]
+ x = (1./rho-1/rhol)/(1/rhog-1/rhol)
+ return (Jl-Jv,
+ Jl*(1/rhog-1/rhol)-log(rhol/rhog)-K,
+ liquido["h"]*(1-x)+vapor["h"]*x - h)
+
+ for to in [To, 300, 400, 500, 600]:
+ rhoLo = self._Liquid_Density(to)
+ rhoGo = self._Vapor_Density(to)
+ sol = fsolve(f, [to, rhoLo, rhoGo], full_output=True)
+ T, rhoL, rhoG = sol[0]
+ x = (1./rho-1/rhoL)/(1/rhoG-1/rhoL)
+ if sol[2] == 1 and 0 <= x <= 1 and \
+ sum(abs(sol[1]["fvec"])) < 1e-5:
+ break
+
+ if sum(abs(sol[1]["fvec"])) > 1e-5:
+ raise(RuntimeError(sol[3]))
+
+ liquido = self._Helmholtz(rhoL, T)
+ vapor = self._Helmholtz(rhoG, T)
+ P = self.R*T*rhoL*rhoG/(rhoL-rhoG)*(
+ liquido["fir"]-vapor["fir"]+log(rhoL/rhoG))/1000
elif self._mode == "rhos":
- T = fsolve(lambda T: self._Helmholtz(rho, T)["s"]-s, 600)
+ T = fsolve(lambda T: self._Helmholtz(rho, T)["s"]-s, To)[0]
rhol = self._Liquid_Density(T)
rhov = self._Vapor_Density(T)
- if T[0] == 600 or rhov <= rho <= rhol:
- def funcion(T):
- rhol, rhov, Ps = self._saturation(T)
- vapor = self._Helmholtz(rhov, T)
+ if T == To or rhov <= rho <= rhol:
+ def f(parr):
+ T, rhol, rhog = parr
+ deltaL = rhol/self.rhoc
+ deltaG = rhog/self.rhoc
liquido = self._Helmholtz(rhol, T)
- x = (1./rho-1/rhol)/(1/rhov-1/rhol)
- return vapor["s"]*x+liquido["s"]*(1-x)-s
- T = fsolve(funcion, 500.)
+ vapor = self._Helmholtz(rhog, T)
+ Jl = rhol*(1+deltaL*liquido["fird"])
+ Jv = rhog*(1+deltaG*vapor["fird"])
+ K = liquido["fir"]-vapor["fir"]
+ x = (1./rho-1/rhol)/(1/rhog-1/rhol)
+ return (Jl-Jv,
+ Jl*(1/rhog-1/rhol)-log(rhol/rhog)-K,
+ liquido["s"]*(1-x)+vapor["s"]*x - s)
+
+ for to in [To, 300, 400, 500, 600]:
+ rhoLo = self._Liquid_Density(to)
+ rhoGo = self._Vapor_Density(to)
+ sol = fsolve(f, [to, rhoLo, rhoGo], full_output=True)
+ T, rhoL, rhoG = sol[0]
+ x = (1./rho-1/rhoL)/(1/rhoG-1/rhoL)
+ if sol[2] == 1 and 0 <= x <= 1 and \
+ sum(abs(sol[1]["fvec"])) < 1e-5:
+ break
+
+ if sum(abs(sol[1]["fvec"])) > 1e-5:
+ raise(RuntimeError(sol[3]))
+
+ liquido = self._Helmholtz(rhoL, T)
+ vapor = self._Helmholtz(rhoG, T)
+ P = self.R*T*rhoL*rhoG/(rhoL-rhoG)*(
+ liquido["fir"]-vapor["fir"]+log(rhoL/rhoG))/1000
elif self._mode == "rhou":
def funcion(T):
par = self._Helmholtz(rho, T)
- return par["h"]-par["P"]/1000*par["v"]-u
- T = fsolve(funcion, 600)
+ return par["h"]-par["P"]/rho-u
+ T = fsolve(funcion, To)[0]
rhol = self._Liquid_Density(T)
rhov = self._Vapor_Density(T)
- if T[0] == 600 or rhov <= rho <= rhol:
- def funcion(T):
- rhol, rhov, Ps = self._saturation(T)
- vapor = self._Helmholtz(rhov, T)
+ if T == To or rhov <= rho <= rhol:
+ def f(parr):
+ T, rhol, rhog = parr
+ deltaL = rhol/self.rhoc
+ deltaG = rhog/self.rhoc
liquido = self._Helmholtz(rhol, T)
- vu = vapor["h"]-Ps/rhov
+ vapor = self._Helmholtz(rhog, T)
+ Jl = rhol*(1+deltaL*liquido["fird"])
+ Jv = rhog*(1+deltaG*vapor["fird"])
+ K = liquido["fir"]-vapor["fir"]
+ x = (1./rho-1/rhol)/(1/rhog-1/rhol)
+ Ps = self.R*T*rhol*rhog/(rhol-rhog)*(
+ liquido["fir"]-vapor["fir"]+log(rhol/rhog))
+ vu = vapor["h"]-Ps/rhog
lu = liquido["h"]-Ps/rhol
- x = (1./rho-1/rhol)/(1/rhov-1/rhol)
- return vu*x+lu*(1-x)-u
- T = fsolve(funcion, 500.)
+ return (Jl-Jv,
+ Jl*(1/rhog-1/rhol)-log(rhol/rhog)-K,
+ lu*(1-x)+vu*x - u)
+
+ for to in [To, 300, 400, 500, 600]:
+ rhoLo = self._Liquid_Density(to)
+ rhoGo = self._Vapor_Density(to)
+ sol = fsolve(f, [to, rhoLo, rhoGo], full_output=True)
+ T, rhoL, rhoG = sol[0]
+ x = (1./rho-1/rhoL)/(1/rhoG-1/rhoL)
+ if sol[2] == 1 and 0 <= x <= 1 and \
+ sum(abs(sol[1]["fvec"])) < 1e-5:
+ break
+
+ if sum(abs(sol[1]["fvec"])) > 1e-5:
+ raise(RuntimeError(sol[3]))
+
+ liquido = self._Helmholtz(rhoL, T)
+ vapor = self._Helmholtz(rhoG, T)
+ P = self.R*T*rhoL*rhoG/(rhoL-rhoG)*(
+ liquido["fir"]-vapor["fir"]+log(rhoL/rhoG))/1000
elif self._mode == "hs":
def funcion(parr):
par = self._Helmholtz(parr[0], parr[1])
return par["h"]-h, par["s"]-s
- rho, T = fsolve(funcion, [1000, 300])
+ rho, T = fsolve(funcion, [rhoo, To])
rhol = self._Liquid_Density(T)
rhov = self._Vapor_Density(T)
if rhov <= rho <= rhol:
@@ -376,15 +638,24 @@ class MEoS(_fase):
return (vapor["h"]*x+liquido["h"]*(1-x)-h,
vapor["s"]*x+liquido["s"]*(1-x)-s)
rho, T = fsolve(funcion, [0.5, 400.])
+ rhol, rhov, Ps = self._saturation(T)
+ vapor = self._Helmholtz(rhov, T)
+ liquido = self._Helmholtz(rhol, T)
+ sv = vapor["s"]
+ sl = liquido["s"]
+ x = (s-sl)/(sv-sl)
+ P = Ps/1000
elif self._mode == "hu":
def funcion(parr):
- par = self._Helmholtz(parr[0], parr[1])
- return par["h"]-par["P"]/1000*par["v"]-u, par["h"]-h
- rho, T = fsolve(funcion, [1000, 600])
+ rho, T = parr
+ par = self._Helmholtz(rho, T)
+ return par["h"]-par["P"]/rho-u, par["h"]-h
+ sol = fsolve(funcion, [rhoo, To], full_output=True)
+ rho, T = sol[0]
rhol = self._Liquid_Density(T)
rhov = self._Vapor_Density(T)
- if T == 600 or rhov <= rho <= rhol:
+ if sol[2] != 1 or rhov <= rho <= rhol:
def funcion(parr):
rho, T = parr
rhol, rhov, Ps = self._saturation(T)
@@ -395,16 +666,43 @@ class MEoS(_fase):
x = (1./rho-1/rhol)/(1/rhov-1/rhol)
return (vapor["h"]*x+liquido["h"]*(1-x)-h,
vu*x+lu*(1-x)-u)
- rho, T = fsolve(funcion, [2., 500.])
+
+ To = [500, 700, 300, 900]
+ if self.kwargs["T0"]:
+ To.insert(0, self.kwargs["T0"])
+ rhov = self._Vapor_Density(self.Tt)
+ rhol = self._Liquid_Density(self.Tt)
+ ro = [1, 1e-3, rhov, rhol]
+ if self.kwargs["rho0"]:
+ ro.insert(0, self.kwargs["rho0"])
+
+ for r, t in product(ro, To):
+ sol = fsolve(funcion, [r, t], full_output=True)
+ rho, T = sol[0]
+ if sol[2] == 1 and sum(abs(sol[1]["fvec"])) < 1e-5:
+ break
+
+ if sum(abs(sol[1]["fvec"])) > 1e-5:
+ raise(RuntimeError(sol[3]))
+
+ rhol, rhov, Ps = self._saturation(T)
+ vapor = self._Helmholtz(rhov, T)
+ liquido = self._Helmholtz(rhol, T)
+ hv = vapor["h"]
+ hl = liquido["h"]
+ x = (h-hl)/(hv-hl)
+ P = Ps/1000
elif self._mode == "su":
def funcion(parr):
- par = self._Helmholtz(parr[0], parr[1])
- return par["h"]-par["P"]/1000*par["v"]-u, par["s"]-s
- rho, T = fsolve(funcion, [1000, 600])
+ rho, T = parr
+ par = self._Helmholtz(rho, T)
+ return par["h"]-par["P"]/rho-u, par["s"]-s
+ sol = fsolve(funcion, [rhoo, To], full_output=True)
+ rho, T = sol[0]
rhol = self._Liquid_Density(T)
rhov = self._Vapor_Density(T)
- if T == 600 or rhov <= rho <= rhol:
+ if sol[2] != 1 or rhov <= rho <= rhol:
def funcion(parr):
rho, T = parr
rhol, rhov, Ps = self._saturation(T)
@@ -415,42 +713,61 @@ class MEoS(_fase):
x = (1./rho-1/rhol)/(1/rhov-1/rhol)
return (vapor["s"]*x+liquido["s"]*(1-x)-s,
vu*x+lu*(1-x)-u)
- rho, T = fsolve(funcion, [2., 500.])
- rho = float(rho)
- T = float(T)
- propiedades = self._Helmholtz(rho, T)
- if T <= self.Tc:
- rhol = self._Liquid_Density(T)
- rhov = self._Vapor_Density(T)
- if rhol > rho > rhov:
+ To = [500, 700, 300, 900]
+ if self.kwargs["T0"]:
+ To.insert(0, self.kwargs["T0"])
+ rhov = self._Vapor_Density(self.Tt)
+ rhol = self._Liquid_Density(self.Tt)
+ ro = [1, 1e-3, rhov, rhol]
+ if self.kwargs["rho0"]:
+ ro.insert(0, self.kwargs["rho0"])
+
+ for r, t in product(ro, To):
+ sol = fsolve(funcion, [r, t], full_output=True)
+ rho, T = sol[0]
+ if sol[2] == 1 and sum(abs(sol[1]["fvec"])) < 1e-5:
+ break
+
+ if sum(abs(sol[1]["fvec"])) > 1e-5:
+ raise(RuntimeError(sol[3]))
+
rhol, rhov, Ps = self._saturation(T)
- x = (1/rho-1/rhol)/(1/rhov-1/rhol)
- if x < 0:
- x = 0
- elif x > 1:
- x = 1
+ vapor = self._Helmholtz(rhov, T)
+ liquido = self._Helmholtz(rhol, T)
+ sv = vapor["s"]
+ sl = liquido["s"]
+ x = (s-sl)/(sv-sl)
P = Ps/1000
- elif rho <= rhov:
- x = 1
- elif rho >= rhol:
- x = 0
- vapor = self._Helmholtz(rhov, T)
- liquido = self._Helmholtz(rhol, T)
+ elif self._mode == "Trho":
+ if T < self.Tc:
+ rhov = self._Vapor_Density(T)
+ rhol = self._Liquid_Density(T)
+ if rhol > rho > rhov:
+ rhol, rhov, Ps = self._saturation(T)
+ vapor = self._Helmholtz(rhov, T)
+ liquido = self._Helmholtz(rhol, T)
+ x = (1/rho-1/rhol)/(1/rhov-1/rhol)
+ rho = 1/(x/rhov-(1-x)/rhol)
+ P = Ps/1000
- elif T > self.Tc:
+ rho = float(rho)
+ T = float(T)
+ propiedades = self._Helmholtz(rho, T)
+
+ if T > self.Tc:
x = 1
- else:
- raise NotImplementedError("Incoming out of bound")
+ elif x is None:
+ x = 0
if not P:
P = propiedades["P"]/1000.
elif self._mode == "Tx":
# Check input T in saturation range
- if self.Tt > T or self.Tc < T:
- raise ValueError("Wrong input values")
+ if self.Tt > T or self.Tc < T or x > 1 or x < 0:
+ raise NotImplementedError("Incoming out of bound")
rhol, rhov, Ps = self._saturation(T)
vapor = self._Helmholtz(rhov, T)
@@ -462,8 +779,11 @@ class MEoS(_fase):
P = Ps/1000.
elif self._mode == "Px":
- # Iterate over saturation routine to get T
+ # Check input P in saturation range
+ if self.Pc < P or x > 1 or x < 0:
+ raise NotImplementedError("Incoming out of bound")
+ # Iterate over saturation routine to get T
def funcion(T):
rhol = self._Liquid_Density(T)
rhog = self._Vapor_Density(T)
@@ -476,7 +796,12 @@ class MEoS(_fase):
liquido["fir"]-vapor["fir"]+log(deltaL/deltaG))
return Ps/1000-P
- To = _TSat_P(P)
+ if T0:
+ To = T0
+ elif self.name == "water":
+ To = _TSat_P(P)
+ else:
+ To = (self.Tc+self.Tt)/2
T = fsolve(funcion, To)[0]
rhol, rhov, Ps = self._saturation(T)
vapor = self._Helmholtz(rhov, T)
@@ -528,29 +853,26 @@ class MEoS(_fase):
# Calculate special properties useful only for one phase
if self._mode in ("Px", "Tx") or (x < 1 and self.Tt <= T <= self.Tc):
- if self.name == "water":
- self.sigma = _Tension(T)
- else:
- self.sigma = self._Tension(T)
+ self.sigma = self._surface(T)
else:
self.sigma = None
- if 0 < x < 1:
- self.virialB = vapor["B"]/self.rhoc
- self.virialC = vapor["C"]/self.rhoc**2
- else:
- self.virialB = propiedades["B"]/self.rhoc
- self.virialC = propiedades["C"]/self.rhoc**2
+ vir = self._virial(T)
+ self.virialB = vir["B"]/self.rhoc
+ self.virialC = vir["C"]/self.rhoc**2
- if self.Tt <= T <= self.Tc:
+ if 0 < x < 1:
self.Hvap = vapor["h"]-liquido["h"]
+ self.Svap = vapor["s"]-liquido["s"]
else:
self.Hvap = None
+ self.Svap = None
+
self.invT = -1/self.T
# Ideal properties
cp0 = self._prop0(self.rho, self.T)
- self.v0 = cp0.v
+ self.v0 = self.R*self.T/self.P/1000
self.rho0 = 1./self.v0
self.h0 = cp0.h
self.u0 = self.h0-self.P*self.v0
@@ -560,12 +882,13 @@ class MEoS(_fase):
self.cp0 = cp0.cp
self.cv0 = cp0.cv
self.cp0_cv = self.cp0/self.cv0
+ cp0.v = self.v0
self.gamma0 = -self.v0/self.P/1000*self.derivative("P", "v", "s", cp0)
def fill(self, fase, estado):
"""Fill phase properties"""
- fase.v = estado["v"]
- fase.rho = 1/fase.v
+ fase.rho = estado["rho"]
+ fase.v = 1/fase.rho
fase.h = estado["h"]
fase.s = estado["s"]
@@ -574,16 +897,27 @@ class MEoS(_fase):
fase.g = fase.h-self.T*fase.s
fase.Z = self.P*fase.v/self.T/self.R*1e3
- fase.fi = estado["fugacity"]
+ fase.fi = exp(estado["fir"]+estado["delta"]*estado["fird"] -
+ log(1+estado["delta"]*estado["fird"]))
fase.f = fase.fi*self.P
- fase.cp = estado["cp"]
fase.cv = estado["cv"]
- fase.cp_cv = fase.cp/fase.cv
- fase.w = estado["w"]
+
+ fase.rhoM = fase.rho/self.M
+ fase.hM = fase.h*self.M
+ fase.sM = fase.s*self.M
+ fase.uM = fase.u*self.M
+ fase.aM = fase.a*self.M
+ fase.gM = fase.g*self.M
fase.alfap = estado["alfap"]
fase.betap = estado["betap"]
+ fase.cp = self.derivative("h", "T", "P", fase)
+ fase.cp_cv = fase.cp/fase.cv
+ fase.w = (self.derivative("P", "rho", "s", fase)*1000)**0.5
+ fase.cvM = fase.cv*self.M
+ fase.cpM = fase.cp*self.M
+
fase.joule = self.derivative("T", "P", "h", fase)*1e3
fase.Gruneisen = fase.v/fase.cv*self.derivative("P", "T", "v", fase)
fase.alfav = self.derivative("v", "T", "P", fase)/fase.v
@@ -599,12 +933,12 @@ class MEoS(_fase):
fase.dhdT_P = self.derivative("h", "T", "P", fase)
fase.dhdP_T = self.derivative("h", "P", "T", fase)*1e3
fase.dhdP_rho = self.derivative("h", "P", "rho", fase)*1e3
- fase.dhdrho_T = estado["dhdrho"]
- fase.dhdrho_P = estado["dhdrho"]+fase.dhdT_rho/estado["drhodt"]
+ fase.dhdrho_T = self.derivative("h", "rho", "T", fase)
+ fase.dhdrho_P = self.derivative("h", "rho", "P", fase)
fase.dpdT_rho = self.derivative("P", "T", "rho", fase)*1e-3
- fase.dpdrho_T = estado["dpdrho"]*1e-3
- fase.drhodP_T = 1/estado["dpdrho"]*1e3
- fase.drhodT_P = estado["drhodt"]
+ fase.dpdrho_T = self.derivative("P", "rho", "T", fase)*1e-3
+ fase.drhodP_T = self.derivative("rho", "P", "T", fase)*1e3
+ fase.drhodT_P = self.derivative("rho", "T", "P", fase)
fase.Z_rho = (fase.Z-1)/fase.rho
fase.IntP = self.T*self.derivative("P", "T", "rho", fase)*1e-3-self.P
@@ -617,16 +951,23 @@ class MEoS(_fase):
fase.Prandt = fase.mu*fase.cp*1000/fase.k
if self.name == "water":
fase.epsilon = _Dielectric(fase.rho, self.T)
- fase.n = _Refractive(fase.rho, self.T, self.kwargs["l"])
+ try:
+ fase.n = _Refractive(fase.rho, self.T, self.kwargs["l"])
+ except NotImplementedError:
+ fase.n = None
else:
fase.epsilon = None
fase.n = None
- def _saturation(self, T=None):
- """Saturation calculation for two phase search"""
- if not T:
- T = self.T
+ def derivative(self, z, x, y, fase):
+ """Wrapper derivative for custom derived properties
+ where x, y, z can be: P, T, v, rho, u, h, s, g, a"""
+ return deriv_H(self, z, x, y, fase)
+ def _saturation(self, T):
+ """Saturation calculation for two phase search"""
+ if T > self.Tc:
+ T = self.Tc
rhoLo = self._Liquid_Density(T)
rhoGo = self._Vapor_Density(T)
@@ -655,95 +996,76 @@ class MEoS(_fase):
liquido["fir"]-vapor["fir"]+log(deltaL/deltaG))
return rhoL, rhoG, Ps
-# def _saturation2(self, T):
-# """Akasaka (2008) "A Reliable and Useful Method to Determine the
-# Saturation State from Helmholtz Energy Equations of State", Journal of
-# Thermal Science and Technology, 3, 442-451
-# http://dx.doi.org/10.1299/jtst.3.442"""
-#
-# rhoL = self._Liquid_Density(T)
-# rhoG = self._Vapor_Density(T)
-# g = 500.
-# erroro = 1e6
-# rholo = rhoL
-# rhogo = rhoG
-# contador = 0
-# while True:
-# contador += 1
-# deltaL = rhoL/self.rhoc
-# deltaG = rhoG/self.rhoc
-# liquido = self._Helmholtz(rhoL, T)
-# vapor = self._Helmholtz(rhoG, T)
-# Jl = deltaL*(1+deltaL*liquido["fird"])
-# Jv = deltaG*(1+deltaG*vapor["fird"])
-# Kl = deltaL*liquido["fird"]+liquido["fir"]+log(deltaL)
-# Kv = deltaG*vapor["fird"]+vapor["fir"]+log(deltaG)
-# Jdl = 1+2*deltaL*liquido["fird"]+deltaL**2*liquido["firdd"]
-# Jdv = 1+2*deltaG*vapor["fird"]+deltaG**2*vapor["firdd"]
-# Kdl = 2*liquido["fird"]+deltaL*liquido["firdd"]+1/deltaL
-# Kdv = 2*vapor["fird"]+deltaG*vapor["firdd"]+1/deltaG
-# Delta = Jdv*Kdl-Jdl*Kdv
-# error = abs(Kv-Kl)+abs(Jv-Jl)
-# if error < 1e-12 or contador > 100:
-# break
-# elif error > erroro:
-# rhoL = rholo
-# rhoG = rhogo
-# g = g*0.5
-# else:
-# erroro = error
-# rholo = rhoL
-# rhogo = rhoG
-# rhoL = rhoL+g/Delta*((Kv-Kl)*Jdv-(Jv-Jl)*Kdv)
-# rhoG = rhoG+g/Delta*((Kv-Kl)*Jdl-(Jv-Jl)*Kdl)
-# if error > 1e-3:
-# print("Iteration don´t converge, residual error %g" % error)
-#
-# Ps = self.R*T*rhoL*rhoG/(rhoL-rhoG)*(
-# liquido["fir"]-vapor["fir"]+log(deltaL/deltaG))
-# return rhoL, rhoG, Ps
-
def _Helmholtz(self, rho, T):
- """Calculated properties, table 3 pag 10"""
+ """Calculated properties from helmholtz free energy and derivatives
+
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ prop : dictionary with calculated properties
+ fir: [-]
+ fird: [∂fir/∂δ]τ [-]
+ firdd: [∂²fir/∂δ²]τ [-]
+ delta: Reducen density, rho/rhoc [-]
+ P: Pressure [kPa]
+ h: Enthalpy [kJ/kg]
+ s: Entropy [kJ/kgK]
+ cv: Isochoric specific heat [kJ/kgK]
+ alfav: Thermal expansion coefficient [1/K]
+ betap: Isothermal compressibility [1/kPa]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Formulation 1995 for the
+ Thermodynamic Properties of Ordinary Water Substance for General and
+ Scientific Use, September 2016, Table 3
+ http://www.iapws.org/relguide/IAPWS-95.html
+ """
+ if isinstance(rho, ndarray):
+ rho = rho[0]
+ if isinstance(T, ndarray):
+ T = T[0]
+ if rho < 0:
+ rho = 1e-20
+ if T < 50:
+ T = 50
rhoc = self._constants.get("rhoref", self.rhoc)
Tc = self._constants.get("Tref", self.Tc)
delta = rho/rhoc
tau = Tc/T
- fio, fiot, fiott, fiod, fiodd, fiodt = self._phi0(tau, delta)
- fir, firt, firtt, fird, firdd, firdt, firdtt, B, C = self._phir(
- tau, delta)
+ ideal = self._phi0(tau, delta)
+ fio = ideal["fio"]
+ fiot = ideal["fiot"]
+ fiott = ideal["fiott"]
+
+ res = self._phir(tau, delta)
+ fir = res["fir"]
+ firt = res["firt"]
+ firtt = res["firtt"]
+ fird = res["fird"]
+ firdd = res["firdd"]
+ firdt = res["firdt"]
propiedades = {}
propiedades["fir"] = fir
propiedades["fird"] = fird
propiedades["firdd"] = firdd
+ propiedades["delta"] = delta
- propiedades["T"] = T
+ propiedades["rho"] = rho
propiedades["P"] = (1+delta*fird)*self.R*T*rho
- propiedades["v"] = 1./rho
propiedades["h"] = self.R*T*(1+tau*(fiot+firt)+delta*fird)
propiedades["s"] = self.R*(tau*(fiot+firt)-fio-fir)
propiedades["cv"] = -self.R*tau**2*(fiott+firtt)
- propiedades["cp"] = self.R*(
- -tau**2*(fiott+firtt) + (1+delta*fird-delta*tau*firdt)**2/(
- 1+2*delta*fird+delta**2*firdd))
- propiedades["w"] = (
- self.R*1000*T*(1+2*delta*fird+delta**2*firdd - (
- 1+delta*fird-delta*tau*firdt)**2/tau**2/(fiott+firtt)))**0.5
propiedades["alfap"] = (1-delta*tau*firdt/(1+delta*fird))/T
propiedades["betap"] = rho*(
1+(delta*fird+delta**2*firdd)/(1+delta*fird))
- propiedades["fugacity"] = exp(fir+delta*fird-log(1+delta*fird))
- propiedades["B"] = B
- propiedades["C"] = C
- propiedades["dpdrho"] = self.R*T*(1+2*delta*fird+delta**2*firdd)
- propiedades["drhodt"] = -rho*(1+delta*fird-delta*tau*firdt) / \
- (T*(1+2*delta*fird+delta**2*firdd))
- propiedades["dhdrho"] = self.R*T/rho * \
- (tau*delta*(fiodt+firdt)+delta*fird+delta**2*firdd)
-# dbt=-phi11/rho/t
-# propiedades["cps"] = propiedades["cv"] Add cps from Argon pag.27
-
return propiedades
def _prop0(self, rho, T):
@@ -752,10 +1074,12 @@ class MEoS(_fase):
Tc = self._constants.get("Tref", self.Tc)
delta = rho/rhoc
tau = Tc/T
- fio, fiot, fiott, fiod, fiodd, fiodt = self._phi0(tau, delta)
+ ideal = self._phi0(tau, delta)
+ fio = ideal["fio"]
+ fiot = ideal["fiot"]
+ fiott = ideal["fiott"]
propiedades = _fase()
- propiedades.v = self.R*T/self.P/1000
propiedades.h = self.R*T*(1+tau*fiot)
propiedades.s = self.R*(tau*fiot-fio)
propiedades.cv = -self.R*tau**2*fiott
@@ -765,6 +1089,32 @@ class MEoS(_fase):
return propiedades
def _phi0(self, tau, delta):
+ """Ideal gas Helmholtz free energy and derivatives
+
+ Parameters
+ ----------
+ tau : float
+ Inverse reduced temperature, Tc/T [-]
+ delta : float
+ Reduced density, rho/rhoc [-]
+
+ Returns
+ -------
+ prop : dictionary with ideal adimensional helmholtz energy and deriv
+ fio [-]
+ fiot: [∂fio/∂τ]δ [-]
+ fiod: [∂fio/∂δ]τ [-]
+ fiott: [∂²fio/∂τ²]δ [-]
+ fiodt: [∂²fio/∂τ∂δ] [-]
+ fiodd: [∂²fio/∂δ²]τ [-]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Formulation 1995 for the
+ Thermodynamic Properties of Ordinary Water Substance for General and
+ Scientific Use, September 2016, Table 4
+ http://www.iapws.org/relguide/IAPWS-95.html
+ """
Fi0 = self.Fi0
fio = Fi0["ao_log"][0]*log(delta)+Fi0["ao_log"][1]*log(tau)
@@ -787,12 +1137,63 @@ class MEoS(_fase):
fiot += n*t*((1-exp(-t*tau))**-1-1)
fiott -= n*t**2*exp(-t*tau)*(1-exp(-t*tau))**-2
- return fio, fiot, fiott, fiod, fiodd, fiodt
+ # Especial term for heavy water
+ # if "tau*logtau" in Fi0:
+ # fio += Fi0["tau*logtau"]*tau*log(tau)
+ # fiot += Fi0["tau*logtau"]*(log(tau)+1)
+ # fiot += Fi0["tau*logtau"]/tau
+ # if "tau*logdelta" in Fi0 and delta:
+ # fio += Fi0["tau*logdelta"]*tau*log(delta)
+ # fiot += Fi0["tau*logdelta"]*log(delta)
+ # fiod += Fi0["tau*logdelta"]*tau/delta
+ # fiodd -= Fi0["tau*logdelta"]*tau/delta**2
+ # fiodt += Fi0["tau*logdelta"]/delta
+
+ # Extension to especial terms of air
+ if "ao_exp2" in Fi0:
+ for n, g, C in zip(Fi0["ao_exp2"], Fi0["titao2"], Fi0["sum2"]):
+ fio += n*log(C+exp(g*tau))
+ fiot += n*g/(C*exp(-g*tau)+1)
+ fiott += C*n*g**2*exp(-g*tau)/(C*exp(-g*tau)+1)**2
+
+ prop = {}
+ prop["fio"] = fio
+ prop["fiot"] = fiot
+ prop["fiott"] = fiott
+ prop["fiod"] = fiod
+ prop["fiodd"] = fiodd
+ prop["fiodt"] = fiodt
+ return prop
def _phir(self, tau, delta):
- delta_0 = 1e-200
-
- fir = fird = firdd = firt = firtt = firdt = firdtt = B = C = 0
+ """Residual contribution to the free Helmholtz energy
+
+ Parameters
+ ----------
+ tau : float
+ Inverse reduced temperature, Tc/T [-]
+ delta : float
+ Reduced density, rho/rhoc [-]
+
+ Returns
+ -------
+ prop : dictionary with residual adimensional helmholtz energy and deriv
+ fir [-]
+ firt: [∂fir/∂τ]δ,x [-]
+ fird: [∂fir/∂δ]τ,x [-]
+ firtt: [∂²fir/∂τ²]δ,x [-]
+ firdt: [∂²fir/∂τ∂δ]x [-]
+ firdd: [∂²fir/∂δ²]τ,x [-]
+ firx: [∂fir/∂x]τ,δ [-]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Formulation 1995 for the
+ Thermodynamic Properties of Ordinary Water Substance for General and
+ Scientific Use, September 2016, Table 5
+ http://www.iapws.org/relguide/IAPWS-95.html
+ """
+ fir = fird = firdd = firt = firtt = firdt = 0
# Polinomial terms
nr1 = self._constants.get("nr1", [])
@@ -805,9 +1206,6 @@ class MEoS(_fase):
firt += n*t*delta**d*tau**(t-1)
firtt += n*t*(t-1)*delta**d*tau**(t-2)
firdt += n*t*d*delta**(d-1)*tau**(t-1)
- firdtt += n*t*d*(t-1)*delta**(d-1)*tau**(t-2)
- B += n*d*delta_0**(d-1)*tau**t
- C += n*d*(d-1)*delta_0**(d-2)*tau**t
# Exponential terms
nr2 = self._constants.get("nr2", [])
@@ -824,11 +1222,6 @@ class MEoS(_fase):
firtt += n*t*(t-1)*delta**d*tau**(t-2)*exp(-g*delta**c)
firdt += n*t*delta**(d-1)*tau**(t-1)*(d-g*c*delta**c)*exp(
-g*delta**c)
- firdtt += n*t*(t-1)*delta**(d-1)*tau**(t-2)*(d-g*c*delta**c) * \
- exp(-g*delta**c)
- B += n*exp(-g*delta_0**c)*delta_0**(d-1)*tau**t*(d-g*c*delta_0**c)
- C += n*exp(-g*delta_0**c)*(delta_0**(d-2)*tau**t*(
- (d-g*c*delta_0**c)*(d-1-g*c*delta_0**c)-g**2*c**2*delta_0**c))
# Gaussian terms
nr3 = self._constants.get("nr3", [])
@@ -838,339 +1231,488 @@ class MEoS(_fase):
e3 = self._constants.get("epsilon3", [])
b3 = self._constants.get("beta3", [])
g3 = self._constants.get("gamma3", [])
- for i in range(len(nr3)):
- exp1 = self._constants.get("exp1", [2]*len(nr3))
- exp2 = self._constants.get("exp2", [2]*len(nr3))
- fir += nr3[i]*delta**d3[i]*tau**t3[i]*exp(-a3[i]*(
- delta-e3[i])**exp1[i]-b3[i]*(tau-g3[i])**exp2[i])
- fird += nr3[i]*delta**d3[i]*tau**t3[i]*exp(
- -a3[i]*(delta-e3[i])**exp1[i]-b3[i]*(tau-g3[i])**exp2[i])*(
- d3[i]/delta-2*a3[i]*(delta-e3[i]))
- firdd += nr3[i]*tau**t3[i]*exp(
- -a3[i]*(delta-e3[i])**exp1[i]-b3[i]*(tau-g3[i])**exp2[i])*(
- -2*a3[i]*delta**d3[i]+4*a3[i]**2*delta**d3[i]*(
- delta-e3[i])**exp1[i]-4*d3[i]*a3[i]*delta**2*(
- delta-e3[i])+d3[i]*2*delta)
- firt += nr3[i]*delta**d3[i]*tau**t3[i]*exp(-a3[i]*(
- delta-e3[i])**exp1[i]-b3[i]*(tau-g3[i])**exp2[i])*(
- t3[i]/tau-2*b3[i]*(tau-g3[i]))
- firtt += nr3[i]*delta**d3[i]*tau**t3[i]*exp(-a3[i]*(
- delta-e3[i])**exp1[i]-b3[i]*(tau-g3[i])**exp2[i])*(
- (t3[i]/tau-2*b3[i]*(tau-g3[i]))**exp2[i]-t3[i]/tau**2 -
- 2*b3[i])
- firdt += nr3[i]*delta**d3[i]*tau**t3[i]*exp(-a3[i]*(
- delta-e3[i])**exp1[i]-b3[i]*(tau-g3[i])**exp2[i])*(
- t3[i]/tau-2*b3[i]*(tau-g3[i]))*(d3[i]/delta-2*a3[i]*(
- delta-e3[i]))
- firdtt += nr3[i]*delta**d3[i]*tau**t3[i]*exp(-a3[i]*(
- delta-e3[i])**exp1[i]-b3[i]*(tau-g3[i])**exp2[i])*((
- t3[i]/tau-2*b3[i]*(tau-g3[i]))**exp2[i]-t3[i]/tau**2-2 *
- b3[i])*(d3[i]/delta-2*a3[i]*(delta-e3[i]))
- B += nr3[i]*delta_0**d3[i]*tau**t3[i]*exp(-a3[i]*(
- delta_0-e3[i])**exp1[i]-b3[i]*(tau-g3[i])**exp2[i])*(
- d3[i]/delta_0-2*a3[i]*(delta_0-e3[i]))
- C += nr3[i]*tau**t3[i]*exp(-a3[i]*(delta_0-e3[i])**exp1[i]-b3[i]*(
- tau-g3[i])**exp2[i])*(
- -2*a3[i]*delta_0**d3[i]+4*a3[i]**2*delta_0**d3[i]*(
- delta_0-e3[i])**exp1[i]-4*d3[i]*a3[i]*delta_0**2*(
- delta_0-e3[i])+d3[i]*2*delta_0)
+ for n, d, t, a, e, b, g in zip(nr3, d3, t3, a3, e3, b3, g3):
+ fir += n*delta**d*tau**t*exp(-a*(delta-e)**2-b*(tau-g)**2)
+ fird += n*delta**d*tau**t*exp(-a*(delta-e)**2-b*(tau-g)**2)*(
+ d/delta-2*a*(delta-e))
+ firdd += n*tau**t*exp(-a*(delta-e)**2-b*(tau-g)**2)*(
+ -2*a*delta**d+4*a**2*delta**d*(delta-e)**2-4*d*a*delta**2*(
+ delta-e)+d*2*delta)
+ firt += n*delta**d*tau**t*exp(-a*(delta-e)**2-b*(tau-g)**2)*(
+ t/tau-2*b*(tau-g))
+ firtt += n*delta**d*tau**t*exp(-a*(delta-e)**2-b*(tau-g)**2)*(
+ (t/tau-2*b*(tau-g))**2-t/tau**2-2*b)
+ firdt += n*delta**d*tau**t*exp(-a*(delta-e)**2-b*(tau-g)**2)*(
+ t/tau-2*b*(tau-g))*(d/delta-2*a*(delta-e))
# Non analitic terms
nr4 = self._constants.get("nr4", [])
a4 = self._constants.get("a4", [])
- b = self._constants.get("b4", [])
- A = self._constants.get("A", [])
+ b4 = self._constants.get("b4", [])
+ Ai = self._constants.get("A", [])
Bi = self._constants.get("B", [])
Ci = self._constants.get("C", [])
- D = self._constants.get("D", [])
- bt = self._constants.get("beta4", [])
- for i in range(len(nr4)):
- Tita = (1-tau)+A[i]*((delta-1)**2)**(0.5/bt[i])
- F = exp(-Ci[i]*(delta-1)**2-D[i]*(tau-1)**2)
- Fd = -2*Ci[i]*F*(delta-1)
- Fdd = 2*Ci[i]*F*(2*Ci[i]*(delta-1)**2-1)
- Ft = -2*D[i]*F*(tau-1)
- Ftt = 2*D[i]*F*(2*D[i]*(tau-1)**2-1)
- Fdt = 4*Ci[i]*D[i]*F*(delta-1)*(tau-1)
- Fdtt = 4*Ci[i]*D[i]*F*(delta-1)*(2*D[i]*(tau-1)**2-1)
-
- Delta = Tita**2+Bi[i]*((delta-1)**2)**a4[i]
- Deltad = (delta-1)*(A[i]*Tita*2/bt[i]*((delta-1)**2)**(
- 0.5/bt[i]-1)+2*Bi[i]*a4[i]*((delta-1)**2)**(a4[i]-1))
+ Di = self._constants.get("D", [])
+ bt4 = self._constants.get("beta4", [])
+ for n, a, b, A, B, C, D, bt in zip(nr4, a4, b4, Ai, Bi, Ci, Di, bt4):
+ Tita = (1-tau)+A*((delta-1)**2)**(0.5/bt)
+ F = exp(-C*(delta-1)**2-D*(tau-1)**2)
+ Fd = -2*C*F*(delta-1)
+ Fdd = 2*C*F*(2*C*(delta-1)**2-1)
+ Ft = -2*D*F*(tau-1)
+ Ftt = 2*D*F*(2*D*(tau-1)**2-1)
+ Fdt = 4*C*D*F*(delta-1)*(tau-1)
+
+ Delta = Tita**2+B*((delta-1)**2)**a
+ Deltad = (delta-1)*(A*Tita*2/bt*((delta-1)**2)**(0.5/bt-1) +
+ 2*B*a*((delta-1)**2)**(a-1))
if delta == 1:
Deltadd = 0
else:
- Deltadd = Deltad/(delta-1)+(delta-1)**2*(4*Bi[i]*a4[i]*(
- a4[i]-1)*((delta-1)**2)**(a4[i]-2)+2*A[i]**2/bt[i]**2*(((
- delta-1)**2)**(0.5/bt[i]-1))**2+A[i]*Tita*4/bt[i]*(
- 0.5/bt[i]-1)*((delta-1)**2)**(0.5/bt[i]-2))
-
- DeltaBd = b[i]*Delta**(b[i]-1)*Deltad
- DeltaBdd = b[i]*(Delta**(b[i]-1)*Deltadd+(b[i]-1)*Delta**(
- b[i]-2)*Deltad**2)
- DeltaBt = -2*Tita*b[i]*Delta**(b[i]-1)
- DeltaBtt = 2*b[i]*Delta**(b[i]-1)+4*Tita**2*b[i]*(
- b[i]-1)*Delta**(b[i]-2)
- DeltaBdt = -A[i]*b[i]*2/bt[i]*Delta**(b[i]-1)*(delta-1)*((
- delta-1)**2)**(0.5/bt[i]-1)-2*Tita*b[i]*(b[i]-1)*Delta**(
- b[i]-2)*Deltad
- DeltaBdtt = 2*b[i]*(b[i]-1)*Delta**(b[i]-2)*(Deltad*(
- 1+2*Tita**2*(b[i]-2)/Delta)+4*Tita*A[i]*(delta-1)/bt[i]*((
- delta-1)**2)**(0.5/bt[i]-1))
-
- fir += nr4[i]*Delta**b[i]*delta*F
- fird += nr4[i]*(Delta**b[i]*(F+delta*Fd)+DeltaBd*delta*F)
- firdd += nr4[i]*(Delta**b[i]*(2*Fd+delta*Fdd)+2*DeltaBd*(
- F+delta*Fd)+DeltaBdd*delta*F)
- firt += nr4[i]*delta*(DeltaBt*F+Delta**b[i]*Ft)
- firtt += nr4[i]*delta*(DeltaBtt*F+2*DeltaBt*Ft+Delta**b[i]*Ftt)
- firdt += nr4[i]*(Delta**b[i]*(Ft+delta*Fdt)+delta*DeltaBd*Ft +
- DeltaBt*(F+delta*Fd)+DeltaBdt*delta*F)
- firdtt += nr4[i]*((DeltaBtt*F+2*DeltaBt*Ft+Delta**b[i]*Ftt)+delta*(
- DeltaBdtt*F+DeltaBtt*Fd+2*DeltaBdt*Ft+2*DeltaBt*Fdt+DeltaBt *
- Ftt+Delta**b[i]*Fdtt))
-
- Tita_ = (1-tau)+A[i]*((delta_0-1)**2)**(0.5/bt[i])
- Delta_ = Tita_**2+Bi[i]*((delta_0-1)**2)**a4[i]
- Deltad_ = (delta_0-1)*(A[i]*Tita_*2/bt[i]*((delta_0-1)**2)**(
- 0.5/bt[i]-1)+2*Bi[i]*a4[i]*((delta_0-1)**2)**(a4[i]-1))
- Deltadd_ = Deltad_/(delta_0-1)+(delta_0-1)**2*(
- 4*Bi[i]*a4[i]*(a4[i]-1)*((delta_0-1)**2)**(
- a4[i]-2)+2*A[i]**2/bt[i]**2*(((delta_0-1)**2)**(
- 0.5/bt[i]-1))**2+A[i]*Tita_*4/bt[i]*(0.5/bt[i]-1)*((
- delta_0-1)**2)**(0.5/bt[i]-2))
- DeltaBd_ = b[i]*Delta_**(b[i]-1)*Deltad_
- DeltaBdd_ = b[i]*(Delta_**(b[i]-1)*Deltadd_+(b[i]-1)*Delta_**(
- b[i]-2)*Deltad_**2)
- F_ = exp(-Ci[i]*(delta_0-1)**2-D[i]*(tau-1)**2)
- Fd_ = -2*Ci[i]*F_*(delta_0-1)
- Fdd_ = 2*Ci[i]*F_*(2*Ci[i]*(delta_0-1)**2-1)
-
- B += nr4[i]*(Delta_**b[i]*(F_+delta_0*Fd_)+DeltaBd_*delta_0*F_)
- C += nr4[i]*(Delta_**b[i]*(2*Fd_+delta_0*Fdd_)+2*DeltaBd_*(
- F_+delta_0*Fd_)+DeltaBdd_*delta_0*F_)
-
- return fir, firt, firtt, fird, firdd, firdt, firdtt, B, C
+ Deltadd = Deltad/(delta-1)+(delta-1)**2*(
+ 4*B*a*(a-1)*((delta-1)**2)**(a-2) +
+ 2*A**2/bt**2*(((delta-1)**2)**(0.5/bt-1))**2 +
+ A*Tita*4/bt*(0.5/bt-1)*((delta-1)**2)**(0.5/bt-2))
+
+ DeltaBd = b*Delta**(b-1)*Deltad
+ DeltaBdd = b*(Delta**(b-1)*Deltadd+(b-1)*Delta**(b-2)*Deltad**2)
+ DeltaBt = -2*Tita*b*Delta**(b-1)
+ DeltaBtt = 2*b*Delta**(b-1)+4*Tita**2*b*(b-1)*Delta**(b-2)
+ DeltaBdt = -A*b*2/bt*Delta**(b-1)*(delta-1)*((delta-1)**2)**(
+ 0.5/bt-1)-2*Tita*b*(b-1)*Delta**(b-2)*Deltad
+
+ fir += n*Delta**b*delta*F
+ fird += n*(Delta**b*(F+delta*Fd)+DeltaBd*delta*F)
+ firdd += n*(Delta**b*(2*Fd+delta*Fdd) + 2*DeltaBd*(F+delta*Fd) +
+ DeltaBdd*delta*F)
+ firt += n*delta*(DeltaBt*F+Delta**b*Ft)
+ firtt += n*delta*(DeltaBtt*F+2*DeltaBt*Ft+Delta**b*Ftt)
+ firdt += n*(Delta**b*(Ft+delta*Fdt)+delta*DeltaBd*Ft +
+ DeltaBt*(F+delta*Fd)+DeltaBdt*delta*F)
+
+ prop = {}
+ prop["fir"] = fir
+ prop["firt"] = firt
+ prop["firtt"] = firtt
+ prop["fird"] = fird
+ prop["firdd"] = firdd
+ prop["firdt"] = firdt
+ return prop
+
+ def _virial(self, T):
+ """Virial coefficient
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ prop : dictionary with residual adimensional helmholtz energy and deriv
+ B: [∂fir/∂δ]δ->0 [-]
+ C: [∂²fir/∂δ²]δ->0 [-]
+ """
+ Tc = self._constants.get("Tref", self.Tc)
+ tau = Tc/T
+ B = C = 0
+ delta = 1e-200
- def derivative(self, z, x, y, fase):
- """Calculate generic partial derivative: (δz/δx)y
- where x, y, z can be: P, T, v, u, h, s, g, a"""
- dT = {"P": self.P*1000*fase.alfap,
- "T": 1,
- "v": 0,
- "rho": 0,
- "u": fase.cv,
- "h": fase.cv+self.P*1000*fase.v*fase.alfap,
- "s": fase.cv/self.T,
- "g": self.P*1000*fase.v*fase.alfap-fase.s,
- "a": -fase.s}
- dv = {"P": -self.P*1000*fase.betap,
- "T": 0,
- "v": 1,
- "rho": -1,
- "u": self.P*1000*(self.T*fase.alfap-1),
- "h": self.P*1000*(self.T*fase.alfap-fase.v*fase.betap),
- "s": self.P*1000*fase.alfap,
- "g": -self.P*1000*fase.v*fase.betap,
- "a": -self.P*1000}
- return (dv[z]*dT[y]-dT[z]*dv[y])/(dv[x]*dT[y]-dT[x]*dv[y])
-
- def _Vapor_Pressure(self, T):
- eq = self._vapor_Pressure["eq"]
- Tita = 1-T/self.Tc
- if eq in [2, 4, 6]:
- Tita = Tita**0.5
- suma = sum([n*Tita**x for n, x in zip(
- self._vapor_Pressure["ao"], self._vapor_Pressure["exp"])])
- if eq in [1, 2]:
- Pr = suma+1
- elif eq in [3, 4]:
- Pr = exp(suma)
- else:
- Pr = exp(self.Tc/T*suma)
- Pv = Pr*self.Pc
+ # Polinomial terms
+ nr1 = self._constants.get("nr1", [])
+ d1 = self._constants.get("d1", [])
+ t1 = self._constants.get("t1", [])
+ for n, d, t in zip(nr1, d1, t1):
+ B += n*d*delta**(d-1)*tau**t
+ C += n*d*(d-1)*delta**(d-2)*tau**t
+
+ # Exponential terms
+ nr2 = self._constants.get("nr2", [])
+ d2 = self._constants.get("d2", [])
+ g2 = self._constants.get("gamma2", [])
+ t2 = self._constants.get("t2", [])
+ c2 = self._constants.get("c2", [])
+ for n, d, g, t, c in zip(nr2, d2, g2, t2, c2):
+ B += n*exp(-g*delta**c)*delta**(d-1)*tau**t*(d-g*c*delta**c)
+ C += n*exp(-g*delta**c)*(delta**(d-2)*tau**t*(
+ (d-g*c*delta**c)*(d-1-g*c*delta**c)-g**2*c**2*delta**c))
+
+ # Gaussian terms
+ nr3 = self._constants.get("nr3", [])
+ d3 = self._constants.get("d3", [])
+ t3 = self._constants.get("t3", [])
+ a3 = self._constants.get("alfa3", [])
+ e3 = self._constants.get("epsilon3", [])
+ b3 = self._constants.get("beta3", [])
+ g3 = self._constants.get("gamma3", [])
+ for n, d, t, a, e, b, g in zip(nr3, d3, t3, a3, e3, b3, g3):
+ B += n*delta**d*tau**t*exp(-a*(delta-e)**2-b*(tau-g)**2)*(
+ d/delta-2*a*(delta-e))
+ C += n*tau**t*exp(-a*(delta-e)**2-b*(tau-g)**2)*(
+ -2*a*delta**d+4*a**2*delta**d*(
+ delta-e)**2-4*d*a*delta**2*(
+ delta-e)+d*2*delta)
+
+ # Non analitic terms
+ nr4 = self._constants.get("nr4", [])
+ a4 = self._constants.get("a4", [])
+ b4 = self._constants.get("b4", [])
+ Ai = self._constants.get("A", [])
+ Bi = self._constants.get("B", [])
+ Ci = self._constants.get("C", [])
+ Di = self._constants.get("D", [])
+ bt4 = self._constants.get("beta4", [])
+ for n, a, b, A, B, C, D, bt in zip(nr4, a4, b4, Ai, Bi, Ci, Di, bt4):
+ Tita = (1-tau)+A*((delta-1)**2)**(0.5/bt)
+ Delta = Tita**2+B*((delta-1)**2)**a
+ Deltad = (delta-1)*(A*Tita*2/bt*((delta-1)**2)**(
+ 0.5/bt-1)+2*B*a*((delta-1)**2)**(a-1))
+ Deltadd = Deltad/(delta-1) + (delta-1)**2*(
+ 4*B*a*(a-1)*((delta-1)**2)**(a-2) +
+ 2*A**2/bt**2*(((delta-1)**2)**(0.5/bt-1))**2 +
+ A*Tita*4/bt*(0.5/bt-1)*((delta-1)**2)**(0.5/bt-2))
+ DeltaBd = b*Delta**(b-1)*Deltad
+ DeltaBdd = b*(Delta**(b-1)*Deltadd+(b-1)*Delta**(b-2)*Deltad**2)
+ F = exp(-C*(delta-1)**2-D*(tau-1)**2)
+ Fd = -2*C*F*(delta-1)
+ Fdd = 2*C*F*(2*C*(delta-1)**2-1)
+
+ B += n*(Delta**b*(F+delta*Fd)+DeltaBd*delta*F)
+ C += n*(Delta**b*(2*Fd+delta*Fdd)+2*DeltaBd*(F+delta*Fd) +
+ DeltaBdd*delta*F)
+
+ prop = {}
+ prop["B"] = B
+ prop["C"] = C
+ return prop
+
+ def _derivDimensional(self, rho, T):
+ """Calcule the dimensional form or Helmholtz free energy derivatives
+
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ prop : dictionary with residual helmholtz energy and derivatives
+ fir [kJ/kg]
+ firt: [∂fir/∂T]ρ [kJ/kgK]
+ fird: [∂fir/∂ρ]T [kJ/m³kg²]
+ firtt: [∂²fir/∂T²]ρ [kJ/kgK²]
+ firdt: [∂²fir/∂T∂ρ] [kJ/m³kg²K]
+ firdd: [∂²fir/∂ρ²]T [kJ/m⁶kg]
+
+ References
+ ----------
+ IAPWS, Guideline on an Equation of State for Humid Air in Contact with
+ Seawater and Ice, Consistent with the IAPWS Formulation 2008 for the
+ Thermodynamic Properties of Seawater, Table 7,
+ http://www.iapws.org/relguide/SeaAir.html
+ """
+ if not rho:
+ prop = {}
+ prop["fir"] = 0
+ prop["firt"] = 0
+ prop["fird"] = 0
+ prop["firtt"] = 0
+ prop["firdt"] = 0
+ prop["firdd"] = 0
+ return prop
+
+ R = self._constants.get("R")/self._constants.get("M", self.M)
+ rhoc = self._constants.get("rhoref", self.rhoc)
+ Tc = self._constants.get("Tref", self.Tc)
+ delta = rho/rhoc
+ tau = Tc/T
+
+ ideal = self._phi0(tau, delta)
+ fio = ideal["fio"]
+ fiot = ideal["fiot"]
+ fiott = ideal["fiott"]
+ fiod = ideal["fiod"]
+ fiodd = ideal["fiodd"]
+
+ res = self._phir(tau, delta)
+ fir = res["fir"]
+ firt = res["firt"]
+ firtt = res["firtt"]
+ fird = res["fird"]
+ firdd = res["firdd"]
+ firdt = res["firdt"]
+
+ prop = {}
+ prop["fir"] = R*T*(fio+fir)
+ prop["firt"] = R*(fio+fir-(fiot+firt)*tau)
+ prop["fird"] = R*T/rhoc*(fiod+fird)
+ prop["firtt"] = R*tau**2/T*(fiott+firtt)
+ prop["firdt"] = R/rhoc*(fiod+fird-firdt*tau)
+ prop["firdd"] = R*T/rhoc**2*(fiodd+firdd)
+ return prop
+
+ def _surface(self, T):
+ """Generic equation for the surface tension
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ sigma : float
+ Surface tension [N/m]
+
+ Notes
+ -----
+ Need a _surf dict in the derived class with the parameters keys:
+ sigma: coefficient
+ exp: exponent
+ """
+ tau = 1-T/self.Tc
+ sigma = 0
+ for n, t in zip(self._surf["sigma"], self._surf["exp"]):
+ sigma += n*tau**t
+ return sigma
+
+ @classmethod
+ def _Vapor_Pressure(cls, T):
+ """Auxiliary equation for the vapour pressure
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ Pv : float
+ Vapour pressure [Pa]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Saturation Properties of
+ Ordinary Water Substance September 1992,
+ http://www.iapws.org/relguide/Supp-sat.html, Eq.1
+ """
+ Tita = 1-T/cls.Tc
+ suma = 0
+ for n, x in zip(cls._Pv["ao"], cls._Pv["exp"]):
+ suma += n*Tita**x
+ Pr = exp(cls.Tc/T*suma)
+ Pv = Pr*cls.Pc
return Pv
- def _Liquid_Density(self, T=None):
- if not T:
- T = self.T
- eq = self._liquid_Density["eq"]
- Tita = 1-T/self.Tc
- if eq in [2, 4, 6]:
+ @classmethod
+ def _Liquid_Density(cls, T):
+ """Auxiliary equation for the density of saturated liquid
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ rho : float
+ Saturated liquid density [kg/m³]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Saturation Properties of
+ Ordinary Water Substance September 1992,
+ http://www.iapws.org/relguide/Supp-sat.html, Eq.2
+ """
+ eq = cls._rhoL["eq"]
+ Tita = 1-T/cls.Tc
+ if eq == 2:
Tita = Tita**(1./3)
- suma = sum([n*Tita**x for n, x in zip(
- self._liquid_Density["ao"], self._liquid_Density["exp"])])
- if eq in [1, 2]:
- Pr = suma+1
- elif eq in [3, 4]:
- Pr = exp(suma)
- else:
- Pr = exp(self.Tc/T*suma)
- rho = Pr*self.rhoc
+ suma = 0
+ for n, x in zip(cls._rhoL["ao"], cls._rhoL["exp"]):
+ suma += n*Tita**x
+ Pr = suma+1
+ rho = Pr*cls.rhoc
return rho
- def _Vapor_Density(self, T=None):
- eq = self._vapor_Density["eq"]
- Tita = 1-T/self.Tc
- if eq in [2, 4, 6]:
+ @classmethod
+ def _Vapor_Density(cls, T):
+ """Auxiliary equation for the density of saturated vapor
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ rho : float
+ Saturated vapor density [kg/m³]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Saturation Properties of
+ Ordinary Water Substance September 1992,
+ http://www.iapws.org/relguide/Supp-sat.html, Eq.3
+ """
+ eq = cls._rhoG["eq"]
+ Tita = 1-T/cls.Tc
+ if eq == 4:
Tita = Tita**(1./3)
- suma = sum([n*Tita**x for n, x in zip(
- self._vapor_Density["ao"], self._vapor_Density["exp"])])
- if eq in [1, 2]:
- Pr = suma+1
- elif eq in [3, 4]:
- Pr = exp(suma)
- else:
- Pr = exp(self.Tc/T*suma)
- rho = Pr*self.rhoc
+ suma = 0
+ for n, x in zip(cls._rhoG["ao"], cls._rhoG["exp"]):
+ suma += n*Tita**x
+ Pr = exp(suma)
+ rho = Pr*cls.rhoc
return rho
- def _Tension(self, T):
- """Equation for the surface tension"""
- tau = 1-T/self.Tc
- tension = 0
- for sigma, n in zip(self._surface["sigma"],
- self._surface["exp"]):
- tension += sigma*tau**n
- return tension
+ @classmethod
+ def _dPdT_sat(cls, T):
+ """Auxiliary equation for the dP/dT along saturation line
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ dPdT : float
+ dPdT [MPa/K]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Saturation Properties of
+ Ordinary Water Substance September 1992,
+ http://www.iapws.org/relguide/Supp-sat.html, derived from Eq.1
+ """
+ Tita = 1-T/cls.Tc
+ suma1 = 0
+ suma2 = 0
+ for n, x in zip(cls._Pv["ao"], cls._Pv["exp"]):
+ suma1 -= n*x*Tita**(x-1)/cls.Tc
+ suma2 += n*Tita**x
+ Pr = (cls.Tc*suma1/T-cls.Tc/T**2*suma2)*exp(cls.Tc/T*suma2)
+ dPdT = Pr*cls.Pc
+ return dPdT
class IAPWS95(MEoS):
- """Multiparameter equation of state for water (including IAPWS95)
+ """Implementation of IAPWS Formulation 1995 for ordinary water substance,
+ (revised release of 2016), see MEoS __doc__
+ Examples
+ --------
>>> water=IAPWS95(T=300, rho=996.5560)
- >>> print("%0.10f %0.8f %0.5f %0.9f" % ( \
- water.P, water.cv, water.w, water.s))
+ >>> water.P, water.cv, water.w, water.s
0.0992418350 4.13018112 1501.51914 0.393062643
>>> water=IAPWS95(T=500, rho=0.435)
- >>> print("%0.10f %0.8f %0.5f %0.9f" % ( \
- water.P, water.cv, water.w, water.s))
+ >>> water.P, water.cv, water.w, water.s
0.0999679423 1.50817541 548.31425 7.944882714
>>> water=IAPWS95(T=900., P=700)
- >>> print("%0.4f %0.8f %0.5f %0.8f" % ( \
- water.rho, water.cv, water.w, water.s))
+ >>> water.rho, water.cv, water.w, water.s
870.7690 2.66422350 2019.33608 4.17223802
>>> water=IAPWS95(T=300., P=0.1)
- >>> print("%0.2f %0.5f %0.2f %0.2f %0.5f %0.4f %0.1f %0.6f" % ( \
- water.T, water.P, water.rho, water.h, water.s, water.cp, water.w, \
- water.virialB))
- 300.00 0.10000 996.56 112.65 0.39306 4.1806 1501.5 -0.066682
+ >>> water.P, water.rho, water.h, water.s, water.cp, water.w, water.virialB
+ 0.10000 996.56 112.65 0.39306 4.1806 1501.5 -0.066682
>>> water=IAPWS95(T=500., P=0.1)
- >>> print("%0.2f %0.5f %0.5f %0.1f %0.4f %0.4f %0.2f %0.7f" % ( \
- water.T, water.P, water.rho, water.h, water.s, water.cp, water.w, \
- water.virialB))
- 500.00 0.10000 0.43514 2928.6 7.9447 1.9813 548.31 -0.0094137
+ >>> water.P, water.rho, water.h, water.s, water.cp, water.w, water.virialB
+ 0.10000 0.43514 2928.6 7.9447 1.9813 548.31 -0.0094137
>>> water=IAPWS95(T=450., x=0.5)
- >>> print("%0.2f %0.5f %0.4f %0.1f %0.4f %0.6f" % ( \
- water.T, water.P, water.rho, water.h, water.s, water.virialB))
+ >>> water.T, water.P, water.rho, water.h, water.s, water.virialB
450.00 0.93220 9.5723 1761.8 4.3589 -0.013028
>>> water=IAPWS95(P=1.5, rho=1000.)
- >>> print("%0.2f %0.4f %0.1f %0.3f %0.5f %0.4f %0.1f %0.6f" % ( \
- water.T, water.P, water.rho, water.h, water.s, water.cp, water.w, \
- water.virialB))
- 286.44 1.5000 1000.0 57.253 0.19931 4.1855 1462.1 -0.085566
+ >>> water.T, water.rho, water.h, water.s, water.cp, water.w, water.virialB
+ 286.44 1000.0 57.253 0.19931 4.1855 1462.1 -0.085566
>>> water=IAPWS95(h=3000, s=8.)
- >>> print("%0.2f %0.5f %0.5f %0.1f %0.4f %0.4f %0.2f %0.7f" % ( \
- water.T, water.P, water.rho, water.h, water.s, water.cp, water.w, \
- water.virialB))
- 536.24 0.11970 0.48547 3000.0 8.0000 1.9984 567.04 -0.0076606
+ >>> water.T, water.P, water.h, water.s, water.cp, water.w, water.virialB
+ 536.24 0.11970 3000.0 8.0000 1.9984 567.04 -0.0076606
>>> water=IAPWS95(h=150, s=0.4)
- >>> print("%0.2f %0.5f %0.2f %0.2f %0.5f %0.4f %0.1f %0.6f" % ( \
- water.T, water.P, water.rho, water.h, water.s, water.cp, water.w, \
- water.virialB))
- 301.27 35.50549 1011.48 150.00 0.40000 4.0932 1564.1 -0.065238
+ >>> water.T, water.P, water.rho, water.h, water.s, water.cp, water.w
+ 301.27 35.50549 1011.48 150.00 0.40000 4.0932 1564.1
>>> water=IAPWS95(T=450., rho=300)
- >>> print("%0.2f %0.5f %0.2f %0.2f %0.4f %0.6f %0.6f" % ( \
- water.T, water.P, water.rho, water.h, water.s, water.x, water.virialB))
+ >>> water.T, water.P, water.rho, water.h, water.s, water.x, water.virialB
450.00 0.93220 300.00 770.82 2.1568 0.010693 -0.013028
>>> water=IAPWS95(rho=300., P=0.1)
- >>> print("%0.2f %0.5f %0.2f %0.2f %0.4f %0.7f %0.6f" % ( \
- water.T, water.P, water.rho, water.h, water.s, water.x, water.virialB))
+ >>> water.T, water.P, water.rho, water.h, water.s, water.x, water.virialB
372.76 0.10000 300.00 420.56 1.3110 0.0013528 -0.025144
>>> water=IAPWS95(h=1500., P=0.1)
- >>> print("%0.2f %0.5f %0.4f %0.1f %0.4f %0.5f %0.6f" % ( \
- water.T, water.P, water.rho, water.h, water.s, water.x, water.virialB))
+ >>> water.T, water.P, water.rho, water.h, water.s, water.x, water.virialB
372.76 0.10000 1.2303 1500.0 4.2068 0.47952 -0.025144
>>> water=IAPWS95(s=5., P=3.5)
- >>> print("%0.2f %0.4f %0.3f %0.1f %0.4f %0.5f %0.7f" % ( \
- water.T, water.P, water.rho, water.h, water.s, water.x, water.virialB))
+ >>> water.T, water.P, water.rho, water.h, water.s, water.x, water.virialB
515.71 3.5000 25.912 2222.8 5.0000 0.66921 -0.0085877
>>> water=IAPWS95(T=500., u=900)
- >>> print("%0.2f %0.2f %0.2f %0.2f %0.1f %0.4f %0.4f %0.1f %0.7f" % ( \
- water.T, water.P, water.rho, water.u, water.h, water.s, water.cp, \
- water.w, water.virialB))
- 500.00 108.21 903.62 900.00 1019.8 2.4271 4.1751 1576.0 -0.0094137
+ >>> water.P, water.rho, water.u, water.h, water.s, water.cp, water.w
+ 108.21 903.62 900.00 1019.8 2.4271 4.1751 1576.0
>>> water=IAPWS95(P=0.3, u=1550.)
- >>> print("%0.2f %0.5f %0.4f %0.1f %0.1f %0.4f %0.5f %0.6f" % ( \
- water.T, water.P, water.rho, water.u, water.h, water.s, water.x, \
- water.virialB))
- 406.67 0.30000 3.3029 1550.0 1640.8 4.3260 0.49893 -0.018263
+ >>> water.T, water.P, water.rho, water.u, water.h, water.s, water.x
+ 406.67 0.30000 3.3029 1550.0 1640.8 4.3260 0.49893
>>> water=IAPWS95(rho=300, h=1000.)
- >>> print("%0.2f %0.4f %0.2f %0.2f %0.1f %0.4f %0.6f %0.7f" % ( \
- water.T, water.P, water.rho, water.u, water.h, water.s, water.x, \
- water.virialB))
- 494.92 2.3991 300.00 992.00 1000.0 2.6315 0.026071 -0.0097064
+ >>> water.T, water.P, water.rho, water.u, water.h, water.s, water.x
+ 494.92 2.3991 300.00 992.00 1000.0 2.6315 0.026071
>>> water=IAPWS95(rho=30, s=8.)
- >>> print("%0.2f %0.3f %0.3f %0.1f %0.1f %0.4f %0.4f %0.2f %0.9f" % ( \
- water.T, water.P, water.rho, water.u, water.h, water.s, water.cp, \
- water.w, water.virialB))
- 1562.42 21.671 30.000 4628.5 5350.9 8.0000 2.7190 943.53 0.000047165
+ >>> water.T, water.P, water.rho, water.u, water.h, water.s, water.cp
+ 1562.42 21.671 30.000 4628.5 5350.9 8.0000 2.7190
>>> water=IAPWS95(rho=30, s=4.)
- >>> print("%0.2f %0.4f %0.3f %0.1f %0.1f %0.4f %0.5f %0.7f" % ( \
- water.T, water.P, water.rho, water.u, water.h, water.s, water.x, \
- water.virialB))
- 495.00 2.4029 30.000 1597.3 1677.4 4.0000 0.39218 -0.0097015
+ >>> water.T, water.P, water.rho, water.u, water.h, water.s, water.x
+ 495.00 2.4029 30.000 1597.3 1677.4 4.0000 0.39218
>>> water=IAPWS95(rho=300, u=1000.)
- >>> print("%0.2f %0.4f %0.3f %0.1f %0.1f %0.4f %0.5f %0.7f" % ( \
- water.T, water.P, water.rho, water.u, water.h, water.s, water.x, \
- water.virialB))
- 496.44 2.4691 300.000 1000.0 1008.2 2.6476 0.02680 -0.0096173
+ >>> water.T, water.P, water.rho, water.u, water.h, water.s, water.x
+ 496.44 2.4691 300.000 1000.0 1008.2 2.6476 0.02680
>>> water=IAPWS95(s=3., h=1000.)
- >>> print("%0.2f %0.6f %0.5f %0.2f %0.1f %0.4f %0.5f %0.6f" % ( \
- water.T, water.P, water.rho, water.u, water.h, water.s, water.x, \
- water.virialB))
- 345.73 0.034850 0.73526 952.60 1000.0 3.0000 0.29920 -0.034124
+ >>> water.T, water.P, water.rho, water.u, water.h, water.s, water.x
+ 345.73 0.034850 0.73526 952.60 1000.0 3.0000 0.29920
>>> water=IAPWS95(u=995., h=1000.)
- >>> print("%0.2f %0.4f %0.2f %0.2f %0.1f %0.4f %0.5f %0.6f" % ( \
- water.T, water.P, water.rho, water.u, water.h, water.s, water.x, \
- water.virialB))
- 501.89 2.7329 546.58 995.00 1000.0 2.6298 0.00866 -0.009308
+ >>> water.T, water.P, water.rho, water.u, water.h, water.s, water.x
+ 501.89 2.7329 546.58 995.00 1000.0 2.6298 0.00866
>>> water=IAPWS95(u=1000., s=3.)
- >>> print("%0.2f %0.6f %0.5f %0.2f %0.1f %0.4f %0.5f %0.6f" % ( \
- water.T, water.P, water.rho, water.u, water.h, water.s, water.x, \
- water.virialB))
- 371.24 0.094712 1.99072 1000.00 1047.6 3.0000 0.28144 -0.025543
-
+ >>> water.T, water.P, water.rho, water.u, water.h, water.s, water.x
+ 371.24 0.094712 1.99072 1000.00 1047.6 3.0000 0.28144
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Formulation 1995 for the Thermodynamic
+ Properties of Ordinary Water Substance for General and Scientific Use,
+ September 2016, http://www.iapws.org/relguide/IAPWS-95.html
+ IAPWS, Revised Supplementary Release on Saturation Properties of Ordinary
+ Water Substance September 1992, http://www.iapws.org/relguide/Supp-sat.html
+ IAPWS, Guideline on a Low-Temperature Extension of the IAPWS-95 Formulation
+ for Water Vapor, http://www.iapws.org/relguide/LowT.html
+ IAPWS, Revised Advisory Note No. 3: Thermodynamic Derivatives from IAPWS
+ Formulations, http://www.iapws.org/relguide/Advise3.pdf
"""
name = "water"
CASNumber = "7732-18-5"
formula = "H2O"
synonym = "R-718"
- Tc = 647.096
- rhoc = 322.
- Pc = 22.064
- M = 18.015268 # g/mol
+ Tc = Tc
+ rhoc = rhoc
+ Pc = Pc
+ M = M
Tt = 273.16
Tb = 373.1243
f_acent = 0.3443
@@ -1235,34 +1777,230 @@ class IAPWS95(MEoS):
"A": [0.32, .32],
"beta4": [0.3, 0.3]}
- _vapor_Pressure = {
- "eq": 6,
+ _Pv = {
"ao": [-7.85951783, 1.84408259, -11.7866497, 22.6807411, -15.9618719,
1.80122502],
- "exp": [2, 3, 6, 7, 8, 15]}
- _liquid_Density = {
+ "exp": [1, 1.5, 3, 3.5, 4, 7.5]}
+ _rhoL = {
"eq": 2,
"ao": [1.99274064, 1.09965342, -0.510839303, -1.75493479, -45.5170352,
-6.74694450e5],
"exp": [1, 2, 5, 16, 43, 110]}
- _vapor_Density = {
+ _rhoG = {
"eq": 4,
"ao": [-2.0315024, -2.6830294, -5.38626492, -17.2991605, -44.7586581,
-63.9201063],
"exp": [1, 2, 4, 9, 18.5, 35.5]}
+ def _phi0(self, tau, delta):
+ """Low temperature extension of the IAPWS-95"""
+ prop = MEoS._phi0(self, tau, delta)
+
+ T = self.Tc/tau
+ if 50 <= T < 130:
+ fex, fext, fextt = self._phiex(T)
+ prop["fio"] += fex
+ prop["fiot"] += fext
+ prop["fiott"] += fextt
+ return prop
+
+ def _phiex(self, T):
+ """Low temperature extension"""
+ tau = self.Tc/T
+ E = 0.278296458178592
+ ep = self.Tc/130
+ fex = E*(-1/2/tau-3/ep**2*(tau+ep)*log(tau/ep)-9/2/ep+9*tau/2/ep**2 +
+ tau**2/2/ep**3)
+ fext = E*(1/2/tau**2-3/tau/ep-3/ep**2*log(tau/ep)+3/2/ep**2+tau/ep**3)
+ fextt = E*(-1/tau+1/ep)**3
+ return fex, fext, fextt
+
+ @classmethod
+ def _alfa_sat(cls, T):
+ """Auxiliary equation for the alfa coefficient for calculate the
+ enthalpy along the saturation line
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ alfa : float
+ alfa coefficient [kJ/kg]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Saturation Properties of
+ Ordinary Water Substance September 1992,
+ http://www.iapws.org/relguide/Supp-sat.html, Eq.4
+ """
+ di = [-1135.905627715, -5.65134998e-8, 2690.66631, 127.287297,
+ -135.003439, 0.981825814]
+ expi = [0, -19, 1, 4.5, 5, 54.5]
+ Tita = T/cls.Tc
+ alfa = 0
+ for d, x in zip(di, expi):
+ alfa += d*Tita**x
+ return alfa
+
+ @classmethod
+ def _phi_sat(cls, T):
+ """Auxiliary equation for the phi coefficient for calculate the
+ entropy along the saturation line
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ phi : float
+ phi coefficient [kJ/kgK]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Saturation Properties of
+ Ordinary Water Substance September 1992,
+ http://www.iapws.org/relguide/Supp-sat.html, Eq.5
+ """
+ di = [2319.5246, -5.65134998e-8*19/20, 2690.66631, 127.287297*9/7,
+ -135.003439*5/4, 0.981825814*109/107]
+ expi = [0, -20, None, 3.5, 4, 53.5]
+ Tita = T/cls.Tc
+ suma = 0
+ for d, x in zip(di, expi):
+ if x is None:
+ suma += d*log(Tita)
+ else:
+ suma += d*Tita**x
+ phi = suma/cls.Tc
+ return phi
+
+ @classmethod
+ def _Liquid_Enthalpy(cls, T):
+ """Auxiliary equation for the specific enthalpy for saturated liquid
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ h : float
+ Saturated liquid enthalpy [kJ/kg]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Saturation Properties of
+ Ordinary Water Substance September 1992,
+ http://www.iapws.org/relguide/Supp-sat.html, Eq.6
+ """
+ alfa = cls._alfa_sat(T)
+ rho = cls._Liquid_Density(T)
+ dpdT = cls._dPdT_sat(T)
+ h = alfa+T/rho*dpdT*1000
+ return h
+
+ @classmethod
+ def _Vapor_Enthalpy(cls, T):
+ """Auxiliary equation for the specific enthalpy for saturated vapor
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ h : float
+ Saturated vapor enthalpy [kJ/kg]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Saturation Properties of
+ Ordinary Water Substance September 1992,
+ http://www.iapws.org/relguide/Supp-sat.html, Eq.7
+ """
+ alfa = cls._alfa_sat(T)
+ rho = cls._Vapor_Density(T)
+ dpdT = cls._dPdT_sat(T)
+ h = alfa+T/rho*dpdT*1000
+ return h
+
+ @classmethod
+ def _Liquid_Entropy(cls, T):
+ """Auxiliary equation for the specific entropy for saturated liquid
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ s : float
+ Saturated liquid entropy [kJ/kgK]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Saturation Properties of
+ Ordinary Water Substance September 1992,
+ http://www.iapws.org/relguide/Supp-sat.html, Eq.8
+ """
+ phi = cls._phi_sat(T)
+ rho = cls._Liquid_Density(T)
+ dpdT = cls._dPdT_sat(T)
+ s = phi+dpdT/rho*1000
+ return s
+
+ @classmethod
+ def _Vapor_Entropy(cls, T):
+ """Auxiliary equation for the specific entropy for saturated vapor
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ s : float
+ Saturated liquid entropy [kJ/kgK]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Saturation Properties of
+ Ordinary Water Substance September 1992,
+ http://www.iapws.org/relguide/Supp-sat.html, Eq.9
+ """
+ phi = cls._phi_sat(T)
+ rho = cls._Vapor_Density(T)
+ dpdT = cls._dPdT_sat(T)
+ s = phi+dpdT/rho*1000
+ return s
+
def _visco(self, rho, T, fase):
ref = IAPWS95()
- estado = ref._Helmholtz(rho, 1.5*647.096)
- drho = 1/estado["dpdrho"]*1e3
+ st = ref._Helmholtz(rho, 1.5*Tc)
+ delta = rho/rhoc
+ drho = 1e3/self.R/1.5/Tc/(1+2*delta*st["fird"]+delta**2*st["firdd"])
return _Viscosity(rho, T, fase, drho)
def _thermo(self, rho, T, fase):
ref = IAPWS95()
- estado = ref._Helmholtz(rho, 1.5*647.096)
- drho = 1/estado["dpdrho"]*1e3
+ st = ref._Helmholtz(rho, 1.5*Tc)
+ delta = rho/rhoc
+ drho = 1e3/self.R/1.5/Tc/(1+2*delta*st["fird"]+delta**2*st["firdd"])
return _ThCond(rho, T, fase, drho)
+ def _surface(self, T):
+ s = _Tension(T)
+ return s
+
class IAPWS95_PT(IAPWS95):
"""Derivated class for direct P and T input"""
@@ -1282,10 +2020,10 @@ class IAPWS95_Ps(IAPWS95):
IAPWS95.__init__(self, P=P, s=s)
-class IAPWS95_Pv(IAPWS95):
+class IAPWS95_Px(IAPWS95):
"""Derivated class for direct P and v input"""
- def __init__(self, P, v):
- IAPWS95.__init__(self, P=P, v=v)
+ def __init__(self, P, x):
+ IAPWS95.__init__(self, P=P, x=x)
class IAPWS95_Tx(IAPWS95):
@@ -1295,126 +2033,139 @@ class IAPWS95_Tx(IAPWS95):
class D2O(MEoS):
- """Multiparameter equation of state for heavy water
+ """Implementation of IAPWS Formulation for heavy water substance,
+ see MEoS __doc__
- >>> water=D2O(T=300, rho=996.5560)
- >>> print("%0.10f %0.8f %0.5f" % ( \
- water.P, water.Liquid.cv, water.Liquid.w))
+ Examples
+ --------
+ >>> hwater=D2O(T=300, rho=996.5560)
+ >>> hwater.P, hwater.Liquid.cv, hwater.Liquid.w
0.0030675947 4.21191157 5332.04871
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPS Formulation 1984 for the Thermodynamic
+ Properties of Heavy Water Substance,
+ http://www.iapws.org/relguide/D2O-2005.pdf
+ IAPWS, Revised Advisory Note No. 3: Thermodynamic Derivatives from IAPWS
+ Formulations, http://www.iapws.org/relguide/Advise3.pdf
+
+ Notes
+ -----
+ The implemented correlation isn't the current IAPWS formulation, it's the
+ preliminary equation to be presented at the 2017 IAPWS meetings.
"""
name = "heavy water"
CASNumber = "7789-20-0"
formula = "D2O"
synonym = "deuterium oxide"
- Tc = 643.847
- rhoc = 356.0
- Pc = 21.671
+ Tc = Tc_D2O
+ rhoc = rhoc_D2O
+ Pc = Pc_D2O
M = 20.027508 # g/mol
Tt = 276.97
Tb = 374.563
f_acent = 0.364
momentoDipolar = 1.9
- Fi0 = {'ao_log': [1, 2.9176485],
- 'ao_pow': [-5.60420745, 5.4495718, 0.100195196505025,
- -0.2844660508898171, 0.06437609920676933,
- -0.005436994367359454],
- 'pow': [0, 1, -1.0, -2.0, -3.0, -4.0],
- 'ao_exp': [], 'titao': []}
+ # Fi0 = {"ao_log": [0.5399322597e-2, 0],
+ # "pow": [0, 1, 2, 3, 4, 5],
+ # "ao_pow": [0.3087155964e2, -.3827264031e2, 0.4424799189,
+ # -.1256336874e1, 0.2843343470, -.2401555088e-1],
+ # "tau*logtau": -.1288399716e2,
+ # "tau*logdelta": 0.4415884023e1,
+ # "ao_exp": [], "titao": [],
+ # "ao_hyp": [], "hyp": []}
+
+ # _constants = {
+ # "R": 8.3143565, "rhoref": 17.875414*M, "Tref": 643.89,
+
+ # "nr1": [-0.384820628204e3, 0.108213047259e4, -0.110768260635e4,
+ # 0.164668954246e4, -0.137959852228e4, 0.598964185629e3,
+ # -0.100451752702e3, 0.419192736351e3, -0.107279987867e4,
+ # 0.653852283544e3, -0.984305985655e3, 0.845444459339e3,
+ # -0.376799930490e3, 0.644512590492e2, -0.214911115714e3,
+ # 0.531113962967e3, -0.135454224420e3, 0.202814416558e3,
+ # -0.178293865031e3, 0.818739394970e2, -0.143312594493e2,
+ # 0.651202383207e2, -0.171227351208e3, 0.100859921516e2,
+ # -0.144684680657e2, 0.128871134847e2, -0.610605957134e1,
+ # 0.109663804408e1, -0.115734899702e2, 0.374970075409e2,
+ # 0.897967147669, -0.527005883203e1, 0.438084681795e-1,
+ # 0.406772082680, -0.965258571044e-2, -0.119044600379e-1],
+ # "d1": [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
+ # 4, 4, 4, 4, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8],
+ # "t1": [0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
+ # 0, 1, 2, 3, 4, 5, 6, 0, 1, 0, 1, 0, 1, 0, 1],
+
+ # "nr2": [0.382589102341e3, -0.106406466204e4, 0.105544952919e4,
+ # -0.157579942855e4, 0.132703387531e4, -0.579348879870e3,
+ # 0.974163902526e2, 0.286799294226e3, -0.127543020847e4,
+ # 0.275802674911e4, -0.381284331492e4, 0.293755152012e4,
+ # -0.117858249946e4, 0.186261198012e3],
+ # "c2": [1]*14,
+ # "d2": [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2],
+ # "t2": [0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6],
+ # "gamma2": [1.5394]*14}
+
+ Fi0 = {"ao_log": [1, 3],
+ "pow": [0, 1, 2, 3, 4, 5],
+ "ao_pow": [-8.6739710041, 6.9611755531],
+ "tau*logtau": -.1288399716e2,
+ "tau*logdelta": 0.4415884023e1,
+ "ao_exp": [0.00863, 0.97454, 2.0646, 0.23528, 0.29555],
+ "titao": [0.4255669437, 2.6093155672, 6.0185106089, 11.3380974051,
+ 29.5101165339],
+ "ao_hyp": [], "hyp": []}
_constants = {
- "R": 8.3143565,
- "rhoref": 358.,
-
- "nr1": [-0.384820628204e3, 0.108213047259e4, -0.110768260635e4,
- 0.164668954246e4, -0.137959852228e4, 0.598964185629e3,
- -0.100451752702e3, 0.419192736351e3, -0.107279987867e4,
- 0.653852283544e3, -0.984305985655e3, 0.845444459339e3,
- -0.376799930490e3, 0.644512590492e2, -0.214911115714e3,
- 0.531113962967e3, -0.135454224420e3, 0.202814416558e3,
- -0.178293865031e3, 0.818739394970e2, -0.143312594493e2,
- 0.651202383207e2, -0.171227351208e3, 0.100859921516e2,
- -0.144684680657e2, 0.128871134847e2, -0.610605957134e1,
- 0.109663804408e1, -0.115734899702e2, 0.374970075409e2,
- 0.897967147669, -0.527005883203e1, 0.438084681795e-1,
- 0.406772082680, -0.965258571044e-2, -0.119044600379e-1],
- "d1": [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
- 4, 4, 4, 4, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8],
- "t1": [0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
- 0, 1, 2, 3, 4, 5, 6, 0, 1, 0, 1, 0, 1, 0, 1],
-
- "nr2": [0.382589102341e3, -0.106406466204e4, 0.105544952919e4,
- -0.157579942855e4, 0.132703387531e4, -0.579348879870e3,
- 0.974163902526e2, 0.286799294226e3, -0.127543020847e4,
- 0.275802674911e4, -0.381284331492e4, 0.293755152012e4,
- -0.117858249946e4, 0.186261198012e3],
- "c2": [1]*14,
- "d2": [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2],
- "t2": [0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6],
- "gamma2": [1.5394]*14}
-
- _surface = {"sigma": [0.238, -0.152082], "exp": [1.25, 2.25]}
- _vapor_Pressure = {
- "eq": 5,
+ "R": 8.3144621, "rhoref": 17.77555*M, "Tref": 643.847,
+
+ "nr1": [0.0105835, 0.99127253, -1.224122, 1.710643, -2.189443,
+ 0.1145315],
+ "d1": [4.0, 1.0, 1.0, 2.0, 2.0, 3.0],
+ "t1": [1.0, 0.463, 1.29, 1.307, 1.2165, 0.587],
+
+ "nr2": [-0.89875532, -1.597051, -2.804509, 0.33016885,
+ -3.396526, -0.001881],
+ "c2": [1.0, 2.0, 2.0, 1.0, 2.0, 1.0],
+ "d2": [1.0, 1.0, 3.0, 2.0, 2.0, 8.0],
+ "t2": [2.95, 1.713, 1.929, 0.94, 3.033, 0.765],
+ "gamma2": [1]*6,
+
+ "nr3": [-0.70355957, -0.20345481, -0.70691398, 2.094255, 3.042546,
+ 0.8010728, 0.213384, 0.32335789, -0.0245055, 0.7380677,
+ -0.21484089],
+ "t3": [1.504, 2.85, 1.96, 0.969, 2.576, 2.79, 3.581, 3.67, 1.7, 1.0,
+ 4.1],
+ "d3": [1.0, 2.0, 3.0, 1.0, 3.0, 1.0, 1.0, 2.0, 2.0, 2.0, 1.0],
+ "beta3": [0.907, 0.48, 1.223, 2.61, 4.283, 1.4, 0.735, 0.24, 1067.0,
+ 13.27, 1.48],
+ "alfa3": [0.982, 1.34, 1.658, 1.6235, 1.4, 2.206, 0.84, 1.535, 11.33,
+ 3.86, 7.56],
+ "epsilon3": [2.272, 1.375, 0.648, 0.8925, 0.145, 0.291, 2.01, 1.08,
+ 0.96, 0.181, 0.529],
+ "gamma3": [2.263, 2.343, 0.929, 1.0, 1.383, 0.968, 1.695, 2.23, 1.07,
+ 1.297, 2.41]}
+
+ _Pv = {
"ao": [-0.80236e1, 0.23957e1, -0.42639e2, 0.99569e2, -0.62135e2],
"exp": [1.0, 1.5, 2.75, 3.0, 3.2]}
- _liquid_Density = {
+ _rhoL = {
"eq": 1,
"ao": [0.26406e1, 0.97090e1, -0.18058e2, 0.87202e1, -0.74487e1],
"exp": [0.3678, 1.9, 2.2, 2.63, 7.3]}
- _vapor_Density = {
+ _rhoG = {
"eq": 3,
"ao": [-0.37651e1, -0.38673e2, 0.73024e2, -0.13251e3, 0.75235e2,
-0.70412e2],
"exp": [0.409, 1.766, 2.24, 3.04, 3.42, 6.9]}
- @classmethod
- def _visco(cls, rho, T, fase=None):
- Tr = T/643.847
- rhor = rho/358.0
-
- no = [1.0, 0.940695, 0.578377, -0.202044]
- fi0 = Tr**0.5/sum([n/Tr**i for i, n in enumerate(no)])
-
- Li = [0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 0, 1, 2, 5, 0, 1, 2, 3, 0, 1, 3,
- 5, 0, 1, 5, 3]
- Lj = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
- 4, 5, 5, 5, 6]
- Lij = [0.4864192, -0.2448372, -0.8702035, 0.8716056, -1.051126,
- 0.3458395, 0.3509007, 1.315436, 1.297752, 1.353448, -0.2847572,
- -1.037026, -1.287846, -0.02148229, 0.07013759, 0.4660127,
- 0.2292075, -0.4857462, 0.01641220, -0.02884911, 0.1607171,
- -.009603846, -.01163815, -.008239587, 0.004559914, -0.003886659]
-
- arr = [lij*(1./Tr-1)**i*(rhor-1)**j for i, j, lij in zip(Li, Lj, Lij)]
- fi1 = exp(rhor*sum(arr))
-
- return 55.2651e-6*fi0*fi1
-
- @classmethod
- def _thermo(cls, rho, T, fase=None):
- rhor = rho/358
- Tr = T/643.847
- tau = Tr/(abs(Tr-1.1)+1.1)
-
- no = [1.0, 37.3223, 22.5485, 13.0465, 0.0, -2.60735]
- Lo = sum([Li*Tr**i for i, Li in enumerate(no)])
-
- nr = [483.656, -191.039, 73.0358, -7.57467]
- Lr = -167.31*(1-exp(-2.506*rhor))+sum(
- [Li*rhor**(i+1) for i, Li in enumerate(nr)])
-
- f1 = exp(0.144847*Tr-5.64493*Tr**2)
- f2 = exp(-2.8*(rhor-1)**2)-0.080738543*exp(-17.943*(rhor-0.125698)**2)
- f3 = 1+exp(60*(tau-1)+20)
- f4 = 1+exp(100*(tau-1)+15)
- Lc = 35429.6*f1*f2*(1+f2**2*(5e9*f1**4/f3+3.5*f2/f4))
-
- Ll = -741.112*f1**1.2*(1-exp(-(rhor/2.5)**10))
-
- return 0.742128e-3*(Lo+Lr+Lc+Ll)
+ def _visco(self, rho, T, fase):
+ return _D2O_Viscosity(rho, T)
+ def _thermo(self, rho, T, fase):
+ return _D2O_ThCond(rho, T)
-if __name__ == "__main__":
- import doctest
- doctest.testmod()
+ def _surface(self, T):
+ s = _D2O_Tension(T)
+ return s
diff --git a/iapws/iapws97.py b/iapws/iapws97.py
index b6b3d6e..756c5d7 100644
--- a/iapws/iapws97.py
+++ b/iapws/iapws97.py
@@ -1,34 +1,145 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
-
-"IAPWS-IF97 Steam Tables implementation"
+"""IAPWS-IF97 standard implementation
+
+.. image:: https://raw.githubusercontent.com/jjgomera/iapws/master/images/iapws97.png
+ :alt: iapws97
+
+The module implement the fundamental equation for the five regions (rectangular
+boxes) and the backward equation (marked in grey).
+
+:func:`IAPWS97`: Global module class with all the functionality integrated
+
+Fundamental equations:
+ * :func:`_Region1`
+ * :func:`_Region2`
+ * :func:`_Region3`
+ * :func:`_Region4`
+ * :func:`_TSat_P`
+ * :func:`_PSat_T`
+ * :func:`_Region5`
+
+Backward equations:
+ * :func:`_Backward1_T_Ph`
+ * :func:`_Backward1_T_Ps`
+ * :func:`_Backward1_P_hs`
+ * :func:`_Backward2_T_Ph`
+ * :func:`_Backward2_T_Ps`
+ * :func:`_Backward2_P_hs`
+ * :func:`_Backward3_T_Ph`
+ * :func:`_Backward3_T_Ps`
+ * :func:`_Backward3_P_hs`
+ * :func:`_Backward3_v_Ph`
+ * :func:`_Backward3_v_Ps`
+ * :func:`_Backward3_v_PT`
+ * :func:`_Backward4_T_hs`
+
+Boundary equations:
+ * :func:`_h13_s`
+ * :func:`_h3a_s`
+ * :func:`_h1_s`
+ * :func:`_t_hs`
+ * :func:`_PSat_h`
+ * :func:`_h2ab_s`
+ * :func:`_h_3ab`
+ * :func:`_h2c3b_s`
+ * :func:`_hab_s`
+ * :func:`_hbc_P`
+
+
+References:
+
+IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+Thermodynamic Properties of Water and Steam August 2007,
+http://www.iapws.org/relguide/IF97-Rev.html
+
+IAPWS, Revised Supplementary Release on Backward Equations for Pressure
+as a Function of Enthalpy and Entropy p(h,s) for Regions 1 and 2 of the IAPWS
+Industrial Formulation 1997 for the Thermodynamic Properties of Water and
+Steam, http://www.iapws.org/relguide/Supp-PHS12-2014.pdf
+
+IAPWS, Revised Supplementary Release on Backward Equations for the
+Functions T(p,h), v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS
+Industrial Formulation 1997 for the Thermodynamic Properties of Water and
+Steam, http://www.iapws.org/relguide/Supp-Tv%28ph,ps%293-2014.pdf
+
+IAPWS, Revised Supplementary Release on Backward Equations p(h,s) for
+Region 3, Equations as a Function of h and s for the Region Boundaries, and an
+Equation Tsat(h,s) for Region 4 of the IAPWS Industrial Formulation 1997 for
+the Thermodynamic Properties of Water and Steam,
+http://www.iapws.org/relguide/Supp-phs3-2014.pdf
+
+IAPWS, Revised Supplementary Release on Backward Equations for Specific
+Volume as a Function of Pressure and Temperature v(p,T) for Region 3 of the
+IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of Water and
+Steam, http://www.iapws.org/relguide/Supp-VPT3-2016.pdf
+
+IAPWS, Revised Advisory Note No. 3: Thermodynamic Derivatives from IAPWS
+Formulations, http://www.iapws.org/relguide/Advise3.pdf
+
+Wagner, W; Kretzschmar, H-J: International Steam Tables: Properties of
+Water and Steam Based on the Industrial Formulation IAPWS-IF97; Springer, 2008;
+doi: 10.1007/978-3-540-74234-0
+"""
from __future__ import division
from math import sqrt, log, exp
from scipy.optimize import fsolve, newton
-from ._iapws import M, R, Tc, Pc, rhoc, Tt, Pt, Tb, Dipole, f_acent, _fase
+from ._iapws import R, Tc, Pc, rhoc, Tt, Pt, Tb, Dipole, f_acent
from ._iapws import _Viscosity, _ThCond, _Tension, _Dielectric, _Refractive
-from ._iapws import getphase
+from ._utils import getphase, deriv_G, _fase
+
+# Critic properties
+sc = 4.41202148223476
+hc = 2087.5468451171537
-sc = 4.41202148223476 # Critic entropy
# Pmin = _PSat_T(273.15) # Minimum pressure
Pmin = 0.000611212677444
# Ps_623 = _PSat_T(623.15) # P Saturation at 623.15 K, boundary region 1-3
Ps_623 = 16.5291642526
-# Boundary Region1-Region2
+# Boundary Region1-Region3
def _h13_s(s):
"""Define the boundary between Region 1 and 3, h=f(s)
- >>> "%.6f" % _h13_s(3.7)
- '1632.525047'
- >>> "%.6f" % _h13_s(3.5)
- '1566.104611'
+ Parameters
+ ----------
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * s(100MPa,623.15K) ≤ s ≤ s'(623.15K)
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations p(h,s) for
+ Region 3, Equations as a Function of h and s for the Region Boundaries, and
+ an Equation Tsat(h,s) for Region 4 of the IAPWS Industrial Formulation 1997
+ for the Thermodynamic Properties of Water and Steam,
+ http://www.iapws.org/relguide/Supp-phs3-2014.pdf. Eq 7
+
+ Examples
+ --------
+ >>> _h13_s(3.7)
+ 1632.525047
+ >>> _h13_s(3.5)
+ 1566.104611
"""
+ # Check input parameters
+ if s < 3.397782955 or s > 3.77828134:
+ raise NotImplementedError("Incoming out of bound")
+
sigma = s/3.8
I = [0, 1, 1, 3, 5, 6]
J = [0, -2, 2, -12, -4, -3]
@@ -36,8 +147,8 @@ def _h13_s(s):
0.117518273082168e-17, 0.220000904781292, -0.690815545851641e2]
suma = 0
- for i in range(6):
- suma += n[i] * (sigma-0.884)**I[i] * (sigma-0.864)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (sigma-0.884)**i * (sigma-0.864)**j
return 1700 * suma
@@ -45,8 +156,26 @@ def _h13_s(s):
def _P23_T(T):
"""Define the boundary between Region 2 and 3, P=f(T)
- >>> "%.8f" % _P23_T(623.15)
- '16.52916425'
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ P : float
+ Pressure [MPa]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 5
+
+ Examples
+ --------
+ >>> _P23_T(623.15)
+ 16.52916425
"""
n = [0.34805185628969e3, -0.11671859879975e1, 0.10192970039326e-2]
return n[0]+n[1]*T+n[2]*T**2
@@ -55,8 +184,26 @@ def _P23_T(T):
def _t_P(P):
"""Define the boundary between Region 2 and 3, T=f(P)
- >>> "%.2f" % _t_P(16.52916425)
- '623.15'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 5
+
+ Examples
+ --------
+ >>> _t_P(16.52916425)
+ 623.15
"""
n = [0.10192970039326e-2, 0.57254459862746e3, 0.1391883977870e2]
return n[1]+((P-n[2])/n[0])**0.5
@@ -65,11 +212,44 @@ def _t_P(P):
def _t_hs(h, s):
"""Define the boundary between Region 2 and 3, T=f(h,s)
- >>> "%.7f" % _t_hs(2600, 5.1)
- '713.5259364'
- >>> "%.7f" % _t_hs(2800, 5.2)
- '817.6202120'
+ Parameters
+ ----------
+ h : float
+ Specific enthalpy [kJ/kg]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 5.048096828 ≤ s ≤ 5.260578707
+ * 2.563592004e3 ≤ h ≤ 2.812942061e3
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations p(h,s) for
+ Region 3, Equations as a Function of h and s for the Region Boundaries, and
+ an Equation Tsat(h,s) for Region 4 of the IAPWS Industrial Formulation 1997
+ for the Thermodynamic Properties of Water and Steam,
+ http://www.iapws.org/relguide/Supp-phs3-2014.pdf. Eq 8
+
+ Examples
+ --------
+ >>> _t_hs(2600, 5.1)
+ 713.5259364
+ >>> _t_hs(2800, 5.2)
+ 817.6202120
"""
+ # Check input parameters
+ if s < 5.048096828 or s > 5.260578707 or \
+ h < 2.563592004e3 or h > 2.812942061e3:
+ raise NotImplementedError("Incoming out of bound")
+
nu = h/3000
sigma = s/5.3
I = [-12, -10, -8, -4, -3, -2, -2, -2, -2, 0, 1, 1, 1, 3, 3, 5, 6, 6, 8, 8,
@@ -87,8 +267,8 @@ def _t_hs(h, s):
0.783237062349385e7]
suma = 0
- for i in range(25):
- suma += n[i]*(nu-0.727)**I[i]*(sigma-0.864)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (nu-0.727)**i * (sigma-0.864)**j
return 900*suma
@@ -96,13 +276,36 @@ def _t_hs(h, s):
def _PSat_T(T):
"""Define the saturated line, P=f(T)
- >>> "%.8f" % _PSat_T(500)
- '2.63889776'
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ P : float
+ Pressure [MPa]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 273.15 ≤ T ≤ 647.096
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 30
+
+ Examples
+ --------
+ >>> _PSat_T(500)
+ 2.63889776
"""
- if T < 273.15:
- T = 273.15
- elif T > Tc:
- T = Tc
+ # Check input parameters
+ if T < 273.15 or T > Tc:
+ raise NotImplementedError("Incoming out of bound")
+
n = [0, 0.11670521452767E+04, -0.72421316703206E+06, -0.17073846940092E+02,
0.12020824702470E+05, -0.32325550322333E+07, 0.14915108613530E+02,
-0.48232657361591E+04, 0.40511340542057E+06, -0.23855557567849E+00,
@@ -117,13 +320,36 @@ def _PSat_T(T):
def _TSat_P(P):
"""Define the saturated line, T=f(P)
- >>> "%.6f" % _TSat_P(10)
- '584.149488'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 0.00061121 ≤ P ≤ 22.064
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 31
+
+ Examples
+ --------
+ >>> _TSat_P(10)
+ 584.149488
"""
- if P < 611.212677/1e6:
- P = 611.212677/1e6
- elif P > 22.064:
- P = 22.064
+ # Check input parameters
+ if P < 611.212677/1e6 or P > 22.064:
+ raise NotImplementedError("Incoming out of bound")
+
n = [0, 0.11670521452767E+04, -0.72421316703206E+06, -0.17073846940092E+02,
0.12020824702470E+05, -0.32325550322333E+07, 0.14915108613530E+02,
-0.48232657361591E+04, 0.40511340542057E+06, -0.23855557567849E+00,
@@ -139,17 +365,41 @@ def _TSat_P(P):
def _PSat_h(h):
"""Define the saturated line, P=f(h) for region 3
- >>> "%.8f" % _PSat_h(1700)
- '17.24175718'
- >>> "%.8f" % _PSat_h(2400)
- '20.18090839'
+ Parameters
+ ----------
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Returns
+ -------
+ P : float
+ Pressure [MPa]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * h'(623.15K) ≤ h ≤ h''(623.15K)
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for the
+ Functions T(p,h), v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS
+ Industrial Formulation 1997 for the Thermodynamic Properties of Water and
+ Steam, http://www.iapws.org/relguide/Supp-Tv%28ph,ps%293-2014.pdf, Eq 10
+
+ Examples
+ --------
+ >>> _PSat_h(1700)
+ 17.24175718
+ >>> _PSat_h(2400)
+ 20.18090839
"""
+ # Check input parameters
hmin_Ps3 = _Region1(623.15, Ps_623)["h"]
hmax_Ps3 = _Region2(623.15, Ps_623)["h"]
- if h < hmin_Ps3:
- h = hmin_Ps3
- if h > hmax_Ps3:
- h = hmax_Ps3
+ if h < hmin_Ps3 or h > hmax_Ps3:
+ raise NotImplementedError("Incoming out of bound")
+
nu = h/2600
I = [0, 1, 1, 1, 1, 5, 7, 8, 14, 20, 22, 24, 28, 36]
J = [0, 1, 3, 4, 36, 3, 0, 24, 16, 16, 3, 18, 8, 24]
@@ -160,19 +410,49 @@ def _PSat_h(h):
0.330611514838798e19, 0.813641294467829e38]
suma = 0
- for i in range(14):
- suma += n[i]*(nu-1.02)**I[i]*(nu-0.608)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (nu-1.02)**i * (nu-0.608)**j
return 22*suma
def _PSat_s(s):
"""Define the saturated line, P=f(s) for region 3
- >>> "%.8f" % _PSat_s(3.8)
- '16.87755057'
- >>> "%.8f" % _PSat_s(5.2)
- '16.68968482'
+ Parameters
+ ----------
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ P : float
+ Pressure [MPa]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * s'(623.15K) ≤ s ≤ s''(623.15K)
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for the
+ Functions T(p,h), v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS
+ Industrial Formulation 1997 for the Thermodynamic Properties of Water and
+ Steam, http://www.iapws.org/relguide/Supp-Tv%28ph,ps%293-2014.pdf, Eq 11
+
+ Examples
+ --------
+ >>> _PSat_s(3.8)
+ 16.87755057
+ >>> _PSat_s(5.2)
+ 16.68968482
"""
+ # Check input parameters
+ smin_Ps3 = _Region1(623.15, Ps_623)["s"]
+ smax_Ps3 = _Region2(623.15, Ps_623)["s"]
+ if s < smin_Ps3 or s > smax_Ps3:
+ raise NotImplementedError("Incoming out of bound")
+
sigma = s/5.2
I = [0, 1, 1, 4, 12, 12, 16, 24, 28, 32]
J = [0, 1, 32, 7, 4, 14, 36, 10, 0, 18]
@@ -182,19 +462,48 @@ def _PSat_s(s):
0.110649277244882e37]
suma = 0
- for i in range(10):
- suma += n[i]*(sigma-1.03)**I[i]*(sigma-0.699)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (sigma-1.03)**i * (sigma-0.699)**j
return 22*suma
def _h1_s(s):
"""Define the saturated line boundary between Region 1 and 4, h=f(s)
- >>> "%.7f" % _h1_s(1)
- '308.5509647'
- >>> "%.6f" % _h1_s(3)
- '1198.359754'
+ Parameters
+ ----------
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * s'(273.15K) ≤ s ≤ s'(623.15K)
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations p(h,s) for
+ Region 3, Equations as a Function of h and s for the Region Boundaries, and
+ an Equation Tsat(h,s) for Region 4 of the IAPWS Industrial Formulation 1997
+ for the Thermodynamic Properties of Water and Steam,
+ http://www.iapws.org/relguide/Supp-phs3-2014.pdf. Eq 3
+
+ Examples
+ --------
+ >>> _h1_s(1)
+ 308.5509647
+ >>> _h1_s(3)
+ 1198.359754
"""
+ # Check input parameters
+ if s < -1.545495919e-4 or s > 3.77828134:
+ raise NotImplementedError("Incoming out of bound")
+
sigma = s/3.8
I = [0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 7, 8, 12, 12, 14, 14, 16, 20,
20, 22, 24, 28, 32, 32]
@@ -211,19 +520,48 @@ def _h1_s(s):
0.834596332878346e-6, 0.503611916682674e1, 0.655444787064505e2]
suma = 0
- for i in range(27):
- suma += n[i]*(sigma-1.09)**I[i]*(sigma+0.366e-4)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (sigma-1.09)**i * (sigma+0.366e-4)**j
return 1700*suma
def _h3a_s(s):
"""Define the saturated line boundary between Region 4 and 3a, h=f(s)
- >>> "%.6f" % _h3a_s(3.8)
- '1685.025565'
- >>> "%.6f" % _h3a_s(4.2)
- '1949.352563'
+ Parameters
+ ----------
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * s'(623.15K) ≤ s ≤ sc
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations p(h,s) for
+ Region 3, Equations as a Function of h and s for the Region Boundaries, and
+ an Equation Tsat(h,s) for Region 4 of the IAPWS Industrial Formulation 1997
+ for the Thermodynamic Properties of Water and Steam,
+ http://www.iapws.org/relguide/Supp-phs3-2014.pdf. Eq 4
+
+ Examples
+ --------
+ >>> _h3a_s(3.8)
+ 1685.025565
+ >>> _h3a_s(4.2)
+ 1949.352563
"""
+ # Check input parameters
+ if s < 3.77828134 or s > 4.41202148223476:
+ raise NotImplementedError("Incoming out of bound")
+
sigma = s/3.8
I = [0, 0, 0, 0, 2, 3, 4, 4, 5, 5, 6, 7, 7, 7, 10, 10, 10, 32, 32]
J = [1, 4, 10, 16, 1, 36, 3, 16, 20, 36, 4, 2, 28, 32, 14, 32, 36, 0, 6]
@@ -236,19 +574,48 @@ def _h3a_s(s):
0.631052532240980]
suma = 0
- for i in range(19):
- suma += n[i]*(sigma-1.09)**I[i]*(sigma+0.366e-4)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (sigma-1.09)**i * (sigma+0.366e-4)**j
return 1700*suma
def _h2ab_s(s):
"""Define the saturated line boundary between Region 4 and 2a-2b, h=f(s)
- >>> "%.6f" % _h2ab_s(7)
- '2723.729985'
- >>> "%.6f" % _h2ab_s(9)
- '2511.861477'
+ Parameters
+ ----------
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * 5.85 ≤ s ≤ s"(273.15K)
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations p(h,s) for
+ Region 3, Equations as a Function of h and s for the Region Boundaries, and
+ an Equation Tsat(h,s) for Region 4 of the IAPWS Industrial Formulation 1997
+ for the Thermodynamic Properties of Water and Steam,
+ http://www.iapws.org/relguide/Supp-phs3-2014.pdf. Eq 5
+
+ Examples
+ --------
+ >>> _h2ab_s(7)
+ 2723.729985
+ >>> _h2ab_s(9)
+ 2511.861477
"""
+ # Check input parameters
+ if s < 5.85 or s > 9.155759395:
+ raise NotImplementedError("Incoming out of bound")
+
sigma1 = s/5.21
sigma2 = s/9.2
I = [1, 1, 2, 2, 4, 4, 7, 8, 8, 10, 12, 12, 18, 20, 24, 28, 28, 28, 28, 28,
@@ -267,19 +634,48 @@ def _h2ab_s(s):
-0.175407764869978e33, 0.347581490626396e35, -0.710971318427851e39]
suma = 0
- for i in range(30):
- suma += n[i]*(1/sigma1-0.513)**I[i]*(sigma2-0.524)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (1/sigma1-0.513)**i * (sigma2-0.524)**j
return 2800*exp(suma)
def _h2c3b_s(s):
"""Define the saturated line boundary between Region 4 and 2c-3b, h=f(s)
- >>> "%.6f" % _h2c3b_s(5.5)
- '2687.693850'
- >>> "%.6f" % _h2c3b_s(4.5)
- '2144.360448'
+ Parameters
+ ----------
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Raises
+ ------
+ NotImplementedError : If input isn't in limit
+ * sc ≤ s ≤ 5.85
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations p(h,s) for
+ Region 3, Equations as a Function of h and s for the Region Boundaries, and
+ an Equation Tsat(h,s) for Region 4 of the IAPWS Industrial Formulation 1997
+ for the Thermodynamic Properties of Water and Steam,
+ http://www.iapws.org/relguide/Supp-phs3-2014.pdf. Eq 6
+
+ Examples
+ --------
+ >>> _h2c3b_s(5.5)
+ 2687.693850
+ >>> _h2c3b_s(4.5)
+ 2144.360448
"""
+ # Check input parameters
+ if s < 4.41202148223476 or s > 5.85:
+ raise NotImplementedError("Incoming out of bound")
+
sigma = s/5.9
I = [0, 0, 0, 1, 1, 5, 6, 7, 8, 8, 12, 16, 22, 22, 24, 36]
J = [0, 3, 4, 0, 12, 36, 12, 16, 2, 20, 32, 36, 2, 32, 7, 20]
@@ -291,8 +687,8 @@ def _h2c3b_s(s):
-0.116994334851995e41]
suma = 0
- for i in range(16):
- suma += n[i]*(sigma-1.02)**I[i]*(sigma-0.726)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (sigma-1.02)**i * (sigma-0.726)**j
return 2800*suma**4
@@ -300,24 +696,53 @@ def _h2c3b_s(s):
def _Region1(T, P):
"""Basic equation for region 1
- >>> "%.11f" % _Region1(300,3)["v"]
- '0.00100215168'
- >>> "%.6f" % _Region1(300,3)["h"]
- '115.331273'
- >>> "%.6f" % (_Region1(300,3)["h"]-3000*_Region1(300,3)["v"], )
- '112.324818'
- >>> "%.9f" % _Region1(300,80)["s"]
- '0.368563852'
- >>> "%.8f" % _Region1(300,80)["cp"]
- '4.01008987'
- >>> "%.8f" % _Region1(300,80)["cv"]
- '3.91736606'
- >>> "%.5f" % _Region1(500,3)["w"]
- '1240.71337'
- >>> "%.11f" % _Region1(500,3)["alfav"]
- '0.00164118128'
- >>> "%.11f" % _Region1(500,3)["kt"]
- '0.00112892188'
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ prop : dict
+ Dict with calculated properties. The available properties are:
+
+ * v: Specific volume [m³/kg]
+ * h: Specific enthalpy [kJ/kg]
+ * s: Specific entropy [kJ/kgK]
+ * cp: Specific isobaric heat capacity [kJ/kgK]
+ * cv: Specific isocoric heat capacity [kJ/kgK]
+ * w: Speed of sound [m/s]
+ * alfav: Cubic expansion coefficient [1/K]
+ * kt: Isothermal compressibility [1/MPa]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 7
+
+ Examples
+ --------
+ >>> _Region1(300,3)["v"]
+ 0.00100215168
+ >>> _Region1(300,3)["h"]
+ 115.331273
+ >>> _Region1(300,3)["h"]-3000*_Region1(300,3)["v"]
+ 112.324818
+ >>> _Region1(300,80)["s"]
+ 0.368563852
+ >>> _Region1(300,80)["cp"]
+ 4.01008987
+ >>> _Region1(300,80)["cv"]
+ 3.91736606
+ >>> _Region1(500,3)["w"]
+ 1240.71337
+ >>> _Region1(500,3)["alfav"]
+ 0.00164118128
+ >>> _Region1(500,3)["kt"]
+ 0.00112892188
"""
I = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4,
4, 4, 5, 8, 8, 21, 23, 29, 30, 31, 32]
@@ -338,13 +763,13 @@ def _Region1(T, P):
Tr = 1386/T
Pr = P/16.53
g = gp = gpp = gt = gtt = gpt = 0
- for i in range(34):
- g += n[i]*(7.1-Pr)**I[i]*(Tr-1.222)**J[i]
- gp -= n[i]*I[i]*(7.1-Pr)**(I[i]-1)*(Tr-1.222)**J[i]
- gpp += n[i]*I[i]*(I[i]-1)*(7.1-Pr)**(I[i]-2)*(Tr-1.222)**J[i]
- gt += n[i] * (7.1-Pr)**I[i] * J[i] * (Tr-1.222)**(J[i]-1)
- gtt += n[i]*(7.1-Pr)**I[i]*J[i]*(J[i]-1)*(Tr-1.222)**(J[i]-2)
- gpt -= n[i]*I[i]*(7.1-Pr)**(I[i]-1)*J[i]*(Tr-1.222)**(J[i]-1)
+ for i, j, ni in zip(I, J, n):
+ g += ni * (7.1-Pr)**i * (Tr-1.222)**j
+ gp -= ni*i * (7.1-Pr)**(i-1) * (Tr-1.222)**j
+ gpp += ni*i*(i-1) * (7.1-Pr)**(i-2) * (Tr-1.222)**j
+ gt += ni*j * (7.1-Pr)**i * (Tr-1.222)**(j-1)
+ gtt += ni*j*(j-1) * (7.1-Pr)**i * (Tr-1.222)**(j-2)
+ gpt -= ni*i*j * (7.1-Pr)**(i-1) * (Tr-1.222)**(j-1)
propiedades = {}
propiedades["T"] = T
@@ -363,12 +788,33 @@ def _Region1(T, P):
def _Backward1_T_Ph(P, h):
- """Backward equation for region 1, T=f(P,h)
-
- >>> "%.6f" % _Backward1_T_Ph(3,500)
- '391.798509'
- >>> "%.6f" % _Backward1_T_Ph(80,1500)
- '611.041229'
+ """
+ Backward equation for region 1, T=f(P,h)
+
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 11
+
+ Examples
+ --------
+ >>> _Backward1_T_Ph(3,500)
+ 391.798509
+ >>> _Backward1_T_Ph(80,1500)
+ 611.041229
"""
I = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, 6]
J = [0, 1, 2, 6, 22, 32, 0, 1, 2, 3, 4, 10, 32, 10, 32, 10, 32, 32, 32, 32]
@@ -383,18 +829,38 @@ def _Backward1_T_Ph(P, h):
Pr = P/1
nu = h/2500
T = 0
- for i in range(20):
- T += n[i]*Pr**I[i]*(nu+1)**J[i]
+ for i, j, ni in zip(I, J, n):
+ T += ni * Pr**i * (nu+1)**j
return T
def _Backward1_T_Ps(P, s):
"""Backward equation for region 1, T=f(P,s)
- >>> "%.6f" % _Backward1_T_Ps(3,0.5)
- '307.842258'
- >>> "%.6f" % _Backward1_T_Ps(80,3)
- '565.899909'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 13
+
+ Examples
+ --------
+ >>> _Backward1_T_Ps(3,0.5)
+ 307.842258
+ >>> _Backward1_T_Ps(80,3)
+ 565.899909
"""
I = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 4]
J = [0, 1, 2, 3, 11, 31, 0, 1, 2, 3, 12, 31, 0, 1, 2, 9, 31, 10, 32, 32]
@@ -409,20 +875,41 @@ def _Backward1_T_Ps(P, s):
Pr = P/1
sigma = s/1
T = 0
- for i in range(20):
- T += n[i]*Pr**I[i]*(sigma+2)**J[i]
+ for i, j, ni in zip(I, J, n):
+ T += ni * Pr**i * (sigma+2)**j
return T
def _Backward1_P_hs(h, s):
"""Backward equation for region 1, P=f(h,s)
- >>> "%.13f" % _Backward1_P_hs(0.001,0)
- '0.0009800980612'
- >>> "%.8f" % _Backward1_P_hs(90,0)
- '91.92954727'
- >>> "%.8f" % _Backward1_P_hs(1500,3.4)
- '58.68294423'
+ Parameters
+ ----------
+ h : float
+ Specific enthalpy [kJ/kg]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ P : float
+ Pressure [MPa]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for Pressure
+ as a Function of Enthalpy and Entropy p(h,s) for Regions 1 and 2 of the
+ IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of
+ Water and Steam, http://www.iapws.org/relguide/Supp-PHS12-2014.pdf, Eq 1
+
+ Examples
+ --------
+ >>> _Backward1_P_hs(0.001,0)
+ 0.0009800980612
+ >>> _Backward1_P_hs(90,0)
+ 91.92954727
+ >>> _Backward1_P_hs(1500,3.4)
+ 58.68294423
"""
I = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 4, 4, 5]
J = [0, 1, 2, 4, 5, 6, 8, 14, 0, 1, 4, 6, 0, 1, 10, 4, 1, 4, 0]
@@ -437,8 +924,8 @@ def _Backward1_P_hs(h, s):
nu = h/3400
sigma = s/7.6
P = 0
- for i in range(19):
- P += n[i]*(nu+0.05)**I[i]*(sigma+0.05)**J[i]
+ for i, j, ni in zip(I, J, n):
+ P += ni * (nu+0.05)**i * (sigma+0.05)**j
return 100*P
@@ -446,24 +933,53 @@ def _Backward1_P_hs(h, s):
def _Region2(T, P):
"""Basic equation for region 2
- >>> "%.11f" % _Region2(700,30)["v"]
- '0.00542946619'
- >>> "%.5f" % _Region2(700,30)["h"]
- '2631.49474'
- >>> "%.5f" % (_Region2(700,30)["h"]-30000*_Region2(700,30)["v"], )
- '2468.61076'
- >>> "%.7f" % _Region2(700,0.0035)["s"]
- '10.1749996'
- >>> "%.8f" % _Region2(700,0.0035)["cp"]
- '2.08141274'
- >>> "%.8f" % _Region2(700,0.0035)["cv"]
- '1.61978333'
- >>> "%.6f" % _Region2(300,0.0035)["w"]
- '427.920172'
- >>> "%.11f" % _Region2(300,0.0035)["alfav"]
- '0.00337578289'
- >>> "%.6f" % _Region2(300,0.0035)["kt"]
- '286.239651'
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ prop : dict
+ Dict with calculated properties. The available properties are:
+
+ * v: Specific volume [m³/kg]
+ * h: Specific enthalpy [kJ/kg]
+ * s: Specific entropy [kJ/kgK]
+ * cp: Specific isobaric heat capacity [kJ/kgK]
+ * cv: Specific isocoric heat capacity [kJ/kgK]
+ * w: Speed of sound [m/s]
+ * alfav: Cubic expansion coefficient [1/K]
+ * kt: Isothermal compressibility [1/MPa]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 15-17
+
+ Examples
+ --------
+ >>> _Region2(700,30)["v"]
+ 0.00542946619
+ >>> _Region2(700,30)["h"]
+ 2631.49474
+ >>> _Region2(700,30)["h"]-30000*_Region2(700,30)["v"]
+ 2468.61076
+ >>> _Region2(700,0.0035)["s"]
+ 10.1749996
+ >>> _Region2(700,0.0035)["cp"]
+ 2.08141274
+ >>> _Region2(700,0.0035)["cv"]
+ 1.61978333
+ >>> _Region2(300,0.0035)["w"]
+ 427.920172
+ >>> _Region2(300,0.0035)["alfav"]
+ 0.00337578289
+ >>> _Region2(300,0.0035)["kt"]
+ 286.239651
"""
Tr = 540/T
Pr = P/1
@@ -495,13 +1011,13 @@ def _Region2(T, P):
-9.4369707241209998e-07]
gr = grp = grpp = grt = grtt = grpt = 0
- for i in range(43):
- gr += nr[i]*Pr**Ir[i]*(Tr-0.5)**Jr[i]
- grp += nr[i]*Ir[i]*Pr**(Ir[i]-1)*(Tr-0.5)**Jr[i]
- grpp += nr[i]*Ir[i]*(Ir[i]-1)*Pr**(Ir[i]-2)*(Tr-0.5)**Jr[i]
- grt += nr[i]*Pr**Ir[i]*Jr[i]*(Tr-0.5)**(Jr[i]-1)
- grtt += nr[i]*Pr**Ir[i]*Jr[i]*(Jr[i]-1)*(Tr-0.5)**(Jr[i]-2)
- grpt += nr[i]*Ir[i]*Pr**(Ir[i]-1)*Jr[i]*(Tr-0.5)**(Jr[i]-1)
+ for i, j, ni in zip(Ir, Jr, nr):
+ gr += ni * Pr**i * (Tr-0.5)**j
+ grp += ni*i * Pr**(i-1) * (Tr-0.5)**j
+ grpp += ni*i*(i-1) * Pr**(i-2) * (Tr-0.5)**j
+ grt += ni*j * Pr**i * (Tr-0.5)**(j-1)
+ grtt += ni*j*(j-1) * Pr**i * (Tr-0.5)**(j-2)
+ grpt += ni*i*j * Pr**(i-1) * (Tr-0.5)**(j-1)
propiedades = {}
propiedades["T"] = T
@@ -522,7 +1038,34 @@ def _Region2(T, P):
def Region2_cp0(Tr, Pr):
- """Ideal properties for Region 2"""
+ """Ideal properties for Region 2
+
+ Parameters
+ ----------
+ Tr : float
+ Reduced temperature [-]
+ Pr : float
+ Reduced pressure [-]
+
+ Returns
+ -------
+ prop : array
+ Array with ideal Gibbs energy partial derivatives:
+
+ * g: Ideal Specific Gibbs energy [kJ/kg]
+ * gp: [∂g/∂P]T
+ * gpp: [∂²g/∂P²]T
+ * gt: [∂g/∂T]P
+ * gtt: [∂²g/∂T²]P
+ * gpt: [∂²g/∂T∂P]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 16
+
+ """
Jo = [0, 1, -5, -4, -3, -2, -1, 2, 3]
no = [-0.96927686500217E+01, 0.10086655968018E+02, -0.56087911283020E-02,
0.71452738081455E-01, -0.40710498223928E+00, 0.14240819171444E+01,
@@ -531,18 +1074,36 @@ def Region2_cp0(Tr, Pr):
gop = Pr**-1
gopp = -Pr**-2
got = gott = gopt = 0
- for i in range(9):
- go += no[i]*Tr**Jo[i]
- got += no[i]*Jo[i]*Tr**(Jo[i]-1)
- gott += no[i]*Jo[i]*(Jo[i]-1)*Tr**(Jo[i]-2)
+ for j, ni in zip(Jo, no):
+ go += ni * Tr**j
+ got += ni*j * Tr**(j-1)
+ gott += ni*j*(j-1) * Tr**(j-2)
return go, gop, gopp, got, gott, gopt
def _P_2bc(h):
"""Define the boundary between Region 2b and 2c, P=f(h)
- >>> "%.3f" % _P_2bc(3516.004323)
- '100.000'
+ Parameters
+ ----------
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Returns
+ -------
+ P : float
+ Pressure [MPa]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 20
+
+ Examples
+ --------
+ >>> _P_2bc(3516.004323)
+ 100.0
"""
return 905.84278514723-0.67955786399241*h+1.2809002730136e-4*h**2
@@ -550,8 +1111,26 @@ def _P_2bc(h):
def _hbc_P(P):
"""Define the boundary between Region 2b and 2c, h=f(P)
- >>> "%.6f" % _hbc_P(100)
- '3516.004323'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 21
+
+ Examples
+ --------
+ >>> _hbc_P(100)
+ 3516.004323
"""
return 0.26526571908428e4+((P-0.45257578905948e1)/1.2809002730136e-4)**0.5
@@ -559,8 +1138,27 @@ def _hbc_P(P):
def _hab_s(s):
"""Define the boundary between Region 2a and 2b, h=f(s)
- >>> "%.6f" % _hab_s(7)
- '3376.437884'
+ Parameters
+ ----------
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for Pressure
+ as a Function of Enthalpy and Entropy p(h,s) for Regions 1 and 2 of the
+ IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of
+ Water and Steam, http://www.iapws.org/relguide/Supp-PHS12-2014.pdf, Eq 2
+
+ Examples
+ --------
+ >>> _hab_s(7)
+ 3376.437884
"""
smin = _Region2(_TSat_P(4), 4)["s"]
smax = _Region2(1073.15, 4)["s"]
@@ -577,10 +1175,30 @@ def _hab_s(s):
def _Backward2a_T_Ph(P, h):
"""Backward equation for region 2a, T=f(P,h)
- >>> "%.6f" % _Backward2a_T_Ph(0.001,3000)
- '534.433241'
- >>> "%.5f" % _Backward2a_T_Ph(3,4000)
- '1010.77577'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 22
+
+ Examples
+ --------
+ >>> _Backward2a_T_Ph(0.001,3000)
+ 534.433241
+ >>> _Backward2a_T_Ph(3,4000)
+ 1010.77577
"""
I = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7]
@@ -602,18 +1220,38 @@ def _Backward2a_T_Ph(P, h):
Pr = P/1
nu = h/2000
T = 0
- for i in range(34):
- T += n[i]*Pr**I[i]*(nu-2.1)**J[i]
+ for i, j, ni in zip(I, J, n):
+ T += ni * Pr**i * (nu-2.1)**j
return T
def _Backward2b_T_Ph(P, h):
"""Backward equation for region 2b, T=f(P,h)
- >>> "%.5f" % _Backward2b_T_Ph(5,4000)
- '1015.31583'
- >>> "%.6f" % _Backward2b_T_Ph(25,3500)
- '875.279054'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 23
+
+ Examples
+ --------
+ >>> _Backward2b_T_Ph(5,4000)
+ 1015.31583
+ >>> _Backward2b_T_Ph(25,3500)
+ 875.279054
"""
I = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3,
3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 6, 7, 7, 9, 9]
@@ -636,18 +1274,38 @@ def _Backward2b_T_Ph(P, h):
Pr = P/1
nu = h/2000
T = 0
- for i in range(38):
- T += n[i]*(Pr-2)**I[i]*(nu-2.6)**J[i]
+ for i, j, ni in zip(I, J, n):
+ T += ni * (Pr-2)**i * (nu-2.6)**j
return T
def _Backward2c_T_Ph(P, h):
"""Backward equation for region 2c, T=f(P,h)
- >>> "%.6f" % _Backward2c_T_Ph(40,2700)
- '743.056411'
- >>> "%.6f" % _Backward2c_T_Ph(60,3200)
- '882.756860'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 24
+
+ Examples
+ --------
+ >>> _Backward2c_T_Ph(40,2700)
+ 743.056411
+ >>> _Backward2c_T_Ph(60,3200)
+ 882.756860
"""
I = [-7, -7, -6, -6, -5, -5, -2, -2, -1, -1, 0, 0, 1, 1, 2, 6, 6, 6, 6, 6,
6, 6, 6]
@@ -665,14 +1323,26 @@ def _Backward2c_T_Ph(P, h):
Pr = P/1
nu = h/2000
T = 0
- for i in range(23):
- T += n[i]*(Pr+25)**I[i]*(nu-1.8)**J[i]
+ for i, j, ni in zip(I, J, n):
+ T += ni * (Pr+25)**i * (nu-1.8)**j
return T
def _Backward2_T_Ph(P, h):
- """Backward equation for region 2, T=f(P,h)"""
- Tsat = _TSat_P(P)
+ """Backward equation for region 2, T=f(P,h)
+
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+ """
if P <= 4:
T = _Backward2a_T_Ph(P, h)
elif 4 < P <= 6.546699678:
@@ -683,16 +1353,40 @@ def _Backward2_T_Ph(P, h):
T = _Backward2b_T_Ph(P, h)
else:
T = _Backward2c_T_Ph(P, h)
- return max(Tsat, T)
+
+ if P <= 22.064:
+ Tsat = _TSat_P(P)
+ T = max(Tsat, T)
+ return T
def _Backward2a_T_Ps(P, s):
"""Backward equation for region 2a, T=f(P,s)
- >>> "%.6f" % _Backward2a_T_Ps(0.1,7.5)
- '399.517097'
- >>> "%.5f" % _Backward2a_T_Ps(2.5,8)
- '1039.84917'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 25
+
+ Examples
+ --------
+ >>> _Backward2a_T_Ps(0.1,7.5)
+ 399.517097
+ >>> _Backward2a_T_Ps(2.5,8)
+ 1039.84917
"""
I = [-1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.25, -1.25, -1.25, -1.0, -1.0,
-1.0, -1.0, -1.0, -1.0, -0.75, -0.75, -0.5, -0.5, -0.5, -0.5, -0.25,
@@ -721,18 +1415,38 @@ def _Backward2a_T_Ps(P, s):
Pr = P/1
sigma = s/2
T = 0
- for i in range(46):
- T += n[i]*Pr**I[i]*(sigma-2)**J[i]
+ for i, j, ni in zip(I, J, n):
+ T += ni * Pr**i * (sigma-2)**j
return T
def _Backward2b_T_Ps(P, s):
"""Backward equation for region 2b, T=f(P,s)
- >>> "%.6f" % _Backward2b_T_Ps(8,6)
- '600.484040'
- >>> "%.5f" % _Backward2b_T_Ps(90,6)
- '1038.01126'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 26
+
+ Examples
+ --------
+ >>> _Backward2b_T_Ps(8,6)
+ 600.484040
+ >>> _Backward2b_T_Ps(90,6)
+ 1038.01126
"""
I = [-6, -6, -5, -5, -4, -4, -4, -3, -3, -3, -3, -2, -2, -2, -2, -1, -1,
-1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3,
@@ -758,18 +1472,38 @@ def _Backward2b_T_Ps(P, s):
Pr = P/1
sigma = s/0.7853
T = 0
- for i in range(44):
- T += n[i]*Pr**I[i]*(10-sigma)**J[i]
+ for i, j, ni in zip(I, J, n):
+ T += ni * Pr**i * (10-sigma)**j
return T
def _Backward2c_T_Ps(P, s):
"""Backward equation for region 2c, T=f(P,s)
- >>> "%.6f" % _Backward2c_T_Ps(20,5.75)
- '697.992849'
- >>> "%.6f" % _Backward2c_T_Ps(80,5.75)
- '949.017998'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 27
+
+ Examples
+ --------
+ >>> _Backward2c_T_Ps(20,5.75)
+ 697.992849
+ >>> _Backward2c_T_Ps(80,5.75)
+ 949.017998
"""
I = [-2, -2, -1, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5,
5, 6, 6, 7, 7, 7, 7, 7]
@@ -789,33 +1523,69 @@ def _Backward2c_T_Ps(P, s):
Pr = P/1
sigma = s/2.9251
T = 0
- for i in range(30):
- T += n[i]*Pr**I[i]*(2-sigma)**J[i]
+ for i, j, ni in zip(I, J, n):
+ T += ni * Pr**i * (2-sigma)**j
return T
def _Backward2_T_Ps(P, s):
- """Backward equation for region 2, T=f(P,s)"""
- sf = 5.85
- Tsat = _TSat_P(P)
+ """Backward equation for region 2, T=f(P,s)
+
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+ """
if P <= 4:
T = _Backward2a_T_Ps(P, s)
- elif s >= sf:
+ elif s >= 5.85:
T = _Backward2b_T_Ps(P, s)
else:
T = _Backward2c_T_Ps(P, s)
- return max(Tsat, T)
+
+ if P <= 22.064:
+ Tsat = _TSat_P(P)
+ T = max(Tsat, T)
+ return T
def _Backward2a_P_hs(h, s):
"""Backward equation for region 2a, P=f(h,s)
- >>> "%.9f" % _Backward2a_P_hs(2800,6.5)
- '1.371012767'
- >>> "%.12f" % _Backward2a_P_hs(2800,9.5)
- '0.001879743844'
- >>> "%.10f" % _Backward2a_P_hs(4100,9.5)
- '0.1024788997'
+ Parameters
+ ----------
+ h : float
+ Specific enthalpy [kJ/kg]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ P : float
+ Pressure [MPa]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for Pressure
+ as a Function of Enthalpy and Entropy p(h,s) for Regions 1 and 2 of the
+ IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of
+ Water and Steam, http://www.iapws.org/relguide/Supp-PHS12-2014.pdf, Eq 3
+
+ Examples
+ --------
+ >>> _Backward2a_P_hs(2800,6.5)
+ 1.371012767
+ >>> _Backward2a_P_hs(2800,9.5)
+ 0.001879743844
+ >>> _Backward2a_P_hs(4100,9.5)
+ 0.1024788997
"""
I = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3,
3, 4, 5, 5, 6, 7]
@@ -835,20 +1605,41 @@ def _Backward2a_P_hs(h, s):
nu = h/4200
sigma = s/12
suma = 0
- for i in range(29):
- suma += n[i]*(nu-0.5)**I[i]*(sigma-1.2)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (nu-0.5)**i * (sigma-1.2)**j
return 4*suma**4
def _Backward2b_P_hs(h, s):
"""Backward equation for region 2b, P=f(h,s)
- >>> "%.9f" % _Backward2b_P_hs(2800,6)
- '4.793911442'
- >>> "%.8f" % _Backward2b_P_hs(3600,6)
- '83.95519209'
- >>> "%.9f" % _Backward2b_P_hs(3600,7)
- '7.527161441'
+ Parameters
+ ----------
+ h : float
+ Specific enthalpy [kJ/kg]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ P : float
+ Pressure [MPa]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for Pressure
+ as a Function of Enthalpy and Entropy p(h,s) for Regions 1 and 2 of the
+ IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of
+ Water and Steam, http://www.iapws.org/relguide/Supp-PHS12-2014.pdf, Eq 4
+
+ Examples
+ --------
+ >>> _Backward2b_P_hs(2800,6)
+ 4.793911442
+ >>> _Backward2b_P_hs(3600,6)
+ 83.95519209
+ >>> _Backward2b_P_hs(3600,7)
+ 7.527161441
"""
I = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6,
6, 6, 7, 7, 8, 8, 8, 8, 12, 14]
@@ -869,20 +1660,41 @@ def _Backward2b_P_hs(h, s):
nu = h/4100
sigma = s/7.9
suma = 0
- for i in range(33):
- suma += n[i]*(nu-0.6)**I[i]*(sigma-1.01)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (nu-0.6)**i * (sigma-1.01)**j
return 100*suma**4
def _Backward2c_P_hs(h, s):
"""Backward equation for region 2c, P=f(h,s)
- >>> "%.8f" % _Backward2c_P_hs(2800,5.1)
- '94.39202060'
- >>> "%.9f" % _Backward2c_P_hs(2800,5.8)
- '8.414574124'
- >>> "%.8f" % _Backward2c_P_hs(3400,5.8)
- '83.76903879'
+ Parameters
+ ----------
+ h : float
+ Specific enthalpy [kJ/kg]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ P : float
+ Pressure [MPa]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for Pressure
+ as a Function of Enthalpy and Entropy p(h,s) for Regions 1 and 2 of the
+ IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of
+ Water and Steam, http://www.iapws.org/relguide/Supp-PHS12-2014.pdf, Eq 5
+
+ Examples
+ --------
+ >>> _Backward2c_P_hs(2800,5.1)
+ 94.39202060
+ >>> _Backward2c_P_hs(2800,5.8)
+ 8.414574124
+ >>> _Backward2c_P_hs(3400,5.8)
+ 83.76903879
"""
I = [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 5,
5, 5, 5, 6, 6, 10, 12, 16]
@@ -903,13 +1715,26 @@ def _Backward2c_P_hs(h, s):
nu = h/3500
sigma = s/5.9
suma = 0
- for i in range(31):
- suma += n[i]*(nu-0.7)**I[i]*(sigma-1.1)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (nu-0.7)**i * (sigma-1.1)**j
return 100*suma**4
def _Backward2_P_hs(h, s):
- """Backward equation for region 2, P=f(h,s)"""
+ """Backward equation for region 2, P=f(h,s)
+
+ Parameters
+ ----------
+ h : float
+ Specific enthalpy [kJ/kg]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ P : float
+ Pressure [MPa]
+ """
sfbc = 5.85
hamin = _hab_s(s)
if h <= hamin:
@@ -925,62 +1750,87 @@ def _Backward2_P_hs(h, s):
def _Region3(rho, T):
"""Basic equation for region 3
- >>> "%.7f" % _Region3(500,650)["P"]
- '25.5837018'
- >>> "%.5f" % _Region3(500,650)["h"]
- '1863.43019'
+ Parameters
+ ----------
+ rho : float
+ Density [kg/m³]
+ T : float
+ Temperature [K]
+
+ Returns
+ -------
+ prop : dict
+ Dict with calculated properties. The available properties are:
+
+ * v: Specific volume [m³/kg]
+ * h: Specific enthalpy [kJ/kg]
+ * s: Specific entropy [kJ/kgK]
+ * cp: Specific isobaric heat capacity [kJ/kgK]
+ * cv: Specific isocoric heat capacity [kJ/kgK]
+ * w: Speed of sound [m/s]
+ * alfav: Cubic expansion coefficient [1/K]
+ * kt: Isothermal compressibility [1/MPa]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 28
+
+ Examples
+ --------
+ >>> _Region3(500,650)["P"]
+ 25.5837018
+ >>> _Region3(500,650)["h"]
+ 1863.43019
>>> p = _Region3(500, 650)
- >>> "%.5f" % (p["h"]-p["P"]*1000*p["v"], )
- '1812.26279'
- >>> "%.8f" % _Region3(200,650)["s"]
- '4.85438792'
- >>> "%.7f" % _Region3(200,650)["cp"]
- '44.6579342'
- >>> "%.8f" % _Region3(200,650)["cv"]
- '4.04118076'
- >>> "%.6f" % _Region3(200,650)["w"]
- '383.444594'
- >>> "%.11f" % _Region3(500,750)["alfav"]
- '0.00441515098'
- >>> "%.11f" % _Region3(500,750)["kt"]
- '0.00806710817'
- >>> "%.11f" % _Region3(500,750)["alfap"]
- '0.00698896514'
- >>> "%.6f" % _Region3(500,750)["betap"]
- '791.475213'
- """
-
- I = [None, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3,
- 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 8, 9, 9, 10, 10, 11]
- J = [None, 0, 1, 2, 7, 10, 12, 23, 2, 6, 15, 17, 0, 2, 6, 7, 22, 26, 0, 2,
- 4, 16, 26, 0, 2, 4, 26, 1, 3, 26, 0, 2, 26, 2, 26, 2, 26, 0, 1, 26]
- n = [0.10658070028513e1, -0.15732845290239e2, 0.20944396974307e2,
- -0.76867707878716e1, 0.26185947787954e1, -0.28080781148620e1,
- 0.12053369696517e1, -0.84566812812502e-2, -0.12654315477714e1,
- -0.11524407806681e1, 0.88521043984318, -0.64207765181607,
- 0.38493460186671, -0.85214708824206, 0.48972281541877e1,
- -0.30502617256965e1, 0.39420536879154e-1, 0.12558408424308,
- -0.27999329698710, 0.13899799569460e1, -0.20189915023570e1,
- -0.82147637173963e-2, -0.47596035734923, 0.43984074473500e-1,
- -0.44476435428739, 0.90572070719733, .70522450087967, .10770512626332,
- -0.32913623258954, -0.50871062041158, -0.22175400873096e-1,
- 0.94260751665092e-1, 0.16436278447961, -0.13503372241348e-1,
- -0.14834345352472e-1, 0.57922953628084e-3, 0.32308904703711e-2,
- 0.80964802996215e-4, -0.16557679795037e-3, -0.44923899061815e-4]
+ >>> p["h"]-p["P"]*1000*p["v"]
+ 1812.26279
+ >>> _Region3(200,650)["s"]
+ 4.85438792
+ >>> _Region3(200,650)["cp"]
+ 44.6579342
+ >>> _Region3(200,650)["cv"]
+ 4.04118076
+ >>> _Region3(200,650)["w"]
+ 383.444594
+ >>> _Region3(500,750)["alfav"]
+ 0.00441515098
+ >>> _Region3(500,750)["kt"]
+ 0.00806710817
+ """
+
+ I = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4,
+ 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 8, 9, 9, 10, 10, 11]
+ J = [0, 1, 2, 7, 10, 12, 23, 2, 6, 15, 17, 0, 2, 6, 7, 22, 26, 0, 2, 4, 16,
+ 26, 0, 2, 4, 26, 1, 3, 26, 0, 2, 26, 2, 26, 2, 26, 0, 1, 26]
+ n = [-0.15732845290239e2, 0.20944396974307e2, -0.76867707878716e1,
+ 0.26185947787954e1, -0.28080781148620e1, 0.12053369696517e1,
+ -0.84566812812502e-2, -0.12654315477714e1, -0.11524407806681e1,
+ 0.88521043984318, -0.64207765181607, 0.38493460186671,
+ -0.85214708824206, 0.48972281541877e1, -0.30502617256965e1,
+ 0.39420536879154e-1, 0.12558408424308, -0.27999329698710,
+ 0.13899799569460e1, -0.20189915023570e1, -0.82147637173963e-2,
+ -0.47596035734923, 0.43984074473500e-1, -0.44476435428739,
+ 0.90572070719733, .70522450087967, .10770512626332, -0.32913623258954,
+ -0.50871062041158, -0.22175400873096e-1, 0.94260751665092e-1,
+ 0.16436278447961, -0.13503372241348e-1, -0.14834345352472e-1,
+ 0.57922953628084e-3, 0.32308904703711e-2, 0.80964802996215e-4,
+ -0.16557679795037e-3, -0.44923899061815e-4]
d = rho/rhoc
Tr = Tc/T
- g = n[0]*log(d)
- gd = n[0]*d**-1
- gdd = -n[0]*d**-2
+ g = 1.0658070028513*log(d)
+ gd = 1.0658070028513/d
+ gdd = -1.0658070028513/d**2
gt = gtt = gdt = 0
- for i in range(1, 40):
- g += n[i]*d**I[i]*Tr**J[i]
- gd += n[i]*I[i]*d**(I[i]-1)*Tr**J[i]
- gdd += n[i]*I[i]*(I[i]-1)*d**(I[i]-2)*Tr**J[i]
- gt += n[i] * d**I[i] * J[i] * Tr**(J[i]-1)
- gtt += n[i]*d**I[i]*J[i]*(J[i]-1)*Tr**(J[i]-2)
- gdt += n[i]*I[i]*d**(I[i]-1)*J[i]*Tr**(J[i]-1)
+ for i, j, ni in zip(I, J, n):
+ g += ni * d**i * Tr**j
+ gd += ni*i * d**(i-1) * Tr**j
+ gdd += ni*i*(i-1) * d**(i-2) * Tr**j
+ gt += ni*j * d**i * Tr**(j-1)
+ gtt += ni*j*(j-1) * d**i * Tr**(j-2)
+ gdt += ni*i*j * d**(i-1) * Tr**(j-1)
propiedades = {}
propiedades["T"] = T
@@ -994,8 +1844,6 @@ def _Region3(rho, T):
Tr**2/gtt))
propiedades["alfav"] = (gd-Tr*gdt)/(2*gd+d*gdd)/T
propiedades["kt"] = 1/(2*d*gd+d**2*gdd)/rho/R/T*1000
- propiedades["alfap"] = (1-Tr*gdt/gd)/T
- propiedades["betap"] = rho*(2+d*gdd/gd)
propiedades["region"] = 3
propiedades["x"] = 1
return propiedades
@@ -1004,8 +1852,20 @@ def _Region3(rho, T):
def _h_3ab(P):
"""Define the boundary between Region 3a-3b, h=f(P)
- >>> "%.6f" % _h_3ab(25)
- '2095.936454'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Examples
+ --------
+ >>> _h_3ab(25)
+ 2095.936454
"""
return 0.201464004206875e4 + 3.74696550136983*P - \
0.0219921901054187*P**2+0.875131686009950e-4*P**3
@@ -1014,8 +1874,27 @@ def _h_3ab(P):
def _tab_P(P):
"""Define the boundary between Region 3a-3b, T=f(P)
- >>> "%.7f" % _tab_P(40)
- '693.0341408'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for Specific
+ Volume as a Function of Pressure and Temperature v(p,T) for Region 3 of the
+ IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of Water
+ and Steam, http://www.iapws.org/relguide/Supp-VPT3-2016.pdf, Eq. 2
+
+ Examples
+ --------
+ >>> _tab_P(40)
+ 693.0341408
"""
I = [0, 1, 2, -1, -2]
n = [0.154793642129415e4, -0.187661219490113e3, 0.213144632222113e2,
@@ -1023,16 +1902,35 @@ def _tab_P(P):
Pr = P/1
T = 0
- for i in range(5):
- T += n[i]*log(Pr)**I[i]
+ for i, ni in zip(I, n):
+ T += ni * log(Pr)**i
return T
def _top_P(P):
"""Define the boundary between Region 3o-3p, T=f(P)
- >>> "%.7f" % _top_P(22.8)
- '650.0106943'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for Specific
+ Volume as a Function of Pressure and Temperature v(p,T) for Region 3 of the
+ IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of Water
+ and Steam, http://www.iapws.org/relguide/Supp-VPT3-2016.pdf, Eq. 2
+
+ Examples
+ --------
+ >>> _top_P(22.8)
+ 650.0106943
"""
I = [0, 1, 2, -1, -2]
n = [0.969461372400213e3, -0.332500170441278e3, 0.642859598466067e2,
@@ -1040,16 +1938,35 @@ def _top_P(P):
Pr = P/1
T = 0
- for i in range(5):
- T += n[i]*log(Pr)**I[i]
+ for i, ni in zip(I, n):
+ T += ni * log(Pr)**i
return T
def _twx_P(P):
"""Define the boundary between Region 3w-3x, T=f(P)
- >>> "%.7f" % _twx_P(22.3)
- '648.2049480'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for Specific
+ Volume as a Function of Pressure and Temperature v(p,T) for Region 3 of the
+ IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of Water
+ and Steam, http://www.iapws.org/relguide/Supp-VPT3-2016.pdf, Eq. 2
+
+ Examples
+ --------
+ >>> _twx_P(22.3)
+ 648.2049480
"""
I = [0, 1, 2, -1, -2]
n = [0.728052609145380e1, 0.973505869861952e2, 0.147370491183191e2,
@@ -1057,40 +1974,79 @@ def _twx_P(P):
Pr = P/1
T = 0
- for i in range(5):
- T += n[i]*log(Pr)**I[i]
+ for i, ni in zip(I, n):
+ T += ni * log(Pr)**i
return T
def _tef_P(P):
"""Define the boundary between Region 3e-3f, T=f(P)
- >>> "%.7f" % _tef_P(40)
- '713.9593992'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for Specific
+ Volume as a Function of Pressure and Temperature v(p,T) for Region 3 of the
+ IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of Water
+ and Steam, http://www.iapws.org/relguide/Supp-VPT3-2016.pdf, Eq. 3
+
+ Examples
+ --------
+ >>> _tef_P(40)
+ 713.9593992
"""
return 3.727888004*(P-22.064)+647.096
-def _txx_P(P, xx):
+def _txx_P(P, xy):
"""Define the boundary between 3x-3y, T=f(P)
- where xx represent the subregions options: cd, gh, ij, jk, mn, qu, rx, uv
-
- >>> "%.7f" % _txx_P(25,"cd")
- '649.3659208'
- >>> "%.7f" % _txx_P(23,"gh")
- '649.8873759'
- >>> "%.7f" % _txx_P(23,"ij")
- '651.5778091'
- >>> "%.7f" % _txx_P(23,"jk")
- '655.8338344'
- >>> "%.7f" % _txx_P(22.8,"mn")
- '649.6054133'
- >>> "%.7f" % _txx_P(22,"qu")
- '645.6355027'
- >>> "%.7f" % _txx_P(22,"rx")
- '648.2622754'
- >>> "%.7f" % _txx_P(22.3,"uv")
- '647.7996121'
+
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ xy: string
+ Subregions options: cd, gh, ij, jk, mn, qu, rx, uv
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for Specific
+ Volume as a Function of Pressure and Temperature v(p,T) for Region 3 of the
+ IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of Water
+ and Steam, http://www.iapws.org/relguide/Supp-VPT3-2016.pdf, Eq. 1
+
+ Examples
+ --------
+ >>> _txx_P(25,"cd")
+ 649.3659208
+ >>> _txx_P(23,"gh")
+ 649.8873759
+ >>> _txx_P(23,"ij")
+ 651.5778091
+ >>> _txx_P(23,"jk")
+ 655.8338344
+ >>> _txx_P(22.8,"mn")
+ 649.6054133
+ >>> _txx_P(22,"qu")
+ 645.6355027
+ >>> _txx_P(22,"rx")
+ 648.2622754
+ >>> _txx_P(22.3,"uv")
+ 647.7996121
"""
ng = {
"cd": [0.585276966696349e3, 0.278233532206915e1, -0.127283549295878e-1,
@@ -1110,21 +2066,42 @@ def _txx_P(P, xx):
"uv": [0.528199646263062e3, 0.890579602135307e1, -0.222814134903755,
0.286791682263697e-2]}
- n = ng[xx]
+ n = ng[xy]
Pr = P/1
T = 0
- for i in range(len(n)):
- T += n[i]*Pr**i
+ for i, ni in enumerate(n):
+ T += ni * Pr**i
return T
def _Backward3a_v_Ph(P, h):
"""Backward equation for region 3a, v=f(P,h)
- >>> "%.12f" % _Backward3a_v_Ph(20,1700)
- '0.001749903962'
- >>> "%.12f" % _Backward3a_v_Ph(100,2100)
- '0.001676229776'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for the
+ Functions T(p,h), v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS
+ Industrial Formulation 1997 for the Thermodynamic Properties of Water and
+ Steam, http://www.iapws.org/relguide/Supp-Tv%28ph,ps%293-2014.pdf, Eq 4
+
+ Returns
+ -------
+ v : float
+ Specific volume [m³/kg]
+
+ Examples
+ --------
+ >>> _Backward3a_v_Ph(20,1700)
+ 0.001749903962
+ >>> _Backward3a_v_Ph(100,2100)
+ 0.001676229776
"""
I = [-12, -12, -12, -12, -10, -10, -10, -8, -8, -6, -6, -6, -4, -4, -3, -2,
-2, -1, -1, -1, -1, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 8]
@@ -1145,18 +2122,39 @@ def _Backward3a_v_Ph(P, h):
Pr = P/100
nu = h/2100
suma = 0
- for i in range(32):
- suma += n[i]*(Pr+0.128)**I[i]*(nu-0.727)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (Pr+0.128)**i * (nu-0.727)**j
return 0.0028*suma
def _Backward3b_v_Ph(P, h):
"""Backward equation for region 3b, v=f(P,h)
- >>> "%.12f" % _Backward3b_v_Ph(20,2500)
- '0.006670547043'
- >>> "%.12f" % _Backward3b_v_Ph(100,2700)
- '0.002404234998'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Returns
+ -------
+ v : float
+ Specific volume [m³/kg]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for the
+ Functions T(p,h), v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS
+ Industrial Formulation 1997 for the Thermodynamic Properties of Water and
+ Steam, http://www.iapws.org/relguide/Supp-Tv%28ph,ps%293-2014.pdf, Eq 5
+
+ Examples
+ --------
+ >>> _Backward3b_v_Ph(20,2500)
+ 0.006670547043
+ >>> _Backward3b_v_Ph(100,2700)
+ 0.002404234998
"""
I = [-12, -12, -8, -8, -8, -8, -8, -8, -6, -6, -6, -6, -6, -6, -4, -4, -4,
-3, -3, -2, -2, -1, -1, -1, -1, 0, 1, 1, 2, 2]
@@ -1176,13 +2174,26 @@ def _Backward3b_v_Ph(P, h):
Pr = P/100
nu = h/2800
suma = 0
- for i in range(30):
- suma += n[i]*(Pr+0.0661)**I[i]*(nu-0.72)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (Pr+0.0661)**i * (nu-0.72)**j
return 0.0088*suma
def _Backward3_v_Ph(P, h):
- """Backward equation for region 3, v=f(P,h)"""
+ """Backward equation for region 3, v=f(P,h)
+
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Returns
+ -------
+ v : float
+ Specific volume [m³/kg]
+ """
hf = _h_3ab(P)
if h <= hf:
return _Backward3a_v_Ph(P, h)
@@ -1193,10 +2204,31 @@ def _Backward3_v_Ph(P, h):
def _Backward3a_T_Ph(P, h):
"""Backward equation for region 3a, T=f(P,h)
- >>> "%.7f" % _Backward3a_T_Ph(20,1700)
- '629.3083892'
- >>> "%.7f" % _Backward3a_T_Ph(100,2100)
- '733.6163014'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for the
+ Functions T(p,h), v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS
+ Industrial Formulation 1997 for the Thermodynamic Properties of Water and
+ Steam, http://www.iapws.org/relguide/Supp-Tv%28ph,ps%293-2014.pdf, Eq 2
+
+ Examples
+ --------
+ >>> _Backward3a_T_Ph(20,1700)
+ 629.3083892
+ >>> _Backward3a_T_Ph(100,2100)
+ 733.6163014
"""
I = [-12, -12, -12, -12, -12, -12, -12, -12, -10, -10, -10, -8, -8, -8, -8,
-5, -3, -2, -2, -2, -1, -1, 0, 0, 1, 3, 3, 4, 4, 10, 12]
@@ -1225,10 +2257,31 @@ def _Backward3a_T_Ph(P, h):
def _Backward3b_T_Ph(P, h):
"""Backward equation for region 3b, T=f(P,h)
- >>> "%.7f" % _Backward3b_T_Ph(20,2500)
- '641.8418053'
- >>> "%.7f" % _Backward3b_T_Ph(100,2700)
- '842.0460876'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for the
+ Functions T(p,h), v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS
+ Industrial Formulation 1997 for the Thermodynamic Properties of Water and
+ Steam, http://www.iapws.org/relguide/Supp-Tv%28ph,ps%293-2014.pdf, Eq 3
+
+ Examples
+ --------
+ >>> _Backward3b_T_Ph(20,2500)
+ 641.8418053
+ >>> _Backward3b_T_Ph(100,2700)
+ 842.0460876
"""
I = [-12, -12, -10, -10, -10, -10, -10, -8, -8, -8, -8, -8, -6, -6, -6, -4,
-4, -3, -2, -2, -1, -1, -1, -1, -1, -1, 0, 0, 1, 3, 5, 6, 8]
@@ -1255,7 +2308,20 @@ def _Backward3b_T_Ph(P, h):
def _Backward3_T_Ph(P, h):
- """Backward equation for region 3, T=f(P,h)"""
+ """Backward equation for region 3, T=f(P,h)
+
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+ """
hf = _h_3ab(P)
if h <= hf:
T = _Backward3a_T_Ph(P, h)
@@ -1267,10 +2333,31 @@ def _Backward3_T_Ph(P, h):
def _Backward3a_v_Ps(P, s):
"""Backward equation for region 3a, v=f(P,s)
- >>> "%.12f" % _Backward3a_v_Ps(20,3.8)
- '0.001733791463'
- >>> "%.12f" % _Backward3a_v_Ps(100,4)
- '0.001555893131'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ v : float
+ Specific volume [m³/kg]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for the
+ Functions T(p,h), v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS
+ Industrial Formulation 1997 for the Thermodynamic Properties of Water and
+ Steam, http://www.iapws.org/relguide/Supp-Tv%28ph,ps%293-2014.pdf, Eq 8
+
+ Examples
+ --------
+ >>> _Backward3a_v_Ps(20,3.8)
+ 0.001733791463
+ >>> _Backward3a_v_Ps(100,4)
+ 0.001555893131
"""
I = [-12, -12, -12, -10, -10, -10, -10, -8, -8, -8, -8, -6, -5, -4, -3, -3,
-2, -2, -1, -1, 0, 0, 0, 1, 2, 4, 5, 6]
@@ -1290,18 +2377,39 @@ def _Backward3a_v_Ps(P, s):
Pr = P/100
sigma = s/4.4
suma = 0
- for i in range(28):
- suma += n[i]*(Pr+0.187)**I[i]*(sigma-0.755)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (Pr+0.187)**i * (sigma-0.755)**j
return 0.0028*suma
def _Backward3b_v_Ps(P, s):
"""Backward equation for region 3b, v=f(P,s)
- >>> "%.12f" % _Backward3b_v_Ps(20,5)
- '0.006262101987'
- >>> "%.12f" % _Backward3b_v_Ps(100,5)
- '0.002449610757'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ v : float
+ Specific volume [m³/kg]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for the
+ Functions T(p,h), v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS
+ Industrial Formulation 1997 for the Thermodynamic Properties of Water and
+ Steam, http://www.iapws.org/relguide/Supp-Tv%28ph,ps%293-2014.pdf, Eq 9
+
+ Examples
+ --------
+ >>> _Backward3b_v_Ps(20,5)
+ 0.006262101987
+ >>> _Backward3b_v_Ps(100,5)
+ 0.002449610757
"""
I = [-12, -12, -12, -12, -12, -12, -10, -10, -10, -10, -8, -5, -5, -5, -4,
-4, -4, -4, -3, -2, -2, -2, -2, -2, -2, 0, 0, 0, 1, 1, 2]
@@ -1322,13 +2430,26 @@ def _Backward3b_v_Ps(P, s):
Pr = P/100
sigma = s/5.3
suma = 0
- for i in range(31):
- suma += n[i]*(Pr+0.298)**I[i]*(sigma-0.816)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (Pr+0.298)**i * (sigma-0.816)**j
return 0.0088*suma
def _Backward3_v_Ps(P, s):
- """Backward equation for region 3, v=f(P,s)"""
+ """Backward equation for region 3, v=f(P,s)
+
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ v : float
+ Specific volume [m³/kg]
+ """
if s <= sc:
return _Backward3a_v_Ps(P, s)
else:
@@ -1338,10 +2459,31 @@ def _Backward3_v_Ps(P, s):
def _Backward3a_T_Ps(P, s):
"""Backward equation for region 3a, T=f(P,s)
- >>> "%.7f" % _Backward3a_T_Ps(20,3.8)
- '628.2959869'
- >>> "%.7f" % _Backward3a_T_Ps(100,4)
- '705.6880237'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for the
+ Functions T(p,h), v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS
+ Industrial Formulation 1997 for the Thermodynamic Properties of Water and
+ Steam, http://www.iapws.org/relguide/Supp-Tv%28ph,ps%293-2014.pdf, Eq 6
+
+ Examples
+ --------
+ >>> _Backward3a_T_Ps(20,3.8)
+ 628.2959869
+ >>> _Backward3a_T_Ps(100,4)
+ 705.6880237
"""
I = [-12, -12, -10, -10, -10, -10, -8, -8, -8, -8, -6, -6, -6, -5, -5, -5,
-4, -4, -4, -2, -2, -1, -1, 0, 0, 0, 1, 2, 2, 3, 8, 8, 10]
@@ -1362,18 +2504,39 @@ def _Backward3a_T_Ps(P, s):
Pr = P/100
sigma = s/4.4
suma = 0
- for i in range(33):
- suma += n[i]*(Pr+0.240)**I[i]*(sigma-0.703)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (Pr+0.240)**i * (sigma-0.703)**j
return 760*suma
def _Backward3b_T_Ps(P, s):
"""Backward equation for region 3b, T=f(P,s)
- >>> "%.7f" % _Backward3b_T_Ps(20,5)
- '640.1176443'
- >>> "%.7f" % _Backward3b_T_Ps(100,5)
- '847.4332825'
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for the
+ Functions T(p,h), v(p,h) and T(p,s), v(p,s) for Region 3 of the IAPWS
+ Industrial Formulation 1997 for the Thermodynamic Properties of Water and
+ Steam, http://www.iapws.org/relguide/Supp-Tv%28ph,ps%293-2014.pdf, Eq 7
+
+ Examples
+ --------
+ >>> _Backward3b_T_Ps(20,5)
+ 640.1176443
+ >>> _Backward3b_T_Ps(100,5)
+ 847.4332825
"""
I = [-12, -12, -12, -12, -8, -8, -8, -6, -6, -6, -5, -5, -5, -5, -5, -4,
-3, -3, -2, 0, 2, 3, 4, 5, 6, 8, 12, 14]
@@ -1393,13 +2556,26 @@ def _Backward3b_T_Ps(P, s):
Pr = P/100
sigma = s/5.3
suma = 0
- for i in range(28):
- suma += n[i]*(Pr+0.760)**I[i]*(sigma-0.818)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (Pr+0.760)**i * (sigma-0.818)**j
return 860*suma
def _Backward3_T_Ps(P, s):
- """Backward equation for region 3, T=f(P,s)"""
+ """Backward equation for region 3, T=f(P,s)
+
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+ """
sc = 4.41202148223476
if s <= sc:
T = _Backward3a_T_Ps(P, s)
@@ -1411,12 +2587,34 @@ def _Backward3_T_Ps(P, s):
def _Backward3a_P_hs(h, s):
"""Backward equation for region 3a, P=f(h,s)
- >>> "%.8f" % _Backward3a_P_hs(1700,3.8)
- '25.55703246'
- >>> "%.8f" % _Backward3a_P_hs(2000,4.2)
- '45.40873468'
- >>> "%.8f" % _Backward3a_P_hs(2100,4.3)
- '60.78123340'
+ Parameters
+ ----------
+ h : float
+ Specific enthalpy [kJ/kg]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ P : float
+ Pressure [MPa]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations p(h,s) for
+ Region 3, Equations as a Function of h and s for the Region Boundaries, and
+ an Equation Tsat(h,s) for Region 4 of the IAPWS Industrial Formulation 1997
+ for the Thermodynamic Properties of Water and Steam,
+ http://www.iapws.org/relguide/Supp-phs3-2014.pdf. Eq 1
+
+ Examples
+ --------
+ >>> _Backward3a_P_hs(1700,3.8)
+ 25.55703246
+ >>> _Backward3a_P_hs(2000,4.2)
+ 45.40873468
+ >>> _Backward3a_P_hs(2100,4.3)
+ 60.78123340
"""
I = [0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 6, 7, 8, 10, 10,
14, 18, 20, 22, 22, 24, 28, 28, 32, 32]
@@ -1437,20 +2635,42 @@ def _Backward3a_P_hs(h, s):
nu = h/2300
sigma = s/4.4
suma = 0
- for i in range(33):
- suma += n[i]*(nu-1.01)**I[i]*(sigma-0.75)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (nu-1.01)**i * (sigma-0.75)**j
return 99*suma
def _Backward3b_P_hs(h, s):
"""Backward equation for region 3b, P=f(h,s)
- >>> "%.8f" % _Backward3b_P_hs(2400,4.7)
- '63.63924887'
- >>> "%.8f" % _Backward3b_P_hs(2600,5.1)
- '34.34999263'
- >>> "%.8f" % _Backward3b_P_hs(2700,5.0)
- '88.39043281'
+ Parameters
+ ----------
+ h : float
+ Specific enthalpy [kJ/kg]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ P : float
+ Pressure [MPa]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations p(h,s) for
+ Region 3, Equations as a Function of h and s for the Region Boundaries, and
+ an Equation Tsat(h,s) for Region 4 of the IAPWS Industrial Formulation 1997
+ for the Thermodynamic Properties of Water and Steam,
+ http://www.iapws.org/relguide/Supp-phs3-2014.pdf. Eq 1
+
+ Examples
+ --------
+ >>> _Backward3b_P_hs(2400,4.7)
+ 63.63924887
+ >>> _Backward3b_P_hs(2600,5.1)
+ 34.34999263
+ >>> _Backward3b_P_hs(2700,5.0)
+ 88.39043281
"""
I = [-12, -12, -12, -12, -12, -10, -10, -10, -10, -8, -8, -6, -6, -6, -6,
-5, -4, -4, -4, -3, -3, -3, -3, -2, -2, -1, 0, 2, 2, 5, 6, 8, 10, 14,
@@ -1473,13 +2693,26 @@ def _Backward3b_P_hs(h, s):
nu = h/2800
sigma = s/5.3
suma = 0
- for i in range(35):
- suma += n[i]*(nu-0.681)**I[i]*(sigma-0.792)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (nu-0.681)**i * (sigma-0.792)**j
return 16.6/suma
def _Backward3_P_hs(h, s):
- """Backward equation for region 3, P=f(h,s)"""
+ """Backward equation for region 3, P=f(h,s)
+
+ Parameters
+ ----------
+ h : float
+ Specific enthalpy [kJ/kg]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ P : float
+ Pressure [MPa]
+ """
sc = 4.41202148223476
if s <= sc:
return _Backward3a_P_hs(h, s)
@@ -1489,7 +2722,25 @@ def _Backward3_P_hs(h, s):
def _Backward3_sat_v_P(P, T, x):
"""Backward equation for region 3 for saturated state, vs=f(P,x)
- x 0,1 vapor quality"""
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+ x : integer
+ Vapor quality [-]
+
+ Returns
+ -------
+ v : float
+ Specific volume [m³/kg]
+
+ Notes
+ -----
+ The vapor quality (x) can be 0 (saturated liquid) or 1 (saturated vapour)
+ """
if x == 0:
if P < 19.00881189:
region = "c"
@@ -1513,7 +2764,27 @@ def _Backward3_sat_v_P(P, T, x):
def _Backward3_v_PT(P, T):
- """Backward equation for region 3, v=f(P,T)"""
+ """Backward equation for region 3, v=f(P,T)
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ v : float
+ Specific volume [m³/kg]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for Specific
+ Volume as a Function of Pressure and Temperature v(p,T) for Region 3 of the
+ IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of Water
+ and Steam, http://www.iapws.org/relguide/Supp-VPT3-2016.pdf, Table 2 and 10
+ """
if P > 40:
if T <= _tab_P(P):
region = "a"
@@ -1601,6 +2872,7 @@ def _Backward3_v_PT(P, T):
elif tcd < T <= tqu:
region = "q"
elif tqu < T <= trx:
+ # Table 10
tef = _tef_P(P)
twx = _twx_P(P)
tuv = _txx_P(P, "uv")
@@ -1654,7 +2926,7 @@ def _Backward3_v_PT(P, T):
region = "r"
else:
region = "k"
- elif 19.00881189 < P <= 20.5:
+ elif 19.00881189173929 < P <= 20.5:
tcd = _txx_P(P, "cd")
Ts = _TSat_P(P)
if T <= tcd:
@@ -1663,7 +2935,7 @@ def _Backward3_v_PT(P, T):
region = "s"
else:
region = "t"
- elif Ps_623 < P <= 19.00881189:
+ elif Ps_623 < P <= 19.00881189173929:
Ts = _TSat_P(P)
if T <= Ts:
region = "c"
@@ -1676,138 +2948,161 @@ def _Backward3_v_PT(P, T):
def _Backward3x_v_PT(T, P, x):
"""Backward equation for region 3x, v=f(P,T)
- >>> "%.12f" % _Backward3x_v_PT(630,50,"a")
- '0.001470853100'
- >>> "%.12f" % _Backward3x_v_PT(670,80,"a")
- '0.001503831359'
- >>> "%.12f" % _Backward3x_v_PT(710,50,"b")
- '0.002204728587'
- >>> "%.12f" % _Backward3x_v_PT(750,80,"b")
- '0.001973692940'
- >>> "%.12f" % _Backward3x_v_PT(630,20,"c")
- '0.001761696406'
- >>> "%.12f" % _Backward3x_v_PT(650,30,"c")
- '0.001819560617'
- >>> "%.12f" % _Backward3x_v_PT(656,26,"d")
- '0.002245587720'
- >>> "%.12f" % _Backward3x_v_PT(670,30,"d")
- '0.002506897702'
- >>> "%.12f" % _Backward3x_v_PT(661,26,"e")
- '0.002970225962'
- >>> "%.12f" % _Backward3x_v_PT(675,30,"e")
- '0.003004627086'
- >>> "%.12f" % _Backward3x_v_PT(671,26,"f")
- '0.005019029401'
- >>> "%.12f" % _Backward3x_v_PT(690,30,"f")
- '0.004656470142'
- >>> "%.12f" % _Backward3x_v_PT(649,23.6,"g")
- '0.002163198378'
- >>> "%.12f" % _Backward3x_v_PT(650,24,"g")
- '0.002166044161'
- >>> "%.12f" % _Backward3x_v_PT(652,23.6,"h")
- '0.002651081407'
- >>> "%.12f" % _Backward3x_v_PT(654,24,"h")
- '0.002967802335'
- >>> "%.12f" % _Backward3x_v_PT(653,23.6,"i")
- '0.003273916816'
- >>> "%.12f" % _Backward3x_v_PT(655,24,"i")
- '0.003550329864'
- >>> "%.12f" % _Backward3x_v_PT(655,23.5,"j")
- '0.004545001142'
- >>> "%.12f" % _Backward3x_v_PT(660,24,"j")
- '0.005100267704'
- >>> "%.12f" % _Backward3x_v_PT(660,23,"k")
- '0.006109525997'
- >>> "%.12f" % _Backward3x_v_PT(670,24,"k")
- '0.006427325645'
- >>> "%.12f" % _Backward3x_v_PT(646,22.6,"l")
- '0.002117860851'
- >>> "%.12f" % _Backward3x_v_PT(646,23,"l")
- '0.002062374674'
- >>> "%.12f" % _Backward3x_v_PT(648.6,22.6,"m")
- '0.002533063780'
- >>> "%.12f" % _Backward3x_v_PT(649.3,22.8,"m")
- '0.002572971781'
- >>> "%.12f" % _Backward3x_v_PT(649,22.6,"n")
- '0.002923432711'
- >>> "%.12f" % _Backward3x_v_PT(649.7,22.8,"n")
- '0.002913311494'
- >>> "%.12f" % _Backward3x_v_PT(649.1,22.6,"o")
- '0.003131208996'
- >>> "%.12f" % _Backward3x_v_PT(649.9,22.8,"o")
- '0.003221160278'
- >>> "%.12f" % _Backward3x_v_PT(649.4,22.6,"p")
- '0.003715596186'
- >>> "%.12f" % _Backward3x_v_PT(650.2,22.8,"p")
- '0.003664754790'
- >>> "%.12f" % _Backward3x_v_PT(640,21.1,"q")
- '0.001970999272'
- >>> "%.12f" % _Backward3x_v_PT(643,21.8,"q")
- '0.002043919161'
- >>> "%.12f" % _Backward3x_v_PT(644,21.1,"r")
- '0.005251009921'
- >>> "%.12f" % _Backward3x_v_PT(648,21.8,"r")
- '0.005256844741'
- >>> "%.12f" % _Backward3x_v_PT(635,19.1,"s")
- '0.001932829079'
- >>> "%.12f" % _Backward3x_v_PT(638,20,"s")
- '0.001985387227'
- >>> "%.12f" % _Backward3x_v_PT(626,17,"t")
- '0.008483262001'
- >>> "%.12f" % _Backward3x_v_PT(640,20,"t")
- '0.006227528101'
- >>> "%.12f" % _Backward3x_v_PT(644.6,21.5,"u")
- '0.002268366647'
- >>> "%.12f" % _Backward3x_v_PT(646.1,22,"u")
- '0.002296350553'
- >>> "%.12f" % _Backward3x_v_PT(648.6,22.5,"v")
- '0.002832373260'
- >>> "%.12f" % _Backward3x_v_PT(647.9,22.3,"v")
- '0.002811424405'
- >>> "%.12f" % _Backward3x_v_PT(647.5,22.15,"w")
- '0.003694032281'
- >>> "%.12f" % _Backward3x_v_PT(648.1,22.3,"w")
- '0.003622226305'
- >>> "%.12f" % _Backward3x_v_PT(648,22.11,"x")
- '0.004528072649'
- >>> "%.12f" % _Backward3x_v_PT(649,22.3,"x")
- '0.004556905799'
- >>> "%.12f" % _Backward3x_v_PT(646.84,22,"y")
- '0.002698354719'
- >>> "%.12f" % _Backward3x_v_PT(647.05,22.064,"y")
- '0.002717655648'
- >>> "%.12f" % _Backward3x_v_PT(646.89,22,"z")
- '0.003798732962'
- >>> "%.12f" % _Backward3x_v_PT(647.15,22.064,"z")
- '0.003701940009'
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+ x : char
+ Region 3 subregion code
+
+ Returns
+ -------
+ v : float
+ Specific volume [m³/kg]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations for Specific
+ Volume as a Function of Pressure and Temperature v(p,T) for Region 3 of the
+ IAPWS Industrial Formulation 1997 for the Thermodynamic Properties of Water
+ and Steam, http://www.iapws.org/relguide/Supp-VPT3-2016.pdf, Eq. 4-5
+
+ Examples
+ --------
+ >>> _Backward3x_v_PT(630,50,"a")
+ 0.001470853100
+ >>> _Backward3x_v_PT(670,80,"a")
+ 0.001503831359
+ >>> _Backward3x_v_PT(710,50,"b")
+ 0.002204728587
+ >>> _Backward3x_v_PT(750,80,"b")
+ 0.001973692940
+ >>> _Backward3x_v_PT(630,20,"c")
+ 0.001761696406
+ >>> _Backward3x_v_PT(650,30,"c")
+ 0.001819560617
+ >>> _Backward3x_v_PT(656,26,"d")
+ 0.002245587720
+ >>> _Backward3x_v_PT(670,30,"d")
+ 0.002506897702
+ >>> _Backward3x_v_PT(661,26,"e")
+ 0.002970225962
+ >>> _Backward3x_v_PT(675,30,"e")
+ 0.003004627086
+ >>> _Backward3x_v_PT(671,26,"f")
+ 0.005019029401
+ >>> _Backward3x_v_PT(690,30,"f")
+ 0.004656470142
+ >>> _Backward3x_v_PT(649,23.6,"g")
+ 0.002163198378
+ >>> _Backward3x_v_PT(650,24,"g")
+ 0.002166044161
+ >>> _Backward3x_v_PT(652,23.6,"h")
+ 0.002651081407
+ >>> _Backward3x_v_PT(654,24,"h")
+ 0.002967802335
+ >>> _Backward3x_v_PT(653,23.6,"i")
+ 0.003273916816
+ >>> _Backward3x_v_PT(655,24,"i")
+ 0.003550329864
+ >>> _Backward3x_v_PT(655,23.5,"j")
+ 0.004545001142
+ >>> _Backward3x_v_PT(660,24,"j")
+ 0.005100267704
+ >>> _Backward3x_v_PT(660,23,"k")
+ 0.006109525997
+ >>> _Backward3x_v_PT(670,24,"k")
+ 0.006427325645
+ >>> _Backward3x_v_PT(646,22.6,"l")
+ 0.002117860851
+ >>> _Backward3x_v_PT(646,23,"l")
+ 0.002062374674
+ >>> _Backward3x_v_PT(648.6,22.6,"m")
+ 0.002533063780
+ >>> _Backward3x_v_PT(649.3,22.8,"m")
+ 0.002572971781
+ >>> _Backward3x_v_PT(649,22.6,"n")
+ 0.002923432711
+ >>> _Backward3x_v_PT(649.7,22.8,"n")
+ 0.002913311494
+ >>> _Backward3x_v_PT(649.1,22.6,"o")
+ 0.003131208996
+ >>> _Backward3x_v_PT(649.9,22.8,"o")
+ 0.003221160278
+ >>> _Backward3x_v_PT(649.4,22.6,"p")
+ 0.003715596186
+ >>> _Backward3x_v_PT(650.2,22.8,"p")
+ 0.003664754790
+ >>> _Backward3x_v_PT(640,21.1,"q")
+ 0.001970999272
+ >>> _Backward3x_v_PT(643,21.8,"q")
+ 0.002043919161
+ >>> _Backward3x_v_PT(644,21.1,"r")
+ 0.005251009921
+ >>> _Backward3x_v_PT(648,21.8,"r")
+ 0.005256844741
+ >>> _Backward3x_v_PT(635,19.1,"s")
+ 0.001932829079
+ >>> _Backward3x_v_PT(638,20,"s")
+ 0.001985387227
+ >>> _Backward3x_v_PT(626,17,"t")
+ 0.008483262001
+ >>> _Backward3x_v_PT(640,20,"t")
+ 0.006227528101
+ >>> _Backward3x_v_PT(644.6,21.5,"u")
+ 0.002268366647
+ >>> _Backward3x_v_PT(646.1,22,"u")
+ 0.002296350553
+ >>> _Backward3x_v_PT(648.6,22.5,"v")
+ 0.002832373260
+ >>> _Backward3x_v_PT(647.9,22.3,"v")
+ 0.002811424405
+ >>> _Backward3x_v_PT(647.5,22.15,"w")
+ 0.003694032281
+ >>> _Backward3x_v_PT(648.1,22.3,"w")
+ 0.003622226305
+ >>> _Backward3x_v_PT(648,22.11,"x")
+ 0.004528072649
+ >>> _Backward3x_v_PT(649,22.3,"x")
+ 0.004556905799
+ >>> _Backward3x_v_PT(646.84,22,"y")
+ 0.002698354719
+ >>> _Backward3x_v_PT(647.05,22.064,"y")
+ 0.002717655648
+ >>> _Backward3x_v_PT(646.89,22,"z")
+ 0.003798732962
+ >>> _Backward3x_v_PT(647.15,22.064,"z")
+ 0.003701940009
"""
par = {
- "a": [0.0024, 100, 760, 30, 0.085, 0.817, 1, 1, 1],
- "b": [0.0041, 100, 860, 32, 0.280, 0.779, 1, 1, 1],
- "c": [0.0022, 40, 690, 35, 0.259, 0.903, 1, 1, 1],
- "d": [0.0029, 40, 690, 38, 0.559, 0.939, 1, 1, 4],
- "e": [0.0032, 40, 710, 29, 0.587, 0.918, 1, 1, 1],
- "f": [0.0064, 40, 730, 42, 0.587, 0.891, 0.5, 1, 4],
- "g": [0.0027, 25, 660, 38, 0.872, 0.971, 1, 1, 4],
- "h": [0.0032, 25, 660, 29, 0.898, 0.983, 1, 1, 4],
- "i": [0.0041, 25, 660, 42, 0.910, 0.984, 0.5, 1, 4],
- "j": [0.0054, 25, 670, 29, 0.875, 0.964, 0.5, 1, 4],
- "k": [0.0077, 25, 680, 34, 0.802, 0.935, 1, 1, 1],
- "l": [0.0026, 24, 650, 43, 0.908, 0.989, 1, 1, 4],
- "m": [0.0028, 23, 650, 40, 1.000, 0.997, 1, 0.25, 1],
- "n": [0.0031, 23, 650, 39, 0.976, 0.997, None, None, None],
- "o": [0.0034, 23, 650, 24, 0.974, 0.996, 0.5, 1, 1],
- "p": [0.0041, 23, 650, 27, 0.972, 0.997, 0.5, 1, 1],
- "q": [0.0022, 23, 650, 24, 0.848, 0.983, 1, 1, 4],
- "r": [0.0054, 23, 650, 27, 0.874, 0.982, 1, 1, 1],
- "s": [0.0022, 21, 640, 29, 0.886, 0.990, 1, 1, 4],
- "t": [0.0088, 20, 650, 33, 0.803, 1.020, 1, 1, 1],
- "u": [0.0026, 23, 650, 38, 0.902, 0.988, 1, 1, 1],
- "v": [0.0031, 23, 650, 39, 0.960, 0.995, 1, 1, 1],
- "w": [0.0039, 23, 650, 35, 0.959, 0.995, 1, 1, 4],
- "x": [0.0049, 23, 650, 36, 0.910, 0.988, 1, 1, 1],
- "y": [0.0031, 22, 650, 20, 0.996, 0.994, 1, 1, 4],
- "z": [0.0038, 22, 650, 23, 0.993, 0.994, 1, 1, 4],
+ "a": [0.0024, 100, 760, 0.085, 0.817, 1, 1, 1],
+ "b": [0.0041, 100, 860, 0.280, 0.779, 1, 1, 1],
+ "c": [0.0022, 40, 690, 0.259, 0.903, 1, 1, 1],
+ "d": [0.0029, 40, 690, 0.559, 0.939, 1, 1, 4],
+ "e": [0.0032, 40, 710, 0.587, 0.918, 1, 1, 1],
+ "f": [0.0064, 40, 730, 0.587, 0.891, 0.5, 1, 4],
+ "g": [0.0027, 25, 660, 0.872, 0.971, 1, 1, 4],
+ "h": [0.0032, 25, 660, 0.898, 0.983, 1, 1, 4],
+ "i": [0.0041, 25, 660, 0.910, 0.984, 0.5, 1, 4],
+ "j": [0.0054, 25, 670, 0.875, 0.964, 0.5, 1, 4],
+ "k": [0.0077, 25, 680, 0.802, 0.935, 1, 1, 1],
+ "l": [0.0026, 24, 650, 0.908, 0.989, 1, 1, 4],
+ "m": [0.0028, 23, 650, 1.000, 0.997, 1, 0.25, 1],
+ "n": [0.0031, 23, 650, 0.976, 0.997, None, None, None],
+ "o": [0.0034, 23, 650, 0.974, 0.996, 0.5, 1, 1],
+ "p": [0.0041, 23, 650, 0.972, 0.997, 0.5, 1, 1],
+ "q": [0.0022, 23, 650, 0.848, 0.983, 1, 1, 4],
+ "r": [0.0054, 23, 650, 0.874, 0.982, 1, 1, 1],
+ "s": [0.0022, 21, 640, 0.886, 0.990, 1, 1, 4],
+ "t": [0.0088, 20, 650, 0.803, 1.020, 1, 1, 1],
+ "u": [0.0026, 23, 650, 0.902, 0.988, 1, 1, 1],
+ "v": [0.0031, 23, 650, 0.960, 0.995, 1, 1, 1],
+ "w": [0.0039, 23, 650, 0.959, 0.995, 1, 1, 4],
+ "x": [0.0049, 23, 650, 0.910, 0.988, 1, 1, 1],
+ "y": [0.0031, 22, 650, 0.996, 0.994, 1, 1, 4],
+ "z": [0.0038, 22, 650, 0.993, 0.994, 1, 1, 4],
}
I = {
@@ -2243,24 +3538,44 @@ def _Backward3x_v_PT(T, P, x):
I = I[x]
J = J[x]
n = n[x]
- v_, P_, T_, N, a, b, c, d, e = par[x]
+ v_, P_, T_, a, b, c, d, e = par[x]
Pr = P/P_
Tr = T/T_
suma = 0
if x == "n":
- for i in range(N):
- suma += n[i]*(Pr-a)**I[i]*(Tr-b)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (Pr-a)**i * (Tr-b)**j
return v_*exp(suma)
else:
- for i in range(N):
- suma += n[i]*(Pr-a)**(c*I[i])*(Tr-b)**(J[i]*d)
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (Pr-a)**(c*i) * (Tr-b)**(j*d)
return v_*suma**e
# Region 4
def _Region4(P, x):
- """Basic equation for region 4"""
+ """Basic equation for region 4
+
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ x : float
+ Vapor quality [-]
+
+ Returns
+ -------
+ prop : dict
+ Dict with calculated properties. The available properties are:
+
+ * T: Saturated temperature [K]
+ * P: Saturated pressure [MPa]
+ * x: Vapor quality [-]
+ * v: Specific volume [m³/kg]
+ * h: Specific enthalpy [kJ/kg]
+ * s: Specific entropy [kJ/kgK]
+ """
T = _TSat_P(P)
if T > 623.15:
rhol = 1./_Backward3_sat_v_P(P, T, 0)
@@ -2282,8 +3597,6 @@ def _Region4(P, x):
propiedades["w"] = None
propiedades["alfav"] = None
propiedades["kt"] = None
- propiedades["alfap"] = None
- propiedades["betap"] = None
propiedades["region"] = 4
propiedades["x"] = x
return propiedades
@@ -2292,12 +3605,34 @@ def _Region4(P, x):
def _Backward4_T_hs(h, s):
"""Backward equation for region 4, T=f(h,s)
- >>> "%.7f" % _Backward4_T_hs(1800,5.3)
- '346.8475498'
- >>> "%.7f" % _Backward4_T_hs(2400,6.0)
- '425.1373305'
- >>> "%.7f" % _Backward4_T_hs(2500,5.5)
- '522.5579013'
+ Parameters
+ ----------
+ h : float
+ Specific enthalpy [kJ/kg]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ T : float
+ Temperature [K]
+
+ References
+ ----------
+ IAPWS, Revised Supplementary Release on Backward Equations p(h,s) for
+ Region 3, Equations as a Function of h and s for the Region Boundaries, and
+ an Equation Tsat(h,s) for Region 4 of the IAPWS Industrial Formulation 1997
+ for the Thermodynamic Properties of Water and Steam,
+ http://www.iapws.org/relguide/Supp-phs3-2014.pdf. Eq 9
+
+ Examples
+ --------
+ >>> _Backward4_T_hs(1800,5.3)
+ 346.8475498
+ >>> _Backward4_T_hs(2400,6.0)
+ 425.1373305
+ >>> _Backward4_T_hs(2500,5.5)
+ 522.5579013
"""
I = [0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6,
8, 10, 10, 12, 14, 14, 16, 16, 18, 18, 18, 20, 28]
@@ -2319,8 +3654,8 @@ def _Backward4_T_hs(h, s):
nu = h/2800
sigma = s/9.2
suma = 0
- for i in range(36):
- suma += n[i]*(nu-0.119)**I[i]*(sigma-1.07)**J[i]
+ for i, j, ni in zip(I, J, n):
+ suma += ni * (nu-0.119)**i * (sigma-1.07)**j
return 550*suma
@@ -2328,24 +3663,53 @@ def _Backward4_T_hs(h, s):
def _Region5(T, P):
"""Basic equation for region 5
- >>> "%.8f" % _Region5(1500,0.5)["v"]
- '1.38455090'
- >>> "%.5f" % _Region5(1500,0.5)["h"]
- '5219.76855'
- >>> "%.5f" % (_Region5(1500,0.5)["h"]-500*_Region5(1500,0.5)["v"], )
- '4527.49310'
- >>> "%.8f" % _Region5(1500,30)["s"]
- '7.72970133'
- >>> "%.8f" % _Region5(1500,30)["cp"]
- '2.72724317'
- >>> "%.8f" % _Region5(1500,30)["cv"]
- '2.19274829'
- >>> "%.5f" % _Region5(2000,30)["w"]
- '1067.36948'
- >>> "%.12f" % _Region5(2000,30)["alfav"]
- '0.000508830641'
- >>> "%.10f" % _Region5(2000,30)["kt"]
- '0.0329193892'
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ prop : dict
+ Dict with calculated properties. The available properties are:
+
+ * v: Specific volume [m³/kg]
+ * h: Specific enthalpy [kJ/kg]
+ * s: Specific entropy [kJ/kgK]
+ * cp: Specific isobaric heat capacity [kJ/kgK]
+ * cv: Specific isocoric heat capacity [kJ/kgK]
+ * w: Speed of sound [m/s]
+ * alfav: Cubic expansion coefficient [1/K]
+ * kt: Isothermal compressibility [1/MPa]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 32-34
+
+ Examples
+ --------
+ >>> _Region5(1500,0.5)["v"]
+ 1.38455090
+ >>> _Region5(1500,0.5)["h"]
+ 5219.76855
+ >>> _Region5(1500,0.5)["h"]-500*_Region5(1500,0.5)["v"]
+ 4527.49310
+ >>> _Region5(1500,30)["s"]
+ 7.72970133
+ >>> _Region5(1500,30)["cp"]
+ 2.72724317
+ >>> _Region5(1500,30)["cv"]
+ 2.19274829
+ >>> _Region5(2000,30)["w"]
+ 1067.36948
+ >>> _Region5(2000,30)["alfav"]
+ 0.000508830641
+ >>> _Region5(2000,30)["kt"]
+ 0.0329193892
"""
Tr = 1000/T
Pr = P/1
@@ -2357,13 +3721,13 @@ def _Region5(T, P):
nr = [0.15736404855259e-2, 0.90153761673944e-3, -0.50270077677648e-2,
0.22440037409485e-5, -0.41163275453471e-5, 0.37919454822955e-7]
gr = grp = grpp = grt = grtt = grpt = 0
- for i in range(6):
- gr += nr[i]*Pr**Ir[i]*Tr**Jr[i]
- grp += nr[i]*Ir[i]*Pr**(Ir[i]-1)*Tr**Jr[i]
- grpp += nr[i]*Ir[i]*(Ir[i]-1)*Pr**(Ir[i]-2)*Tr**Jr[i]
- grt += nr[i]*Pr**Ir[i]*Jr[i]*Tr**(Jr[i]-1)
- grtt += nr[i]*Pr**Ir[i]*Jr[i]*(Jr[i]-1)*Tr**(Jr[i]-2)
- grpt += nr[i]*Ir[i]*Pr**(Ir[i]-1)*Jr[i]*Tr**(Jr[i]-1)
+ for i, j, ni in zip(Ir, Jr, nr):
+ gr += ni * Pr**i * Tr**j
+ grp += ni*i * Pr**(i-1) * Tr**j
+ grpp += ni*i*(i-1) * Pr**(i-2) * Tr**j
+ grt += ni*j * Pr**i * Tr**(j-1)
+ grtt += ni*j*(j-1) * Pr**i * Tr**(j-2)
+ grpt += ni*i*j * Pr**(i-1) * Tr**(j-1)
propiedades = {}
propiedades["T"] = T
@@ -2384,7 +3748,33 @@ def _Region5(T, P):
def Region5_cp0(Tr, Pr):
- """Ideal properties for Region 5"""
+ """Ideal properties for Region 5
+
+ Parameters
+ ----------
+ Tr : float
+ Reduced temperature [-]
+ Pr : float
+ Reduced pressure [-]
+
+ Returns
+ -------
+ prop : array
+ Array with ideal Gibbs energy partial derivatives:
+
+ * g: Ideal Specific Gibbs energy [kJ/kg]
+ * gp: [∂g/∂P]T
+ * gpp: [∂²g/∂P²]T
+ * gt: [∂g/∂T]P
+ * gtt: [∂²g/∂T²]P
+ * gpt: [∂²g/∂T∂P]
+
+ References
+ ----------
+ IAPWS, Revised Release on the IAPWS Industrial Formulation 1997 for the
+ Thermodynamic Properties of Water and Steam August 2007,
+ http://www.iapws.org/relguide/IF97-Rev.html, Eq 33
+ """
Jo = [0, 1, -3, -2, -1, 2]
no = [-0.13179983674201e2, 0.68540841634434e1, -0.24805148933466e-1,
0.36901534980333, -0.31161318213925e1, -0.32961626538917]
@@ -2392,17 +3782,36 @@ def Region5_cp0(Tr, Pr):
gop = Pr**-1
gopp = -Pr**-2
got = gott = gopt = 0
- for i in range(6):
- go += no[i]*Tr**Jo[i]
- got += no[i]*Jo[i]*Tr**(Jo[i]-1)
- gott += no[i]*Jo[i]*(Jo[i]-1)*Tr**(Jo[i]-2)
+ for j, ni in zip(Jo, no):
+ go += ni * Tr**j
+ got += ni*j * Tr**(j-1)
+ gott += ni*j*(j-1) * Tr**(j-2)
return go, gop, gopp, got, gott, gopt
# Region definitions
def _Bound_TP(T, P):
- """Region definition for input T and P"""
+ """Region definition for input T and P
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ region : float
+ IAPWS-97 region code
+
+ References
+ ----------
+ Wagner, W; Kretzschmar, H-J: International Steam Tables: Properties of
+ Water and Steam Based on the Industrial Formulation IAPWS-IF97; Springer,
+ 2008; doi: 10.1007/978-3-540-74234-0. Fig. 2.3
+ """
region = None
if 1073.15 < T <= 2273.15 and Pmin <= P <= 50:
region = 5
@@ -2416,15 +3825,34 @@ def _Bound_TP(T, P):
T_b23 = _t_P(P)
if 273.15 <= T <= 623.15:
region = 1
- elif T_b23 <= T <= 1073.15:
- region = 2
elif 623.15 < T < T_b23:
region = 3
+ elif T_b23 <= T <= 1073.15:
+ region = 2
return region
def _Bound_Ph(P, h):
- """Region definition for input P y h"""
+ """Region definition for input P y h
+
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ h : float
+ Specific enthalpy [kJ/kg]
+
+ Returns
+ -------
+ region : float
+ IAPWS-97 region code
+
+ References
+ ----------
+ Wagner, W; Kretzschmar, H-J: International Steam Tables: Properties of
+ Water and Steam Based on the Industrial Formulation IAPWS-IF97; Springer,
+ 2008; doi: 10.1007/978-3-540-74234-0. Fig. 2.5
+ """
region = None
if Pmin <= P <= Ps_623:
h14 = _Region1(_TSat_P(P), P)["h"]
@@ -2449,7 +3877,10 @@ def _Bound_Ph(P, h):
if hmin <= h <= h13:
region = 1
elif h13 < h < h32:
- p34 = _PSat_h(h)
+ try:
+ p34 = _PSat_h(h)
+ except NotImplementedError:
+ p34 = Pc
if P < p34:
region = 4
else:
@@ -2476,7 +3907,26 @@ def _Bound_Ph(P, h):
def _Bound_Ps(P, s):
- """Region definition for input P and s"""
+ """Region definition for input P and s
+
+ Parameters
+ ----------
+ P : float
+ Pressure [MPa]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ region : float
+ IAPWS-97 region code
+
+ References
+ ----------
+ Wagner, W; Kretzschmar, H-J: International Steam Tables: Properties of
+ Water and Steam Based on the Industrial Formulation IAPWS-IF97; Springer,
+ 2008; doi: 10.1007/978-3-540-74234-0. Fig. 2.9
+ """
region = None
if Pmin <= P <= Ps_623:
smin = _Region1(273.15, P)["s"]
@@ -2501,7 +3951,10 @@ def _Bound_Ps(P, s):
if smin <= s <= s13:
region = 1
elif s13 < s < s32:
- p34 = _PSat_s(s)
+ try:
+ p34 = _PSat_s(s)
+ except NotImplementedError:
+ p34 = Pc
if P < p34:
region = 4
else:
@@ -2528,95 +3981,164 @@ def _Bound_Ps(P, s):
def _Bound_hs(h, s):
- """Region definition for input h and s"""
+ """Region definition for input h and s
+
+ Parameters
+ ----------
+ h : float
+ Specific enthalpy [kJ/kg]
+ s : float
+ Specific entropy [kJ/kgK]
+
+ Returns
+ -------
+ region : float
+ IAPWS-97 region code
+
+ References
+ ----------
+ Wagner, W; Kretzschmar, H-J: International Steam Tables: Properties of
+ Water and Steam Based on the Industrial Formulation IAPWS-IF97; Springer,
+ 2008; doi: 10.1007/978-3-540-74234-0. Fig. 2.14
+ """
region = None
- smin = _Region1(273.15, 100)["s"]
- hmin = _Region1(273.15, 100)["h"]
s13 = _Region1(623.15, 100)["s"]
s13s = _Region1(623.15, Ps_623)["s"]
- smax = _Region2(1073.15, _PSat_T(273.15))["s"]
- hmax = _Region2(1073.15, _PSat_T(273.15))["h"]
+ sTPmax = _Region2(1073.15, 100)["s"]
+ s2ab = _Region2(1073.15, 4)["s"]
- s4l = _Region1(273.15, Pmin)["s"]
- h4l = _Region1(273.15, Pmin)["h"]
- s4v = _Region2(273.15, Pmin)["s"]
- h4v = _Region2(273.15, Pmin)["h"]
+ # Left point in h-s plot
+ smin = _Region1(273.15, 100)["s"]
+ hmin = _Region1(273.15, Pmin)["h"]
+
+ # Right point in h-s plot
+ _Pmax = _Region2(1073.15, Pmin)
+ hmax = _Pmax["h"]
+ smax = _Pmax["s"]
+
+ # Region 4 left and right point
+ _sL = _Region1(273.15, Pmin)
+ h4l = _sL["h"]
+ s4l = _sL["s"]
+ _sV = _Region2(273.15, Pmin)
+ h4v = _sV["h"]
+ s4v = _sV["s"]
+
+ if smin <= s <= s13:
+ hmin = h4l+(s-s4l)/(s4v-s4l)*(h4v-h4l)
+ hs = _h1_s(s)
+ T = _Backward1_T_Ps(100, s)-0.0218
+ hmax = _Region1(T, 100)["h"]
+ if hmin <= h < hs:
+ region = 4
+ elif hs <= h <= hmax:
+ region = 1
- h23max = _Region2(863.15, 100)["h"]
- h23min = _Region2(623.15, Ps_623)["h"]
+ elif s13 < s <= s13s:
+ hmin = h4l+(s-s4l)/(s4v-s4l)*(h4v-h4l)
+ hs = _h1_s(s)
+ h13 = _h13_s(s)
+ v = _Backward3_v_Ps(100, s)*(1+9.6e-5)
+ T = _Backward3_T_Ps(100, s)-0.0248
+ hmax = _Region3(1/v, T)["h"]
+ if hmin <= h < hs:
+ region = 4
+ elif hs <= h < h13:
+ region = 1
+ elif h13 <= h <= hmax:
+ region = 3
- if h <= hmax:
- if smin <= s <= s13:
- P = _Backward1_P_hs(h, s)
- T = _Backward1_T_Ph(P, h)
- if T-0.0218 >= 273.15 and Pt <= P <= 100:
- hs = _h1_s(s)
- if h >= hs:
- region = 1
- elif hmin <= h < hs:
- region = 4
- elif s13 < s <= s13s:
- hs = _h1_s(s)
- h13 = _h13_s(s)
- hmin4 = h4l+(s-s4l)/(s4v-s4l)*(h4v-h4l)
- if h > h13 and _Backward3_P_hs(h, s) <= 100:
- region = 3
- elif hs <= h <= h13:
- region = 1
- elif hmin4 <= h < hs:
- region = 4
- elif s13s < s <= sc:
- hs = _h3a_s(s)
- hmin4 = h4l+(s-s4l)/(s4v-s4l)*(h4v-h4l)
- if h >= hs and _Backward3_P_hs(h, s) <= 100:
- region = 3
- elif hmin4 <= h < hs:
- region = 4
- elif sc < s < 5.049096828:
- hs = _h2c3b_s(s)
- hmin4 = h4l+(s-s4l)/(s4v-s4l)*(h4v-h4l)
- if h >= hs and _Backward3_P_hs(h, s) <= 100:
- region = 3
- elif hmin4 <= h < hs:
- region = 4
- elif 5.049096828 <= s < 5.260578707:
- hs = _h2c3b_s(s)
- hmin4 = h4l+(s-s4l)/(s4v-s4l)*(h4v-h4l)
- if h23max <= h and _Backward2_P_hs(h, s) <= 100:
+ elif s13s < s <= sc:
+ hmin = h4l+(s-s4l)/(s4v-s4l)*(h4v-h4l)
+ hs = _h3a_s(s)
+ v = _Backward3_v_Ps(100, s)*(1+9.6e-5)
+ T = _Backward3_T_Ps(100, s)-0.0248
+ hmax = _Region3(1/v, T)["h"]
+ if hmin <= h < hs:
+ region = 4
+ elif hs <= h <= hmax:
+ region = 3
+
+ elif sc < s < 5.049096828:
+ hmin = h4l+(s-s4l)/(s4v-s4l)*(h4v-h4l)
+ hs = _h2c3b_s(s)
+ v = _Backward3_v_Ps(100, s)*(1+9.6e-5)
+ T = _Backward3_T_Ps(100, s)-0.0248
+ hmax = _Region3(1/v, T)["h"]
+ if hmin <= h < hs:
+ region = 4
+ elif hs <= h <= hmax:
+ region = 3
+
+ elif 5.049096828 <= s < 5.260578707:
+ # Specific zone with 2-3 boundary in s shape
+ hmin = h4l+(s-s4l)/(s4v-s4l)*(h4v-h4l)
+ hs = _h2c3b_s(s)
+ h23max = _Region2(863.15, 100)["h"]
+ h23min = _Region2(623.15, Ps_623)["h"]
+ T = _Backward2_T_Ps(100, s)-0.019
+ hmax = _Region2(T, 100)["h"]
+
+ if hmin <= h < hs:
+ region = 4
+ elif hs <= h < h23min:
+ region = 3
+ elif h23min <= h < h23max:
+ if _Backward2c_P_hs(h, s) <= _P23_T(_t_hs(h, s)):
region = 2
- elif h23min <= h < h23max:
- if _Backward2c_P_hs(h, s) <= _P23_T(_t_hs(h, s)):
- region = 2
- else:
- region = 3
- elif hs <= h < h23min:
+ else:
region = 3
- elif hmin4 <= h < hs:
- region = 4
- elif 5.260578707 <= s < 5.85:
- hs = _h2c3b_s(s)
- hmin4 = h4l+(s-s4l)/(s4v-s4l)*(h4v-h4l)
- if hs <= h and _Backward2_P_hs(h, s) <= 100:
- region = 2
- elif hmin4 <= h < hs:
- region = 4
- elif 5.85 <= s < s4v:
- hs = _h2ab_s(s)
- hmin4 = h4l+(s-s4l)/(s4v-s4l)*(h4v-h4l)
- P = _Backward2_P_hs(h, s)
- if P <= 100:
- T = _Backward2_T_Ph(P, h)
- h2max = _Region2(1073.15, P)["h"]
- if hs <= h <= h2max and Pmin <= P <= 100 and T <= 1073.15:
- region = 2
- elif hmin4 <= h < hs:
- region = 4
- elif s4v <= s <= smax:
- P = _Backward2a_P_hs(h, s)
- T = _Backward2a_T_Ph(P, h)
- if P >= Pmin and T <= 1073.15:
- region = 2
+ elif h23max <= h <= hmax:
+ region = 2
+
+ elif 5.260578707 <= s < 5.85:
+ hmin = h4l+(s-s4l)/(s4v-s4l)*(h4v-h4l)
+ hs = _h2c3b_s(s)
+ T = _Backward2_T_Ps(100, s)-0.019
+ hmax = _Region2(T, 100)["h"]
+ if hmin <= h < hs:
+ region = 4
+ elif hs <= h <= hmax:
+ region = 2
+
+ elif 5.85 <= s < sTPmax:
+ hmin = h4l+(s-s4l)/(s4v-s4l)*(h4v-h4l)
+ hs = _h2ab_s(s)
+ T = _Backward2_T_Ps(100, s)-0.019
+ hmax = _Region2(T, 100)["h"]
+ if hmin <= h < hs:
+ region = 4
+ elif hs <= h <= hmax:
+ region = 2
+ elif sTPmax <= s < s2ab:
+ hmin = h4l+(s-s4l)/(s4v-s4l)*(h4v-h4l)
+ hs = _h2ab_s(s)
+ P = _Backward2_P_hs(h, s)
+ hmax = _Region2(1073.15, P)["h"]
+ if hmin <= h < hs:
+ region = 4
+ elif hs <= h <= hmax:
+ region = 2
+
+ elif s2ab <= s < s4v:
+ hmin = h4l+(s-s4l)/(s4v-s4l)*(h4v-h4l)
+ hs = _h2ab_s(s)
+ P = _Backward2_P_hs(h, s)
+ hmax = _Region2(1073.15, P)["h"]
+ if hmin <= h < hs:
+ region = 4
+ elif hs <= h <= hmax:
+ region = 2
+
+ elif s4v <= s <= smax:
+ hmin = _Region2(273.15, Pmin)["h"]
+ P = _Backward2a_P_hs(h, s)
+ hmax = _Region2(1073.15, P)["h"]
+ if Pmin <= P <= 100 and hmin <= h <= hmax:
+ region = 2
+
+ # Check region 5
if not region and \
_Region5(1073.15, 50)["s"] < s <= _Region5(2273.15, Pmin)["s"] \
and _Region5(1073.15, 50)["h"] < h <= _Region5(2273.15, Pmin)["h"]:
@@ -2631,7 +4153,29 @@ def _Bound_hs(h, s):
def prop0(T, P):
- """Ideal gas properties"""
+ """Ideal gas properties
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+
+ Returns
+ -------
+ prop : dict
+ Dict with calculated properties. The available properties are:
+
+ * v: Specific volume [m³/kg]
+ * h: Specific enthalpy [kJ/kg]
+ * s: Specific entropy [kJ/kgK]
+ * cp: Specific isobaric heat capacity [kJ/kgK]
+ * cv: Specific isocoric heat capacity [kJ/kgK]
+ * w: Speed of sound [m/s]
+ * alfav: Cubic expansion coefficient [1/K]
+ * kt: Isothermal compressibility [1/MPa]
+ """
if T <= 1073.15:
Tr = 540/T
Pr = P/1.
@@ -2655,91 +4199,97 @@ def prop0(T, P):
class IAPWS97(object):
- """Class to model a state for liquid water or steam with the IAPWS-IF97
-
- Incoming properties::
- T - Temperature, K
- P - Pressure, MPa
- h - Specific enthalpy, kJ/kg
- s - Specific entropy, kJ/kg·K
- x - Quality
-
- Optional:
- l - Wavelength of light, for refractive index
-
+ """Class to model a state of liquid water or steam with the IAPWS-IF97
+
+ Parameters
+ ----------
+ T : float
+ Temperature [K]
+ P : float
+ Pressure [MPa]
+ h : float
+ Specific enthalpy [kJ/kg]
+ s : float
+ Specific entropy [kJ/kgK]
+ x : float
+ Vapor quality [-]
+ l : float, optional
+ Wavelength of light, for refractive index [nm]
+
+ Notes
+ -----
Definitions options:
- T, P Not valid for two-phases region
- P, h
- P, s
- h, s
- T, x Only for two-phases region
- P, x Only for two-phases region
-
-
- Properties:
- P - Pressure, MPa
- T - Temperature, K
- g - Specific Gibbs free energy, kJ/kg
- a - Specific Helmholtz free energy, kJ/kg
- v - Specific volume, m³/kg
- r - Density, kg/m³
- h - Specific enthalpy, kJ/kg
- u - Specific internal energy, kJ/kg
- s - Specific entropy, kJ/kg·K
- cp - Specific isobaric heat capacity, kJ/kg·K
- cv - Specific isochoric heat capacity, kJ/kg·K
- Z - Compression factor
- fi - Fugacity coefficient
- f - Fugacity, MPa
-
- gamma - Isoentropic exponent
- alfav - Isobaric cubic expansion coefficient, 1/K
- xkappa - Isothermal compressibility, 1/MPa
- kappas - Adiabatic compresibility, 1/MPa
- alfap - Relative pressure coefficient, 1/K
- betap - Isothermal stress coefficient, kg/m³
- joule - Joule-Thomson coefficient, K/MPa
- deltat - Isothermal throttling coefficient, kJ/kg·MPa
- region - Region
-
- v0 - Ideal specific volume, m³/kg
- u0 - Ideal specific internal energy, kJ/kg
- h0 - Ideal specific enthalpy, kJ/kg
- s0 - Ideal specific entropy, kJ/kg·K
- a0 - Ideal specific Helmholtz free energy, kJ/kg
- g0 - Ideal specific Gibbs free energy, kJ/kg
- cp0 - Ideal specific isobaric heat capacity, kJ/kg·K
- cv0 - Ideal specific isochoric heat capacity, kJ/kg·K
- w0 - Ideal speed of sound, m/s
- gamma0 - Ideal isoentropic exponent
-
- w - Speed of sound, m/s
- mu - Dynamic viscosity, Pa·s
- nu - Kinematic viscosity, m²/s
- k - Thermal conductivity, W/m·K
- alfa - Thermal diffusivity, m²/s
- sigma - Surface tension, N/m
- epsilon - Dielectric constant
- n - Refractive index
- Prandt - Prandtl number
- Pr - Reduced Pressure
- Tr - Reduced Temperature
- Hvap - Vaporization heat, kJ/kg
- Svap - Vaporization entropy, kJ/kg·K
-
- Usage:
+ * T, P: Not valid for two-phases region
+ * P, h
+ * P, s
+ * h, s
+ * T, x: Only for two-phases region
+ * P, x: Only for two-phases region
+
+ Returns
+ -------
+ The calculated instance has the following properties:
+ * P: Pressure [MPa]
+ * T: Temperature [K]
+ * g: Specific Gibbs free energy [kJ/kg]
+ * a: Specific Helmholtz free energy [kJ/kg]
+ * v: Specific volume [m³/kg]
+ * r: Density [kg/m³]
+ * h: Specific enthalpy [kJ/kg]
+ * u: Specific internal energy [kJ/kg]
+ * s: Specific entropy [kJ/kg·K]
+ * cp: Specific isobaric heat capacity [kJ/kg·K]
+ * cv: Specific isochoric heat capacity [kJ/kg·K]
+ * Z: Compression factor [-]
+ * fi: Fugacity coefficient [-]
+ * f: Fugacity [MPa]
+
+ * gamma: Isoentropic exponent [-]
+ * alfav: Isobaric cubic expansion coefficient [1/K]
+ * xkappa: Isothermal compressibility [1/MPa]
+ * kappas: Adiabatic compresibility [1/MPa]
+ * alfap: Relative pressure coefficient [1/K]
+ * betap: Isothermal stress coefficient [kg/m³]
+ * joule: Joule-Thomson coefficient [K/MPa]
+ * deltat: Isothermal throttling coefficient [kJ/kg·MPa]
+ * region: Region
+
+ * v0: Ideal specific volume [m³/kg]
+ * u0: Ideal specific internal energy [kJ/kg]
+ * h0: Ideal specific enthalpy [kJ/kg]
+ * s0: Ideal specific entropy [kJ/kg·K]
+ * a0: Ideal specific Helmholtz free energy [kJ/kg]
+ * g0: Ideal specific Gibbs free energy [kJ/kg]
+ * cp0: Ideal specific isobaric heat capacity [kJ/kg·K]
+ * cv0: Ideal specific isochoric heat capacity [kJ/kg·K]
+ * w0: Ideal speed of sound [m/s]
+ * gamma0: Ideal isoentropic exponent [-]
+
+ * w: Speed of sound [m/s]
+ * mu: Dynamic viscosity [Pa·s]
+ * nu: Kinematic viscosity [m²/s]
+ * k: Thermal conductivity [W/m·K]
+ * alfa: Thermal diffusivity [m²/s]
+ * sigma: Surface tension [N/m]
+ * epsilon: Dielectric constant [-]
+ * n: Refractive index [-]
+ * Prandt: Prandtl number [-]
+ * Pr: Reduced Pressure [-]
+ * Tr: Reduced Temperature [-]
+ * Hvap: Vaporization heat [kJ/kg]
+ * Svap: Vaporization entropy [kJ/kg·K]
+
+ Examples
+ --------
>>> water=IAPWS97(T=170+273.15,x=0.5)
- >>> "%0.4f %0.4f %0.1f %0.2f" %(water.Liquid.cp, water.Vapor.cp, \
- water.Liquid.w, water.Vapor.w)
- '4.3695 2.5985 1418.3 498.78'
+ >>> water.Liquid.cp, water.Vapor.cp, water.Liquid.w, water.Vapor.w
+ 4.3695 2.5985 1418.3 498.78
>>> water=IAPWS97(T=325+273.15,x=0.5)
- >>> "%0.4f %0.8f %0.7f %0.2f %0.2f" %(water.P, water.Liquid.v, \
- water.Vapor.v, water.Liquid.h, water.Vapor.h)
- '12.0505 0.00152830 0.0141887 1493.37 2684.48'
+ >>> water.P, water.Liquid.v, water.Vapor.v, water.Liquid.h, water.Vapor.h
+ 12.0505 0.00152830 0.0141887 1493.37 2684.48
>>> water=IAPWS97(T=50+273.15,P=0.0006112127)
- >>> "%0.4f %0.4f %0.2f %0.3f %0.2f" %(water.cp0, water.cv0, water.h0, \
- water.s0, water.w0)
- '1.8714 1.4098 2594.66 9.471 444.93'
+ >>> water.cp0, water.cv0, water.h0, water.s0, water.w0
+ 1.8714 1.4098 2594.66 9.471 444.93
"""
kwargs = {"T": 0.0,
"P": 0.0,
@@ -2797,11 +4347,14 @@ class IAPWS97(object):
elif region == 2:
propiedades = _Region2(T, P)
elif region == 3:
- vo = _Backward3_v_PT(P, T)
+ if T == Tc and P == Pc:
+ rho = rhoc
+ else:
+ vo = _Backward3_v_PT(P, T)
- def funcion(rho):
- return _Region3(rho, self.kwargs["T"])["P"]-P
- rho = newton(funcion, 1/vo)
+ def funcion(rho):
+ return _Region3(rho, self.kwargs["T"])["P"]-P
+ rho = newton(funcion, 1/vo)
propiedades = _Region3(rho, T)
elif region == 5:
propiedades = _Region5(T, P)
@@ -2915,8 +4468,8 @@ class IAPWS97(object):
propiedades = _Region2(T, P)
elif region == 3:
P = _Backward3_P_hs(h, s)
- vo = _Backward3_v_Ps(P, s)
- To = _Backward3_T_Ps(P, s)
+ vo = _Backward3_v_Ph(P, h)
+ To = _Backward3_T_Ph(P, h)
def funcion(par):
return (_Region3(par[0], par[1])["h"]-h,
@@ -2924,12 +4477,40 @@ class IAPWS97(object):
rho, T = fsolve(funcion, [1/vo, To])
propiedades = _Region3(rho, T)
elif region == 4:
- T = _Backward4_T_hs(h, s)
- P = _PSat_T(T)
- h1 = _Region1(T, P)["h"]
- h2 = _Region2(T, P)["h"]
- x = (h-h1)/(h2-h1)
- propiedades = _Region4(P, x)
+ if round(s-sc, 6) == 0 and round(h-hc, 6) == 0:
+ propiedades = _Region3(rhoc, Tc)
+
+ else:
+ To = _Backward4_T_hs(h, s)
+ if To < 273.15 or To > Tc:
+ To = 300
+
+ def funcion(par):
+ if par[1] < 0:
+ par[1] = 0
+ elif par[1] > 1:
+ par[1] = 1
+ if par[0] < 273.15:
+ par[0] = 273.15
+ elif par[0] > Tc:
+ par[0] = Tc
+
+ Po = _PSat_T(par[0])
+ liquid = _Region1(par[0], Po)
+ vapor = _Region2(par[0], Po)
+ hl = liquid["h"]
+ sl = liquid["s"]
+ hv = vapor["h"]
+ sv = vapor["s"]
+ return (hv*par[1]+hl*(1-par[1])-h,
+ sv*par[1]+sl*(1-par[1])-s)
+ T, x = fsolve(funcion, [To, 0.5])
+ P = _PSat_T(T)
+
+ if Pt <= P < Pc and 0 < x < 1:
+ propiedades = _Region4(P, x)
+ elif Pt <= P <= Ps_623 and x == 0:
+ propiedades = _Region1(T, P)
elif region == 5:
def funcion(par):
return (_Region5(par[0], par[1])["h"]-h,
@@ -2942,42 +4523,45 @@ class IAPWS97(object):
elif self._thermo == "Px":
P, x = args
T = _TSat_P(P)
- if Pt <= P <= Pc and 0 < x < 1:
+ if Pt <= P < Pc and 0 < x < 1:
propiedades = _Region4(P, x)
- elif P > Ps_623 and x in (0, 1):
- rho = 1./_Backward3_sat_v_P(P, T, x)
- propiedades = _Region3(rho, T)
- elif x == 0:
+ elif Pt <= P <= Ps_623 and x == 0:
propiedades = _Region1(T, P)
- elif x == 1:
+ elif Pt <= P <= Ps_623 and x == 1:
propiedades = _Region2(T, P)
+ elif Ps_623 < P < Pc and x in (0, 1):
+ def funcion(rho):
+ return _Region3(rho, T)["P"]-P
+ rhoo = 1./_Backward3_sat_v_P(P, T, x)
+ rho = fsolve(funcion, rhoo)[0]
+ propiedades = _Region3(rho, T)
+ elif P == Pc and 0 <= x <= 1:
+ propiedades = _Region3(rhoc, Tc)
else:
raise NotImplementedError("Incoming out of bound")
self.sigma = _Tension(T)
+ propiedades["x"] = x
elif self._thermo == "Tx":
T, x = args
P = _PSat_T(T)
- if 273.15 <= T <= Tc and 0 < x < 1:
+ if 273.15 <= T < Tc and 0 < x < 1:
propiedades = _Region4(P, x)
- elif T > 623.15 and x in (0, 1):
- rho = 1./_Backward3_sat_v_P(P, T, x)
- propiedades = _Region3(rho, T)
elif 273.15 <= T <= 623.15 and x == 0:
propiedades = _Region1(T, P)
elif 273.15 <= T <= 623.15 and x == 1:
propiedades = _Region2(T, P)
- elif P > Ps_623:
- rho = 1./_Backward3_v_PT(P, T)
+ elif 623.15 < T < Tc and x in (0, 1):
+ rho = 1./_Backward3_sat_v_P(P, T, x)
propiedades = _Region3(rho, T)
+ elif T == Tc and 0 <= x <= 1:
+ propiedades = _Region3(rhoc, Tc)
else:
raise NotImplementedError("Incoming out of bound")
self.sigma = _Tension(T)
+ propiedades["x"] = x
- else:
- raise NotImplementedError("Bad incoming variables")
-
- self.M = M
+ self.M = 18.015257 # kg/kmol
self.Pc = Pc
self.Tc = Tc
self.rhoc = rhoc
@@ -3064,48 +4648,35 @@ class IAPWS97(object):
fase.xkappa = estado["kt"]
fase.kappas = -1/fase.v*self.derivative("v", "P", "s", fase)
- fase.mu = _Viscosity(fase.rho, self.T)
- fase.k = _ThCond(fase.rho, self.T)
- fase.nu = fase.mu/fase.rho
- fase.epsilon = _Dielectric(fase.rho, self.T)
- fase.Prandt = fase.mu*fase.cp*1000/fase.k
- fase.n = _Refractive(fase.rho, self.T, self.kwargs["l"])
-
- fase.alfa = fase.k/1000/fase.rho/fase.cp
fase.joule = self.derivative("T", "P", "h", fase)
fase.deltat = self.derivative("h", "P", "T", fase)
fase.gamma = -self.v/self.P/1000*self.derivative("P", "v", "s", fase)
- if self.region == 3:
- fase.alfap = estado["alfap"]
- fase.betap = estado["betap"]
- else:
- fase.alfap = fase.alfav/self.P/fase.xkappa
- fase.betap = -1/self.P*self.derivative("P", "v", "T", fase)
+ fase.alfap = fase.alfav/self.P/fase.xkappa
+ fase.betap = -1/self.P*self.derivative("P", "v", "T", fase)
fase.fi = exp((fase.g-self.g0)/R/self.T)
fase.f = self.P*fase.fi
+ fase.mu = _Viscosity(fase.rho, self.T)
+ # Use industrial formulation for critical enhancement in thermal
+ # conductivity calculation
+ fase.drhodP_T = self.derivative("rho", "P", "T", fase)
+ fase.k = _ThCond(fase.rho, self.T, fase)
+
+ fase.nu = fase.mu/fase.rho
+ fase.alfa = fase.k/1000/fase.rho/fase.cp
+ fase.epsilon = _Dielectric(fase.rho, self.T)
+ fase.Prandt = fase.mu*fase.cp*1000/fase.k
+ try:
+ fase.n = _Refractive(fase.rho, self.T, self.kwargs["l"])
+ except NotImplementedError:
+ fase.n = None
+
def derivative(self, z, x, y, fase):
- """Calculate generic partial derivative: (δz/δx)y
+ """Wrapper derivative for custom derived properties
where x, y, z can be: P, T, v, u, h, s, g, a"""
- dT = {"P": 0,
- "T": 1,
- "v": fase.v*fase.alfav,
- "u": fase.cp-self.P*1000*fase.v*fase.alfav,
- "h": fase.cp,
- "s": fase.cp/self.T,
- "g": -fase.s,
- "a": -self.P*1000*fase.v*fase.alfav-fase.s}
- dP = {"P": 1,
- "T": 0,
- "v": -fase.v*fase.xkappa,
- "u": fase.v*(self.P*1000*fase.xkappa-self.T*fase.alfav),
- "h": fase.v*(1-self.T*fase.alfav),
- "s": -fase.v*fase.alfav,
- "g": fase.v,
- "a": self.P*1000*fase.v*fase.xkappa}
- return (dP[z]*dT[y]-dT[z]*dP[y])/(dP[x]*dT[y]-dT[x]*dP[y])
+ return deriv_G(self, z, x, y, fase)
class IAPWS97_PT(IAPWS97):
@@ -3136,13 +4707,3 @@ class IAPWS97_Tx(IAPWS97):
"""Derivated class for direct T and x input"""
def __init__(self, T, x):
IAPWS97.__init__(self, T=T, x=x)
-
-
-if __name__ == "__main__":
- # import doctest
- # doctest.testmod()
-
- liquido = IAPWS97(P=18, T=626)
- print(liquido.h, liquido.T, liquido.region, liquido.x)
- vapor = IAPWS97(P=17, x=1)
- print(vapor.h)
diff --git a/setup.cfg b/setup.cfg
index a669c45..8bfd5a1 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,4 @@
[egg_info]
-tag_svn_revision = 0
tag_build =
tag_date = 0
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/iapws.git
More information about the debian-science-commits
mailing list