Files
CoolProp/dev/TTSE/TTSE_ranges.py
2019-01-12 20:45:25 -07:00

436 lines
12 KiB
Python

from CoolProp.Plots import Ph
import CoolProp.CoolProp as CP
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import matplotlib.ticker
import numpy as np
import random
import scipy.ndimage
import scipy.interpolate
from mpl_toolkits.mplot3d import Axes3D
import matplotlib._pylab_helpers
def fill_nan(A):
'''
interpolate to fill nan values
'''
inds = np.arange(A.shape[0])
good = np.where(np.isfinite(A))
f = scipy.interpolate.interp1d(inds[good], A[good],bounds_error=False)
B = np.where(np.isfinite(A),A,f(inds))
return B
def get_Z(X_in,Y_in,fluid):
'''
Just a wrapper to call CoolProp
'''
return False
def fill_Z(X,Y):
'''
Use 2D arrays X and Y to calculate a Z value
'''
Z = np.empty_like(X)
for i in range(len(X)):
for j in range(len(X[i])):
Z[i,j] = get_Z(X[i,j],Y[i,j],fluid)
Z[i] = fill_nan(Z[i])
tr = np.transpose(Z)
for i in range(len(tr)):
tr[i] = fill_nan(tr[i])
return np.transpose(tr)
def plotLineAndProjection(ax,X,Y,Z,draw='CXYZ',color='black',xlim=None,ylim=None,zlim=None):
alpha = 0.5
if 'C' in draw:
ax.plot(X,Y,zs=Z,color=color)
#else:
# ax.plot(X,Y,Z,color=color,alpha=0)
if xlim == None: xlim = ax.get_xlim()
if ylim == None: ylim = ax.get_ylim()
if zlim == None: zlim = ax.get_zlim()
if 'X' in draw:
constArr = np.ones_like(X) * xlim[0]
ax.plot(constArr,Y,zs=Z,color=color,alpha=alpha)
ax.set_xlim(xlim)
if 'Y' in draw:
constArr = np.ones_like(Y) * ylim[1]
ax.plot(X,constArr,zs=Z,color=color,alpha=alpha)
ax.set_ylim(ylim)
if 'Z' in draw:
constArr = np.ones_like(Z) * zlim[0]
ax.plot(X,Y,zs=constArr,color=color,alpha=alpha)
ax.set_zlim(zlim)
def make3Dlpot(X,Y,Z=None,ax=None,invert='',draw='CXYZ',color='blue',xlim=None,ylim=None,zlim=None):
'''
A simple wrapper around the plotting routines
invert: which axes to invert could be 'X' or 'YZ' or ...
draw: which lines to draw could be 'C' or 'YZ' or ...
C for curve and the rest are projections in the different dimensions
'''
if Z == None: Z = fill_Z(X, Y)
## Now we have all data and need to resample it for a smoother plot
resFactor = 10
Xr = scipy.ndimage.zoom(X, resFactor, order=1)
Yr = scipy.ndimage.zoom(Y, resFactor, order=1)
Zr = scipy.ndimage.zoom(Z, resFactor, order=1)
## Make the plot
if ax==None:
fig = plt.figure()
ax = fig.gca(projection='3d')
else:
fig = ''
if 'X' in invert: ax.invert_xaxis()
if 'Y' in invert: ax.invert_yaxis()
if 'Z' in invert: ax.invert_zaxis()
## Reduce data again and call the plotting wrapper
stride=np.round(len(Xr)/3.0)
for i in range(len(Xr)):
if np.mod(i,stride)==0:
plotLineAndProjection(ax,Xr[i],Yr[i],Zr[i],draw=draw,color=color,xlim=xlim,ylim=ylim,zlim=zlim)
plotLineAndProjection(ax,Xr[-1],Yr[-1],Zr[-1],draw=draw,color=color,xlim=xlim,ylim=ylim,zlim=zlim)
for i in range(len(Xr[0])):
if np.mod(i,stride)==0:
Xi = [row[i] for row in Xr]
Yi = [row[i] for row in Yr]
Zi = [row[i] for row in Zr]
plotLineAndProjection(ax,Xi,Yi,Zi,draw=draw,color=color,xlim=xlim,ylim=ylim,zlim=zlim)
Xi = [row[-1] for row in Xr]
Yi = [row[-1] for row in Yr]
Zi = [row[-1] for row in Zr]
plotLineAndProjection(ax,Xi,Yi,Zi,draw=draw,color=color,xlim=xlim,ylim=ylim,zlim=zlim)
#cset = ax.contour(X, Y, Z, cmap=cm.coolwarm)
#ax.clabel(cset, fontsize=9, inline=1)
## In case we need a surface plot
#from matplotlib import cm
#from matplotlib.ticker import LinearLocator, FormatStrFormatter
#
#surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,
# linewidth=0, antialiased=False)
#ax.set_zlim(-1.01, 1.01)
#
#ax.zaxis.set_major_locator(LinearLocator(10))
#ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
#
#fig.colorbar(surf, shrink=0.5, aspect=5)
## Alternative plotting solution
#cmap = plt.get_cmap('jet')
#
#if PRINT:
# ax.plot_surface(
# X, Y, Z,
# rstride=100,
# cstride=100,
# alpha=0.5,
# cmap=cmap,
# linewidth=0,
# antialiased=True
# )
#else:
# #ax.plot_surface(
# ax.plot_wireframe(
# X, Y, Z,
# rstride=100,
# cstride=100,
# #alpha=0.5,
# #cmap=cmap,
# #linewidth=0,
# #antialiased=False
# )
### Make the plot
#fig = plt.figure()
#ax = fig.gca(projection='3d')
##cset = ax.contour(X, Y, Z, cmap=cm.coolwarm)
##ax.clabel(cset, fontsize=9, inline=1)
#
#ax.plot_wireframe(
# X, Y, Z,
# rstride=np.round(resFactor*10),
# cstride=np.round(resFactor*10),
# #alpha=0.5,
# #cmap=cmap,
# #linewidth=0,
# #antialiased=False
# )
## Plot the two-phase dome and its projections
#ax.plot(X_TP,Y_TP,Z_TP,color='black')
#xlim = ax.get_xlim()
#ylim = ax.get_ylim()
#zlim = ax.get_zlim()
#
#constArr = np.ones_like(X_TP) * xlim[0]
#ax.plot(constArr,Y_TP,Z_TP,color='black')
#constArr = np.ones_like(Y_TP) * ylim[1]
#ax.plot(X_TP,constArr,Z_TP,color='black')
#constArr = np.ones_like(Z_TP) * zlim[0]
#ax.plot(X_TP,Y_TP,constArr,color='black')
## Or do we want contour lines?
##cset = ax.contour(X, Y, Z, zdir='z', offset=zlim[0], cmap=cmap)
##cset = ax.contour(X, Y, Z, zdir='x', offset=xlim[0], cmap=cmap)
##cset = ax.contour(X, Y, Z, zdir='y', offset=ylim[1], cmap=cmap)
#
#ax.set_xlim(xlim)
#ax.set_ylim(ylim)
#ax.set_zlim(zlim)
#majorFormatter = matplotlib.ticker.EngFormatter("J/kg")
#majorFormatter = matplotlib.ticker.
majorFormatter = matplotlib.ticker.ScalarFormatter()
#majorFormatter.set_scientific(True)
majorFormatter.set_powerlimits((-4,4))
ax.xaxis.set_major_formatter(majorFormatter)
ax.yaxis.set_major_formatter(majorFormatter)
ax.zaxis.set_major_formatter(majorFormatter)
return fig, ax, Z
def getlim(key,dicts,fac=1):
min = np.min([dict[key]/fac for dict in dicts])
max = np.max([dict[key]/fac for dict in dicts])
return [np.floor(min)*fac, np.ceil(max)*fac]
#########################################################################
# Here starts the real script
#########################################################################
fluid = 'water'
CP.enable_TTSE_LUT(fluid)
PRINT = False
if PRINT:
points = 200
dpi = 300
toFile = True
else:
points = 100
dpi = 75
toFile = False
Tmin = CP.PropsSI('Tmin' ,'T',0,'P',0,fluid) + 5.0
Tcri = CP.PropsSI('Tcrit','T',0,'P',0,fluid)
Tmax = CP.PropsSI('Tcrit','T',0,'P',0,fluid) * 2.0
## Get phase boundary
T_TP = np.linspace(Tmin, Tcri-0.5, 0.5*points)
D_TP = CP.PropsSI('D','T',T_TP,'Q',0,fluid)
P_TP = CP.PropsSI('P','T',T_TP,'Q',0,fluid)
H_TP = CP.PropsSI('H','T',T_TP,'Q',0,fluid)
S_TP = CP.PropsSI('S','T',T_TP,'Q',0,fluid)
D_TP = np.append(D_TP, CP.PropsSI('D','T',T_TP[::-1],'Q',1,fluid))
P_TP = np.append(P_TP, CP.PropsSI('P','T',T_TP[::-1],'Q',1,fluid))
H_TP = np.append(H_TP, CP.PropsSI('H','T',T_TP[::-1],'Q',1,fluid))
S_TP = np.append(S_TP, CP.PropsSI('S','T',T_TP[::-1],'Q',1,fluid))
logV_TP = np.log10(1.0/D_TP)
logP_TP = np.log10(1.0*P_TP)
T_TP = np.append(T_TP, T_TP[::-1])
## These are the default TTSE ranges
D_L = CP.PropsSI('D','T',Tmin,'Q',0,fluid)
D_V = CP.PropsSI('D','T',Tmin,'Q',1,fluid)
H_L = CP.PropsSI('H','T',Tmin,'Q',0,fluid)
H_V = CP.PropsSI('H','T',Tmin,'Q',1,fluid)
P_L = CP.PropsSI('P','T',Tmin,'Q',0,fluid)
P_V = CP.PropsSI('P','T',Tmin,'Q',1,fluid)
Hmin = H_L
Hmax = H_L + (H_V-H_L)*2.0
#Pmin = CP.PropsSI('ptriple','T',0,'P',0,fluid) + 1
Pmin = np.min([P_L,P_V])
Pmax = CP.PropsSI('pcrit','T',0,'P',0,fluid) * 2.0 # should be p_reduce
Dmin = CP.PropsSI('D','H',Hmin,'P',Pmax,fluid)
Dmax = CP.PropsSI('D','H',Hmax,'P',Pmin,fluid)
#########################################################################
# Start with the first diagram, hps
#########################################################################
## Set the ranges for the plot
X_TP = H_TP
Y_TP = logP_TP
Z_TP = S_TP
Xmin = Hmin
Xmax = Hmax
Ymin = np.log10(Pmin)
Ymax = np.log10(Pmax)
X = np.linspace(Xmin, Xmax, points) # Enthalpy
Y = np.linspace(Ymin, Ymax, points) # Pressure
X, Y = np.meshgrid(X, Y)
def get_Z(X_in,Y_in,fluid,out='S'):
'''
Just a wrapper to call CoolProp
'''
X = X_in
Y = np.power(10.0,Y_in)
Z = np.NAN
try:
Z = CP.PropsSI(out,'H',X,'P',Y,fluid)
except(ValueError):
print("CoolProp failed, returning NAN")
Z = np.NAN
return Z
## Now we also need the variables
Z = fill_Z(X,Y)
get_Z_old = get_Z
def get_Z(X_in,Y_in,fluid):
return get_Z_old(X_in,Y_in,fluid,out='D')
logVdata = np.log10(1.0/fill_Z(X,Y))
def get_Z(X_in,Y_in,fluid):
return get_Z_old(X_in,Y_in,fluid,out='T')
Tdata = fill_Z(X,Y)
HPSdict = {'H': X, 'P': Y, 'S': Z, 'V': logVdata, 'T': Tdata, 'H_TP': X_TP, 'P_TP': Y_TP, 'S_TP': Z_TP}
#########################################################################
# Start with the next diagram, vTp
#########################################################################
## Set the ranges for the plot
X_TP = logV_TP
Y_TP = T_TP
Z_TP = logP_TP
#Xmin = np.log10(1.0/Dmax)
#Xmax = np.log10(1.0/Dmin)
Xmin = np.min(X_TP)
Xmax = np.max(X_TP)
Ymin = np.min(Y_TP)
Ymax = Tmax
X = np.linspace(Xmin, Xmax, points) # Volume
Y = np.linspace(Ymin, Ymax, points) # Temperature
X, Y = np.meshgrid(X, Y)
def get_Z(X_in,Y_in,fluid,out='P'):
'''
Just a wrapper to call CoolProp
'''
X = 1.0/np.power(10.0,X_in)
Y = Y_in
Z = np.NAN
try:
Z = np.log10(CP.PropsSI(out,'D',X,'T',Y,fluid))
except(ValueError):
print("CoolProp failed, returning NAN")
Z = np.NAN
return Z
## Now we also need the variables
Z = fill_Z(X,Y)
get_Z_old = get_Z
def get_Z(X_in,Y_in,fluid):
return np.power(10.0,get_Z_old(X_in,Y_in,fluid,out='H'))
Hdata = fill_Z(X,Y)
def get_Z(X_in,Y_in,fluid):
return np.power(10.0,get_Z_old(X_in,Y_in,fluid,out='S'))
Sdata = fill_Z(X,Y)
VTPdict = {'V': X, 'T': Y, 'P': Z, 'H': Hdata, 'S': Sdata, 'V_TP': X_TP, 'T_TP': Y_TP, 'P_TP': Z_TP}
#########################################################################
# Now we have all the data and can start mixing the
# different definitions
#########################################################################
dicts = [HPSdict,VTPdict]
Hlim = getlim('H',dicts,fac=1e6)
Plim = getlim('P',dicts)
Slim = getlim('S',dicts,fac=1e3)
Vlim = getlim('V',dicts)
Tlim = getlim('T',dicts,fac=1e2)
figHPS, axHPS, Z = make3Dlpot(HPSdict['H'],HPSdict['P'],Z=HPSdict['S'],invert='Z',draw='XYZ',color='blue',xlim=Hlim,ylim=Plim,zlim=Slim[::-1])
## Plot the two-phase dome and its projections
plotLineAndProjection(axHPS,HPSdict['H_TP'],HPSdict['P_TP'],HPSdict['S_TP'])
## .. and add the other plot
make3Dlpot(VTPdict['H'],VTPdict['P'],Z=VTPdict['S'],ax=axHPS,draw='XYZ',color='red')
axHPS.set_xlabel(r'$h$')
axHPS.set_ylabel(r'log $p$')
axHPS.set_zlabel(r'$s$')
figVTP, axVTP, Z = make3Dlpot(VTPdict['V'],VTPdict['T'],Z=VTPdict['P'],draw='XYZ',color='red',xlim=Vlim,ylim=Tlim,zlim=Plim)
## Plot the two-phase dome and its projections
plotLineAndProjection(axVTP,VTPdict['V_TP'],VTPdict['T_TP'],VTPdict['P_TP'])
## .. and add the other plot
make3Dlpot(HPSdict['V'],HPSdict['T'],Z=HPSdict['P'],ax=axVTP,draw='XYZ',color='blue')
axVTP.set_xlabel(r'log $v$')
axVTP.set_ylabel(r'$T$')
axVTP.set_zlabel(r'log $p$')
if toFile:
figHPS.savefig('phs-'+fluid+'.png', dpi = dpi, transparent = True)
figHPS.savefig('phs-'+fluid+'.pdf', transparent = True)
#figHPS.close()
figVTP.savefig('pvT-'+fluid+'.png', dpi = dpi, transparent = True)
figVTP.savefig('pvT-'+fluid+'.pdf', transparent = True)
#figVTP.close()
#plt.savefig('TTSE_RANGES.pdf')
else:
plt.show()
#figHPS.show()
#figVTP.show()