6.6 KiB
Getting Started with Entropyk
This guide will help you set up your environment and understand the core concepts of thermodynamic simulation with Entropyk.
Prerequisites
-
Rust: Install the latest stable version via rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh rustup update stable -
Python (optional): For Python bindings, Python 3.8+ is required
pip install maturin
Installation
Clone and Build
git clone https://github.com/your-username/Entropyk.git
cd Entropyk
cargo build --workspace
Run Tests
cargo test --workspace
Build Documentation
cargo doc --workspace --open
Project Structure
Entropyk/
├── crates/
│ ├── core/ # Core types (Pressure, Temperature, Enthalpy, MassFlow, Calib)
│ ├── components/ # Thermodynamic components (Compressor, HeatExchanger, etc.)
│ ├── solver/ # Solver strategies (Newton, Picard, Fallback)
│ └── entropyk/ # Unified API crate
├── bindings/
│ ├── python/ # Python bindings
│ └── wasm/ # WebAssembly bindings
├── demo/ # Example applications
└── docs/ # Documentation
Current Status
Important: The Python bindings currently use placeholder adapters (SimpleAdapter) that:
- Accept component parameters
- Build system topology correctly
- Return zero residuals (no actual physics equations)
This means the solver will not converge because there are no real thermodynamic equations to solve. The Python bindings are useful for learning the API structure and testing topology, but not for actual simulations.
Core Concepts
1. System Topology
Entropyk models thermodynamic systems as a directed graph:
- Nodes: Components (Compressor, Heat Exchanger, Valve, etc.)
- Edges: Fluid connections between components
Each edge carries state variables: Pressure (P) and Enthalpy (h).
2. Component Categories
| Category | Purpose | Components |
|---|---|---|
| Active | Add work to fluid | Compressor, Pump, Fan |
| Passive | Pressure drop, no work | Pipe, ExpansionValve |
| Heat Transfer | Exchange heat between fluids | Evaporator, Condenser, Economizer |
| Boundary | Fixed conditions | FlowSource, FlowSink |
| Junction | Flow splitting/merging | FlowSplitter, FlowMerger |
3. Heat Exchanger Architecture
Important: Heat exchangers in Entropyk have 4 ports (not 2):
┌─────────────────────┐
Hot Inlet ──────►│ │──────► Hot Outlet
│ Heat Exchanger │
Cold Inlet ──────►│ │──────► Cold Outlet
└─────────────────────┘
- Evaporator: Refrigerant (cold side) evaporates, absorbing heat from hot side (water/air)
- Condenser: Refrigerant (hot side) condenses, releasing heat to cold side (water/air)
4. Boundary Conditions
Every fluid circuit needs boundary conditions:
- FlowSource: Imposes fixed P and h at circuit inlet
- FlowSink: Imposes back-pressure at circuit outlet
Running the Demo
The macro-chiller demo shows the system architecture:
cargo run --bin macro-chiller
This demonstrates:
- Two chillers in parallel (MacroComponent pattern)
- Hierarchical system composition
- JSON snapshot serialization
Note: The demo uses LinearComponent placeholders, so the solver shows "NonConvergence" - this is expected because placeholders don't implement real thermodynamic equations.
Working Rust Example
Here's a working example using the test infrastructure:
use entropyk_solver::System;
use entropyk_components::{Component, ComponentError, ConnectedPort,
JacobianBuilder, ResidualVector, SystemState};
/// A simple component that returns zero residuals (for testing topology)
struct TestComponent {
n_eq: usize,
}
impl Component for TestComponent {
fn compute_residuals(
&self,
_state: &SystemState,
residuals: &mut ResidualVector,
) -> Result<(), ComponentError> {
for r in residuals.iter_mut().take(self.n_eq) {
*r = 0.0;
}
Ok(())
}
fn jacobian_entries(
&self,
_state: &SystemState,
jacobian: &mut JacobianBuilder,
) -> Result<(), ComponentError> {
for i in 0..self.n_eq {
jacobian.add_entry(i, i, 1.0);
}
Ok(())
}
fn n_equations(&self) -> usize {
self.n_eq
}
fn get_ports(&self) -> &[ConnectedPort] {
&[]
}
}
fn main() {
let mut system = System::new();
// Add components
let comp = system.add_component(Box::new(TestComponent { n_eq: 2 }));
let cond = system.add_component(Box::new(TestComponent { n_eq: 3 }));
let valve = system.add_component(Box::new(TestComponent { n_eq: 1 }));
let evap = system.add_component(Box::new(TestComponent { n_eq: 3 }));
// Connect in cycle
system.add_edge(comp, cond).unwrap();
system.add_edge(cond, valve).unwrap();
system.add_edge(valve, evap).unwrap();
system.add_edge(evap, comp).unwrap();
// Finalize
system.finalize().unwrap();
println!("System created with {} state variables", system.state_vector_len());
}
Python Bindings Status
The Python bindings are useful for:
- Learning the API structure
- Building system topology
- Testing component creation
import entropyk
# Create components (placeholders)
compressor = entropyk.Compressor(
speed_rpm=2900.0,
displacement=0.0001,
efficiency=0.85,
fluid="R134a",
)
# Build system topology
system = entropyk.System()
comp_idx = system.add_component(compressor)
# ... add more components
# Finalize
system.finalize()
print(f"State vector length: {system.state_vector_len}")
Note: The Python bindings use SimpleAdapter placeholders. They accept parameters but don't implement real thermodynamic equations. The solver will not converge because there are no actual physics equations to solve.
Next Steps
- Learn about Physical Types for type-safe unit handling
- Explore Components for all available thermodynamic components
- See Solver Configuration for convergence tuning
- Check the
demo/directory for working Rust examples - Read the
crates/solver/tests/directory for integration test examples