CoolProp 6.8.1dev
An open-source fluid property and humid air property database
VTPRBackend.cpp
Go to the documentation of this file.
1
2#include <string>
3#include <fstream>
4#include <sstream>
5#include <iostream>
6#include <cmath>
7
8#include "VTPRBackend.h"
9#include "Configuration.h"
10#include "Exceptions.h"
11
13
14void CoolProp::VTPRBackend::setup(const std::vector<std::string>& names, bool generate_SatL_and_SatV) {
15
16 R = get_config_double(R_U_CODATA);
17
18 // Set the pure fluid flag
19 is_pure_or_pseudopure = (N == 1);
20
21 // Reset the residual Helmholtz energy class
23
24 // If pure, set the mole fractions to be unity
26 mole_fractions = std::vector<CoolPropDbl>(1, 1.0);
27 }
28
29 // Now set the reducing function for the mixture
30 Reducing.reset(new ConstantReducingFunction(cubic->get_Tr(), cubic->get_rhor()));
31
32 VTPRCubic* _cubic = static_cast<VTPRCubic*>(cubic.get());
33 _cubic->get_unifaq().set_components("name", names);
35
36 // Store the fluid names
37 m_fluid_names = names;
38
39 // Set the alpha function for the backend
41
42 // Set the ideal-gas helmholtz energy based on the components in use;
44
45 // Top-level class can hold copies of the base saturation classes,
46 // saturation classes cannot hold copies of the saturation classes
47 if (generate_SatL_and_SatV) {
48 bool SatLSatV = false;
49 SatL.reset(this->get_copy(SatLSatV));
50 SatL->specify_phase(iphase_liquid);
51 linked_states.push_back(SatL);
52 SatV.reset(this->get_copy(SatLSatV));
53 SatV->specify_phase(iphase_gas);
54 linked_states.push_back(SatV);
55
57 std::vector<CoolPropDbl> z(1, 1.0);
59 SatL->set_mole_fractions(z);
60 SatV->set_mole_fractions(z);
61 }
62 }
63
64 // Resize the vectors (including linked states)
65 resize(names.size());
66}
67
69
70 VTPRCubic* _cubic = static_cast<VTPRCubic*>(cubic.get());
71 const std::vector<UNIFACLibrary::Component>& components = _cubic->get_unifaq().get_components();
72
74 if (components.empty()) {
75 return;
76 }
77
78 for (std::size_t i = 0; i < N; ++i) {
79 const std::string& alpha_type = components[i].alpha_type;
80 if (alpha_type != "default") {
81 const std::vector<double>& c = components[i].alpha_coeffs;
82 shared_ptr<AbstractCubicAlphaFunction> acaf;
83 if (alpha_type == "Twu") {
84 acaf.reset(new TwuAlphaFunction(get_cubic()->a0_ii(i), c[0], c[1], c[2], get_cubic()->get_Tr() / get_cubic()->get_Tc()[i]));
85 } else if (alpha_type == "MathiasCopeman" || alpha_type == "Mathias-Copeman") {
86 acaf.reset(
87 new MathiasCopemanAlphaFunction(get_cubic()->a0_ii(i), c[0], c[1], c[2], get_cubic()->get_Tr() / get_cubic()->get_Tc()[i]));
88 } else {
89 throw ValueError("alpha function is not understood");
90 }
91 cubic->set_alpha_function(i, acaf);
92 }
93 }
94}
95
97 double summer = 0;
98 for (unsigned int i = 0; i < N; ++i) {
99 summer += mole_fractions[i] * molemass[i];
100 }
101 return summer;
102}
103
104void CoolProp::VTPRBackend::set_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter,
105 const double value) {
106 // bound-check indices
107 if (i < 0 || i >= N) {
108 if (j < 0 || j >= N) {
109 throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N-1));
110 } else {
111 throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N-1));
112 }
113 } else if (j < 0 || j >= N) {
114 throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N-1));
115 }
116 cubic->set_interaction_parameter(i, j, parameter, value);
117 for (std::vector<shared_ptr<HelmholtzEOSMixtureBackend>>::iterator it = linked_states.begin(); it != linked_states.end(); ++it) {
118 (*it)->set_binary_interaction_double(i, j, parameter, value);
119 }
120};
121
122void CoolProp::VTPRBackend::set_Q_k(const size_t sgi, const double value) {
123 cubic->set_Q_k(sgi, value);
124};
125
126double CoolProp::VTPRBackend::get_binary_interaction_double(const std::size_t i, const std::size_t j, const std::string& parameter) {
127 // bound-check indices
128 if (i < 0 || i >= N) {
129 if (j < 0 || j >= N) {
130 throw ValueError(format("Both indices i [%d] and j [%d] are out of bounds. Must be between 0 and %d.", i, j, N-1));
131 } else {
132 throw ValueError(format("Index i [%d] is out of bounds. Must be between 0 and %d.", i, N-1));
133 }
134 } else if (j < 0 || j >= N) {
135 throw ValueError(format("Index j [%d] is out of bounds. Must be between 0 and %d.", j, N-1));
136 }
137 return cubic->get_interaction_parameter(i, j, parameter);
138};
139
141 if (!lib.is_populated() || get_config_bool(VTPR_ALWAYS_RELOAD_LIBRARY)) {
142 std::string UNIFAC_path = get_config_string(VTPR_UNIFAC_PATH);
143 if (UNIFAC_path.empty()) {
144 throw ValueError("You must provide the path to the UNIFAC library files as VTPR_UNIFAC_PATH");
145 }
146 if (!(UNIFAC_path[UNIFAC_path.size() - 1] == '\\' || UNIFAC_path[UNIFAC_path.size() - 1] == '/')) {
147 throw ValueError("VTPR_UNIFAC_PATH must end with / or \\ character");
148 }
149 std::string group_path = UNIFAC_path + "group_data.json";
150 std::string groups = get_file_contents(group_path.c_str());
151 std::string interaction_path = UNIFAC_path + "interaction_parameters.json";
152 std::string interaction = get_file_contents(interaction_path.c_str());
153 std::string decomps_path = UNIFAC_path + "decompositions.json";
154 std::string decomps = get_file_contents(decomps_path.c_str());
155 lib.populate(groups, interaction, decomps);
156 }
157 return lib;
158}
159
161 //double slower = log(HelmholtzEOSMixtureBackend::calc_fugacity_coefficient(i));
162 VTPRCubic* _cubic = static_cast<VTPRCubic*>(cubic.get());
163 std::vector<double> here = _cubic->ln_fugacity_coefficient(mole_fractions, rhomolar(), p(), T());
164 return exp(here[i]);
165}
166
167#ifdef ENABLE_CATCH
168# include <catch2/catch_all.hpp>
169
171
172using namespace CoolProp;
173
174//TEST_CASE("VTPR test", "[VTPR]") {
175// shared_ptr<VTPRBackend> VTPR(new VTPRBackend(strsplit("Ethane&n-Propane&n-Butane", '&')));
176// std::vector<double> z(3);
177// z[0] = 0.1;
178// z[1] = 0.2;
179// z[2] = 0.7;
180// VTPR->set_mole_fractions(z);
181//
182// SECTION("dam_dxi") {
183// shared_ptr<AbstractCubic> cubic = VTPR->get_cubic();
184// double tau = 0.001, dz = 1e-6;
185// std::vector<double> zp = z, zm = z;
186// zp[0] += dz;
187// zm[0] -= dz;
188// if (!XN_INDEPENDENT) {
189// zp[2] -= dz;
190// zm[2] += dz;
191// }
192//
193// double dam_dxi_num = (cubic->am_term(tau, zp, 0) - cubic->am_term(tau, zm, 0)) / (2 * dz);
194// double dam_dxi_ana = cubic->d_am_term_dxi(tau, z, 0, 0, XN_INDEPENDENT);
195// double diff = dam_dxi_num - dam_dxi_ana;
196// CHECK(std::abs(diff) < 1e-6);
197// }
198//}
199
200#endif