KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_transline_roundtrip.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.TXT for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21
22#include <cmath>
23
34
35
36namespace TC = TRANSLINE_CALCULATIONS;
38
39
40/*
41 * Parameter-flow regression net: for every transmission-line calculator, drive
42 * Analyse -> set Z0 as the synthesis target -> Synthesize the canonical geometry
43 * unknown -> re-Analyse, and assert Z0 (or Z0_E / Z0_O for coupled lines) recovers
44 * within tolerance. The per-calculator test files already cover each math class
45 * in isolation; this file exists so that a parameter added to TRANSLINE_PARAMETERS
46 * that is forgotten in one calculator's parameter list is caught by a single
47 * failing test rather than requiring coverage of every edge case in every suite.
48 *
49 * Tolerances are 1% relative on Z0 except where the underlying synthesis is
50 * ill-conditioned at the fixture's starting geometry; in that case the tolerance
51 * is widened and the site is flagged with a comment explaining why.
52 */
53
54
55BOOST_AUTO_TEST_SUITE( TranslineRoundTrip )
56
57
58// Microstrip. Fixture mirrors a typical 50 Ohm FR-4 line: εr 4.3, tanδ 0.02,
59// H 0.2 mm, W 0.4 mm, T 35 μm, 1 GHz. Synthesis target is PHYS_WIDTH.
60BOOST_AUTO_TEST_CASE( MicrostripWidthRoundTrip )
61{
62 MICROSTRIP calc;
63 calc.SetParameter( TCP::EPSILONR, 4.3 );
64 calc.SetParameter( TCP::TAND, 0.02 );
65 calc.SetParameter( TCP::MUR, 1.0 );
66 calc.SetParameter( TCP::MURC, 1.0 );
67 calc.SetParameter( TCP::ROUGH, 0.0 );
68 calc.SetParameter( TCP::SIGMA, 5.8e7 );
69 calc.SetParameter( TCP::H, 0.2 * TC::UNIT_MM );
70 calc.SetParameter( TCP::H_T, 1.0e20 );
71 calc.SetParameter( TCP::T, 35.0 * TC::UNIT_MICRON );
73 calc.SetParameter( TCP::PHYS_LEN, 100.0 * TC::UNIT_MM );
74 calc.SetParameter( TCP::FREQUENCY, 1.0e9 );
75 calc.SetParameter( TCP::ANG_L, 0.0 );
76
77 calc.Analyse();
78 const double Z0_orig = calc.GetAnalysisResults()[TCP::Z0].first;
79
80 calc.SetParameter( TCP::Z0, Z0_orig );
81 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
83
84 const double W_synth = calc.GetParameter( TCP::PHYS_WIDTH );
85 BOOST_TEST( std::isfinite( W_synth ) );
86 BOOST_TEST( W_synth > 0.0 );
87
88 calc.Analyse();
89 const double Z0_check = calc.GetAnalysisResults()[TCP::Z0].first;
90 BOOST_TEST( Z0_check == Z0_orig, boost::test_tools::tolerance( 0.01 ) );
91}
92
93
94// Stripline. b = 1.6 mm (H), W = 0.4 mm, T = 35 μm, STRIPLINE_A centres the strip
95// (STRIPLINE_A = (H - T) / 2). εr 4.3, 1 GHz. Synthesis target is PHYS_WIDTH.
96BOOST_AUTO_TEST_CASE( StriplineWidthRoundTrip )
97{
98 STRIPLINE calc;
99 calc.SetParameter( TCP::EPSILONR, 4.3 );
100 calc.SetParameter( TCP::TAND, 0.02 );
101 calc.SetParameter( TCP::MURC, 1.0 );
102 calc.SetParameter( TCP::SIGMA, 5.8e7 );
103 const double h = 1.6 * TC::UNIT_MM;
104 const double t = 35.0 * TC::UNIT_MICRON;
105 calc.SetParameter( TCP::H, h );
106 calc.SetParameter( TCP::T, t );
107 calc.SetParameter( TCP::STRIPLINE_A, ( h - t ) / 2.0 );
109 calc.SetParameter( TCP::PHYS_LEN, 100.0 * TC::UNIT_MM );
110 calc.SetParameter( TCP::FREQUENCY, 1.0e9 );
111 calc.SetParameter( TCP::ANG_L, 0.0 );
112
113 calc.Analyse();
114 const double Z0_orig = calc.GetAnalysisResults()[TCP::Z0].first;
115
116 calc.SetParameter( TCP::Z0, Z0_orig );
117 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
119
120 const double W_synth = calc.GetParameter( TCP::PHYS_WIDTH );
121 BOOST_TEST( std::isfinite( W_synth ) );
122 BOOST_TEST( W_synth > 0.0 );
123
124 calc.Analyse();
125 const double Z0_check = calc.GetAnalysisResults()[TCP::Z0].first;
126 BOOST_TEST( Z0_check == Z0_orig, boost::test_tools::tolerance( 0.01 ) );
127}
128
129
130// Coupled microstrip. Same fixture as test_coupled_microstrip.cpp. Synthesises
131// PHYS_WIDTH with spacing fixed (FIX_SPACING). The 1D Z0_O-only solve is less
132// conditioned than the full 2D newton in the default branch, so use a 2%
133// tolerance on Z0_O recovery.
134BOOST_AUTO_TEST_CASE( CoupledMicrostripWidthRoundTrip )
135{
137 calc.SetParameter( TCP::EPSILONR, 4.3 );
138 calc.SetParameter( TCP::TAND, 0.02 );
139 calc.SetParameter( TCP::MURC, 1.0 );
140 calc.SetParameter( TCP::ROUGH, 0.0 );
141 calc.SetParameter( TCP::SIGMA, 5.8e7 );
142 calc.SetParameter( TCP::H, 0.2 * TC::UNIT_MM );
143 calc.SetParameter( TCP::H_T, 1.0e20 );
145 calc.SetParameter( TCP::PHYS_S, 0.2 * TC::UNIT_MM );
146 calc.SetParameter( TCP::T, 35.0 * TC::UNIT_MICRON );
147 calc.SetParameter( TCP::PHYS_LEN, 100.0 * TC::UNIT_MM );
148 calc.SetParameter( TCP::FREQUENCY, 1.0e9 );
149 calc.SetParameter( TCP::ANG_L, 0.0 );
150
151 calc.Analyse();
152 auto& results = calc.GetAnalysisResults();
153 const double Z0_E_orig = results.at(TCP::Z0_E).first;
154 const double Z0_O_orig = results.at(TCP::Z0_O).first;
155
156 // FIX_SPACING path only drives Z0_O; we'll verify Z0_O recovers after solving W.
157 calc.SetParameter( TCP::Z0_E, Z0_E_orig );
158 calc.SetParameter( TCP::Z0_O, Z0_O_orig );
159 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
160
162
163 const double W_synth = calc.GetParameter( TCP::PHYS_WIDTH );
164 BOOST_TEST( std::isfinite( W_synth ) );
165 BOOST_TEST( W_synth > 0.0 );
166
167 calc.Analyse();
168 const double Z0_O_check = calc.GetAnalysisResults()[TCP::Z0_O].first;
169 BOOST_TEST( Z0_O_check == Z0_O_orig, boost::test_tools::tolerance( 0.02 ) );
170}
171
172
173// Coupled stripline. Mirrors the fixture from test_coupled_stripline.cpp. The
174// FIX_SPACING path solves PHYS_WIDTH against Z0_O; keep 2% tolerance to match
175// the coupled microstrip convention for 1D coupled solves.
176BOOST_AUTO_TEST_CASE( CoupledStriplineWidthRoundTrip )
177{
179 calc.SetParameter( TCP::EPSILONR, 4.3 );
180 calc.SetParameter( TCP::TAND, 0.02 );
181 calc.SetParameter( TCP::MUR, 1.0 );
182 calc.SetParameter( TCP::MURC, 1.0 );
183 calc.SetParameter( TCP::ROUGH, 0.0 );
184 calc.SetParameter( TCP::SIGMA, 5.8e7 );
185 calc.SetParameter( TCP::H, 20.0 * TC::UNIT_MIL );
188 calc.SetParameter( TCP::T, 0.7 * TC::UNIT_MIL );
189 calc.SetParameter( TCP::PHYS_LEN, 100.0 * TC::UNIT_MM );
190 calc.SetParameter( TCP::FREQUENCY, 1.0e9 );
191 calc.SetParameter( TCP::ANG_L, 0.0 );
192
193 calc.Analyse();
194 auto& results = calc.GetAnalysisResults();
195 const double Z0_E_orig = results.at(TCP::Z0_E).first;
196 const double Z0_O_orig = results.at(TCP::Z0_O).first;
197
198 calc.SetParameter( TCP::Z0_E, Z0_E_orig );
199 calc.SetParameter( TCP::Z0_O, Z0_O_orig );
200 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
201
203
204 const double W_synth = calc.GetParameter( TCP::PHYS_WIDTH );
205 BOOST_TEST( std::isfinite( W_synth ) );
206 BOOST_TEST( W_synth > 0.0 );
207
208 calc.Analyse();
209 const double Z0_O_check = calc.GetAnalysisResults()[TCP::Z0_O].first;
210 BOOST_TEST( Z0_O_check == Z0_O_orig, boost::test_tools::tolerance( 0.02 ) );
211}
212
213
214// Coax. Teflon-filled RG-142-ish geometry. Default synthesis target is
215// PHYS_DIAM_IN. The closed-form synthesis is exact, so 1% is comfortable.
216BOOST_AUTO_TEST_CASE( CoaxDinRoundTrip )
217{
218 COAX calc;
219 calc.SetParameter( TCP::MUR, 1.0 );
220 calc.SetParameter( TCP::MURC, 1.0 );
221 calc.SetParameter( TCP::SIGMA, 5.8e7 );
222 calc.SetParameter( TCP::TAND, 0.0 );
223 calc.SetParameter( TCP::EPSILONR, 2.04 );
226 calc.SetParameter( TCP::PHYS_LEN, 100.0 * TC::UNIT_MM );
227 calc.SetParameter( TCP::FREQUENCY, 1.0e9 );
228 calc.SetParameter( TCP::ANG_L, 0.0 );
229
230 calc.Analyse();
231 const double Z0_orig = calc.GetAnalysisResults()[TCP::Z0].first;
232
233 calc.SetParameter( TCP::Z0, Z0_orig );
234 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
236
237 const double Din_synth = calc.GetParameter( TCP::PHYS_DIAM_IN );
238 BOOST_TEST( std::isfinite( Din_synth ) );
239 BOOST_TEST( Din_synth > 0.0 );
240
241 calc.Analyse();
242 const double Z0_check = calc.GetAnalysisResults()[TCP::Z0].first;
243 BOOST_TEST( Z0_check == Z0_orig, boost::test_tools::tolerance( 0.01 ) );
244}
245
246
247// Coplanar (ungrounded CPW). Default synthesis target is PHYS_WIDTH.
248BOOST_AUTO_TEST_CASE( CoplanarWidthRoundTrip )
249{
250 COPLANAR calc;
251 calc.SetParameter( TCP::EPSILONR, 4.4 );
252 calc.SetParameter( TCP::TAND, 0.0 );
253 calc.SetParameter( TCP::MURC, 1.0 );
254 calc.SetParameter( TCP::SIGMA, 5.8e7 );
255 calc.SetParameter( TCP::H, 0.8 * TC::UNIT_MM );
256 calc.SetParameter( TCP::T, 35.0 * TC::UNIT_MICRON );
258 calc.SetParameter( TCP::PHYS_S, 0.3 * TC::UNIT_MM );
259 calc.SetParameter( TCP::PHYS_LEN, 100.0 * TC::UNIT_MM );
260 calc.SetParameter( TCP::FREQUENCY, 1.0e9 );
261 calc.SetParameter( TCP::ANG_L, 0.0 );
262 calc.SetParameter( TCP::CPW_BACKMETAL, 0.0 );
263
264 calc.Analyse();
265 const double Z0_orig = calc.GetAnalysisResults()[TCP::Z0].first;
266
267 calc.SetParameter( TCP::Z0, Z0_orig );
268 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
270
271 const double W_synth = calc.GetParameter( TCP::PHYS_WIDTH );
272 BOOST_TEST( std::isfinite( W_synth ) );
273 BOOST_TEST( W_synth > 0.0 );
274
275 calc.Analyse();
276 const double Z0_check = calc.GetAnalysisResults()[TCP::Z0].first;
277 BOOST_TEST( Z0_check == Z0_orig, boost::test_tools::tolerance( 0.01 ) );
278}
279
280
281// Rectangular waveguide. WR-90-ish geometry at 10 GHz. Default synthesis
282// target is PHYS_WIDTH (the broad dimension a).
283BOOST_AUTO_TEST_CASE( RectWaveguideWidthRoundTrip )
284{
285 RECTWAVEGUIDE calc;
286 calc.SetParameter( TCP::EPSILONR, 1.0 );
287 calc.SetParameter( TCP::TAND, 0.0 );
288 calc.SetParameter( TCP::SIGMA, 5.8e7 );
289 calc.SetParameter( TCP::MUR, 1.0 );
290 calc.SetParameter( TCP::MURC, 1.0 );
292 calc.SetParameter( TCP::PHYS_S, 10.16 * TC::UNIT_MM );
293 calc.SetParameter( TCP::PHYS_LEN, 100.0 * TC::UNIT_MM );
294 calc.SetParameter( TCP::FREQUENCY, 10.0e9 );
295 calc.SetParameter( TCP::ANG_L, 0.0 );
296
297 calc.Analyse();
298 const double Z0_orig = calc.GetAnalysisResults()[TCP::Z0].first;
299
300 calc.SetParameter( TCP::Z0, Z0_orig );
301 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
303
304 const double a_synth = calc.GetParameter( TCP::PHYS_WIDTH );
305 BOOST_TEST( std::isfinite( a_synth ) );
306 BOOST_TEST( a_synth > 0.0 );
307
308 calc.Analyse();
309 const double Z0_check = calc.GetAnalysisResults()[TCP::Z0].first;
310 BOOST_TEST( Z0_check == Z0_orig, boost::test_tools::tolerance( 0.01 ) );
311}
312
313
314// Twisted pair. Cat5e-like geometry. Default synthesis target is
315// PHYS_DIAM_OUT. Lefferson model; a 1% tolerance is achievable because the
316// single-variable solve over Dout is well-conditioned for Z0 in the 100-135 Ω
317// band that this fixture covers.
318BOOST_AUTO_TEST_CASE( TwistedPairDoutRoundTrip )
319{
320 TWISTEDPAIR calc;
321 calc.SetParameter( TCP::EPSILONR, 2.3 );
322 calc.SetParameter( TCP::TAND, 0.0 );
323 calc.SetParameter( TCP::SIGMA, 5.8e7 );
324 calc.SetParameter( TCP::MURC, 1.0 );
327 calc.SetParameter( TCP::PHYS_LEN, 1.000 * TC::UNIT_M );
329 calc.SetParameter( TCP::ANG_L, 0.0 );
332
333 calc.Analyse();
334 const double Z0_orig = calc.GetAnalysisResults()[TCP::Z0].first;
335
336 calc.SetParameter( TCP::Z0, Z0_orig );
337 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
339
340 const double Dout_synth = calc.GetParameter( TCP::PHYS_DIAM_OUT );
341 BOOST_TEST( std::isfinite( Dout_synth ) );
342 BOOST_TEST( Dout_synth > 0.0 );
343
344 calc.SetParameter( TCP::Z0, 0.0 );
345 calc.Analyse();
346 const double Z0_check = calc.GetAnalysisResults()[TCP::Z0].first;
347 BOOST_TEST( Z0_check == Z0_orig, boost::test_tools::tolerance( 0.01 ) );
348}
349
350
Coaxial transmission line calculation (TEM mode).
bool Synthesize(SYNTHESIZE_OPTS aOpts) override
Synthesize the cable geometry to match the given Z0 target.
void Analyse() override
Analyse cable geometry parameters to output Z0, electrical length, losses and cutoffs.
Coplanar waveguide (CPW) and conductor-backed coplanar waveguide (CBCPW) calculation.
void Analyse() override
Analyse trace geometry to produce Z0, electrical length, effective permittivity, and losses.
bool Synthesize(SYNTHESIZE_OPTS aOpts) override
Synthesize the unknown geometry parameter to match the Z0 target.
void Analyse() override
Analyse track geometry parameters to output Z0 and Ang_L.
bool Synthesize(SYNTHESIZE_OPTS aOpts) override
Synthesis track geometry parameters to match given Z0.
void Analyse() override
Analyse track geometry parameters to output Z0 and Ang_L.
bool Synthesize(SYNTHESIZE_OPTS aOpts) override
Synthesis track geometry parameters to match given Z0.
bool Synthesize(SYNTHESIZE_OPTS aOpts) override
Synthesis track geometry parameters to match given Z0.
void Analyse() override
Analyse track geometry parameters to output Z0 and Ang_L.
Rectangular waveguide calculation.
bool Synthesize(SYNTHESIZE_OPTS aOpts) override
Synthesize the broad dimension a from a target Z0. Only PHYS_WIDTH is a valid target.
void Analyse() override
Analyse waveguide geometry to produce Z0, electrical length, loss, and mode cutoffs.
bool Synthesize(SYNTHESIZE_OPTS aOpts) override
Synthesis track geometry parameters to match given Z0.
void Analyse() override
Analyse track geometry parameters to output Z0 and Ang_L.
double GetParameter(const TRANSLINE_PARAMETERS aParam) const
Gets the given calculation property.
void SetParameter(const TRANSLINE_PARAMETERS aParam, const double aValue)
Sets the given calculation property.
std::unordered_map< TRANSLINE_PARAMETERS, std::pair< double, TRANSLINE_STATUS > > & GetAnalysisResults()
Gets the output parameters following analysis.
Twisted-pair transmission line calculation.
bool Synthesize(SYNTHESIZE_OPTS aOpts) override
Synthesize Din or Dout to hit the target Z0. Length is recomputed from ANG_L.
void Analyse() override
Analyse pair geometry to output Z0, electrical length, losses, skin depth, εeff.
TRANSLINE_PARAMETERS TCP
BOOST_AUTO_TEST_CASE(HorizontalAlignment)
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
BOOST_AUTO_TEST_SUITE_END()
BOOST_TEST(netlist.find("R_G1 ARM_OUT1 DIE_B R='0.001 / ((SW_STATE)") !=std::string::npos)
BOOST_AUTO_TEST_CASE(MicrostripWidthRoundTrip)
#define M_PI
TRANSLINE_PARAMETERS
All possible parameters used (as inputs or outputs) by the transmission line calculations.