CoolProp 7.2.0
An open-source fluid property and humid air property database
CoolPropLib.cpp
Go to the documentation of this file.
1#if defined(_MSC_VER)
2# define _CRTDBG_MAP_ALLOC
3# define _CRT_SECURE_NO_WARNINGS
4# include <crtdbg.h>
5#else
6# include <fenv.h>
7#endif
8
9#include "CoolPropLib.h"
10#include "CoolProp.h"
11#include "HumidAirProp.h"
12#include "DataStructures.h"
13#include "Exceptions.h"
14#include "float.h"
16#include "AbstractState.h"
17#include "Exceptions.h"
18#include "Configuration.h"
20
21#include <string.h>
22#include <mutex>
23
24void str2buf(const std::string& str, char* buf, int n) {
25 if (str.size() < static_cast<unsigned int>(n)) {
26 strncpy(buf, str.c_str(), n - 1);
27 buf[n - 1] = '\0';
28 } else {
29 throw CoolProp::ValueError("Buffer is too small; must be at least " + std::to_string(str.size()) + " characters in size");
30 }
31}
32void HandleException(long* errcode, char* message_buffer, const long buffer_length) {
33 try {
34 throw; // Rethrow the error, and here we handle the error
35 } catch (CoolProp::HandleError& e) {
36 std::string errmsg = std::string("HandleError: ") + e.what();
37 if (errmsg.size() < static_cast<std::size_t>(buffer_length)) {
38 *errcode = 1;
39 strcpy(message_buffer, errmsg.c_str());
40 } else {
41 *errcode = 2;
42 }
43 } catch (CoolProp::CoolPropBaseError& e) {
44 std::string errmsg = std::string("Error: ") + e.what();
45 if (errmsg.size() < static_cast<std::size_t>(buffer_length)) {
46 *errcode = 1;
47 strcpy(message_buffer, errmsg.c_str());
48 } else {
49 *errcode = 2;
50 }
51 } catch (...) {
52 *errcode = 3;
53 }
54}
55
56// In Microsoft Excel, they seem to check the FPU exception bits and error out because of it.
57// By calling the _clearfp(), we can reset these bits, and not get the error
58// See also http://stackoverflow.com/questions/11685441/floating-point-error-when-calling-dll-function-from-vba/27336496#27336496
59// See also http://stackoverflow.com/questions/16849009/in-linux-do-there-exist-functions-similar-to-clearfp-and-statusfp for linux and OSX
61{
63#if defined(_MSC_VER)
64 _clearfp(); // For MSVC, clear the floating point error flags
65#elif defined(FE_ALL_EXCEPT)
66 feclearexcept(FE_ALL_EXCEPT);
67#endif
68 }
69};
70double convert_from_kSI_to_SI(long iInput, double value) {
71 if (get_debug_level() > 8) {
72 std::cout << format("%s:%d: convert_from_kSI_to_SI(i=%d,value=%g)\n", __FILE__, __LINE__, iInput, value).c_str();
73 }
74
75 switch (iInput) {
76 case CoolProp::iP:
85 return value * 1000.0;
88 case CoolProp::iQ:
90 case CoolProp::iT:
93 return value;
94 default:
95 throw CoolProp::ValueError(format("index [%d] is invalid in convert_from_kSI_to_SI", iInput).c_str());
96 }
97}
98
99double convert_from_SI_to_kSI(long iInput, double value) {
100 if (get_debug_level() > 8) {
101 std::cout << format("%s:%d: convert_from_SI_to_kSI(%d,%g)\n", __FILE__, __LINE__, iInput, value).c_str();
102 }
103
104 switch (iInput) {
105 case CoolProp::iP:
108 case CoolProp::iSmass:
109 case CoolProp::iGmass:
111 case CoolProp::iHmass:
112 case CoolProp::iUmass:
114 return value / 1000.0;
115 case CoolProp::iDmass:
116 case CoolProp::iQ:
119 case CoolProp::iT:
121 return value;
122 default:
123 throw CoolProp::ValueError(format("index [%d] is invalid in convert_from_SI_to_kSI", iInput).c_str());
124 }
125}
126
127EXPORT_CODE long CONVENTION redirect_stdout(const char* file) {
128 FILE* fp = freopen(file, "a+", stdout);
129 return (fp) ? 1 : 0; // 0 = failure if redirection could not be done; original stdout is already closed
130}
131EXPORT_CODE int CONVENTION set_reference_stateS(const char* Ref, const char* reference_state) {
132 fpu_reset_guard guard;
133 try {
134 CoolProp::set_reference_stateS(std::string(Ref), std::string(reference_state));
135 return true;
136 } catch (std::exception& e) {
138 } catch (...) {
139 CoolProp::set_error_string("Undefined error");
140 }
141 return false;
142}
143EXPORT_CODE int CONVENTION set_reference_stateD(const char* Ref, double T, double rhomolar, double hmolar0, double smolar0) {
144 fpu_reset_guard guard;
145 try {
146 CoolProp::set_reference_stateD(std::string(Ref), T, rhomolar, hmolar0, smolar0);
147 return true;
148 } catch (std::exception& e) {
150 } catch (...) {
151 CoolProp::set_error_string("Undefined error");
152 }
153 return false;
154}
155
156// All the function interfaces that point to the single-input Props function
157EXPORT_CODE double CONVENTION Props1(const char* FluidName, const char* Output) {
158 fpu_reset_guard guard;
159 double val = Props1SI(Output, FluidName);
160 if (!ValidNumber(val))
161 // Error code was already set in Props1SI
162 return val;
163 // val is valid; so, Output is already checked in Props1SI -> get_parameter_index won't throw
165 return convert_from_SI_to_kSI(iOutput, val);
166}
167EXPORT_CODE double CONVENTION PropsS(const char* Output, const char* Name1, double Prop1, const char* Name2, double Prop2, const char* Ref) {
168 return Props(Output, Name1[0], Prop1, Name2[0], Prop2, Ref);
169}
170EXPORT_CODE double CONVENTION Props(const char* Output, const char Name1, double Prop1, const char Name2, double Prop2, const char* Ref) {
171 fpu_reset_guard guard;
172 try {
173 // Get parameter indices
174 std::string sName1 = std::string(1, Name1), sName2 = std::string(1, Name2);
176 if (!CoolProp::is_trivial_parameter(iOutput)) {
179
180 // Convert inputs to SI
181 Prop1 = convert_from_kSI_to_SI(iName1, Prop1);
182 Prop2 = convert_from_kSI_to_SI(iName2, Prop2);
183 }
184
185 // Call the SI function
186 double val = PropsSI(Output, sName1.c_str(), Prop1, sName2.c_str(), Prop2, Ref);
187
188 // Convert back to unit system
189 return convert_from_SI_to_kSI(iOutput, val);
190 } catch (std::exception& e) {
192 } catch (...) {
193 CoolProp::set_error_string("Undefined error");
194 }
195 return _HUGE;
196}
197EXPORT_CODE double CONVENTION saturation_ancillary(const char* fluid_name, const char* output, int Q, const char* input, double value) {
198 fpu_reset_guard guard;
199 try {
200 return CoolProp::saturation_ancillary(fluid_name, std::string(output), Q, std::string(input), value);
201 } catch (std::exception& e) {
203 } catch (...) {
204 CoolProp::set_error_string("Undefined error");
205 }
206 return _HUGE;
207}
208EXPORT_CODE double CONVENTION Props1SI(const char* FluidName, const char* Output) {
209 fpu_reset_guard guard;
210 return CoolProp::Props1SI(std::string(FluidName), std::string(Output));
211}
212EXPORT_CODE void CONVENTION Props1SImulti(const char* Outputs, char* backend, const char* FluidNames, const double* fractions,
213 const long length_fractions, double* result, long* resdim1) {
214 fpu_reset_guard guard;
215 try {
216 // Outputs is a delimited string separated by LIST_STRING_DELIMITER
217 std::string delim = CoolProp::get_config_string(LIST_STRING_DELIMITER);
218 // strsplit only support char delimiter
219 if (delim.length() > 1)
220 throw CoolProp::ValueError(format("Length of string delimiter [%d] is bigger than 1 [%d]", delim.length(), delim.size()));
221 std::vector<std::string> _outputs = strsplit(Outputs, delim[0]);
222 // FluidNames is a delimited string separated by LIST_STRING_DELIMITER
223 std::vector<std::string> _fluidNames = strsplit(FluidNames, delim[0]);
224 if (_fluidNames.size() != length_fractions)
226 format("Length of fractions vector [%d] is not equal to length of fluidNames vector [%d]", _fluidNames.size(), length_fractions));
227 std::vector<double> _fractions(fractions, fractions + length_fractions);
228 std::vector<std::vector<double>> _result = CoolProp::Props1SImulti(_outputs, backend, _fluidNames, _fractions);
229 // if CoolProp::Props1SImulti fails it will return an empty vector -> set result dimensions to 0
230 if (_result.size() == 0) {
231 *resdim1 = 0;
232 } else {
233 if (_result.size() > static_cast<size_t>(*resdim1))
234 throw CoolProp::ValueError(format("Result vector [%d] is bigger than allocated memory [%d]", _result[0].size(), *resdim1));
235 *resdim1 = static_cast<long>(_result[0].size());
236 for (size_t i = 0; i < _result[0].size(); i++) {
237 result[i] = _result[0][i];
238 }
239 }
240 } catch (std::exception& e) {
242 } catch (...) {
243 CoolProp::set_error_string("Undefined error");
244 }
245}
246EXPORT_CODE double CONVENTION PropsSI(const char* Output, const char* Name1, double Prop1, const char* Name2, double Prop2, const char* FluidName) {
247 fpu_reset_guard guard;
248 return CoolProp::PropsSI(std::string(Output), std::string(Name1), Prop1, std::string(Name2), Prop2, std::string(FluidName));
249}
250EXPORT_CODE void CONVENTION PropsSImulti(const char* Outputs, const char* Name1, double* Prop1, const long size_Prop1, const char* Name2,
251 double* Prop2, const long size_Prop2, char* backend, const char* FluidNames, const double* fractions,
252 const long length_fractions, double* result, long* resdim1, long* resdim2) {
253 fpu_reset_guard guard;
254 try {
255 // Outputs is a delimited string separated by LIST_STRING_DELIMITER
256 std::string delim = CoolProp::get_config_string(LIST_STRING_DELIMITER);
257 // strsplit only support char delimiter
258 if (delim.length() > 1)
259 throw CoolProp::ValueError(format("Length of string delimiter [%d] is bigger than 1 [%d]", delim.length(), delim.size()));
260 std::vector<std::string> _outputs = strsplit(Outputs, delim[0]);
261 if (size_Prop1 != size_Prop2)
263 format("Length of input parameter 1 [%d] is not equal to length of input parameter 2 [%d]", size_Prop1, size_Prop2));
264 // make vectors out of double pointer
265 std::vector<double> _prop1(Prop1, Prop1 + size_Prop1);
266 std::vector<double> _prop2(Prop2, Prop2 + size_Prop2);
267 // FluidNames is a delimited string separated by LIST_STRING_DELIMITER
268 std::vector<std::string> _fluidNames = strsplit(FluidNames, delim[0]);
269 if (_fluidNames.size() != length_fractions)
271 format("Length of fractions vector [%d] is not equal to length of fluidNames vector [%d]", _fluidNames.size(), length_fractions));
272 std::vector<double> _fractions(fractions, fractions + length_fractions);
273 std::vector<std::vector<double>> _result =
274 CoolProp::PropsSImulti(_outputs, std::string(Name1), _prop1, std::string(Name2), _prop2, backend, _fluidNames, _fractions);
275 // if CoolProp::PropsSImulti fails it will return an empty vector -> set result dimensions to 0
276 if (_result.size() == 0) {
277 *resdim1 = 0;
278 *resdim2 = 0;
279 } else {
280 if (_result.size() > static_cast<size_t>(*resdim1) || _result[0].size() > static_cast<size_t>(*resdim2))
282 format("Result matrix [%d x %d] is bigger than allocated memory [%d x %d]", _result.size(), _result[0].size(), *resdim1, *resdim2));
283 *resdim1 = static_cast<long>(_result.size());
284 *resdim2 = static_cast<long>(_result[0].size());
285 for (size_t i = 0; i < _result.size(); i++) {
286 for (size_t j = 0; j < _result[i].size(); j++) {
287 result[j + _result[i].size() * i] = _result[i][j];
288 }
289 }
290 }
291 } catch (std::exception& e) {
292 // set result dimensions to 0 to signalize, an error occured
293 *resdim1 = 0;
294 *resdim2 = 0;
296 } catch (...) {
297 // set result dimensions to 0 to signalize, an error occured
298 *resdim1 = 0;
299 *resdim2 = 0;
300 CoolProp::set_error_string("Undefined error");
301 }
302}
303EXPORT_CODE long CONVENTION PhaseSI(const char* Name1, double Prop1, const char* Name2, double Prop2, const char* FluidName, char* phase, int n) {
304 fpu_reset_guard guard;
305 try {
306 std::string s = CoolProp::PhaseSI(std::string(Name1), Prop1, std::string(Name2), Prop2, std::string(FluidName));
307 str2buf(s, phase, n);
308 return 1;
309 } catch (std::exception& e) {
311 } catch (...) {
312 CoolProp::set_error_string("Undefined error");
313 }
314 return 0;
315}
316/*
317 * EXPORT_CODE double CONVENTION PropsSIZ(const char *Output, const char *Name1, double Prop1, const char *Name2, double Prop2, const char * FluidName, const double *z, int n)
318{
319 std::string _Output = Output, _Name1 = Name1, _Name2 = Name2, _FluidName = FluidName;
320 double val = CoolProp::PropsSI(_Output, _Name1, Prop1, _Name2, Prop2, _FluidName, std::vector<double>(z, z+n));
321 reset_fpu();
322 return val;
323}
324 * */
325EXPORT_CODE void CONVENTION propssi_(const char* Output, const char* Name1, const double* Prop1, const char* Name2, const double* Prop2,
326 const char* FluidName, double* output) {
327 *output = PropsSI(Output, Name1, *Prop1, Name2, *Prop2, FluidName);
328}
329
330EXPORT_CODE double CONVENTION K2F(double T) {
331 return T * 9 / 5 - 459.67;
332}
333EXPORT_CODE double CONVENTION F2K(double T_F) {
334 return (T_F + 459.67) * 5 / 9;
335}
338}
341}
342EXPORT_CODE long CONVENTION get_param_index(const char* param) {
343 try {
344 return CoolProp::get_parameter_index(param);
345 } catch (std::exception& e) {
347 } catch (...) {
348 CoolProp::set_error_string("Undefined error");
349 }
350 return -1;
351}
353 try {
355 } catch (std::exception& e) {
357 } catch (...) {
358 CoolProp::set_error_string("Undefined error");
359 }
360 return -1;
361}
362EXPORT_CODE long CONVENTION get_global_param_string(const char* param, char* Output, int n) {
363 try {
364 std::string s = CoolProp::get_global_param_string(param);
365 str2buf(s, Output, n);
366 return 1;
367 } catch (std::exception& e) {
369 } catch (...) {
370 CoolProp::set_error_string("Undefined error");
371 }
372 return 0;
373}
374EXPORT_CODE long CONVENTION get_parameter_information_string(const char* param, char* Output, int n) {
375 try {
376 int key = CoolProp::get_parameter_index(param);
377 std::string s = CoolProp::get_parameter_information(key, Output);
378 str2buf(s, Output, n);
379 return 1;
380 } catch (std::exception& e) {
381 // if param is wrong, CoolProp::get_parameter_index throws string like
382 // "Your input name [%s] is not valid in get_parameter_index (names are case sensitive)"
383 // CoolProp::get_parameter_information throws string like
384 // "Bad info string [%s] to get_parameter_information" (if Output is wrong)
385 // or "Unable to match the key [%d] in get_parameter_information for info [%s]"
386 // (see src/DataStructures.cpp)
387 // if n is too small, str2buf throws string
388 // "Buffer size is too small"
389 CoolProp::set_error_string(format("get_parameter_information_string(\"%s\", \"%s\", %d): %s", param, Output, n, e.what()));
390 } catch (...) {
391 CoolProp::set_error_string(format("get_parameter_information_string(\"%s\", \"%s\", %d): Undefined error", param, Output, n));
392 }
393 return 0;
394}
395EXPORT_CODE long CONVENTION get_fluid_param_string(const char* fluid, const char* param, char* Output, int n) {
396 try {
397 std::string s = CoolProp::get_fluid_param_string(std::string(fluid), std::string(param));
398 str2buf(s, Output, n);
399 return 1;
400 } catch (std::exception& e) {
402 } catch (...) {
403 CoolProp::set_error_string("Undefined error");
404 }
405 return 0;
406}
407EXPORT_CODE long CONVENTION get_fluid_param_string_len(const char* fluid, const char* param) {
408 try {
409 std::string s = CoolProp::get_fluid_param_string(std::string(fluid), std::string(param));
410 return static_cast<long>(s.size());
411 } catch (std::exception& e) {
413 } catch (...) {
414 CoolProp::set_error_string("Undefined error");
415 }
416 return -1;
417}
418EXPORT_CODE void CONVENTION set_config_string(const char* key, const char* val) {
419 try {
420 CoolProp::set_config_string(CoolProp::config_string_to_key(std::string(key)), std::string(val));
421 } catch (std::exception& e) {
423 } catch (...) {
424 CoolProp::set_error_string("Undefined error");
425 }
426}
427EXPORT_CODE void CONVENTION set_config_double(const char* key, const double val) {
428 try {
430 } catch (std::exception& e) {
432 } catch (...) {
433 CoolProp::set_error_string("Undefined error");
434 }
435}
436EXPORT_CODE void CONVENTION set_config_bool(const char* key, const bool val) {
437 try {
439 } catch (std::exception& e) {
441 } catch (...) {
442 CoolProp::set_error_string("Undefined error");
443 }
444}
445EXPORT_CODE void CONVENTION set_departure_functions(const char* string_data, long* errcode, char* message_buffer, const long buffer_length) {
446 *errcode = 0;
447 try {
449 } catch (...) {
450 HandleException(errcode, message_buffer, buffer_length);
451 }
452}
453EXPORT_CODE double CONVENTION HAPropsSI(const char* Output, const char* Name1, double Prop1, const char* Name2, double Prop2, const char* Name3,
454 double Prop3) {
455 fpu_reset_guard guard;
456 return HumidAir::HAPropsSI(std::string(Output), std::string(Name1), Prop1, std::string(Name2), Prop2, std::string(Name3), Prop3);
457}
459 fpu_reset_guard guard;
460 return HumidAir::cair_sat(T);
461}
462EXPORT_CODE void CONVENTION hapropssi_(const char* Output, const char* Name1, const double* Prop1, const char* Name2, const double* Prop2,
463 const char* Name3, const double* Prop3, double* output) {
464 *output = HAPropsSI(Output, Name1, *Prop1, Name2, *Prop2, Name3, *Prop3);
465}
466EXPORT_CODE double CONVENTION HAProps(const char* Output, const char* Name1, double Prop1, const char* Name2, double Prop2, const char* Name3,
467 double Prop3) {
468 fpu_reset_guard guard;
469 try {
470 return HumidAir::HAProps(std::string(Output), std::string(Name1), Prop1, std::string(Name2), Prop2, std::string(Name3), Prop3);
471 } catch (std::exception& e) {
473 } catch (...) {
474 CoolProp::set_error_string("Undefined error");
475 }
476 return _HUGE;
477}
478EXPORT_CODE void CONVENTION haprops_(const char* Output, const char* Name1, const double* Prop1, const char* Name2, const double* Prop2,
479 const char* Name3, const double* Prop3, double* output) {
480 *output = HAProps(Output, Name1, *Prop1, Name2, *Prop2, Name3, *Prop3);
481}
483{
484 private:
485 std::map<std::size_t, shared_ptr<CoolProp::AbstractState>> ASlibrary;
486 long next_handle;
487 std::mutex ASLib_mutex;
488
489 public:
490 AbstractStateLibrary() : next_handle(0) {};
491 long add(shared_ptr<CoolProp::AbstractState> AS) {
492 std::lock_guard<std::mutex> guard(ASLib_mutex);
493 ASlibrary.insert(std::pair<std::size_t, shared_ptr<CoolProp::AbstractState>>(this->next_handle, AS));
494 this->next_handle++;
495 return next_handle - 1;
496 }
497 void remove(long handle) {
498 std::lock_guard<std::mutex> guard(ASLib_mutex);
499 std::size_t count_removed = ASlibrary.erase(handle);
500 if (count_removed != 1) {
501 throw CoolProp::HandleError("could not free handle");
502 }
503 }
504 shared_ptr<CoolProp::AbstractState>& get(long handle) {
505 std::lock_guard<std::mutex> guard(ASLib_mutex);
506 std::map<std::size_t, shared_ptr<CoolProp::AbstractState>>::iterator it = ASlibrary.find(handle);
507 if (it != ASlibrary.end()) {
508 return it->second;
509 } else {
510 throw CoolProp::HandleError("could not get handle");
511 }
512 }
513};
514static AbstractStateLibrary handle_manager;
515
516EXPORT_CODE long CONVENTION AbstractState_factory(const char* backend, const char* fluids, long* errcode, char* message_buffer,
517 const long buffer_length) {
518 *errcode = 0;
519 try {
520 shared_ptr<CoolProp::AbstractState> AS(CoolProp::AbstractState::factory(backend, fluids));
521 return handle_manager.add(AS);
522 } catch (...) {
523 HandleException(errcode, message_buffer, buffer_length);
524 }
525 return -1;
526}
527EXPORT_CODE void CONVENTION AbstractState_fluid_names(const long handle, char* fluids, long* errcode, char* message_buffer,
528 const long buffer_length) {
529 *errcode = 0;
530
531 try {
532 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
533 std::vector<std::string> _fluids = AS->fluid_names();
534 std::string fluidsstring = strjoin(_fluids, CoolProp::get_config_string(LIST_STRING_DELIMITER));
535 if (fluidsstring.size() < static_cast<std::size_t>(buffer_length)) {
536 strcpy(fluids, fluidsstring.c_str());
537 } else {
538 throw CoolProp::ValueError(format("Length of string [%d] is greater than allocated buffer length [%d]", fluidsstring.size(),
539 static_cast<std::size_t>(buffer_length)));
540 }
541
542 } catch (...) {
543 HandleException(errcode, message_buffer, buffer_length);
544 }
545}
546EXPORT_CODE void CONVENTION AbstractState_free(const long handle, long* errcode, char* message_buffer, const long buffer_length) {
547 *errcode = 0;
548 try {
549 handle_manager.remove(handle);
550 } catch (...) {
551 HandleException(errcode, message_buffer, buffer_length);
552 }
553}
554EXPORT_CODE void CONVENTION AbstractState_set_fractions(const long handle, const double* fractions, const long N, long* errcode, char* message_buffer,
555 const long buffer_length) {
556 *errcode = 0;
557 std::vector<double> _fractions(fractions, fractions + N);
558 try {
559 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
560 if (AS->using_mole_fractions()) {
561 AS->set_mole_fractions(_fractions);
562 } else if (AS->using_mass_fractions()) {
563 AS->set_mass_fractions(_fractions);
564 } else if (AS->using_volu_fractions()) {
565 AS->set_volu_fractions(_fractions);
566 }
567 } catch (...) {
568 HandleException(errcode, message_buffer, buffer_length);
569 }
570}
571EXPORT_CODE void CONVENTION AbstractState_get_mole_fractions(const long handle, double* fractions, const long maxN, long* N, long* errcode,
572 char* message_buffer, const long buffer_length) {
573 *errcode = 0;
574
575 try {
576 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
577 std::vector<double> _fractions = AS->get_mole_fractions();
578 *N = static_cast<long>(_fractions.size());
579 if (*N <= maxN) {
580 for (int i = 0; i < *N; i++)
581 fractions[i] = _fractions[i];
582 } else {
583 throw CoolProp::ValueError(format("Length of array [%d] is greater than allocated buffer length [%d]", *N, maxN));
584 }
585 } catch (...) {
586 HandleException(errcode, message_buffer, buffer_length);
587 }
588}
589EXPORT_CODE void CONVENTION AbstractState_get_mole_fractions_satState(const long handle, const char* saturated_state, double* fractions,
590 const long maxN, long* N, long* errcode, char* message_buffer,
591 const long buffer_length) {
592 *errcode = 0;
593
594 try {
595 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
596 std::vector<double> _fractions;
597 double quality = AS->Q();
598 std::string string_state(saturated_state);
599 if (0 <= quality && quality <= 1) {
600 if (string_state == "liquid") {
601 _fractions = AS->mole_fractions_liquid();
602 } else if (string_state == "gas") {
603 _fractions = AS->mole_fractions_vapor();
604 } else {
606 format("Bad info string [%s] to saturated state mole fractions, options are \"liquid\" and \"gas\"", saturated_state));
607 }
608 } else {
609 throw CoolProp::ValueError(format("AbstractState_get_mole_fractions_satState only returns outputs for saturated states if AbstractState "
610 "quality [%g] is within two-phase region (0 <= quality <= 1)",
611 static_cast<double>(quality)));
612 }
613 *N = static_cast<long>(_fractions.size());
614 if (*N <= maxN) {
615 for (int i = 0; i < *N; i++) {
616 fractions[i] = _fractions[i];
617 }
618 } else {
619 throw CoolProp::ValueError(format("Length of array [%d] is greater than allocated buffer length [%d]", *N, maxN));
620 }
621 } catch (...) {
622 HandleException(errcode, message_buffer, buffer_length);
623 }
624}
625EXPORT_CODE double CONVENTION AbstractState_get_fugacity(const long handle, const long i, long* errcode, char* message_buffer,
626 const long buffer_length) {
627 *errcode = 0;
628 try {
629 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
630 return AS->fugacity(i);
631 } catch (...) {
632 HandleException(errcode, message_buffer, buffer_length);
633 }
634 return _HUGE;
635}
636EXPORT_CODE double CONVENTION AbstractState_get_fugacity_coefficient(const long handle, const long i, long* errcode, char* message_buffer,
637 const long buffer_length) {
638 *errcode = 0;
639 try {
640 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
641 return AS->fugacity_coefficient(i);
642 } catch (...) {
643 HandleException(errcode, message_buffer, buffer_length);
644 }
645 return _HUGE;
646}
647EXPORT_CODE void CONVENTION AbstractState_update(const long handle, const long input_pair, const double value1, const double value2, long* errcode,
648 char* message_buffer, const long buffer_length) {
649 *errcode = 0;
650 try {
651 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
652 AS->update(static_cast<CoolProp::input_pairs>(input_pair), value1, value2);
653 } catch (...) {
654 HandleException(errcode, message_buffer, buffer_length);
655 }
656}
657EXPORT_CODE void CONVENTION AbstractState_specify_phase(const long handle, const char* phase, long* errcode, char* message_buffer,
658 const long buffer_length) {
659 *errcode = 0;
660 try {
661 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
662 return AS->specify_phase(CoolProp::get_phase_index(std::string(phase)));
663 } catch (...) {
664 HandleException(errcode, message_buffer, buffer_length);
665 }
666}
667EXPORT_CODE void CONVENTION AbstractState_unspecify_phase(const long handle, long* errcode, char* message_buffer, const long buffer_length) {
668 *errcode = 0;
669 try {
670 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
671 return AS->unspecify_phase();
672 } catch (...) {
673 HandleException(errcode, message_buffer, buffer_length);
674 }
675}
676EXPORT_CODE double CONVENTION AbstractState_keyed_output(const long handle, const long param, long* errcode, char* message_buffer,
677 const long buffer_length) {
678 *errcode = 0;
679 try {
680 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
681 return AS->keyed_output(static_cast<CoolProp::parameters>(param));
682 } catch (...) {
683 HandleException(errcode, message_buffer, buffer_length);
684 }
685 return _HUGE;
686}
687
688EXPORT_CODE double CONVENTION AbstractState_first_saturation_deriv(const long handle, const long Of, const long Wrt, long* errcode,
689 char* message_buffer, const long buffer_length) {
690 *errcode = 0;
691 try {
692 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
693 return AS->first_saturation_deriv(static_cast<CoolProp::parameters>(Of), static_cast<CoolProp::parameters>(Wrt));
694 } catch (...) {
695 HandleException(errcode, message_buffer, buffer_length);
696 }
697 return _HUGE;
698}
699
700EXPORT_CODE double CONVENTION AbstractState_first_partial_deriv(const long handle, const long Of, const long Wrt, const long Constant, long* errcode,
701 char* message_buffer, const long buffer_length) {
702 *errcode = 0;
703 try {
704 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
705 return AS->first_partial_deriv(static_cast<CoolProp::parameters>(Of), static_cast<CoolProp::parameters>(Wrt),
706 static_cast<CoolProp::parameters>(Constant));
707 } catch (...) {
708 HandleException(errcode, message_buffer, buffer_length);
709 }
710 return _HUGE;
711}
712
713EXPORT_CODE double CONVENTION AbstractState_second_partial_deriv(const long handle, const long Of1, const long Wrt1, const long Constant1,
714 const long Wrt2, const long Constant2, long* errcode, char* message_buffer,
715 const long buffer_length) {
716 *errcode = 0;
717 try {
718 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
719 return AS->second_partial_deriv(static_cast<CoolProp::parameters>(Of1), static_cast<CoolProp::parameters>(Wrt1),
720 static_cast<CoolProp::parameters>(Constant1), static_cast<CoolProp::parameters>(Wrt2),
721 static_cast<CoolProp::parameters>(Constant2));
722 } catch (...) {
723 HandleException(errcode, message_buffer, buffer_length);
724 }
725 return _HUGE;
726}
727
728EXPORT_CODE double CONVENTION AbstractState_second_two_phase_deriv(const long handle, const long Of1, const long Wrt1, const long Constant1,
729 const long Wrt2, const long Constant2, long* errcode, char* message_buffer,
730 const long buffer_length) {
731 *errcode = 0;
732 try {
733 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
734 return AS->second_two_phase_deriv(static_cast<CoolProp::parameters>(Of1), static_cast<CoolProp::parameters>(Wrt1),
735 static_cast<CoolProp::parameters>(Constant1), static_cast<CoolProp::parameters>(Wrt2),
736 static_cast<CoolProp::parameters>(Constant2));
737 } catch (...) {
738 HandleException(errcode, message_buffer, buffer_length);
739 }
740 return _HUGE;
741}
742
743EXPORT_CODE double CONVENTION AbstractState_first_two_phase_deriv(const long handle, const long Of, const long Wrt, const long Constant,
744 long* errcode, char* message_buffer, const long buffer_length) {
745 *errcode = 0;
746 try {
747 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
748 return AS->first_two_phase_deriv(static_cast<CoolProp::parameters>(Of), static_cast<CoolProp::parameters>(Wrt),
749 static_cast<CoolProp::parameters>(Constant));
750 } catch (...) {
751 HandleException(errcode, message_buffer, buffer_length);
752 }
753 return _HUGE;
754}
755
756EXPORT_CODE double CONVENTION AbstractState_first_two_phase_deriv_splined(const long handle, const long Of, const long Wrt, const long Constant,
757 const double x_end, long* errcode, char* message_buffer,
758 const long buffer_length) {
759 *errcode = 0;
760 try {
761 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
762 return AS->first_two_phase_deriv_splined(static_cast<CoolProp::parameters>(Of), static_cast<CoolProp::parameters>(Wrt),
763 static_cast<CoolProp::parameters>(Constant), x_end);
764 } catch (...) {
765 HandleException(errcode, message_buffer, buffer_length);
766 }
767 return _HUGE;
768}
769
770EXPORT_CODE void CONVENTION AbstractState_update_and_common_out(const long handle, const long input_pair, const double* value1, const double* value2,
771 const long length, double* T, double* p, double* rhomolar, double* hmolar,
772 double* smolar, long* errcode, char* message_buffer, const long buffer_length) {
773 *errcode = 0;
774 try {
775 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
776
777 for (int i = 0; i < length; i++) {
778 try {
779 AS->update(static_cast<CoolProp::input_pairs>(input_pair), *(value1 + i), *(value2 + i));
780 *(T + i) = AS->T();
781 *(p + i) = AS->p();
782 *(rhomolar + i) = AS->rhomolar();
783 *(hmolar + i) = AS->hmolar();
784 *(smolar + i) = AS->smolar();
785 } catch (...) {
786 }
787 };
788 } catch (...) {
789 HandleException(errcode, message_buffer, buffer_length);
790 }
791}
792
793EXPORT_CODE void CONVENTION AbstractState_update_and_1_out(const long handle, const long input_pair, const double* value1, const double* value2,
794 const long length, const long output, double* out, long* errcode, char* message_buffer,
795 const long buffer_length) {
796 *errcode = 0;
797 try {
798 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
799
800 for (int i = 0; i < length; i++) {
801 try {
802 AS->update(static_cast<CoolProp::input_pairs>(input_pair), *(value1 + i), *(value2 + i));
803 *(out + i) = AS->keyed_output(static_cast<CoolProp::parameters>(output));
804 } catch (...) {
805 }
806 };
807 } catch (...) {
808 HandleException(errcode, message_buffer, buffer_length);
809 }
810}
811
812EXPORT_CODE void CONVENTION AbstractState_update_and_5_out(const long handle, const long input_pair, const double* value1, const double* value2,
813 const long length, long* outputs, double* out1, double* out2, double* out3, double* out4,
814 double* out5, long* errcode, char* message_buffer, const long buffer_length) {
815 *errcode = 0;
816 try {
817 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
818
819 for (int i = 0; i < length; i++) {
820 try {
821 AS->update(static_cast<CoolProp::input_pairs>(input_pair), *(value1 + i), *(value2 + i));
822 *(out1 + i) = AS->keyed_output(static_cast<CoolProp::parameters>(outputs[0]));
823 *(out2 + i) = AS->keyed_output(static_cast<CoolProp::parameters>(outputs[1]));
824 *(out3 + i) = AS->keyed_output(static_cast<CoolProp::parameters>(outputs[2]));
825 *(out4 + i) = AS->keyed_output(static_cast<CoolProp::parameters>(outputs[3]));
826 *(out5 + i) = AS->keyed_output(static_cast<CoolProp::parameters>(outputs[4]));
827 } catch (...) {
828 }
829 };
830 } catch (...) {
831 HandleException(errcode, message_buffer, buffer_length);
832 }
833}
834
835EXPORT_CODE void CONVENTION AbstractState_set_binary_interaction_double(const long handle, const long i, const long j, const char* parameter,
836 const double value, long* errcode, char* message_buffer,
837 const long buffer_length) {
838 *errcode = 0;
839 try {
840 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
841 AS->set_binary_interaction_double(static_cast<std::size_t>(i), static_cast<std::size_t>(j), parameter, value);
842 } catch (...) {
843 HandleException(errcode, message_buffer, buffer_length);
844 }
845}
846
847EXPORT_CODE void CONVENTION AbstractState_set_cubic_alpha_C(const long handle, const long i, const char* parameter, const double c1, const double c2,
848 const double c3, long* errcode, char* message_buffer, const long buffer_length) {
849 *errcode = 0;
850 try {
851 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
852 AS->set_cubic_alpha_C(static_cast<std::size_t>(i), parameter, c1, c2, c3);
853 } catch (...) {
854 HandleException(errcode, message_buffer, buffer_length);
855 }
856}
857
858EXPORT_CODE void CONVENTION AbstractState_set_fluid_parameter_double(const long handle, const long i, const char* parameter, const double value,
859 long* errcode, char* message_buffer, const long buffer_length) {
860 *errcode = 0;
861 try {
862 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
863 AS->set_fluid_parameter_double(static_cast<std::size_t>(i), parameter, value);
864 } catch (...) {
865 HandleException(errcode, message_buffer, buffer_length);
866 }
867}
868
869EXPORT_CODE void CONVENTION AbstractState_build_phase_envelope(const long handle, const char* level, long* errcode, char* message_buffer,
870 const long buffer_length) {
871 *errcode = 0;
872 try {
873 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
874 AS->build_phase_envelope(level);
875 } catch (...) {
876 HandleException(errcode, message_buffer, buffer_length);
877 }
878}
879
880EXPORT_CODE void CONVENTION AbstractState_get_phase_envelope_data(const long handle, const long length, double* T, double* p, double* rhomolar_vap,
881 double* rhomolar_liq, double* x, double* y, long* errcode, char* message_buffer,
882 const long buffer_length) {
883 *errcode = 0;
884 try {
885 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
886 CoolProp::PhaseEnvelopeData pe = AS->get_phase_envelope_data();
887 if (pe.T.size() > static_cast<std::size_t>(length)) {
888 throw CoolProp::ValueError(format("Length of phase envelope vectors [%d] is greater than allocated buffer length [%d]",
889 static_cast<int>(pe.T.size()), static_cast<int>(length)));
890 }
891 std::size_t N = pe.x.size();
892 for (std::size_t i = 0; i < pe.T.size(); i++) {
893 *(T + i) = pe.T[i];
894 *(p + i) = pe.p[i];
895 *(rhomolar_vap + i) = pe.rhomolar_vap[i];
896 *(rhomolar_liq + i) = pe.rhomolar_liq[i];
897 for (std::size_t j = 0; j < N; ++j) {
898 *(x + i * N + j) = pe.x[j][i];
899 *(y + i * N + j) = pe.y[j][i];
900 }
901 }
902 } catch (...) {
903 HandleException(errcode, message_buffer, buffer_length);
904 }
905}
906
907EXPORT_CODE void CONVENTION AbstractState_get_phase_envelope_data_checkedMemory(const long handle, const long length, const long maxComponents,
908 double* T, double* p, double* rhomolar_vap, double* rhomolar_liq,
909 double* x, double* y, long* actual_length, long* actual_components,
910 long* errcode, char* message_buffer, const long buffer_length) {
911 *errcode = 0;
912 try {
913 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
914 CoolProp::PhaseEnvelopeData pe = AS->get_phase_envelope_data();
915 *actual_length = static_cast<long>(pe.T.size());
916 if (pe.T.size() > static_cast<std::size_t>(length)) {
917 throw CoolProp::ValueError(format("Length of phase envelope vectors [%d] is greater than allocated buffer length [%d]",
918 static_cast<int>(pe.T.size()), static_cast<int>(length)));
919 }
920 *actual_components = static_cast<long>(pe.x.size());
921 if (static_cast<std::size_t>(*actual_components) > static_cast<std::size_t>(maxComponents)) {
922 throw CoolProp::ValueError(format("Length of phase envelope composition vectors [%d] is greater than allocated buffer length [%d]",
923 static_cast<int>(*actual_components), static_cast<int>(maxComponents)));
924 }
925 for (std::size_t i = 0; i < pe.T.size(); i++) {
926 *(T + i) = pe.T[i];
927 *(p + i) = pe.p[i];
928 *(rhomolar_vap + i) = pe.rhomolar_vap[i];
929 *(rhomolar_liq + i) = pe.rhomolar_liq[i];
930 for (std::size_t j = 0; j < static_cast<std::size_t>(*actual_components); ++j) {
931 *(x + i * *actual_components + j) = pe.x[j][i];
932 *(y + i * *actual_components + j) = pe.y[j][i];
933 }
934 }
935 } catch (...) {
936 HandleException(errcode, message_buffer, buffer_length);
937 }
938}
939
940EXPORT_CODE void CONVENTION AbstractState_build_spinodal(const long handle, long* errcode, char* message_buffer, const long buffer_length) {
941 *errcode = 0;
942 try {
943 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
944 AS->build_spinodal();
945 } catch (...) {
946 HandleException(errcode, message_buffer, buffer_length);
947 }
948}
949
950EXPORT_CODE void CONVENTION AbstractState_get_spinodal_data(const long handle, const long length, double* tau, double* delta, double* M1,
951 long* errcode, char* message_buffer, const long buffer_length) {
952 *errcode = 0;
953 try {
954 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
955 CoolProp::SpinodalData spin = AS->get_spinodal_data();
956 if (spin.tau.size() > static_cast<std::size_t>(length)) {
957 throw CoolProp::ValueError(format("Length of spinodal vectors [%d] is greater than allocated buffer length [%d]",
958 static_cast<int>(spin.tau.size()), static_cast<int>(length)));
959 }
960 for (std::size_t i = 0; i < spin.tau.size(); ++i) {
961 *(tau + i) = spin.tau[i];
962 *(delta + i) = spin.delta[i];
963 *(M1 + i) = spin.M1[i];
964 }
965 } catch (...) {
966 HandleException(errcode, message_buffer, buffer_length);
967 }
968}
969
970EXPORT_CODE void CONVENTION AbstractState_all_critical_points(const long handle, long length, double* T, double* p, double* rhomolar, long* stable,
971 long* errcode, char* message_buffer, const long buffer_length) {
972 *errcode = 0;
973 try {
974 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
975 std::vector<CoolProp::CriticalState> pts = AS->all_critical_points();
976 if (pts.size() > static_cast<std::size_t>(length)) {
977 throw CoolProp::ValueError(format("Length of critical point vector [%d] is greater than allocated buffer length [%d]",
978 static_cast<int>(pts.size()), static_cast<int>(length)));
979 }
980 for (std::size_t i = 0; i < pts.size(); ++i) {
981 *(T + i) = pts[i].T;
982 *(p + i) = pts[i].p;
983 *(rhomolar + i) = pts[i].rhomolar;
984 *(stable + i) = pts[i].stable;
985 }
986 } catch (...) {
987 HandleException(errcode, message_buffer, buffer_length);
988 }
989}
990
991EXPORT_CODE double CONVENTION AbstractState_keyed_output_satState(const long handle, const char* saturated_state, const long param, long* errcode,
992 char* message_buffer, const long buffer_length) {
993 *errcode = 0;
994
995 try {
996 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
997 double quality = AS->Q();
998 std::string string_state(saturated_state);
999 if (0 <= quality && quality <= 1) {
1000 if (string_state == "liquid") {
1001 return AS->saturated_liquid_keyed_output(static_cast<CoolProp::parameters>(param));
1002 } else if (string_state == "gas") {
1003 return AS->saturated_vapor_keyed_output(static_cast<CoolProp::parameters>(param));
1004 } else {
1006 format("Bad info string [%s] to saturated state output, options are \"liquid\" and \"gas\"", saturated_state));
1007 }
1008 } else {
1009 throw CoolProp::ValueError(format("AbstractState_keyed_output_satState only returns outputs for saturated states if AbstractState "
1010 "quality [%g] is within two-phase region (0 <= quality <= 1)",
1011 static_cast<double>(quality)));
1012 }
1013 } catch (...) {
1014 HandleException(errcode, message_buffer, buffer_length);
1015 return _HUGE;
1016 }
1017}
1018
1019EXPORT_CODE void CONVENTION AbstractState_backend_name(const long handle, char* backend, long* errcode, char* message_buffer,
1020 const long buffer_length) {
1021 *errcode = 0;
1022
1023 try {
1024 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
1025 std::string backendstring = AS->backend_name();
1026 if (backendstring.size() < static_cast<std::size_t>(buffer_length)) {
1027 strcpy(backend, backendstring.c_str());
1028 } else {
1029 throw CoolProp::ValueError(format("Length of string [%d] is greater than allocated buffer length [%d]", backendstring.size(),
1030 static_cast<std::size_t>(buffer_length)));
1031 }
1032 } catch (...) {
1033 HandleException(errcode, message_buffer, buffer_length);
1034 }
1035}
1036
1037EXPORT_CODE int CONVENTION AbstractState_phase(const long handle, long* errcode, char* message_buffer, const long buffer_length) {
1038 *errcode = 0;
1039 try {
1040 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
1041 return AS->phase();
1042 } catch (...) {
1043 HandleException(errcode, message_buffer, buffer_length);
1044 }
1045 return -1;
1046}
1047
1048EXPORT_CODE void CONVENTION AbstractState_fluid_param_string(const long handle, const char* param, char* return_buffer,
1049 const long return_buffer_length, long* errcode, char* message_buffer,
1050 const long buffer_length) {
1051 *errcode = 0;
1052 try {
1053 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
1054 std::string temp = AS->fluid_param_string(param);
1055 if (temp.size() < static_cast<std::size_t>(return_buffer_length)) {
1056 strcpy(return_buffer, temp.c_str());
1057 } else {
1058 *errcode = 2;
1059 }
1060 } catch (...) {
1061 HandleException(errcode, message_buffer, buffer_length);
1062 }
1063}
1064
1065EXPORT_CODE double CONVENTION AbstractState_saturated_liquid_keyed_output(const long handle, const long param, long* errcode, char* message_buffer,
1066 const long buffer_length) {
1067 *errcode = 0;
1068 try {
1069 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
1070 return AS->saturated_liquid_keyed_output(static_cast<CoolProp::parameters>(param));
1071 } catch (...) {
1072 HandleException(errcode, message_buffer, buffer_length);
1073 }
1074 return _HUGE;
1075}
1076
1077EXPORT_CODE double CONVENTION AbstractState_saturated_vapor_keyed_output(const long handle, const long param, long* errcode, char* message_buffer,
1078 const long buffer_length) {
1079 *errcode = 0;
1080 try {
1081 shared_ptr<CoolProp::AbstractState>& AS = handle_manager.get(handle);
1082 return AS->saturated_vapor_keyed_output(static_cast<CoolProp::parameters>(param));
1083 } catch (...) {
1084 HandleException(errcode, message_buffer, buffer_length);
1085 }
1086 return _HUGE;
1087}
1088
1089EXPORT_CODE void CONVENTION add_fluids_as_JSON(const char* backend, const char* fluidstring, long* errcode, char* message_buffer,
1090 const long buffer_length) {
1091 *errcode = 0;
1092
1093 try {
1094 CoolProp::add_fluids_as_JSON(backend, fluidstring);
1095 } catch (...) {
1096 HandleException(errcode, message_buffer, buffer_length);
1097 }
1098}
1099
1101 return CoolProp::is_valid_fluid_string(fluidName);
1102}
1103
1104EXPORT_CODE int CONVENTION C_extract_backend(const char* fluid_string, char* backend, const long backend_length, char* fluid,
1105 const long fluid_length) {
1106 std::string _fluid, _backend;
1107 CoolProp::extract_backend(fluid_string, _backend, _fluid);
1108 if (_backend.size() < static_cast<std::size_t>(backend_length)) {
1109 strcpy(backend, _backend.c_str());
1110 } else {
1111 return -1;
1112 }
1113 if (_fluid.size() < static_cast<std::size_t>(fluid_length)) {
1114 strcpy(fluid, _fluid.c_str());
1115 } else {
1116 return -1;
1117 }
1118 return 0;
1119}