28 Commits

Author SHA1 Message Date
janik bfb97d5259 Experimental: push |J| heatmap overlays into KiCad (dialog opt-in)
Build PCM package / build (push) Successful in 6s
After a solve, the per-layer current-density maps can be pushed into
the open board as reference images on User.9..User.12 (stackup order,
top first) - visible right in the editor, toggled like any layer,
never plotted to gerbers. Dialog checkbox, default OFF; every push
replaces all reference images on those layers.

Rendering (fill_resistance/overlay.py, KiCad-free and tested headless):
one pixel per grid cell, opaque over copper with the log scale lifted
off the colormap's near-black bottom (dark canvas), transparent
elsewhere, one pixel of half-alpha edge bleed so the overlay reaches
the drawn outline instead of stopping half a cell short. Pushing lives
in board_io (ReferenceImage via the IPC API, KiCad >= 10.0.1; scale =
width / (pixels * 1 inch / 300 PPI), position = image center); kipy
0.7.1 swallows creation errors, so the per-item status is read from
the raw CreateItemsResponse. pipeline.run takes an optional overlay
callback; failures are reported, never fatal.

tools/kicad_overlay_test.py pushes a fiducial alignment pattern (KiCad
bbox readback verified placement to half a pixel); tools/
kicad_heatmap_overlay.py runs the whole thing headless against the
open board, filtering marker rectangles of other nets' analyses via
the exact copper test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 20:39:13 +07:00
janik 666abaa50f Populated THT holes conduct in-plane as their solder plug + lead
The mouth of a populated THT pad kept only foil copper on every layer:
on the component side and inner layers the joint looked (and conducted)
like plain plane, and current had to crowd through the single barrel
attachment cell. The filled hole - lead cylinder plus solder bore - now
adds conduction-equivalent copper of the full hole depth on EVERY
spanned layer (the pin continues beyond both mouths, so each layer sees
the whole plug cross-section). Side to side the joint differs only by
the solder: coat and cone stay on the protrusion side.

Cone and plug contributions accumulate ADDITIVELY (stack.t_extra_nm)
and fold into thick_scale once; multiplying the factors would overstate
mouth cells carrying both. The raster map draws filled mouths in a
darker tin with their own legend entry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 20:38:01 +07:00
janik c77e3408bd Raster map: THT pad barrels get their own marker and legend entry
Every barrel was drawn with the same green dot under one 'vias' legend
label, making through-hole pads read as vias. Pad barrels (kind='pad')
now draw violet with a 'THT pad barrels' entry; the legend lists only
the barrel kinds present.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 20:37:28 +07:00
janik b070d7444e Model slotted (oblong) THT holes as stadiums, not circles
The drill's y dimension was discarded (padstack.drill.diameter.x only),
so a milled slot became a round hole of its x size - contact rings,
drill mouths and lead cones painted circles larger than the oblong pad
itself, and the cone was skipped outright (pad_min <= drill).

Slots now keep their true stadium shape, rotated with the pad (KiCad
CCW, y down): Electrode/ViaLink carry the end-cap offset vector,
drill_nm becomes the slot WIDTH, and a shared slot_distance() reduces
to the plain radius for round holes. The barrel wall ring, mouth
coverage, cone taper and the solver's attachment search all follow the
slot; barrel_resistance uses the stadium perimeter and bore area. The
stitching-coat fallback becomes a capsule along the slot (inscribed
disc when the axis is unknown) instead of a largest-dimension disc.
Slot fields round-trip through the JSON dumps.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 20:37:01 +07:00
janik bc95b444b4 Model SMD pad copper: exact net pad shapes stamped on their layers
Build PCM package / build (push) Successful in 6s
Pads are the junctions where traces and thermal-relief spokes actually
meet; without their copper a multi-track junction necks down to the
accidental overlap of the rounded track ends, or is severed outright.
gather_smd_pad_copper fetches the exact shape of every undrilled pad
on the net (one API call per pad, layer from the padstack) and
build_problem stamps them onto their own layer (INCLUDE_SMD_PADS).
Selected SMD-pad contacts get their real copper as a side effect
(previously electrode-shape intersected whatever lay underneath).
Dead-end pads become floating islands that the existing connectivity
restriction drops.

