teqp 0.22.0
Loading...
Searching...
No Matches
ancillary_builder.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <iostream>
4
7
8namespace teqp{
9namespace ancillaries{
10
11using namespace teqp;
12using namespace teqp::cppinterface;
13
14auto build_ancillaries(const AbstractModel& model, double Tcritguess, double rhocritguess, double Tmin, std::optional<nlohmann::json> flags_ = std::nullopt)
15{
16 nlohmann::json flags = flags_.value_or(nlohmann::json::object());
17
18 bool ii = flags.is_object();
19 bool verify = flags.value("verify", true);
20 int Npts = flags.value("Npts", 1000);
21 double Theta_nearcrit = flags.value("Theta_nearcrit", 0.01);
22
23 auto [Tcrittrue, rhocrittrue] = model.solve_pure_critical(Tcritguess, rhocritguess);
24 double Tclosec = (1-Theta_nearcrit)*Tcrittrue;
25 auto rhovec = model.extrapolate_from_critical(Tcrittrue, rhocrittrue, Tclosec);
26 double rhoL = rhovec[0], rhoV = rhovec[1];
27 auto molefrac = (Eigen::ArrayXd(1) << 1.0).finished();
28 double R = model.get_R(molefrac);
29 double pcrittrue = rhocrittrue*R*Tcrittrue*(1+model.get_Ar01(Tcrittrue, rhocrittrue, molefrac));
30
31 double dT = (Tcrittrue-Tmin)/(Npts-1);
32
33 // Convenience function to get the density derivatives
34 auto getdrhodTs = [&R, &molefrac](const auto& model, double T, double rhoL, double rhoV){
35 double dpsatdT = model.dpsatdT_pure(T, rhoL, rhoV);
36
37 auto get_drhodT = [&](double T, double rho){
38 double dpdrho = R*T*(1 + 2*model.get_Ar01(T, rho, molefrac) + model.get_Ar02(T, rho, molefrac));
39 double dpdT = R*rho*(1 + model.get_Ar01(T, rho, molefrac) - model.get_Ar11(T, rho, molefrac));
40 return -dpdT/dpdrho + dpsatdT/dpdrho;
41 };
42
43 return std::make_tuple(get_drhodT(T, rhoL), get_drhodT(T, rhoV));
44 };
45
46 std::vector<double> Thetas_, rhoLs_, rhoVs_, pLs_;
47 for (int i = 0; i < Npts; ++i){
48 auto T = Tclosec - dT*i;
49 auto rhovec = model.pure_VLE_T(T, rhoL, rhoV, 10);
50 rhoL = rhovec[0]; rhoV = rhovec[1];
51 auto [drhodTL, drhodTV] = getdrhodTs(model, T, rhoL, rhoV);
52 rhoL += drhodTL*dT;
53 rhoV += drhodTV*dT;
54 T += dT;
55 auto Theta = (Tcrittrue-T)/Tcrittrue;
56 double pL = rhoL*R*T*(1+model.get_Ar01(T, rhoL, molefrac));
57
58 Thetas_.push_back(Theta);
59 rhoLs_.push_back(rhoL);
60 rhoVs_.push_back(rhoV);
61 pLs_.push_back(pL);
62 }
63 auto N = Thetas_.size();
64 auto pLs = Eigen::Map<Eigen::ArrayXd>(&(pLs_[0]), N);
65 auto rhoLs = Eigen::Map<Eigen::ArrayXd>(&(rhoLs_[0]), N);
66 auto rhoVs = Eigen::Map<Eigen::ArrayXd>(&(rhoVs_[0]), N);
67 auto Thetass = Eigen::Map<Eigen::ArrayXd>(&(Thetas_[0]), N);
68
69 // Solve the least-squares problem for the polynomial coefficients
70 Eigen::ArrayXd exponents = Eigen::ArrayXd::LinSpaced(10, 0, 4.5);
71 Eigen::MatrixXd A(N,exponents.size());
72 Eigen::VectorXd bL(N), bV(N), bpL(N);
73 for (auto i = 0; i < exponents.size(); ++i){
74 auto view = (Eigen::Map<Eigen::ArrayXd>(&(Thetass[0]), N));
75 A.col(i) = view.pow(exponents[i]);
76 }
77
78 bL = (rhoLs/rhocrittrue)-1;
79 auto TTr = 1.0-Thetass;
80 bV = (rhoVs/rhocrittrue).log()*TTr;
81 bpL = (pLs/pcrittrue).log()*TTr;
82
83 Eigen::ArrayXd cLarray = A.colPivHouseholderQr().solve(bL).array();
84 Eigen::ArrayXd cVarray = A.colPivHouseholderQr().solve(bV).array();
85 Eigen::ArrayXd cpLarray = A.colPivHouseholderQr().solve(bpL).array();
86
87 auto toj = [](const Eigen::ArrayXd& a){
88 std::vector<double> o(a.size());
89 Eigen::Map<Eigen::ArrayXd>(&(o[0]), o.size()) = a;
90 return o;
91 };
92
93 nlohmann::json jrhoL = {
94 {"T_r", Tcrittrue},
95 {"Tmax", Tcrittrue},
96 {"Tmin", Tmin},
97 {"type", "rhoLnoexp"},
98 {"description", "I'm a description"},
99 {"n", toj(cLarray)},
100 {"t", toj(exponents)},
101 {"reducing_value", rhocrittrue},
102 {"using_tau_r", false},
103 };
104 nlohmann::json jrhoV = {
105 {"T_r", Tcrittrue},
106 {"Tmax", Tcrittrue},
107 {"Tmin", Tmin},
108 {"type", "type"},
109 {"description", "I'm a description"},
110 {"n", toj(cVarray)},
111 {"t", toj(exponents)},
112 {"reducing_value", rhocrittrue},
113 {"using_tau_r", true},
114 };
115 nlohmann::json jpsat = {
116 {"T_r", Tcrittrue},
117 {"Tmax", Tcrittrue},
118 {"Tmin", Tmin},
119 {"type", "type"},
120 {"description", "I'm a description"},
121 {"n", toj(cpLarray)},
122 {"t", toj(exponents)},
123 {"reducing_value", pcrittrue},
124 {"using_tau_r", true},
125 };
126 nlohmann::json j{
127 {"rhoL", jrhoL},
128 {"rhoV", jrhoV},
129 {"pS", jpsat}
130 };
131 auto anc = MultiFluidVLEAncillaries(j);
132
133 if (verify){
134 // Verify
135 for (auto i = 0U; i < Thetas_.size(); ++i){
136 double T = (1-Thetas_[i])*Tcrittrue;
137
138 double rhoLanc = anc.rhoL(T);
139 double rhoVanc = anc.rhoV(T);
140// double panc = anc.pL(T);
141 if (std::abs(rhoLanc/rhoLs_[i]-1) > 1e-2){
142 std::cout << T << " " << rhoLs_[i] << " " << rhoLanc << std::endl;
143 }
144 if (std::abs(rhoVanc/rhoVs_[i]-1) > 1e-2){
145 std::cout << T << " " << rhoVs_[i] << " " << rhoVanc << std::endl;
146 }
147 }
148 }
149
150 return anc;
151}
152
153
154}
155}
virtual double get_Ar01(const double T, const double rho, const REArrayd &molefrac) const =0
double dpsatdT_pure(const double T, const double rhoL, const double rhoV) const
virtual double get_R(const EArrayd &) const =0
virtual double get_Ar02(const double T, const double rho, const REArrayd &molefrac) const =0
EArray2 extrapolate_from_critical(const double Tc, const double rhoc, const double Tgiven, const std::optional< Eigen::ArrayXd > &molefracs=std::nullopt) const
EArray2 pure_VLE_T(const double T, const double rhoL, const double rhoV, int maxiter, const std::optional< Eigen::ArrayXd > &molefracs=std::nullopt) const
std::tuple< double, double > solve_pure_critical(const double T, const double rho, const std::optional< nlohmann::json > &=std::nullopt) const
virtual double get_Ar11(const double T, const double rho, const REArrayd &molefrac) const =0
auto build_ancillaries(const AbstractModel &model, double Tcritguess, double rhocritguess, double Tmin, std::optional< nlohmann::json > flags_=std::nullopt)
auto view(const TemplatedModel &tp)