teqp 0.22.0
Loading...
Searching...
No Matches
LKP.hpp
Go to the documentation of this file.
1#pragma once // Only include header once in a compilation unit if it is included multiple times
2
3#include <set>
4
5#include "teqp/constants.hpp" // used for R
6#include "teqp/types.hpp" // needed for forceeval
7#include "teqp/exceptions.hpp" // to return teqp error messages
8
9#include "nlohmann/json.hpp"
10
11namespace teqp{
12namespace LKP{
13
15 std::vector<double> b, c, d;
16 double beta, gamma_, omega;
17};
18
19class LKPMix{
20public:
21 const LKPFluidParameters simple{{0.0, 0.1181193, 0.265728, 0.154790, 0.303230e-1}, // b, with pad to match indices
22 {0.0, 0.236744e-1, 0.186984e-1, 0, 0.427240e-1}, // c, with pad to match indices
23 {0, 0.155428e-4, 0.623689e-4}, // d, with pad to match indices
24 0.653920, 0.601670e-1, 0.0}, // beta, gamma, omega
25 ref{{0, 0.2026579, 0.331511, 0.276550e-1, 0.203488}, // b, with pad to match indices
26 {0, 0.313385e-1, 0.503618e-1, 0.169010e-1,0.41577e-1}, // c, with pad to match indices
27 {0, 0.487360e-4, 0.740336e-5}, // d, with pad to match indices
28 1.226, 0.03754, 0.3978}; // beta, gamma, omega
29 const std::vector<double> Tcrit, pcrit, acentric;
30 const double m_R;
31 const std::vector<std::vector<double>> kmat;
32
33 LKPMix(const std::vector<double>& Tcrit, const std::vector<double>& pcrit, const std::vector<double>& acentric, double R, const std::vector<std::vector<double>>& kmat) : Tcrit(Tcrit), pcrit(pcrit), acentric(acentric), m_R(R), kmat(kmat){
34 std::size_t N = Tcrit.size();
35 if (std::set<std::size_t>{Tcrit.size(), pcrit.size(), acentric.size()}.size() > 1){
36 throw teqp::InvalidArgument("The arrays should all be the same size.");
37 }
38 std::string kmaterr = "The kmat is the wrong size. It should be square with dimension " + std::to_string(N);
39 if (kmat.size() != N){
40 throw teqp::InvalidArgument(kmaterr);
41 }
42 else{
43 for (auto& krow: kmat){
44 if(krow.size() != N){
45 throw teqp::InvalidArgument(kmaterr);
46 }
47 }
48 }
49 }
50
51 template<class VecType>
52 auto R(const VecType& /*molefrac*/) const { return m_R; }
53
55 template<typename TTYPE, typename RhoType, typename ZcType>
56 auto alphar_func(const TTYPE& tau, const RhoType& delta, const ZcType& Zc, const LKPFluidParameters& params) const {
57 auto B = params.b[1] - params.b[2]*tau - params.b[3]*powi(tau, 2) - params.b[4]*powi(tau, 3);
58 auto C = params.c[1] - params.c[2]*tau + params.c[3]*powi(tau, 3);
59 auto D = params.d[1] + params.d[2]*tau;
60 auto deltaZc = forceeval(delta/Zc);
61 return forceeval(B/Zc*delta + 1.0/2.0*C*powi(deltaZc, 2) + 1.0/5.0*D*powi(deltaZc, 5) - params.c[4]*powi(tau, 3)/(2*params.gamma_)*(params.gamma_*powi(deltaZc, 2)+params.beta+1.0)*exp(-params.gamma_*powi(deltaZc, 2)) + params.c[4]*powi(tau,3)/(2*params.gamma_)*(params.beta+1.0));
62 }
63
64 template<typename TTYPE, typename RhoType, typename VecType>
65 auto alphar(const TTYPE& T, const RhoType& rhomolar, const VecType& mole_fractions) const {
66
67 if (static_cast<std::size_t>(mole_fractions.size()) != acentric.size()){
68 throw teqp::InvalidArgument("The mole fractions should be of of size "+ std::to_string(acentric.size()));
69 }
70
71 const VecType& x = mole_fractions; // just an alias to save typing, no copy is invoked
72 std::decay_t<decltype(mole_fractions[0])> summer_omega = 0.0, summer_vcmix = 0.0, summer_Tcmix = 0.0;
73 double Ru = m_R;
74
75 for (auto i = 0; i < mole_fractions.size(); ++i){
76 summer_omega += mole_fractions[i]*acentric[i];
77 auto v_ci = (0.2905-0.085*acentric[i])*Ru*Tcrit[i]/pcrit[i];
78 for (auto j = 0; j < mole_fractions.size(); ++j){
79 auto v_cj = (0.2905-0.085*acentric[j])*Ru*Tcrit[j]/pcrit[j];
80 auto v_c_ij = 1.0/8.0*powi(cbrt(v_ci) + cbrt(v_cj), 3);
81 auto T_c_ij = kmat[i][j]*sqrt(Tcrit[i]*Tcrit[j]);
82 summer_vcmix += x[i]*x[j]*v_c_ij;
83 summer_Tcmix += x[i]*x[j]*pow(v_c_ij, 0.25)*T_c_ij;
84 }
85 }
86 auto omega_mix = summer_omega;
87 auto vc_mix = summer_vcmix;
88 auto Tc_mix = 1.0/pow(summer_vcmix, 0.25)*summer_Tcmix;
89// auto pc_mix = (0.2905-0.085*omega_mix)*Ru*Tc_mix/vc_mix;
90 auto Zc = forceeval(0.2905-0.085*omega_mix);
91 auto tau = forceeval(Tc_mix/T);
92 auto delta = forceeval(vc_mix*rhomolar);
93
94 auto retval = (1.0-omega_mix/ref.omega)*alphar_func(tau, delta, Zc, simple) + (omega_mix/ref.omega)*alphar_func(tau, delta, Zc, ref);
95 return forceeval(retval);
96 }
97};
98
99// Factory function takes in JSON data and returns an instance of the LKPMix class
100inline auto make_LKPMix(const nlohmann::json& j){
101 return LKPMix(j.at("Tcrit / K"), j.at("pcrit / Pa"), j.at("acentric"), j.at("R / J/mol/K"), j.at("kmat"));
102}
103
104}
105}
const LKPFluidParameters ref
Definition LKP.hpp:25
auto R(const VecType &) const
Definition LKP.hpp:52
const LKPFluidParameters simple
Definition LKP.hpp:21
const std::vector< double > acentric
Definition LKP.hpp:29
LKPMix(const std::vector< double > &Tcrit, const std::vector< double > &pcrit, const std::vector< double > &acentric, double R, const std::vector< std::vector< double > > &kmat)
Definition LKP.hpp:33
const std::vector< double > pcrit
Definition LKP.hpp:29
auto alphar(const TTYPE &T, const RhoType &rhomolar, const VecType &mole_fractions) const
Definition LKP.hpp:65
const std::vector< double > Tcrit
Definition LKP.hpp:29
auto alphar_func(const TTYPE &tau, const RhoType &delta, const ZcType &Zc, const LKPFluidParameters &params) const
Calculate the contribution for one of the fluids, depending on the parameter set passed in.
Definition LKP.hpp:56
const double m_R
molar gas constant to be used in this model, in J/mol/K
Definition LKP.hpp:30
const std::vector< std::vector< double > > kmat
Definition LKP.hpp:31
auto make_LKPMix(const nlohmann::json &j)
Definition LKP.hpp:100
T powi(const T &x, int n)
From Ulrich Deiters.
Definition types.hpp:139
auto pow(const double &x, const double &e)
Definition types.hpp:195
auto forceeval(T &&expr)
Definition types.hpp:52
std::vector< double > d
Definition LKP.hpp:15
std::vector< double > b
Definition LKP.hpp:15
std::vector< double > c
Definition LKP.hpp:15