KiCad PCB EDA Suite
Loading...
Searching...
No Matches
common/transline_calculations/coax.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2001 Gopal Narayanan <[email protected]>
3 * Copyright (C) 2002 Claudio Girardi <[email protected]>
4 * Copyright (C) 2005, 2006 Stefan Jahn <[email protected]>
5 * Modified for Kicad: 2018 Jean-Pierre Charras <jp.charras at wanadoo.fr>
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this package. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <cstdio>
23
26
27
28namespace TC = TRANSLINE_CALCULATIONS;
30
31
32// Formulas throughout this file follow Pozar, "Microwave Engineering", 4th ed.,
33// Wiley 2012, §2.2 (TEM coaxial Z0, Table 2.1) and §3.5 (higher-order TE/TM modes).
34// Collin, "Foundations for Microwave Engineering", 2nd ed., McGraw-Hill 1992, §3.5
35// gives identical derivations.
36
37double COAX::AlphaD() const
38{
39 // Homogeneous-TEM dielectric loss alpha_d = pi*f*sqrt(eps_r)*tan(delta)/c (Pozar §2.7).
40 double ad = ( M_PI / TC::C0 ) * GetParameter( TCP::FREQUENCY ) * std::sqrt( GetParameter( TCP::EPSILONR ) )
42 return ad * TC::LOG2DB;
43}
44
45
46double COAX::AlphaC() const
47{
48 // Coax conductor loss alpha_c = (Rs/(2*eta))*(1/a + 1/b)/ln(b/a), from R = (Rs/(2*pi))*
49 // (1/a + 1/b) in Pozar Table 2.1 divided by 2*Z0. Surface resistance Rs = sqrt(pi*f*
50 // mu_c*mu_0/sigma). Expressed below in diameter form.
51 const double Rs = std::sqrt( M_PI * GetParameter( TCP::FREQUENCY ) * GetParameter( TCP::MURC ) * TC::MU0
53
54 const double Din = GetParameter( TCP::PHYS_DIAM_IN );
55 const double Dout = GetParameter( TCP::PHYS_DIAM_OUT );
56
57 double ac = std::sqrt( GetParameter( TCP::EPSILONR ) ) * ( ( 1.0 / Din ) + ( 1.0 / Dout ) )
58 / std::log( Dout / Din ) * ( Rs / TC::ZF0 );
59 return ac * TC::LOG2DB;
60}
61
62
64{
65 // Higher-order mode cutoffs. Exact kc values are roots of the Bessel cross-product
66 // transcendental (Pozar eq. 3.159); the forms below use the standard kc ~ 2/(a+b)
67 // approximation for TE11 quoted just below Pozar eq. (3.159) on p. 132.
68 // Wave velocity in the filling medium is c / sqrt(eps_r * mu_r), so every cutoff scales
69 // by sqrt(eps_r * mu_r) rather than sqrt(eps_r) alone.
70 // TE11 (dominant non-TEM): f_c = 2*c / (pi * sqrt(eps_r * mu_r) * (Din + Dout))
71 // TM_0m: f_c = m*c / (sqrt(eps_r * mu_r) * (Dout - Din))
72 // TE_1m (m>=2): approx f_c(TE11) + (m-1)*c / (sqrt(eps_r * mu_r) * (Dout - Din))
73 const double epsr = GetParameter( TCP::EPSILONR );
74 const double mur = GetParameter( TCP::MUR );
75 const double Din = GetParameter( TCP::PHYS_DIAM_IN );
76 const double Dout = GetParameter( TCP::PHYS_DIAM_OUT );
77 const double freq = GetParameter( TCP::FREQUENCY );
78 const double sqrtMuEr = std::sqrt( epsr * mur );
79
80 const double fc_TE11 = ( 2.0 * TC::C0 ) / ( M_PI * sqrtMuEr * ( Din + Dout ) );
81 const double fc_step = TC::C0 / ( sqrtMuEr * ( Dout - Din ) );
82
84
85 m_teModes.clear();
86 m_tmModes.clear();
87
88 if( fc_TE11 <= freq )
89 {
90 m_teModes = "H(1,1) ";
91
92 for( int m = 2; m < 10; ++m )
93 {
94 const double fc = fc_TE11 + static_cast<double>( m - 1 ) * fc_step;
95
96 if( fc > freq )
97 break;
98
99 char buf[32];
100 std::snprintf( buf, sizeof( buf ), "H(1,%d) ", m );
101 m_teModes += buf;
102 }
103 }
104
105 for( int m = 1; m < 10; ++m )
106 {
107 const double fc = static_cast<double>( m ) * fc_step;
108
109 if( fc > freq )
110 break;
111
112 char buf[32];
113 std::snprintf( buf, sizeof( buf ), "E(0,%d) ", m );
114 m_tmModes += buf;
115 }
116}
117
118
120{
122
123 const double freq = GetParameter( TCP::FREQUENCY );
124 const double rawEpsR = GetParameter( TCP::EPSILONR );
125 const double rawTanD = GetParameter( TCP::TAND );
126
127 // Overlay dispersed values so helpers reading EPSILONR / TAND via GetParameter
128 // pick them up. Raw inputs are restored before return.
131
133
134 const double Din = GetParameter( TCP::PHYS_DIAM_IN );
135 const double Dout = GetParameter( TCP::PHYS_DIAM_OUT );
136 const double epsr = GetParameter( TCP::EPSILONR );
137 const double mur = GetParameter( TCP::MUR );
138 const double len = GetParameter( TCP::PHYS_LEN );
139
140 // Coax Z0 = eta*ln(b/a)/(2*pi) with eta = eta_0/sqrt(eps_r) (Pozar eq. 2.32).
141 SetParameter( TCP::Z0, ( TC::ZF0 / ( 2.0 * M_PI * std::sqrt( epsr ) ) ) * std::log( Dout / Din ) );
142
143 const double lambda_g = ( TC::C0 / freq ) / std::sqrt( epsr * mur );
144
145 SetParameter( TCP::ANG_L, ( 2.0 * M_PI * len ) / lambda_g );
146
149
151
152 SetParameter( TCP::EPSILONR, rawEpsR );
153 SetParameter( TCP::TAND, rawTanD );
154}
155
156
157bool COAX::Synthesize( const SYNTHESIZE_OPTS /* aOpts */ )
158{
159 // Fit the DS model before sizing so the follow-up Analyse() sees the same eps_r.
161
162 const double mur = GetParameter( TCP::MUR );
163 const double freq = GetParameter( TCP::FREQUENCY );
164 const double Z0 = GetParameter( TCP::Z0 );
165 const double angL = GetParameter( TCP::ANG_L );
166 const double epsr = GetDispersedEpsilonR( freq );
167
168 const double k = Z0 * std::sqrt( epsr ) / TC::ZF0 * 2.0 * M_PI;
169
174
175 const double lambda_g = ( TC::C0 / freq ) / std::sqrt( epsr * mur );
176 SetParameter( TCP::PHYS_LEN, ( lambda_g * angL ) / ( 2.0 * M_PI ) );
177
178 // Re-run analysis so losses, skin depth, and mode cutoffs reflect the synthesized geometry.
179 Analyse();
180
181 // Restore user-supplied Z0 and ANG_L targets (Analyse overwrites them from the new geometry).
183 SetParameter( TCP::ANG_L, angL );
184
185 return true;
186}
187
188
190{
196
197 const double Z0 = GetParameter( TCP::Z0 );
198 const double angL = GetParameter( TCP::ANG_L );
199 const double len = GetParameter( TCP::PHYS_LEN );
200 const double Din = GetParameter( TCP::PHYS_DIAM_IN );
201 const double Dout = GetParameter( TCP::PHYS_DIAM_OUT );
202
203 const bool Z0_invalid = !std::isfinite( Z0 ) || Z0 < 0;
204 const bool angL_invalid = !std::isfinite( angL ) || angL < 0;
205 const bool len_invalid = !std::isfinite( len ) || len < 0;
206 const bool Din_invalid = !std::isfinite( Din ) || Din <= 0.0;
207 const bool Dout_invalid = !std::isfinite( Dout ) || Dout <= 0.0;
208 const bool geometry_invalid = Din >= Dout;
209
214 ( Din_invalid || geometry_invalid ) ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
216 ( Dout_invalid || geometry_invalid ) ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
217}
218
219
221{
227
228 const double Z0 = GetParameter( TCP::Z0 );
229 const double angL = GetParameter( TCP::ANG_L );
230 const double len = GetParameter( TCP::PHYS_LEN );
231 const double Din = GetParameter( TCP::PHYS_DIAM_IN );
232 const double Dout = GetParameter( TCP::PHYS_DIAM_OUT );
233
234 const bool Z0_invalid = !std::isfinite( Z0 ) || Z0 < 0;
235 const bool angL_invalid = !std::isfinite( angL ) || angL < 0;
236 const bool len_invalid = !std::isfinite( len ) || len < 0;
237 const bool Din_invalid = !std::isfinite( Din ) || Din <= 0.0;
238 const bool Dout_invalid = !std::isfinite( Dout ) || Dout <= 0.0;
239 const bool geometry_invalid = Din >= Dout;
240
246 : ( Dout_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
247
254 : Din_status );
258 : Dout_status );
259}
std::string m_teModes
Cached TE_1m propagating-modes string produced by UpdateModeCutoffs.
void UpdateModeCutoffs()
Populates the TE / TM mode cutoff display strings and CUTOFF_FREQUENCY from current geometry.
void SetAnalysisResults() override
Sets the output values and status following analysis.
double AlphaD() const
Dielectric loss per unit length, in dB/m.
bool Synthesize(SYNTHESIZE_OPTS aOpts) override
Synthesize the cable geometry to match the given Z0 target.
std::string m_tmModes
Cached TM_0m propagating-modes string produced by UpdateModeCutoffs.
void Analyse() override
Analyse cable geometry parameters to output Z0, electrical length, losses and cutoffs.
void SetSynthesisResults() override
Sets the output values and status following synthesis.
double AlphaC() const
Conductor loss per unit length, in dB/m.
double GetDispersedEpsilonR(double aF) const
Dispersed permittivity at aF. Returns raw EPSILONR when the model is inactive.
TRANSLINE_PARAMETERS m_synthesizeTarget
Which geometry parameter is the unknown during synthesis (set by the UI)
double GetDispersedTanDelta(double aF) const
Dispersed loss tangent at aF. Returns raw TAND when the model is inactive.
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.
void SetSynthesisResult(TRANSLINE_PARAMETERS aParam, const double aValue, const TRANSLINE_STATUS aStatus=TRANSLINE_STATUS::OK)
Sets a synthesis result.
void UpdateDielectricModel()
Refit the Djordjevic-Sarkar model from the current parameter map.
double SkinDepth() const
Calculate skin depth.
void SetAnalysisResult(TRANSLINE_PARAMETERS aParam, const double aValue, const TRANSLINE_STATUS aStatus=TRANSLINE_STATUS::OK)
Sets an analysis result.
TRANSLINE_PARAMETERS TCP
#define M_PI
SYNTHESIZE_OPTS
Options for specifying synthesis inputs, targets, or strategies.
TRANSLINE_STATUS
Parameter status values.
TRANSLINE_PARAMETERS
All possible parameters used (as inputs or outputs) by the transmission line calculations.