CoolProp 7.1.0
An open-source fluid property and humid air property database
UNIFACLibrary.cpp
Go to the documentation of this file.
1#include "UNIFACLibrary.h"
3#include "Configuration.h"
4
5namespace UNIFACLibrary {
6
7void UNIFACParameterLibrary::jsonize(std::string& s, rapidjson::Document& d) {
8 d.Parse<0>(s.c_str());
9 if (d.HasParseError()) {
10 throw -1;
11 } else {
12 return;
13 }
14}
15void UNIFACParameterLibrary::populate(rapidjson::Value& group_data, rapidjson::Value& interaction_data, rapidjson::Value& comp_data) {
16 if (CoolProp::get_config_bool(VTPR_ALWAYS_RELOAD_LIBRARY)) {
17 groups.clear();
18 interaction_parameters.clear();
19 components.clear();
20 }
21 // Schema should have been used to validate the data already, so by this point we are can safely consume the data without checking ...
22 for (rapidjson::Value::ValueIterator itr = group_data.Begin(); itr != group_data.End(); ++itr) {
23 Group g;
24 g.sgi = (*itr)["sgi"].GetInt();
25 g.mgi = (*itr)["mgi"].GetInt();
26 g.R_k = (*itr)["R_k"].GetDouble();
27 g.Q_k = (*itr)["Q_k"].GetDouble();
28 groups.push_back(g);
29 }
30 for (rapidjson::Value::ValueIterator itr = interaction_data.Begin(); itr != interaction_data.End(); ++itr) {
32 ip.mgi1 = (*itr)["mgi1"].GetInt();
33 ip.mgi2 = (*itr)["mgi2"].GetInt();
34 ip.a_ij = (*itr)["a_ij"].GetDouble();
35 ip.a_ji = (*itr)["a_ji"].GetDouble();
36 ip.b_ij = (*itr)["b_ij"].GetDouble();
37 ip.b_ji = (*itr)["b_ji"].GetDouble();
38 ip.c_ij = (*itr)["c_ij"].GetDouble();
39 ip.c_ji = (*itr)["c_ji"].GetDouble();
40 interaction_parameters.push_back(ip);
41 }
42 for (rapidjson::Value::ValueIterator itr = comp_data.Begin(); itr != comp_data.End(); ++itr) {
43 Component c;
44 c.inchikey = (*itr)["inchikey"].GetString();
45 c.registry_number = (*itr)["registry_number"].GetString();
46 c.name = (*itr)["name"].GetString();
47 c.Tc = (*itr)["Tc"].GetDouble();
48 c.pc = (*itr)["pc"].GetDouble();
49 c.acentric = (*itr)["acentric"].GetDouble();
50 c.molemass = (*itr)["molemass"].GetDouble();
51 // userid is an optional user identifier
52 if ((*itr).HasMember("userid")) {
53 c.userid = (*itr)["userid"].GetString();
54 }
55 // If provided, store information about the alpha function in use
56 if ((*itr).HasMember("alpha") && (*itr)["alpha"].IsObject()) {
57 rapidjson::Value& alpha = (*itr)["alpha"];
58 c.alpha_type = cpjson::get_string(alpha, "type");
60 } else {
61 c.alpha_type = "default";
62 }
63 if ((*itr).HasMember("alpha0") && (*itr)["alpha0"].IsArray()) {
65 }
66 rapidjson::Value& groups = (*itr)["groups"];
67 for (rapidjson::Value::ValueIterator itrg = groups.Begin(); itrg != groups.End(); ++itrg) {
68 int count = (*itrg)["count"].GetInt();
69 int sgi = (*itrg)["sgi"].GetInt();
70 if (has_group(sgi)) {
71 ComponentGroup cg(count, get_group(sgi));
72 c.groups.push_back(cg);
73 }
74 }
75 components.push_back(c);
76 }
77}
78void UNIFACParameterLibrary::populate(std::string& group_data, std::string& interaction_data, std::string& decomp_data) {
79 rapidjson::Document group_JSON;
80 jsonize(group_data, group_JSON);
81 rapidjson::Document interaction_JSON;
82 jsonize(interaction_data, interaction_JSON);
83 rapidjson::Document decomp_JSON;
84 jsonize(decomp_data, decomp_JSON);
85 populate(group_JSON, interaction_JSON, decomp_JSON);
86 m_populated = true;
87}
89 for (std::vector<Group>::const_iterator it = groups.begin(); it != groups.end(); ++it) {
90 if (it->sgi == sgi) {
91 return *it;
92 }
93 }
94 throw CoolProp::ValueError("Could not find group");
95}
97 for (std::vector<Group>::const_iterator it = groups.begin(); it != groups.end(); ++it) {
98 if (it->sgi == sgi) {
99 return true;
100 }
101 }
102 return false;
103}
104
106
107 // If both mgi are the same, yield all zeros for the interaction parameters
108 if (mgi1 == mgi2) {
110 ip.mgi1 = mgi1;
111 ip.mgi2 = mgi2;
112 ip.zero_out();
113 return ip;
114 }
115 for (std::vector<InteractionParameters>::const_iterator it = interaction_parameters.begin(); it != interaction_parameters.end(); ++it) {
116 if (it->mgi1 == mgi1 && it->mgi2 == mgi2) {
117 // Correct order, return it
118 return *it;
119 }
120 if (it->mgi2 == mgi1 && it->mgi1 == mgi2) {
121 // Backwards, swap the parameters
122 InteractionParameters ip = *it;
123 ip.swap();
124 return ip;
125 }
126 }
127 throw CoolProp::ValueError(format("Could not find interaction between pair mgi[%d]-mgi[%d]", static_cast<int>(mgi1), static_cast<int>(mgi2)));
128}
129
130Component UNIFACParameterLibrary::get_component(const std::string& identifier, const std::string& value) const {
131 if (identifier == "name") {
132 for (std::vector<Component>::const_iterator it = components.begin(); it != components.end(); ++it) {
133 if (it->name == value) {
134 return *it;
135 }
136 }
137 }
138 throw CoolProp::ValueError(format("Could not find component: %s with identifier: %s", value.c_str(), identifier.c_str()));
139}
140
141}; /* namespace UNIFACLibrary */
142
143#if defined(ENABLE_CATCH)
144# include <catch2/catch_all.hpp>
145
146# include "UNIFAC.h"
147
148TEST_CASE("Check Poling example for UNIFAC", "[UNIFAC]") {
149 std::string acetone_pentane_groups =
150 "[{ \"Tc\": 508.1, \"acentric\": 0.3071, \"groups\": [ { \"count\": 1, \"sgi\": 1 }, {\"count\": 1, \"sgi\": 18 } ], \"molemass\": 0.44, "
151 "\"inchikey\": \"?????????????\", \"name\": \"Acetone\", \"pc\": 4700000.0, \"registry_number\": \"67-64-1\", \"userid\": \"\" }, { \"Tc\": "
152 "469.7000000000001, \"acentric\": 0.251, \"molemass\": 0.44, \"groups\": [ { \"count\": 2, \"sgi\": 1 }, { \"count\": 3, \"sgi\": 2 } ], "
153 "\"inchikey\": \"?????????????\", \"name\": \"n-Pentane\", \"pc\": 3370000.0, \"registry_number\": \"109-66-0\", \"userid\": \"\" } ]";
154 std::string groups = "[{\"Q_k\": 0.848, \"R_k\": 0.9011, \"maingroup_name\": \"CH2\", \"mgi\": 1, \"sgi\": 1, \"subgroup_name\": \"CH3\"},"
155 "{\"Q_k\": 0.540, \"R_k\": 0.6744, \"maingroup_name\": \"CH2\", \"mgi\": 1, \"sgi\": 2, \"subgroup_name\": \"CH2\"},"
156 "{\"Q_k\": 1.488, \"R_k\": 1.6724, \"maingroup_name\": \"CH2CO\", \"mgi\": 9, \"sgi\": 18, \"subgroup_name\": \"CH3CO\"}]";
157 std::string interactions =
158 "[{\"a_ij\": 476.4, \"a_ji\": 26.76, \"b_ij\": 0.0, \"b_ji\": 0.0, \"c_ij\": 0.0, \"c_ji\": 0.0, \"mgi1\": 1, \"mgi2\": 9}]";
159
160 SECTION("Validate AC for acetone + n-pentane") {
162 CHECK_NOTHROW(lib.populate(groups, interactions, acetone_pentane_groups));
163 UNIFAC::UNIFACMixture mix(lib, 1.0);
164 std::vector<std::string> names;
165 names.push_back("Acetone");
166 names.push_back("n-Pentane");
167 mix.set_components("name", names);
168 mix.set_interaction_parameters();
169
170 std::vector<double> z(2, 0.047);
171 z[1] = 1 - z[0];
172 mix.set_mole_fractions(z);
173 CHECK_NOTHROW(mix.set_temperature(307));
174
175 double lngammaR0 = mix.ln_gamma_R(1.0 / 307, 0, 0);
176 double lngammaR1 = mix.ln_gamma_R(1.0 / 307, 1, 0);
177 CAPTURE(lngammaR0);
178 CAPTURE(lngammaR1);
179 CHECK(std::abs(lngammaR0 - 1.66) < 1e-2);
180 CHECK(std::abs(lngammaR1 - 5.68e-3) < 1e-3);
181
182 std::vector<double> gamma(2);
183 mix.activity_coefficients(1.0 / 307, z, gamma);
184 CAPTURE(gamma[0]);
185 CAPTURE(gamma[1]);
186 CHECK(std::abs(gamma[0] - 4.99) < 1e-2);
187 CHECK(std::abs(gamma[1] - 1.005) < 1e-3);
188 };
189};
190
191#endif