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