KiCad PCB EDA Suite
transline.cpp
Go to the documentation of this file.
1 
2 /*
3  * TRANSLINE.cpp - base for a transmission line implementation
4  *
5  * Copyright (C) 2005 Stefan Jahn <stefan@lkcc.org>
6  * Modified for Kicad: 2018 jean-pierre.charras
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 
25 #include <cmath>
26 #include <limits>
27 
28 #include <wx/colour.h>
29 #include <wx/settings.h>
30 
31 #include "transline.h"
32 #include "units.h"
33 
34 #ifndef INFINITY
35 #define INFINITY std::numeric_limits<double>::infinity()
36 #endif
37 
38 
39 #ifndef M_PI_2
40 #define M_PI_2 ( M_PI / 2 )
41 #endif
42 
43 
44 // Functions to Read/Write parameters in pcb_calculator main frame:
45 // They are wrapper to actual functions, so all transline functions do not
46 // depend on Graphic User Interface
47 void SetPropertyInDialog( enum PRMS_ID aPrmId, double value );
48 
49 /* Puts the text into the given result line.
50 */
51 void SetResultInDialog( int line, const char* text );
52 
53 /* print aValue into the given result line.
54 */
55 void SetResultInDialog( int aLineNumber, double aValue, const char* aText );
56 
57 /* Returns a named property value. */
58 double GetPropertyInDialog( enum PRMS_ID aPrmId );
59 
60 // Returns true if the param aPrmId is selected
61 // Has meaning only for params that have a radio button
62 bool IsSelectedInDialog( enum PRMS_ID aPrmId );
63 
69 void SetPropertyBgColorInDialog( enum PRMS_ID aPrmId, const KIGFX::COLOR4D* aCol );
70 
71 
72 /* Constructor creates a transmission line instance. */
74 {
75  m_parameters[MURC_PRM] = 1.0;
76  m_Name = nullptr;
77  ang_l = 0.0; // Electrical length in angle
78  len = 0.0; // length of line
79  er_eff = 1.0; // effective dielectric constant
80  Init();
81 }
82 
83 
84 /* Destructor destroys a transmission line instance. */
86 {
87 }
88 
89 
90 void TRANSLINE::Init( void )
91 {
92  wxColour wxcol = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
93  okCol = KIGFX::COLOR4D( wxcol );
94  okCol.r = wxcol.Red() / 255.0;
95  okCol.g = wxcol.Green() / 255.0;
96  okCol.b = wxcol.Blue() / 255.0;
97  int i;
98  // Initialize these variables mainly to avoid warnings from a static analyzer
99  for( i = 0; i < EXTRA_PRMS_COUNT; ++i )
100  {
101  m_parameters[i] = 0;
102  }
103 }
104 
105 
106 /* Sets a named property to the given value, access through the
107  * application.
108  */
109 void TRANSLINE::setProperty( enum PRMS_ID aPrmId, double value )
110 {
111  SetPropertyInDialog( aPrmId, value );
112 }
113 
114 
115 /*
116  *Returns true if the param aPrmId is selected
117  * Has meaning only for params that have a radio button
118  */
119 bool TRANSLINE::isSelected( enum PRMS_ID aPrmId )
120 {
121  return IsSelectedInDialog( aPrmId );
122 }
123 
124 
125 /* Puts the text into the given result line.
126 */
127 void TRANSLINE::setResult( int line, const char* text )
128 {
129  SetResultInDialog( line, text );
130 }
131 void TRANSLINE::setResult( int line, double value, const char* text )
132 {
133  SetResultInDialog( line, value, text );
134 }
135 
136 
137 /* Returns a property value. */
138 double TRANSLINE::getProperty( enum PRMS_ID aPrmId )
139 {
140  return GetPropertyInDialog( aPrmId );
141 }
142 
148 {
149  int i;
150  for( i = 0; i < DUMMY_PRM; ++i )
151  {
152  m_parameters[i] = getProperty( (PRMS_ID) i );
154  }
158 }
165 {
166  // Do not check for values that are results of analyzing / synthesizing
167  // Do not check for transline specific incompatibilities ( like " conductor height should be lesser than dielectric height")
168  if( !std::isfinite( m_parameters[EPSILONR_PRM] ) || m_parameters[EPSILONR_PRM] <= 0 )
170 
171  if( !std::isfinite( m_parameters[TAND_PRM] ) || m_parameters[TAND_PRM] < 0 )
173 
174  if( !std::isfinite( m_parameters[RHO_PRM] ) || m_parameters[RHO_PRM] < 0 )
176 
177  if( !std::isfinite( m_parameters[H_PRM] ) || m_parameters[H_PRM] < 0 )
179 
180  if( !std::isfinite( m_parameters[TWISTEDPAIR_TWIST_PRM] )
183 
184  if( !std::isfinite( m_parameters[STRIPLINE_A_PRM] ) || m_parameters[STRIPLINE_A_PRM] <= 0 )
186 
187  if( !std::isfinite( m_parameters[H_T_PRM] ) || m_parameters[H_T_PRM] <= 0 )
189 
190  // How can we check ROUGH_PRM ?
191 
192  if( !std::isfinite( m_parameters[MUR_PRM] ) || m_parameters[MUR_PRM] < 0 )
194 
195  if( !std::isfinite( m_parameters[TWISTEDPAIR_EPSILONR_ENV_PRM] )
198 
199  if( !std::isfinite( m_parameters[MURC_PRM] ) || m_parameters[MURC_PRM] < 0 )
201 
202  if( !std::isfinite( m_parameters[FREQUENCY_PRM] ) || m_parameters[FREQUENCY_PRM] <= 0 )
204 }
205 
207 {
208  getProperties();
209  checkProperties();
210  calcAnalyze();
211  showAnalyze();
212  show_results();
213 }
214 
216 {
217  getProperties();
218  checkProperties();
219  calcSynthesize();
220  showSynthesize();
221  show_results();
222 }
223 
224 
231 #include <cstdio>
233 {
234  double depth;
235  depth = 1.0
236  / sqrt( M_PI * m_parameters[FREQUENCY_PRM] * m_parameters[MURC_PRM] * MU0
237  * m_parameters[SIGMA_PRM] );
238  return depth;
239 }
240 
241 
242 /* *****************************************************************
243 ********** **********
244 ********** mathematical functions **********
245 ********** **********
246 ***************************************************************** */
247 
248 #define NR_EPSI 2.2204460492503131e-16
249 
250 /* The function computes the complete elliptic integral of first kind
251  * K() and the second kind E() using the arithmetic-geometric mean
252  * algorithm (AGM) by Abramowitz and Stegun.
253  */
254 void TRANSLINE::ellipke( double arg, double& k, double& e )
255 {
256  int iMax = 16;
257 
258  if( arg == 1.0 )
259  {
260  k = INFINITY; // infinite
261  e = 0;
262  }
263  else if( std::isinf( arg ) && arg < 0 )
264  {
265  k = 0;
266  e = INFINITY; // infinite
267  }
268  else
269  {
270  double a, b, c, fr, s, fk = 1, fe = 1, t, da = arg;
271  int i;
272  if( arg < 0 )
273  {
274  fk = 1 / sqrt( 1 - arg );
275  fe = sqrt( 1 - arg );
276  da = -arg / ( 1 - arg );
277  }
278  a = 1;
279  b = sqrt( 1 - da );
280  c = sqrt( da );
281  fr = 0.5;
282  s = fr * c * c;
283  for( i = 0; i < iMax; i++ )
284  {
285  t = ( a + b ) / 2;
286  c = ( a - b ) / 2;
287  b = sqrt( a * b );
288  a = t;
289  fr *= 2;
290  s += fr * c * c;
291  if( c / a < NR_EPSI )
292  break;
293  }
294 
295  if( i >= iMax )
296  {
297  k = 0;
298  e = 0;
299  }
300  else
301  {
302  k = M_PI_2 / a;
303  e = M_PI_2 * ( 1 - s ) / a;
304  if( arg < 0 )
305  {
306  k *= fk;
307  e *= fe;
308  }
309  }
310  }
311 }
312 
313 
314 /* We need to know only K(k), and if possible KISS. */
315 double TRANSLINE::ellipk( double k )
316 {
317  double r, lost;
318 
319  ellipke( k, r, lost );
320  return r;
321 }
322 
323 #define MAX_ERROR 0.000001
324 
340 bool TRANSLINE::minimizeZ0Error1D( double* aVar )
341 {
342  double Z0_dest, Z0_current, Z0_result, angl_l_dest, increment, slope, error;
343  int iteration;
344 
345  if( !std::isfinite( m_parameters[Z0_PRM] ) )
346  {
347  *aVar = NAN;
348  return false;
349  }
350 
351  if( ( !std::isfinite( *aVar ) ) || ( *aVar == 0 ) )
352  {
353  *aVar = 0.001;
354  }
355 
356  /* required value of Z0 */
357  Z0_dest = m_parameters[Z0_PRM];
358 
359  /* required value of angl_l */
360  angl_l_dest = m_parameters[ANG_L_PRM];
361 
362  /* Newton's method */
363  iteration = 0;
364 
365  /* compute parameters */
366  calcAnalyze();
367  Z0_current = m_parameters[Z0_PRM];
368 
369  error = fabs( Z0_dest - Z0_current );
370 
371  while( error > MAX_ERROR )
372  {
373  iteration++;
374  increment = *aVar / 100.0;
375  *aVar += increment;
376  /* compute parameters */
377  calcAnalyze();
378  Z0_result = m_parameters[Z0_PRM];
379  /* f(w(n)) = Z0 - Z0(w(n)) */
380  /* f'(w(n)) = -f'(Z0(w(n))) */
381  /* f'(Z0(w(n))) = (Z0(w(n)) - Z0(w(n+delw))/delw */
382  /* w(n+1) = w(n) - f(w(n))/f'(w(n)) */
383  slope = ( Z0_result - Z0_current ) / increment;
384  slope = ( Z0_dest - Z0_current ) / slope - increment;
385  *aVar += slope;
386  if( *aVar <= 0.0 )
387  *aVar = increment;
388  /* find new error */
389  /* compute parameters */
390  calcAnalyze();
391  Z0_current = m_parameters[Z0_PRM];
392  error = fabs( Z0_dest - Z0_current );
393 
394  if( iteration > 100 )
395  break;
396  }
397 
398  /* Compute one last time, but with correct length */
399  m_parameters[Z0_PRM] = Z0_dest;
400  m_parameters[ANG_L_PRM] = angl_l_dest;
403  / 2.0 / M_PI; /* in m */
404  calcAnalyze();
405 
406  /* Restore parameters */
407  m_parameters[Z0_PRM] = Z0_dest;
408  m_parameters[ANG_L_PRM] = angl_l_dest;
411  / 2.0 / M_PI; /* in m */
412  return error <= MAX_ERROR;
413 }
426 void TRANSLINE::setErrorLevel( PRMS_ID aP, char aErrorLevel )
427 {
428  switch( aErrorLevel )
429  {
430  case( TRANSLINE_WARNING ):
432  break;
433  case( TRANSLINE_ERROR ):
435  break;
436  default:
438  break;
439  }
440 }
bool isSelected(enum PRMS_ID aPrmId)
Definition: transline.cpp:119
double GetPropertyInDialog(enum PRMS_ID aPrmId)
virtual void calcAnalyze()
Computation for analysis.
Definition: transline.h:100
bool IsSelectedInDialog(enum PRMS_ID aPrmId)
bool minimizeZ0Error1D(double *)
@function minimizeZ0Error1D
Definition: transline.cpp:340
void SetResultInDialog(int line, const char *text)
void Init()
Definition: transline.cpp:90
#define MAX_ERROR
Definition: transline.cpp:323
double ang_l
Definition: transline.h:122
double er_eff
Definition: transline.h:121
#define MU0
Definition: units.h:62
virtual ~TRANSLINE()
Definition: transline.cpp:85
#define M_PI_2
Definition: transline.cpp:40
void setResult(int, double, const char *)
Definition: transline.cpp:131
void setProperty(enum PRMS_ID aPrmId, double aValue)
Definition: transline.cpp:109
double g
Green component.
Definition: color4d.h:364
virtual void calcSynthesize()
Computation for synthesis.
Definition: transline.h:103
void checkProperties(void)
@function checkProperties
Definition: transline.cpp:164
virtual void showSynthesize()
Shows analysis results and checks for errors / warnings.
Definition: transline.h:109
double b
Blue component.
Definition: color4d.h:365
double ellipk(double)
Definition: transline.cpp:315
#define NR_EPSI
Definition: transline.cpp:248
virtual void show_results()
Shows results.
Definition: transline.h:112
void SetPropertyInDialog(enum PRMS_ID aPrmId, double value)
void analyze()
Definition: transline.cpp:206
void SetPropertyBgColorInDialog(enum PRMS_ID aPrmId, const KIGFX::COLOR4D *aCol)
Function SetPropertyBgColorInDialog Set the background color of a parameter.
double m_parameters[EXTRA_PRMS_COUNT]
Definition: transline.h:119
PRMS_ID
Definition: transline.h:36
KIGFX::COLOR4D okCol
Definition: transline.h:116
virtual void showAnalyze()
Shows synthesis results and checks for errors / warnings.
Definition: transline.h:106
double getProperty(enum PRMS_ID aPrmId)
Definition: transline.cpp:138
void getProperties(void)
@function getProperties
Definition: transline.cpp:147
KIGFX::COLOR4D errCol
Definition: transline.h:114
#define INFINITY
Definition: transline.cpp:35
double len
Definition: transline.h:120
const char * m_Name
Definition: transline.h:84
#define C0
Definition: units.h:63
#define TRANSLINE_ERROR
Definition: transline.h:31
KIGFX::COLOR4D warnCol
Definition: transline.h:115
#define TRANSLINE_OK
Definition: transline.h:29
virtual void synthesize()
Definition: transline.cpp:215
double r
Red component.
Definition: color4d.h:363
void ellipke(double, double &, double &)
Definition: transline.cpp:254
#define TRANSLINE_WARNING
Definition: transline.h:30
double skin_depth()
@function skin_depth calculate skin depth
Definition: transline.cpp:232
void setErrorLevel(PRMS_ID, char)
@function setErrorLevel
Definition: transline.cpp:426
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103