chadwick-warner-tools/thermal-expansion-calculator.html

444 lines
14 KiB
HTML
Raw Normal View History

2026-07-18 19:29:29 +02:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Thermal Expansion Calculator | Chadwick Warner</title>
<style>
:root {
--bg: #0a0a0a;
--surface: #141414;
--primary: #e8b446;
--text: #e8e8e8;
--muted: #888888;
--border: #2a2a2a;
--success: #4ade80;
--danger: #f87171;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'SF Mono', 'Menlo', monospace;
background: var(--bg);
color: var(--text);
line-height: 1.6;
min-height: 100vh;
padding: 2rem 1rem;
}
.container {
max-width: 900px;
margin: 0 auto;
display: grid;
gap: 2rem;
}
header {
border-bottom: 1px solid var(--border);
padding-bottom: 1.5rem;
margin-bottom: 1rem;
}
h1 {
font-size: clamp(1.5rem, 4vw, 2.5rem);
letter-spacing: -0.02em;
margin-bottom: 0.5rem;
}
h1 .accent { color: var(--primary); }
.subtitle {
color: var(--muted);
font-size: 0.95rem;
max-width: 60ch;
}
.card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 8px;
padding: 1.5rem;
}
.card h2 {
font-size: 1.1rem;
color: var(--primary);
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.control-group {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin-bottom: 1.5rem;
}
label {
display: block;
font-size: 0.85rem;
color: var(--muted);
margin-bottom: 0.5rem;
}
input[type="range"] {
width: 100%;
height: 4px;
background: var(--border);
outline: none;
-webkit-appearance: none;
appearance: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 18px;
height: 18px;
background: var(--primary);
border-radius: 50%;
cursor: pointer;
}
select {
width: 100%;
padding: 0.75rem;
background: var(--bg);
border: 1px solid var(--border);
color: var(--text);
font-family: inherit;
font-size: 0.9rem;
border-radius: 4px;
}
.value-display {
font-size: 1.25rem;
color: var(--primary);
font-weight: 600;
margin-top: 0.5rem;
}
.result-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
margin-top: 1.5rem;
}
.result-box {
background: var(--bg);
border: 1px solid var(--border);
border-radius: 6px;
padding: 1rem;
text-align: center;
}
.result-label {
font-size: 0.75rem;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 0.5rem;
}
.result-value {
font-size: 1.5rem;
font-weight: 700;
}
.result-unit {
font-size: 0.9rem;
color: var(--muted);
}
.alert {
padding: 1rem;
border-radius: 6px;
margin-top: 1rem;
font-size: 0.9rem;
display: none;
}
.alert.active { display: block; }
.alert.danger {
background: rgba(248, 113, 113, 0.1);
border: 1px solid var(--danger);
color: var(--danger);
}
.alert.success {
background: rgba(74, 222, 128, 0.1);
border: 1px solid var(--success);
color: var(--success);
}
.image-frame {
position: relative;
margin: 2rem 0;
border-radius: 8px;
overflow: hidden;
border: 1px solid var(--border);
}
.image-frame img {
width: 100%;
height: auto;
display: block;
}
.caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: linear-gradient(transparent, rgba(0,0,0,0.9));
color: var(--text);
padding: 1rem;
font-size: 0.8rem;
}
.formula {
background: var(--bg);
border-left: 3px solid var(--primary);
padding: 1.5rem;
margin: 2rem 0;
font-family: 'SF Mono', monospace;
font-size: 1.1rem;
line-height: 1.8;
}
.citation-links {
margin-top: 2rem;
padding-top: 1rem;
border-top: 1px dashed var(--border);
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.citation-links a {
color: var(--primary);
font-size: 0.8rem;
text-decoration: none;
border: 1px solid var(--border);
padding: 0.5rem 1rem;
border-radius: 4px;
transition: all 0.2s;
}
.citation-links a:hover {
background: var(--primary);
color: var(--bg);
border-color: var(--primary);
}
.nav-links {
display: flex;
gap: 1.5rem;
margin-top: 1rem;
font-size: 0.85rem;
}
.nav-links a {
color: var(--muted);
text-decoration: none;
}
.nav-links a:hover {
color: var(--primary);
}
@media (max-width: 600px) {
.control-group { grid-template-columns: 1fr; }
.result-grid { grid-template-columns: 1fr; }
}
</style>
<script defer src="https://analytics.4ort.xyz/script.js" data-website-id="d3ed927c-888a-4a6c-ae5f-0b1c613ddf5b"></script>
</head>
<body>
<div class="container">
<header>
<h1><span class="accent">ΔL</span> = α × L₀ × ΔT</h1>
<p class="subtitle">
Thermal expansion calculator for aerospace-grade alloys.
In the vacuum, a 0.002-inch misalignment isn't art—it's a breach.
</p>
<nav class="nav-links">
<a href="/">← Home</a>
<a href="/scrap-log.html">Scrap Log</a>
<a href="/tolerances.html">Tolerance Stack-Up</a>
</nav>
</header>
<section class="card">
<h2>⚙️ Material Selection</h2>
<div class="control-group">
<div>
<label for="material">Alloy</label>
<select id="material">
<option value="6061">Aluminium 6061-T6</option>
<option value="titanium">Titanium Ti-6Al-4V</option>
<option value="316ss">Stainless Steel 316L</option>
<option value="inconel">Inconel 718</option>
<option value="carbon">Carbon Fiber (0°)</option>
</select>
</div>
<div>
<label for="alpha">α (×10⁻⁶/K)</label>
<div class="value-display" id="alpha-display">23.6</div>
</div>
</div>
</section>
<section class="card">
<h2>📐 Initial Dimensions</h2>
<div class="control-group">
<div>
<label for="length">Initial Length (mm)</label>
<input type="range" id="length" min="10" max="5000" value="500">
<div class="value-display"><span id="length-value">500</span> mm</div>
</div>
<div>
<label for="delta-t">Temperature Delta (K)</label>
<input type="range" id="delta-t" min="-273" max="1500" value="300">
<div class="value-display"><span id="dt-value">+300</span> K</div>
</div>
</div>
</section>
<section class="card">
<h2>🎯 Results</h2>
<div class="result-grid">
<div class="result-box">
<div class="result-label">Expansion</div>
<div class="result-value" id="dl-mm">3.54</div>
<div class="result-unit">mm</div>
</div>
<div class="result-box">
<div class="result-label">Microns</div>
<div class="result-value" id="dl-microns">3540</div>
<div class="result-unit">μm</div>
</div>
<div class="result-box">
<div class="result-label">Tolerance Check</div>
<div class="result-value" id="tol-status" style="color: var(--success)">PASS</div>
<div class="result-unit">@ ±0.05mm</div>
</div>
</div>
<div id="alert-danger" class="alert danger">
⚠️ EXPANSION EXCEEDS TOLERANCE BAND<br>
<small>Current: <span id="overage-val">0</span>μm | Limit: 50μm</small>
</div>
<div id="alert-success" class="alert success">
✓ Within Spec<br>
<small>Marginal clearance: <span id="clearance-val">0</span>μm</small>
</div>
</section>
<div class="image-frame">
<img src="https://images-assets.nasa.gov/image/KSC-98pc620/KSC-98pc620~medium.jpg" alt="NASA Kennedy Space Center machined component">
<div class="caption">
KSC-98pc620 • Kennedy Space Center • Public Domain<br>
Every micron counts when the atmosphere drops away.
</div>
</div>
<section class="formula">
<strong>The Equation:</strong><br>
ΔL = α × L₀ × ΔT<br><br>
Where:<br>
• ΔL = Change in length (mm)<br>
α = Coefficient of thermal expansion (×10⁻⁶/K)<br>
• L₀ = Initial length (mm)<br>
• ΔT = Temperature difference (K)<br><br>
<small>Citation: Wikidata Q45760 — coefficient of thermal expansion</small>
</section>
<section class="card">
<h2>🔬 Constants Database</h2>
<table style="width:100%; border-collapse: collapse; font-size: 0.85rem;">
<thead>
<tr style="border-bottom: 1px solid var(--border);">
<th style="text-align:left; padding: 0.5rem;">Alloy</th>
<th style="text-align:right; padding: 0.5rem;">α (×10⁻⁶/K)</th>
<th style="text-align:left; padding: .5rem;">Source</th>
</tr>
</thead>
<tbody>
<tr>
<td style="padding: 0.5rem;">Aluminium 6061-T6</td>
<td style="text-align:right; padding: 0.5rem;">23.6</td>
<td style="padding: 0.5rem;"><a href="https://4ort.xyz/entity/aluminium-alloy" target="_blank" style="color:var(--primary);">Q447725</a></td>
</tr>
<tr>
<td style="padding: 0.5rem;">Titanium Ti-6Al-4V</td>
<td style="text-align:right; padding: 0.5rem;">8.6</td>
<td style="padding: 0.5rem;"><a href="https://4ort.xyz/entity/titanium-based-alloy" target="_blank" style="color:var(--primary);">Q3300719</a></td>
</tr>
<tr>
<td style="padding: 0.5rem;">Stainless Steel 316L</td>
<td style="text-align:right; padding: 0.5rem;">16.0</td>
<td style="padding: 0.5rem;"><a href="https://4ort.xyz/entity/stainless-steel" target="_blank" style="color:var(--primary);">Q447725</a></td>
</tr>
<tr>
<td style="padding: 0.5rem;">Inconel 718</td>
<td style="text-align:right; padding: 0.5rem;">13.0</td>
<td style="padding: 0.5rem;">ASM Handbook Vol 1</td>
</tr>
<tr>
<td style="padding: 0.5rem;">Carbon Fiber (0°)</td>
<td style="text-align:right; padding: 0.5rem;">-1.5</td>
<td style="padding: 0.5rem;">Hexcel Design Data</td>
</tr>
</tbody>
</table>
<div class="citation-links">
<a href="https://4ort.xyz/entity/coefficient-of-thermal-expansion" target="_blank">Q45760: CTE Definition</a>
<a href="https://4ort.xyz/entity/aluminium-alloy" target="_blank">Q447725: Aluminium Alloys</a>
<a href="https://4ort.xyz/entity/titanium-based-alloy" target="_blank">Q3300719: Titanium Alloys</a>
<a href="https://4ort.xyz/entity/stainless-steel" target="_blank">Stainless Steel Entity</a>
</div>
</section>
<footer style="margin-top: 3rem; padding-top: 1.5rem; border-top: 1px solid var(--border); color: var(--muted); font-size: 0.8rem; display: flex; justify-content: space-between; flex-wrap: wrap; gap: 1rem;">
<div>Built by Chadwick Warner • Los Angeles Shop Floor</div>
<div><a href="/thermal-expansion-data.json" style="color: var(--primary);">Download Constants (.json)</a></div>
</footer>
</div>
<script>
const CONSTANTS = {
"6061": { alpha: 23.6, name: "Aluminium 6061-T6" },
"titanium": { alpha: 8.6, name: "Titanium Ti-6Al-4V" },
"316ss": { alpha: 16.0, name: "Stainless Steel 316L" },
"inconel": { alpha: 13.0, name: "Inconel 718" },
"carbon": { alpha: -1.5, name: "Carbon Fiber (0°)" }
};
const TOLERANCE_BAND_MICRONS = 50; // ±0.05mm = 50μm
const materialSelect = document.getElementById('material');
const alphaDisplay = document.getElementById('alpha-display');
const lengthSlider = document.getElementById('length');
const lengthValue = document.getElementById('length-value');
const dtSlider = document.getElementById('delta-t');
const dtValue = document.getElementById('dt-value');
const dlMm = document.getElementById('dl-mm');
const dlMicrons = document.getElementById('dl-microns');
const tolStatus = document.getElementById('tol-status');
const alertDanger = document.getElementById('alert-danger');
const alertSuccess = document.getElementById('alert-success');
const overageVal = document.getElementById('overage-val');
const clearanceVal = document.getElementById('clearance-val');
function calculate() {
const mat = materialSelect.value;
const L0 = parseFloat(lengthSlider.value);
const dT = parseFloat(dtSlider.value);
const alpha = CONSTANTS[mat].alpha;
alphaDisplay.textContent = alpha.toFixed(1);
lengthValue.textContent = L0;
dtValue.textContent = (dT >= 0 ? '+' : '') + dT;
const dL_microns = alpha * L0 * dT;
const dL_mm = dL_microns / 1000;
dlMm.textContent = dL_mm.toFixed(3);
dlMicrons.textContent = Math.abs(Math.round(dL_microns));
const absExpansion = Math.abs(dL_microns);
if (absExpansion > TOLERANCE_BAND_MICRONS) {
tolStatus.textContent = "FAIL";
tolStatus.style.color = "var(--danger)";
alertDanger.classList.add('active');
alertSuccess.classList.remove('active');
overageVal.textContent = Math.round(absExpansion - TOLERANCE_BAND_MICRONS);
} else {
tolStatus.textContent = "PASS";
tolStatus.style.color = "var(--success)";
alertSuccess.classList.add('active');
alertDanger.classList.remove('active');
clearanceVal.textContent = Math.round(TOLERANCE_BAND_MICRONS - absExpansion);
}
}
materialSelect.addEventListener('change', calculate);
lengthSlider.addEventListener('input', calculate);
dtSlider.addEventListener('input', calculate);
calculate();
</script>
</body>
</html>