1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
//! [<img alt="GitHub" src="https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="22">](https://github.com/portyanikhin/rfluids)
//! [<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs" height="22">](https://docs.rs/rfluids)
//! [<img alt="crates.io" src="https://img.shields.io/crates/v/rfluids?style=for-the-badge&logo=rust&labelColor=555555&color=fc8d62" height="22">](https://crates.io/crates/rfluids)
//! [<img alt="CI" src="https://img.shields.io/github/actions/workflow/status/portyanikhin/rfluids/ci.yml?style=for-the-badge&logo=githubactions&logoColor=ffffff&label=ci&labelColor=555555" height="22">](https://github.com/portyanikhin/rfluids/actions/workflows/ci.yml)
//! [<img alt="codecov" src="https://img.shields.io/codecov/c/github/portyanikhin/rfluids?style=for-the-badge&logo=codecov&label=codecov&labelColor=555555" height="22">](https://app.codecov.io/gh/portyanikhin/rfluids)
//!
//! 🦀 Rusty [`CoolProp`](https://coolprop.org) wrapper
//!
//! ## Overview
//!
//! `rfluids` provides a safe, idiomatic Rust interface to [`CoolProp`](https://coolprop.org) ---
//! a comprehensive C++ library for thermophysical property calculations.
//! Built with type safety and ergonomics in mind, it enables precise fluid property
//! calculations for engineering and scientific applications.
//!
//! ### Key Features
//!
//! - **Rich substance library**: pure fluids, incompressible fluids, predefined mixtures, binary
//! mixtures, and custom mass- or volume-based mixtures
//! - **Comprehensive property calculations**: thermodynamic (e.g., density, enthalpy, entropy,
//! etc.) and transport properties (e.g., viscosity, thermal conductivity, etc.)
//! - **Psychrometric calculations**: based on **ASHRAE RP-1485** standard
//! - **Flexible backends**: choose between `HEOS`, `IF97`, and other `CoolProp` backends, which
//! determine the underlying equation of state or calculation method used for thermophysical
//! property calculations
//! - **Type-safe API**: leverages Rust's type system with the [Typestate Pattern](https://en.wikipedia.org/wiki/Typestate_analysis)
//! to prevent invalid operations at compile time
//! - **Configuration management**: flexible control over `CoolProp` configuration via type-safe
//! builder, with optional `serde` support for loading from configuration files
//! - **Batteries included**: pre-compiled `CoolProp` dynamic libraries for all supported platforms
//!
//! ### Modules
//!
//! - [`fluid`](crate::fluid) -- thermophysical properties of substances (pure fluids and mixtures)
//! - [`humid_air`](crate::humid_air) -- thermophysical properties of _**real**_ humid air
//! - [`substance`](crate::substance) -- types representing `CoolProp` substances
//! - [`io`](crate::io) -- input/output parameter types for fluid and humid air calculations
//! - [`native`](crate::native) -- low-level and high-level `CoolProp` API bindings
//! - [`config`](crate::config) -- global configuration management for `CoolProp`
//! - [`prelude`](crate::prelude) -- convenient re-exports of commonly used types and traits
//!
//! ### Feature Flags
//!
//! - **`regen-bindings`** -- regenerates FFI bindings to `CoolProp` (requires `libclang`)
//! - **`serde`** -- enables serialization and deserialization support for
//! [`Config`](crate::config::Config), allowing integration with configuration management crates
//! and file-based configuration
//!
//! ## Supported platforms
//!
//! - `Linux x86-64`
//! - `macOS AArch64`
//! - `macOS x86-64`
//! - `Windows AArch64`
//! - `Windows x86-64`
//!
//! ## MSRV
//!
//! `rfluids` requires `rustc` 1.85.0 or later.
//!
//! ## How to install
//!
//! Add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! rfluids = "0.3"
//! ```
//!
//! Or via command line:
//!
//! ```shell
//! cargo add rfluids
//! ```
//!
//! 🎁 It comes with native `CoolProp` dynamic libraries for supported platforms. The library
//! required for your platform will be automatically copied to the target directory during build.
//!
//! It also includes pre-generated FFI bindings, so `libclang` is not required for normal builds.
//!
//! ### Regenerating bindings
//!
//! If you need to regenerate the FFI bindings (requires `libclang`), enable the
//! **`regen-bindings`** feature.
//!
//! Add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! rfluids = { version = "0.3", features = ["regen-bindings"] }
//! ```
//!
//! Or via command line:
//!
//! ```shell
//! cargo add rfluids --features regen-bindings
//! ```
//!
//! ## Examples
//!
//! | ℹ️ All calculations are performed in SI units |
//! | :-------------------------------------------: |
//!
//! Specific heat **\[J/kg/K\]** of saturated water vapor at _1 atm_:
//!
//! ```
//! use approx::assert_relative_eq;
//! use rfluids::prelude::*;
//!
//! let mut water_vapor = Fluid::from(Pure::Water)
//! .in_state(FluidInput::pressure(101_325.0), FluidInput::quality(1.0))?;
//! assert_relative_eq!(water_vapor.specific_heat()?, 2_079.937_085_633_241, max_relative = 1e-6);
//! # Ok::<(), rfluids::Error>(())
//! ```
//!
//! Dynamic viscosity **\[Pa·s\]** of propylene glycol aqueous solution
//! with _60 %_ mass fraction at _100 kPa_ and _-20 °C_:
//!
//! ```
//! use approx::assert_relative_eq;
//! use rfluids::prelude::*;
//!
//! let mut propylene_glycol = Fluid::from(BinaryMixKind::MPG.with_fraction(0.6)?)
//! .in_state(FluidInput::pressure(100e3), FluidInput::temperature(253.15))?;
//! assert_relative_eq!(
//! propylene_glycol.dynamic_viscosity()?,
//! 0.139_073_910_539_388_78,
//! max_relative = 1e-6
//! );
//! # Ok::<(), rfluids::Error>(())
//! ```
//!
//! Density **\[kg/m³\]** of ethanol aqueous solution
//! (with ethanol _40 %_ mass fraction) at _200 kPa_ and _4 °C_:
//!
//! ```
//! use approx::assert_relative_eq;
//! use rfluids::prelude::*;
//!
//! let mut mix =
//! Fluid::try_from(CustomMix::mass_based([(Pure::Water, 0.6), (Pure::Ethanol, 0.4)])?)?
//! .in_state(FluidInput::pressure(200e3), FluidInput::temperature(277.15))?;
//! assert_relative_eq!(mix.density()?, 883.392_277_162_775_9, max_relative = 1e-6);
//! # Ok::<(), rfluids::Error>(())
//! ```
//!
//! Wet-bulb temperature **\[K\]** of humid air at _300 m_ above sea level,
//! _30 °C_ and _50 %_ relative humidity:
//!
//! ```
//! use approx::assert_relative_eq;
//! use rfluids::prelude::*;
//!
//! let mut humid_air = HumidAir::new().in_state(
//! HumidAirInput::altitude(300.0)?,
//! HumidAirInput::temperature(303.15),
//! HumidAirInput::rel_humidity(0.5),
//! )?;
//! assert_relative_eq!(
//! humid_air.wet_bulb_temperature()?,
//! 295.067_569_033_474_57,
//! max_relative = 1e-6
//! );
//! # Ok::<(), rfluids::Error>(())
//! ```
//!
//! [`Fluid`](crate::fluid::Fluid) and [`HumidAir`](crate::humid_air::HumidAir)
//! implement the [`PartialEq`] trait. Equality is checked by the thermodynamic state:
//!
//! ```
//! use rfluids::prelude::*;
//!
//! let mut humid_air = HumidAir::new().in_state(
//! HumidAirInput::altitude(0.0)?,
//! HumidAirInput::temperature(293.15),
//! HumidAirInput::rel_humidity(0.5),
//! )?;
//! let mut another_humid_air = HumidAir::new().in_state(
//! HumidAirInput::pressure(101_325.0),
//! HumidAirInput::temperature(293.15),
//! HumidAirInput::rel_humidity(0.5),
//! )?;
//! assert_eq!(humid_air, another_humid_air);
//!
//! another_humid_air.update(
//! HumidAirInput::pressure(101_325.0),
//! HumidAirInput::temperature(303.15),
//! HumidAirInput::rel_humidity(0.5),
//! )?;
//! assert_ne!(humid_air, another_humid_air);
//! # Ok::<(), rfluids::Error>(())
//! ```
//!
//! You can also specify a `CoolProp` backend for [`Fluid`](crate::fluid::Fluid)
//! instead of the default one using [`Fluid::builder`](crate::fluid::Fluid::builder):
//!
//! ```
//! use rfluids::prelude::*;
//!
//! let mut water = Fluid::from(Pure::Water)
//! .in_state(FluidInput::pressure(101_325.0), FluidInput::temperature(293.15))?;
//! let mut if97_water = Fluid::builder()
//! .substance(Pure::Water)
//! .with_backend(BaseBackend::If97)
//! .build()?
//! .in_state(FluidInput::pressure(101_325.0), FluidInput::temperature(293.15))?;
//!
//! // Fluids with different backends are never equal
//! assert_ne!(water, if97_water);
//!
//! // Different backends may yield slightly different results for the same property
//! assert!((water.specific_heat()? - if97_water.specific_heat()?).abs() > 1e-6);
//! # Ok::<(), rfluids::Error>(())
//! ```
//!
//! #### License
//!
//! <sup>
//! This project is licensed under
//! <a href="https://github.com/portyanikhin/rfluids/blob/main/LICENSE">MIT License</a>.
//! </sup>
pub use *;
pub use *;