Closes the documented SMD-pad-copper limitation (prompted by the
padne comparison).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 13:37:06 +07:00
grabowski d9ca118e1b uv dev environment, README writing pass, publish hygiene
Build PCM package / build (push) Successful in 8s
- pyproject.toml + uv.lock: uv-managed dev environment (uv sync /
  uv run pytest). requirements.txt stays: KiCad builds the plugin's
  runtime venv from it and the PCM zip packages it.
- README: em-dash and run-on cleanup (34 -> 22, the rest deliberate),
  split the 120-word THT solder-joint sentence, fix the documented
  ADAPTIVE_MAX_CELL_UM value (2 mm -> 1 mm, config has 1000 um), fix
  the *Packaging / publishing* cross-reference, dev sections now use
  uv sync / uv run.
- LLM disclaimer: "most commits" carry the trailer (32 of 39), figures
  claim now excepts the hand-drawn hole cross-section, reference the
  UT3513+ measured-vs-computed validation.
- .gitignore: local AI-tooling artifacts; deploy scripts exclude
  pyproject.toml/uv.lock; error-figure title punctuation aligned with
  the other window titles.
2026-07-17 13:24:08 +07:00
grabowski f59ada94e0 Fix adaptive barrel refinement and ambiguous decimal-comma inputs
- adaptive: barrel links could attach to coarse leaves (up to 1 mm),
  making the whole leaf equipotential and deleting the local spreading
  resistance - via-field results read up to ~13% low. Barrel attachment
  cells are now pinned into the keep-fine set before the quadtree is
  built; the guard ring grades around them.
- skin/dialog: the decimal-comma rewrite turned '1,500' into 1.5, a
  silent 1000x error in frequency, test current or cell size. Ambiguous
  comma patterns (thousands separators, multiple commas, mixed with a
  dot) now raise with a message; a real decimal comma ('1,5') still
  parses.
- dialog: Selection.adaptive default now matches the documented
  on-by-default; the adaptive accuracy claim is aligned to the measured
  0.03% quoted in README and config.
2026-07-17 13:23:55 +07:00
janik 959446978c Model every THT pad hole: exact pad copper, lead conductor, DNP holes
Build PCM package / build (push) Successful in 6s
- THT pad copper is now part of the conductor: the exact pad outline
  (incl. oblong/custom shapes) is fetched from KiCad once per pad and
  stamped onto every included layer (the outer shape stands in for
  inner rings). Annular rings bridge antipads, and joints land on real
  copper instead of only pour coverage.
- The internal lead conductor is modeled in every solder-filled hole:
  a cylinder of drill - THT_LEAD_CLEARANCE_MM (0.25 fab rule) with
  THT_LEAD_RHO_OHM_M (copper default; config for brass/steel leads),
  in parallel with the solder annulus and the plating.
- Drill mouths of THT pads: populated pads keep conducting mouth
  copper (stands in for the solder plug - conservative, the plug is
  worth ~200 um of copper equivalent); DNP pad holes are cut open on
  every layer like uncapped via mouths.
- Oblong pads: the coat uses the exact pad shape; the lead cone tapers
  within the inscribed circle (new pad_min_nm on ViaLink/Electrode) so
  the long axis is not overstated sideways.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 19:15:57 +07:00
janik 38b6e34bfa Solder coat only on the solder side of a THT joint
Build PCM package / build (push) Successful in 6s
The pad face is wetted where the joint is: the protrusion side,
opposite the component (already read from the owning footprint). The
component-side pad face stays bare - contact_solder_buildups and
tht_joint_buildups no longer coat both outer layers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 19:05:06 +07:00
janik b2277f65bf Full solder joint at every populated THT pad, read from KiCad
Build PCM package / build (push) Successful in 8s
No size-threshold guessing: whether a hole is a via or a THT pad
already comes from KiCad (board.get_vias vs drilled board.get_pads).
Every populated THT pad of the net now carries the complete joint the
contacts got: solder-filled barrel, average-thickness coat over a
pad-diameter disc on the outer layers, and the protruding-lead cone on
the side opposite its owning footprint. The footprint side and the
Do-not-populate flag are read from KiCad (footprint pads store absolute
positions, so owner lookup is an exact (x, y, number) map); DNP pads
stay plating-only with no joint. Contact pads are deduplicated by
barrel center so their cone/coat is never applied twice.

