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