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