🎯 Inverse Control Demo Report

Generated: 2026-02-21 10:42:46

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)