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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
25
26#include <cmath>
27
38
39
40namespace TC = TRANSLINE_CALCULATIONS;
42
43
44/*
45 * Parameter-flow regression net: for every transmission-line calculator, drive
46 * Analyse -> set Z0 as the synthesis target -> Synthesize the canonical geometry
47 * unknown -> re-Analyse, and assert Z0 (or Z0_E / Z0_O for coupled lines) recovers
48 * within tolerance. The per-calculator test files already cover each math class
49 * in isolation; this file exists so that a parameter added to TRANSLINE_PARAMETERS
50 * that is forgotten in one calculator's parameter list is caught by a single
51 * failing test rather than requiring coverage of every edge case in every suite.
52 *
53 * Tolerances are 1% relative on Z0 except where the underlying synthesis is
54 * ill-conditioned at the fixture's starting geometry; in that case the tolerance
55 * is widened and the site is flagged with a comment explaining why.
56 */
57
58
59BOOST_AUTO_TEST_SUITE( TranslineRoundTrip )
60
61
62// Microstrip. Fixture mirrors a typical 50 Ohm FR-4 line: εr 4.3, tanδ 0.02,
63// H 0.2 mm, W 0.4 mm, T 35 μm, 1 GHz. Synthesis target is PHYS_WIDTH.
64BOOST_AUTO_TEST_CASE( MicrostripWidthRoundTrip )
65{
66 MICROSTRIP calc;
67 calc.SetParameter( TCP::EPSILONR, 4.3 );
68 calc.SetParameter( TCP::TAND, 0.02 );
69 calc.SetParameter( TCP::MUR, 1.0 );
70 calc.SetParameter( TCP::MURC, 1.0 );
71 calc.SetParameter( TCP::ROUGH, 0.0 );
72 calc.SetParameter( TCP::SIGMA, 5.8e7 );
73 calc.SetParameter( TCP::H, 0.2 * TC::UNIT_MM );
74 calc.SetParameter( TCP::H_T, 1.0e20 );
75 calc.SetParameter( TCP::T, 35.0 * TC::UNIT_MICRON );
77 calc.SetParameter( TCP::PHYS_LEN, 100.0 * TC::UNIT_MM );
78 calc.SetParameter( TCP::FREQUENCY, 1.0e9 );
79 calc.SetParameter( TCP::ANG_L, 0.0 );
80
81 calc.Analyse();
82 const double Z0_orig = calc.GetAnalysisResults()[TCP::Z0].first;
83
84 calc.SetParameter( TCP::Z0, Z0_orig );
85 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
87
88 const double W_synth = calc.GetParameter( TCP::PHYS_WIDTH );
89 BOOST_TEST( std::isfinite( W_synth ) );
90 BOOST_TEST( W_synth > 0.0 );
91
92 calc.Analyse();
93 const double Z0_check = calc.GetAnalysisResults()[TCP::Z0].first;
94 BOOST_TEST( Z0_check == Z0_orig, boost::test_tools::tolerance( 0.01 ) );
95}
96
97
98// Stripline. b = 1.6 mm (H), W = 0.4 mm, T = 35 μm, STRIPLINE_A centres the strip
99// (STRIPLINE_A = (H - T) / 2). εr 4.3, 1 GHz. Synthesis target is PHYS_WIDTH.
100BOOST_AUTO_TEST_CASE( StriplineWidthRoundTrip )
101{
102 STRIPLINE calc;
103 calc.SetParameter( TCP::EPSILONR, 4.3 );
104 calc.SetParameter( TCP::TAND, 0.02 );
105 calc.SetParameter( TCP::MURC, 1.0 );
106 calc.SetParameter( TCP::SIGMA, 5.8e7 );
107 const double h = 1.6 * TC::UNIT_MM;
108 const double t = 35.0 * TC::UNIT_MICRON;
109 calc.SetParameter( TCP::H, h );
110 calc.SetParameter( TCP::T, t );
111 calc.SetParameter( TCP::STRIPLINE_A, ( h - t ) / 2.0 );
113 calc.SetParameter( TCP::PHYS_LEN, 100.0 * TC::UNIT_MM );
114 calc.SetParameter( TCP::FREQUENCY, 1.0e9 );
115 calc.SetParameter( TCP::ANG_L, 0.0 );
116
117 calc.Analyse();
118 const double Z0_orig = calc.GetAnalysisResults()[TCP::Z0].first;
119
120 calc.SetParameter( TCP::Z0, Z0_orig );
121 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
123
124 const double W_synth = calc.GetParameter( TCP::PHYS_WIDTH );
125 BOOST_TEST( std::isfinite( W_synth ) );
126 BOOST_TEST( W_synth > 0.0 );
127
128 calc.Analyse();
129 const double Z0_check = calc.GetAnalysisResults()[TCP::Z0].first;
130 BOOST_TEST( Z0_check == Z0_orig, boost::test_tools::tolerance( 0.01 ) );
131}
132
133
134// Coupled microstrip. Same fixture as test_coupled_microstrip.cpp. Synthesises
135// PHYS_WIDTH with spacing fixed (FIX_SPACING). The 1D Z0_O-only solve is less
136// conditioned than the full 2D newton in the default branch, so use a 2%
137// tolerance on Z0_O recovery.
138BOOST_AUTO_TEST_CASE( CoupledMicrostripWidthRoundTrip )
139{
141 calc.SetParameter( TCP::EPSILONR, 4.3 );
142 calc.SetParameter( TCP::TAND, 0.02 );
143 calc.SetParameter( TCP::MURC, 1.0 );
144 calc.SetParameter( TCP::ROUGH, 0.0 );
145 calc.SetParameter( TCP::SIGMA, 5.8e7 );
146 calc.SetParameter( TCP::H, 0.2 * TC::UNIT_MM );
147 calc.SetParameter( TCP::H_T, 1.0e20 );
149 calc.SetParameter( TCP::PHYS_S, 0.2 * TC::UNIT_MM );
150 calc.SetParameter( TCP::T, 35.0 * TC::UNIT_MICRON );
151 calc.SetParameter( TCP::PHYS_LEN, 100.0 * TC::UNIT_MM );
152 calc.SetParameter( TCP::FREQUENCY, 1.0e9 );
153 calc.SetParameter( TCP::ANG_L, 0.0 );
154
155 calc.Analyse();
156 auto& results = calc.GetAnalysisResults();
157 const double Z0_E_orig = results.at(TCP::Z0_E).first;
158 const double Z0_O_orig = results.at(TCP::Z0_O).first;
159
160 // FIX_SPACING path only drives Z0_O; we'll verify Z0_O recovers after solving W.
161 calc.SetParameter( TCP::Z0_E, Z0_E_orig );
162 calc.SetParameter( TCP::Z0_O, Z0_O_orig );
163 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
164
166
167 const double W_synth = calc.GetParameter( TCP::PHYS_WIDTH );
168 BOOST_TEST( std::isfinite( W_synth ) );
169 BOOST_TEST( W_synth > 0.0 );
170
171 calc.Analyse();
172 const double Z0_O_check = calc.GetAnalysisResults()[TCP::Z0_O].first;
173 BOOST_TEST( Z0_O_check == Z0_O_orig, boost::test_tools::tolerance( 0.02 ) );
174}
175
176
177// Coupled stripline. Mirrors the fixture from test_coupled_stripline.cpp. The
178// FIX_SPACING path solves PHYS_WIDTH against Z0_O; keep 2% tolerance to match
179// the coupled microstrip convention for 1D coupled solves.
180BOOST_AUTO_TEST_CASE( CoupledStriplineWidthRoundTrip )
181{
183 calc.SetParameter( TCP::EPSILONR, 4.3 );
184 calc.SetParameter( TCP::TAND, 0.02 );
185 calc.SetParameter( TCP::MUR, 1.0 );
186 calc.SetParameter( TCP::MURC, 1.0 );
187 calc.SetParameter( TCP::ROUGH, 0.0 );
188 calc.SetParameter( TCP::SIGMA, 5.8e7 );
189 calc.SetParameter( TCP::H, 20.0 * TC::UNIT_MIL );
192 calc.SetParameter( TCP::T, 0.7 * TC::UNIT_MIL );
193 calc.SetParameter( TCP::PHYS_LEN, 100.0 * TC::UNIT_MM );
194 calc.SetParameter( TCP::FREQUENCY, 1.0e9 );
195 calc.SetParameter( TCP::ANG_L, 0.0 );
196
197 calc.Analyse();
198 auto& results = calc.GetAnalysisResults();
199 const double Z0_E_orig = results.at(TCP::Z0_E).first;
200 const double Z0_O_orig = results.at(TCP::Z0_O).first;
201
202 calc.SetParameter( TCP::Z0_E, Z0_E_orig );
203 calc.SetParameter( TCP::Z0_O, Z0_O_orig );
204 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
205
207
208 const double W_synth = calc.GetParameter( TCP::PHYS_WIDTH );
209 BOOST_TEST( std::isfinite( W_synth ) );
210 BOOST_TEST( W_synth > 0.0 );
211
212 calc.Analyse();
213 const double Z0_O_check = calc.GetAnalysisResults()[TCP::Z0_O].first;
214 BOOST_TEST( Z0_O_check == Z0_O_orig, boost::test_tools::tolerance( 0.02 ) );
215}
216
217
218// Coax. Teflon-filled RG-142-ish geometry. Default synthesis target is
219// PHYS_DIAM_IN. The closed-form synthesis is exact, so 1% is comfortable.
220BOOST_AUTO_TEST_CASE( CoaxDinRoundTrip )
221{
222 COAX calc;
223 calc.SetParameter( TCP::MUR, 1.0 );
224 calc.SetParameter( TCP::MURC, 1.0 );
225 calc.SetParameter( TCP::SIGMA, 5.8e7 );
226 calc.SetParameter( TCP::TAND, 0.0 );
227 calc.SetParameter( TCP::EPSILONR, 2.04 );
230 calc.SetParameter( TCP::PHYS_LEN, 100.0 * TC::UNIT_MM );
231 calc.SetParameter( TCP::FREQUENCY, 1.0e9 );
232 calc.SetParameter( TCP::ANG_L, 0.0 );
233
234 calc.Analyse();
235 const double Z0_orig = calc.GetAnalysisResults()[TCP::Z0].first;
236
237 calc.SetParameter( TCP::Z0, Z0_orig );
238 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
240
241 const double Din_synth = calc.GetParameter( TCP::PHYS_DIAM_IN );
242 BOOST_TEST( std::isfinite( Din_synth ) );
243 BOOST_TEST( Din_synth > 0.0 );
244
245 calc.Analyse();
246 const double Z0_check = calc.GetAnalysisResults()[TCP::Z0].first;
247 BOOST_TEST( Z0_check == Z0_orig, boost::test_tools::tolerance( 0.01 ) );
248}
249
250
251// Coplanar (ungrounded CPW). Default synthesis target is PHYS_WIDTH.
252BOOST_AUTO_TEST_CASE( CoplanarWidthRoundTrip )
253{
254 COPLANAR calc;
255 calc.SetParameter( TCP::EPSILONR, 4.4 );
256 calc.SetParameter( TCP::TAND, 0.0 );
257 calc.SetParameter( TCP::MURC, 1.0 );
258 calc.SetParameter( TCP::SIGMA, 5.8e7 );
259 calc.SetParameter( TCP::H, 0.8 * TC::UNIT_MM );
260 calc.SetParameter( TCP::T, 35.0 * TC::UNIT_MICRON );
262 calc.SetParameter( TCP::PHYS_S, 0.3 * TC::UNIT_MM );
263 calc.SetParameter( TCP::PHYS_LEN, 100.0 * TC::UNIT_MM );
264 calc.SetParameter( TCP::FREQUENCY, 1.0e9 );
265 calc.SetParameter( TCP::ANG_L, 0.0 );
266 calc.SetParameter( TCP::CPW_BACKMETAL, 0.0 );
267
268 calc.Analyse();
269 const double Z0_orig = calc.GetAnalysisResults()[TCP::Z0].first;
270
271 calc.SetParameter( TCP::Z0, Z0_orig );
272 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
274
275 const double W_synth = calc.GetParameter( TCP::PHYS_WIDTH );
276 BOOST_TEST( std::isfinite( W_synth ) );
277 BOOST_TEST( W_synth > 0.0 );
278
279 calc.Analyse();
280 const double Z0_check = calc.GetAnalysisResults()[TCP::Z0].first;
281 BOOST_TEST( Z0_check == Z0_orig, boost::test_tools::tolerance( 0.01 ) );
282}
283
284
285// Rectangular waveguide. WR-90-ish geometry at 10 GHz. Default synthesis
286// target is PHYS_WIDTH (the broad dimension a).
287BOOST_AUTO_TEST_CASE( RectWaveguideWidthRoundTrip )
288{
289 RECTWAVEGUIDE calc;
290 calc.SetParameter( TCP::EPSILONR, 1.0 );
291 calc.SetParameter( TCP::TAND, 0.0 );
292 calc.SetParameter( TCP::SIGMA, 5.8e7 );
293 calc.SetParameter( TCP::MUR, 1.0 );
294 calc.SetParameter( TCP::MURC, 1.0 );
296 calc.SetParameter( TCP::PHYS_S, 10.16 * TC::UNIT_MM );
297 calc.SetParameter( TCP::PHYS_LEN, 100.0 * TC::UNIT_MM );
298 calc.SetParameter( TCP::FREQUENCY, 10.0e9 );
299 calc.SetParameter( TCP::ANG_L, 0.0 );
300
301 calc.Analyse();
302 const double Z0_orig = calc.GetAnalysisResults()[TCP::Z0].first;
303
304 calc.SetParameter( TCP::Z0, Z0_orig );
305 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
307
308 const double a_synth = calc.GetParameter( TCP::PHYS_WIDTH );
309 BOOST_TEST( std::isfinite( a_synth ) );
310 BOOST_TEST( a_synth > 0.0 );
311
312 calc.Analyse();
313 const double Z0_check = calc.GetAnalysisResults()[TCP::Z0].first;
314 BOOST_TEST( Z0_check == Z0_orig, boost::test_tools::tolerance( 0.01 ) );
315}
316
317
318// Twisted pair. Cat5e-like geometry. Default synthesis target is
319// PHYS_DIAM_OUT. Lefferson model; a 1% tolerance is achievable because the
320// single-variable solve over Dout is well-conditioned for Z0 in the 100-135 Ω
321// band that this fixture covers.
322BOOST_AUTO_TEST_CASE( TwistedPairDoutRoundTrip )
323{
324 TWISTEDPAIR calc;
325 calc.SetParameter( TCP::EPSILONR, 2.3 );
326 calc.SetParameter( TCP::TAND, 0.0 );
327 calc.SetParameter( TCP::SIGMA, 5.8e7 );
328 calc.SetParameter( TCP::MURC, 1.0 );
331 calc.SetParameter( TCP::PHYS_LEN, 1.000 * TC::UNIT_M );
333 calc.SetParameter( TCP::ANG_L, 0.0 );
336
337 calc.Analyse();
338 const double Z0_orig = calc.GetAnalysisResults()[TCP::Z0].first;
339
340 calc.SetParameter( TCP::Z0, Z0_orig );
341 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
343
344 const double Dout_synth = calc.GetParameter( TCP::PHYS_DIAM_OUT );
345 BOOST_TEST( std::isfinite( Dout_synth ) );
346 BOOST_TEST( Dout_synth > 0.0 );
347
348 calc.SetParameter( TCP::Z0, 0.0 );
349 calc.Analyse();
350 const double Z0_check = calc.GetAnalysisResults()[TCP::Z0].first;
351 BOOST_TEST( Z0_check == Z0_orig, boost::test_tools::tolerance( 0.01 ) );
352}
353
354
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_TEST(contains==c.ExpectedContains)
BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(MicrostripWidthRoundTrip)
#define M_PI
TRANSLINE_PARAMETERS
All possible parameters used (as inputs or outputs) by the transmission line calculations.