31 if (!doc.is_array() || !doc[0].is_object()) {
32 throw ValueError(
"You must provide an array of objects");
35 for (
const auto& el : doc) {
51static PredefinedMixturesLibrary predefined_mixtures_library;
54 std::vector<std::string> out;
85 std::map<std::vector<std::string>, std::vector<Dictionary>> m_binary_pair_map;
89 std::once_flag m_load_flag;
94 return m_binary_pair_map;
119 for (
const auto& el : doc) {
124 std::vector<std::string> CAS;
131 std::sort(CAS.begin(), CAS.end());
137 std::swap(name1, name2);
149 if (el.contains(
"xi") && el.contains(
"zeta")) {
154 }
else if (el.contains(
"gammaT") && el.contains(
"gammaV") && el.contains(
"betaT") && el.contains(
"betaV")) {
169 std::cout <<
"Loading error: binary pair of " << name1 <<
" & " << name2
170 <<
"does not provide either a) xi and zeta b) gammaT, gammaV, betaT, and betaV" <<
'\n';
174 auto it = m_binary_pair_map.find(CAS);
175 if (it == m_binary_pair_map.end()) {
177 m_binary_pair_map.emplace(CAS, std::vector<Dictionary>(1, dict));
181 m_binary_pair_map.erase(it);
182 std::pair<std::map<std::vector<std::string>, std::vector<Dictionary>>::iterator,
bool> ret;
183 ret = m_binary_pair_map.emplace(CAS, std::vector<Dictionary>(1, dict));
184 assert(ret.second ==
true);
188 format(
"CAS pair(%s,%s) already in binary interaction map; considering enabling configuration key OVERWRITE_BINARY_INTERACTION",
189 CAS[0].c_str(), CAS[1].c_str()));
200 std::string CAS1, CAS2, name1 = identifier1, name2 = identifier2;
201 shared_ptr<CoolProp::HelmholtzEOSMixtureBackend> HEOS1, HEOS2;
203 std::vector<std::string> id1split =
strsplit(identifier1,
'-');
204 if (id1split.size() == 3) {
207 std::vector<std::string> names1(1, identifier1);
208 HEOS1 = std::make_shared<CoolProp::HelmholtzEOSMixtureBackend>(names1);
209 CAS1 = HEOS1->fluid_param_string(
"CAS");
212 std::vector<std::string> id2split =
strsplit(identifier2,
'-');
213 if (id2split.size() == 3) {
216 std::vector<std::string> names2(1, identifier2);
217 HEOS2 = std::make_shared<CoolProp::HelmholtzEOSMixtureBackend>(names2);
218 CAS2 = HEOS2->fluid_param_string(
"CAS");
222 std::vector<std::string> CAS;
227 std::sort(CAS.begin(), CAS.end());
230 if (CAS[0] != CAS1) {
231 std::swap(name1, name2);
241 if (rule ==
"linear") {
243 HEOS1 = std::make_shared<CoolProp::HelmholtzEOSMixtureBackend>(std::vector<std::string>(1, name1));
244 HEOS2 = std::make_shared<CoolProp::HelmholtzEOSMixtureBackend>(std::vector<std::string>(1, name2));
246 dict.
add_number(
"gammaT", 0.5 * (HEOS1->T_critical() + HEOS2->T_critical()) / sqrt(HEOS1->T_critical() * HEOS2->T_critical()));
247 double rhoc1 = HEOS1->rhomolar_critical(), rhoc2 = HEOS2->rhomolar_critical();
248 dict.
add_number(
"gammaV", 4 * (1 / rhoc1 + 1 / rhoc2) / pow(1 / pow(rhoc1, 1.0 / 3.0) + 1 / pow(rhoc2, 1.0 / 3.0), 3));
251 }
else if (rule ==
"Lorentz-Berthelot") {
259 throw ValueError(
format(
"Your simple mixing rule [%s] was not understood", rule.c_str()));
262 auto it = m_binary_pair_map.find(CAS);
263 if (it == m_binary_pair_map.end()) {
265 m_binary_pair_map.emplace(CAS, std::vector<Dictionary>(1, dict));
269 m_binary_pair_map.erase(it);
270 std::pair<std::map<std::vector<std::string>, std::vector<Dictionary>>::iterator,
bool> ret;
271 ret = m_binary_pair_map.emplace(CAS, std::vector<Dictionary>(1, dict));
272 assert(ret.second ==
true);
276 format(
"CAS pair(%s,%s) already in binary interaction map; considering enabling configuration key OVERWRITE_BINARY_INTERACTION",
277 CAS[0].c_str(), CAS[1].c_str()));
283static MixtureBinaryPairLibrary mixturebinarypairlibrary;
293 std::vector<std::string> out;
294 for (
const auto& [key, val] : mixturebinarypairlibrary.
binary_pair_map()) {
295 out.push_back(
strjoin(key,
"&"));
302 std::vector<std::string> CAS;
307 std::vector<Dictionary>& v = mixturebinarypairlibrary.
binary_pair_map()[CAS];
309 if (key ==
"name1") {
310 return v[0].get_string(
"name1");
311 }
else if (key ==
"name2") {
312 return v[0].get_string(
"name2");
313 }
else if (key ==
"BibTeX") {
314 return v[0].get_string(
"BibTeX");
315 }
else if (key ==
"function") {
316 return v[0].get_string(
"function");
317 }
else if (key ==
"type") {
318 return v[0].get_string(
"type");
319 }
else if (key ==
"F") {
321 }
else if (key ==
"xi") {
323 }
else if (key ==
"zeta") {
325 }
else if (key ==
"gammaT") {
327 }
else if (key ==
"gammaV") {
329 }
else if (key ==
"betaT") {
331 }
else if (key ==
"betaV") {
340 throw ValueError(
format(
"Could not match the parameter [%s] for the binary pair [%s,%s] - for now this is an error.", key.c_str(),
341 CAS1.c_str(), CAS2.c_str()));
344 std::sort(CAS.begin(), CAS.end());
346 throw ValueError(
format(
"Could not match the binary pair [%s,%s] - order of CAS numbers is backwards; found the swapped CAS numbers.",
347 CAS1.c_str(), CAS2.c_str()));
349 throw ValueError(
format(
"Could not match the binary pair [%s,%s] - for now this is an error.", CAS1.c_str(), CAS2.c_str()));
356 std::vector<std::string> CAS;
361 std::vector<Dictionary>& v = mixturebinarypairlibrary.
binary_pair_map()[CAS];
362 if (v[0].has_number(key)) {
363 v[0].add_number(key, value);
365 throw ValueError(
format(
"Could not set the parameter [%s] for the binary pair [%s,%s] - for now this is an error", key.c_str(),
366 CAS1.c_str(), CAS2.c_str()));
370 std::sort(CAS.begin(), CAS.end());
372 throw ValueError(
format(
"Could not match the binary pair [%s,%s] - order of CAS numbers is backwards; found the swapped CAS numbers.",
373 CAS1.c_str(), CAS2.c_str()));
375 throw ValueError(
format(
"Could not match the binary pair [%s,%s] - for now this is an error.", CAS1.c_str(), CAS2.c_str()));
382 std::vector<std::string> CAS;
387 std::sort(CAS.begin(), CAS.end());
390 return mixturebinarypairlibrary.
binary_pair_map()[CAS][0].get_string(
"function");
392 throw ValueError(
format(
"Could not match the binary pair [%s,%s] - for now this is an error.", CAS1.c_str(), CAS2.c_str()));
407 std::map<std::string, Dictionary> m_departure_function_map;
409 std::once_flag m_load_flag;
414 return m_departure_function_map;
423 for (
const auto& el : doc) {
441 if (!type.compare(
"GERG-2008")) {
449 }
else if (type ==
"Gaussian+Exponential") {
459 }
else if (!type.compare(
"Exponential")) {
462 throw ValueError(
format(
"It was not possible to parse departure function with type [%s]", type.c_str()));
468 for (
const auto& alias : aliases) {
477 auto it = m_departure_function_map.find(name);
478 if (it == m_departure_function_map.end()) {
480 m_departure_function_map.insert(std::pair<std::string, Dictionary>(name, dict));
484 m_departure_function_map.erase(it);
485 std::pair<std::map<std::string, Dictionary>::iterator,
bool> ret;
486 ret = m_departure_function_map.emplace(name, dict);
487 assert(ret.second ==
true);
492 std::vector<std::string> names;
493 names.reserve(m_departure_function_map.size());
494 for (
const auto& [name, dict] : m_departure_function_map) {
495 names.push_back(name);
497 throw ValueError(
format(
"Name of departure function [%s] is already loaded. Current departure function names are: %s", name.c_str(),
511static MixtureDepartureFunctionsLibrary mixturedeparturefunctionslibrary;
518 throw ValueError(
format(
"Departure function name [%s] seems to be invalid", Name.c_str()));
526 std::string type_dep = dict_dep.
get_string(
"type");
528 if (!type_dep.compare(
"GERG-2008")) {
530 int Npower =
static_cast<int>(dict_dep.
get_number(
"Npower"));
537 }
else if (!type_dep.compare(
"Exponential")) {
541 }
else if (!type_dep.compare(
"Gaussian+Exponential")) {
543 int Npower =
static_cast<int>(dict_dep.
get_number(
"Npower"));
560 std::size_t N = components.size();
562 STLMatrix beta_v, gamma_v, beta_T, gamma_T;
563 beta_v.resize(N, std::vector<CoolPropDbl>(N, 0));
564 gamma_v.resize(N, std::vector<CoolPropDbl>(N, 0));
565 beta_T.resize(N, std::vector<CoolPropDbl>(N, 0));
566 gamma_T.resize(N, std::vector<CoolPropDbl>(N, 0));
570 for (std::size_t i = 0; i < N; ++i) {
571 for (std::size_t j = 0; j < N; ++j) {
576 std::string CAS1 = components[i].CAS;
577 std::vector<std::string> CAS(2,
"");
578 CAS[0] = components[i].CAS;
579 CAS[1] = components[j].CAS;
580 std::sort(CAS.begin(), CAS.end());
583 bool swapped = (CAS1.compare(CAS[0]) != 0);
590 throw ValueError(
format(
"Could not match the binary pair [%s,%s] - for now this is an error.", CAS[0].c_str(), CAS[1].c_str()));
597 std::string type_red = dict_red.
get_string(
"type");
599 if (!type_red.compare(
"GERG-2008")) {
601 beta_v[i][j] = 1 / dict_red.
get_number(
"betaV");
602 beta_T[i][j] = 1 / dict_red.
get_number(
"betaT");
607 gamma_v[i][j] = dict_red.
get_number(
"gammaV");
608 gamma_T[i][j] = dict_red.
get_number(
"gammaT");
609 }
else if (!type_red.compare(
"Lemmon-xi-zeta")) {
612 throw ValueError(
format(
"type [%s] for reducing function for pair [%s, %s] is invalid", type_red.c_str(),
631 std::vector<double> n(1, 0), d(1, 1), t(1, 1), l(1, 0);
632 HEOS.
residual_helmholtz->Excess.DepartureFunctionMatrix[i][j] = std::make_shared<ExponentialDepartureFunction>(n, d, t, l);
643 HEOS.
Reducing = std::make_shared<GERG2008ReducingFunction>(components, beta_v, gamma_v, beta_T, gamma_T);
646void parse_HMX_BNC(
const std::string& s, std::vector<REFPROP_binary_element>& BIP, std::vector<REFPROP_departure_function>& functions) {
648 bool block_started =
false;
649 std::size_t i_started = 0, i_ended = 0, i = 0;
650 std::vector<std::string> lines =
strsplit(s,
'\n');
651 for (
auto& line : lines) {
653 block_started =
true;
656 if (block_started &&
strstrip(line).empty()) {
663 for (i = i_started; i < i_ended; ++i) {
670 std::vector<std::pair<std::size_t, std::size_t>> bounds;
671 std::size_t last_excalamation = i_started;
672 for (i = i_started; i <= i_ended; ++i) {
674 bounds.push_back(std::make_pair<std::size_t, std::size_t>(last_excalamation + 1, i - 1));
675 last_excalamation = i;
679 std::vector<REFPROP_binary_element> chunks;
680 for (
const auto& [bstart, bend] : bounds) {
682 for (std::size_t i = bstart; i <= bend; ++i) {
689 if (lines[i].find(
'/') > 0) {
693 for (std::size_t j = bits.size() - 1; j > 0; --j) {
694 if (bits[j].empty()) {
695 bits.erase(bits.begin() + j);
699 if (bits[0].find(
'/') > 0 && bits[1].size() == 3) {
700 std::vector<std::string> theCAS =
strsplit(bits[0],
'/');
701 bnc.
CAS1 = theCAS[0];
702 bnc.
CAS2 = theCAS[1];
710 }
else if (
strstrip(bits[0]) ==
"CAS#") {
717 if (!bnc.
CAS1.empty()) {
725 for (std::size_t i = i_ended + 1; i < lines.size(); ++i) {
726 std::size_t j_end = 0;
728 for (j_end = i + 1; j_end < lines.size(); ++j_end) {
729 if (
strstrip(lines[j_end]).empty()) {
738 dep.
model = std::string(lines[i + 1].begin(), lines[i + 1].begin() + 3);
739 dep.
comments.push_back(lines[i + 1]);
740 for (std::size_t j = i + 2; j <= j_end; ++j) {
749 std::vector<std::string> bits =
strsplit(lines[j],
' ');
751 for (std::size_t k = bits.size() - 1; k > 0; --k) {
752 if (bits[k].empty()) {
753 bits.erase(bits.begin() + k);
759 dep.
Npower =
static_cast<short>(strtol(bits[0].c_str(),
nullptr, 10));
760 dep.
Nterms_power =
static_cast<short>(strtol(bits[1].c_str(),
nullptr, 10));
761 dep.
Nspecial =
static_cast<short>(strtol(bits[3].c_str(),
nullptr, 10));
762 dep.
Nterms_special =
static_cast<short>(strtol(bits[4].c_str(),
nullptr, 10));
772 if (dep.
a.size() - 1 <
static_cast<size_t>(dep.
Npower)) {
773 dep.
eta.push_back(0);
775 dep.
beta.push_back(0);
776 dep.
gamma.push_back(0);
787 functions.push_back(dep);
793 if (string_data.find(
"#MXM") != std::string::npos) {
795 std::vector<REFPROP_binary_element> BIP;
796 std::vector<REFPROP_departure_function> functions;
800 nlohmann::json doc = nlohmann::json::array();
801 for (
const auto& bip : BIP) {
803 el[
"CAS1"] = bip.CAS1;
804 el[
"CAS2"] = bip.CAS2;
807 el[
"betaT"] = bip.betaT;
808 el[
"gammaT"] = bip.gammaT;
809 el[
"betaV"] = bip.betaV;
810 el[
"gammaV"] = bip.gammaV;
812 el[
"function"] = bip.model;
813 el[
"BibTeX"] =
"(from HMX.BNC format)::" +
strjoin(bip.comments,
"\n");
814 doc.push_back(std::move(el));
819 nlohmann::json doc = nlohmann::json::array();
820 for (
const auto& func : functions) {
822 el[
"Name"] = func.model;
823 el[
"aliases"] = nlohmann::json::array();
827 if (func.Nterms_special > 0 || func.Nterms_power == 3) {
828 el[
"type"] =
"GERG-2008";
829 el[
"Npower"] = func.Npower;
830 if (func.Nterms_power == 3 && func.Nspecial == 0) {
831 std::vector<double> zeros(func.a.size(), 0.0);
833 el[
"epsilon"] = zeros;
837 el[
"eta"] = func.eta;
838 el[
"epsilon"] = func.epsilon;
839 el[
"beta"] = func.beta;
840 el[
"gamma"] = func.gamma;
843 el[
"type"] =
"Exponential";
846 el[
"BibTeX"] =
"(from HMX.BNC format)::" +
strjoin(func.comments,
"\n");
847 doc.push_back(std::move(el));