Entropyk/docs/tutorial/01-getting-started.md

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