From ebacd0eeaa186d26dc7e65b59bf75559c641ca86 Mon Sep 17 00:00:00 2001 From: Ian Bell <ian.bell@nist.gov> Date: Fri, 21 May 2021 13:48:03 -0400 Subject: [PATCH] move the needed derivative into C++ and expose --- include/teqp/algorithms/VLE.hpp | 77 +++++++++ include/teqp/derivs.hpp | 2 +- interface/pybind11_wrapper.cpp | 6 +- notebooks/isochoric.py | 277 ++++++++++++++++++++++++-------- 4 files changed, 297 insertions(+), 65 deletions(-) diff --git a/include/teqp/algorithms/VLE.hpp b/include/teqp/algorithms/VLE.hpp index 5932ca7..f653ee3 100644 --- a/include/teqp/algorithms/VLE.hpp +++ b/include/teqp/algorithms/VLE.hpp @@ -130,4 +130,81 @@ auto extrapolate_from_critical(const Model& model, const Scalar Tc, const Scalar auto rholiq = -drhohat/sqrt(1 - T/Tc) + rhoc; auto rhovap = drhohat/sqrt(1 - T/Tc) + rhoc; return (Eigen::ArrayXd(2) << rholiq, rhovap).finished(); +} + +template<class A, class B> +auto linsolve(const A &a, const B& b) { + return a.matrix().colPivHouseholderQr().solve(b.matrix()).array().eval(); +} + +template<class Model, class Scalar, class VecType> +auto get_drhovecdp_Tsat(const Model& model, const Scalar &T, const VecType& rhovecL, const VecType& rhovecV) { + //tic = timeit.default_timer(); + using id = IsochoricDerivatives<Model, Scalar, VecType>; + auto Hliq = id::build_Psi_Hessian_autodiff(model, T, rhovecL).eval(); + auto Hvap = id::build_Psi_Hessian_autodiff(model, T, rhovecV).eval(); + //Hvap[~np.isfinite(Hvap)] = 1e20; + //Hliq[~np.isfinite(Hliq)] = 1e20; + + auto N = rhovecL.size(); + Eigen::MatrixXd A = decltype(Hliq)::Zero(N, N); + auto b = decltype(Hliq)::Ones(N, 1); + decltype(Hliq) drhodp_liq, drhodp_vap; + assert(rhovecL.size() == rhovecV.size()); + if ((rhovecL != 0).all() && (rhovecV != 0).all()) { + // Normal treatment for all concentrations not equal to zero + A(0, 0) = Hliq.row(0).dot(rhovecV.matrix()); + A(0, 1) = Hliq.row(1).dot(rhovecV.matrix()); + A(1, 0) = Hliq.row(0).dot(rhovecL.matrix()); + A(1, 1) = Hliq.row(1).dot(rhovecL.matrix()); + + drhodp_liq = linsolve(A, b); + drhodp_vap = linsolve(Hvap, Hliq*drhodp_liq); + } + else{ + // Special treatment for infinite dilution + auto murL = id::build_Psir_gradient_autodiff(model, T, rhovecL); + auto murV = id::build_Psir_gradient_autodiff(model, T, rhovecV); + auto RL = model.R(rhovecL / rhovecL.sum()); + auto RV = model.R(rhovecV / rhovecV.sum()); + + // First, for the liquid part + for (auto i = 0; i < N; ++i) { + for (auto j = 0; j < N; ++j) { + if (rhovecL[j] == 0) { + // Analysis is special if j is the index that is a zero concentration.If you are multiplying by the vector + // of liquid concentrations, a different treatment than the case where you multiply by the vector + // of vapor concentrations is required + // ... + // Initial values + auto Aij = (Hliq.row(j).array().cwiseProduct(((i == 0) ? rhovecV : rhovecL).array().transpose())).eval(); // coefficient - wise product + // A throwaway boolean for clarity + bool is_liq = (i == 1); + // Apply correction to the j term (RT if liquid, RT*phi for vapor) + Aij[j] = (is_liq) ? RL*T : RL*T*exp(-(murV[j] - murL[j])/(RL*T)); + // Fill in entry + A(i, j) = Aij.sum(); + } + else{ + // Normal + A(i, j) = Hliq.row(j).dot(((i==0) ? rhovecV : rhovecL).matrix()); + } + } + } + drhodp_liq = linsolve(A, b); + + // Then, for the vapor part, also requiring special treatment + // Left - multiplication of both sides of equation by diagonal matrix with liquid concentrations along diagonal, all others zero + auto diagrhovecL = rhovecL.matrix().asDiagonal(); + auto PSIVstar = (diagrhovecL*Hvap).eval(); + auto PSILstar = (diagrhovecL*Hliq).eval(); + for (auto j = 0; j < N; ++j) { + if (rhovecL[j] == 0) { + PSILstar(j, j) = RL*T; + PSIVstar(j, j) = RV*T/exp(-(murV[j] - murL[j]) / (RV * T)); + } + } + drhodp_vap = linsolve(PSIVstar, PSILstar*drhodp_liq); + } + return std::make_tuple(drhodp_liq, drhodp_vap); } \ No newline at end of file diff --git a/include/teqp/derivs.hpp b/include/teqp/derivs.hpp index 5568e0a..e1169bf 100644 --- a/include/teqp/derivs.hpp +++ b/include/teqp/derivs.hpp @@ -421,7 +421,7 @@ struct IsochoricDerivatives{ static auto build_Psi_Hessian_autodiff(const Model& model, const Scalar& T, const VectorType& rho) { auto rhotot_ = rho.sum(); auto molefrac = (rho / rhotot_).eval(); - auto H = build_Psir_Hessian_autodiff(model, T, rho); + auto H = build_Psir_Hessian_autodiff(model, T, rho).eval(); for (auto i = 0; i < 2; ++i) { H(i, i) += model.R(molefrac) * T / rho[i]; } diff --git a/interface/pybind11_wrapper.cpp b/interface/pybind11_wrapper.cpp index 1767bf1..117464b 100644 --- a/interface/pybind11_wrapper.cpp +++ b/interface/pybind11_wrapper.cpp @@ -23,6 +23,9 @@ namespace py = pybind11; template<typename Model, typename Wrapper> void add_derivatives(py::module &m, Wrapper &cls) { + + using RAX = Eigen::Ref<Eigen::ArrayXd>; + using id = IsochoricDerivatives<Model, double, Eigen::Array<double,Eigen::Dynamic,1> >; m.def("get_Ar00", &id::get_Ar00, py::arg("model"), py::arg("T"), py::arg("rho")); m.def("get_Ar10", &id::get_Ar10, py::arg("model"), py::arg("T"), py::arg("rho")); @@ -47,11 +50,12 @@ void add_derivatives(py::module &m, Wrapper &cls) { m.def("extrapolate_from_critical", &extrapolate_from_critical<Model, double>); m.def("pure_VLE_T", &pure_VLE_T<Model, double>); + m.def("get_drhovecdp_Tsat", &get_drhovecdp_Tsat<Model, double, RAX>, py::arg("model"), py::arg("T"), py::arg("rhovecL").noconvert(), py::arg("rhovecV").noconvert()); //cls.def("get_Ar01", [](const Model& m, const double T, const Eigen::ArrayXd& rhovec) { return id::get_Ar01(m, T, rhovec); }); //cls.def("get_Ar10", [](const Model& m, const double T, const Eigen::ArrayXd& rhovec) { return id::get_Ar10(m, T, rhovec); }); using tdx = TDXDerivatives<Model, double, Eigen::Array<double, Eigen::Dynamic, 1> >; - using RAX = Eigen::Ref<Eigen::ArrayXd>; + cls.def("get_R", [](const Model& m, const RAX molefrac) { return m.R(molefrac); }, py::arg("molefrac").noconvert()); cls.def("get_Ar00", [](const Model& m, const double T, const double rho, const RAX molefrac) { return tdx::get_Ar00(m, T, rho, molefrac); }, py::arg("T"), py::arg("rho"), py::arg("molefrac").noconvert()); cls.def("get_Ar01", [](const Model& m, const double T, const double rho, const RAX molefrac) { return tdx::template get_Ar01<ADBackends::autodiff>(m, T, rho, molefrac); }, py::arg("T"), py::arg("rho"), py::arg("molefrac").noconvert()); diff --git a/notebooks/isochoric.py b/notebooks/isochoric.py index e2542a6..3edea4c 100644 --- a/notebooks/isochoric.py +++ b/notebooks/isochoric.py @@ -14,6 +14,7 @@ import teqp import CoolProp.CoolProp as CP def get_drhovecdp_sat(model, T, rhovecL, rhovecV): + tic = timeit.default_timer() Hliq = teqp.build_Psi_Hessian_autodiff(model, T, rhovecL) Hvap = teqp.build_Psi_Hessian_autodiff(model, T, rhovecV) Hvap[~np.isfinite(Hvap)] = 1e20 @@ -31,6 +32,7 @@ def get_drhovecdp_sat(model, T, rhovecL, rhovecV): drhodp_liq = np.linalg.solve(A, b).squeeze() drhodp_vap = np.linalg.solve(Hvap, np.dot(Hliq,drhodp_liq)) + return drhodp_liq, drhodp_vap else: # Special treatment for infinite dilution @@ -71,7 +73,8 @@ def get_drhovecdp_sat(model, T, rhovecL, rhovecV): PSILstar[j, j] = RL*T PSIVstar[j, j] = RV*T/np.exp(-(murV[j] - murL[j])/(RV*T)) drhodp_vap = np.linalg.solve(PSIVstar, PSILstar@drhodp_liq) - + toc = timeit.default_timer() + # print(toc-tic) return drhodp_liq.squeeze(), drhodp_vap.squeeze() def get_dxdp(*, rhovec, drhovecdp): @@ -96,36 +99,65 @@ def traceT(model, T, rhovec0, *, kwargs={}): p = [teqp.get_pr(model, T, sol.y[0:2,j]) + R*T*sol.y[0:2,j].sum() for j in range(len(sol.t))] toc = timeit.default_timer() print(toc-tic) - y = sol.y[2,:]/(sol.y[2,:]+sol.y[3,:]) + y = sol.y[2,:]/(sol.y[2,:] + sol.y[3,:]) plt.plot(sol.t, p, 'r',**kwargs) plt.plot(y, p, 'g',**kwargs) -def drhovecdT_oldschool(model,T, rhovec, fluids): - rhovecL = rhovec[0:2] - rhovecV = rhovec[2::] - tracer = vle.VLEIsolineTracer(vle.VLEIsolineTracer.imposed_variable.IMPOSED_T, 20000, 'HEOS', fluids) - def get_derivs(T, rhovec): - return tracer.get_derivs(T,rhovec)#vle.VLEIsolineTracer(vle.VLEIsolineTracer.imposed_variable.IMPOSED_T, 20000, 'HEOS', fluids).get_derivs(T, rhovec) - - derV = get_derivs(T, rhovecV) - derL = get_derivs(T, rhovecL) - # dT = 1e-3 - # print(derL.dpdT__constrhovec(), (get_derivs(T+dT, rhovecV).p() - get_derivs(T-dT, rhovecV).p())/(2*dT)) - AS = tracer.get_AbstractState_pointer() - R = AS.gas_constant() - # AS.set_mole_fractions(z) - z = rhovecL/rhovecL.sum() +def traceT_arclength(model, T, rhovec0, *, kwargs={}): - rhoV = sum(rhovecV) - rhoL = sum(rhovecL) - DELTAs2 = np.array([derV.d2psir_dTdrhoi__constrhoj(i) - derL.d2psir_dTdrhoi__constrhoj(i) + R*np.log(rhovecV[i]/rhoV/(rhovecL[i]/rhoL)) for i in range(2)]) # Column vector - DELTAs = np.array([derV.d2psir_dTdrhoi__constrhoj(i) - derL.d2psir_dTdrhoi__constrhoj(i) + R*np.log(rhovecV[i]/rhovecL[i]) for i in range(2)]) # Column vector - DELTAbetarho = derV.dpdT__constrhovec() - derL.dpdT__constrhovec() # double - PSIL = derL.get_Hessian() - PSIV = derV.get_Hessian() - drhovecL_dT = (np.dot(DELTAs,rhovecV)-DELTAbetarho)/np.dot(np.dot(PSIL,rhovecV-rhovecL),z)*np.array(z) - drhovecV_dT = np.linalg.solve(PSIV, np.dot(PSIL,drhovecL_dT)-DELTAs) - return np.array(drhovecL_dT.tolist()+drhovecV_dT.tolist()) + R = model.get_R(np.array([0.0, 1.0])) + print(T) + c = 1.0 + def rhovecprime(t, rhovec): + tic = timeit.default_timer() + drhovecdpL, drhovecdpV = teqp.get_drhovecdp_Tsat(model, T, rhovec[0:2], rhovec[2::]) + toc = timeit.default_timer() + # print(toc-tic) + + def norm(x): + return (x*x).sum()**0.5 + dpdt = (norm(drhovecdpL) + norm(drhovecdpV))**-0.5 + der = np.zeros_like(rhovec) + der[0:2] = (drhovecdpL*dpdt).squeeze() + der[2:4] = (drhovecdpV*dpdt).squeeze() + # print(rhovec, rhovec[0]+rhovec[1], rhovec[2]+rhovec[3]) + return c*der + + der_init = rhovecprime(0, rhovec0) + if np.any(rhovec0 + der_init*1e-6 < 0): + c *= -1 + # print('init', der_init, T) + + events = [lambda t,x: x[0], lambda t,x: x[1], + lambda t,x: x[2], lambda t,x: x[3]] + events.append(lambda t, z: ((z[0]+z[1])/(z[2]+z[3])-1)-0.2) + # class StepCounter(): + # def __init__(self, Nmax): + # self.counter = 0 + # self.Nmax = Nmax + # def __call__(self, t, z): + # self.counter += 1 + # v = self.Nmax-self.counter+0.5 + # return v + # events.append(StepCounter(200)) + for e in events: + e.direction = -1 + e.terminal = True + + tic = timeit.default_timer() + sol = solve_ivp(rhovecprime, [0.0, 3500000], y0=rhovec0.copy(), method='RK45',dense_output=True, events=events)#, rtol=1e-8) + # print(sol.t_events, sol.y_events) + # print(sol.message) + toc = timeit.default_timer() + print(toc-tic,'s for parametric') + t = np.linspace(np.min(sol.t), np.max(sol.t), 1000) + soly = sol.sol(t) + x = soly[0,:]/(soly[0,:] + soly[1,:]) + y = soly[2,:]/(soly[2,:] + soly[3,:]) + p = [teqp.get_pr(model, T, soly[0:2,j]) + R*T*soly[0:2,j].sum() for j in range(len(t))] + plt.plot(x, p, 'r', **kwargs) + plt.plot(y, p, 'g', **kwargs) + # print(x,p) def drhovecdT_isopleth(model, T, rhovec): assert(len(rhovec)==4) @@ -137,7 +169,7 @@ def drhovecdT_isopleth(model, T, rhovec): rhoV = sum(rhovecV) xL = rhovecL/rhoL xV = rhovecV/rhoV - R = 8.31446161815324 + R = model.get_R(xL) deltas = teqp.get_dchempotdT_autodiff(model, T, rhovecV) - teqp.get_dchempotdT_autodiff(model, T, rhovecL) deltarho = rhovecV-rhovecL dpdTV = R*rhoV*(1+model.get_Ar01(T, rhoV, xV)-model.get_Ar11(T, rhoV, xV)) @@ -147,6 +179,100 @@ def drhovecdT_isopleth(model, T, rhovec): drhovecdTV = np.linalg.solve(Hvap, Hliq@drhovecdTL-deltas) return np.array(drhovecdTL.tolist()+drhovecdTV.tolist()) +def robust_VLE(model, T, Tc, rhoc): + DeltaT = 1e-2*Tc + Tg = Tc-DeltaT + if Tg < 0: + raise ValueError("T > Tc") + rholiq, rhovap = teqp.extrapolate_from_critical(model, Tc, rhoc, Tg) + if rholiq < 0 or rhovap < 0: + raise ValueError("Negative density obtained from critical extrapolation") + rholiq, rhovap = teqp.pure_VLE_T(model, Tg, rholiq, rhovap, 100) + + z = np.array([1.0]) + R = model.get_R(z) + + def dpdTsat(model, T, rhoL, rhoV): + """ dp/dT = ((hV-hL)/T)/(vV-vL) + The ideal parts of enthalpy cancel, leaving just the residual parts + """ + numV = R*(model.get_Ar01(T, rhoV, z) + model.get_Ar10(T,rhoV,z)) + numL = R*(model.get_Ar01(T, rhoL, z) + model.get_Ar10(T,rhoL,z)) + num = numV-numL + den = 1/rhoV-1/rhoL + return num/den + + def get_drhodT_sat(model, T, rhoL, rhoV, Q): + dpdT = dpdTsat(model, T, rhoL, rhoV) + + rho = rhoL if Q == 0 else rhoV + Ar01 = model.get_Ar01(T, rho, z) + Ar02 = model.get_Ar02n(T, rho, z)[2] + Ar11 = model.get_Ar11(T, rho, z) + + dpdrho__T = R*T*(1 + 2*Ar01 + Ar02) + dpdT__rho = R*rho*(1 + Ar01 - Ar11) + + drhodT__p = -dpdT__rho/dpdrho__T + drhodp__T = 1/dpdrho__T + return drhodT__p + drhodp__T*dpdT + + def rhoprime(T, rhoLrhoV): + rhoL, rhoV = rhoLrhoV + drhoLdT = get_drhodT_sat(model, T, rhoL, rhoV, 0) + drhoVdT = get_drhodT_sat(model, T, rhoL, rhoV, 1) + return np.array([drhoLdT, drhoVdT]) + + sol = solve_ivp(rhoprime, [Tg, T], y0=[rholiq, rhovap], method='RK45', dense_output=False, rtol=1e-8) + rholiq, rhovap = sol.y[:,-1] + rholiq, rhovap = teqp.pure_VLE_T(model, T, rholiq, rhovap, 100) + return rholiq, rhovap + +def prettyPX(model, puremodels, ipure, Tvec): + """ + ipure: int + index (0-based) of the pure fluid model to use + """ + def plot_critical_curve(): + tic = timeit.default_timer() + Tcvec = model.get_Tcvec() + rhocvec = 1/model.get_vcvec() + k = 1 # Have to start at pure second component for now... In theory either are possible. + T0 = Tcvec[k] + rho0 = rhocvec + rho0[1-k] = 0 + curveJSON = teqp.trace_critical_arclength_binary(model, T0, rho0, "") + toc = timeit.default_timer() + print(toc-tic, 'to trace critical locus') + df = pandas.DataFrame(curveJSON) + df['z0 / mole frac.'] = df['rho0 / mol/m^3']/(df['rho0 / mol/m^3']+df['rho1 / mol/m^3']) + plt.plot(df['z0 / mole frac.'], df['p / Pa'], lw=2) + + def plot_isotherms(): + for T in Tvec: + puremodel = puremodels[ipure] + # rhoL, rhoV = robust_VLE(puremodel, T, puremodel.get_Tcvec()[0], 1/puremodel.get_vcvec()[0]) + rhoL = CP.PropsSI('Dmolar','T',T,'Q',0,names[ipure]) + rhoV = CP.PropsSI('Dmolar','T',T,'Q',1,names[ipure]) + if ipure == 0: + # Both phases are pure of the first component with index 0 + rhovec = np.array([rhoL, 0, rhoV, 0]) + else: + # Both phases are pure of the second component with index 1 + rhovec = np.array([0, rhoL, 0, rhoV]) + try: + traceT_arclength(model, T, rhovec.copy(), kwargs={'lw': 0.5}) + except BaseException as BE: + print(BE) + # raise + plot_critical_curve() + plot_isotherms() + + plt.gca().set(xlabel='$x_1$ / mole frac.', ylabel='$p$ / Pa') + plt.tight_layout(pad=0.2) + plt.savefig('pxdiagram.pdf') + plt.show() + def main(names): T = 300 @@ -154,8 +280,8 @@ def main(names): tracer = vle.VLEIsolineTracer(IMPOSED_T, T, backend, names) # Set flags tracer.set_allowable_error(1e-6) - tracer.polishing(False) - tracer.set_debug_polishing(True) + tracer.polishing(True) + tracer.set_debug_polishing(False) tracer.set_forwards_integration(True) tracer.set_unstable_termination(False) @@ -179,8 +305,8 @@ def main(names): # ax4.plot(x, rhoVmat[:,1],dashes = [2,2], color='r') dx0dpL = np.diff(x)/np.diff(pL) dx1dpL = np.diff(x1)/np.diff(pL) - ax4.plot(x, pL) - ax4.plot(y, pL, dashes=[2, 2]) + ax4.plot(x, pL, dashes=[2,2]) + ax4.plot(y, pL, dashes=[2,2]) model = teqp.build_multifluid_model(names, '../mycp', '../mycp/dev/mixtures/mixture_binary_pairs.json') @@ -202,14 +328,39 @@ def main(names): traceT(model, T, rhovec.copy()) - for f in np.linspace(0.9, 1.1, 100): - modeltweak = teqp.build_BIPmodified(model, {'betaT': 1.0, 'gammaT': 1.001633952*f, 'betaV': 1.0, 'gammaV': 1.006268954}) + # for f in np.linspace(0.9, 1.1, 100): + # modeltweak = teqp.build_BIPmodified(model, {'betaT': 1.0, 'gammaT': 1.001633952*f, 'betaV': 1.0, 'gammaV': 1.006268954}) + # try: + # traceT(modeltweak, T, rhovec.copy(), kwargs=dict(lw=0.5, dashes=[3,1,1,1])) + # except: + # pass + + for increment in np.linspace(-120,60,30): + T2 = T+increment try: - traceT(modeltweak, T, rhovec.copy(), kwargs=dict(lw=0.5, dashes=[3,1,1,1])) - except: - pass + AS = CP.AbstractState('HEOS', names[1]) + AS.update(CP.QT_INPUTS, 0, T2) + rhoL = AS.saturated_liquid_keyed_output(CP.iDmolar) + rhoV = AS.saturated_vapor_keyed_output(CP.iDmolar) + rhovec = np.array([0, rhoL, 0, rhoV]) + traceT_arclength(model, T2, rhovec.copy(), kwargs={'lw':0.5}) + except BaseException as BE: + print(T2, BE) - plt.ylim(0.00019e6, 0.026e6) + tic = timeit.default_timer() + Tcvec = model.get_Tcvec() + rhocvec = 1/model.get_vcvec() + T0 = Tcvec[1] + rho0 = rhocvec*np.array([1,0]) + curveJSON = teqp.trace_critical_arclength_binary(model, T0, rho0, "") + toc = timeit.default_timer() + print(toc-tic, 'to trace critical locus') + + df = pandas.DataFrame(curveJSON) + df['z0 / mole frac.'] = df['rho0 / mol/m^3']/(df['rho0 / mol/m^3']+df['rho1 / mol/m^3']) + plt.plot(df['z0 / mole frac.'], df['p / Pa'], lw=2) + + # plt.ylim(0.00019e6, 0.026e6) plt.gca().set(xlabel='$x_1$ / mole frac.', ylabel='$p$ / Pa') plt.tight_layout(pad=0.2) plt.show() @@ -219,37 +370,28 @@ def trace_isopleth(names): AS.set_mole_fractions([0.25, 0.75]) AS.build_phase_envelope("") PE = AS.get_phase_envelope_data() - print(dir(PE)) model = teqp.build_multifluid_model(names, '../mycp', '../mycp/dev/mixtures/mixture_binary_pairs.json') i = 0 rhovec0 = np.array([ PE.rhomolar_liq[i]*PE.x[0][i], PE.rhomolar_liq[i]*PE.x[1][i], PE.rhomolar_vap[i]*PE.y[0][i], PE.rhomolar_vap[i]*PE.y[1][i]]) - T = PE.T[0] - dT = 1e-2 + T = PE.T[i] + dT = 1e-1 R = model.get_R(np.array([1.0])) rhovec = rhovec0.copy() - for i in range(10000): - xL0 = rhovec[0]/rhovec[0:2].sum() - molefrac = np.array([xL0, 1-xL0]) - rhovecL = rhovec[0:2] - rhoL = rhovecL.sum() - rhovecV = rhovec[2::] - rhoV = rhovecV.sum() - - # plt.plot(T, rhoL, 'o') - # plt.plot(T, rhoV, 'x') - - vec1 = drhovecdT_isopleth(model, T, rhovec) - rhovec += vec1*dT - T += dT - - rhovecL = rhovec[0:2] - rhoL = rhovecL.sum() - p = rhoL*R*T + teqp.get_pr(model, T, rhovecL) - print(T, xL0, rhoL) - plt.plot(T, p, 'x') + + def rhovecprime(T, rhovec): + return drhovecdT_isopleth(model=model, T=T, rhovec=rhovec) + tic = timeit.default_timer() + Tmax = 430 + sol = solve_ivp(rhovecprime, [T, Tmax], y0=rhovec0.copy(), method='RK45',dense_output=True, t_eval = np.linspace(T,Tmax,1000)) + p = [teqp.get_pr(model, T, sol.y[0:2,j]) + R*T*sol.y[0:2,j].sum() for T,j in zip(sol.t,range(len(sol.t)))] + x = sol.y[0,:]/(sol.y[0,:]+sol.y[1,:]) + y = sol.y[2,:]/(sol.y[2,:]+sol.y[3,:]) + toc = timeit.default_timer() + plt.plot(sol.t, p) + print(toc-tic) # plt.plot(PE.T, PE.rhomolar_vap) # plt.plot(PE.T, PE.rhomolar_liq) @@ -257,6 +399,15 @@ def trace_isopleth(names): plt.show() if __name__ == '__main__': - names = ['n-Hexane', 'n-Octane'] # main(names) - trace_isopleth(names) \ No newline at end of file + # trace_isopleth(names) + + # names = ['Methane', 'n-Propane'] + # model = teqp.build_multifluid_model(names, '../mycp', '../mycp/dev/mixtures/mixture_binary_pairs.json') + # puremodel = teqp.build_multifluid_model(['n-Propane'], '../mycp', '../mycp/dev/mixtures/mixture_binary_pairs.json') + # prettyPX(model, puremodel, np.linspace(180, 365, 100)) + + names = ['n-Butane', 'HydrogenSulfide'] + model = teqp.build_multifluid_model(names, '../mycp', '../mycp/dev/mixtures/mixture_binary_pairs.json',{'estimate':'linear'}) + puremodels = [teqp.build_multifluid_model([name], '../mycp', '../mycp/dev/mixtures/mixture_binary_pairs.json') for name in names] + prettyPX(model, puremodels, 0, np.linspace(230, 420, 100)) \ No newline at end of file -- GitLab