# Entropyk: Comprehensive Examples Suite This document provides advanced modeling scenarios for Entropyk across its multi-platform ecosystem. --- ## 1. Multi-Circuit Industrial Chiller (Rust) Modeling a water-cooled chiller where a refrigerant loop (R134a) and a water loop are coupled via an evaporator (bridge). ### 1.1 System Architecture ```mermaid graph LR subgraph Circuit_0 [Circuit 0: Refrigerant] comp[Compressor] --> cond[Condenser] cond --> valve[Expansion Valve] valve --> evap_a[Evaporator Side A] evap_a --> comp end subgraph Circuit_1 [Circuit 1: Water Loop] pump[Pump] --> evap_b[Evaporator Side B] evap_b --> building[Building Load] building --> pump end evap_a <-.->|Thermal Coupling| evap_b ``` ### 1.2 Implementation Detail ```rust use entropyk_components::{Compressor, HeatExchanger, Pump}; use entropyk_solver::{System, NewtonConfig, ThermalCoupling}; fn main() -> Result<(), Box> { let mut system = System::new(); // Circuit 0: Refrigerant Loop let comp = system.add_component(Compressor::new(coeffs, ...)); let cond = system.add_component(HeatExchanger::new_condenser(ua_air)); let valve = system.add_component(ExpansionValve::new(cv)); let evap = system.add_component(HeatExchanger::new_bridge(ua_water)); // COUPLING POINT system.add_edge_in_circuit(comp, cond, 0)?; system.add_edge_in_circuit(cond, valve, 0)?; system.add_edge_in_circuit(valve, evap.side_a, 0)?; system.add_edge_in_circuit(evap.side_a, comp, 0)?; // Circuit 1: Water loop let pump = system.add_component(Pump::new(curve)); let building = system.add_component(HeatExchanger::new_load(50_000.0)); // 50kW Load system.add_edge_in_circuit(pump, evap.side_b, 1)?; system.add_edge_in_circuit(evap.side_b, building, 1)?; system.add_edge_in_circuit(building, pump, 1)?; system.finalize()?; // Simultaneous Multi-Circuit Solve let solver = NewtonConfig::default().with_line_search(true); let state = solver.solve(&mut system)?; println!("Chiller System COP: {}", state.cop()); Ok(()) } ``` ### 1.3 Control & Coupling Logic The solver treats both circuits as a unified graph. The `HeatExchanger` bridge enforces the following boundary conditions: - **Energy Balance**: $\dot{Q}_{refrig} = \dot{Q}_{water}$ (assuming no ambient loss). - **Temperature Coupling**: The effectiveness-NTU model internally calculates the heat transfer based on the inlet temperatures of *both* circuits. - **Unified Jacobian**: The solver constructs a single Jacobian matrix where off-diagonal blocks represent the thermal coupling, allowing for simultaneous convergence of both loops. --- ## 2. Inverse Control & Parameter Estimation (Python) Finding the Heat Exchanger Fouling (UA) by matching simulation to sensor data. ### 2.1 Control Flow Diagram ```mermaid sequenceDiagram participant U as User (Script) participant S as System Solver participant P as Physical Model participant C as Constraint Engine U->>S: Define Architecture & Constraints Note over S,C: Link Constraint (Temp) to Control (UA) loop Iterations (Newton-Raphson) S->>P: Compute Residuals F(x) P->>S: Physical Violations S->>C: Compute Constraint Gradients (dC/dua) C->>S: Jacobian Block S->>S: Solve Augmented System [J | G] S->>S: Update State (x) & Control (ua) end S->>U: Converged Parameters (UA) ``` ### 2.2 Implementation Breakdown ```python import entropyk as ek # 1. Define physical system sys = ek.System() hx = sys.add_component(ek.HeatExchanger(ua=5000.0)) # Initial guess # 2. Add Constraint: We KNOW the exit temperature from a sensor # Target: Exit port of HX must be 280.15 K sys.add_constraint( node_id=hx, variable="exit_temp", target=280.15, tolerance=0.01 ) # 3. Designate UA as a "Calibration Variable" (Solver will tune this) sys.link_constraint_to_control(hx, "ua", bounds=(1000.0, 10000.0)) # 4. Solve Sparse Inverse Problem solver = ek.NewtonConfig(inverse_mode=True) result = solver.solve(sys) print(f"Estimated UA based on sensor: {hx.ua:.2f} W/K") ``` ### 2.3 Logic Breakdown: The Augmented Matrix In standard "Forward" mode, the solver solves $F(x) = 0$. In "Inverse" mode, we add a constraint $C(x, u) = 0$ (where $u$ is our control, e.g., UA). The solver internally solves: $$ \begin{bmatrix} \mathcal{J}_x & \mathcal{G}_u \\ \mathcal{C}_x & 0 \end{bmatrix} \begin{bmatrix} \Delta x \\ \Delta u \end{bmatrix} = -\begin{bmatrix} F(x) \\ C(x, u) \end{bmatrix} $$ - $\mathcal{J}_x$: Standard physical Jacobian. - $\mathcal{G}_u$: Sensitivity of physics to the control variable (how a change in UA affects mass/energy residuals). - $\mathcal{C}_x$: Sensitivity of the constraint to state variables. - $\Delta u$: The correction to our estimated parameter (UA) to satisfy the sensor target. --- ## 3. Real-Time HIL Integration (C FFI) Zero-allocation solving for embedded controllers at 100Hz. ```c #include "entropyk.h" int main() { // 1. Initialize system once (pre-allocate hooks) ek_system_t* sys = ek_system_create(); ek_compressor_t* comp = ek_compressor_create(coeffs); ek_system_add_component(sys, comp); // ... connections ... ek_system_finalize(sys); // 2. Control Loop (10ms steps) while (running) { // Update boundary conditions (e.g. ambient T) ek_system_set_source_temp(sys, source_node, get_sensor_t()); // Solve using previous state as hot-start ek_converged_state_t* res = ek_solve(sys, PICARD_STRATEGY); if (ek_converged_state_is_ok(res)) { float p_disch = ek_converged_state_get_p(res, discharge_port); apply_to_plc(p_disch); } ek_converged_state_free(res); } ek_system_free(sys); } ```