main
Colby Knox adom-fields 0.10.7: the board's ground (issue 25); coincident lands as one terminal (issue 26); verify keeps via copper… 554eeec

name: adom-fields-spec description: >- The full Adom Fields spec and solver reference: loads and explicit terminals, hot parts (tabNet, tabPad, tjMaxC, thetaJcKPerW), voltages, sources, switching, stackup, copper, epsilonR, solid bodies, package cooling, heatsinks, fan levels, transients, electro-thermal, plated holes, Fusion boards, evidence identity. Use when writing or debugging an adom-fields spec, "spec key", "terminals", "solids", "packageCooling", "fanLevels", "transient", "stackupMm".

Parent skill: adom-fields

Adom Fields: the spec and the solver, in full

Every spec key and what the solver does with it. The core keys are in SKILL.md; read this for terminals, solids, package cooling, fans, transients, stackups and Fusion boards.

What a solve writes

adom-fields analyze --board <board.kicad_pcb | board.brd from Fusion> --spec <spec.json> --out fields

The board must be saved with its zones filled (the filled polygons are the copper). The spec is the AI Flow spec: loads (net: amps, maxRiseC, maxDropMv, draws: {part: amps}), sources (net: [the parts that feed it]), hot (ref: watts, tabNet, maxRiseC: that part's own limit, else hotMaxRiseC), copperUm, hotMaxRiseC, thermalVias (pad, count), optional stackupMm (three dielectric thicknesses). About two minutes for a 65 x 75 mm four-layer board at the default 0.2 mm cell; --pitch 0.1 is four times longer and sharper.

What comes out, in fields/fields.json and fields/tex/:

  • nets, ordered by amps then by peak density: peak A/mm² and where, the layers, the copper mm², the Joule loss, the vias.
  • chips, hottest first: the rise at the tab in still and moving air, and where its watts go within 3 mm (along its layer, down its vias, through the bare dielectric, to the air), with how many vias the spec asked for.
  • issues: current-neck (a loaded net over 60 A/mm², about what IPC-2221 allows at 35 µm for 10 °C), tab-rise (over the budget), thermal-vias (fewer than the spec asks), each with at, layer, net, reference and a fix.
  • textures per layer: J-<layer>.png (all nets), J-<net>-<layer>.png, q-<layer>.png (heat flow, W/mm), T-<layer>.png and Tm-<layer>.png (rise, still and moving air), copper-<layer>.png, plus .raw.png 16-bit values for the readout.

Terminals per net: the wire pads and connectors (MC*, J*, P*) on one side; on the other the spec's hot parts on the net (a FET's tab and its source pins both count), else the Q and U parts, else the parts with real pads, each part's share by its pad area. A net with neither is skipped and says so.

Honest limits (0.1)

DC only (no skin effect, no switching loss on the copper); per-layer thickness when copperUmByLayer is supplied; the 1.6 mm stack is 0.2 / 1.065 / 0.2 mm unless stackupMm says otherwise; convection is a flat coefficient on both faces (10 or 25 W/m²K), optional specified rectangular conducting blocks; no fins, enclosure or radiation; the tab watts come from the spec, not from a switching model. It is a screen that finds the necks and the starved tabs, and shows them; it is not a datasheet number.

Evidence identity

Each solve records SHA-256 identities of the board and spec in fields.json.inputIdentity, plus the solver version. If an input changes while solving, analysis refuses to publish the summary. AI Flow uses these identities to reject stale field screens, and requires every positive load and hot part to be represented. Existing summaries without these identities must be re-solved, not manually stamped. The identities establish which inputs were used; they do not establish the accuracy of assumed terminals, losses, materials or convection.

Fusion boards (0.6.0+)

A Fusion Electronics board works as --board <board>.brd (EAGLE source: fusion_export_eagle_source on the Fusion bridge). Run RATSNEST in Fusion first so the pours are filled: the reader then uses Fusion's own fill. Put the parts' STEP files, named by MPN, in a folder and pass --models-dir so the chips sit over the fields.

