178 lines
5.8 KiB
Markdown
178 lines
5.8 KiB
Markdown
# 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<dyn std::error::Error>> {
|
|
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);
|
|
}
|
|
```
|