KiCad PCB EDA Suite
Loading...
Searching...
No Matches
test_djordjevic_sarkar_integration.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
32
33
35
36
37BOOST_AUTO_TEST_SUITE( DjordjevicSarkarIntegration )
38
39
40// Populate a realistic 50 ohm FR-4 microstrip driven at 10 GHz. W / h / T are chosen
41// so the static impedance lands near 50 ohm (typical 8 mil trace on 8 mil FR-4 core
42// with 1 oz copper). Loss tangent 0.02 at the 1 GHz spec frequency.
44{
45 aCalc.SetParameter( TCP::EPSILONR, 4.4 );
46 aCalc.SetParameter( TCP::TAND, 0.02 );
47 aCalc.SetParameter( TCP::H, 200.0e-6 ); // 200 um substrate
48 aCalc.SetParameter( TCP::H_T, 1.0e12 ); // effectively unbounded cover
49 aCalc.SetParameter( TCP::T, 35.0e-6 ); // 1 oz copper
50 aCalc.SetParameter( TCP::PHYS_WIDTH, 380.0e-6 ); // ~50 ohm trace on 200 um FR-4
51 aCalc.SetParameter( TCP::PHYS_LEN, 25.4e-3 ); // 1 inch
52 aCalc.SetParameter( TCP::FREQUENCY, 10.0e9 ); // 10 GHz operating
53 aCalc.SetParameter( TCP::MUR, 1.0 );
54 aCalc.SetParameter( TCP::MURC, 1.0 );
55 aCalc.SetParameter( TCP::SIGMA, 5.8e7 ); // copper
56 aCalc.SetParameter( TCP::ROUGH, 0.0 );
57}
58
59
60// FR-4 microstrip at 10 GHz. CONSTANT uses epsR=4.4/tan d=0.02 everywhere. DJORDJEVIC_SARKAR
61// fit at 1 GHz yields epsR(10 GHz)~4.27 and tan d(10 GHz)~0.0205, so Z0 shifts by a small but
62// observable amount (positive, because lower epsR at operating frequency raises Z0).
63BOOST_AUTO_TEST_CASE( MicrostripFR4Z0Shift )
64{
65 MICROSTRIP calc;
67
68 // CONSTANT mode baseline
70 static_cast<double>( DIELECTRIC_MODEL::CONSTANT ) );
71 calc.Analyse();
72 const double z0_const = calc.GetParameter( TCP::Z0 );
73
74 // DJORDJEVIC_SARKAR mode
77 static_cast<double>( DIELECTRIC_MODEL::DJORDJEVIC_SARKAR ) );
78 calc.Analyse();
79 const double z0_ds = calc.GetParameter( TCP::Z0 );
80
81 BOOST_TEST_MESSAGE( "FR-4 microstrip 10 GHz: Z0_const=" << z0_const << " ohm, Z0_ds="
82 << z0_ds << " ohm" );
83
84 const double shift = std::fabs( z0_ds - z0_const );
85 BOOST_TEST( shift > 0.3 );
86 BOOST_TEST( shift < 3.0 );
87
88 // Raw EPSILONR / TAND must survive the swap-and-restore in MICROSTRIP::Analyse
89 BOOST_TEST( calc.GetParameter( TCP::EPSILONR ) == 4.4 );
90 BOOST_TEST( calc.GetParameter( TCP::TAND ) == 0.02 );
91}
92
93
94// FR-4 microstrip dielectric attenuation scales linearly with tan delta. At 10 GHz the DS
95// model raises tan d from 0.02 (spec @ 1 GHz) to ~0.020486, so alpha_d ratio should be
96// ~1.0243 within ~1%.
97BOOST_AUTO_TEST_CASE( MicrostripFR4DielectricLossShift )
98{
99 MICROSTRIP calc;
101
102 // CONSTANT baseline alpha_d
104 static_cast<double>( DIELECTRIC_MODEL::CONSTANT ) );
105 calc.Analyse();
106 const double atten_d_const = calc.GetParameter( TCP::ATTEN_DILECTRIC );
107
108 // DS mode alpha_d
111 static_cast<double>( DIELECTRIC_MODEL::DJORDJEVIC_SARKAR ) );
112 calc.Analyse();
113 const double atten_d_ds = calc.GetParameter( TCP::ATTEN_DILECTRIC );
114
115 BOOST_TEST_MESSAGE( "FR-4 microstrip 10 GHz: atten_d_const=" << atten_d_const
116 << " dB, atten_d_ds="
117 << atten_d_ds << " dB" );
118
119 BOOST_TEST( atten_d_const > 0.0 );
120 BOOST_TEST( atten_d_ds > 0.0 );
121
122 const double ratio = atten_d_ds / atten_d_const;
123
124 // DS raises tan d at 10 GHz (0.02 -> ~0.02049) but simultaneously lowers e_r (4.4 -> ~4.27).
125 // The Hammerstad / Kirschning-Jansen microstrip dielectric-loss formula combines both through
126 // e_r * (e_r_eff - 1) / ((e_r - 1) * sqrt(e_r_eff)), which partially compensates the tan-delta
127 // bump. Assert a small but clearly positive ratio (observed ~1.008 vs 1.000 CONSTANT) and
128 // bound it below the naive tan-delta-only ratio of 1.0243 that would apply to coax.
129 BOOST_TEST( ratio > 1.005 );
130 BOOST_TEST( ratio < 1.030 );
131}
132
133
134// Coax LOSS_DIELECTRIC is proportional to sqrt(epsR) * tan d. DS shifts both, so the loss
135// ratio between CONSTANT and DS at 10 GHz is sqrt(4.2709 / 4.4) * (0.020486 / 0.02) ~ 1.0094.
136BOOST_AUTO_TEST_CASE( CoaxFR4DispersionShift )
137{
138 COAX calc;
139 calc.SetParameter( TCP::EPSILONR, 4.4 );
140 calc.SetParameter( TCP::TAND, 0.02 );
141 calc.SetParameter( TCP::MUR, 1.0 );
142 calc.SetParameter( TCP::MURC, 1.0 );
143 calc.SetParameter( TCP::SIGMA, 5.8e7 );
144 calc.SetParameter( TCP::PHYS_DIAM_IN, 0.5e-3 );
145 calc.SetParameter( TCP::PHYS_DIAM_OUT, 1.8e-3 );
146 calc.SetParameter( TCP::PHYS_LEN, 100.0e-3 );
147 calc.SetParameter( TCP::FREQUENCY, 10.0e9 );
148
150 static_cast<double>( DIELECTRIC_MODEL::CONSTANT ) );
151 calc.Analyse();
152 const double z0_const = calc.GetParameter( TCP::Z0 );
153 const double loss_d_const = calc.GetParameter( TCP::LOSS_DIELECTRIC );
154
157 static_cast<double>( DIELECTRIC_MODEL::DJORDJEVIC_SARKAR ) );
158 calc.Analyse();
159 const double z0_ds = calc.GetParameter( TCP::Z0 );
160 const double loss_d_ds = calc.GetParameter( TCP::LOSS_DIELECTRIC );
161
162 BOOST_TEST_MESSAGE( "Coax 10 GHz: Z0_const=" << z0_const << " Z0_ds=" << z0_ds
163 << " loss_d_const=" << loss_d_const
164 << " loss_d_ds=" << loss_d_ds );
165
166 // Z0 rises because eps_r drops at 10 GHz. Z0 = ZF0 / (2 pi sqrt(eps_r)) * ln(Dout/Din).
167 BOOST_TEST( z0_ds > z0_const );
168 const double z0_ratio_expected = std::sqrt( 4.4 / 4.270924 );
169 BOOST_TEST( z0_ds / z0_const == z0_ratio_expected, boost::test_tools::tolerance( 0.002 ) );
170
171 // Loss is proportional to sqrt(eps_r) * tan d. Expected ratio 1.0094.
172 BOOST_TEST( loss_d_ds > loss_d_const );
173 const double loss_ratio_expected = std::sqrt( 4.270924 / 4.4 ) * ( 0.020486 / 0.02 );
174 BOOST_TEST( loss_d_ds / loss_d_const == loss_ratio_expected,
175 boost::test_tools::tolerance( 0.005 ) );
176
177 // Raw parameters must survive the swap-and-restore
178 BOOST_TEST( calc.GetParameter( TCP::EPSILONR ) == 4.4 );
179 BOOST_TEST( calc.GetParameter( TCP::TAND ) == 0.02 );
180}
181
182
183// Synthesize must size the cable against the dispersed permittivity, not eps_r_spec.
184// At 10 GHz on FR-4 spec'd at 1 GHz, eps_r drops from 4.4 to ~4.2709, which shrinks the
185// diameter ratio needed to hit a given Z0. Verify the DS-mode synth yields a smaller
186// outer diameter than the CONSTANT-mode synth for identical targets.
187BOOST_AUTO_TEST_CASE( CoaxFR4SynthesizeDispersion )
188{
189 auto configure = []( COAX& calc )
190 {
191 calc.SetParameter( TCP::EPSILONR, 4.4 );
192 calc.SetParameter( TCP::TAND, 0.02 );
193 calc.SetParameter( TCP::MUR, 1.0 );
194 calc.SetParameter( TCP::MURC, 1.0 );
195 calc.SetParameter( TCP::SIGMA, 5.8e7 );
196 calc.SetParameter( TCP::PHYS_DIAM_IN, 0.5e-3 );
197 calc.SetParameter( TCP::Z0, 50.0 );
198 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
199 calc.SetParameter( TCP::FREQUENCY, 10.0e9 );
200 };
201
202 COAX calcConst;
203 configure( calcConst );
206 static_cast<double>( DIELECTRIC_MODEL::CONSTANT ) );
208 const double dOut_const = calcConst.GetParameter( TCP::PHYS_DIAM_OUT );
209 const double len_const = calcConst.GetParameter( TCP::PHYS_LEN );
210
211 COAX calcDs;
212 configure( calcDs );
214 calcDs.SetParameter( TCP::EPSILONR_SPEC_FREQ, 1.0e9 );
216 static_cast<double>( DIELECTRIC_MODEL::DJORDJEVIC_SARKAR ) );
218 const double dOut_ds = calcDs.GetParameter( TCP::PHYS_DIAM_OUT );
219 const double len_ds = calcDs.GetParameter( TCP::PHYS_LEN );
220
221 BOOST_TEST_MESSAGE( "Coax synth 10 GHz: Dout_const=" << dOut_const
222 << " Dout_ds=" << dOut_ds
223 << " len_const=" << len_const
224 << " len_ds=" << len_ds );
225
226 // Dout = Din * exp(Z0 * sqrt(eps_r) / ZF0 * 2 pi). Lower eps_r at 10 GHz shrinks
227 // the exponent, so DS-mode Dout sits below the CONSTANT-mode Dout for identical
228 // targets (Din, Z0, f).
229 BOOST_TEST( dOut_ds < dOut_const );
230 // Lower eps_r raises phase velocity => longer guided wavelength => longer physical
231 // length for the same ANG_L.
232 BOOST_TEST( len_ds > len_const );
233
234 // Raw EPSILONR / TAND must survive the synth pipeline.
235 BOOST_TEST( calcDs.GetParameter( TCP::EPSILONR ) == 4.4 );
236 BOOST_TEST( calcDs.GetParameter( TCP::TAND ) == 0.02 );
237}
238
239
240// Rectangular waveguide synthesis must also use dispersed eps_r. At low dielectric
241// fill (eps_r ~ 1.0006 for PTFE foam) this matters little, but for an eps_r=4.4 FR-4
242// fill the dispersion shift is comparable to the microstrip case. Verify the synthesized
243// broad-wall width differs between CONSTANT and DS modes and that raw params are restored.
244BOOST_AUTO_TEST_CASE( RectWaveguideFR4SynthesizeDispersion )
245{
246 auto configure = []( RECTWAVEGUIDE& calc )
247 {
248 calc.SetParameter( TCP::EPSILONR, 4.4 );
249 calc.SetParameter( TCP::TAND, 0.02 );
250 calc.SetParameter( TCP::MUR, 1.0 );
251 calc.SetParameter( TCP::MURC, 1.0 );
252 calc.SetParameter( TCP::SIGMA, 5.8e7 );
253 calc.SetParameter( TCP::PHYS_S, 5.0e-3 );
254 calc.SetParameter( TCP::Z0, 400.0 );
255 calc.SetParameter( TCP::ANG_L, M_PI / 2.0 );
256 calc.SetParameter( TCP::FREQUENCY, 10.0e9 );
257 };
258
259 RECTWAVEGUIDE calcConst;
260 configure( calcConst );
262 static_cast<double>( DIELECTRIC_MODEL::CONSTANT ) );
264 const double a_const = calcConst.GetParameter( TCP::PHYS_WIDTH );
265 const double len_const = calcConst.GetParameter( TCP::PHYS_LEN );
266
267 RECTWAVEGUIDE calcDs;
268 configure( calcDs );
269 calcDs.SetParameter( TCP::EPSILONR_SPEC_FREQ, 1.0e9 );
271 static_cast<double>( DIELECTRIC_MODEL::DJORDJEVIC_SARKAR ) );
273 const double a_ds = calcDs.GetParameter( TCP::PHYS_WIDTH );
274 const double len_ds = calcDs.GetParameter( TCP::PHYS_LEN );
275
276 BOOST_TEST_MESSAGE( "Rectwg synth 10 GHz: a_const=" << a_const << " a_ds=" << a_ds
277 << " len_const=" << len_const
278 << " len_ds=" << len_ds );
279
280 BOOST_TEST( std::isfinite( a_const ) );
281 BOOST_TEST( a_const > 0.0 );
282 BOOST_TEST( std::isfinite( a_ds ) );
283 BOOST_TEST( a_ds > 0.0 );
284 BOOST_TEST( a_ds != a_const );
285 BOOST_TEST( len_ds != len_const );
286
287 BOOST_TEST( calcDs.GetParameter( TCP::EPSILONR ) == 4.4 );
288 BOOST_TEST( calcDs.GetParameter( TCP::TAND ) == 0.02 );
289}
290
291
Coaxial transmission line calculation (TEM mode).
void SetSynthesizeTarget(TRANSLINE_PARAMETERS aTarget) override
Choose which geometry parameter will be solved for during synthesis.
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.
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.
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.
TRANSLINE_PARAMETERS TCP
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
static void configureFR4Microstrip(MICROSTRIP &aCalc)
BOOST_AUTO_TEST_CASE(MicrostripFR4Z0Shift)
BOOST_TEST(contains==c.ExpectedContains)
BOOST_AUTO_TEST_SUITE_END()
BOOST_TEST_MESSAGE("\n=== Real-World Polygon PIP Benchmark ===\n"<< formatTable(table))
#define M_PI
TRANSLINE_PARAMETERS
All possible parameters used (as inputs or outputs) by the transmission line calculations.