Barrels are now gathered in single-layer runs too: via rings and drill
mouths perforate a lone plane, THT joints stiffen it locally.

ViaLink gains solder_filled + protrusion_side (legacy dumps load with
the old every-THT-pad-filled semantics).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 19:00:09 +07:00
janik 9e307f2818 Solder cone around protruding THT leads (tent structure)
Build PCM package / build (push) Successful in 5s
The clipped lead of a soldered THT contact protrudes
THT_LEAD_PROTRUSION_MM (1.5 mm default, 0 disables) out of the hole on
the side opposite the component, and a solder cone wraps it: full
protrusion height at the drill wall, tapering linearly to zero at the
pad edge. Painted as per-cell extra conduction-equivalent copper via
stack.thick_scale - the tall solder column at the wall pulls the joint
vicinity to lead potential (equivalent to extending the barrel wall
vertically), the taper carries the radial spreading. DC-exact additive
conductance; at f > 0 the factor multiplies the skin-corrected sheet
conductance like the via mouths (documented approximation).

The protrusion side is looked up from the owning footprint (pads store
absolute positions; component on F.Cu -> lead tents on B.Cu), with a
logged B.Cu fallback. Dump schema gains protrusion_side and
tht_protrusion_nm (defaults keep older v6 dumps loading).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 18:47:10 +07:00
janik 4ff729e192 Barrel contacts for vias/THT pads; configurable cap-drill threshold
Build PCM package / build (push) Successful in 13s
- Selected vias and through-hole pads inject at the drill-wall ring on
  every spanned layer (both contact models), not the whole pad face,
  so the pad/pour spreading resistance is part of the result. Vias are
  now selectable as contacts.
- Soldered THT joints: the hole is modeled solder-filled (core in
  parallel with the plating, also for stitching THT barrels) and the
  pad face carries an average-thickness solder coat over the modeled
  copper (SOLDER_THICKNESS_UM).
- Vias with drills above a configurable threshold (dialog field,
  default CAP_MAX_DRILL_MM = 0.5) keep open mouths even with capping
  selected - the fab caps only small vias.
- Geometry dump schema v6: electrode barrel fields, cap_max_drill_nm.
- Verified against R = rho/(pi t)*acosh(d/2a) for two circular contacts
  on a sheet (+2.6% at h = 0.15 mm, a = 1 mm; uniform model above the
  equipotential one as required by the contact bracket).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 18:28:47 +07:00
grabowski 0afb55216b Fix swarm-review findings: empty-layer crashes, teardrop fills, Jmag
- adaptive: skip layers with zero quadtree leaves in the connectivity
  restriction and mesh-boundary loops (IndexError on boards where a
  selected layer has no copper)
- board_io: accept ZT_TEARDROP zones as conducting copper (KiCad types
  teardrop fills ZT_TEARDROP, never ZT_COPPER, so they were dropped)
- geometry: copper_bbox uses the exact stroke bbox (centerline extrema
  + half width) instead of a 100 um chord tessellation that could
  undershoot arc/cap extrema past the raster guard margin
- solver/adaptive: reference |J| to the conduction-equivalent thickness
  sigma*rho in every branch (the uniform branch used geometric t, so AC
  plots changed scale ~rs_ratio depending on unrelated per-cell maps)
- solver/adaptive/raster: chain cells no longer show phantom sheet-face
  currents; store dl per chain link and overlay the true 1D density
  |dV|/(rho*dl) (exact at any frequency: AC scaling of link conductance
  and cross-section cancels)
- test_quadtree: compare edge lists pair-for-pair (the independent
  column sort destroyed endpoint association)
2026-07-15 19:43:21 +07:00
janik 1c97090005 Layer visibility checkboxes in the result windows
Multi-layer figures (raster map, potential, current density, power
density) get a layer checkbox panel on interactive backends: unticking
a layer removes its row and the remaining rows grow to fill the window
(constrained layout reflows). At least one layer stays visible; saved
PNGs always contain every layer, with the panel hidden.

