Use the vendored Hammerstad-Jensen/Cohn engine for microstrip, stripline, and coupled-diff advice. Skip OpenEMS/pcbnew and refuse CPWG rather than inventing a number. Co-authored-by: Cursor <cursoragent@cursor.com>
81 lines
2.8 KiB
Python
81 lines
2.8 KiB
Python
"""zsolver validation: a published reference point plus monotonicity checks
|
|
against the underlying physics, so the tests don't just re-derive whatever
|
|
the implementation happens to compute.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from impedancefinder import zsolver
|
|
|
|
|
|
def test_microstrip_matches_classic_50ohm_fr4_rule_of_thumb():
|
|
# ~3mm trace on 1.6mm FR4 (er~4.5) is the textbook "50 ohm microstrip"
|
|
# widely quoted in PCB fab application notes.
|
|
z0 = zsolver.microstrip_z0(width_mm=3.0, height_mm=1.6, er=4.5, t_mm=0.035)
|
|
assert z0 == pytest.approx(50.0, rel=0.05)
|
|
|
|
|
|
def test_microstrip_z0_decreases_with_width():
|
|
narrow = zsolver.microstrip_z0(0.2, 0.15, 4.3, 0.035)
|
|
wide = zsolver.microstrip_z0(0.6, 0.15, 4.3, 0.035)
|
|
assert wide < narrow
|
|
|
|
|
|
def test_microstrip_z0_increases_with_dielectric_height():
|
|
thin = zsolver.microstrip_z0(0.3, 0.1, 4.3, 0.035)
|
|
thick = zsolver.microstrip_z0(0.3, 0.3, 4.3, 0.035)
|
|
assert thick > thin
|
|
|
|
|
|
def test_microstrip_z0_decreases_with_er():
|
|
low_er = zsolver.microstrip_z0(0.3, 0.15, 3.0, 0.035)
|
|
high_er = zsolver.microstrip_z0(0.3, 0.15, 5.0, 0.035)
|
|
assert high_er < low_er
|
|
|
|
|
|
def test_microstrip_z0_finite_thickness_correction_is_a_small_effect():
|
|
with_thickness = zsolver.microstrip_z0(0.3, 0.15, 4.3, 0.035)
|
|
without_thickness = zsolver.microstrip_z0(0.3, 0.15, 4.3, 0.0)
|
|
assert without_thickness == pytest.approx(with_thickness, rel=0.15)
|
|
|
|
|
|
def test_stripline_requires_positive_copper_thickness():
|
|
with pytest.raises(ValueError):
|
|
zsolver.stripline_z0(0.15, 0.3, 4.4, 0.0)
|
|
|
|
|
|
def test_stripline_z0_decreases_with_width():
|
|
narrow = zsolver.stripline_z0(0.1, 0.5, 4.4, 0.035)
|
|
wide = zsolver.stripline_z0(0.3, 0.5, 4.4, 0.035)
|
|
assert wide < narrow
|
|
|
|
|
|
def test_stripline_z0_increases_with_plane_spacing():
|
|
tight = zsolver.stripline_z0(0.15, 0.3, 4.4, 0.035)
|
|
loose = zsolver.stripline_z0(0.15, 0.6, 4.4, 0.035)
|
|
assert loose > tight
|
|
|
|
|
|
def test_diff_microstrip_is_between_single_ended_and_twice_single_ended():
|
|
single = zsolver.microstrip_z0(0.2, 0.15, 4.3, 0.035)
|
|
diff = zsolver.diff_microstrip_z0(0.2, 0.15, 0.2, 4.3, 0.035)
|
|
assert single < diff < 2 * single
|
|
|
|
|
|
def test_diff_microstrip_approaches_twice_single_ended_as_spacing_grows():
|
|
single = zsolver.microstrip_z0(0.2, 0.15, 4.3, 0.035)
|
|
wide_gap = zsolver.diff_microstrip_z0(0.2, 0.15, 5.0, 4.3, 0.035)
|
|
assert wide_gap == pytest.approx(2 * single, rel=0.02)
|
|
|
|
|
|
def test_diff_stripline_approaches_twice_single_ended_as_spacing_grows():
|
|
single = zsolver.stripline_z0(0.15, 0.3, 4.4, 0.035)
|
|
wide_gap = zsolver.diff_stripline_z0(0.15, 0.3, 5.0, 4.4, 0.035)
|
|
assert wide_gap == pytest.approx(2 * single, rel=0.02)
|
|
|
|
|
|
def test_cpwg_is_not_implemented():
|
|
with pytest.raises(NotImplementedError):
|
|
zsolver.cpwg_z0()
|