this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add shunt-R SPICE netlist and SPICE comparison test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

+74
+57
physics.test.js
··· 435 435 const step = Math.round(0.3 / sim.dt); 436 436 near(voltageAt(0.5, step, sim), 0, "V(0.5) = 0 before wave", 1e-9); 437 437 }); 438 + 439 + // ──────────────────────────────────────────────────────────────────────────── 440 + // SPICE comparison: shunt-R at midpoint between two T-line segments 441 + // 442 + // Circuit: Rg=10Ω → T1(Z0=50,τ=1ns) → Rshunt=100Ω → T2(Z0=50,τ=1ns) → open 443 + // Netlist: sim/tline-shunt-r.sp TSV columns: t v(a) t v(b) t v(c) 444 + // 445 + // Tolerance is 1e-2 (vs 1e-4 for the bounce-series SPICE tests) because the 446 + // MoC simulator is discrete-time: linear interpolation between steps introduces 447 + // a bounded error at ramp knees proportional to dt × slope ≈ 8 mV at oversample=256. 448 + // This confirms the physics is correct, not floating-point exact. 449 + // ──────────────────────────────────────────────────────────────────────────── 450 + { 451 + const tsvPath = path.join(__dirname, "sim", "results-tline-shunt-r.tsv"); 452 + const skip = !existsSync(tsvPath); 453 + 454 + test("SPICE comparison: shunt-R at midpoint (tline-shunt-r.sp)", 455 + { skip: skip ? "TSV not found — run: cd sim && ngspice tline-shunt-r.sp" : false }, 456 + () => { 457 + const TAU_D = 1e-9; 458 + const TR_NORM = 0.1; 459 + const TOL = 1e-2; 460 + const model = { 461 + Vg: 1, Rg: 10, 462 + riseTimeTr: TR_NORM, riseShape: "linear", 463 + blocks: [ 464 + { type: "tl", Z0: 50, tau: 1 }, 465 + { type: "R", value: 100 }, 466 + { type: "tl", Z0: 50, tau: 1 }, 467 + ], 468 + terminal: { type: "open" }, 469 + }; 470 + const sim = simulateTimeDomain(model, { tEnd: 14, oversample: 256 }); 471 + const { dt, nSteps, nodeV } = sim; 472 + 473 + // Linear interpolation between adjacent sim steps to reduce quantisation error. 474 + function interp(arr, tn) { 475 + const f = tn / dt; 476 + const k0 = Math.floor(f); 477 + const k1 = Math.min(k0 + 1, nSteps - 1); 478 + return arr[k0] * (1 - (f - k0)) + arr[k1] * (f - k0); 479 + } 480 + 481 + const rows = readFileSync(tsvPath, "utf8").trim().split("\n") 482 + .map((line) => line.trim().split(/\s+/).map(Number)) 483 + .filter((cols) => cols.length >= 6); 484 + assert.ok(rows.length > 10, "TSV should have many rows"); 485 + 486 + for (const [t_s, va_spice, , vb_spice, , vc_spice] of rows) { 487 + const tn = t_s / TAU_D; 488 + near(interp(nodeV[0], tn), va_spice, `v(a) at t=${t_s.toExponential(3)}s`, TOL); 489 + near(interp(nodeV[1], tn), vb_spice, `v(b) at t=${t_s.toExponential(3)}s`, TOL); 490 + near(interp(nodeV[2], tn), vc_spice, `v(c) at t=${t_s.toExponential(3)}s`, TOL); 491 + } 492 + } 493 + ); 494 + }
+17
sim/tline-shunt-r.sp
··· 1 + .title Two T-lines with shunt resistor at midpoint (open-circuit load) 2 + * Rg=10Ω, Z0=50Ω (each segment τ_d=1ns), Rshunt=100Ω at midpoint, load=open 3 + * Probes: v(a)=source node, v(b)=midpoint node, v(c)=load node 4 + .model __T LTRA( r=0 l=5e-08 g=0 c=2e-11 len=1 ) 5 + .save all 6 + Rs1 S A 10 7 + V1 S GND PULSE( 0 1 0 100p 100p 1u 2u ) 8 + OT1 A GND B GND __T 9 + Rshunt B GND 100 10 + OT2 B GND C GND __T 11 + 12 + .control 13 + run 14 + tran 100p 14n 15 + wrdata results-tline-shunt-r.tsv v(a) v(b) v(c) 16 + .endc 17 + .end