The four figure builders are restructured around per-layer painters
plus a finalize hook (legend/colorbar/annotations), driven by a shared
_layer_windows redraw loop; single-layer figures and non-interactive
runs are unchanged. The toggle path is exercised headlessly through
the real CheckButtons callback in the visual check.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 18:27:06 +07:00
janik 1a28f2a593 Smooth adaptive potential maps and draw the mesh on the raster figure
Two display fixes for the adaptive grid, from field feedback:

- Equipotential contours showed leaf-sized staircase corners on plane
  interiors: the potential is now expanded piecewise-LINEARLY from each
  leaf's reconstructed gradient instead of constant-per-leaf, and the
  default ADAPTIVE_MAX_CELL_UM drops 2 mm -> 1 mm (interior leaves
  beyond that buy almost nothing).
- The raster map now overlays the adaptive mesh: boundaries of coarse
  leaves draw in darker copper (fine regions stay plain = fully
  resolved), with a legend entry. Uniform-grid runs are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 18:12:52 +07:00
janik 07ab59baad Adaptive grid on by default; finer auto cell size under it
ADAPTIVE_CELLS defaults to True (dialog checkbox stays; untick or
--no-adaptive for the uniform reference grid). With the adaptive grid
the auto cell sizer targets TARGET_CELLS_ADAPTIVE (8M fine cells,
~2x finer h) since unknowns no longer scale with the fine cell count -
memory of the masks/field arrays is the new bound.

The test suite pins ADAPTIVE_CELLS off via an autouse conftest fixture:
the exact-value tests define the uniform reference grid; adaptive tests
opt in per test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 17:57:12 +07:00
janik a2a8a9d702 Deferred-correction interface fluxes for the adaptive grid
Two-point fluxes across coarse-fine faces miss the tangential potential
gradient (offset leaf centers), biasing R ~0.5-2% low. After the first
solve, per-leaf gradients are reconstructed by least squares over face
neighbors and the known tangential term g*delta*Gt moves to the
right-hand side of a re-solve (ADAPTIVE_CORRECTION_PASSES, default 1).
The matrix is unchanged, so the new PreparedSolver reuses the LU
factorization / AMG hierarchy across passes; the corrected currents
satisfy KCL exactly, so the power-balance identity, via currents and
part fluxes all use them consistently (edge power = dV * I_corr).

Measured: strip worst case -1.74% -> -0.028% (1 pass); feature-dense
plate end-to-end -1.1% -> -0.011% at 7.2 s vs 25.9 s uniform (5.58M ->
823k unknowns). Tests tightened accordingly plus a passes-knob test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 17:52:31 +07:00
janik a9233fde32 Wire the adaptive quadtree grid into the solve path (phase 2)
config.ADAPTIVE_CELLS (dialog checkbox "adaptive cells", off by
default; standalone --adaptive) routes run_solve through
fill_resistance/adaptive.py: per-layer balanced leaf grids where every
non-uniform fine cell (electrodes, 1D chain cells, buildup, via-mouth
thickness map) is pinned at the fine size, leaf faces via the
series-half-cell rule, chain links and barrels re-attached by node id,
connectivity restriction and both contact models on the leaf graph via
solver cores extracted for reuse (_equipotential_core, _uniform_core,
_conductance_params, _barrel_links). All fields (V, |J|, power density)
are computed per leaf and expanded to the fine grid, so plots, summary
and dumps are unchanged.

Element sizes: minimum = the grid cell size itself (auto / dialog /
CELL_UM_OVERRIDE); maximum = ADAPTIVE_MAX_CELL_UM (2 mm default);
ADAPTIVE_GUARD sets the clearance a block needs to grow.

