CoolProp 6.8.0
An open-source fluid property and humid air property database
PCSAFTLibrary.cpp
Go to the documentation of this file.
1#include <string>
2#include <map>
3#include "PCSAFTLibrary.h"
4#include "all_pcsaft_JSON.h" // Makes a std::string variable called all_pcsaft_JSON
5#include "pcsaft_fluids_schema_JSON.h" // Makes a std::string variable called pcsaft_fluids_schema_JSON
6#include "mixture_binary_pairs_pcsaft_JSON.h" // Makes a std::string variable called mixture_binary_pairs_pcsaft_JSON
7#include "rapidjson_include.h"
8#include "CPstrings.h"
9#include "CoolProp.h"
10#include "Configuration.h"
12#include "CoolPropTools.h"
13
14namespace CoolProp {
15
16std::string get_mixture_binary_pair_pcsaft(const std::string& CAS1, const std::string& CAS2, const std::string& key) {
18}
19
20void set_mixture_binary_pair_pcsaft(const std::string& CAS1, const std::string& CAS2, const std::string& key, const double value) {
22}
23
24namespace PCSAFTLibrary {
25
26static PCSAFTLibraryClass library;
27
29 return library;
30}
31
33 // This JSON formatted string comes from the all_pcsaft_JSON.h header which is a C++-escaped version of the JSON file
35
36 // Then we add the library of binary interaction parameters
37 if (m_binary_pair_map.size() == 0) {
38 PCSAFTLibraryClass::load_from_string(mixture_binary_pairs_pcsaft_JSON);
39 }
40}
41
42// Get a PCSAFTFluid instance stored in this library
43PCSAFTFluid& PCSAFTLibraryClass::get(const std::string& key) {
44 // Try to find it
45 std::map<std::string, std::size_t>::iterator it = string_to_index_map.find(key);
46 // If it is found
47 if (it != string_to_index_map.end()) {
48 return get(it->second);
49 } else {
50 throw ValueError(format("key [%s] was not found in string_to_index_map in PCSAFTLibraryClass", key.c_str()));
51 }
52}
53
55
59 // Try to find it
60 std::map<std::size_t, PCSAFTFluid>::iterator it = fluid_map.find(key);
61 // If it is found
62 if (it != fluid_map.end()) {
63 return it->second;
64 } else {
65 throw ValueError(format("key [%d] was not found in PCSAFTLibraryClass", key));
66 }
67};
68
69void add_fluids_as_JSON(const std::string& JSON) {
70 // First we validate the json string against the schema;
71 std::string errstr;
73 // Then we check the validation code
74
75 if (val_code == cpjson::SCHEMA_VALIDATION_OK) {
76 rapidjson::Document dd;
77
78 dd.Parse<0>(JSON.c_str());
79 if (dd.HasParseError()) {
80 throw ValueError("Unable to load all_pcsaft_JSON.json");
81 } else {
82 try {
83 library.add_many(dd);
84 } catch (std::exception& e) {
85 std::cout << e.what() << std::endl;
86 }
87 }
88 } else {
89 if (get_debug_level() > 0) {
90 throw ValueError(format("Unable to load PC-SAFT library with error: %s", errstr.c_str()));
91 }
92 }
93}
94
95int PCSAFTLibraryClass::add_many(rapidjson::Value& listing) {
96 int counter = 0;
97 std::string fluid_name;
98 for (rapidjson::Value::ValueIterator itr = listing.Begin(); itr != listing.End(); ++itr) {
99 try {
100 PCSAFTFluid fluid(itr);
101 fluid_name = fluid.getName();
102
103 // If the fluid is ok...
104
105 // First check that none of the identifiers are already present
106 bool already_present = false;
107
108 if (string_to_index_map.find(fluid.getCAS()) != string_to_index_map.end()
109 || string_to_index_map.find(fluid_name) != string_to_index_map.end()
110 || string_to_index_map.find(upper(fluid_name)) != string_to_index_map.end()) {
111 already_present = true;
112 } else {
113 // Check the aliases
114 for (std::size_t i = 0; i < fluid.getAliases().size(); ++i) {
115 if (string_to_index_map.find(fluid.getAliases()[i]) != string_to_index_map.end()) {
116 already_present = true;
117 break;
118 }
119 if (string_to_index_map.find(upper(fluid.getAliases()[i])) != string_to_index_map.end()) {
120 already_present = true;
121 break;
122 }
123 }
124 }
125
126 if (already_present) {
127 if (!get_config_bool(OVERWRITE_FLUIDS)) {
128 throw ValueError(format(
129 "Cannot load fluid [%s:%s] because it is already in library; consider enabling the config boolean variable OVERWRITE_FLUIDS",
130 fluid.getName().c_str(), fluid.getCAS().c_str()));
131 } else {
132 // Remove the one(s) that are already there
133
134 // Remove the actual fluid instance
135 std::size_t index = string_to_index_map.find(fluid_name)->second;
136
137 if (fluid_map.find(index) != fluid_map.end()) {
138 fluid_map.erase(fluid_map.find(index));
139 }
140
141 if (string_to_index_map.find(fluid_name) != string_to_index_map.end()) {
142 fluid_map.erase(fluid_map.find(index));
143 }
144
145 // Remove the identifiers pointing to that instance
146 if (string_to_index_map.find(fluid.getCAS()) != string_to_index_map.end()) {
147 string_to_index_map.erase(string_to_index_map.find(fluid.getCAS()));
148 }
149 if (string_to_index_map.find(fluid_name) != string_to_index_map.end()) {
150 string_to_index_map.erase(string_to_index_map.find(fluid_name));
151 }
152 // Check the aliases
153 for (std::size_t i = 0; i < fluid.getAliases().size(); ++i) {
154 if (string_to_index_map.find(fluid.getAliases()[i]) != string_to_index_map.end()) {
155 string_to_index_map.erase(string_to_index_map.find(fluid.getAliases()[i]));
156 }
157 if (string_to_index_map.find(upper(fluid.getAliases()[i])) != string_to_index_map.end()) {
158 string_to_index_map.erase(string_to_index_map.find(upper(fluid.getAliases()[i])));
159 }
160 }
161 }
162 }
163
164 // By now, the library has been cleared of remnants of this fluid; safe to add the fluid now.
165
166 // Get the next index for this fluid
167 std::size_t index = fluid_map.size();
168
169 // Add index->fluid mapping
170 fluid_map[index] = fluid;
171
172 // fluid_map[index] = cpjson::json2string(fluid_json);
173
174 // Add CAS->index mapping
175 string_to_index_map[fluid.getCAS()] = index;
176
177 // Add name->index mapping
178 string_to_index_map[fluid_name] = index;
179
180 // Add the aliases
181 for (std::size_t i = 0; i < fluid.getAliases().size(); ++i) {
182 string_to_index_map[fluid.getAliases()[i]] = index;
183
184 // Add uppercase alias for EES compatibility
185 string_to_index_map[upper(fluid.getAliases()[i])] = index;
186 }
187
188 counter++;
189 if (get_debug_level() > 5) {
190 std::cout << format("Loaded.\n");
191 }
192 } catch (const std::exception& e) {
193 throw ValueError(format("Unable to load fluid [%s] due to error: %s", fluid_name.c_str(), e.what()));
194 }
195 }
196 return counter;
197};
198
201}
202
203std::string PCSAFTLibraryClass::get_binary_interaction_pcsaft(const std::string& CAS1, const std::string& CAS2, const std::string& key) {
204 // Find pair
205 std::vector<std::string> CAS;
206 CAS.push_back(CAS1);
207 CAS.push_back(CAS2);
208
209 std::vector<std::string> CASrev;
210 CASrev.push_back(CAS2);
211 CASrev.push_back(CAS1);
212
213 if (m_binary_pair_map.find(CAS) != m_binary_pair_map.end()) {
214 std::vector<Dictionary>& v = m_binary_pair_map[CAS];
215 try {
216 if (key == "name1") {
217 return v[0].get_string("name1");
218 } else if (key == "name2") {
219 return v[0].get_string("name2");
220 } else if (key == "BibTeX") {
221 return v[0].get_string("BibTeX");
222 } else if (key == "kij") {
223 return format("%0.16g", v[0].get_double("kij"));
224 } else if (key == "kijT") {
225 try {
226 return format("%0.16g", v[0].get_double("kijT"));
227 } catch (ValueError) {
228 return format("%0.16g", 0.0);
229 }
230 } else {
231 }
232 } catch (...) {
233 }
234 throw ValueError(format("Could not match the parameter [%s] for the binary pair [%s,%s] - for now this is an error.", key.c_str(),
235 CAS1.c_str(), CAS2.c_str()));
236 } else if (m_binary_pair_map.find(CASrev) != m_binary_pair_map.end()) {
237 std::vector<Dictionary>& v = m_binary_pair_map[CASrev];
238 try {
239 if (key == "name1") {
240 return v[0].get_string("name1");
241 } else if (key == "name2") {
242 return v[0].get_string("name2");
243 } else if (key == "BibTeX") {
244 return v[0].get_string("BibTeX");
245 } else if (key == "kij") {
246 return format("%0.16g", v[0].get_double("kij"));
247 } else if (key == "kijT") {
248 try {
249 return format("%0.16g", v[0].get_double("kijT"));
250 } catch (ValueError) {
251 return format("%0.16g", 0.0);
252 }
253 } else {
254 }
255 } catch (...) {
256 }
257 throw ValueError(format("Could not match the parameter [%s] for the binary pair [%s,%s] - for now this is an error.", key.c_str(),
258 CAS1.c_str(), CAS2.c_str()));
259 } else {
260 // Sort, see if other order works properly
261 std::sort(CAS.begin(), CAS.end());
262 if (m_binary_pair_map.find(CAS) != m_binary_pair_map.end()) {
263 throw ValueError(format("Could not match the binary pair [%s,%s] - order of CAS numbers is backwards; found the swapped CAS numbers.",
264 CAS1.c_str(), CAS2.c_str()));
265 } else {
266 throw ValueError(format("Could not match the binary pair [%s,%s] - for now this is an error.", CAS1.c_str(), CAS2.c_str()));
267 }
268 }
269}
270
271void PCSAFTLibraryClass::set_binary_interaction_pcsaft(const std::string& CAS1, const std::string& CAS2, const std::string& key, const double value) {
272 // Find pair
273 std::vector<std::string> CAS;
274 CAS.push_back(CAS1);
275 CAS.push_back(CAS2);
276
277 std::vector<std::string> CASrev;
278 CASrev.push_back(CAS2);
279 CASrev.push_back(CAS1);
280
281 if (m_binary_pair_map.find(CAS) != m_binary_pair_map.end()) {
282 if (get_config_bool(OVERWRITE_BINARY_INTERACTION)) {
283 std::vector<Dictionary>& v = m_binary_pair_map[CAS];
284 if (v[0].has_number(key)) {
285 v[0].add_number(key, value);
286 } else {
287 throw ValueError(format("Could not set the parameter [%s] for the binary pair [%s,%s] - for now this is an error", key.c_str(),
288 CAS1.c_str(), CAS2.c_str()));
289 }
290 } else {
291 throw ValueError(
292 format("CAS pair(%s,%s) already in binary interaction map; considering enabling configuration key OVERWRITE_BINARY_INTERACTION",
293 CAS1.c_str(), CAS2.c_str()));
294 }
295 } else if (m_binary_pair_map.find(CASrev) != m_binary_pair_map.end()) {
296 if (get_config_bool(OVERWRITE_BINARY_INTERACTION)) {
297 std::vector<Dictionary>& v = m_binary_pair_map[CASrev];
298 if (v[0].has_number(key)) {
299 v[0].add_number(key, value);
300 } else {
301 throw ValueError(format("Could not set the parameter [%s] for the binary pair [%s,%s] - for now this is an error", key.c_str(),
302 CAS1.c_str(), CAS2.c_str()));
303 }
304 } else {
305 throw ValueError(
306 format("CAS pair(%s,%s) already in binary interaction map; considering enabling configuration key OVERWRITE_BINARY_INTERACTION",
307 CAS1.c_str(), CAS2.c_str()));
308 }
309 } else {
310 Dictionary dict;
311 std::vector<std::string> CAS;
312 CAS.push_back(CAS1);
313 CAS.push_back(CAS2);
314 dict.add_number(key, value);
315
316 m_binary_pair_map.insert(std::pair<std::vector<std::string>, std::vector<Dictionary>>(CAS, std::vector<Dictionary>(1, dict)));
317 }
318}
319
320void PCSAFTLibraryClass::load_from_JSON(rapidjson::Document& doc) {
321 for (rapidjson::Value::ValueIterator itr = doc.Begin(); itr != doc.End(); ++itr) {
322 // Get the empty dictionary to be filled by the appropriate interaction parameter
323 Dictionary dict;
324
325 // Get the vector of CAS numbers
326 std::vector<std::string> CAS;
327 CAS.push_back(cpjson::get_string(*itr, "CAS1"));
328 CAS.push_back(cpjson::get_string(*itr, "CAS2"));
329 std::string name1 = cpjson::get_string(*itr, "Name1");
330 std::string name2 = cpjson::get_string(*itr, "Name2");
331
332 // Sort the CAS number vector
333 std::sort(CAS.begin(), CAS.end());
334
335 // A sort was carried out, names/CAS were swapped
336 bool swapped = CAS[0].compare(cpjson::get_string(*itr, "CAS1")) != 0;
337
338 if (swapped) {
339 std::swap(name1, name2);
340 }
341
342 // Populate the dictionary with common terms
343 dict.add_string("name1", name1);
344 dict.add_string("name2", name2);
345 dict.add_string("BibTeX", cpjson::get_string(*itr, "BibTeX"));
346 if (itr->HasMember("kij")) {
347 dict.add_number("kij", cpjson::get_double(*itr, "kij"));
348 } else {
349 std::cout << "Loading error: binary pair of " << name1 << " & " << name2 << "does not provide kij" << std::endl;
350 }
351 if (itr->HasMember("kijT")) {
352 dict.add_number("kijT", cpjson::get_double(*itr, "kijT"));
353 }
354
355 std::map<std::vector<std::string>, std::vector<Dictionary>>::iterator it = m_binary_pair_map.find(CAS);
356 if (it == m_binary_pair_map.end()) {
357 // Add to binary pair map by creating one-element vector
358 m_binary_pair_map.insert(std::pair<std::vector<std::string>, std::vector<Dictionary>>(CAS, std::vector<Dictionary>(1, dict)));
359 } else {
360 if (get_config_bool(OVERWRITE_BINARY_INTERACTION)) {
361 // Already there, see http://www.cplusplus.com/reference/map/map/insert/, so we are going to pop it and overwrite it
362 m_binary_pair_map.erase(it);
363 std::pair<std::map<std::vector<std::string>, std::vector<Dictionary>>::iterator, bool> ret;
364 ret = m_binary_pair_map.insert(std::pair<std::vector<std::string>, std::vector<Dictionary>>(CAS, std::vector<Dictionary>(1, dict)));
365 assert(ret.second == true);
366 } else {
367 // Error if already in map!
368 throw ValueError(
369 format("CAS pair(%s,%s) already in binary interaction map; considering enabling configuration key OVERWRITE_BINARY_INTERACTION",
370 CAS[0].c_str(), CAS[1].c_str()));
371 }
372 }
373 }
374}
375
376void PCSAFTLibraryClass::load_from_string(const std::string& str) {
377 rapidjson::Document doc;
378 doc.Parse<0>(str.c_str());
379 if (doc.HasParseError()) {
380 throw ValueError("Unable to parse PC-SAFT binary interaction parameter string");
381 }
382 load_from_JSON(doc);
383}
384
385} // namespace PCSAFTLibrary
386} // namespace CoolProp