Meta Description" name="description" />
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>210 MW Thermal Power Plant Simulator</title>
<style>
:root {
--bg-color: #0f172a;
--panel-bg: #1e293b;
--accent-blue: #38bdf8;
--accent-orange: #f97316;
--accent-green: #22c55e;
--accent-red: #ef4444;
--text-color: #f8fafc;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
margin: 0;
padding: 20px;
}
header {
text-align: center;
margin-bottom: 20px;
border-bottom: 2px solid #334155;
padding-bottom: 10px;
}
h1 { margin: 0; color: var(--accent-blue); font-size: 1.8rem; }
p.subtitle { color: #94a3b8; margin: 5px 0 0 0; font-size: 0.95rem; }
.dashboard {
display: grid;
grid-template-columns: 320px 1fr 300px;
gap: 15px;
max-width: 1600px;
margin: 0 auto;
}
.panel {
background: var(--panel-bg);
border-radius: 10px;
padding: 15px;
box-shadow: 0 4px 15px rgba(0,0,0,0.3);
border: 1px solid #334155;
}
.panel h2 {
font-size: 1.1rem;
color: var(--accent-blue);
margin-top: 0;
border-bottom: 1px solid #334155;
padding-bottom: 8px;
}
/* Controls */
.control-group {
margin-bottom: 18px;
}
label {
display: flex;
justify-content: space-between;
font-size: 0.85rem;
margin-bottom: 5px;
font-weight: 600;
}
input[type="range"] {
width: 100%;
accent-color: var(--accent-blue);
}
.btn {
width: 100%;
padding: 10px;
border: none;
border-radius: 6px;
font-weight: bold;
cursor: pointer;
transition: all 0.2s;
margin-top: 8px;
}
.btn-trip { background: var(--accent-red); color: white; }
.btn-trip:hover { background: #dc2626; }
.btn-reset { background: var(--accent-blue); color: #0f172a; }
.btn-reset:hover { background: #0284c7; }
/* Plant Schematic Canvas */
#schematicCanvas {
width: 100%;
height: 520px;
background: #090d16;
border-radius: 8px;
border: 1px solid #334155;
}
/* Readouts */
.metric-card {
background: #0f172a;
padding: 10px;
border-radius: 6px;
margin-bottom: 10px;
border-left: 4px solid var(--accent-blue);
}
.metric-title { font-size: 0.75rem; color: #94a3b8; text-transform: uppercase; }
.metric-value { font-size: 1.4rem; font-weight: bold; color: var(--text-color); margin-top: 2px; }
.metric-unit { font-size: 0.8rem; color: #64748b; font-weight: normal; }
.status-badge {
display: inline-block;
padding: 4px 8px;
border-radius: 4px;
font-size: 0.8rem;
font-weight: bold;
margin-top: 5px;
}
.status-ok { background: #15803d; color: #dcfce7; }
.status-warn { background: #b45309; color: #fef3c7; }
.status-alarm { background: #b91c1c; color: #fee2e2; }
.log-box {
background: #090d16;
border: 1px solid #334155;
border-radius: 6px;
height: 120px;
overflow-y: auto;
padding: 8px;
font-family: monospace;
font-size: 0.75rem;
color: #38bdf8;
margin-top: 10px;
}
</style>
</head>
<body>
<header>
<h1>210 MW Thermal Power Plant Real-Time Simulator</h1>
<p class="subtitle">Interactive Thermodynamic & Operational Model (LMZ Regenerative Rankine Cycle)</p>
</header>
<div class="dashboard">
<!-- Control Panel -->
<div class="panel">
<h2>Operator Controls</h2>
<div class="control-group">
<label>Coal Feeder Rate <span id="val-coal">75 %</span></label>
<input type="range" id="input-coal" min="0" max="100" value="75">
</div>
<div class="control-group">
<label>Boiler Feed Pump Speed <span id="val-bfp">80 %</span></label>
<input type="range" id="input-bfp" min="0" max="100" value="80">
</div>
<div class="control-group">
<label>Condenser Cooling Water Flow <span id="val-cw">85 %</span></label>
<input type="range" id="input-cw" min="10" max="100" value="85">
</div>
<div class="control-group">
<label>Turbine Control Valve (Governing) <span id="val-tcv">70 %</span></label>
<input type="range" id="input-tcv" min="0" max="100" value="70">
</div>
<button class="btn btn-trip" id="btn-mft">EMERGENCY TRIP (MFT)</button>
<button class="btn btn-reset" id="btn-reset">RESET PLANT</button>
<h2 style="margin-top: 20px;">Event Log</h2>
<div class="log-box" id="logBox">
[00:00:00] Plant initialized in Steady State...<br>
</div>
</div>
<!-- Live Graphic Schematic -->
<div class="panel">
<h2>Process Flow Visualizer</h2>
<canvas id="schematicCanvas" width="800" height="520"></canvas>
</div>
<!-- Live Telemetry -->
<div class="panel">
<h2>Plant Telemetry</h2>
<div class="metric-card" style="border-color: #22c55e;">
<div class="metric-title">Active Power Output</div>
<div class="metric-value"><span id="m-power">157.5</span> <span class="metric-unit">MW</span></div>
</div>
<div class="metric-card" style="border-color: #ef4444;">
<div class="metric-title">Main Steam Pressure</div>
<div class="metric-value"><span id="m-press">137.0</span> <span class="metric-unit">kg/cm²</span></div>
</div>
<div class="metric-card" style="border-color: #f97316;">
<div class="metric-title">Main Steam Temp</div>
<div class="metric-value"><span id="m-temp">537.5</span> <span class="metric-unit">°C</span></div>
</div>
<div class="metric-card" style="border-color: #38bdf8;">
<div class="metric-title">Deaerator Pressure / NPSHa</div>
<div class="metric-value"><span id="m-deaer">6.2</span> <span class="metric-unit">kg/cm²</span> | <span id="m-npsh">18.2</span> <span class="metric-unit">m</span></div>
</div>
<div class="metric-card" style="border-color: #a855f7;">
<div class="metric-title">Condenser Vacuum</div>
<div class="metric-value"><span id="m-vac">0.91</span> <span class="metric-unit">kg/cm² vac</span></div>
</div>
<div class="metric-card" style="border-color: #eab308;">
<div class="metric-title">Overall Plant Efficiency</div>
<div class="metric-value"><span id="m-eff">36.8</span> <span class="metric-unit">%</span></div>
</div>
<div style="text-align: center; margin-top: 15px;">
<span id="plantStatus" class="status-badge status-ok">NORMAL OPERATION</span>
</div>
</div>
</div>
<script>
// System States & Physics
let state = {
coal: 75,
bfp: 80,
cw: 85,
tcv: 70,
tripped: false,
// Calculated physics variables
steamTemp: 537.5,
steamPress: 137.0,
powerMW: 157.5,
deaerPress: 6.2,
npshAvail: 18.2,
vac: 0.91,
efficiency: 36.8,
flowParticleOffset: 0
};
// DOM Elements
const canvas = document.getElementById('schematicCanvas');
const ctx = canvas.getContext('2d');
const logBox = document.getElementById('logBox');
function addLog(msg) {
const time = new Date().toLocaleTimeString();
logBox.innerHTML = `[${time}] ${msg}<br>` + logBox.innerHTML;
}
// Input Controllers
document.getElementById('input-coal').addEventListener('input', (e) => {
state.coal = parseFloat(e.target.value);
document.getElementById('val-coal').innerText = state.coal + ' %';
});
document.getElementById('input-bfp').addEventListener('input', (e) => {
state.bfp = parseFloat(e.target.value);
document.getElementById('val-bfp').innerText = state.bfp + ' %';
});
document.getElementById('input-cw').addEventListener('input', (e) => {
state.cw = parseFloat(e.target.value);
document.getElementById('val-cw').innerText = state.cw + ' %';
});
document.getElementById('input-tcv').addEventListener('input', (e) => {
state.tcv = parseFloat(e.target.value);
document.getElementById('val-tcv').innerText = state.tcv + ' %';
});
document.getElementById('btn-mft').addEventListener('click', () => {
state.tripped = true;
state.coal = 0;
state.tcv = 0;
document.getElementById('input-coal').value = 0;
document.getElementById('val-coal').innerText = '0 %';
document.getElementById('input-tcv').value = 0;
document.getElementById('val-tcv').innerText = '0 %';
addLog("CRITICAL: MASTER FUEL TRIP (MFT) ACTUATED!");
});
document.getElementById('btn-reset').addEventListener('click', () => {
state.tripped = false;
state.coal = 75;
state.bfp = 80;
state.cw = 85;
state.tcv = 70;
document.getElementById('input-coal').value = 75;
document.getElementById('val-coal').innerText = '75 %';
document.getElementById('input-bfp').value = 80;
document.getElementById('val-bfp').innerText = '80 %';
document.getElementById('input-cw').value = 85;
document.getElementById('val-cw').innerText = '85 %';
document.getElementById('input-tcv').value = 70;
document.getElementById('val-tcv').innerText = '70 %';
addLog("SYSTEM: Plant state reset to defaults.");
});
// Thermodynamic Engine Loop
function updatePhysics() {
if (state.tripped) {
state.steamTemp = Math.max(30, state.steamTemp - 1.5);
state.steamPress = Math.max(0, state.steamPress - 1.0);
state.powerMW = Math.max(0, state.powerMW - 5.0);
state.deaerPress = Math.max(1.0, state.deaerPress - 0.05);
} else {
// Heat Balance
let targetTemp = 300 + (state.coal * 3.2);
let targetPress = (state.bfp * 1.5) + (state.coal * 0.4) - (state.tcv * 0.3);
state.steamTemp += (targetTemp - state.steamTemp) * 0.05;
state.steamPress += (targetPress - state.steamPress) * 0.05;
// Power Generation formula
let steamFlow = (state.steamPress / 150) * (state.tcv / 100);
let targetMW = 210 * steamFlow * (state.steamTemp / 540);
state.powerMW += (targetMW - state.powerMW) * 0.1;
// Deaerator Pressure & NPSH
state.deaerPress = 1.0 + (steamFlow * 5.5);
state.npshAvail = 18.5 - (steamFlow * 3.0) + (state.bfp * 0.02);
// Condenser Vacuum vs CW flow
state.vac = 0.70 + (state.cw / 100) * 0.23;
// Plant Thermal Efficiency
state.efficiency = state.powerMW > 10 ? (31 + (state.powerMW / 210) * 7.5) : 0;
}
// Status Indicators
const statusElem = document.getElementById('plantStatus');
if (state.tripped) {
statusElem.innerText = "TRIPPED (MFT)";
statusElem.className = "status-badge status-alarm";
} else if (state.steamTemp > 545 || state.npshAvail < 10) {
statusElem.innerText = "WARNING / ALARM";
statusElem.className = "status-badge status-warn";
} else {
statusElem.innerText = "NORMAL OPERATION";
statusElem.className = "status-badge status-ok";
}
// Update Readouts
document.getElementById('m-power').innerText = state.powerMW.toFixed(1);
document.getElementById('m-press').innerText = state.steamPress.toFixed(1);
document.getElementById('m-temp').innerText = state.steamTemp.toFixed(1);
document.getElementById('m-deaer').innerText = state.deaerPress.toFixed(1);
document.getElementById('m-npsh').innerText = state.npshAvail.toFixed(1);
document.getElementById('m-vac').innerText = state.vac.toFixed(2);
document.getElementById('m-eff').innerText = state.efficiency.toFixed(1);
}
// Animation & Canvas Drawing
function drawSchematic() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
state.flowParticleOffset = (state.flowParticleOffset + 2) % 20;
// Draw Boiler / Furnace
ctx.fillStyle = state.tripped ? '#334155' : '#b91c1c';
ctx.fillRect(50, 150, 120, 220);
ctx.fillStyle = '#ffffff';
ctx.font = 'bold 14px sans-serif';
ctx.fillText("BOILER", 80, 250);
ctx.font = '11px sans-serif';
ctx.fillText(`Coal: ${state.coal.toFixed(0)}%`, 85, 270);
// Draw High Pressure Turbine
ctx.fillStyle = '#475569';
ctx.beginPath();
ctx.moveTo(280, 160); ctx.lineTo(350, 180); ctx.lineTo(350, 240); ctx.lineTo(280, 260);
ctx.closePath();
ctx.fill();
ctx.fillStyle = '#fff';
ctx.fillText("TURBINE", 290, 215);
// Draw Generator
ctx.fillStyle = '#0284c7';
ctx.fillRect(410, 180, 80, 60);
ctx.fillStyle = '#fff';
ctx.fillText("GEN", 435, 215);
// Draw Condenser
ctx.fillStyle = '#1e3a8a';
ctx.fillRect(280, 350, 120, 80);
ctx.fillStyle = '#fff';
ctx.fillText("CONDENSER", 300, 395);
// Draw Deaerator
ctx.fillStyle = '#0284c7';
ctx.fillRect(120, 420, 100, 40);
ctx.fillStyle = '#fff';
ctx.fillText("DEAERATOR", 130, 445);
// Connecting Steam Pipe (Boiler -> Turbine)
ctx.strokeStyle = state.tripped ? '#64748b' : '#ef4444';
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(170, 200);
ctx.lineTo(280, 200);
ctx.stroke();
// Connecting Water Pipe (Deaerator -> BFP -> Boiler)
ctx.strokeStyle = '#38bdf8';
ctx.lineWidth = 4;
ctx.beginPath();
ctx.moveTo(120, 440);
ctx.lineTo(80, 440);
ctx.lineTo(80, 370);
ctx.stroke();
// Flow Particles Animation
if (!state.tripped && state.powerMW > 5) {
ctx.fillStyle = '#fbbf24';
for (let x = 180 + state.flowParticleOffset; x < 270; x += 20) {
ctx.beginPath();
ctx.arc(x, 200, 3, 0, Math.PI * 2);
ctx.fill();
}
}
}
// Main Loop
function loop() {
updatePhysics();
drawSchematic();
requestAnimationFrame(loop);
}
loop();
</script>
</body>
</html>
1
1
16KB
16KB
296.0ms
804.0ms
296.0ms