15template<
typename Model>
using is_AbstractModel =
typename std::is_base_of<teqp::cppinterface::AbstractModel, Model>;
18template<
typename Model,
typename TYPE=
double, ADBackends backend = ADBackends::autodiff>
27 const Eigen::ArrayXd molefracs;
34 IsothermPureVLEResiduals(
const Model& model,
const TYPE& T,
const std::optional<Eigen::ArrayXd>& molefracs_ = std::nullopt) : m_model(model), m_T(T),
35 molefracs( (molefracs_) ? molefracs_.value() : Eigen::ArrayXd::Ones(1,1)) {
37 Rr = m_model.R(molefracs);
38 R0 = m_model.R(molefracs);
41 Rr = m_model.get_R(molefracs);
42 R0 = m_model.get_R(molefracs);
48 template<
typename Rho>
52 return tdx::template get_Ar0n<2, backend>(m_model, m_T, rho, molefracs);
55 return m_model.get_Ar02n(m_T, rho, molefracs);
60 assert(rhovec.size() == 2);
64 const auto rhomolarL = rhovecL.sum(), rhomolarV = rhovecV.sum();
67 double R0_over_Rr =
R0 /
Rr;
70 auto pRTL = rhomolarL*(R0_over_Rr + derL[1]);
71 auto dpRTLdrhoL = R0_over_Rr + 2*derL[1] + derL[2];
72 auto hatmurL = derL[1] + derL[0] + R0_over_Rr*log(rhomolarL);
73 auto dhatmurLdrho = (2*derL[1] + derL[2])/rhomolarL + R0_over_Rr/rhomolarL;
76 auto pRTV = rhomolarV*(R0_over_Rr + derV[1]);
77 auto dpRTVdrhoV = R0_over_Rr + 2*derV[1] + derV[2];
78 auto hatmurV = derV[1] + derV[0] + R0_over_Rr *log(rhomolarV);
79 auto dhatmurVdrho = (2*derV[1] + derV[2])/rhomolarV + R0_over_Rr/rhomolarV;
83 J(0, 1) = -dpRTVdrhoV;
85 y(1) = hatmurL - hatmurV;
86 J(1, 0) = dhatmurLdrho;
87 J(1, 1) = -dhatmurVdrho;
106template<
typename Res
idual,
typename Scalar=
double>
108 using EArray = Eigen::Array<Scalar, 2, 1>;
109 auto rhovec = (EArray() << rhoL, rhoV).finished();
110 auto r0 = resid.call(rhovec);
111 auto J = resid.Jacobian(rhovec);
112 for (
int iter = 0; iter < maxiter; ++iter){
114 r0 = resid.call(rhovec);
115 J = resid.Jacobian(rhovec);
117 auto v = J.matrix().colPivHouseholderQr().solve(-r0.matrix()).array().eval();
118 auto rhovecnew = (rhovec + v).eval();
125 auto minval = std::numeric_limits<Scalar>::epsilon();
127 if (((rhovecnew - rhovec).cwiseAbs() < minval).all()) {
130 if ((r0.cwiseAbs() < minval).all()) {
139 Eigen::ArrayXd molefracs_{Eigen::ArrayXd::Ones(1,1)};
140 if (molefracs){ molefracs_ = molefracs.value(); }
160 auto molefrac = (Eigen::ArrayXd(1) << 1.0).finished();
161 if (molefracs){ molefrac = molefracs.value(); }
163 auto R = model.
get_R(molefrac);
165 auto hrVLERTV = model.
get_Ar01(T, rhoV, molefrac) + model.
get_Ar10(T, rhoV, molefrac);
166 auto hrVLERTL = model.
get_Ar01(T, rhoL, molefrac) + model.
get_Ar10(T, rhoL, molefrac);
167 auto deltahr_over_T = R*(hrVLERTV-hrVLERTL);
168 auto dpsatdT = deltahr_over_T/(1/rhoV-1/rhoL);
186 nlohmann::json pure_spec;
187 Eigen::ArrayXd z{Eigen::ArrayXd::Ones(1,1)};
188 if (spec.contains(
"pure_spec")){
189 pure_spec = spec.at(
"pure_spec");
190 z = Eigen::ArrayXd(pure_spec.at(
"alternative_length").get<
int>()); z.setZero();
191 z(pure_spec.at(
"alternative_pure_index").get<
int>()) = 1;
194 auto [Tc, rhoc] =
solve_pure_critical(model, spec.at(
"Tcguess").get<
double>(), spec.at(
"rhocguess").get<
double>(), pure_spec);
197 double Tclose = spec.at(
"Tred").get<
double>()*Tc;
199 auto rhoLrhoVpolished =
pure_VLE_T(model, Tclose, rhoLrhoV[0], rhoLrhoV[1], spec.value(
"NVLE", 10), z);
200 if (rhoLrhoVpolished[0] == rhoLrhoVpolished[1]){
205 int Nstep = spec.at(
"Nstep");
206 double R = model.
R(z);
207 bool with_deriv = spec.at(
"with_deriv");
208 double dT = -(Tclose-T)/(Nstep-1);
210 for (
auto T_: Eigen::ArrayXd::LinSpaced(Nstep, Tclose, T)){
211 rhoLrhoVpolished =
pure_VLE_T(model, T_, rhoLrhoVpolished[0], rhoLrhoVpolished[1], spec.value(
"NVLE", 10), z);
218 auto dpsatdT =
dpsatdT_pure(model, T_, rhoLrhoVpolished[0], rhoLrhoVpolished[1], z);
219 auto get_drhodT = [&z, R, dpsatdT](
const AbstractModel& model,
double T,
double rho){
220 auto dpdrho = R*T*(1 + 2*model.get_Ar01(T, rho, z) + model.get_Ar02(T, rho, z));
221 auto dpdT = R*rho*(1 + model.get_Ar01(T, rho, z) - model.get_Ar11(T, rho, z));
222 return -dpdT/dpdrho + dpsatdT/dpdrho;
224 auto drhodTL = get_drhodT(model, T_, rhoLrhoVpolished[0]);
225 auto drhodTV = get_drhodT(model, T_, rhoLrhoVpolished[1]);
227 auto DeltarhoL = dT*drhodTL, DeltarhoV = dT*drhodTV;
228 rhoLrhoVpolished[0] += DeltarhoL;
229 rhoLrhoVpolished[1] += DeltarhoV;
233 if (!std::isfinite(rhoLrhoVpolished[0])){
236 if (rhoLrhoVpolished[0] == rhoLrhoVpolished[1]){
240 return rhoLrhoVpolished;
243#define VLE_PURE_FUNCTIONS_TO_WRAP \
248#define X(f) template <typename TemplatedModel, typename ...Params, \
249typename = typename std::enable_if<is_not_AbstractModel<TemplatedModel>::value>::type> \
250inline auto f(const TemplatedModel& model, Params&&... params){ \
251 auto view = teqp::cppinterface::adapter::make_cview(model); \
252 const AbstractModel& am = *view.get(); \
253 return f(am, std::forward<Params>(params)...); \
257#undef VLE_PURE_FUNCTIONS_TO_WRAP
#define VLE_PURE_FUNCTIONS_TO_WRAP
Eigen::Array< TYPE, 1, 1 > EigenArray1
auto call(const EigenArray &rhovec)
const auto & get_errors()
Eigen::Array< TYPE, 2, 2 > EigenMatrix
auto get_der(const Rho &rho)
auto Jacobian(const EigenArray &)
IsothermPureVLEResiduals(const Model &model, const TYPE &T, const std::optional< Eigen::ArrayXd > &molefracs_=std::nullopt)
Eigen::Array< TYPE, 2, 1 > EigenArray
virtual double get_Ar01(const double T, const double rho, const REArrayd &molefrac) const =0
virtual double get_R(const EArrayd &) const =0
virtual double get_Ar10(const double T, const double rho, const REArrayd &molefrac) const =0
double R(const EArrayd &x) const
std::negation< is_AbstractModel< Model > > is_not_AbstractModel
auto pure_trace_VLE(const teqp::cppinterface::AbstractModel &model, const double T, const nlohmann::json &spec)
auto do_pure_VLE_T(Residual &resid, Scalar rhoL, Scalar rhoV, int maxiter)
auto solve_pure_critical(const Model &model, const Scalar T0, const Scalar rho0, const std::optional< nlohmann::json > &flags=std::nullopt)
Eigen::Array< double, 2, 1 > extrapolate_from_critical(const Model &model, const Scalar &Tc, const Scalar &rhoc, const Scalar &T, const std::optional< Eigen::ArrayXd > &z=std::nullopt)
IterationFailure IterationError
auto dpsatdT_pure(const teqp::cppinterface::AbstractModel &model, double T, double rhoL, double rhoV, const std::optional< Eigen::ArrayXd > &molefracs=std::nullopt)
typename std::is_base_of< teqp::cppinterface::AbstractModel, Model > is_AbstractModel
auto pure_VLE_T(const teqp::cppinterface::AbstractModel &model, double T, double rhoL, double rhoV, int maxiter, const std::optional< Eigen::ArrayXd > &molefracs=std::nullopt)