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

172 lines
4.6 KiB
Python

from CoolProp import CoolProp as CP
from PDSim.misc.datatypes import Collector
import numpy as np
import matplotlib.pyplot as plt
from scipy.odr import *
import textwrap
#
#fluid = 'Propane'
#Rfluid = 'REFPROP-propane'
#e_k = 263.88
#sigma = 0.49748
#
fluid = 'DimethylEther'
Rfluid = 'REFPROP-DME'
e_k = 329.72
sigma = 0.5529
molemass = CP.Props(fluid, 'molemass')
Ttriple = CP.Props(fluid, 'Ttriple')
Tcrit = CP.Props(fluid, 'Tcrit')
rhocrit = CP.Props(fluid, 'rhocrit')
n = 6
m = 3
NP = 1
Nb = 0
N = (n - 1) * (m + 1) + 3 + Nb
mu, mu_dilute, RHO, TTT = Collector(), Collector(), Collector(), Collector()
rhomax = CP.Props('D', 'T', Ttriple, 'Q', 0, fluid)
# Build a database of "experimental" data
for T in np.linspace(Ttriple, Tcrit + 30, 400):
for rho in np.linspace(1e-10, rhomax, 400):
muval = CP.Props('V', 'T', T, 'D', rho, Rfluid)
mudilute = CP.viscosity_dilute(fluid, T, rho, e_k, sigma)
# Want positive value, and single-phase
if (muval > 0 and T > Tcrit or rho > CP.rhosatL_anc(fluid, T) or rho < CP.rhosatV_anc(fluid, T)):
mu << muval
mu_dilute << mudilute
TTT << T
RHO << rho
from CoolProp.Plots.Plots import Trho
Trho(fluid)
plt.plot(RHO.vec, TTT.vec, '.')
plt.show()
#tau = np.array(TTT.vec)/Tcrit
tau = np.array(TTT.vec) / Tcrit
delta = np.array(RHO.vec) / rhocrit
Tstar = np.array(TTT.vec) / e_k
# Define the objective function
def OBJECTIVE_fit(c, x):
tau = x[0, :]
delta = x[1, :]
# Unpack the inputs into e matrix and f vector
e = np.zeros((n + 1, m + 1))
sum = 0
k = 0
for i in range(2, n + 1):
for j in range(0, m + 1):
e[i][j] = c[k]
sum += e[i][j] * delta**i / tau**j
k += 1
for o in range(0, NP):
f1 = c[k + o * 3]
g1 = c[k + 1 + o * 3]
g2 = c[k + 2 + o * 3]
delta_0 = g1 * (1 + g2 * tau**0.5)
sum += f1 * (delta / (delta_0 - delta) - delta / delta_0)
return sum + np.array(mu_dilute.vec)
print('starting fit')
XXX = np.r_[np.array(tau, ndmin=2), np.array(delta, ndmin=2)]
mod = Model(OBJECTIVE_fit)
mydata = Data(XXX.copy(), np.array(mu.vec))
beta0 = [1 for _ in range(N)]
myodr = ODR(mydata, mod, beta0=beta0)
myoutput = myodr.run()
myoutput.pprint()
print(myoutput.sum_square)
YFIT = OBJECTIVE_fit(myoutput.beta, XXX)
plt.plot(np.array(mu.vec), YFIT / np.array(mu.vec), 'o')
plt.show()
rel_error = (YFIT) / np.array(mu.vec) - 1
MAE = np.mean(np.abs(rel_error)) * 100
SSE = np.sum(np.power(YFIT - np.array(mu.vec), 2))
print(SSE)
def write_output(c):
e = np.zeros((n + 1, m + 1))
k = 0
edata = ''
for i in range(2, n + 1):
erow = ''
for j in range(0, m + 1):
e[i][j] = c[k]
erow += 'e[{i:d}][{j:d}] = {val:0.16g}; '.format(val=e[i][j], i=i, j=j)
k += 1
edata += erow + '\n'
f1 = c[k]
g1 = c[k + 1]
g2 = c[k + 2]
template = textwrap.dedent(
"""
double {name:s}Class::viscosity_Trho(double T, double rho)
{{
// This function was generated by fitting REFPROP ECS data
// to the functional form of Vogel, 1998 (propane viscosity)
// The script entitled dev/fit_avoid_ECS.py was used to make this
// function. The mean absolute error of the fit is equal to
// {MAE:g} %
double delta_0, sum, DELTA_H_eta, e_k, sigma, tau, delta;
double e[{n:d}+1][{m:d}+1];
tau = T/reduce.T; //[Opposite to normal definition]
delta = rho/reduce.rho;
// Load the coefficients
double f1 = {f1:0.16g}, g1 = {g1:0.16g}, g2 = {g2:0.16g};
for (int i=0;i<={n:d};i++){{ for(int j=0;j<={m:d};j++){{ e[i][j]=0.0; }} }}
{edata:s}
delta_0=g1*(1+g2*sqrt(tau)); //[no units]
sum=0;
for (int i=2;i<={n:d};i++){{
for (int j=0;j<={m:d};j++){{
sum += e[i][j]*pow(delta,i)/pow(tau,j);
}}
}}
DELTA_H_eta = sum + f1*(delta/(delta_0-delta)-delta/delta_0); //[Pa-s]
try{{
// Get the ECS params for the fluid if it has them
ECSParams(&e_k,&sigma);
}}
catch(NotImplementedError)
{{
throw ValueError(format("Your fluid does not implement ECSParams"));
}}
return viscosity_dilute(T,e_k,sigma) + DELTA_H_eta;
}}
"""
)
values = dict(f1=f1,
g1=g1,
g2=g2,
n=n,
m=m,
name=fluid,
edata=edata,
MAE=MAE)
print(template.format(**values))
write_output(myoutput.beta)