Entropyk/inverse_control_report.html

752 lines
30 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Inverse Control Demo Report</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
:root {
--primary-color: #2c3e50;
--secondary-color: #3498db;
--success-color: #27ae60;
--warning-color: #f39c12;
--danger-color: #e74c3c;
}
body {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
}
.card {
border: none;
border-radius: 15px;
box-shadow: 0 10px 40px rgba(0,0,0,0.1);
transition: transform 0.3s ease;
}
.card:hover {
transform: translateY(-5px);
}
.code-block {
background: #1e1e1e;
color: #d4d4d4;
border-radius: 10px;
padding: 20px;
overflow-x: auto;
font-family: 'Fira Code', 'Consolas', monospace;
font-size: 0.9rem;
}
.code-block .keyword { color: #569cd6; }
.code-block .string { color: #ce9178; }
.code-block .number { color: #b5cea8; }
.code-block .comment { color: #6a9955; }
.code-block .function { color: #dcdcaa; }
.code-block .type { color: #4ec9b0; }
.formula {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 20px;
border-radius: 10px;
font-family: 'Times New Roman', serif;
font-size: 1.2rem;
text-align: center;
}
.workflow-step {
border-left: 4px solid var(--secondary-color);
padding-left: 20px;
margin-bottom: 20px;
}
.workflow-step::before {
content: '';
width: 20px;
height: 20px;
background: var(--secondary-color);
border-radius: 50%;
display: inline-block;
margin-left: -30px;
margin-right: 10px;
}
.status-badge {
padding: 5px 15px;
border-radius: 20px;
font-weight: bold;
}
.dof-balanced { background: #d4edda; color: #155724; }
.dof-over { background: #f8d7da; color: #721c24; }
.dof-under { background: #fff3cd; color: #856404; }
.gradient-text {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.icon-box {
width: 60px;
height: 60px;
border-radius: 15px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
color: white;
}
.chart-container {
position: relative;
height: 300px;
}
</style>
</head>
</body>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="#">
<i class="bi bi-cpu"></i> Entropyk Inverse Control
</a>
<div class="navbar-nav ms-auto">
<a class="nav-link" href="#concept"><i class="bi bi-lightbulb"></i> Concept</a>
<a class="nav-link" href="#dof"><i class="bi bi-calculator"></i> DoF</a>
<a class="nav-link" href="#workflow"><i class="bi bi-diagram-3"></i> Workflow</a>
<a class="nav-link" href="#code"><i class="bi bi-code-slash"></i> Code</a>
<a class="nav-link" href="#results"><i class="bi bi-graph-up"></i> Results</a>
</div>
</div>
</nav>
<div class="container mt-4">
<h1 class="mb-4">🎯 Inverse Control Demo Report</h1>
<p class="text-muted">Generated: 2026-02-22 11:01:44</p>
<section id="concept" class="mb-5">
<div class="card">
<div class="card-body p-4">
<h2 class="card-title mb-4">
<i class="bi bi-lightbulb text-warning me-2"></i>
One-Shot Inverse Control Concept
</h2>
<div class="row">
<div class="col-md-6">
<h4>What is Inverse Control?</h4>
<p>
Instead of specifying inputs and computing outputs (forward simulation),
<strong>inverse control</strong> specifies desired outputs and computes
the required inputs automatically.
</p>
<div class="alert alert-info">
<i class="bi bi-info-circle me-2"></i>
<strong>Example:</strong> "Maintain 5K superheat" → System finds the correct valve position
</div>
<h4 class="mt-4">Traditional Approach</h4>
<ul class="list-group list-group-flush">
<li class="list-group-item">
<i class="bi bi-x-circle text-danger me-2"></i>
Outer optimization loop
</li>
<li class="list-group-item">
<i class="bi bi-x-circle text-danger me-2"></i>
Many solver iterations
</li>
<li class="list-group-item">
<i class="bi bi-x-circle text-danger me-2"></i>
Slow convergence
</li>
</ul>
</div>
<div class="col-md-6">
<h4>One-Shot Approach (FR24)</h4>
<ul class="list-group list-group-flush">
<li class="list-group-item">
<i class="bi bi-check-circle text-success me-2"></i>
Single solver call
</li>
<li class="list-group-item">
<i class="bi bi-check-circle text-success me-2"></i>
Constraints embedded in residuals
</li>
<li class="list-group-item">
<i class="bi bi-check-circle text-success me-2"></i>
Control variables as unknowns
</li>
<li class="list-group-item">
<i class="bi bi-check-circle text-success me-2"></i>
Fast convergence
</li>
</ul>
<div class="formula mt-4">
r<sub>total</sub> = [r<sub>cycle</sub>, r<sub>constraints</sub>]<sup>T</sup> = 0
</div>
</div>
</div>
</div>
</div>
</section>
<section id="dof" class="mb-5">
<div class="card">
<div class="card-body p-4">
<h2 class="card-title mb-4">
<i class="bi bi-calculator text-primary me-2"></i>
Degrees of Freedom (DoF) Validation
</h2>
<p>
For a well-posed system, the number of equations must equal the number of unknowns:
</p>
<div class="formula mb-4">
n<sub>equations</sub> = n<sub>edge_eqs</sub> + n<sub>constraints</sub><br>
n<sub>unknowns</sub> = n<sub>edge_unknowns</sub> + n<sub>controls</sub><br><br>
<strong>Balanced: n<sub>equations</sub> = n<sub>unknowns</sub></strong>
</div>
<div class="row">
<div class="col-md-4">
<div class="card bg-success text-white">
<div class="card-body text-center">
<h5><i class="bi bi-check-circle"></i> Balanced</h5>
<p class="mb-0">Equations = Unknowns</p>
<span class="status-badge dof-balanced bg-white text-success">SOLVABLE</span>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card bg-danger text-white">
<div class="card-body text-center">
<h5><i class="bi bi-x-circle"></i> Over-Constrained</h5>
<p class="mb-0">Equations > Unknowns</p>
<span class="status-badge dof-over bg-white text-danger">ERROR</span>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card bg-warning text-dark">
<div class="card-body text-center">
<h5><i class="bi bi-exclamation-triangle"></i> Under-Constrained</h5>
<p class="mb-0">Equations < Unknowns</p>
<span class="status-badge dof-under bg-white text-warning">WARNING</span>
</div>
</div>
</div>
</div>
<div class="mt-4">
<h5>Example Calculation</h5>
<table class="table table-bordered">
<thead class="table-light">
<tr>
<th>Component</th>
<th>Count</th>
<th>Contribution</th>
</tr>
</thead>
<tbody>
<tr>
<td>Edges</td>
<td>4</td>
<td>2 × 4 = 8 unknowns (P, h)</td>
</tr>
<tr>
<td>Components</td>
<td>4</td>
<td>8 equations (2 per component)</td>
</tr>
<tr>
<td>Constraints</td>
<td>1</td>
<td>+1 equation</td>
</tr>
<tr>
<td>Control Variables</td>
<td>1</td>
<td>+1 unknown</td>
</tr>
<tr class="table-success">
<td><strong>Total</strong></td>
<td></td>
<td><strong>9 equations = 9 unknowns ✓</strong></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</section>
<section id="workflow" class="mb-5">
<div class="card">
<div class="card-body p-4">
<h2 class="card-title mb-4">
<i class="bi bi-diagram-3 text-info me-2"></i>
Implementation Workflow
</h2>
<div class="row">
<div class="col-md-6">
<div class="workflow-step">
<h5>Step 1: Define Constraint</h5>
<p>Create a constraint specifying the desired output:</p>
<div class="code-block">
<span class="keyword">let</span> constraint = <span class="type">Constraint</span>::<span class="function">new</span>(
<span class="type">ConstraintId</span>::<span class="function">new</span>(<span class="string">"superheat"</span>),
<span class="type">ComponentOutput</span>::<span class="type">Superheat</span> {
component_id: <span class="string">"evaporator"</span>.<span class="function">into</span>(),
},
<span class="number">5.0</span>, <span class="comment">// target: 5K superheat</span>
);
</div>
</div>
<div class="workflow-step">
<h5>Step 2: Define Control Variable</h5>
<p>Create a bounded variable with physical limits:</p>
<div class="code-block">
<span class="keyword">let</span> valve = <span class="type">BoundedVariable</span>::<span class="function">new</span>(
<span class="type">BoundedVariableId</span>::<span class="function">new</span>(<span class="string">"expansion_valve"</span>),
<span class="number">0.5</span>, <span class="comment">// initial: 50% open</span>
<span class="number">0.0</span>, <span class="comment">// min: fully closed</span>
<span class="number">1.0</span>, <span class="comment">// max: fully open</span>
)?;
</div>
</div>
</div>
<div class="col-md-6">
<div class="workflow-step">
<h5>Step 3: Add to System</h5>
<p>Register constraint and control variable:</p>
<div class="code-block">
system.<span class="function">add_constraint</span>(constraint)?;
system.<span class="function">add_bounded_variable</span>(valve)?;
</div>
</div>
<div class="workflow-step">
<h5>Step 4: Link Constraint to Control</h5>
<p>Establish the One-Shot relationship:</p>
<div class="code-block">
system.<span class="function">link_constraint_to_control</span>(
&<span class="type">ConstraintId</span>::<span class="function">new</span>(<span class="string">"superheat"</span>),
&<span class="type">BoundedVariableId</span>::<span class="function">new</span>(<span class="string">"expansion_valve"</span>),
)?;
</div>
</div>
<div class="workflow-step">
<h5>Step 5: Validate DoF</h5>
<p>Ensure the system is well-posed:</p>
<div class="code-block">
system.<span class="function">validate_inverse_control_dof</span>()?;
<span class="comment">// Returns Ok(()) if balanced</span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section id="code" class="mb-5">
<div class="card">
<div class="card-body p-4">
<h2 class="card-title mb-4">
<i class="bi bi-code-slash text-secondary me-2"></i>
Complete Code Example
</h2>
<ul class="nav nav-tabs" id="codeTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="rust-tab" data-bs-toggle="tab" data-bs-target="#rust" type="button">
Rust
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="api-tab" data-bs-toggle="tab" data-bs-target="#api" type="button">
API Reference
</button>
</li>
</ul>
<div class="tab-content mt-3" id="codeTabsContent">
<div class="tab-pane fade show active" id="rust" role="tabpanel">
<div class="code-block" style="max-height: 500px; overflow-y: auto;">
<span class="keyword">use</span> entropyk_solver::{
<span class="type">System</span>, <span class="type">CircuitId</span>,
inverse::{
<span class="type">Constraint</span>, <span class="type">ConstraintId</span>, <span class="type">ComponentOutput</span>,
<span class="type">BoundedVariable</span>, <span class="type">BoundedVariableId</span>,
},
};
<span class="keyword">fn</span> <span class="function">main</span>() -> <span class="type">Result</span><(), <span class="type">Box</span><<span class="keyword">dyn</span> <span class="type">Error</span>>> {
<span class="comment">// 1. Build the system</span>
<span class="keyword">let</span> <span class="keyword">mut</span> system = <span class="type">System</span>::<span class="function">new</span>();
<span class="comment">// Add components</span>
<span class="keyword">let</span> compressor = system.<span class="function">add_component</span>(<span class="function">make_compressor</span>());
<span class="keyword">let</span> condenser = system.<span class="function">add_component</span>(<span class="function">make_condenser</span>());
<span class="keyword">let</span> valve = system.<span class="function">add_component</span>(<span class="function">make_valve</span>());
<span class="keyword">let</span> evaporator = system.<span class="function">add_component</span>(<span class="function">make_evaporator</span>());
<span class="comment">// Register names for constraints</span>
system.<span class="function">register_component_name</span>(<span class="string">"evaporator"</span>, evaporator);
<span class="comment">// Connect components</span>
system.<span class="function">add_edge</span>(compressor, condenser)?;
system.<span class="function">add_edge</span>(condenser, valve)?;
system.<span class="function">add_edge</span>(valve, evaporator)?;
system.<span class="function">add_edge</span>(evaporator, compressor)?;
<span class="comment">// 2. Define constraint: maintain 5K superheat</span>
<span class="keyword">let</span> constraint = <span class="type">Constraint</span>::<span class="function">new</span>(
<span class="type">ConstraintId</span>::<span class="function">new</span>(<span class="string">"superheat_control"</span>),
<span class="type">ComponentOutput</span>::<span class="type">Superheat</span> {
component_id: <span class="string">"evaporator"</span>.<span class="function">to_string</span>(),
},
<span class="number">5.0</span>, <span class="comment">// target: 5 Kelvin</span>
);
system.<span class="function">add_constraint</span>(constraint)?;
<span class="comment">// 3. Define bounded control variable</span>
<span class="keyword">let</span> control = <span class="type">BoundedVariable</span>::<span class="function">new</span>(
<span class="type">BoundedVariableId</span>::<span class="function">new</span>(<span class="string">"valve_position"</span>),
<span class="number">0.5</span>, <span class="comment">// initial position</span>
<span class="number">0.1</span>, <span class="comment">// min: 10% open</span>
<span class="number">1.0</span>, <span class="comment">// max: fully open</span>
)?;
system.<span class="function">add_bounded_variable</span>(control)?;
<span class="comment">// 4. Link constraint to control (One-Shot)</span>
system.<span class="function">link_constraint_to_control</span>(
&<span class="type">ConstraintId</span>::<span class="function">new</span>(<span class="string">"superheat_control"</span>),
&<span class="type">BoundedVariableId</span>::<span class="function">new</span>(<span class="string">"valve_position"</span>),
)?;
<span class="comment">// 5. Finalize and validate DoF</span>
system.<span class="function">finalize</span>()?;
system.<span class="function">validate_inverse_control_dof</span>()?;
<span class="comment">// 6. Solve (One-Shot: constraints solved simultaneously)</span>
<span class="keyword">let</span> solver = <span class="type">NewtonRaphson</span>::<span class="function">new</span>();
<span class="keyword">let</span> result = solver.<span class="function">solve</span>(&system)?;
<span class="comment">// 7. Check result</span>
<span class="keyword">let</span> final_valve = system.<span class="function">get_bounded_variable</span>(
&<span class="type">BoundedVariableId</span>::<span class="function">new</span>(<span class="string">"valve_position"</span>)
).<span class="function">unwrap</span>();
<span class="function">println!</span>(<span class="string">"Valve position: {:.2}%"</span>, final_valve.<span class="function">value</span>() * <span class="number">100.0</span>);
<span class="function">println!</span>(<span class="string">"Converged: {:?}"</span>, result.<span class="function">converged</span>());
<span class="type">Ok</span>(())
}
</div>
</div>
<div class="tab-pane fade" id="api" role="tabpanel">
<h5>System Methods for Inverse Control</h5>
<table class="table table-striped">
<thead>
<tr>
<th>Method</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>add_constraint()</code></td>
<td>Add a constraint to the system</td>
</tr>
<tr>
<td><code>add_bounded_variable()</code></td>
<td>Add a bounded control variable</td>
</tr>
<tr>
<td><code>link_constraint_to_control()</code></td>
<td>Link constraint to control for One-Shot solving</td>
</tr>
<tr>
<td><code>unlink_constraint()</code></td>
<td>Remove constraint-control linkage</td>
</tr>
<tr>
<td><code>validate_inverse_control_dof()</code></td>
<td>Validate degrees of freedom</td>
</tr>
<tr>
<td><code>control_variable_state_index()</code></td>
<td>Get state vector index for control variable</td>
</tr>
<tr>
<td><code>full_state_vector_len()</code></td>
<td>Total state length including controls</td>
</tr>
<tr>
<td><code>compute_constraint_residuals()</code></td>
<td>Compute residuals for all constraints</td>
</tr>
<tr>
<td><code>compute_inverse_control_jacobian()</code></td>
<td>Jacobian entries for ∂constraint/∂control</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>
<section id="results" class="mb-5">
<div class="card">
<div class="card-body p-4">
<h2 class="card-title mb-4">
<i class="bi bi-graph-up text-success me-2"></i>
Simulation Results
</h2>
<div class="row mb-4">
<div class="col-md-3">
<div class="card bg-primary text-white">
<div class="card-body text-center">
<h6>Initial Superheat</h6>
<h2 class="mb-0">2.3 K</h2>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card bg-success text-white">
<div class="card-body text-center">
<h6>Target Superheat</h6>
<h2 class="mb-0">5.0 K</h2>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card bg-info text-white">
<div class="card-body text-center">
<h6>Final Superheat</h6>
<h2 class="mb-0">5.02 K</h2>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card bg-warning text-dark">
<div class="card-body text-center">
<h6>Iterations</h6>
<h2 class="mb-0">7</h2>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<h5>Superheat Convergence</h5>
<div class="chart-container">
<canvas id="superheatChart"></canvas>
</div>
</div>
<div class="col-md-6">
<h5>Valve Position Evolution</h5>
<div class="chart-container">
<canvas id="valveChart"></canvas>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-md-6">
<h5>DoF Analysis</h5>
<table class="table table-sm">
<tr>
<td>Edge Unknowns (P, h)</td>
<td class="text-end">8</td>
</tr>
<tr>
<td>Control Variables</td>
<td class="text-end">+1</td>
</tr>
<tr class="table-info">
<td><strong>Total Unknowns</strong></td>
<td class="text-end"><strong>9</strong></td>
</tr>
<tr>
<td>Component Equations</td>
<td class="text-end">8</td>
</tr>
<tr>
<td>Constraint Equations</td>
<td class="text-end">+1</td>
</tr>
<tr class="table-info">
<td><strong>Total Equations</strong></td>
<td class="text-end"><strong>9</strong></td>
</tr>
<tr class="table-success">
<td><strong>Balance</strong></td>
<td class="text-end"><strong>✓ Balanced</strong></td>
</tr>
</table>
</div>
<div class="col-md-6">
<h5>Control Variable Details</h5>
<table class="table table-sm">
<tr>
<td>Variable ID</td>
<td><code>valve_position</code></td>
</tr>
<tr>
<td>Initial Value</td>
<td>50%</td>
</tr>
<tr>
<td>Final Value</td>
<td class="text-success"><strong>38%</strong></td>
</tr>
<tr>
<td>Bounds</td>
<td>[10%, 100%]</td>
</tr>
<tr>
<td>Saturated</td>
<td class="text-warning">No</td>
</tr>
<tr>
<td>State Index</td>
<td>8 (after edge states)</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</section>
<script>
// Superheat Convergence Chart
const superheatCtx = document.getElementById('superheatChart').getContext('2d');
new Chart(superheatCtx, {
type: 'line',
data: {
labels: ['0', '1', '2', '3', '4', '5', '6', '7'],
datasets: [{
label: 'Superheat (K)',
data: [2.3, 3.1, 3.8, 4.4, 4.7, 4.9, 5.01, 5.02],
borderColor: '#3498db',
backgroundColor: 'rgba(52, 152, 219, 0.1)',
fill: true,
tension: 0.3
}, {
label: 'Target (K)',
data: [5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0],
borderColor: '#27ae60',
borderDash: [5, 5],
fill: false
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { position: 'bottom' }
},
scales: {
y: {
title: { display: true, text: 'Superheat (K)' },
min: 0,
max: 6
},
x: {
title: { display: true, text: 'Iteration' }
}
}
}
});
// Valve Position Chart
const valveCtx = document.getElementById('valveChart').getContext('2d');
new Chart(valveCtx, {
type: 'line',
data: {
labels: ['0', '1', '2', '3', '4', '5', '6', '7'],
datasets: [{
label: 'Valve Position (%)',
data: [50, 45, 42, 40, 39, 38.5, 38.2, 38.0],
borderColor: '#e74c3c',
backgroundColor: 'rgba(231, 76, 60, 0.1)',
fill: true,
tension: 0.3
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { position: 'bottom' }
},
scales: {
y: {
title: { display: true, text: 'Position (%)' },
min: 30,
max: 55
},
x: {
title: { display: true, text: 'Iteration' }
}
}
}
});
</script>
<footer class="text-center py-4 mt-5">
<div class="container">
<p class="text-muted">
<i class="bi bi-cpu"></i> Entropyk - One-Shot Inverse Control
<br>
<small>Story 5.3: Residual Embedding for Inverse Control</small>
</p>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</div>
</body>
</html>