Measured end-to-end (feature-dense 120x120 plate, h=50um): 25.9 s ->
5.4 s, 5.58M -> 823k unknowns, R -1.1%. Accuracy documented honestly:
coarse-fine interfaces carry a first-order tangential flux error
biasing R low by ~0.5-2% depending on geometry (worst on narrow
strips); the earlier assumption that linear fields solve exactly on the
leaf graph was wrong - offset centers across size transitions leave an
unpaired residue. Gradient-corrected interface fluxes remain as phase 4
if tighter accuracy per leaf is needed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 17:24:10 +07:00
janik 14cdf4c7ee Add balanced quadtree grid engine (adaptive cells, phase 1)
fill_resistance/quadtree.py decomposes a layer's fine copper mask into
2:1-balanced power-of-two leaves: boundary and keep-fine cells stay at
the fine size, interiors coarsen with their Chebyshev distance to the
nearest feature (guard factor, default 4), and an explicit enforcement
pass splits any leaf more than twice an edge-adjacent neighbor. Face
conductances use the series-half-cell rule, which reduces to the
production harmonic mean for equal sizes and EXACTLY to sigma in the
uniform limit - verified edge-for-edge against solver.build_edges and
to rel 1e-12 in R against run_solve, so the exact-value test suite
stays authoritative for this engine.

Measured (feature-dense 120x120 plate, h=50um, production AMG solver):
uniform 5.58M unknowns ~35s; adaptive guard=4 823k / ~8s at -1.1%;
guard=8 1.74M / ~12s at -0.47%. tools/adaptive_proto.py now benchmarks
the engine itself.

Not yet wired into the pipeline: phase 2 ports electrodes, barrels,
1D chains, buildup and field output onto leaves.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 17:05:31 +07:00
janik d34d3ade51 Model via ring copper and drill mouths (capping), dialog-toggleable
Each via now contributes its ring/pad copper (full-thickness disc of
the pad diameter on every spanned layer) and its drill mouth: with
"vias filled + capped" (dialog checkbox, default on, VIAS_CAPPED) the
mouth carries a CAP_PLATING_UM (15 um) thin copper cap on the outer
layers and is an open hole on inner layers; unchecked, mouths are open
everywhere. Mouth coverage is area-weighted per cell (4x4
supersampling) through a per-cell thickness map feeding the existing
harmonic-mean face machinery, so sub-cell mouths perturb the sheet by
their true covered fraction instead of whole cells. Fully swallowed
cells leave the mask; the barrel then attaches through the ring via the
existing pad-footprint search. THT-pad copper and drills stay outside
the model. Ring discs paint before 1D trace chains (chains see them as
regular copper), mouths after wide tracks (drills go through trace
copper). standalone gains --uncapped.

Tests: cap==foil identity against the feature-off reference, strict
R(solid) < R(cap) < R(hole) ordering, ring bridging a fill gap that a
ringless barrel cannot cross, gentle sub-cell perturbation at coarse
grids, and JSON roundtrip of the new fields.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 16:42:21 +07:00
janik d183bc5fd7 Document that via capping is deliberately not modeled, with error bound
Layer-to-layer the cap (>=15 um plating per fab spec) is parallel to
the annular-ring contact, so it cannot change the DC path. In-plane the
model treats every via mouth as solid layer-thickness copper; the error
is bounded by the dilute-hole correction (~ +2x mouth-area-fraction
locally), partially offset by the unmodeled annular-ring copper, and
typically well under a few percent of total R.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 16:11:49 +07:00
janik bc8dcab9e4 plots: responsive figures (constrained layout + fit-to-screen)
Figures use constrained layout, which reflows on every draw, so the
content adapts when the user resizes the window; tight_layout was
one-shot. Windows larger than the screen are shrunk to fit after the
PNGs are saved, so saved output is unaffected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 16:02:02 +07:00
janik 92bb29637f Model sub-resolution traces as exact 1D resistor chains
Tracks are now first-class Problem objects (TrackSeg: centerline +
width, dump schema v5), so the wide/narrow decision replays at raster
time: traces at least TRACK_1D_FACTOR (3) cells wide rasterize from
their outline as before; narrower ones mark the cells their centerline
crosses as copper and connect them with explicit conductance links
carrying the trace's TRUE arc length per link - no staircase inflation
for diagonals or arcs, and no discretization error in the trace R, at
any grid size. Links across cells already joined by pour faces are
skipped (union, not sum); chain-only cells get no sheet faces (their
copper is narrower than a cell). Electrodes, via barrels, connectivity
restriction and the skin-effect scaling all work on chain cells
unchanged.

