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; see the file COPYING. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 */
23
24#include <cstdio>
25
28
29
30namespace TC = TRANSLINE_CALCULATIONS;
32
33
34// Formulas throughout this file follow Pozar, "Microwave Engineering", 4th ed.,
35// Wiley 2012, §2.2 (TEM coaxial Z0, Table 2.1) and §3.5 (higher-order TE/TM modes).
36// Collin, "Foundations for Microwave Engineering", 2nd ed., McGraw-Hill 1992, §3.5
37// gives identical derivations.
38
39double COAX::AlphaD() const
40{
41 // Homogeneous-TEM dielectric loss alpha_d = pi*f*sqrt(eps_r)*tan(delta)/c (Pozar §2.7).
42 double ad = ( M_PI / TC::C0 ) * GetParameter( TCP::FREQUENCY ) * std::sqrt( GetParameter( TCP::EPSILONR ) )
44 return ad * TC::LOG2DB;
45}
46
47
48double COAX::AlphaC() const
49{
50 // Coax conductor loss alpha_c = (Rs/(2*eta))*(1/a + 1/b)/ln(b/a), from R = (Rs/(2*pi))*
51 // (1/a + 1/b) in Pozar Table 2.1 divided by 2*Z0. Surface resistance Rs = sqrt(pi*f*
52 // mu_c*mu_0/sigma). Expressed below in diameter form.
53 const double Rs = std::sqrt( M_PI * GetParameter( TCP::FREQUENCY ) * GetParameter( TCP::MURC ) * TC::MU0
55
56 const double Din = GetParameter( TCP::PHYS_DIAM_IN );
57 const double Dout = GetParameter( TCP::PHYS_DIAM_OUT );
58
59 double ac = std::sqrt( GetParameter( TCP::EPSILONR ) ) * ( ( 1.0 / Din ) + ( 1.0 / Dout ) )
60 / std::log( Dout / Din ) * ( Rs / TC::ZF0 );
61 return ac * TC::LOG2DB;
62}
63
64
66{
67 // Higher-order mode cutoffs. Exact kc values are roots of the Bessel cross-product
68 // transcendental (Pozar eq. 3.159); the forms below use the standard kc ~ 2/(a+b)
69 // approximation for TE11 quoted just below Pozar eq. (3.159) on p. 132.
70 // Wave velocity in the filling medium is c / sqrt(eps_r * mu_r), so every cutoff scales
71 // by sqrt(eps_r * mu_r) rather than sqrt(eps_r) alone.
72 // TE11 (dominant non-TEM): f_c = 2*c / (pi * sqrt(eps_r * mu_r) * (Din + Dout))
73 // TM_0m: f_c = m*c / (sqrt(eps_r * mu_r) * (Dout - Din))
74 // TE_1m (m>=2): approx f_c(TE11) + (m-1)*c / (sqrt(eps_r * mu_r) * (Dout - Din))
75 const double epsr = GetParameter( TCP::EPSILONR );
76 const double mur = GetParameter( TCP::MUR );
77 const double Din = GetParameter( TCP::PHYS_DIAM_IN );
78 const double Dout = GetParameter( TCP::PHYS_DIAM_OUT );
79 const double freq = GetParameter( TCP::FREQUENCY );
80 const double sqrtMuEr = std::sqrt( epsr * mur );
81
82 const double fc_TE11 = ( 2.0 * TC::C0 ) / ( M_PI * sqrtMuEr * ( Din + Dout ) );
83 const double fc_step = TC::C0 / ( sqrtMuEr * ( Dout - Din ) );
84
86
87 m_teModes.clear();
88 m_tmModes.clear();
89
90 if( fc_TE11 <= freq )
91 {
92 m_teModes = "H(1,1) ";
93
94 for( int m = 2; m < 10; ++m )
95 {
96 const double fc = fc_TE11 + static_cast<double>( m - 1 ) * fc_step;
97
98 if( fc > freq )
99 break;
100
101 char buf[32];
102 std::snprintf( buf, sizeof( buf ), "H(1,%d) ", m );
103 m_teModes += buf;
104 }
105 }
106
107 for( int m = 1; m < 10; ++m )
108 {
109 const double fc = static_cast<double>( m ) * fc_step;
110
111 if( fc > freq )
112 break;
113
114 char buf[32];
115 std::snprintf( buf, sizeof( buf ), "E(0,%d) ", m );
116 m_tmModes += buf;
117 }
118}
119
120
122{
124
125 const double freq = GetParameter( TCP::FREQUENCY );
126 const double rawEpsR = GetParameter( TCP::EPSILONR );
127 const double rawTanD = GetParameter( TCP::TAND );
128
129 // Overlay dispersed values so helpers reading EPSILONR / TAND via GetParameter
130 // pick them up. Raw inputs are restored before return.
133
135
136 const double Din = GetParameter( TCP::PHYS_DIAM_IN );
137 const double Dout = GetParameter( TCP::PHYS_DIAM_OUT );
138 const double epsr = GetParameter( TCP::EPSILONR );
139 const double mur = GetParameter( TCP::MUR );
140 const double len = GetParameter( TCP::PHYS_LEN );
141
142 // Coax Z0 = eta*ln(b/a)/(2*pi) with eta = eta_0/sqrt(eps_r) (Pozar eq. 2.32).
143 SetParameter( TCP::Z0, ( TC::ZF0 / ( 2.0 * M_PI * std::sqrt( epsr ) ) ) * std::log( Dout / Din ) );
144
145 const double lambda_g = ( TC::C0 / freq ) / std::sqrt( epsr * mur );
146
147 SetParameter( TCP::ANG_L, ( 2.0 * M_PI * len ) / lambda_g );
148
151
153
154 SetParameter( TCP::EPSILONR, rawEpsR );
155 SetParameter( TCP::TAND, rawTanD );
156}
157
158
159bool COAX::Synthesize( const SYNTHESIZE_OPTS /* aOpts */ )
160{
161 // Fit the DS model before sizing so the follow-up Analyse() sees the same eps_r.
163
164 const double mur = GetParameter( TCP::MUR );
165 const double freq = GetParameter( TCP::FREQUENCY );
166 const double Z0 = GetParameter( TCP::Z0 );
167 const double angL = GetParameter( TCP::ANG_L );
168 const double epsr = GetDispersedEpsilonR( freq );
169
170 const double k = Z0 * std::sqrt( epsr ) / TC::ZF0 * 2.0 * M_PI;
171
176
177 const double lambda_g = ( TC::C0 / freq ) / std::sqrt( epsr * mur );
178 SetParameter( TCP::PHYS_LEN, ( lambda_g * angL ) / ( 2.0 * M_PI ) );
179
180 // Re-run analysis so losses, skin depth, and mode cutoffs reflect the synthesized geometry.
181 Analyse();
182
183 // Restore user-supplied Z0 and ANG_L targets (Analyse overwrites them from the new geometry).
185 SetParameter( TCP::ANG_L, angL );
186
187 return true;
188}
189
190
192{
198
199 const double Z0 = GetParameter( TCP::Z0 );
200 const double angL = GetParameter( TCP::ANG_L );
201 const double len = GetParameter( TCP::PHYS_LEN );
202 const double Din = GetParameter( TCP::PHYS_DIAM_IN );
203 const double Dout = GetParameter( TCP::PHYS_DIAM_OUT );
204
205 const bool Z0_invalid = !std::isfinite( Z0 ) || Z0 < 0;
206 const bool angL_invalid = !std::isfinite( angL ) || angL < 0;
207 const bool len_invalid = !std::isfinite( len ) || len < 0;
208 const bool Din_invalid = !std::isfinite( Din ) || Din <= 0.0;
209 const bool Dout_invalid = !std::isfinite( Dout ) || Dout <= 0.0;
210 const bool geometry_invalid = Din >= Dout;
211
216 ( Din_invalid || geometry_invalid ) ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
218 ( Dout_invalid || geometry_invalid ) ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
219}
220
221
223{
229
230 const double Z0 = GetParameter( TCP::Z0 );
231 const double angL = GetParameter( TCP::ANG_L );
232 const double len = GetParameter( TCP::PHYS_LEN );
233 const double Din = GetParameter( TCP::PHYS_DIAM_IN );
234 const double Dout = GetParameter( TCP::PHYS_DIAM_OUT );
235
236 const bool Z0_invalid = !std::isfinite( Z0 ) || Z0 < 0;
237 const bool angL_invalid = !std::isfinite( angL ) || angL < 0;
238 const bool len_invalid = !std::isfinite( len ) || len < 0;
239 const bool Din_invalid = !std::isfinite( Din ) || Din <= 0.0;
240 const bool Dout_invalid = !std::isfinite( Dout ) || Dout <= 0.0;
241 const bool geometry_invalid = Din >= Dout;
242
248 : ( Dout_invalid ? TRANSLINE_STATUS::WARNING : TRANSLINE_STATUS::OK );
249
256 : Din_status );
260 : Dout_status );
261}
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.