app
Adom Fields
Public Made by Adomby adom
Adom Fields: where the current and the heat go on your board.
← Commit history
adom-fields 0.8.5: solid bodies follow the parts' offset as the stack opens
6 files changed
+18−28
Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "adom-fields"-version = "0.8.4"+version = "0.8.5" edition = "2021" license = "MIT" description = "Adom Fields: where the current and the heat go on your board. Current density, copper heat flow and board temperature from the board file itself, in 3D, for the AI to drive and the human to explore."
docs/release-0.8.5.mdadded+3@@ -0,0 +1,3 @@+# adom-fields 0.8.5++- **The solved bodies stay on the parts when the stack opens.** Pulling the layers apart lifts the parts; the solid bodies (a package, its pad, a finned heatsink) now ride up by exactly the same amount on every frame of the animation, so the solved heatsink stays on the real one in the Heat and Temperature views.
package.json+1−1@@ -1,7 +1,7 @@ { "slug": "adom-fields", "type": "app",- "version": "0.8.4",+ "version": "0.8.5", "title": "Adom Fields", "brief": "Adom Fields: where the current and the heat go on your board.", "summary": "Current density on the copper, heat flow through the pours and the vias, and the temperature over the board, solved from the board file itself and shown on the board in 3D. The AI does the analysis and drives the view; the human orbits, zooms, hovers for the number under the cursor, and reads the nets by what they carry and the issues by what to fix. A step in Adom's AI Flow: the walkthrough goes into the video.",
page.json+8−23@@ -1,7 +1,7 @@ { "slug": "adom-fields", "type": "app",- "version": "0.8.4",+ "version": "0.8.5", "title": "Adom Fields", "brief": "Adom Fields: where the current and the heat go on your board.", "summary": "Current density on the copper, heat flow through the pours and the vias, and the temperature over the board, solved from the board file itself and shown on the board in 3D. The AI does the analysis and drives the view; the human orbits, zooms, hovers for the number under the cursor, and reads the nets by what they carry and the issues by what to fix. A step in Adom's AI Flow: the walkthrough goes into the video.",@@ -17,10 +17,7 @@ "vias", "3d", "analysis",- "eda",- "current flow animation",- "voltage",- "river"+ "eda" ], "status": "live", "discovery_pitch": "Solve where the current and the heat go on a KiCad board and show it on the board in 3D: current density per net, heat flow per layer with the vias, temperature over the board, the nets by what they carry, the issues with the fix. One command to solve, one to serve, one to drive it on camera.",@@ -40,10 +37,11 @@ "fields", "flow of current", "river view",- "voltage drop in 3d",- "ground bounce",+ "energy flow on a board",+ "poynting vector",+ "speed of light on a pcb",+ "electron drift speed", "exploded layer stack",- "current through vias", "explain the view out loud", "narrate the fields", "energy cycle",@@ -85,20 +83,7 @@ "anti-resonance", "input filter stability", "middlebrook",- "ngspice pdn",- "signals view",- "copper capacitance",- "switch node capacitance",- "plane capacitance",- "differential pair skew",- "six layer board",- "receiver frequency plan",- "lo leakage",- "tone in band",- "rf crosstalk",- "return path over supply plane",- "antenna ground loop",- "stage feed bypass"+ "ngspice pdn" ], "sample_prompts": [ {@@ -139,4 +124,4 @@ "name": "John Lauer", "email": "[email protected]" }-}+}
src/ui/flow.js+1−1@@ -975,6 +975,6 @@ void main(void) { console.log(`flow: ${nets.filter(n => n.loaded).length} loaded nets, ${viaGaps.size} barrels carrying current, ${terrains.length} terrain layer(s) at stride ${stride}, ${P} particles (${tier}); river 1 V = ${kR.toFixed(3)} mm, slopes x${exaggeration.toFixed(0)}`); console.log(`light: er ${ER}, ${arrivals.length} part arrivals, the slowest ${tMax.toFixed(0)} ps; ` + arrivals.slice(0, 6).map(a => `${a.ref}/${a.net} ${a.ps.toFixed(0)} ps`).join(', ')); console.log(`energy: ${gaps.length} gap(s) between copper layers ${real.map(k => LAYERS[k]).join(', ')}; S up to ${sHi.toFixed(2)} W/mm² (99.5th pct); electrons drift ${DRIFT.toFixed(4)} mm/s per A/mm²`);- const api = { data: { lay, real, W, H, d, meta, cuMm, nets, zOf, cellOf, bx, by, ER }, apply, readout, describe, narration, knob, get particles() { return P; }, set particles(n) { P = Math.max(500, Math.min(COUNTS.high, n | 0)); }, stats: () => ({ energyParticles: EP, gaps: gaps.length, sHi, particles: P, tier, jLo, jHi, kR, kD, exaggeration, terrains: terrains.length, barrels: viaGaps.size, explode: knob.explode, river: knob.river }) };+ const api = { data: { lay, real, W, H, d, meta, cuMm, nets, zOf, cellOf, bx, by, ER }, /** how far the top-side parts ride up as the stack opens: the solid bodies (solids.js) follow the same rule */ topOffset: () => knob.explode * gap * 1.5, apply, readout, describe, narration, knob, get particles() { return P; }, set particles(n) { P = Math.max(500, Math.min(COUNTS.high, n | 0)); }, stats: () => ({ energyParticles: EP, gaps: gaps.length, sHi, particles: P, tier, jLo, jHi, kR, kD, exaggeration, terrains: terrains.length, barrels: viaGaps.size, explode: knob.explode, river: knob.river }) }; return api; }
src/ui/solids.js+4−2@@ -75,6 +75,9 @@ export async function attach(ctx) { const legend = document.getElementById('legend'); let info = document.getElementById('solidsInfo'); if (!info && legend) { info = document.createElement('div'); info.id = 'solidsInfo'; info.style.cssText = 'margin-top:6px;font-size:11px;line-height:1.35;opacity:.9;max-width:340px'; legend.appendChild(info); }+ // pulled apart with the stack, every frame of the animation: the bodies ride up exactly as the parts model does, so the+ // solved heatsink stays on the real one+ scene.onBeforeRenderObservable.add(() => { const z = window.fieldsFlow && window.fieldsFlow.topOffset ? window.fieldsFlow.topOffset() : 0; for (const b of bodies) b.mesh.position.z = z; }); function apply(view) { const q = view.quantity, show = q === 'heat' || q === 'temperature'; const fk = S.levels ? (view.air === 'still' ? 'fan0' : view.air === 'moving' ? 'fan100' : view.air) : null;@@ -93,8 +96,7 @@ export async function attach(ctx) { for (let v = 0; v < 4; v++) { const o = (f * 4 + v) * 4; col[o] = c[0] * s; col[o + 1] = c[1] * s; col[o + 2] = c[2] * s; col[o + 3] = 1; } } b.mesh.setVerticesData(BAB.VertexBuffer.ColorKind, col, true);- // pulled apart with the stack: the bodies ride on the top copper- const L = state.layerMeshes['F.Cu']; b.mesh.position.z = L ? L.position.z - Z['F.Cu'] : 0;+ } if (info) { info.hidden = !show;