teqp 0.22.0
Loading...
Searching...
No Matches
activity_models.hpp
Go to the documentation of this file.
1#pragma once
2
4
6
10template<typename NumType>
12public:
13 template<typename TType, typename MoleFractions>
14 auto operator () (const TType& /*T*/, const MoleFractions& molefracs) const {
15 std::common_type_t<TType, decltype(molefracs[0])> val = 0.0;
16 return val;
17 }
18};
19
40template<typename NumType>
42
43public:
44 const std::vector<double> b;
45 const Eigen::ArrayXXd m, n;
46 WilsonResidualHelmholtzOverRT(const std::vector<double>& b, const Eigen::ArrayXXd& m, const Eigen::ArrayXXd& n) : b(b), m(m), n(n) {};
47
48 template<typename TType, typename MoleFractions>
49 auto combinatorial(const TType& /*T*/, const MoleFractions& molefracs) const {
50 if (b.size() != static_cast<std::size_t>(molefracs.size())){
51 throw teqp::InvalidArgument("Bad size of molefracs");
52 }
53
54 using TYPE = std::common_type_t<TType, decltype(molefracs[0])>;
55 // The denominator in Phi
56 TYPE Vtot = 0.0;
57 for (auto i = 0U; i < molefracs.size(); ++i){
58 auto v_i = b[i];
59 Vtot += molefracs[i]*v_i;
60 }
61
62 TYPE summer = 0.0;
63 for (auto i = 0U; i < molefracs.size(); ++i){
64 auto v_i = b[i];
65 // The ratio phi_i/z_i is expressed like this to better handle
66 // the case of z_i = 0, which would otherwise be a divide by zero
67 // in the case that the composition of one component is zero
68 auto phi_i_over_z_i = v_i/Vtot;
69 summer += molefracs[i]*log(phi_i_over_z_i);
70 }
71 return summer;
72 }
73
74 template<typename TType>
75 auto get_Aij(std::size_t i, std::size_t j, const TType& T) const{
76 return forceeval(m(i,j)*T + n(i,j));
77 }
78
79 template<typename TType, typename MoleFractions>
80 auto total(const TType& T, const MoleFractions& molefracs) const {
81
82 using TYPE = std::common_type_t<TType, decltype(molefracs[0])>;
83 TYPE summer = 0.0;
84 for (auto i = 0U; i < molefracs.size(); ++i){
85 auto v_i = b[i];
86 TYPE summerj = 0.0;
87 for (auto j = 0U; j < molefracs.size(); ++j){
88 auto v_j = b[j];
89 auto Aij = get_Aij(i,j,T);
90 auto Omega_ji = v_j/v_i*exp(-Aij/T);
91 summerj += molefracs[j]*Omega_ji;
92 }
93 summer += molefracs[i]*log(summerj);
94 }
95 return forceeval(-summer);
96 }
97
98 // Returns ares/RT
99 template<typename TType, typename MoleFractions>
100 auto operator () (const TType& T, const MoleFractions& molefracs) const {
101 return forceeval(total(T, molefracs) - combinatorial(T, molefracs));
102 }
103};
104
106// \note This approach works well except that... the derivatives at the pure fluid endpoints don't. So this is more a record as a failed idea
107// */
108//template<typename NumType>
109//class BinaryBetaResidualHelmholtzOverRT {
110//
111//public:
112// const std::vector<double> c;
113// BinaryBetaResidualHelmholtzOverRT(const std::vector<double>& c) : c(c) {};
114//
115// // Returns ares/RT
116// template<typename TType, typename MoleFractions>
117// auto operator () (const TType& /*T*/, const MoleFractions& molefracs) const {
118// if (molefracs.size() != 2){
119// throw teqp::InvalidArgument("Must be size of 2");
120// }
121// std::decay_t<std::common_type_t<TType, decltype(molefracs[0])>> out = c[0]*pow(molefracs[0], c[1])*pow(molefracs[1], c[2]);
122// return out;
123// }
124//};
125
126template<typename NumType>
128
129public:
130 const std::vector<double> c;
131 BinaryInvariantResidualHelmholtzOverRT(const std::vector<double>& c) : c(c) {};
132
133 // Returns ares/RT
134 template<typename TType, typename MoleFractions>
135 auto operator () (const TType& /*T*/, const MoleFractions& molefracs) const {
136 if (molefracs.size() != 2){
137 throw teqp::InvalidArgument("Must be size of 2");
138 }
139 std::decay_t<std::common_type_t<TType, decltype(molefracs[0])>> out = c[0]*molefracs[0]*molefracs[1]*(c[1] + c[2]*molefracs[1]);
140 return out;
141 }
142};
143
145
146inline ResidualHelmholtzOverRTVariant ares_model_factory(const nlohmann::json& armodel) {
147
148 std::string type = armodel.at("type");
149 if (type == "Wilson"){
150 std::vector<double> b = armodel.at("b");
151 auto mWilson = build_square_matrix(armodel.at("m"));
152 auto nWilson = build_square_matrix(armodel.at("n"));
153 return WilsonResidualHelmholtzOverRT<double>(b, mWilson, nWilson);
154 }
155// else if (type == "binaryBeta"){
156// std::vector<double> c = armodel.at("c");
157// return BinaryBetaResidualHelmholtzOverRT<double>(c);
158// }
159 else if (type == "binaryInvariant"){
160 std::vector<double> c = armodel.at("c");
162 }
163 else if (type == "COSMO-SAC-2010"){
164 std::vector<double> A_COSMOSAC_A2 = armodel.at("A_COSMOSAC / A^2");
165 std::vector<double> V_COSMOSAC_A3 = armodel.at("V_COSMOSAC / A^3");
166 std::vector<COSMOSAC::FluidSigmaProfiles> profiles;
167 for (auto& el : armodel.at("profiles")){
169 auto get_ = [](const auto& j){
171 j.at("sigma / e/A^2").template get<std::vector<double>>(),
172 j.at("p(sigma)*A / A^2").template get<std::vector<double>>()
173 };
174 };
175 prof.nhb = get_(el.at("nhb"));
176 prof.oh = get_(el.at("oh"));
177 prof.ot = get_(el.at("ot"));
178 profiles.push_back(prof);
179 }
181 if (armodel.contains("constants")){
182 const auto &jconstants = armodel.at("constants");
183 constants.A_ES = jconstants.value("A_ES / kcal A^4 /(mol e^2)", constants.A_ES);
184 constants.B_ES = jconstants.value("B_ES / kcal A^4 K^2/(mol e^2)", constants.B_ES);
185 constants.fast_Gamma = jconstants.value("fast_Gamma", constants.fast_Gamma);
186 }
187 std::cout << constants.A_ES << std::endl;
188 std::cout << constants.B_ES << std::endl;
189 return COSMOSAC::COSMO3(A_COSMOSAC_A2, V_COSMOSAC_A3, profiles, constants);
190 }
191 else{
192 throw teqp::InvalidArgument("bad type of ares model: " + type);
193 }
194};
195
196}
auto operator()(const TType &, const MoleFractions &molefracs) const
auto operator()(const TType &, const MoleFractions &molefracs) const
auto combinatorial(const TType &, const MoleFractions &molefracs) const
auto total(const TType &T, const MoleFractions &molefracs) const
auto get_Aij(std::size_t i, std::size_t j, const TType &T) const
auto operator()(const TType &T, const MoleFractions &molefracs) const
WilsonResidualHelmholtzOverRT(const std::vector< double > &b, const Eigen::ArrayXXd &m, const Eigen::ArrayXXd &n)
ResidualHelmholtzOverRTVariant ares_model_factory(const nlohmann::json &armodel)
std::variant< NullResidualHelmholtzOverRT< double >, WilsonResidualHelmholtzOverRT< double >, BinaryInvariantResidualHelmholtzOverRT< double >, COSMOSAC::COSMO3 > ResidualHelmholtzOverRTVariant
auto build_square_matrix
auto forceeval(T &&expr)
Definition types.hpp:52
SigmaProfile ot
The profile for the "other" segments.
Definition COSMOSAC.hpp:36
SigmaProfile oh
The profile for the OH-bonding segments.
Definition COSMOSAC.hpp:35
SigmaProfile nhb
The profile for the non-hydrogen-bonding segments.
Definition COSMOSAC.hpp:34