7.9 KiB
7.9 KiB
Story 2.1: Fluid Backend Trait Abstraction
Status: done
Story
As a library developer, I want to define a FluidBackend trait, so that the solver can switch between CoolProp, tabular, and mock backends.
Acceptance Criteria
-
FluidBackend Trait Definition (AC: #1)
- Define
FluidBackendtrait incrates/fluids/src/backend.rs - Trait must include
property()method for thermodynamic property queries - Trait must include
critical_point()method - Trait must support multiple backend implementations
- Define
-
Method Signatures (AC: #2)
property(&self, fluid: FluidId, property: Property, state: ThermoState) -> Result<f64, FluidError>critical_point(&self, fluid: FluidId) -> Result<CriticalPoint, FluidError>
-
Backend Implementations (AC: #3)
CoolPropBackend- wraps CoolProp C++ library via sys-crateTabularBackend- NIST tables with interpolationTestBackend- mock backend for unit tests (no C++ dependency)
Tasks / Subtasks
- Create
crates/fluidscrate structure (AC: #1)- Create
crates/fluids/Cargo.tomlwith dependencies - Create
crates/fluids/build.rsfor CoolProp C++ compilation - Create
crates/fluids/src/lib.rswith module structure
- Create
- Create
coolprop-syssys-crate for C++ FFI (AC: #2)- Set up
crates/fluids/coolprop-sys/directory - Configure static linking for CoolProp
- Create safe Rust wrappers
- Set up
- Define FluidBackend trait with required methods (AC: #1, #2)
- Add documentation comments with examples
- Ensure method signatures match architecture spec
- Implement CoolPropBackend (AC: #3)
- Wrap CoolProp C++ calls safely
- Handle error translation between C++ and Rust
- Implement TabularBackend (AC: #3)
- Design table structure for fluid properties
- Implement interpolation algorithm
- Verify < 0.01% deviation from NIST
- Implement TestBackend (AC: #3)
- Simple mock implementation for testing
- No external dependencies
- Add comprehensive tests (AC: #3)
- Unit tests for all backends
- Integration tests comparing backends
Dev Notes
Architecture Context
FluidBackend Trait Design (from Architecture Decision Document):
trait FluidBackend {
fn property(&self, fluid: FluidId, property: Property, state: ThermoState)
-> Result<f64, FluidError>;
fn critical_point(&self, fluid: FluidId) -> Result<CriticalPoint, FluidError>;
}
struct CoolPropBackend { /* sys-crate wrapper */ }
struct TabularBackend { /* NIST tables with interpolation */ }
struct TestBackend { /* mocks for unit tests */ }
Caching Strategy:
- LRU cache in backends to avoid redundant CoolProp calls
- Cache invalidation on temperature/pressure changes
- Thread-safe (Arc<Mutex>) for future parallelization
Critical Point Handling (CO2 R744):
fn property_with_damping(&self, state: ThermoState) -> Result<f64, FluidError> {
if self.near_critical_point(state) {
// Automatic damping to avoid NaN in partial derivatives
self.compute_with_damping(state)
} else {
self.property(state)
}
}
Workspace Structure
Crate Location: crates/fluids/
crates/fluids/
├── Cargo.toml
├── build.rs # Compilation CoolProp C++
├── coolprop-sys/ # Sys-crate C++
│ ├── Cargo.toml
│ ├── build.rs
│ └── src/
│ └── lib.rs
└── src/
├── lib.rs
├── backend.rs # FluidBackend trait HERE
├── coolprop.rs # FR25: CoolProp integration
├── tabular.rs # FR26: Tables NIST
├── cache.rs # LRU cache
└── damping.rs # FR29: Critical point
Inter-crate Dependencies:
fluidscrate depends oncorecrate for typessolverandcomponentswill depend onfluidsfor properties- This is the foundation for Epic 2 (all other stories depend on this)
Technical Requirements
Rust Naming Conventions (MUST FOLLOW):
snake_case: modules, functions, variablesCamelCase: types, traits, enum variants- NO prefix
Ifor traits (useFluidBackend, notIFluidBackend)
Required Dependencies (from Architecture):
- CoolProp C++ (via sys-crate)
- nalgebra (for future vector operations)
- thiserror (for FluidError enum)
- serde (for serialization)
- lru-cache or dashmap (for caching)
Error Handling Pattern:
#[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 },
}
pub type FluidResult<T> = Result<T, FluidError>;
Implementation Strategy
- Create crate structure first with Cargo.toml and build.rs
- Set up coolprop-sys for C++ compilation
- Define FluidBackend trait with property() and critical_point()
- Implement TestBackend first - easiest, no dependencies
- Implement CoolPropBackend - wraps sys-crate
- Implement TabularBackend - interpolation tables
- Add caching layer for performance
- Add critical point damping for CO2
Testing Requirements
Required Tests:
- Unit tests for each backend implementation
- Test that all backends return consistent results for known states
- Test error handling for invalid fluids/states
- Test caching behavior
- Test critical point damping for CO2
Test Pattern:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_backend_consistency() {
let coolprop = CoolPropBackend::new();
let test = TestBackend::new();
// Same input should give same output
let state = ThermoState::from_pressure_temperature(101325.0, 300.0);
let cp_result = coolprop.property("R134a", Property::Density, state);
let test_result = test.property("R134a", Property::Density, state);
assert_relative_eq!(cp_result.unwrap(), test_result.unwrap(), epsilon = 0.01);
}
}
Project Structure Notes
Alignment with Unified Structure:
- Follows workspace-based multi-crate architecture
- Uses trait-based design as specified in Architecture
- Located in
crates/fluids/per project structure - Sys-crate pattern for CoolProp C++ integration
Dependencies to Core Crate:
- Will need types from
crates/core:Pressure,Temperature,Enthalpy, etc. - Story 1.2 (Physical Types) created NewTypes that should be used here
References
- Architecture Fluid Properties Backend: [Source: planning-artifacts/architecture.md#Fluid Properties Backend]
- Project Structure: [Source: planning-artifacts/architecture.md#Project Structure & Boundaries]
- FR25-FR29, FR40: Fluid requirements in Epic 2 [Source: planning-artifacts/epics.md#Epic 2]
- Naming Conventions: [Source: planning-artifacts/architecture.md#Naming Patterns]
- Sys-crate Pattern: [Source: planning-artifacts/architecture.md#C++ Integration]
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 and architecture
- All acceptance criteria defined with checkboxes
- Dev notes include architecture patterns, code examples, testing requirements
- References to source documents provided
File List
2-1-fluid-backend-trait-abstraction.md- New story file (this file)
Ultimate context engine analysis completed - comprehensive developer guide created