KiCad PCB EDA Suite
Loading...
Searching...
No Matches
transline_calculation_base.cpp
Go to the documentation of this file.
1/*
2 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this package; see the file COPYING. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20#include <stdexcept>
21#include <utility>
22
25
26
28namespace TC = TRANSLINE_CALCULATIONS;
29
30
31void TRANSLINE_CALCULATION_BASE::InitProperties( const std::initializer_list<TRANSLINE_PARAMETERS>& aParams )
32{
33 for( const TRANSLINE_PARAMETERS& param : aParams )
34 m_parameters[param] = 0.0;
35}
36
37
38std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>&
44
45
46std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>&
52
53
55 const TRANSLINE_STATUS aStatus )
56{
57 m_analysisStatus[aParam] = { aValue, aStatus };
58}
59
60
62 const TRANSLINE_STATUS aStatus )
63{
64 m_synthesisStatus[aParam] = { aValue, aStatus };
65}
66
67
69 const TRANSLINE_PARAMETERS aMeasure, bool aRecalculateLength )
70{
71 double& var = GetParameterRef( aOptimise );
72 double& Z0_param = GetParameterRef( aMeasure );
73 double& ANG_L_param = GetParameterRef( TCP::ANG_L );
74
75 if( !std::isfinite( Z0_param ) )
76 {
77 var = NAN;
78 return false;
79 }
80
81 if( ( !std::isfinite( var ) ) || ( var == 0 ) )
82 var = 0.001;
83
84 /* required value of Z0 */
85 double Z0_dest = Z0_param;
86
87 /* required value of angl_l */
88 double angl_l_dest = ANG_L_param;
89
90 /* Newton's method */
91 int iteration = 0;
92
93 /* compute parameters */
94 Analyse();
95 double Z0_current = Z0_param;
96
97 double error = fabs( Z0_dest - Z0_current );
98
99 while( error > m_maxError )
100 {
101 iteration++;
102 double increment = var / 100.0;
103 var += increment;
104
105 /* compute parameters */
106 Analyse();
107 double Z0_result = Z0_param;
108
109 // f(w(n)) = Z0 - Z0(w(n))
110 // f'(w(n)) = -f'(Z0(w(n)))
111 // f'(Z0(w(n))) = (Z0(w(n)) - Z0(w(n+delw))/delw
112 // w(n+1) = w(n) - f(w(n))/f'(w(n))
113 double slope = ( Z0_result - Z0_current ) / increment;
114 slope = ( Z0_dest - Z0_current ) / slope - increment;
115 var += slope;
116
117 if( var <= 0.0 )
118 var = increment;
119
120 /* find new error */
121 /* compute parameters */
122 Analyse();
123 Z0_current = Z0_param;
124 error = fabs( Z0_dest - Z0_current );
125
126 if( iteration > 250 )
127 break;
128 }
129
130 /* Compute one last time, but with correct length */
131 if( aRecalculateLength )
132 {
133 Z0_param = Z0_dest;
134 ANG_L_param = angl_l_dest;
136 * ANG_L_param / 2.0 / M_PI ); /* in m */
137 Analyse();
138
139 /* Restore parameters */
140 Z0_param = Z0_dest;
141 ANG_L_param = angl_l_dest;
143 * ANG_L_param / 2.0 / M_PI ); /* in m */
144 }
145
146 return error <= m_maxError;
147}
148
149
151{
152 double depth = 1.0
155 return depth;
156}
157
158
159double TRANSLINE_CALCULATION_BASE::UnitPropagationDelay( const double aEpsilonEff )
160{
161 return std::sqrt( aEpsilonEff ) * ( 1.0e10 / 2.99e8 );
162}
163
164
166{
167 const auto selected = static_cast<int>( GetParameter( TCP::DIELECTRIC_MODEL_SEL ) );
168
169 if( selected != static_cast<int>( DIELECTRIC_MODEL::DJORDJEVIC_SARKAR ) )
170 {
171 m_dsModel.reset();
172 return;
173 }
174
175 const double epsRSpec = GetParameter( TCP::EPSILONR );
176 const double tanDSpec = GetParameter( TCP::TAND );
177 const double fSpec = GetParameter( TCP::EPSILONR_SPEC_FREQ );
178
179 // User-supplied spec frequency must be positive, otherwise fall back to CONSTANT.
180 if( !std::isfinite( fSpec ) || fSpec <= 0.0 )
181 {
182 m_dsModel.reset();
183 return;
184 }
185
186 try
187 {
189 ds.Fit( epsRSpec, tanDSpec, fSpec );
190 m_dsModel.emplace( std::move( ds ) );
191 }
192 catch( const std::invalid_argument& )
193 {
194 m_dsModel.reset();
195 }
196}
197
198
200{
201 if( m_dsModel )
202 return m_dsModel->EpsilonRealAt( aF );
203
204 return GetParameter( TCP::EPSILONR );
205}
206
207
209{
210 if( m_dsModel )
211 return m_dsModel->TanDeltaAt( aF );
212
213 return GetParameter( TCP::TAND );
214}
215
216
217std::pair<double, double> TRANSLINE_CALCULATION_BASE::EllipticIntegral( const double arg )
218{
219 static constexpr double NR_EPSI = 2.2204460492503131e-16;
220 int iMax = 16;
221
222 double k = 0.0, e = 0.0;
223
224 if( arg == 1.0 )
225 {
226 k = INFINITY; // infinite
227 e = 0;
228 }
229 else if( std::isinf( arg ) && arg < 0 )
230 {
231 k = 0;
232 e = INFINITY; // infinite
233 }
234 else
235 {
236 double a, b, c, fr, s, fk = 1, fe = 1, t, da = arg;
237 int i;
238
239 if( arg < 0 )
240 {
241 fk = 1 / sqrt( 1 - arg );
242 fe = sqrt( 1 - arg );
243 da = -arg / ( 1 - arg );
244 }
245
246 a = 1;
247 b = sqrt( 1 - da );
248 c = sqrt( da );
249 fr = 0.5;
250 s = fr * c * c;
251
252 for( i = 0; i < iMax; i++ )
253 {
254 t = ( a + b ) / 2;
255 c = ( a - b ) / 2;
256 b = sqrt( a * b );
257 a = t;
258 fr *= 2;
259 s += fr * c * c;
260
261 if( c / a < NR_EPSI )
262 break;
263 }
264
265 if( i >= iMax )
266 {
267 k = 0;
268 e = 0;
269 }
270 else
271 {
272 k = M_PI_2 / a;
273 e = M_PI_2 * ( 1 - s ) / a;
274 if( arg < 0 )
275 {
276 k *= fk;
277 e *= fe;
278 }
279 }
280 }
281
282 return { k, e };
283}
Kramers-Kronig-consistent wideband dielectric model after Djordjevic et al.
void Fit(double aEpsRSpec, double aTanDSpec, double aFSpec, double aF1=1.0e3, double aF2=1.0e12)
Fit the model from a single (epsR, tan delta) datapoint at f_spec.
double GetDispersedEpsilonR(double aF) const
Dispersed permittivity at aF. Returns raw EPSILONR when the model is inactive.
double GetDispersedTanDelta(double aF) const
Dispersed loss tangent at aF. Returns raw TAND when the model is inactive.
std::unordered_map< TRANSLINE_PARAMETERS, std::pair< double, TRANSLINE_STATUS > > & GetSynthesisResults()
Gets the output parameters following synthesis.
virtual void SetAnalysisResults()=0
Sets values in the output analysis results structure.
virtual void SetSynthesisResults()=0
Sets values in the output synthesis results structure.
double GetParameter(const TRANSLINE_PARAMETERS aParam) const
Gets the given calculation property.
void InitProperties(const std::initializer_list< TRANSLINE_PARAMETERS > &aParams)
Initialises the properties used (as inputs or outputs) by the calculation.
std::optional< DIELECTRIC_DJORDJEVIC_SARKAR > m_dsModel
Fitted Djordjevic-Sarkar model. Empty unless DIELECTRIC_MODEL_SEL selects it.
static std::pair< double, double > EllipticIntegral(double arg)
Computes the complete elliptic integral of first kind K() and the second kind E() using the arithmeti...
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.
static constexpr double m_maxError
The maximum error for Z0 optimisations.
double SkinDepth() const
Calculate skin depth.
virtual void Analyse()=0
Analyses the transmission line using the current parameter set.
double & GetParameterRef(const TRANSLINE_PARAMETERS aParam)
Adds a constant to the given parameter.
std::unordered_map< TRANSLINE_PARAMETERS, double > m_parameters
All input and output properties used by the calculation.
bool MinimiseZ0Error1D(TRANSLINE_PARAMETERS aOptimise, TRANSLINE_PARAMETERS aMeasure, bool aRecalculateLength=false)
minimizeZ0Error1D
void SetAnalysisResult(TRANSLINE_PARAMETERS aParam, const double aValue, const TRANSLINE_STATUS aStatus=TRANSLINE_STATUS::OK)
Sets an analysis result.
std::unordered_map< TRANSLINE_PARAMETERS, std::pair< double, TRANSLINE_STATUS > > m_synthesisStatus
Synthesis results.
static double UnitPropagationDelay(double aEpsilonEff)
Calculates the unit propagation delay (ps/cm) for the given effective permittivity.
std::unordered_map< TRANSLINE_PARAMETERS, std::pair< double, TRANSLINE_STATUS > > & GetAnalysisResults()
Gets the output parameters following analysis.
std::unordered_map< TRANSLINE_PARAMETERS, std::pair< double, TRANSLINE_STATUS > > m_analysisStatus
Analysis results.
TRANSLINE_PARAMETERS TCP
#define M_PI
TRANSLINE_STATUS
Parameter status values.
TRANSLINE_PARAMETERS
All possible parameters used (as inputs or outputs) by the transmission line calculations.