The solver: holes, terminals, heat models, fans, transients

  • Plated holes (PR 5, 9): every via and plated through-hole pad barrel joins its copper layers in the electrical and thermal models (25 µm plating, circular or slotted, platedPads counted apart from vias). Drill holes are voids on every layer; each barrel's conductance is spread around its plated wall on cells with copper on both faces, and a wall the mesh does not resolve falls back to the nearest such cells, so a plated hole never disconnects a net. nets[].platedConnections gives each hole's current and mean barrel density. Blind, buried and micro vias are refused; Fusion boards read their declared layerSetup. See docs/plated-wall-coupling.md.
  • Explicit pin currents (PR 6, 10): loads.<net>.terminals: [{reference, pad, amps, at?}], positive into the copper, negative out, each side summing to amps; at: [x, y] picks one physical land where a pin number repeats. Lands of one pad number at one centre on one net (a Texas DGN exposed pad's two coincident lands) are one piece of copper: at names it (0.10.7). Wrong-net, missing, duplicate and unbalanced pins are refused; a loaded net the spec names that cannot be solved fails the run instead of publishing a partial report. terminalAssignments says explicit or heuristic per net.
  • Peak current density is the modeled maximum (PR 8), before the display texture's 99.5th-percentile clip and unrounded (peakJDefinition).
  • dcMaxIterations (PR 5, default 20000, at most 100000) bounds each net's solve; the target is unchanged.
  • Electro-thermal (0.9.1, review.electroThermal). Copper's resistance rises 0.393 %/°C, so every run reports the first-order extra Joule heat at the solved temperatures, and an electro-thermal issue when it is over 10 %. With spec electroThermal: true, a second full pass solves the current and heat with each copper cell at its solved temperature. On the ESC: +33 % Joule, peak rise 109 → 119 °C.
  • Heating transient (0.9.1, transient). Spec transient {durationS, steps (24), powerScale (1; a stall or surge at 3× is 3), fromSteady}: implicit Euler on the still-air heat system with copper, FR4 and the solid bodies' heat capacities.
    • It gives the board peak and each hot part's rise over time, and each part's time constant (t63S, to 63 % of its steady rise).
    • On the buck: U1 about 2 min, L1 about 3 min.
  • Terminals (0.8.1): without explicit loads.<net>.terminals, the solve picks them. The named sources feed the net, and every other connector and part on it is a sink, so a board-to-board connector that a rail feeds counts as a load. Otherwise connectors feed and parts draw. A part listed in loads.<net>.draws carries its own amps, the rest share what is left (sinks by pad area, sources evenly), and each part's share splits evenly over its pins. A pin with no copper near it is left out and its share goes to the other pins on its side, so the injection always balances. Every net in fields.json lists terminalCurrents (pin, amps, + into the copper) and terminalBasis, so a reviewer can check them.
  • Solid bodies off the board (0.8.0): solids: {pitchMm, bodies: [{name, boxesMm: [[x0,y0,z0,x1,y1,z1]], conductivityWMk, watts | heatOf: "<hot ref>", hStillWM2k, hMovingWM2k, boardContactM2kW?, provenance}], contacts: [{bodies: [a, b], resistanceM2kW}], boardLinks: [{body, at, layer, resistanceKPerW, pad}], assumptions}. Boxes are in board mm (x and y as KiCad, z up from the top copper). The bodies are voxelized and solved in the same heat system as the board, so the heat runs from the die through the tab, the pad and the heatsink fins to the air, and down the leads into the copper, in one energy balance. Bodies may touch only through a declared contact (0 means ideal), and they may not overlap. A body under the board couples to B.Cu through boardContactM2kW with its top face at z = minus board.thicknessMm (within 0.05 mm); a body missing the copper raises solid-uncoupled (0.10.6). fields.json solids gives each body's peak rise, heat to air and to board, peak flux and onCopper. solids.json has every cell's temperature and flux vector, and the viewer paints them in the Heat and Temperature views. Calibrate a sink's h to its vendor rating rather than trusting a textbook h. See docs/solids.md.
  • Fan levels (0.8.0): fanLevels: [0, 0.25, 0.5, 0.75, 1] solves each level fully. h on every exposed face (board, bodies, a packageCooling sink) follows (h_still³ + (h_forced·sⁿ)³)^⅓, where s is the fraction of full speed, s = 1 gives the moving-air h, and n is fanExponent (0.5). fields.json airStates gives each level's h, chip rises and bodies. The viewer's Fan control (Off, 25, 50, 75, 100 %) switches the board and the bodies together, on one colour scale, so the levels compare by eye. ui view --air fan50 drives it.
  • Package cooling (PR 11): packageCooling: [{reference, junctionCaseKPerW, caseSinkKPerW, sinkAmbientStillKPerW, sinkAmbientMovingKPerW, boardLinks, provenance}] puts a hot part's watts at its junction and lets them split through the supplied case, sink and board links; junction, case and sink rises per air state and an energy balance in packageCooling. See docs/package-cooling.md.
  • adom-fields thermal3d --spec --out (PR 12): axis-aligned 3D solids with explicit materials, contacts and convection for an off-board package and finned sink, with a GLB of the surface temperatures. Not CFD. See docs/thermal3d.md.

The board's ground (0.10.7)

ground: "GND" names the net that is the board's ground. Without it the ground is the net named GND, else the ground-named net the most pads are on, so a separate return such as BRIDGE_GND, or a small AGND, never wins by its name's place in the alphabet. review.ground records net, groundFrom and groundNets. The ground offset, islands and stitching are measured on it. A protector or bypass capacitor to any ground counts, decoupling counts the chip's own grounds, and --with pdn judges each rail against the ground most of its capacitors go to (return, with capsToOtherGrounds). A spec ground that isn't a net on the board is refused. The converter's power ground is separate (converter.ground).

The converter block (0.10.5)

converter: {inductor: "L1", vinMin: 21, ground: "PGND", series: ["R1"]}, all optional:

  • inductor names the inductor when its path cannot be traced. The tracing already follows current shunts (a Value such as 3m 1W or 0R003 1% reads as 3 mΩ), ferrites and 0 Ω links.
  • vinMin is the lowest input. For a 4-switch buck-boost (the inductor between two switch nodes, each listed in switching with its switches in sources), it evaluates the boost mode alongside the buck mode at the spec's input voltage.
  • ground is the power-stage ground. Without it, the ground is the net the switch legs return to (the low-side switches' sources), so a board with AGND and PGND uses PGND. Set it only when review.converter.groundFrom shows a wrong pick.
  • series lists parts to treat as series links on the inductor's path when their Value does not read as a low resistance.
  • The record: review.converter has topology, switchNodes, seriesParts, ground, groundFrom, groundNets and modes (each with duty, inductor current, ripple, hot loop and emissions). It is {"unsupported": why} when the board cannot be modelled.