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