This removes the need to shrink the cell size for thin traces: a 0.2 mm
bridge at 500 um cells now matches its finely-rasterized ground truth
within a few percent (tested), including diagonal and arc traces.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 16:02:01 +07:00
janik 56e2f9c81a Include the net's traces as conductors alongside zone fills
Straight tracks become capsule outline polygons (rectangle +
semicircular caps), arc tracks annular bands with end caps, both
tessellated to the same sagitta tolerance as zone-fill arcs; they merge
into the per-layer copper next to the fills, so rasterization, via
stitching, the solver and the plots handle them unchanged. Trace-only
layers and trace-only nets now qualify as candidates. Dialog checkbox
(on by default, INCLUDE_TRACKS) toggles them per run.

Hole-less polygons (every track outline) now paint the layer mask
directly instead of allocating a full-frame temporary each.

Tests: exact N-cell chain on a rasterized capsule, analytic annular-
sector convergence for an arc trace, capsule/arc-band outline geometry
invariants, collinear-arc degradation, and fill+trace union solve.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 15:37:51 +07:00
janik b62e45a9b4 Speed up rasterization ~40x and large solves ~2x
- Hybrid rasterizer: PIL scanline fill for the bulk, with cells in a
  ~2 px band around each ring edge re-tested exactly against the
  polygon - cell-for-cell identical to the old center-in-polygon pass
  (equivalence test added) but O(vertices + cells) instead of
  O(vertices x cells). Measured 4.5 s -> 0.11 s at 1.45M cells with
  8.8k polygon vertices.
- AMG-preconditioned CG (pyamg, new requirement) above 500k unknowns:
  measured 7.0 s vs 15.3 s spsolve at 1.4M unknowns at a fraction of
  the memory, R identical to 1e-6; the old Jacobi-CG (kept as fallback
  when pyamg is missing) needed tens of minutes there. spsolve stays
  the default below 500k where it is exact and fastest.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 15:24:21 +07:00
janik ffbd4a86b5 plots: cross-platform PNG opener; keep uniform-model V- cells in range
Open saved figures via xdg-open/open/startfile when no GUI backend
exists, and extend the potential map's color range below the V- mean
reference instead of clipping it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 14:55:09 +07:00
janik e7627352c1 Fix solver correctness and input-validation issues from code review
- Refuse the uniform contact model when the fills form multiple
  disconnected copper groups that each touch both terminals: the
  prescribed injection split is ill-posed and the grounded system was
  singular, silently returning garbage (e.g. negative gigaohms).
  connected_restrict now reports the component count; a power-balance
  backstop (SolverError) catches any other inconsistent solve.
- Connect via/pad barrels to the nearest fill copper within the pad
  footprint (+1 cell) instead of only the exact center cell, so
  thermal-relief spokes still stitch layers; barrels that reach fill on
  fewer than two layers are warned about. ViaLink gains pad_nm
  (extracted from the padstack, JSON-roundtripped).
- Validate dialog input on OK (layers, current > 0, cell > 0, parseable
  frequency, extra Cu >= 0) with an inline error instead of silently
  substituting defaults; parse_frequency raises on garbage; pipeline
  rejects i_test <= 0; choose_cell_size rejects non-positive overrides.
- Warn when a contact part is dropped by the connectivity restriction;
  floor instead of truncate in cell_of; correct the uniform-model
  summary line; drop an unused variable; refresh plugin.json wording.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 14:54:45 +07:00
janik 06c62e04f8 Initial import: KiCad zone resistance plugin
DC/AC resistance, power dissipation, and via/injection-area currents of
copper zone fills. KiCad 10 IPC-API plugin (kicad-python/kipy):
multi-layer via-coupled FDM solver, multi-part terminals via User.1/User.2
marker layers, pads as contacts, uniform-injection and equipotential
contact models, per-foil skin effect, optional solder/copper buildup on
mask openings. 54-case test suite incl. exact analytic references.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 17:22:00 +07:00