# Story 2.2: CoolProp Integration (sys-crate) Status: done ## Story As a simulation user, I want CoolProp as the primary backend, so that I get NIST-quality thermodynamic data. ## Acceptance Criteria 1. **CoolProp Backend Implementation** (AC: #1) - [x] Implement `CoolPropBackend` struct wrapping CoolProp C++ library - [x] All `FluidBackend` trait methods must work correctly - [x] Results must match CoolProp 6.4+ within machine precision 2. **Static Linking via sys-crate** (AC: #2) - [x] Set up `crates/fluids/coolprop-sys/` sys-crate - [x] Configure `build.rs` for static compilation of CoolProp C++ - [x] Ensure distribution without runtime C++ dependencies 3. **Safe Rust FFI Wrappers** (AC: #3) - [x] Create safe Rust wrappers around raw CoolProp FFI - [x] Handle error translation between C++ and Rust - [x] No unsafe code exposed in public API 4. **Thermodynamic Properties** (AC: #4) - [x] Support property queries: density, enthalpy, entropy, specific heat - [x] Support (P, T), (P, h), (P, x) state inputs - [x] Handle pure fluids and mixtures ## Tasks / Subtasks - [x] Complete coolprop-sys sys-crate setup (continues from 2-1) - [x] Finalize `coolprop-sys/Cargo.toml` with correct features - [x] Configure static linking in `build.rs` - [x] Generate safe FFI bindings - [x] Implement CoolPropBackend struct (AC: #1) - [x] Wrap CoolProp C++ calls in safe Rust - [x] Implement all FluidBackend trait methods - [x] Handle fluid name translation (CoolProp internal names) - [x] Add error handling (AC: #3) - [x] Translate CoolProp error codes to FluidError - [x] Handle missing fluids gracefully - [x] Handle invalid states - [x] Test CoolProp backend (AC: #4) - [x] Test against known values from CoolProp documentation - [x] Verify precision matches within machine epsilon - [x] Test all supported property types ## Dev Notes ### Previous Story Intelligence **From Story 2-1 (Fluid Backend Trait Abstraction):** - The `FluidBackend` trait is already defined in `crates/fluids/src/backend.rs` - Trait includes `property()` and `critical_point()` methods - Three backends planned: CoolPropBackend, TabularBackend, TestBackend - Error handling pattern established with `FluidError` enum - Workspace structure created: `crates/fluids/coolprop-sys/` directory exists - Build.rs started for CoolProp C++ compilation - **Key learning:** Sys-crate setup is complex - ensure static linking works before implementing backend ### Architecture Context **C++ Integration Requirements (from Architecture):** ```rust // Sys-crate pattern location: crates/fluids/coolprop-sys/ // build.rs manages static compilation of CoolProp C++ ``` **CoolPropBackend Structure:** ```rust pub struct CoolPropBackend { // Wraps coolprop-sys FFI calls // Uses interior mutability for thread-safety if needed } impl FluidBackend for CoolPropBackend { fn property(&self, fluid: FluidId, property: Property, state: ThermoState) -> Result { // Translate to CoolProp internal fluid names // Call CoolProp C++ via sys-crate // Translate result/error back to Rust } } ``` **Fluid Name Translation:** - CoolProp uses internal names (e.g., "R134a" → "R1344A") - Need mapping table or lookup - Handle case sensitivity ### Workspace Structure **Location:** `crates/fluids/` ``` crates/fluids/ ├── Cargo.toml ├── build.rs # Compilation CoolProp C++ ├── coolprop-sys/ # Sys-crate C++ (CONTINUE FROM 2-1) │ ├── Cargo.toml │ ├── build.rs # Configure static linking │ └── src/ │ └── lib.rs # FFI bindings └── src/ ├── lib.rs ├── backend.rs # FluidBackend trait (DONE in 2-1) ├── coolprop.rs # FR25: CoolProp integration (THIS STORY) ├── tabular.rs # FR26: Tables NIST (Story 2.3) ├── cache.rs # LRU cache (Story 2.4) └── damping.rs # FR29: Critical point (Story 2.6) ``` ### Technical Requirements **Sys-crate Configuration (CRITICAL):** - Static linking required for distribution - `build.rs` must compile CoolProp C++ library - Use `cc` crate for C++ compilation - Configure appropriate compiler flags for static libs **FFI Safety:** - All FFI calls must be in `unsafe` blocks - Wrap in safe public methods - No `unsafe` exposed to users of the crate **Supported Properties:** - Density (rho) - Enthalpy (h) - Entropy (s) - Specific heat (cp, cv) - Temperature (T) - Pressure (P) - Quality (x) - Viscosity (optional) - Thermal conductivity (optional) **Supported State Inputs:** - (P, T) - pressure & temperature - (P, h) - pressure & enthalpy (preferred for two-phase) - (P, x) - pressure & quality - (T, x) - temperature & quality - (P, s) - pressure & entropy ### Error Handling Pattern ```rust #[derive(Error, Debug)] pub enum FluidError { #[error("Fluid {fluid} not found")] UnknownFluid { fluid: String }, #[error("Invalid state for property calculation: {reason}")] InvalidState { reason: String }, #[error("CoolProp error: {0}")] CoolPropError(String), #[error("Critical point not available for {fluid}")] NoCriticalPoint { fluid: String }, } // From 2-1 - already defined, reuse ``` ### Testing Requirements **Required Tests:** - Verify CoolProp backend returns expected values for R134a, R410A, CO2 - Test all property types - Test all state input types - Compare against CoolProp documentation values - Test error handling for invalid fluids - Test mixture handling (if supported) **Validation Values (Examples from CoolProp):** ```rust // R134a at 0°C (273.15K), saturated liquid // Expected: density ≈ 1205.97 kg/m³, h ≈ 200 kJ/kg ``` ### Project Structure Notes **Alignment with Unified Structure:** - Follows workspace-based multi-crate architecture - Uses trait-based design from Story 2-1 - Located in `crates/fluids/` per project structure - Sys-crate pattern for CoolProp C++ integration **Dependencies:** - Depends on `crates/core` for types (Pressure, Temperature, etc.) - Depends on Story 2-1 `FluidBackend` trait - coolprop-sys provides C++ FFI layer ### References - **Epic 2 Story 2.2:** [Source: planning-artifacts/epics.md#Story 2.2] - **Architecture C++ Integration:** [Source: planning-artifacts/architecture.md#C++ Integration] - **Architecture Fluid Backend:** [Source: planning-artifacts/architecture.md#Fluid Properties Backend] - **Story 2-1 (Previous):** [Source: implementation-artifacts/2-1-fluid-backend-trait-abstraction.md] - **NFR11:** CoolProp 6.4+ compatibility [Source: planning-artifacts/epics.md#NonFunctional Requirements] - **FR25:** Load fluid properties via CoolProp [Source: planning-artifacts/epics.md#Requirements Inventory] --- ## Dev Agent Record ### Agent Model Used opencode/minimax-m2.5-free ### Debug Log References N/A - Story just created ### Completion Notes List - Story file created with comprehensive context from epics, architecture, and previous story - All acceptance criteria defined with checkboxes - Dev notes include architecture patterns, code examples, testing requirements - References to source documents provided - Previous story learnings incorporated (2-1) - Status set to ready-for-dev - Code review fixes applied: - Added #![allow(dead_code)] to coolprop-sys to suppress unused FFI warnings - Added lints.rust configuration to Cargo.toml for unsafe_code - Fixed test imports to only include what's needed ### File List 1. `crates/fluids/coolprop-sys/Cargo.toml` - Sys-crate configuration 2. `crates/fluids/coolprop-sys/build.rs` - Build script for static linking 3. `crates/fluids/coolprop-sys/src/lib.rs` - FFI bindings to CoolProp C++ 4. `crates/fluids/src/coolprop.rs` - CoolPropBackend implementation 5. `crates/fluids/src/lib.rs` - Updated exports 6. `crates/fluids/Cargo.toml` - Added coolprop-sys dependency ### Change Log - Date: 2026-02-15 - Initial implementation of CoolPropBackend with sys-crate FFI - Date: 2026-02-15 - Code review fixes: Added #![allow(dead_code)] and lints.rust config --- **Ultimate context engine analysis completed - comprehensive developer guide created**