kicad/pcb_calculator/transline/transline.cpp

209 lines
5.2 KiB
C++

/*
* TRANSLINE.cpp - base for a transmission line implementation
*
* Copyright (C) 2005 Stefan Jahn <stefan@lkcc.org>
* Modified for Kicad: 2018 jean-pierre.charras
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#include <cmath>
#include <limits>
#include <transline.h>
#include <units.h>
#ifndef INFINITY
#define INFINITY std::numeric_limits<double>::infinity()
#endif
#ifndef M_PI_2
#define M_PI_2 (M_PI/2)
#endif
// Functions to Read/Write parameters in pcb_calculator main frame:
// They are wrapper to actual functions, so all transline functions do not
// depend on Graphic User Interface
void SetPropertyInDialog( enum PRMS_ID aPrmId, double value );
/* Puts the text into the given result line.
*/
void SetResultInDialog( int line, const char* text );
/* print aValue into the given result line.
*/
void SetResultInDialog( int aLineNumber, double aValue, const char* aText );
/* Returns a named property value. */
double GetPropertyInDialog( enum PRMS_ID aPrmId );
// Returns true if the param aPrmId is selected
// Has meaning only for params that have a radio button
bool IsSelectedInDialog( enum PRMS_ID aPrmId );
/* Constructor creates a transmission line instance. */
TRANSLINE::TRANSLINE()
{
m_murC = 1.0;
m_Name = nullptr;
// Initialize these variables mainly to avoid warnings from a static analyzer
m_freq = 0.0; // Frequency of operation
er = 0.0; // dielectric constant
m_tand = 0.0; // Dielectric Loss Tangent
m_sigma = 0.0; // Conductivity of the metal
m_skindepth = 0.0; // Skin depth
}
/* Destructor destroys a transmission line instance. */
TRANSLINE::~TRANSLINE()
{
}
/* Sets a named property to the given value, access through the
* application.
*/
void TRANSLINE::setProperty( enum PRMS_ID aPrmId, double value )
{
SetPropertyInDialog( aPrmId, value );
}
/*
*Returns true if the param aPrmId is selected
* Has meaning only for params that have a radio button
*/
bool TRANSLINE::isSelected( enum PRMS_ID aPrmId )
{
return IsSelectedInDialog( aPrmId );
}
/* Puts the text into the given result line.
*/
void TRANSLINE::setResult( int line, const char* text )
{
SetResultInDialog( line, text );
}
void TRANSLINE::setResult( int line, double value, const char* text )
{
SetResultInDialog( line, value, text );
}
/* Returns a property value. */
double TRANSLINE::getProperty( enum PRMS_ID aPrmId )
{
return GetPropertyInDialog( aPrmId );
}
/*
* skin_depth - calculate skin depth
*/
#include <stdio.h>
double TRANSLINE::skin_depth()
{
double depth;
depth = 1.0 / sqrt( M_PI * m_freq * m_murC * MU0 * m_sigma );
return depth;
}
/* *****************************************************************
********** **********
********** mathematical functions **********
********** **********
***************************************************************** */
#define NR_EPSI 2.2204460492503131e-16
/* The function computes the complete elliptic integral of first kind
* K() and the second kind E() using the arithmetic-geometric mean
* algorithm (AGM) by Abramowitz and Stegun.
*/
void TRANSLINE::ellipke( double arg, double& k, double& e )
{
int iMax = 16;
if( arg == 1.0 )
{
k = INFINITY; // infinite
e = 0;
}
else if( std::isinf( arg ) && arg < 0 )
{
k = 0;
e = INFINITY; // infinite
}
else
{
double a, b, c, fr, s, fk = 1, fe = 1, t, da = arg;
int i;
if( arg < 0 )
{
fk = 1 / sqrt( 1 - arg );
fe = sqrt( 1 - arg );
da = -arg / (1 - arg);
}
a = 1;
b = sqrt( 1 - da );
c = sqrt( da );
fr = 0.5;
s = fr * c * c;
for( i = 0; i < iMax; i++ )
{
t = (a + b) / 2;
c = (a - b) / 2;
b = sqrt( a * b );
a = t;
fr *= 2;
s += fr * c * c;
if( c / a < NR_EPSI )
break;
}
if( i >= iMax )
{
k = 0; e = 0;
}
else
{
k = M_PI_2 / a;
e = M_PI_2 * (1 - s) / a;
if( arg < 0 )
{
k *= fk;
e *= fe;
}
}
}
}
/* We need to know only K(k), and if possible KISS. */
double TRANSLINE::ellipk( double k )
{
double r, lost;
ellipke( k, r, lost );
return r;
}