# 🎯 Inverse Control Demo Report

Generated: 2026-02-22 11:01:44

## One-Shot Inverse Control Concept

#### What is Inverse Control?

Instead of specifying inputs and computing outputs (forward simulation), inverse control specifies desired outputs and computes the required inputs automatically.

Example: "Maintain 5K superheat" → System finds the correct valve position

#### Traditional Approach

- Outer optimization loop
- Many solver iterations
- Slow convergence

#### One-Shot Approach (FR24)

- Single solver call
- Constraints embedded in residuals
- Control variables as unknowns
- Fast convergence

rtotal = [rcycle, rconstraints]T = 0

## Degrees of Freedom (DoF) Validation

For a well-posed system, the number of equations must equal the number of unknowns:

nequations = nedge_eqs + nconstraints
nunknowns = nedge_unknowns + ncontrols
Balanced: nequations = nunknowns

##### Balanced

Equations = Unknowns

SOLVABLE

##### Over-Constrained

Equations > Unknowns

ERROR

##### Under-Constrained

Equations < Unknowns

WARNING

##### Example Calculation

Component | Count | Contribution
--- | --- | ---
Edges | 4 | 2 × 4 = 8 unknowns (P, h)
Components | 4 | 8 equations (2 per component)
Constraints | 1 | +1 equation
Control Variables | 1 | +1 unknown
Total |  | 9 equations = 9 unknowns ✓

## Implementation Workflow

##### Step 1: Define Constraint

Create a constraint specifying the desired output:

let constraint = Constraint::new( ConstraintId::new("superheat"), ComponentOutput::Superheat { component_id: "evaporator".into(), }, 5.0, // target: 5K superheat );

##### Step 2: Define Control Variable

Create a bounded variable with physical limits:

let valve = BoundedVariable::new( BoundedVariableId::new("expansion_valve"), 0.5, // initial: 50% open 0.0, // min: fully closed 1.0, // max: fully open )?;

##### Step 3: Add to System

Register constraint and control variable:

system.add_constraint(constraint)?; system.add_bounded_variable(valve)?;

##### Step 4: Link Constraint to Control

Establish the One-Shot relationship:

system.link_constraint_to_control( &ConstraintId::new("superheat"), &BoundedVariableId::new("expansion_valve"), )?;

##### Step 5: Validate DoF

Ensure the system is well-posed:

system.validate_inverse_control_dof()?; // Returns Ok(()) if balanced

## Complete Code Example

use entropyk_solver::{ System, CircuitId, inverse::{ Constraint, ConstraintId, ComponentOutput, BoundedVariable, BoundedVariableId, }, }; fn main() -> Result<(), Box<dyn Error>> { // 1. Build the system let mut system = System::new(); // Add components let compressor = system.add_component(make_compressor()); let condenser = system.add_component(make_condenser()); let valve = system.add_component(make_valve()); let evaporator = system.add_component(make_evaporator()); // Register names for constraints system.register_component_name("evaporator", evaporator); // Connect components system.add_edge(compressor, condenser)?; system.add_edge(condenser, valve)?; system.add_edge(valve, evaporator)?; system.add_edge(evaporator, compressor)?; // 2. Define constraint: maintain 5K superheat let constraint = Constraint::new( ConstraintId::new("superheat_control"), ComponentOutput::Superheat { component_id: "evaporator".to_string(), }, 5.0, // target: 5 Kelvin ); system.add_constraint(constraint)?; // 3. Define bounded control variable let control = BoundedVariable::new( BoundedVariableId::new("valve_position"), 0.5, // initial position 0.1, // min: 10% open 1.0, // max: fully open )?; system.add_bounded_variable(control)?; // 4. Link constraint to control (One-Shot) system.link_constraint_to_control( &ConstraintId::new("superheat_control"), &BoundedVariableId::new("valve_position"), )?; // 5. Finalize and validate DoF system.finalize()?; system.validate_inverse_control_dof()?; // 6. Solve (One-Shot: constraints solved simultaneously) let solver = NewtonRaphson::new(); let result = solver.solve(&system)?; // 7. Check result let final_valve = system.get_bounded_variable( &BoundedVariableId::new("valve_position") ).unwrap(); println!("Valve position: {:.2}%", final_valve.value() * 100.0); println!("Converged: {:?}", result.converged()); Ok(()) }

##### System Methods for Inverse Control

Method | Description
--- | ---
`add_constraint()` | Add a constraint to the system
`add_bounded_variable()` | Add a bounded control variable
`link_constraint_to_control()` | Link constraint to control for One-Shot solving
`unlink_constraint()` | Remove constraint-control linkage
`validate_inverse_control_dof()` | Validate degrees of freedom
`control_variable_state_index()` | Get state vector index for control variable
`full_state_vector_len()` | Total state length including controls
`compute_constraint_residuals()` | Compute residuals for all constraints
`compute_inverse_control_jacobian()` | Jacobian entries for ∂constraint/∂control

## Simulation Results

###### Initial Superheat

## 2.3 K

###### Target Superheat

## 5.0 K

###### Final Superheat

## 5.02 K

###### Iterations

## 7

##### Superheat Convergence

##### Valve Position Evolution

##### DoF Analysis

Edge Unknowns (P, h) | 8
Control Variables | +1
Total Unknowns | 9
Component Equations | 8
Constraint Equations | +1
Total Equations | 9
Balance | ✓ Balanced

##### Control Variable Details

Variable ID | `valve_position`
Initial Value | 50%
Final Value | 38%
Bounds | [10%, 100%]
Saturated | No
State Index | 8 (after edge states)