Adom Fields
Public Made by Adomby adom
Adom Fields: where the current and the heat go on your board.
main
d982a7e
name: adom-fields-views description: >- Adom Fields app and its 3D views: serve the solved board, drive the view (current, heat, temperature, flow, river, energy, light, cycle, charge, magnetic, ground, noise, pdn), parts and silkscreen, narration, the tour for a video. Use when asked to show the board in 3D, open the fields app, drive the view, make a walkthrough video, "show me the current", "explode the stack", "river view", "magnetic view", "energy view", "adom-fields tour".
Parent skill: adom-fields
Adom Fields: the app and its views
Read this when you show the board to a person or make a video. None of it changes a finding: the views draw what analyze solved.
Serve and show
adom-fields serve --fields fields --port 8874 &
Open https://<slug>.adom.cloud/proxy/8874/ in pup, the browser, or a Hydrogen webview (never localhost from outside the container). The app: a 44 px header, the board in 3D on the canonical Adom 3D viewer (adom/adom-3d-viewer, embedded; ViewCube, studio lighting, zoom to the cursor), the field painted on the picked layer with the other layers faded, the vias as dots, the hot parts labelled with their rise, the legend, the readout under the cursor, the nets and hot parts on the left, the issues and the method on the right. Phone: the two side panels open from the header buttons.
Drive it (the AI's wheel)
adom-fields ui view --quantity current|heat|temperature|signals|flow|river|energy|light|cycle|charge|magnetic|emc|ground|noise|pdn [--explode 0..1] [--probe mm] [--speed 1] [--layer F.Cu|In1.Cu|In2.Cu|B.Cu] [--camera top|iso|bottom|fit|zoom --at x,y] [--air still|moving] [--parts auto|ghost|solid|off]
adom-fields ui select --net +VBAT # one net lit alone (current)
adom-fields ui select --chip Q3 # fly to a hot part, heat view
adom-fields ui issue --index 0 # fly to an issue
adom-fields ui toast "20 A through a 1.5 mm neck"
adom-fields ui state | console
adom-fields tour --pause-ms 20000 # the scripted walkthrough: nets by relevance, each field, the hot parts, the issues
The server: GET /state, GET /console (the UI's log), GET /events (SSE), GET /fields.json, POST /ui/view|select|issue|toast. State lives on the server; the UI, the CLI and the AI see the same view.
The parts over the fields (0.5.0)
analyze now also places every footprint's own 3D model on the board, so the chip stands in its hot zone and the cause of a hot spot is plain. The models come from the board file: each footprint's (model ...) entries, resolved as KiCad does (${KIPRJMOD}, ${KICAD*_3DMODEL_DIR}, then --models-dir <folder> by file name, then a stock KiCad library model fetched by name), converted once to GLB on the Adom STEP service (step2glb) and cached by content in ~/.cache/adom-fields/models/. They land in <out>/parts/ and the parts block of fields.json. A footprint with no model gets a 1 mm box from its courtyard; test points and board-only footprints stay bare copper. A failed conversion never fails the solve: it is logged and the part becomes a box.
On a Fusion board (.brd) the parts are found by name, since Fusion binds its 3D packages by cloud urn: each element's MPN, then its deviceset, then its package, as <name>.step in the --models-dir folders, then in 3d/ or 3dmodels/ beside the board. AI Flow's fusion library writes the checked Z-up models to <run>/3d/<MPN>.step, so a solve of <run>/board-live.brd finds them with no flag. The conversion needs step2glb on the PATH (a declared dependency since 0.6.1; adom-wiki pkg install adom/adom-step2glb); without it every model is logged as a failure and the parts stay bare.
adom-fields analyze --board run/board-2.kicad_pcb --spec spec.json --out fields --models-dir kicad/3d # a snapshot outside the project folder
adom-fields parts --board board.kicad_pcb --fields fields # add or refresh the parts of an existing solve
adom-fields ui view --parts ghost|solid|off|auto # auto: see-through on every field but signals
adom-fields analyze ... --no-parts # skip them (no STEP service needed)
ghost draws the bodies see-through so the field glows through them; solid is the plain assembly; the header's cube button cycles them. The hot-part labels ride on top of their part.
Calmer motion (0.5.0)
Every camera move and the idle sway run at half the 0.4 speed (the sway period is about 40 s), because the flow plays the clip ten times faster. tour --pause-ms defaults to 20000 so a beat settles before the next. For frame-exact video, the page exposes window.fieldsCapture.begin(1/30) and .step() (one frame of page time per call; the live loop stops and the orbit pivot marker hides); ui view --camera zoom --at x,y flies to any board point.
In the AI Flow video
Record the pup window (Adom Bridge desktop_record_window_start on it) while adom-fields tour runs: the clip is the fields step, the toasts are the captions, the AI's own analysis on the board in 3D.
Flow, river and the exploded stack (0.7.0)
analyze also writes flow.bin (the signed current, the voltage and the owning net of every cell) and fields.json flow (each net's rail, sense, drop, terminals as source or sink, and the current down each barrel). Two views use it:
ui view --quantity flow: the current as charge, streaks whose speed and glow follow |J|, dropping through the barrels by their solved share.--explode 1pulls the layers apart (0 puts them back); the camera backs off to keep the stack in frame.ui view --quantity river: each net lifted to its voltage, water over it, loads as waterfalls, sources as fountains, a switching node as a slowed tide. Signs give each net's voltage and drop; the readout gives the volts under the cursor.--speed 0.1..4slows or quickens both. The badge states the scale and the exaggeration; say it when you narrate.
Tell the solve the voltages it cannot read from names, in the spec:
"voltages": {"VIN": 12, "VOUT": 5},
"sources": {"VOUT": ["L1"], "SW": ["U1"]},
"switching": {"SW": {"highV": 12, "lowV": 0, "freqHz": 500000}}
Names give GND/PGND/AGND/VSS 0, 3V3 3.3, +12V 12, 5V_AUX 5; SW, LX and PH are switching nodes between the highest rail and 0 unless the spec says otherwise. Default sense: a supply flows from its connector to its parts, a ground from its parts back to its connector; sources flips a net whose feed is a part (a regulator or inductor output). A net with no rail stays at its drop and says "rail not given". The voltages are DC: the rail plus the solved IR drop. Copper the pinned terminal cannot reach (a floating island) sits still at the rail.
Developing the page: ADOM_FIELDS_UI_DIR=<repo>/src/ui adom-fields serve ... serves index.html, app.js and flow.js from disk, so a reload shows a change without a rebuild.
Energy and light
Energy (ui view --quantity energy --explode 0.6) shows where the energy really travels: pink particles in the board material between the copper layers, along the Poynting vector S = E × H. Between two layers a gap h apart, E is (V_top − V_bottom)/h and the two current sheets give H, so S = ½ (V_top − V_bottom)/h · (K_top − K_bottom) in W/mm²; over a supply and its return that integrates to V × I. Pink rising into a part is that part taking its energy. The blue dots are the electrons in the copper at their real drift speed (J / n e, 0.073 mm/s per A/mm²), moving against the current. DC, inside the board only: part of the energy travels in the air around it.
Light (ui view --quantity light) colours each piece of copper by how fast a change travels in its field, as a % of the speed of light: 1/√εr_eff, all FR4 between planes (about 48 %), Hammerstad's εr_eff for a trace over a plane (wider is slower), mostly air with no plane under it. A switch-on front sweeps out from each fed net's source, and each load is tagged with its arrival time in picoseconds (the fastest path, the sum of length over speed along the way). εr comes from the spec's signals epsilonR, else 4.3. A switching node's DC average (switching.SW.meanV) sets its level in the energy view.
Explained out loud (0.7.1)
Every view can explain itself by voice: the speaker button in the header, adom-fields ui explain [--quantity q] (--stop silences it), or automatically. The left panel's "Explain each view out loud" sets the rule per viewer: First time (the default: each kind of view speaks once, the first time this viewer opens it, so a newcomer hears what they are looking at), Always, or On ask. The page writes each explanation from a template with this board's own numbers (the peak density and its net, the hottest part, the rails, the electrons' speed, the arrival times), so no AI tokens are spent; the server voices it with adom-tts and keeps the mp3 under <fields>/narration/, named by the text's hash, so it is voiced once. A one-line subtitle follows the voice, sentence by sentence, sitting above the legend and readout so neither is covered. Without adom-tts, a toast says so.
The energy cycle (0.7.2)
ui view --quantity cycle: one switching period of a buck converter, slowed about a million times (the meter states the factor). Pink energy packets run from the input capacitors through the switch into the inductor while the switch is on, and from the inductor to the output capacitors and the load all the time; blue particles ride the inductor's magnetic field lines, brightening and swelling as its current and stored energy grow, collapsing on the off-time; red arches over each capacitor brighten as its stored energy rises; orange heat leaves the switch and the inductor. A meter (bottom left, click its title to fold) gives the switch state, the inductor current waveform with a cursor, each store's voltage or current and energy, the heat and the energy delivered per cycle.
The model is the ideal continuous-conduction buck solved exactly: D = Vout/Vin, inductor ripple ΔI = (Vin − Vout)·D·T/L, the capacitor charge integrated over the period. It finds the converter from the solve: the switching node, the inductor on it (L*), the switch (the node's source), the input rail (the switch's highest rail), the output (the inductor's other net), the input and output capacitors (C* between each rail and ground). L and C come from the parts' values on the board (KiCad Value, Fusion element value; fields.json partValues), fsw from the spec's switching.freqHz, the load from the output net's amps, the heat from the hot parts' watts. A board it cannot model says why.
The silkscreen (0.7.2)
analyze exports the board's F.SilkS and B.SilkS with kicad-cli as SVG (silk-front.svg, silk-back.svg, fields.json silk); adom-fields silk --board <pcb> --fields <dir> adds them to an existing solve. The page draws each once into a texture on one plane per side (two quads, no geometry), riding its copper layer and the exploded stack, each side shown only from its own side of the board, hidden in the river. The header's T button or ui view --silk on|off toggles it. --no-silk skips it; a Fusion board has none yet.
Charge: the board as capacitors (0.7.3)
ui view --quantity charge (the Charge button pulls the layers apart): wherever copper at different voltages faces copper across the board material, it is a capacitor. Each face holds σ = ε0·εr·ΔV/h, red on the higher voltage, blue on the lower, brighter for more charge; particles cross the gap from the + face to the − face along the field; a switching node's copper charges and empties with its tide every cycle (the stray capacitance switching noise couples through). A panel compares the copper's own capacitance between net pairs (pF, pC) with the capacitor parts (µF, µC, the energy ½CV²); the readout gives the charge per mm² and the field under the cursor. Parallel plates only: fringing and the air above are not counted.
Magnetic: the field of every current (0.7.4)
ui view --quantity magnetic [--probe 2]: the Biot–Savart field of the solved currents (every copper cell's current summed onto a half-millimetre grid of current elements, plus the current down each via). Glowing blue field lines loop around the current paths, brightest where the field is strongest, their dashes running the way the field points; a sheet at --probe mm above the top copper (the slider beside the view buttons, 0.5 to 15 mm) glows where the field is strong, with a white ring at every tenfold step, the way a near-field probe would see it. The readout gives µT, the share of Earth's field (about 50 µT) and H in A/m. DC: the switching field comes with the EMC loop views.
The ground view (0.7.6)
ui view --quantity ground: the ground copper lifted by its solved millivolts (rings every step), each part's ground pin tagged with its offset, dashed arcs for the possible loops through the ground connectors' cables, floating ground islands in red, and the stitching fence: a ring per ground via (λ/40 reach) with the uncovered stretches of the edge in red.
Also in this area
- Field views frame themselves (0.8.6): entering Energy (stack open 0.8, parts off, low front camera), Flow (0.6, parts ghosted, low side) or Magnetic (parts off, low side) sets the stack, parts and camera so the field shows; values the command sets win,
ui view --keep-camerakeeps everything as it is, and leaving for another view restores what was there. Camera presets: top, iso, front, low, bottom, fit, zoom.
---
name: adom-fields-views
description: >-
Adom Fields app and its 3D views: serve the solved board, drive the view (current, heat, temperature, flow, river, energy, light, cycle, charge, magnetic, ground, noise, pdn), parts and silkscreen, narration, the tour for a video. Use when asked to show the board in 3D, open the fields app, drive the view, make a walkthrough video, "show me the current", "explode the stack", "river view", "magnetic view", "energy view", "adom-fields tour".
---
Parent skill: **adom-fields**
# Adom Fields: the app and its views
Read this when you show the board to a person or make a video. None of it changes a finding: the views draw what `analyze` solved.
## Serve and show
```
adom-fields serve --fields fields --port 8874 &
```
Open `https://<slug>.adom.cloud/proxy/8874/` in pup, the browser, or a Hydrogen webview (never localhost from outside the container). The app: a 44 px header, the board in 3D on the canonical Adom 3D viewer (adom/adom-3d-viewer, embedded; ViewCube, studio lighting, zoom to the cursor), the field painted on the picked layer with the other layers faded, the vias as dots, the hot parts labelled with their rise, the legend, the readout under the cursor, the nets and hot parts on the left, the issues and the method on the right. Phone: the two side panels open from the header buttons.
## Drive it (the AI's wheel)
```
adom-fields ui view --quantity current|heat|temperature|signals|flow|river|energy|light|cycle|charge|magnetic|emc|ground|noise|pdn [--explode 0..1] [--probe mm] [--speed 1] [--layer F.Cu|In1.Cu|In2.Cu|B.Cu] [--camera top|iso|bottom|fit|zoom --at x,y] [--air still|moving] [--parts auto|ghost|solid|off]
adom-fields ui select --net +VBAT # one net lit alone (current)
adom-fields ui select --chip Q3 # fly to a hot part, heat view
adom-fields ui issue --index 0 # fly to an issue
adom-fields ui toast "20 A through a 1.5 mm neck"
adom-fields ui state | console
adom-fields tour --pause-ms 20000 # the scripted walkthrough: nets by relevance, each field, the hot parts, the issues
```
The server: `GET /state`, `GET /console` (the UI's log), `GET /events` (SSE), `GET /fields.json`, `POST /ui/view|select|issue|toast`. State lives on the server; the UI, the CLI and the AI see the same view.
## The parts over the fields (0.5.0)
`analyze` now also places every footprint's own 3D model on the board, so the chip stands in its hot zone and the cause of a hot spot is plain. The models come from the board file: each footprint's `(model ...)` entries, resolved as KiCad does (`${KIPRJMOD}`, `${KICAD*_3DMODEL_DIR}`, then `--models-dir <folder>` by file name, then a stock KiCad library model fetched by name), converted once to GLB on the Adom STEP service (`step2glb`) and cached by content in `~/.cache/adom-fields/models/`. They land in `<out>/parts/` and the `parts` block of fields.json. A footprint with no model gets a 1 mm box from its courtyard; test points and board-only footprints stay bare copper. A failed conversion never fails the solve: it is logged and the part becomes a box.
On a Fusion board (`.brd`) the parts are found by name, since Fusion binds its 3D packages by cloud urn: each element's MPN, then its deviceset, then its package, as `<name>.step` in the `--models-dir` folders, then in `3d/` or `3dmodels/` beside the board. AI Flow's `fusion library` writes the checked Z-up models to `<run>/3d/<MPN>.step`, so a solve of `<run>/board-live.brd` finds them with no flag. The conversion needs `step2glb` on the PATH (a declared dependency since 0.6.1; `adom-wiki pkg install adom/adom-step2glb`); without it every model is logged as a failure and the parts stay bare.
```
adom-fields analyze --board run/board-2.kicad_pcb --spec spec.json --out fields --models-dir kicad/3d # a snapshot outside the project folder
adom-fields parts --board board.kicad_pcb --fields fields # add or refresh the parts of an existing solve
adom-fields ui view --parts ghost|solid|off|auto # auto: see-through on every field but signals
adom-fields analyze ... --no-parts # skip them (no STEP service needed)
```
`ghost` draws the bodies see-through so the field glows through them; `solid` is the plain assembly; the header's cube button cycles them. The hot-part labels ride on top of their part.
## Calmer motion (0.5.0)
Every camera move and the idle sway run at half the 0.4 speed (the sway period is about 40 s), because the flow plays the clip ten times faster. `tour --pause-ms` defaults to 20000 so a beat settles before the next. For frame-exact video, the page exposes `window.fieldsCapture.begin(1/30)` and `.step()` (one frame of page time per call; the live loop stops and the orbit pivot marker hides); `ui view --camera zoom --at x,y` flies to any board point.
## In the AI Flow video
Record the pup window (Adom Bridge `desktop_record_window_start` on it) while `adom-fields tour` runs: the clip is the fields step, the toasts are the captions, the AI's own analysis on the board in 3D.
## Flow, river and the exploded stack (0.7.0)
`analyze` also writes `flow.bin` (the signed current, the voltage and the owning net of every cell) and `fields.json` `flow` (each net's rail, sense, drop, terminals as source or sink, and the current down each barrel). Two views use it:
- `ui view --quantity flow`: the current as charge, streaks whose speed and glow follow |J|, dropping through the barrels by their solved share. `--explode 1` pulls the layers apart (0 puts them back); the camera backs off to keep the stack in frame.
- `ui view --quantity river`: each net lifted to its voltage, water over it, loads as waterfalls, sources as fountains, a switching node as a slowed tide. Signs give each net's voltage and drop; the readout gives the volts under the cursor.
- `--speed 0.1..4` slows or quickens both. The badge states the scale and the exaggeration; say it when you narrate.
Tell the solve the voltages it cannot read from names, in the spec:
```json
"voltages": {"VIN": 12, "VOUT": 5},
"sources": {"VOUT": ["L1"], "SW": ["U1"]},
"switching": {"SW": {"highV": 12, "lowV": 0, "freqHz": 500000}}
```
Names give GND/PGND/AGND/VSS 0, 3V3 3.3, +12V 12, 5V_AUX 5; SW, LX and PH are switching nodes between the highest rail and 0 unless the spec says otherwise. Default sense: a supply flows from its connector to its parts, a ground from its parts back to its connector; `sources` flips a net whose feed is a part (a regulator or inductor output). A net with no rail stays at its drop and says "rail not given". The voltages are DC: the rail plus the solved IR drop. Copper the pinned terminal cannot reach (a floating island) sits still at the rail.
Developing the page: `ADOM_FIELDS_UI_DIR=<repo>/src/ui adom-fields serve ...` serves index.html, app.js and flow.js from disk, so a reload shows a change without a rebuild.
## Energy and light
**Energy** (`ui view --quantity energy --explode 0.6`) shows where the energy really travels: pink particles in the board material between the copper layers, along the Poynting vector S = E × H. Between two layers a gap h apart, E is (V_top − V_bottom)/h and the two current sheets give H, so S = ½ (V_top − V_bottom)/h · (K_top − K_bottom) in W/mm²; over a supply and its return that integrates to V × I. Pink rising into a part is that part taking its energy. The blue dots are the electrons in the copper at their real drift speed (J / n e, 0.073 mm/s per A/mm²), moving against the current. DC, inside the board only: part of the energy travels in the air around it.
**Light** (`ui view --quantity light`) colours each piece of copper by how fast a change travels in its field, as a % of the speed of light: 1/√εr_eff, all FR4 between planes (about 48 %), Hammerstad's εr_eff for a trace over a plane (wider is slower), mostly air with no plane under it. A switch-on front sweeps out from each fed net's source, and each load is tagged with its arrival time in picoseconds (the fastest path, the sum of length over speed along the way). εr comes from the spec's signals epsilonR, else 4.3. A switching node's DC average (`switching.SW.meanV`) sets its level in the energy view.
## Explained out loud (0.7.1)
Every view can explain itself by voice: the speaker button in the header, `adom-fields ui explain [--quantity q]` (`--stop` silences it), or automatically. The left panel's "Explain each view out loud" sets the rule per viewer: **First time** (the default: each kind of view speaks once, the first time this viewer opens it, so a newcomer hears what they are looking at), **Always**, or **On ask**. The page writes each explanation from a template with this board's own numbers (the peak density and its net, the hottest part, the rails, the electrons' speed, the arrival times), so no AI tokens are spent; the server voices it with adom-tts and keeps the mp3 under `<fields>/narration/`, named by the text's hash, so it is voiced once. A one-line subtitle follows the voice, sentence by sentence, sitting above the legend and readout so neither is covered. Without adom-tts, a toast says so.
## The energy cycle (0.7.2)
`ui view --quantity cycle`: one switching period of a buck converter, slowed about a million times (the meter states the factor). Pink energy packets run from the input capacitors through the switch into the inductor while the switch is on, and from the inductor to the output capacitors and the load all the time; blue particles ride the inductor's magnetic field lines, brightening and swelling as its current and stored energy grow, collapsing on the off-time; red arches over each capacitor brighten as its stored energy rises; orange heat leaves the switch and the inductor. A meter (bottom left, click its title to fold) gives the switch state, the inductor current waveform with a cursor, each store's voltage or current and energy, the heat and the energy delivered per cycle.
The model is the ideal continuous-conduction buck solved exactly: D = Vout/Vin, inductor ripple ΔI = (Vin − Vout)·D·T/L, the capacitor charge integrated over the period. It finds the converter from the solve: the switching node, the inductor on it (L*), the switch (the node's source), the input rail (the switch's highest rail), the output (the inductor's other net), the input and output capacitors (C* between each rail and ground). L and C come from the parts' values on the board (KiCad Value, Fusion element value; `fields.json` `partValues`), fsw from the spec's `switching.freqHz`, the load from the output net's amps, the heat from the hot parts' watts. A board it cannot model says why.
## The silkscreen (0.7.2)
`analyze` exports the board's F.SilkS and B.SilkS with kicad-cli as SVG (`silk-front.svg`, `silk-back.svg`, fields.json `silk`); `adom-fields silk --board <pcb> --fields <dir>` adds them to an existing solve. The page draws each once into a texture on one plane per side (two quads, no geometry), riding its copper layer and the exploded stack, each side shown only from its own side of the board, hidden in the river. The header's T button or `ui view --silk on|off` toggles it. `--no-silk` skips it; a Fusion board has none yet.
## Charge: the board as capacitors (0.7.3)
`ui view --quantity charge` (the Charge button pulls the layers apart): wherever copper at different voltages faces copper across the board material, it is a capacitor. Each face holds σ = ε0·εr·ΔV/h, red on the higher voltage, blue on the lower, brighter for more charge; particles cross the gap from the + face to the − face along the field; a switching node's copper charges and empties with its tide every cycle (the stray capacitance switching noise couples through). A panel compares the copper's own capacitance between net pairs (pF, pC) with the capacitor parts (µF, µC, the energy ½CV²); the readout gives the charge per mm² and the field under the cursor. Parallel plates only: fringing and the air above are not counted.
## Magnetic: the field of every current (0.7.4)
`ui view --quantity magnetic [--probe 2]`: the Biot–Savart field of the solved currents (every copper cell's current summed onto a half-millimetre grid of current elements, plus the current down each via). Glowing blue field lines loop around the current paths, brightest where the field is strongest, their dashes running the way the field points; a sheet at `--probe` mm above the top copper (the slider beside the view buttons, 0.5 to 15 mm) glows where the field is strong, with a white ring at every tenfold step, the way a near-field probe would see it. The readout gives µT, the share of Earth's field (about 50 µT) and H in A/m. DC: the switching field comes with the EMC loop views.
## The ground view (0.7.6)
`ui view --quantity ground`: the ground copper lifted by its solved millivolts (rings every step), each part's ground pin tagged with its offset, dashed arcs for the possible loops through the ground connectors' cables, floating ground islands in red, and the stitching fence: a ring per ground via (λ/40 reach) with the uncovered stretches of the edge in red.
## Also in this area
- **Field views frame themselves** (0.8.6): entering Energy (stack open 0.8, parts off, low front camera), Flow (0.6, parts ghosted, low side) or Magnetic (parts off, low side) sets the stack, parts and camera so the field shows; values the command sets win, `ui view --keep-camera` keeps everything as it is, and leaving for another view restores what was there. Camera presets: top, iso, front, low, bottom, fit, zoom.