Source code for lib.freeSteam

#!/usr/bin/python3
# -*- coding: utf-8 -*-

"""Pychemqt, Chemical Engineering Process simulator
Copyright (C) 2009-2025, Juan José Gómez Romera <jjgomera@gmail.com>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.


Library to use freesteam library to calculate water properties with IAPWS-IF97 \
to meos calculation or in stream calculations, http://freesteam.sourceforge.net

This library is optional, pychemqt has a python implementation for IAPWS-IF97 \
in file lib/iapws97.py, but if freesteam is available in your system this is \
faster because is implemented in c++.

All the functionality is included in the main class:

  * :class:`Freesteam`: Stream definition using freesteam external library

API reference
-------------

"""


from math import exp
import os

import iapws
from iapws.iapws97 import prop0
from scipy.constants import R

try:
    import freesteam
except:
    pass

from lib import unidades, mEoS
from lib.thermo import ThermoWater


__doi__ = {
    1:
        {"autor": "John Pye",
         "title": "Open source steam property routines in C. Implements the "
                  "IAPWS-IF97 steam tables from the International Association "
                  "for the Properties of Water and Steam ",
         "ref": "https://sourceforge.net/projects/freesteam/",
         "doi": ""}}


[docs] class Freesteam(ThermoWater): """Class to define a water stream It can be defined by the pair: P,T P,h P,s P,v T,s T,x where: -T: Temperature, Kelvin -P: Pressure, Pa -x: Quality, [-] -s: entropy, kJ/kgK -h: enthalpy, kJ/kg -v: specific volume, m³/kg """ kwargs = {"T": 0.0, "P": 0.0, "x": None, "h": 0.0, "s": 0.0, "v": 0.0, "l": 0.5893} M = unidades.Dimensionless(iapws._iapws.M) if os.environ["freesteam"] == "True": Pc = unidades.Pressure(freesteam.PCRIT) Tc = unidades.Temperature(freesteam.TCRIT) rhoc = unidades.Density(freesteam.RHOCRIT*M) else: Pc = unidades.Pressure(iapws._iapws.Pc, "MPa") Tc = unidades.Temperature(iapws._iapws.Tc) rhoc = unidades.Density(iapws._iapws.rhoc) Tt = iapws._iapws.Tt Tb = iapws._iapws.Tb f_accent = unidades.Dimensionless(iapws._iapws.f_acent) momentoDipolar = iapws._iapws.Dipole @property def calculable(self): self._thermo = -1 if self.kwargs["T"] and self.kwargs["P"]: self._thermo = 0 self.var1 = self.kwargs["P"] self.var2 = self.kwargs["T"] elif self.kwargs["P"] and self.kwargs["h"]: self._thermo = 1 self.var1 = self.kwargs["P"] self.var2 = self.kwargs["h"] elif self.kwargs["P"] and self.kwargs["s"]: self._thermo = 2 self.var1 = self.kwargs["P"] self.var2 = self.kwargs["s"] elif self.kwargs["P"] and self.kwargs["v"]: self._thermo = 3 self.var1 = self.kwargs["P"] self.var2 = self.kwargs["v"] elif self.kwargs["T"] and self.kwargs["s"]: self._thermo = 4 self.var1 = self.kwargs["T"] self.var2 = self.kwargs["s"] elif self.kwargs["T"] and self.kwargs["x"] is not None: self._thermo = 5 self.var1 = self.kwargs["T"] self.var2 = self.kwargs["x"] return self._thermo+1
[docs] def calculo(self): method = [freesteam.steam_pT, freesteam.steam_ph, freesteam.steam_ps, freesteam.steam_pv, freesteam.steam_Ts, freesteam.steam_Tx] func = method[self._thermo] fluido = func(self.var1, self.var2) self.x = unidades.Dimensionless(fluido.x) self.name = mEoS.H2O.name self.region = fluido.region self.synonim = mEoS.H2O.synonym self.CAS = mEoS.H2O.CASNumber self.T = unidades.Temperature(fluido.T) self.P = unidades.Pressure(fluido.p) self.phase = self.getphase(Tc=self.Tc, Pc=self.Pc, T=self.T, P=self.P, x=self.x, region=self.region) self.Tr = unidades.Dimensionless(self.T/self.Tc) self.Pr = unidades.Dimensionless(self.P/self.Pc) self.rho = unidades.Density(fluido.rho) self.v = unidades.SpecificVolume(1./self.rho) cp0 = prop0(self.T, self.P.MPa) cp0["h"] *= 1000 cp0["s"] *= 1000 cp0["cp"] *= 1000 cp0["cv"] *= 1000 self._cp0(cp0) self.Liquido = ThermoWater() self.Gas = ThermoWater() if self.x == 0: # only liquid phase self.fill(self, fluido) self.fill(self.Liquido, fluido) self.sigma = unidades.Tension(freesteam.surftens_T(self.T)) self.Hvap = unidades.Enthalpy(None) self.Svap = unidades.SpecificHeat(None) elif self.x == 1: # only vapor phase self.fill(self, fluido) self.fill(self.Gas, fluido) self.Hvap = unidades.Enthalpy(None) self.Svap = unidades.SpecificHeat(None) else: # two phases liquido = freesteam.steam_Tx(fluido.T, 0.) self.fill(self.Liquido, liquido) self.sigma = unidades.Tension(freesteam.surftens_T(self.T)) vapor = freesteam.steam_Tx(fluido.T, 1.) self.fill(self.Gas, vapor) self.h = unidades.Enthalpy( self.x*self.Gas.h+(1-self.x)*self.Liquido.h) self.s = unidades.SpecificHeat( self.x*self.Gas.s+(1-self.x)*self.Liquido.s) self.u = unidades.SpecificHeat( self.x*self.Gas.u+(1-self.x)*self.Liquido.u) self.a = unidades.Enthalpy( self.x*self.Gas.a+(1-self.x)*self.Liquido.a) self.g = unidades.Enthalpy( self.x*self.Gas.g+(1-self.x)*self.Liquido.g) self.cv = unidades.SpecificHeat(None) self.cp = unidades.SpecificHeat(None) self.cp_cv = unidades.Dimensionless(None) self.w = unidades.Speed(None) self.Hvap = unidades.Enthalpy(vapor["h"]-liquido["h"], "kJkg") self.Svap = unidades.SpecificHeat(vapor["s"]-liquido["s"], "kJkgK")
[docs] def fill(self, fase, estado): fase._bool = True fase.M = self.M fase.rho = unidades.Density(estado.rho) fase.v = unidades.SpecificVolume(estado.v) fase.Z = unidades.Dimensionless(self.P*estado.v/R/1000*self.M/self.T) fase.h = unidades.Enthalpy(estado.h) fase.s = unidades.SpecificHeat(estado.s) fase.u = unidades.Enthalpy(estado.u) fase.a = unidades.Enthalpy(fase.u-self.T*fase.s) fase.g = unidades.Enthalpy(fase.h-self.T*fase.s) fi = exp((fase.g-self.g0)/1000/R*self.M/self.T) fase.fi = [unidades.Pressure(fi)] fase.f = [unidades.Pressure(self.P*f) for f in fase.fi] fase.cv = unidades.SpecificHeat(estado.cv) fase.cp = unidades.SpecificHeat(estado.cp) fase.cp_cv = unidades.Dimensionless(fase.cp/fase.cv) fase.gamma = fase.cp_cv fase.w = unidades.Speed(estado.w) fase.rhoM = unidades.MolarDensity(fase.rho/self.M) fase.hM = unidades.MolarEnthalpy(fase.h*self.M) fase.sM = unidades.MolarSpecificHeat(fase.s*self.M) fase.uM = unidades.MolarEnthalpy(fase.u*self.M) fase.aM = unidades.MolarEnthalpy(fase.a*self.M) fase.gM = unidades.MolarEnthalpy(fase.g*self.M) fase.cvM = unidades.MolarSpecificHeat(fase.cv*self.M) fase.cpM = unidades.MolarSpecificHeat(fase.cp*self.M) fase.mu = unidades.Viscosity(estado.mu) fase.nu = unidades.Diffusivity(fase.mu/fase.rho) fase.k = unidades.ThermalConductivity(estado.k) fase.alfa = unidades.Diffusivity(fase.k/fase.rho/fase.cp) fase.epsilon = unidades.Dimensionless( iapws._Dielectric(estado.rho, self.T)) fase.Prandt = unidades.Dimensionless(estado.mu*estado.cp/estado.k) fase.n = unidades.Dimensionless( iapws._Refractive(fase.rho, self.T, self.kwargs["l"])) fase.alfav = unidades.InvTemperature(estado.deriv("Tpv")/fase.v) fase.kappa = unidades.InvPressure(-estado.deriv("pTv")/fase.v) fase.kappas = unidades.InvPressure( -1/fase.v*self.derivative("v", "P", "s", fase)) fase.joule = unidades.TemperaturePressure(estado.deriv("Tph")) fase.deltat = unidades.EnthalpyPressure(estado.deriv("pTh")) fase.alfap = unidades.Density(fase.alfav/self.P/fase.kappa) fase.betap = unidades.Density(-1/self.P*estado.deriv("vTp")) fase.fraccion = [1] fase.fraccion_masica = [1]
if __name__ == '__main__': fluido = Freesteam(T=373.15, x=1) print(fluido.h.kJkg, fluido.P)