CoolProp 8.0.0
An open-source fluid property and humid air property database
CubicsLibrary.cpp
Go to the documentation of this file.
1#include <string>
2#include <map>
3#include "CubicsLibrary.h"
4#include "all_cubics_JSON.h" // Makes a std::string variable called all_cubics_JSON
5#include "cubic_fluids_schema_JSON.h" // Makes a std::string variable called cubic_fluids_schema_JSON
8#include "CoolProp/CoolProp.h"
11
12namespace CoolProp {
13namespace CubicLibrary {
14
16{
17 private:
18 std::map<std::string, CubicsValues> fluid_map;
19 std::map<std::string, std::string> aliases_map;
21 std::map<std::string, std::string> JSONstring_map;
22 bool empty; // Is empty
23
24 public:
26 bool is_empty() {
27 return empty;
28 };
29 int add_many(const nlohmann::json& listing) {
30 int counter = 0;
31 for (const auto& el : listing) {
32 CubicsValues val;
33 val.Tc = cpjson::get_double(el, "Tc");
34 val.pc = cpjson::get_double(el, "pc");
35 val.acentric = cpjson::get_double(el, "acentric");
36 val.molemass = cpjson::get_double(el, "molemass");
37 val.name = cpjson::get_string(el, "name");
38 val.aliases = cpjson::get_string_array(el, "aliases");
39 val.CAS = cpjson::get_string(el, "CAS");
40 if (el.contains("rhomolarc") && el.at("rhomolarc").is_number()) {
41 val.rhomolarc = cpjson::get_double(el, "rhomolarc");
42 }
43 if (el.contains("alpha") && el.at("alpha").is_object()) {
44 const nlohmann::json& alpha = el.at("alpha");
45 val.alpha_type = cpjson::get_string(alpha, "type");
46 val.alpha_coeffs = cpjson::get_double_array(alpha, "c");
47 } else {
48 val.alpha_type = "default";
49 }
50 if (el.contains("alpha0") && el.at("alpha0").is_array()) {
51 val.alpha0 = JSONFluidLibrary::parse_alpha0(el.at("alpha0"));
52 }
53 std::pair<std::map<std::string, CubicsValues>::iterator, bool> ret;
54 ret = fluid_map.emplace(upper(val.name), val);
55 if (ret.second == false && get_config_bool(OVERWRITE_FLUIDS)) {
56 fluid_map.erase(ret.first);
57 ret = fluid_map.emplace(upper(val.name), val);
58 if (get_debug_level() > 0) {
59 std::cout << "added the cubic fluid: " + val.name << '\n';
60 }
61 assert(ret.second == true);
62 }
63 for (auto it = val.aliases.begin(); it != val.aliases.end(); ++it) {
64 if (aliases_map.find(*it) == aliases_map.end()) {
65 aliases_map.emplace(*it, upper(val.name));
66 }
67 }
68 std::pair<std::map<std::string, std::string>::iterator, bool> addJson;
69 addJson = JSONstring_map.emplace(upper(val.name), el.dump());
70 if (addJson.second == false && get_config_bool(OVERWRITE_FLUIDS)) {
71 JSONstring_map.erase(addJson.first);
72 addJson = JSONstring_map.emplace(upper(val.name), el.dump());
73 if (get_debug_level() > 0) {
74 std::cout << "added the cubic fluid: " + val.name << '\n';
75 }
76 assert(addJson.second == true);
77 }
78 counter++;
79 }
80 return counter;
81 };
82
83 std::string get_JSONstring(const std::string& key) {
84 std::string uppercase_identifier = upper(key);
85 // Try to find it
86 auto it = JSONstring_map.find(uppercase_identifier);
87 // If it is found
88 if (it == JSONstring_map.end()) {
89 auto italias = aliases_map.find(uppercase_identifier);
90 if (italias != aliases_map.end()) {
91 // Alias was found, use it to get the fluid name, and then the cubic values
92 it = JSONstring_map.find(italias->second);
93 } else {
94 throw ValueError(format("Fluid identifier [%s] was not found in CubicsLibrary", uppercase_identifier.c_str()));
95 }
96 }
97 // Then, wrap the single fluid object in an array, as callers expect
98 nlohmann::json doc = cpjson::parse(it->second);
99 nlohmann::json doc2 = nlohmann::json::array();
100 doc2.push_back(doc);
101 return doc2.dump();
102 }
103
104 CubicsValues get(const std::string& identifier) {
105 std::string uppercase_identifier = upper(identifier);
106 // Try to find it
107 auto it = fluid_map.find(uppercase_identifier);
108 // If it is found
109 if (it != fluid_map.end()) {
110 return it->second;
111 } else {
112 auto italias = aliases_map.find(uppercase_identifier);
113 if (italias != aliases_map.end()) {
114 // Alias was found, use it to get the fluid name, and then the cubic values
115 return fluid_map.find(italias->second)->second;
116 } else {
117 throw ValueError(format("Fluid identifier [%s] was not found in CubicsLibrary", uppercase_identifier.c_str()));
118 }
119 }
120 };
121 std::string get_fluids_list() {
122 std::vector<std::string> out;
123 for (auto it = fluid_map.begin(); it != fluid_map.end(); ++it) {
124 out.push_back(it->first);
125 }
126 return strjoin(out, ",");
127 }
128};
129namespace {
133void add_fluids_from_JSON_string(CubicsLibraryClass& dest, const std::string_view& JSON) {
134 std::string errstr;
135 cpjson::schema_validation_code val_code = cpjson::validate_schema(cubic_fluids_schema_JSON, JSON, errstr);
136 if (val_code == cpjson::SCHEMA_VALIDATION_OK) {
137 nlohmann::json dd = cpjson::parse(JSON);
138 try {
139 dest.add_many(dd);
140 } catch (std::exception& e) {
141 throw ValueError(format("Unable to load cubics library with error: %s", e.what()));
142 }
143 } else {
144 throw ValueError(format("Unable to validate cubics library against schema with error: %s", errstr.c_str()));
145 }
146}
147} // anonymous namespace
148
150 // Populate via the file-private helper so the constructor does NOT recurse
151 // through get_library() while the singleton is still being built.
152 add_fluids_from_JSON_string(*this, all_cubics_JSON);
153}
154
160static CubicsLibraryClass& get_library() {
161 static CubicsLibraryClass library;
162 return library;
163}
164
165void add_fluids_as_JSON(const std::string_view& JSON) {
166 add_fluids_from_JSON_string(get_library(), JSON);
167}
168std::string get_fluid_as_JSONstring(const std::string& identifier) {
169 return get_library().get_JSONstring(identifier);
170}
171
172CubicLibrary::CubicsValues get_cubic_values(const std::string& identifier) {
173 return get_library().get(identifier);
174}
175std::string_view get_cubic_fluids_schema() {
176 return cubic_fluids_schema_JSON;
177}
179 return get_library().get_fluids_list();
180}
181
182} // namespace CubicLibrary
183} // namespace CoolProp