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)