pcb_calculator : do not overwrite input parameters

Split the computing / displaying code into different functions
Add coloured warnings when a value is not finite / illogical .

Fixes https://gitlab.com/kicad/code/kicad/-/issues/1849
This commit is contained in:
Fabien Corona 2020-08-07 00:09:33 +00:00 committed by Seth Hillbrand
parent 0ff5dcee69
commit 8de6aa161f
20 changed files with 1803 additions and 1663 deletions

View File

@ -19,11 +19,12 @@
*/ */
#include <wx/app.h> #include <wx/app.h>
#include <wx/msgdlg.h> #include <wx/colour.h>
#include <wx/log.h> #include <wx/log.h>
#include <wx/msgdlg.h>
#include <pcb_calculator_frame_base.h>
#include <pcb_calculator.h> #include <pcb_calculator.h>
#include <pcb_calculator_frame_base.h>
#include <transline.h> #include <transline.h>
/* /*
@ -56,17 +57,25 @@ double DoubleFromString( const wxString& TextValue )
while( brk_point < buf.Len() ) while( brk_point < buf.Len() )
{ {
wxChar ch = buf[brk_point]; wxChar ch = buf[brk_point];
if( !( (ch >= '0' && ch <='9') || (ch == decimal_point) if( !( ( ch >= '0' && ch <= '9' ) || ( ch == decimal_point ) || ( ch == '-' )
|| (ch == '-') || (ch == '+') || (ch == 'e') || (ch == 'E') ) ) || ( ch == '+' ) || ( ch == 'e' ) || ( ch == 'E' ) ) )
{ {
break; break;
} }
++brk_point; ++brk_point;
} }
/* Extract the numeric part */ // Check for strings that cannot qualify as a number
buf.Left( brk_point ).ToDouble( &value ); if( brk_point == 0 )
{
return std::nan( "" );
}
/* Extract the numeric part */
if( !buf.Left( brk_point ).ToDouble( &value ) )
{
return std::nan( "" );
}
return value; return value;
} }
@ -76,15 +85,21 @@ double DoubleFromString( const wxString& TextValue )
// depend on Graphic User Interface // depend on Graphic User Interface
void SetPropertyInDialog( enum PRMS_ID aPrmId, double value ) void SetPropertyInDialog( enum PRMS_ID aPrmId, double value )
{ {
PCB_CALCULATOR_FRAME * frame = (PCB_CALCULATOR_FRAME *) wxTheApp->GetTopWindow(); PCB_CALCULATOR_FRAME* frame = (PCB_CALCULATOR_FRAME*) wxTheApp->GetTopWindow();
frame->SetPrmValue( aPrmId, value ); frame->SetPrmValue( aPrmId, value );
} }
void SetPropertyBgColorInDialog( enum PRMS_ID aPrmId, const KIGFX::COLOR4D* aCol )
{
PCB_CALCULATOR_FRAME* frame = (PCB_CALCULATOR_FRAME*) wxTheApp->GetTopWindow();
frame->SetPrmBgColor( aPrmId, aCol );
}
/* Puts the text into the given result line. /* Puts the text into the given result line.
*/ */
void SetResultInDialog( int line, const char* aText ) void SetResultInDialog( int line, const char* aText )
{ {
PCB_CALCULATOR_FRAME * frame = (PCB_CALCULATOR_FRAME *) wxTheApp->GetTopWindow(); PCB_CALCULATOR_FRAME* frame = (PCB_CALCULATOR_FRAME*) wxTheApp->GetTopWindow();
wxString msg = wxString::FromUTF8( aText ); wxString msg = wxString::FromUTF8( aText );
frame->SetResult( line, msg ); frame->SetResult( line, msg );
} }
@ -93,10 +108,10 @@ void SetResultInDialog( int line, const char* aText )
*/ */
void SetResultInDialog( int aLineNumber, double aValue, const char* aText ) void SetResultInDialog( int aLineNumber, double aValue, const char* aText )
{ {
PCB_CALCULATOR_FRAME * frame = (PCB_CALCULATOR_FRAME *) wxTheApp->GetTopWindow(); PCB_CALCULATOR_FRAME* frame = (PCB_CALCULATOR_FRAME*) wxTheApp->GetTopWindow();
wxString msg = wxString::FromUTF8( aText ); wxString msg = wxString::FromUTF8( aText );
wxString fullmsg; wxString fullmsg;
fullmsg.Printf( wxT("%g "), aValue ); fullmsg.Printf( wxT( "%g " ), aValue );
fullmsg += msg; fullmsg += msg;
frame->SetResult( aLineNumber, fullmsg ); frame->SetResult( aLineNumber, fullmsg );
} }
@ -104,7 +119,7 @@ void SetResultInDialog( int aLineNumber, double aValue, const char* aText )
/* Returns a named property value. */ /* Returns a named property value. */
double GetPropertyInDialog( enum PRMS_ID aPrmId ) double GetPropertyInDialog( enum PRMS_ID aPrmId )
{ {
PCB_CALCULATOR_FRAME * frame = (PCB_CALCULATOR_FRAME *) wxTheApp->GetTopWindow(); PCB_CALCULATOR_FRAME* frame = (PCB_CALCULATOR_FRAME*) wxTheApp->GetTopWindow();
return frame->GetPrmValue( aPrmId ); return frame->GetPrmValue( aPrmId );
} }
@ -112,7 +127,7 @@ double GetPropertyInDialog( enum PRMS_ID aPrmId )
// Has meaning only for params that have a radio button // Has meaning only for params that have a radio button
bool IsSelectedInDialog( enum PRMS_ID aPrmId ) bool IsSelectedInDialog( enum PRMS_ID aPrmId )
{ {
PCB_CALCULATOR_FRAME * frame = (PCB_CALCULATOR_FRAME *) wxTheApp->GetTopWindow(); PCB_CALCULATOR_FRAME* frame = (PCB_CALCULATOR_FRAME*) wxTheApp->GetTopWindow();
return frame->IsPrmSelected( aPrmId ); return frame->IsPrmSelected( aPrmId );
} }
@ -132,8 +147,6 @@ double PCB_CALCULATOR_FRAME::GetPrmValue( enum PRMS_ID aPrmId )
if( aPrmId == prm->m_Id ) if( aPrmId == prm->m_Id )
return prm->m_NormalizedValue; return prm->m_NormalizedValue;
} }
wxLogMessage( wxT("GetPrmValue: prm %d not found"), (int) aPrmId );
return 1.0; return 1.0;
} }
@ -149,19 +162,52 @@ void PCB_CALCULATOR_FRAME::SetPrmValue( enum PRMS_ID aPrmId, double aValue )
for( unsigned ii = 0; ii < tr_ident->GetPrmsCount(); ii++ ) for( unsigned ii = 0; ii < tr_ident->GetPrmsCount(); ii++ )
{ {
TRANSLINE_PRM* prm = tr_ident->GetPrm( ii ); TRANSLINE_PRM* prm = tr_ident->GetPrm( ii );
if( aPrmId == prm->m_Id ) if( aPrmId == prm->m_Id )
{ {
prm->m_Value = prm->m_NormalizedValue = aValue;
prm->m_NormalizedValue = aValue; prm->m_NormalizedValue = aValue;
prm->m_Value = prm->m_NormalizedValue * prm->ToUserUnit(); prm->m_Value = prm->m_NormalizedValue * prm->ToUserUnit();
wxString msg; wxString msg;
msg.Printf( wxT("%g"), prm->m_Value); msg.Printf( wxT( "%g" ), prm->m_Value );
((wxTextCtrl*)prm->m_ValueCtrl )->SetValue( msg ); ( (wxTextCtrl*) prm->m_ValueCtrl )->SetValue( msg );
return; return;
} }
} }
wxLogMessage( wxT( "GetPrmValue: prm %d not found" ), (int) aPrmId );
}
wxLogMessage( wxT("GetPrmValue: prm %d not found"), (int) aPrmId ); /**
* Function SetPrmBgColor
* Set the background color for a given parameter
* @param aPrmId = @ref PRMS_ID of the parameter
* @param aCol = color ( @ref KIGFX::COLOR4D * )
*/
void PCB_CALCULATOR_FRAME::SetPrmBgColor( enum PRMS_ID aPrmId, const KIGFX::COLOR4D* aCol )
{
wxColour wxcol = wxColour( static_cast<unsigned char>( aCol->r * 255 ),
static_cast<unsigned char>( aCol->g * 255 ),
static_cast<unsigned char>( aCol->b * 255 ) );
if( !wxcol.IsOk() )
{
return;
}
TRANSLINE_IDENT* tr_ident = m_transline_list[m_currTransLineType];
for( unsigned ii = 0; ii < tr_ident->GetPrmsCount(); ii++ )
{
TRANSLINE_PRM* prm = tr_ident->GetPrm( ii );
wxTextCtrl* ctl = static_cast<wxTextCtrl*>( prm->m_ValueCtrl );
if( aPrmId == prm->m_Id )
{
ctl->SetBackgroundColour( wxcol );
ctl->SetStyle( 0, -1, ctl->GetDefaultStyle() );
return;
}
}
} }
/** /**
@ -170,10 +216,10 @@ void PCB_CALCULATOR_FRAME::SetPrmValue( enum PRMS_ID aPrmId, double aValue )
* @param aLineNumber = the line (0 to MSG_CNT_MAX-1) wher to display the text * @param aLineNumber = the line (0 to MSG_CNT_MAX-1) wher to display the text
* @param aText = the text to display * @param aText = the text to display
*/ */
void PCB_CALCULATOR_FRAME::SetResult( int aLineNumber, const wxString & aText ) void PCB_CALCULATOR_FRAME::SetResult( int aLineNumber, const wxString& aText )
{ {
#define MSG_CNT_MAX 7 #define MSG_CNT_MAX 7
wxStaticText * messages[MSG_CNT_MAX] = wxStaticText* messages[MSG_CNT_MAX] =
{ m_Message1, m_Message2, m_Message3, { m_Message1, m_Message2, m_Message3,
m_Message4, m_Message5, m_Message6, m_Message4, m_Message5, m_Message6,
m_Message7 m_Message7
@ -184,7 +230,7 @@ void PCB_CALCULATOR_FRAME::SetResult( int aLineNumber, const wxString & aText )
if( aLineNumber < 0 ) if( aLineNumber < 0 )
aLineNumber = 0; aLineNumber = 0;
if( aLineNumber >= MSG_CNT_MAX ) if( aLineNumber >= MSG_CNT_MAX )
aLineNumber = MSG_CNT_MAX-1; aLineNumber = MSG_CNT_MAX - 1;
messages[aLineNumber]->SetLabel( aText ); messages[aLineNumber]->SetLabel( aText );
} }
@ -199,7 +245,7 @@ bool PCB_CALCULATOR_FRAME::IsPrmSelected( enum PRMS_ID aPrmId )
switch( aPrmId ) switch( aPrmId )
{ {
default: default:
wxMessageBox( wxT("IsPrmSelected() error") ); wxMessageBox( wxT( "IsPrmSelected() error" ) );
break; break;
case PHYS_WIDTH_PRM: case PHYS_WIDTH_PRM:
@ -214,4 +260,3 @@ bool PCB_CALCULATOR_FRAME::IsPrmSelected( enum PRMS_ID aPrmId )
} }
return false; return false;
} }

View File

@ -26,10 +26,10 @@
#include <pcb_calculator_frame_base.h> #include <pcb_calculator_frame_base.h>
#include <transline.h> // Included for SUBST_PRMS_ID definition.
#include <transline_ident.h>
#include <attenuator_classes.h> #include <attenuator_classes.h>
#include <class_regulator_data.h> #include <class_regulator_data.h>
#include <transline.h> // Included for SUBST_PRMS_ID definition.
#include <transline_ident.h>
extern const wxString PcbCalcDataFileExt; extern const wxString PcbCalcDataFileExt;
@ -56,23 +56,21 @@ private:
bool m_TWNested; // Used to stop events caused by setting the answers. bool m_TWNested; // Used to stop events caused by setting the answers.
enum TRANSLINE_TYPE_ID m_currTransLineType; enum TRANSLINE_TYPE_ID m_currTransLineType;
TRANSLINE * m_currTransLine; // a pointer to the active transline TRANSLINE* m_currTransLine; // a pointer to the active transline
// List of translines: ordered like in dialog menu list // List of translines: ordered like in dialog menu list
std::vector <TRANSLINE_IDENT *> m_transline_list; std::vector<TRANSLINE_IDENT*> m_transline_list;
ATTENUATOR * m_currAttenuator; ATTENUATOR* m_currAttenuator;
// List ofattenuators: ordered like in dialog menu list // List ofattenuators: ordered like in dialog menu list
std::vector <ATTENUATOR *> m_attenuator_list; std::vector<ATTENUATOR*> m_attenuator_list;
wxString m_lastSelectedRegulatorName; // last regulator name selected wxString m_lastSelectedRegulatorName; // last regulator name selected
public: public:
PCB_CALCULATOR_FRAME( KIWAY* aKiway, wxWindow* aParent ); PCB_CALCULATOR_FRAME( KIWAY* aKiway, wxWindow* aParent );
~PCB_CALCULATOR_FRAME(); ~PCB_CALCULATOR_FRAME();
private: private:
// Event handlers // Event handlers
void OnClosePcbCalc( wxCloseEvent& event ) override; void OnClosePcbCalc( wxCloseEvent& event ) override;
@ -99,7 +97,7 @@ private:
* force the standard extension of the file (.pcbcalc) * force the standard extension of the file (.pcbcalc)
* @param aFilename = the full filename, with or without extension * @param aFilename = the full filename, with or without extension
*/ */
void SetDataFilename( const wxString & aFilename); void SetDataFilename( const wxString& aFilename );
// Trace width / maximum current capability calculations. // Trace width / maximum current capability calculations.
@ -154,23 +152,23 @@ private:
* Function TWCalculateWidth * Function TWCalculateWidth
* Calculate track width required based on given current and temperature rise. * Calculate track width required based on given current and temperature rise.
*/ */
double TWCalculateWidth( double aCurrent, double aThickness, double aDeltaT_C, double TWCalculateWidth(
bool aUseInternalLayer ); double aCurrent, double aThickness, double aDeltaT_C, bool aUseInternalLayer );
/** /**
* Function TWCalculateCurrent * Function TWCalculateCurrent
* Calculate maximum current based on given width and temperature rise. * Calculate maximum current based on given width and temperature rise.
*/ */
double TWCalculateCurrent( double aWidth, double aThickness, double aDeltaT_C, double TWCalculateCurrent(
bool aUseInternalLayer ); double aWidth, double aThickness, double aDeltaT_C, bool aUseInternalLayer );
/** /**
* Function TWDisplayValues * Function TWDisplayValues
* Displays the results of a calculation (including resulting values such * Displays the results of a calculation (including resulting values such
* as the resistance and power loss). * as the resistance and power loss).
*/ */
void TWDisplayValues( double aCurrent, double aExtWidth, double aIntWidth, void TWDisplayValues( double aCurrent, double aExtWidth, double aIntWidth, double aExtThickness,
double aExtThickness, double aIntThickness ); double aIntThickness );
/** /**
* Function TWUpdateModeDisplay * Function TWUpdateModeDisplay
@ -358,8 +356,14 @@ public:
* @param aLineNumber = the line (0 to 5) wher to display the text * @param aLineNumber = the line (0 to 5) wher to display the text
* @param aText = the text to display * @param aText = the text to display
*/ */
void SetResult( int aLineNumber, const wxString & aText ); void SetResult( int aLineNumber, const wxString& aText );
/** Function SetPrgmBgColor
* Set the background color of a parameter
* @param aPrmId = param id to set
* @param aCol = new color
*/
void SetPrmBgColor( enum PRMS_ID aPrmId, const KIGFX::COLOR4D* aCol );
/** /**
* Function GetPrmValue * Function GetPrmValue
* Returns a param value. * Returns a param value.
@ -380,7 +384,10 @@ public:
void BoardClassesUpdateData( double aUnitScale ); void BoardClassesUpdateData( double aUnitScale );
// Calculator doesn't host a tool framework // Calculator doesn't host a tool framework
wxWindow* GetToolCanvas() const override { return nullptr; } wxWindow* GetToolCanvas() const override
{
return nullptr;
}
}; };

View File

@ -31,43 +31,16 @@
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <units.h>
#include <transline.h>
#include <microstrip.h>
#include <c_microstrip.h> #include <c_microstrip.h>
#include <microstrip.h>
#include <transline.h>
#include <units.h>
C_MICROSTRIP::C_MICROSTRIP() : TRANSLINE() C_MICROSTRIP::C_MICROSTRIP() : TRANSLINE()
{ {
m_Name = "Coupled_MicroStrip"; m_Name = "Coupled_MicroStrip";
aux_ms = NULL; aux_ms = NULL;
Init();
// Initialize these variables mainly to avoid warnings from a static analyzer
h = 0.0; // height of substrate
ht = 0.0; // height to the top of box
t = 0.0; // thickness of top metal
rough = 0.0; // Roughness of top metal
w = 0.0; // width of lines
w_t_e = 0.0; // even-mode thickness-corrected line width
w_t_o = 0.0; // odd-mode thickness-corrected line width
l = 0.0; // length of lines
s = 0.0; // spacing of lines
Z0_e_0 = 0.0; // static even-mode impedance
Z0_o_0 = 0.0; // static odd-mode impedance
Z0e = 0.0; // even-mode impedance
Z0o = 0.0; // odd-mode impedance
c_e = 0.0; // even-mode capacitance
c_o = 0.0; // odd-mode capacitance
ang_l_e = 0.0; // even-mode electrical length in angle
ang_l_o = 0.0; // odd-mode electrical length in angle
er_eff_e = 0.0; // even-mode effective dielectric constant
er_eff_o = 0.0; // odd-mode effective dielectric constant
er_eff_e_0 = 0.0; // static even-mode effective dielectric constant
er_eff_o_0 = 0.0; // static odd-mode effective dielectric constant
w_eff = 0.0; // Effective width of line
atten_dielectric_e = 0.0; // even-mode dielectric losses (dB)
atten_cond_e = 0.0; // even-mode conductors losses (dB)
atten_dielectric_o = 0.0; // odd-mode conductors losses (dB)
atten_cond_o = 0.0; // odd-mode conductors losses (dB)
} }
@ -99,6 +72,7 @@ double C_MICROSTRIP::delta_u_thickness_single( double u, double t_h )
log( ( 2.0 + log( ( 2.0 +
(4.0 * M_PI * u - (4.0 * M_PI * u -
2.0) / ( 1.0 + exp( -100.0 * ( u - 1.0 / (2.0 * M_PI) ) ) ) ) / t_h ) ); 2.0) / ( 1.0 + exp( -100.0 * ( u - 1.0 / (2.0 * M_PI) ) ) ) ) / t_h ) );
} }
else else
{ {
@ -122,16 +96,16 @@ void C_MICROSTRIP::delta_u_thickness()
double e_r, u, g, t_h; double e_r, u, g, t_h;
double delta_u, delta_t, delta_u_e, delta_u_o; double delta_u, delta_t, delta_u_e, delta_u_o;
e_r = er; e_r = m_parameters[EPSILONR_PRM];
u = w / h; /* normalized line width */ u = m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM]; /* normalized line width */
g = s / h; /* normalized line spacing */ g = m_parameters[PHYS_S_PRM] / m_parameters[H_PRM]; /* normalized line spacing */
t_h = t / h; /* normalized strip thickness */ t_h = m_parameters[T_PRM] / m_parameters[H_PRM]; /* normalized strip thickness */
if( t_h > 0.0 ) if( t_h > 0.0 )
{ {
/* single microstrip correction for finite strip thickness */ /* single microstrip correction for finite strip thickness */
delta_u = delta_u_thickness_single( u, t_h ); delta_u = delta_u_thickness_single( u, t_h );
delta_t = t_h / (g * e_r); delta_t = t_h / ( g * e_r );
/* thickness correction for the even- and odd-mode */ /* thickness correction for the even- and odd-mode */
delta_u_e = delta_u * ( 1.0 - 0.5 * exp( -0.69 * delta_u / delta_t ) ); delta_u_e = delta_u * ( 1.0 - 0.5 * exp( -0.69 * delta_u / delta_t ) );
delta_u_o = delta_u_e + delta_t; delta_u_o = delta_u_e + delta_t;
@ -141,8 +115,8 @@ void C_MICROSTRIP::delta_u_thickness()
delta_u_e = delta_u_o = 0.0; delta_u_e = delta_u_o = 0.0;
} }
w_t_e = w + delta_u_e * h; w_t_e = m_parameters[PHYS_WIDTH_PRM] + delta_u_e * m_parameters[H_PRM];
w_t_o = w + delta_u_o * h; w_t_o = m_parameters[PHYS_WIDTH_PRM] + delta_u_o * m_parameters[H_PRM];
} }
@ -155,15 +129,15 @@ void C_MICROSTRIP::compute_single_line()
aux_ms = new MICROSTRIP(); aux_ms = new MICROSTRIP();
/* prepare parameters for single microstrip computations */ /* prepare parameters for single microstrip computations */
aux_ms->er = er; aux_ms->m_parameters[EPSILONR_PRM] = m_parameters[EPSILONR_PRM];
aux_ms->w = w; aux_ms->m_parameters[PHYS_WIDTH_PRM] = m_parameters[PHYS_WIDTH_PRM];
aux_ms->h = h; aux_ms->m_parameters[H_PRM] = m_parameters[H_PRM];
aux_ms->t = 0.0; aux_ms->m_parameters[T_PRM] = 0.0;
//aux_ms->t = t; //aux_ms->m_parameters[H_T_PRM] = m_parameters[H_T_PRM];
aux_ms->ht = 1e12; /* arbitrarily high */ aux_ms->m_parameters[H_T_PRM] = 1e12; /* arbitrarily high */
aux_ms->m_freq = m_freq; aux_ms->m_parameters[FREQUENCY_PRM] = m_parameters[FREQUENCY_PRM];
aux_ms->m_murC = m_murC; aux_ms->m_parameters[MURC_PRM] = m_parameters[MURC_PRM];
aux_ms->microstrip_Z0(); aux_ms->microstrip_Z0();
aux_ms->dispersion(); aux_ms->dispersion();
} }
@ -177,15 +151,15 @@ double C_MICROSTRIP::filling_factor_even( double u, double g, double e_r )
{ {
double v, v3, v4, a_e, b_e, q_inf; double v, v3, v4, a_e, b_e, q_inf;
v = u * (20.0 + g * g) / (10.0 + g * g) + g* exp( -g ); v = u * ( 20.0 + g * g ) / ( 10.0 + g * g ) + g * exp( -g );
v3 = v * v * v; v3 = v * v * v;
v4 = v3 * v; v4 = v3 * v;
a_e = 1.0 + log( (v4 + v * v / 2704.0) / (v4 + 0.432) ) / 49.0 + log( 1.0 + v3 / 5929.741 ) a_e = 1.0 + log( ( v4 + v * v / 2704.0 ) / ( v4 + 0.432 ) ) / 49.0
/ 18.7; + log( 1.0 + v3 / 5929.741 ) / 18.7;
b_e = 0.564 * pow( ( (e_r - 0.9) / (e_r + 3.0) ), 0.053 ); b_e = 0.564 * pow( ( ( e_r - 0.9 ) / ( e_r + 3.0 ) ), 0.053 );
/* filling factor, with width corrected for thickness */ /* filling factor, with width corrected for thickness */
q_inf = pow( (1.0 + 10.0 / v), -a_e * b_e ); q_inf = pow( ( 1.0 + 10.0 / v ), -a_e * b_e );
return q_inf; return q_inf;
} }
@ -197,8 +171,8 @@ double C_MICROSTRIP::filling_factor_even( double u, double g, double e_r )
*/ */
double C_MICROSTRIP::filling_factor_odd( double u, double g, double e_r ) double C_MICROSTRIP::filling_factor_odd( double u, double g, double e_r )
{ {
double b_odd = 0.747 * e_r / (0.15 + e_r); double b_odd = 0.747 * e_r / ( 0.15 + e_r );
double c_odd = b_odd - (b_odd - 0.207) * exp( -0.414 * u ); double c_odd = b_odd - ( b_odd - 0.207 ) * exp( -0.414 * u );
double d_odd = 0.593 + 0.694 * exp( -0.562 * u ); double d_odd = 0.593 + 0.694 * exp( -0.562 * u );
/* filling factor, with width corrected for thickness */ /* filling factor, with width corrected for thickness */
@ -239,7 +213,7 @@ double C_MICROSTRIP::delta_q_cover_odd( double h2h )
if( h2h <= 7 ) if( h2h <= 7 )
{ {
q_c = tanh( 9.575 / (7.0 - h2h) - 2.965 + 1.68 * h2h - 0.311 * h2h * h2h ); q_c = tanh( 9.575 / ( 7.0 - h2h ) - 2.965 + 1.68 * h2h - 0.311 * h2h * h2h );
} }
else else
{ {
@ -263,17 +237,20 @@ void C_MICROSTRIP::er_eff_static()
double u_t_e, u_t_o, g, h2, h2h; double u_t_e, u_t_o, g, h2, h2h;
double a_o, t_h, q, q_c, q_t, q_inf; double a_o, t_h, q, q_c, q_t, q_inf;
double er_eff_single; double er_eff_single;
double er;
er = m_parameters[EPSILONR_PRM];
/* compute zero-thickness single line parameters */ /* compute zero-thickness single line parameters */
compute_single_line(); compute_single_line();
er_eff_single = aux_ms->er_eff_0; er_eff_single = aux_ms->er_eff_0;
h2 = ht; h2 = m_parameters[H_T_PRM];
u_t_e = w_t_e / h; /* normalized even_mode line width */ u_t_e = w_t_e / m_parameters[H_PRM]; /* normalized even_mode line width */
u_t_o = w_t_o / h; /* normalized odd_mode line width */ u_t_o = w_t_o / m_parameters[H_PRM]; /* normalized odd_mode line width */
g = s / h; /* normalized line spacing */ g = m_parameters[PHYS_S_PRM] / m_parameters[H_PRM]; /* normalized line spacing */
h2h = h2 / h; /* normalized cover height */ h2h = h2 / m_parameters[H_PRM]; /* normalized cover height */
t_h = t / h; /* normalized strip thickness */ t_h = m_parameters[T_PRM] / m_parameters[H_PRM]; /* normalized strip thickness */
/* filling factor, computed with thickness corrected width */ /* filling factor, computed with thickness corrected width */
q_inf = filling_factor_even( u_t_e, g, er ); q_inf = filling_factor_even( u_t_e, g, er );
@ -282,9 +259,9 @@ void C_MICROSTRIP::er_eff_static()
/* thickness effect */ /* thickness effect */
q_t = aux_ms->delta_q_thickness( u_t_e, t_h ); q_t = aux_ms->delta_q_thickness( u_t_e, t_h );
/* resultant filling factor */ /* resultant filling factor */
q = (q_inf - q_t) * q_c; q = ( q_inf - q_t ) * q_c;
/* static even-mode effective dielectric constant */ /* static even-mode effective dielectric constant */
er_eff_e_0 = 0.5 * (er + 1.0) + 0.5 * (er - 1.0) * q; er_eff_e_0 = 0.5 * ( er + 1.0 ) + 0.5 * ( er - 1.0 ) * q;
/* filling factor, with width corrected for thickness */ /* filling factor, with width corrected for thickness */
q_inf = filling_factor_odd( u_t_o, g, er ); q_inf = filling_factor_odd( u_t_o, g, er );
@ -293,12 +270,12 @@ void C_MICROSTRIP::er_eff_static()
/* thickness effect */ /* thickness effect */
q_t = aux_ms->delta_q_thickness( u_t_o, t_h ); q_t = aux_ms->delta_q_thickness( u_t_o, t_h );
/* resultant filling factor */ /* resultant filling factor */
q = (q_inf - q_t) * q_c; q = ( q_inf - q_t ) * q_c;
a_o = 0.7287 * ( er_eff_single - 0.5 * (er + 1.0) ) * ( 1.0 - exp( -0.179 * u_t_o ) ); a_o = 0.7287 * ( er_eff_single - 0.5 * ( er + 1.0 ) ) * ( 1.0 - exp( -0.179 * u_t_o ) );
/* static odd-mode effective dielectric constant */ /* static odd-mode effective dielectric constant */
er_eff_o_0 = (0.5 * (er + 1.0) + a_o - er_eff_single) * q + er_eff_single; er_eff_o_0 = ( 0.5 * ( er + 1.0 ) + a_o - er_eff_single ) * q + er_eff_single;
} }
@ -317,14 +294,14 @@ double C_MICROSTRIP::delta_Z0_even_cover( double g, double u, double h2h )
A = -4.351 / pow( 1.0 + h2h, 1.842 ); A = -4.351 / pow( 1.0 + h2h, 1.842 );
B = 6.639 / pow( 1.0 + h2h, 1.861 ); B = 6.639 / pow( 1.0 + h2h, 1.861 );
C = -2.291 / pow( 1.0 + h2h, 1.90 ); C = -2.291 / pow( 1.0 + h2h, 1.90 );
f_e = 1.0 - atanh( A + (B + C * u) * u ); f_e = 1.0 - atanh( A + ( B + C * u ) * u );
x = pow( 10.0, 0.103 * g - 0.159 ); x = pow( 10.0, 0.103 * g - 0.159 );
y = pow( 10.0, 0.0492 * g - 0.073 ); y = pow( 10.0, 0.0492 * g - 0.073 );
D = 0.747 / sin( 0.5 * M_PI * x ); D = 0.747 / sin( 0.5 * M_PI * x );
E = 0.725 * sin( 0.5 * M_PI * y ); E = 0.725 * sin( 0.5 * M_PI * y );
F = pow( 10.0, 0.11 - 0.0947 * g ); F = pow( 10.0, 0.11 - 0.0947 * g );
g_e = 270.0 * ( 1.0 - tanh( D + E * sqrt( 1.0 + h2h ) - F / (1.0 + h2h) ) ); g_e = 270.0 * ( 1.0 - tanh( D + E * sqrt( 1.0 + h2h ) - F / ( 1.0 + h2h ) ) );
delta_Z0_even = f_e * g_e; delta_Z0_even = f_e * g_e;
@ -364,7 +341,7 @@ double C_MICROSTRIP::delta_Z0_odd_cover( double g, double u, double h2h )
{ {
L = 2.674; L = 2.674;
} }
g_o = 270.0 * ( 1.0 - tanh( G + K * sqrt( 1.0 + h2h ) - L / (1.0 + h2h) ) ); g_o = 270.0 * ( 1.0 - tanh( G + K * sqrt( 1.0 + h2h ) - L / ( 1.0 + h2h ) ) );
delta_Z0_odd = f_o * g_o; delta_Z0_odd = f_o * g_o;
@ -387,11 +364,11 @@ void C_MICROSTRIP::Z0_even_odd()
double Q_1, Q_2, Q_3, Q_4, Q_5, Q_6, Q_7, Q_8, Q_9, Q_10; double Q_1, Q_2, Q_3, Q_4, Q_5, Q_6, Q_7, Q_8, Q_9, Q_10;
double delta_Z0_e_0, delta_Z0_o_0, Z0_single, er_eff_single; double delta_Z0_e_0, delta_Z0_o_0, Z0_single, er_eff_single;
h2 = ht; h2 = m_parameters[H_T_PRM];
u_t_e = w_t_e / h; /* normalized even-mode line width */ u_t_e = w_t_e / m_parameters[H_PRM]; /* normalized even-mode line width */
u_t_o = w_t_o / h; /* normalized odd-mode line width */ u_t_o = w_t_o / m_parameters[H_PRM]; /* normalized odd-mode line width */
g = s / h; /* normalized line spacing */ g = m_parameters[PHYS_S_PRM] / m_parameters[H_PRM]; /* normalized line spacing */
h2h = h2 / h; /* normalized cover height */ h2h = h2 / m_parameters[H_PRM]; /* normalized cover height */
Z0_single = aux_ms->Z0_0; Z0_single = aux_ms->Z0_0;
er_eff_single = aux_ms->er_eff_0; er_eff_single = aux_ms->er_eff_0;
@ -400,16 +377,13 @@ void C_MICROSTRIP::Z0_even_odd()
er_eff = er_eff_e_0; er_eff = er_eff_e_0;
Q_1 = 0.8695 * pow( u_t_e, 0.194 ); Q_1 = 0.8695 * pow( u_t_e, 0.194 );
Q_2 = 1.0 + 0.7519 * g + 0.189 * pow( g, 2.31 ); Q_2 = 1.0 + 0.7519 * g + 0.189 * pow( g, 2.31 );
Q_3 = 0.1975 + Q_3 = 0.1975 + pow( ( 16.6 + pow( ( 8.4 / g ), 6.0 ) ), -0.387 )
pow( ( 16.6 + + log( pow( g, 10.0 ) / ( 1.0 + pow( g / 3.4, 10.0 ) ) ) / 241.0;
pow( (8.4 / g), Q_4 = 2.0 * Q_1
6.0 ) ), / ( Q_2 * ( exp( -g ) * pow( u_t_e, Q_3 ) + ( 2.0 - exp( -g ) ) * pow( u_t_e, -Q_3 ) ) );
-0.387 ) + log( pow( g, 10.0 ) / ( 1.0 + pow( g / 3.4, 10.0 ) ) ) / 241.0;
Q_4 = 2.0 * Q_1 /
( Q_2 * ( exp( -g ) * pow( u_t_e, Q_3 ) + ( 2.0 - exp( -g ) ) * pow( u_t_e, -Q_3 ) ) );
/* static even-mode impedance */ /* static even-mode impedance */
Z0_e_0 = Z0_single * Z0_e_0 = Z0_single * sqrt( er_eff_single / er_eff )
sqrt( er_eff_single / er_eff ) / (1.0 - sqrt( er_eff_single ) * Q_4 * Z0_single / ZF0); / ( 1.0 - sqrt( er_eff_single ) * Q_4 * Z0_single / ZF0 );
/* correction for cover */ /* correction for cover */
delta_Z0_e_0 = delta_Z0_even_cover( g, u_t_e, h2h ) / sqrt( er_eff ); delta_Z0_e_0 = delta_Z0_even_cover( g, u_t_e, h2h ) / sqrt( er_eff );
@ -418,17 +392,16 @@ void C_MICROSTRIP::Z0_even_odd()
/* odd-mode */ /* odd-mode */
er_eff = er_eff_o_0; er_eff = er_eff_o_0;
Q_5 = 1.794 + 1.14 * log( 1.0 + 0.638 / ( g + 0.517 * pow( g, 2.43 ) ) ); Q_5 = 1.794 + 1.14 * log( 1.0 + 0.638 / ( g + 0.517 * pow( g, 2.43 ) ) );
Q_6 = 0.2305 + log( pow( g, 10.0 ) / ( 1.0 + pow( g / 5.8, 10.0 ) ) ) / 281.3 + log( Q_6 = 0.2305 + log( pow( g, 10.0 ) / ( 1.0 + pow( g / 5.8, 10.0 ) ) ) / 281.3
1.0 + 0.598 * pow( g, 1.154 ) ) / 5.1; + log( 1.0 + 0.598 * pow( g, 1.154 ) ) / 5.1;
Q_7 = (10.0 + 190.0 * g * g) / (1.0 + 82.3 * g * g * g); Q_7 = ( 10.0 + 190.0 * g * g ) / ( 1.0 + 82.3 * g * g * g );
Q_8 = exp( -6.5 - 0.95 * log( g ) - pow( g / 0.15, 5.0 ) ); Q_8 = exp( -6.5 - 0.95 * log( g ) - pow( g / 0.15, 5.0 ) );
Q_9 = log( Q_7 ) * (Q_8 + 1.0 / 16.5); Q_9 = log( Q_7 ) * ( Q_8 + 1.0 / 16.5 );
Q_10 = ( Q_2 * Q_4 - Q_5 * exp( log( u_t_o ) * Q_6 * pow( u_t_o, -Q_9 ) ) ) / Q_2; Q_10 = ( Q_2 * Q_4 - Q_5 * exp( log( u_t_o ) * Q_6 * pow( u_t_o, -Q_9 ) ) ) / Q_2;
/* static odd-mode impedance */ /* static odd-mode impedance */
Z0_o_0 = Z0_single * Z0_o_0 = Z0_single * sqrt( er_eff_single / er_eff )
sqrt( er_eff_single / / ( 1.0 - sqrt( er_eff_single ) * Q_10 * Z0_single / ZF0 );
er_eff ) / (1.0 - sqrt( er_eff_single ) * Q_10 * Z0_single / ZF0);
/* correction for cover */ /* correction for cover */
delta_Z0_o_0 = delta_Z0_odd_cover( g, u_t_o, h2h ) / sqrt( er_eff ); delta_Z0_o_0 = delta_Z0_odd_cover( g, u_t_o, h2h ) / sqrt( er_eff );
@ -446,41 +419,42 @@ void C_MICROSTRIP::er_eff_freq()
double F_e, F_o; double F_e, F_o;
double er_eff, u, g, f_n; double er_eff, u, g, f_n;
u = w / h; /* normalize line width */ u = m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM]; /* normalize line width */
g = s / h; /* normalize line spacing */ g = m_parameters[PHYS_S_PRM] / m_parameters[H_PRM]; /* normalize line spacing */
/* normalized frequency [GHz * mm] */ /* normalized frequency [GHz * mm] */
f_n = m_freq * h / 1e06; f_n = m_parameters[FREQUENCY_PRM] * m_parameters[H_PRM] / 1e06;
er_eff = er_eff_e_0; er_eff = er_eff_e_0;
P_1 = 0.27488 + ( 0.6315 + 0.525 / pow( 1.0 + 0.0157 * f_n, 20.0 ) ) * u - 0.065683 * exp( P_1 = 0.27488 + ( 0.6315 + 0.525 / pow( 1.0 + 0.0157 * f_n, 20.0 ) ) * u
-8.7513 * u ); - 0.065683 * exp( -8.7513 * u );
P_2 = 0.33622 * ( 1.0 - exp( -0.03442 * er ) ); P_2 = 0.33622 * ( 1.0 - exp( -0.03442 * m_parameters[EPSILONR_PRM] ) );
P_3 = 0.0363 * exp( -4.6 * u ) * ( 1.0 - exp( -pow( f_n / 38.7, 4.97 ) ) ); P_3 = 0.0363 * exp( -4.6 * u ) * ( 1.0 - exp( -pow( f_n / 38.7, 4.97 ) ) );
P_4 = 1.0 + 2.751 * ( 1.0 - exp( -pow( er / 15.916, 8.0 ) ) ); P_4 = 1.0 + 2.751 * ( 1.0 - exp( -pow( m_parameters[EPSILONR_PRM] / 15.916, 8.0 ) ) );
P_5 = 0.334 * exp( -3.3 * pow( er / 15.0, 3.0 ) ) + 0.746; P_5 = 0.334 * exp( -3.3 * pow( m_parameters[EPSILONR_PRM] / 15.0, 3.0 ) ) + 0.746;
P_6 = P_5 * exp( -pow( f_n / 18.0, 0.368 ) ); P_6 = P_5 * exp( -pow( f_n / 18.0, 0.368 ) );
P_7 = 1.0 + P_7 = 1.0
4.069* P_6* pow( g, 0.479 ) * exp( -1.347 * pow( g, 0.595 ) - 0.17 * pow( g, 2.5 ) ); + 4.069 * P_6 * pow( g, 0.479 ) * exp( -1.347 * pow( g, 0.595 ) - 0.17 * pow( g, 2.5 ) );
F_e = P_1 * P_2 * pow( (P_3 * P_4 + 0.1844 * P_7) * f_n, 1.5763 ); F_e = P_1 * P_2 * pow( ( P_3 * P_4 + 0.1844 * P_7 ) * f_n, 1.5763 );
/* even-mode effective dielectric constant */ /* even-mode effective dielectric constant */
er_eff_e = er - (er - er_eff) / (1.0 + F_e); er_eff_e = m_parameters[EPSILONR_PRM] - ( m_parameters[EPSILONR_PRM] - er_eff ) / ( 1.0 + F_e );
er_eff = er_eff_o_0; er_eff = er_eff_o_0;
P_8 = 0.7168 * ( 1.0 + 1.076 / ( 1.0 + 0.0576 * (er - 1.0) ) ); P_8 = 0.7168 * ( 1.0 + 1.076 / ( 1.0 + 0.0576 * ( m_parameters[EPSILONR_PRM] - 1.0 ) ) );
P_9 = P_8 - 0.7913 * P_9 = P_8
( 1.0 - exp( -pow( f_n / 20.0, 1.424 ) ) ) * atan( 2.481 * pow( er / 8.0, 0.946 ) ); - 0.7913 * ( 1.0 - exp( -pow( f_n / 20.0, 1.424 ) ) )
P_10 = 0.242 * pow( er - 1.0, 0.55 ); * atan( 2.481 * pow( m_parameters[EPSILONR_PRM] / 8.0, 0.946 ) );
P_11 = 0.6366 * (exp( -0.3401 * f_n ) - 1.0) * atan( 1.263 * pow( u / 3.0, 1.629 ) ); P_10 = 0.242 * pow( m_parameters[EPSILONR_PRM] - 1.0, 0.55 );
P_12 = P_9 + (1.0 - P_9) / ( 1.0 + 1.183 * pow( u, 1.376 ) ); P_11 = 0.6366 * ( exp( -0.3401 * f_n ) - 1.0 ) * atan( 1.263 * pow( u / 3.0, 1.629 ) );
P_13 = 1.695 * P_10 / (0.414 + 1.605 * P_10); P_12 = P_9 + ( 1.0 - P_9 ) / ( 1.0 + 1.183 * pow( u, 1.376 ) );
P_13 = 1.695 * P_10 / ( 0.414 + 1.605 * P_10 );
P_14 = 0.8928 + 0.1072 * ( 1.0 - exp( -0.42 * pow( f_n / 20.0, 3.215 ) ) ); P_14 = 0.8928 + 0.1072 * ( 1.0 - exp( -0.42 * pow( f_n / 20.0, 3.215 ) ) );
P_15 = fabs( 1.0 - 0.8928 * (1.0 + P_11) * P_12 * exp( -P_13 * pow( g, 1.092 ) ) / P_14 ); P_15 = fabs( 1.0 - 0.8928 * ( 1.0 + P_11 ) * P_12 * exp( -P_13 * pow( g, 1.092 ) ) / P_14 );
F_o = P_1 * P_2 * pow( (P_3 * P_4 + 0.1844) * f_n * P_15, 1.5763 ); F_o = P_1 * P_2 * pow( ( P_3 * P_4 + 0.1844 ) * f_n * P_15, 1.5763 );
/* odd-mode effective dielectric constant */ /* odd-mode effective dielectric constant */
er_eff_o = er - (er - er_eff) / (1.0 + F_o); er_eff_o = m_parameters[EPSILONR_PRM] - ( m_parameters[EPSILONR_PRM] - er_eff ) / ( 1.0 + F_o );
} }
@ -497,34 +471,40 @@ void C_MICROSTRIP::conductor_losses()
e_r_eff_o_0 = er_eff_o_0; e_r_eff_o_0 = er_eff_o_0;
Z0_h_e = Z0_e_0 * sqrt( e_r_eff_e_0 ); /* homogeneous stripline impedance */ Z0_h_e = Z0_e_0 * sqrt( e_r_eff_e_0 ); /* homogeneous stripline impedance */
Z0_h_o = Z0_o_0 * sqrt( e_r_eff_o_0 ); /* homogeneous stripline impedance */ Z0_h_o = Z0_o_0 * sqrt( e_r_eff_o_0 ); /* homogeneous stripline impedance */
delta = m_skindepth; delta = m_parameters[SKIN_DEPTH_PRM];
if( m_freq > 0.0 ) if( m_parameters[FREQUENCY_PRM] > 0.0 )
{ {
/* current distribution factor (same for the two modes) */ /* current distribution factor (same for the two modes) */
K = exp( -1.2 * pow( (Z0_h_e + Z0_h_o) / (2.0 * ZF0), 0.7 ) ); K = exp( -1.2 * pow( ( Z0_h_e + Z0_h_o ) / ( 2.0 * ZF0 ), 0.7 ) );
/* skin resistance */ /* skin resistance */
R_s = 1.0 / (m_sigma * delta); R_s = 1.0 / ( m_parameters[SIGMA_PRM] * delta );
/* correction for surface roughness */ /* correction for surface roughness */
R_s *= 1.0 + ( (2.0 / M_PI) * atan( 1.40 * pow( (rough / delta), 2.0 ) ) ); R_s *= 1.0
+ ( ( 2.0 / M_PI )
* atan( 1.40 * pow( ( m_parameters[ROUGH_PRM] / delta ), 2.0 ) ) );
/* even-mode strip inductive quality factor */ /* even-mode strip inductive quality factor */
Q_c_e = (M_PI * Z0_h_e * w * m_freq) / (R_s * C0 * K); Q_c_e = ( M_PI * Z0_h_e * m_parameters[PHYS_WIDTH_PRM] * m_parameters[FREQUENCY_PRM] )
/ ( R_s * C0 * K );
/* even-mode losses per unith length */ /* even-mode losses per unith length */
alpha_c_e = ( 20.0 * M_PI / log( 10.0 ) ) * m_freq * sqrt( e_r_eff_e_0 ) / (C0 * Q_c_e); alpha_c_e = ( 20.0 * M_PI / log( 10.0 ) ) * m_parameters[FREQUENCY_PRM]
* sqrt( e_r_eff_e_0 ) / ( C0 * Q_c_e );
/* odd-mode strip inductive quality factor */ /* odd-mode strip inductive quality factor */
Q_c_o = (M_PI * Z0_h_o * w * m_freq) / (R_s * C0 * K); Q_c_o = ( M_PI * Z0_h_o * m_parameters[PHYS_WIDTH_PRM] * m_parameters[FREQUENCY_PRM] )
/ ( R_s * C0 * K );
/* odd-mode losses per unith length */ /* odd-mode losses per unith length */
alpha_c_o = ( 20.0 * M_PI / log( 10.0 ) ) * m_freq * sqrt( e_r_eff_o_0 ) / (C0 * Q_c_o); alpha_c_o = ( 20.0 * M_PI / log( 10.0 ) ) * m_parameters[FREQUENCY_PRM]
* sqrt( e_r_eff_o_0 ) / ( C0 * Q_c_o );
} }
else else
{ {
alpha_c_e = alpha_c_o = 0.0; alpha_c_e = alpha_c_o = 0.0;
} }
atten_cond_e = alpha_c_e * l; atten_cond_e = alpha_c_e * m_parameters[PHYS_LEN_PRM];
atten_cond_o = alpha_c_o * l; atten_cond_o = alpha_c_o * m_parameters[PHYS_LEN_PRM];
} }
@ -537,21 +517,19 @@ void C_MICROSTRIP::dielectric_losses()
double e_r, e_r_eff_e_0, e_r_eff_o_0; double e_r, e_r_eff_e_0, e_r_eff_o_0;
double alpha_d_e, alpha_d_o; double alpha_d_e, alpha_d_o;
e_r = er; e_r = m_parameters[EPSILONR_PRM];
e_r_eff_e_0 = er_eff_e_0; e_r_eff_e_0 = er_eff_e_0;
e_r_eff_o_0 = er_eff_o_0; e_r_eff_o_0 = er_eff_o_0;
alpha_d_e = alpha_d_e = ( 20.0 * M_PI / log( 10.0 ) ) * ( m_parameters[FREQUENCY_PRM] / C0 )
( 20.0 * M_PI / * ( e_r / sqrt( e_r_eff_e_0 ) ) * ( ( e_r_eff_e_0 - 1.0 ) / ( e_r - 1.0 ) )
log( 10.0 ) ) * * m_parameters[TAND_PRM];
(m_freq / C0) * ( e_r / sqrt( e_r_eff_e_0 ) ) * ( (e_r_eff_e_0 - 1.0) / (e_r - 1.0) ) * m_tand; alpha_d_o = ( 20.0 * M_PI / log( 10.0 ) ) * ( m_parameters[FREQUENCY_PRM] / C0 )
alpha_d_o = * ( e_r / sqrt( e_r_eff_o_0 ) ) * ( ( e_r_eff_o_0 - 1.0 ) / ( e_r - 1.0 ) )
( 20.0 * M_PI / * m_parameters[TAND_PRM];
log( 10.0 ) ) *
(m_freq / C0) * ( e_r / sqrt( e_r_eff_o_0 ) ) * ( (e_r_eff_o_0 - 1.0) / (e_r - 1.0) ) * m_tand;
atten_dielectric_e = alpha_d_e * l; atten_dielectric_e = alpha_d_e * m_parameters[PHYS_LEN_PRM];
atten_dielectric_o = alpha_d_o * l; atten_dielectric_o = alpha_d_o * m_parameters[PHYS_LEN_PRM];
} }
@ -561,7 +539,7 @@ void C_MICROSTRIP::dielectric_losses()
*/ */
void C_MICROSTRIP::attenuation() void C_MICROSTRIP::attenuation()
{ {
m_skindepth = skin_depth(); m_parameters[SKIN_DEPTH_PRM] = skin_depth();
conductor_losses(); conductor_losses();
dielectric_losses(); dielectric_losses();
} }
@ -583,38 +561,33 @@ void C_MICROSTRIP::line_angle()
/* odd-mode velocity */ /* odd-mode velocity */
v_o = C0 / sqrt( e_r_eff_o ); v_o = C0 / sqrt( e_r_eff_o );
/* even-mode wavelength */ /* even-mode wavelength */
lambda_g_e = v_e / m_freq; lambda_g_e = v_e / m_parameters[FREQUENCY_PRM];
/* odd-mode wavelength */ /* odd-mode wavelength */
lambda_g_o = v_o / m_freq; lambda_g_o = v_o / m_parameters[FREQUENCY_PRM];
/* electrical angles */ /* electrical angles */
ang_l_e = 2.0 * M_PI * l / lambda_g_e; /* in radians */ ang_l_e = 2.0 * M_PI * m_parameters[PHYS_LEN_PRM] / lambda_g_e; /* in radians */
ang_l_o = 2.0 * M_PI * l / lambda_g_o; /* in radians */ ang_l_o = 2.0 * M_PI * m_parameters[PHYS_LEN_PRM] / lambda_g_o; /* in radians */
} }
void C_MICROSTRIP::syn_err_fun( double* f1, void C_MICROSTRIP::syn_err_fun(
double* f2, double* f1, double* f2, double s_h, double w_h, double e_r, double w_h_se, double w_h_so )
double s_h,
double w_h,
double e_r,
double w_h_se,
double w_h_so )
{ {
double g, he; double g, he;
g = cosh( 0.5 * M_PI * s_h ); g = cosh( 0.5 * M_PI * s_h );
he = cosh( M_PI * w_h + 0.5 * M_PI * s_h ); he = cosh( M_PI * w_h + 0.5 * M_PI * s_h );
*f1 = (2.0 / M_PI) * acosh( (2.0 * he - g + 1.0) / (g + 1.0) ); *f1 = ( 2.0 / M_PI ) * acosh( ( 2.0 * he - g + 1.0 ) / ( g + 1.0 ) );
*f2 = (2.0 / M_PI) * acosh( (2.0 * he - g - 1.0) / (g - 1.0) ); *f2 = ( 2.0 / M_PI ) * acosh( ( 2.0 * he - g - 1.0 ) / ( g - 1.0 ) );
if( e_r <= 6.0 ) if( e_r <= 6.0 )
{ {
*f2 += ( 4.0 / ( M_PI * (1.0 + e_r / 2.0) ) ) * acosh( 1.0 + 2.0 * w_h / s_h ); *f2 += ( 4.0 / ( M_PI * ( 1.0 + e_r / 2.0 ) ) ) * acosh( 1.0 + 2.0 * w_h / s_h );
} }
else else
{ {
*f2 += (1.0 / M_PI) * acosh( 1.0 + 2.0 * w_h / s_h ); *f2 += ( 1.0 / M_PI ) * acosh( 1.0 + 2.0 * w_h / s_h );
} }
*f1 -= w_h_se; *f1 -= w_h_se;
@ -637,44 +610,45 @@ void C_MICROSTRIP::synth_width()
double eps = 1e-04; double eps = 1e-04;
f1 = f2 = 0; f1 = f2 = 0;
e_r = er; e_r = m_parameters[EPSILONR_PRM];
Z0 = Z0e / 2.0; Z0 = m_parameters[Z0_E_PRM] / 2.0;
/* Wheeler formula for single microstrip synthesis */ /* Wheeler formula for single microstrip synthesis */
a = exp( Z0 * sqrt( e_r + 1.0 ) / 42.4 ) - 1.0; a = exp( Z0 * sqrt( e_r + 1.0 ) / 42.4 ) - 1.0;
w_h_se = 8.0 * sqrt( a * ( (7.0 + 4.0 / e_r) / 11.0 ) + ( (1.0 + 1.0 / e_r) / 0.81 ) ) / a; w_h_se = 8.0 * sqrt( a * ( ( 7.0 + 4.0 / e_r ) / 11.0 ) + ( ( 1.0 + 1.0 / e_r ) / 0.81 ) ) / a;
Z0 = Z0o / 2.0; Z0 = m_parameters[Z0_O_PRM] / 2.0;
/* Wheeler formula for single microstrip synthesis */ /* Wheeler formula for single microstrip synthesis */
a = exp( Z0 * sqrt( e_r + 1.0 ) / 42.4 ) - 1.0; a = exp( Z0 * sqrt( e_r + 1.0 ) / 42.4 ) - 1.0;
w_h_so = 8.0 * sqrt( a * ( (7.0 + 4.0 / e_r) / 11.0 ) + ( (1.0 + 1.0 / e_r) / 0.81 ) ) / a; w_h_so = 8.0 * sqrt( a * ( ( 7.0 + 4.0 / e_r ) / 11.0 ) + ( ( 1.0 + 1.0 / e_r ) / 0.81 ) ) / a;
ce = cosh( 0.5 * M_PI * w_h_se ); ce = cosh( 0.5 * M_PI * w_h_se );
co = cosh( 0.5 * M_PI * w_h_so ); co = cosh( 0.5 * M_PI * w_h_so );
/* first guess at s/h */ /* first guess at m_parameters[PHYS_S_PRM]/h */
s_h = (2.0 / M_PI) * acosh( (ce + co - 2.0) / (co - ce) ); s_h = ( 2.0 / M_PI ) * acosh( ( ce + co - 2.0 ) / ( co - ce ) );
/* first guess at w/h */ /* first guess at w/h */
w_h = acosh( (ce * co - 1.0) / (co - ce) ) / M_PI - s_h / 2.0; w_h = acosh( ( ce * co - 1.0 ) / ( co - ce ) ) / M_PI - s_h / 2.0;
s = s_h * h; m_parameters[PHYS_S_PRM] = s_h * m_parameters[H_PRM];
w = w_h * h; m_parameters[PHYS_WIDTH_PRM] = w_h * m_parameters[H_PRM];
syn_err_fun( &f1, &f2, s_h, w_h, e_r, w_h_se, w_h_so ); syn_err_fun( &f1, &f2, s_h, w_h, e_r, w_h_se, w_h_so );
/* rather crude Newton-Rhapson; we need this beacuse the estimate of */ /* rather crude Newton-Rhapson; we need this beacuse the estimate of */
/* w_h is often quite far from the true value (see Akhtarzad S. et al.) */ /* w_h is often quite far from the true value (see Akhtarzad S. et al.) */
do { do
{
/* compute Jacobian */ /* compute Jacobian */
syn_err_fun( &ft1, &ft2, s_h + eps, w_h, e_r, w_h_se, w_h_so ); syn_err_fun( &ft1, &ft2, s_h + eps, w_h, e_r, w_h_se, w_h_so );
j11 = (ft1 - f1) / eps; j11 = ( ft1 - f1 ) / eps;
j21 = (ft2 - f2) / eps; j21 = ( ft2 - f2 ) / eps;
syn_err_fun( &ft1, &ft2, s_h, w_h + eps, e_r, w_h_se, w_h_so ); syn_err_fun( &ft1, &ft2, s_h, w_h + eps, e_r, w_h_se, w_h_so );
j12 = (ft1 - f1) / eps; j12 = ( ft1 - f1 ) / eps;
j22 = (ft2 - f2) / eps; j22 = ( ft2 - f2 ) / eps;
/* compute next step */ /* compute next step */
d_s_h = (-f1 * j22 + f2 * j12) / (j11 * j22 - j21 * j12); d_s_h = ( -f1 * j22 + f2 * j12 ) / ( j11 * j22 - j21 * j12 );
d_w_h = (-f2 * j11 + f1 * j21) / (j11 * j22 - j21 * j12); d_w_h = ( -f2 * j11 + f1 * j21 ) / ( j11 * j22 - j21 * j12 );
//g_print("j11 = %e\tj12 = %e\tj21 = %e\tj22 = %e\n", j11, j12, j21, j22); //g_print("j11 = %e\tj12 = %e\tj21 = %e\tj22 = %e\n", j11, j12, j21, j22);
//g_print("det = %e\n", j11*j22 - j21*j22); //g_print("det = %e\n", j11*j22 - j21*j22);
@ -691,8 +665,8 @@ void C_MICROSTRIP::synth_width()
} while( err > 1e-04 ); } while( err > 1e-04 );
s = s_h * h; m_parameters[PHYS_S_PRM] = s_h * m_parameters[H_PRM];
w = w_h * h; m_parameters[PHYS_WIDTH_PRM] = w_h * m_parameters[H_PRM];
} }
@ -711,62 +685,54 @@ void C_MICROSTRIP::Z0_dispersion()
double f_n, g, u, e_r; double f_n, g, u, e_r;
double R_1, R_2, R_7, R_10, R_11, R_12, R_15, R_16, tmpf; double R_1, R_2, R_7, R_10, R_11, R_12, R_15, R_16, tmpf;
e_r = er; e_r = m_parameters[EPSILONR_PRM];
u = w / h; /* normalize line width */ u = m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM]; /* normalize line width */
g = s / h; /* normalize line spacing */ g = m_parameters[PHYS_S_PRM] / m_parameters[H_PRM]; /* normalize line spacing */
/* normalized frequency [GHz * mm] */ /* normalized frequency [GHz * mm] */
f_n = m_freq * h / 1e06; f_n = m_parameters[FREQUENCY_PRM] * m_parameters[H_PRM] / 1e06;
e_r_eff_single_f = aux_ms->er_eff; e_r_eff_single_f = aux_ms->er_eff;
e_r_eff_single_0 = aux_ms->er_eff_0; e_r_eff_single_0 = aux_ms->er_eff_0;
Z0_single_f = aux_ms->Z0; Z0_single_f = aux_ms->m_parameters[Z0_PRM];
e_r_eff_o_f = er_eff_o; e_r_eff_o_f = er_eff_o;
e_r_eff_o_0 = er_eff_o_0; e_r_eff_o_0 = er_eff_o_0;
Q_11 = 0.893 * ( 1.0 - 0.3 / ( 1.0 + 0.7 * (e_r - 1.0) ) ); Q_11 = 0.893 * ( 1.0 - 0.3 / ( 1.0 + 0.7 * ( e_r - 1.0 ) ) );
Q_12 = 2.121 * ( pow( f_n / 20.0, 4.91 ) / ( 1.0 + Q_11 * pow( f_n / 20.0, 4.91 ) ) ) * exp( Q_12 = 2.121 * ( pow( f_n / 20.0, 4.91 ) / ( 1.0 + Q_11 * pow( f_n / 20.0, 4.91 ) ) )
-2.87 * g ) * pow( g, 0.902 ); * exp( -2.87 * g ) * pow( g, 0.902 );
Q_13 = 1.0 + 0.038 * pow( e_r / 8.0, 5.1 ); Q_13 = 1.0 + 0.038 * pow( e_r / 8.0, 5.1 );
Q_14 = 1.0 + 1.203 * pow( e_r / 15.0, 4.0 ) / ( 1.0 + pow( e_r / 15.0, 4.0 ) ); Q_14 = 1.0 + 1.203 * pow( e_r / 15.0, 4.0 ) / ( 1.0 + pow( e_r / 15.0, 4.0 ) );
Q_15 = 1.887 * Q_15 = 1.887 * exp( -1.5 * pow( g, 0.84 ) ) * pow( g, Q_14 )
exp( -1.5 * / ( 1.0
pow( g, + 0.41 * pow( f_n / 15.0, 3.0 ) * pow( u, 2.0 / Q_13 )
0.84 ) ) * / ( 0.125 + pow( u, 1.626 / Q_13 ) ) );
pow( g,
Q_14 ) /
( 1.0 + 0.41 *
pow( f_n / 15.0, 3.0 ) * pow( u, 2.0 / Q_13 ) / ( 0.125 + pow( u, 1.626 / Q_13 ) ) );
Q_16 = ( 1.0 + 9.0 / ( 1.0 + 0.403 * pow( e_r - 1.0, 2 ) ) ) * Q_15; Q_16 = ( 1.0 + 9.0 / ( 1.0 + 0.403 * pow( e_r - 1.0, 2 ) ) ) * Q_15;
Q_17 = 0.394 * Q_17 = 0.394 * ( 1.0 - exp( -1.47 * pow( u / 7.0, 0.672 ) ) )
( 1.0 - * ( 1.0 - exp( -4.25 * pow( f_n / 20.0, 1.87 ) ) );
exp( -1.47 * pow( u / 7.0, 0.672 ) ) ) * ( 1.0 - exp( -4.25 * pow( f_n / 20.0, 1.87 ) ) );
Q_18 = 0.61 * ( 1.0 - exp( -2.13 * pow( u / 8.0, 1.593 ) ) ) / ( 1.0 + 6.544 * pow( g, 4.17 ) ); Q_18 = 0.61 * ( 1.0 - exp( -2.13 * pow( u / 8.0, 1.593 ) ) ) / ( 1.0 + 6.544 * pow( g, 4.17 ) );
Q_19 = 0.21 * g * g * g * g / Q_19 = 0.21 * g * g * g * g
( ( 1.0 + 0.18 * pow( g, 4.9 ) ) * (1.0 + 0.1 * u * u) * ( 1.0 + pow( f_n / 24.0, 3.0 ) ) ); / ( ( 1.0 + 0.18 * pow( g, 4.9 ) ) * ( 1.0 + 0.1 * u * u )
* ( 1.0 + pow( f_n / 24.0, 3.0 ) ) );
Q_20 = ( 0.09 + 1.0 / ( 1.0 + 0.1 * pow( e_r - 1, 2.7 ) ) ) * Q_19; Q_20 = ( 0.09 + 1.0 / ( 1.0 + 0.1 * pow( e_r - 1, 2.7 ) ) ) * Q_19;
Q_21 = Q_21 = fabs( 1.0
fabs( 1.0 - 42.54 * - 42.54 * pow( g, 0.133 ) * exp( -0.812 * g ) * pow( u, 2.5 )
pow( g, 0.133 ) * exp( -0.812 * g ) * pow( u, 2.5 ) / ( 1.0 + 0.033 * pow( u, 2.5 ) ) ); / ( 1.0 + 0.033 * pow( u, 2.5 ) ) );
r_e = pow( f_n / 28.843, 12 ); r_e = pow( f_n / 28.843, 12 );
q_e = 0.016 + pow( 0.0514 * e_r * Q_21, 4.524 ); q_e = 0.016 + pow( 0.0514 * e_r * Q_21, 4.524 );
p_e = 4.766 * exp( -3.228 * pow( u, 0.641 ) ); p_e = 4.766 * exp( -3.228 * pow( u, 0.641 ) );
d_e = 5.086 * q_e * d_e = 5.086 * q_e * ( r_e / ( 0.3838 + 0.386 * q_e ) )
( r_e / * ( exp( -22.2 * pow( u, 1.92 ) ) / ( 1.0 + 1.2992 * r_e ) )
(0.3838 + 0.386 * * ( pow( e_r - 1.0, 6.0 ) / ( 1.0 + 10 * pow( e_r - 1.0, 6.0 ) ) );
q_e) ) * C_e = 1.0
( exp( -22.2 * + 1.275
pow( u, * ( 1.0
1.92 ) ) / - exp( -0.004625 * p_e * pow( e_r, 1.674 )
(1.0 + 1.2992 * r_e) ) * ( pow( e_r - 1.0, 6.0 ) / ( 1.0 + 10 * pow( e_r - 1.0, 6.0 ) ) ); * pow( f_n / 18.365, 2.745 ) ) )
C_e = 1.0 + 1.275 * - Q_12 + Q_16 - Q_17 + Q_18 + Q_20;
( 1.0 -
exp( -0.004625 * p_e *
pow( e_r,
1.674 ) * pow( f_n / 18.365, 2.745 ) ) ) - Q_12 + Q_16 - Q_17 + Q_18 + Q_20;
R_1 = 0.03891 * pow( e_r, 1.4 ); R_1 = 0.03891 * pow( e_r, 1.4 );
@ -774,42 +740,41 @@ void C_MICROSTRIP::Z0_dispersion()
R_7 = 1.206 - 0.3144 * exp( -R_1 ) * ( 1.0 - exp( -R_2 ) ); R_7 = 1.206 - 0.3144 * exp( -R_1 ) * ( 1.0 - exp( -R_2 ) );
R_10 = 0.00044 * pow( e_r, 2.136 ) + 0.0184; R_10 = 0.00044 * pow( e_r, 2.136 ) + 0.0184;
tmpf = pow( f_n / 19.47, 6.0 ); tmpf = pow( f_n / 19.47, 6.0 );
R_11 = tmpf / (1.0 + 0.0962 * tmpf); R_11 = tmpf / ( 1.0 + 0.0962 * tmpf );
R_12 = 1.0 / (1.0 + 0.00245 * u * u); R_12 = 1.0 / ( 1.0 + 0.00245 * u * u );
R_15 = 0.707* R_10* pow( f_n / 12.3, 1.097 ); R_15 = 0.707 * R_10 * pow( f_n / 12.3, 1.097 );
R_16 = 1.0 + 0.0503 * e_r * e_r * R_11 * ( 1.0 - exp( -pow( u / 15.0, 6.0 ) ) ); R_16 = 1.0 + 0.0503 * e_r * e_r * R_11 * ( 1.0 - exp( -pow( u / 15.0, 6.0 ) ) );
Q_0 = R_7 * ( 1.0 - 1.1241 * (R_12 / R_16) * exp( -0.026 * pow( f_n, 1.15656 ) - R_15 ) ); Q_0 = R_7 * ( 1.0 - 1.1241 * ( R_12 / R_16 ) * exp( -0.026 * pow( f_n, 1.15656 ) - R_15 ) );
/* even-mode frequency-dependent characteristic impedances */ /* even-mode frequency-dependent characteristic impedances */
Z0e = Z0_e_0 * pow( 0.9408 * pow( e_r_eff_single_f, C_e ) - 0.9603, Q_0 ) / pow( m_parameters[Z0_E_PRM] = Z0_e_0 * pow( 0.9408 * pow( e_r_eff_single_f, C_e ) - 0.9603, Q_0 )
(0.9408 - d_e) * pow( e_r_eff_single_0, C_e ) - 0.9603, Q_0 ); / pow( ( 0.9408 - d_e ) * pow( e_r_eff_single_0, C_e ) - 0.9603, Q_0 );
Q_29 = 15.16 / ( 1.0 + 0.196 * pow( e_r - 1.0, 2.0 ) ); Q_29 = 15.16 / ( 1.0 + 0.196 * pow( e_r - 1.0, 2.0 ) );
tmpf = pow( e_r - 1.0, 3.0 ); tmpf = pow( e_r - 1.0, 3.0 );
Q_28 = 0.149 * tmpf / (94.5 + 0.038 * tmpf); Q_28 = 0.149 * tmpf / ( 94.5 + 0.038 * tmpf );
tmpf = pow( e_r - 1.0, 1.5 ); tmpf = pow( e_r - 1.0, 1.5 );
Q_27 = 0.4 * pow( g, 0.84 ) * ( 1.0 + 2.5 * tmpf / (5.0 + tmpf) ); Q_27 = 0.4 * pow( g, 0.84 ) * ( 1.0 + 2.5 * tmpf / ( 5.0 + tmpf ) );
tmpf = pow( (e_r - 1.0) / 13.0, 12.0 ); tmpf = pow( ( e_r - 1.0 ) / 13.0, 12.0 );
Q_26 = 30.0 - 22.2 * ( tmpf / (1.0 + 3.0 * tmpf) ) - Q_29; Q_26 = 30.0 - 22.2 * ( tmpf / ( 1.0 + 3.0 * tmpf ) ) - Q_29;
tmpf = (e_r - 1.0) * (e_r - 1.0); tmpf = ( e_r - 1.0 ) * ( e_r - 1.0 );
Q_25 = ( 0.3 * f_n * f_n / (10.0 + f_n * f_n) ) * ( 1.0 + 2.333 * tmpf / (5.0 + tmpf) ); Q_25 = ( 0.3 * f_n * f_n / ( 10.0 + f_n * f_n ) ) * ( 1.0 + 2.333 * tmpf / ( 5.0 + tmpf ) );
Q_24 = Q_24 = 2.506 * Q_28 * pow( u, 0.894 ) * pow( ( 1.0 + 1.3 * u ) * f_n / 99.25, 4.29 )
2.506* Q_28* pow( u, / ( 3.575 + pow( u, 0.894 ) );
0.894 ) * Q_23 = 1.0
pow( (1.0 + 1.3 * u) * f_n / 99.25, 4.29 ) / ( 3.575 + pow( u, 0.894 ) ); + 0.005 * f_n * Q_27
Q_23 = 1.0 + 0.005 * f_n * Q_27 / / ( ( 1.0 + 0.812 * pow( f_n / 15.0, 1.9 ) ) * ( 1.0 + 0.025 * u * u ) );
( ( 1.0 + 0.812 * pow( f_n / 15.0, 1.9 ) ) * (1.0 + 0.025 * u * u) );
Q_22 = 0.925 * pow( f_n / Q_26, 1.536 ) / ( 1.0 + 0.3 * pow( f_n / 30.0, 1.536 ) ); Q_22 = 0.925 * pow( f_n / Q_26, 1.536 ) / ( 1.0 + 0.3 * pow( f_n / 30.0, 1.536 ) );
/* odd-mode frequency-dependent characteristic impedances */ /* odd-mode frequency-dependent characteristic impedances */
Z0o = Z0_single_f + m_parameters[Z0_O_PRM] =
(Z0_o_0 * Z0_single_f
pow( e_r_eff_o_f / e_r_eff_o_0, + ( Z0_o_0 * pow( e_r_eff_o_f / e_r_eff_o_0, Q_22 ) - Z0_single_f * Q_23 )
Q_22 ) - Z0_single_f * Q_23) / (1.0 + Q_24 + pow( 0.46 * g, 2.2 ) * Q_25); / ( 1.0 + Q_24 + pow( 0.46 * g, 2.2 ) * Q_25 );
} }
void C_MICROSTRIP::calc() void C_MICROSTRIP::calcAnalyze()
{ {
/* compute thickness corrections */ /* compute thickness corrections */
delta_u_thickness(); delta_u_thickness();
@ -828,67 +793,62 @@ void C_MICROSTRIP::calc()
} }
/* void C_MICROSTRIP::showAnalyze()
* get_microstrip_sub
* get and assign microstrip substrate parameters
* into microstrip structure
*/
void C_MICROSTRIP::get_c_microstrip_sub()
{ {
er = getProperty( EPSILONR_PRM ); setProperty( Z0_E_PRM, m_parameters[Z0_E_PRM] );
m_murC = getProperty( MURC_PRM ); setProperty( Z0_O_PRM, m_parameters[Z0_O_PRM] );
h = getProperty( H_PRM ); setProperty( ANG_L_PRM, sqrt( ang_l_e * ang_l_o ) );
ht = getProperty( H_T_PRM );
t = getProperty( T_PRM ); //Check for errors
m_sigma = 1.0/getProperty( RHO_PRM ); if( !std::isfinite( m_parameters[Z0_O_PRM] ) || m_parameters[Z0_O_PRM] <= 0.0 )
m_tand = getProperty( TAND_PRM ); setErrorLevel( Z0_O_PRM, TRANSLINE_ERROR );
rough = getProperty( ROUGH_PRM );
if( !std::isfinite( m_parameters[Z0_E_PRM] ) || m_parameters[Z0_E_PRM] <= 0.0 )
setErrorLevel( Z0_E_PRM, TRANSLINE_ERROR );
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] <= 0.0 )
setErrorLevel( ANG_L_PRM, TRANSLINE_ERROR );
// Check for warnings
if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || m_parameters[PHYS_WIDTH_PRM] <= 0.0 )
setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[PHYS_S_PRM] ) || m_parameters[PHYS_S_PRM] <= 0.0 )
setErrorLevel( PHYS_S_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] <= 0.0 )
setErrorLevel( PHYS_LEN_PRM, TRANSLINE_WARNING );
} }
void C_MICROSTRIP::showSynthesize()
/*
* get_c_microstrip_comp
* get and assign microstrip component parameters
* into microstrip structure
*/
void C_MICROSTRIP::get_c_microstrip_comp()
{ {
m_freq = getProperty( FREQUENCY_PRM ); setProperty( PHYS_WIDTH_PRM, m_parameters[PHYS_WIDTH_PRM] );
setProperty( PHYS_S_PRM, m_parameters[PHYS_S_PRM] );
setProperty( PHYS_LEN_PRM, m_parameters[PHYS_LEN_PRM] );
//Check for errors
if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || m_parameters[PHYS_WIDTH_PRM] <= 0.0 )
setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_ERROR );
if( !std::isfinite( m_parameters[PHYS_S_PRM] ) || m_parameters[PHYS_S_PRM] <= 0.0 )
setErrorLevel( PHYS_S_PRM, TRANSLINE_ERROR );
if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] <= 0.0 )
setErrorLevel( PHYS_LEN_PRM, TRANSLINE_ERROR );
// Check for warnings
if( !std::isfinite( m_parameters[Z0_O_PRM] ) || m_parameters[Z0_O_PRM] <= 0.0 )
setErrorLevel( Z0_O_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[Z0_E_PRM] ) || m_parameters[Z0_E_PRM] <= 0.0 )
setErrorLevel( Z0_E_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] <= 0.0 )
setErrorLevel( ANG_L_PRM, TRANSLINE_WARNING );
} }
/*
* get_c_microstrip_elec
* get and assign microstrip electrical parameters
* into microstrip structure
*/
void C_MICROSTRIP::get_c_microstrip_elec()
{
Z0e = getProperty( Z0_E_PRM );
Z0o = getProperty( Z0_O_PRM );
ang_l_e = getProperty( ANG_L_PRM );
ang_l_o = getProperty( ANG_L_PRM );
}
/*
* get_c_microstrip_phys
* get and assign microstrip physical parameters
* into microstrip structure
*/
void C_MICROSTRIP::get_c_microstrip_phys()
{
w = getProperty( PHYS_WIDTH_PRM );
s = getProperty( PHYS_S_PRM );
l = getProperty( PHYS_LEN_PRM );
}
void C_MICROSTRIP::show_results() void C_MICROSTRIP::show_results()
{ {
setProperty( Z0_E_PRM, Z0e );
setProperty( Z0_O_PRM , Z0o );
setProperty( ANG_L_PRM, sqrt( ang_l_e * ang_l_o ) );
setResult( 0, er_eff_e, "" ); setResult( 0, er_eff_e, "" );
setResult( 1, er_eff_o, "" ); setResult( 1, er_eff_o, "" );
@ -897,94 +857,65 @@ void C_MICROSTRIP::show_results()
setResult( 4, atten_dielectric_e, "dB" ); setResult( 4, atten_dielectric_e, "dB" );
setResult( 5, atten_dielectric_o, "dB" ); setResult( 5, atten_dielectric_o, "dB" );
setResult( 6, m_skindepth / UNIT_MICRON, "µm" ); setResult( 6, m_parameters[SKIN_DEPTH_PRM] / UNIT_MICRON, "µm" );
} }
/* void C_MICROSTRIP::syn_fun(
* analysis function double* f1, double* f2, double s_h, double w_h, double Z0_e, double Z0_o )
*/
void C_MICROSTRIP::analyze()
{ {
/* Get and assign substrate parameters */ m_parameters[PHYS_S_PRM] = s_h * m_parameters[H_PRM];
get_c_microstrip_sub(); m_parameters[PHYS_WIDTH_PRM] = w_h * m_parameters[H_PRM];
/* Get and assign component parameters */
get_c_microstrip_comp();
/* Get and assign physical parameters */
get_c_microstrip_phys();
/* compute coupled microstrip parameters */ /* compute coupled microstrip parameters */
calc(); calcAnalyze();
/* print results in the subwindow */
show_results();
}
*f1 = m_parameters[Z0_E_PRM] - Z0_e;
void C_MICROSTRIP::syn_fun( double* f1, *f2 = m_parameters[Z0_O_PRM] - Z0_o;
double* f2,
double s_h,
double w_h,
double Z0_e,
double Z0_o )
{
s = s_h * h;
w = w_h * h;
/* compute coupled microstrip parameters */
calc();
*f1 = Z0e - Z0_e;
*f2 = Z0o - Z0_o;
} }
/* /*
* synthesis function * synthesis function
*/ */
void C_MICROSTRIP::synthesize() void C_MICROSTRIP::calcSynthesize()
{ {
double Z0_e, Z0_o; double Z0_e, Z0_o, ang_l_dest;
double f1, f2, ft1, ft2, j11, j12, j21, j22, d_s_h, d_w_h, err; double f1, f2, ft1, ft2, j11, j12, j21, j22, d_s_h, d_w_h, err;
double eps = 1e-04; double eps = 1e-04;
double w_h, s_h, le, lo; double w_h, s_h, le, lo;
/* Get and assign substrate parameters */
get_c_microstrip_sub();
/* Get and assign component parameters */
get_c_microstrip_comp();
/* Get and assign electrical parameters */
get_c_microstrip_elec();
/* Get and assign physical parameters */
/* at present it is required only for getting strips length */
get_c_microstrip_phys();
/* required value of Z0_e and Z0_o */ /* required value of Z0_e and Z0_o */
Z0_e = Z0e; Z0_e = m_parameters[Z0_E_PRM];
Z0_o = Z0o; Z0_o = m_parameters[Z0_O_PRM];
ang_l_e = m_parameters[ANG_L_PRM];
ang_l_o = m_parameters[ANG_L_PRM];
ang_l_dest = m_parameters[ANG_L_PRM];
/* calculate width and use for initial value in Newton's method */ /* calculate width and use for initial value in Newton's method */
synth_width(); synth_width();
w_h = w / h; w_h = m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM];
s_h = s / h; s_h = m_parameters[PHYS_S_PRM] / m_parameters[H_PRM];
f1 = f2 = 0; f1 = f2 = 0;
/* rather crude Newton-Rhapson */ /* rather crude Newton-Rhapson */
do { do
{
/* compute Jacobian */ /* compute Jacobian */
syn_fun( &ft1, &ft2, s_h + eps, w_h, Z0_e, Z0_o ); syn_fun( &ft1, &ft2, s_h + eps, w_h, Z0_e, Z0_o );
j11 = (ft1 - f1) / eps; j11 = ( ft1 - f1 ) / eps;
j21 = (ft2 - f2) / eps; j21 = ( ft2 - f2 ) / eps;
syn_fun( &ft1, &ft2, s_h, w_h + eps, Z0_e, Z0_o ); syn_fun( &ft1, &ft2, s_h, w_h + eps, Z0_e, Z0_o );
j12 = (ft1 - f1) / eps; j12 = ( ft1 - f1 ) / eps;
j22 = (ft2 - f2) / eps; j22 = ( ft2 - f2 ) / eps;
/* compute next step; increments of s_h and w_h */ /* compute next step; increments of s_h and w_h */
d_s_h = (-f1 * j22 + f2 * j12) / (j11 * j22 - j21 * j12); d_s_h = ( -f1 * j22 + f2 * j12 ) / ( j11 * j22 - j21 * j12 );
d_w_h = (-f2 * j11 + f1 * j21) / (j11 * j22 - j21 * j12); d_w_h = ( -f2 * j11 + f1 * j21 ) / ( j11 * j22 - j21 * j12 );
s_h += d_s_h; s_h += d_s_h;
w_h += d_w_h; w_h += d_w_h;
@ -997,21 +928,18 @@ void C_MICROSTRIP::synthesize()
} while( err > 1e-04 ); } while( err > 1e-04 );
/* denormalize computed width and spacing */ /* denormalize computed width and spacing */
s = s_h * h; m_parameters[PHYS_S_PRM] = s_h * m_parameters[H_PRM];
w = w_h * h; m_parameters[PHYS_WIDTH_PRM] = w_h * m_parameters[H_PRM];
setProperty( PHYS_WIDTH_PRM, w );
setProperty( PHYS_S_PRM, s );
/* calculate physical length */ /* calculate physical length */
ang_l_e = getProperty( ANG_L_PRM ); le = C0 / m_parameters[FREQUENCY_PRM] / sqrt( er_eff_e ) * ang_l_dest / 2.0 / M_PI;
ang_l_o = getProperty( ANG_L_PRM ); lo = C0 / m_parameters[FREQUENCY_PRM] / sqrt( er_eff_o ) * ang_l_dest / 2.0 / M_PI;
le = C0 / m_freq / sqrt( er_eff_e ) * ang_l_e / 2.0 / M_PI; m_parameters[PHYS_LEN_PRM] = sqrt( le * lo );
lo = C0 / m_freq / sqrt( er_eff_o ) * ang_l_o / 2.0 / M_PI;
l = sqrt( le * lo );
setProperty( PHYS_LEN_PRM, l );
calc(); calcAnalyze();
/* print results in the subwindow */
show_results(); m_parameters[ANG_L_PRM] = ang_l_dest;
m_parameters[Z0_E_PRM] = Z0_e;
m_parameters[Z0_O_PRM] = Z0_o;
} }

View File

@ -25,9 +25,13 @@
#ifndef _C_MICROSTRIP_H_ #ifndef _C_MICROSTRIP_H_
#define _C_MICROSTRIP_H_ #define _C_MICROSTRIP_H_
#include <microstrip.h>
#include <transline.h>
class C_MICROSTRIP : public TRANSLINE class C_MICROSTRIP : public TRANSLINE
{ {
public: C_MICROSTRIP(); public:
C_MICROSTRIP();
~C_MICROSTRIP(); ~C_MICROSTRIP();
private: private:
@ -58,10 +62,6 @@ private:
double atten_dielectric_o; // odd-mode dielectric losses (dB) double atten_dielectric_o; // odd-mode dielectric losses (dB)
double atten_cond_o; // odd-mode conductors losses (dB) double atten_cond_o; // odd-mode conductors losses (dB)
public:
void analyze() override;
void synthesize() override;
private: private:
double delta_u_thickness_single( double, double ); double delta_u_thickness_single( double, double );
void delta_u_thickness(); void delta_u_thickness();
@ -82,12 +82,11 @@ private:
void syn_err_fun( double*, double*, double, double, double, double, double ); void syn_err_fun( double*, double*, double, double, double, double, double );
void synth_width(); void synth_width();
void Z0_dispersion(); void Z0_dispersion();
void calc(); void calcAnalyze() override;
void get_c_microstrip_sub(); void calcSynthesize() override;
void get_c_microstrip_comp(); void showAnalyze() override;
void get_c_microstrip_elec(); void showSynthesize() override;
void get_c_microstrip_phys(); void show_results() override;
void show_results();
void syn_fun( double*, double*, double, double, double, double ); void syn_fun( double*, double*, double, double, double, double );

View File

@ -27,86 +27,26 @@
* coax.c - Puts up window for microstrip and * coax.c - Puts up window for microstrip and
* performs the associated calculations * performs the associated calculations
*/ */
#include <cmath> #include <cmath>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <units.h>
#include <transline.h>
#include <coax.h> #include <coax.h>
#include <units.h>
COAX::COAX() : TRANSLINE() COAX::COAX() : TRANSLINE()
{ {
m_Name = "Coax"; m_Name = "Coax";
Init();
// Initialize these variables mainly to avoid warnings from a static analyzer
mur = 0.0; // magnetic permeability of substrate
din = 0.0; // Inner diameter of cable
dout = 0.0; // Outer diameter of cable
l = 0.0; // Length of cable
Z0 = 0.0; // characteristic impedance
ang_l = 0.0; // Electrical length in angle
atten_dielectric = 0.0; // Loss in dielectric (dB)
atten_cond = 0.0; // Loss in conductors (dB)
fc = 0.0; // Cutoff frequency for higher order modes
} }
/*
* get_coax_sub() - get and assign coax substrate parameters into coax
* structure
*/
void COAX::get_coax_sub()
{
er = getProperty( EPSILONR_PRM );
mur = getProperty( MUR_PRM );
m_murC = getProperty( MURC_PRM );
m_tand = getProperty( TAND_PRM );
m_sigma = 1.0 / getProperty( RHO_PRM );
}
/*
* get_coax_comp() - get and assign coax component parameters into
* coax structure
*/
void COAX::get_coax_comp()
{
m_freq = getProperty( FREQUENCY_PRM );
}
/*
* get_coax_elec() - get and assign coax electrical parameters into
* coax structure
*/
void COAX::get_coax_elec()
{
Z0 = getProperty( Z0_PRM );
ang_l = getProperty( ANG_L_PRM );
}
/*
* get_coax_phys() - get and assign coax physical parameters into coax
* structure
*/
void COAX::get_coax_phys()
{
din = getProperty( PHYS_DIAM_IN_PRM );
dout = getProperty( PHYS_DIAM_OUT_PRM );
l = getProperty( PHYS_LEN_PRM );
}
double COAX::alphad_coax() double COAX::alphad_coax()
{ {
double ad; double ad;
ad = (M_PI / C0) * m_freq * sqrt( er ) * m_tand; ad = ( M_PI / C0 ) * m_parameters[FREQUENCY_PRM] * sqrt( m_parameters[EPSILONR_PRM] )
* m_parameters[TAND_PRM];
ad = ad * 20.0 / log( 10.0 ); ad = ad * 20.0 / log( 10.0 );
return ad; return ad;
} }
@ -116,86 +56,165 @@ double COAX::alphac_coax()
{ {
double ac, Rs; double ac, Rs;
Rs = sqrt( M_PI * m_freq * m_murC * MU0 / m_sigma ); Rs = sqrt( M_PI * m_parameters[FREQUENCY_PRM] * m_parameters[MURC_PRM] * MU0
ac = sqrt( er ) * ( ( (1 / din) + (1 / dout) ) / log( dout / din ) ) * (Rs / ZF0); / m_parameters[SIGMA_PRM] );
ac = sqrt( m_parameters[EPSILONR_PRM] )
* ( ( ( 1 / m_parameters[PHYS_DIAM_IN_PRM] ) + ( 1 / m_parameters[PHYS_DIAM_OUT_PRM] ) )
/ log( m_parameters[PHYS_DIAM_OUT_PRM] / m_parameters[PHYS_DIAM_IN_PRM] ) )
* ( Rs / ZF0 );
ac = ac * 20.0 / log( 10.0 ); ac = ac * 20.0 / log( 10.0 );
return ac; return ac;
} }
/* /**
* analyze() - analysis function * \f$ Z_0 = \frac{Z_{0_{\mathrm{vaccum}}}}{\sqrt{\epsilon_r}}\log_{10}\left( \frac{D_{\mathrm{out}}}{D_{\mathrm{in}}}\right) \f$
*/ *
void COAX::analyze() * \f$ \lambda_g = \frac{c}{f \cdot \sqrt{ \epsilon_r \cdot \mu_r}} \f$
*
* \f$ L_{[\mathrm{rad}]} = \frac{ 2\pi\cdot L_{[\mathrm{m}]}}{\lambda_g} \f$
* */
void COAX::calcAnalyze()
{ {
double lambda_g; double lambda_g;
/* Get and assign substrate parameters */
get_coax_sub();
/* Get and assign component parameters */ m_parameters[Z0_PRM] =
get_coax_comp(); ( ZF0 / 2 / M_PI / sqrt( m_parameters[EPSILONR_PRM] ) )
* log( m_parameters[PHYS_DIAM_OUT_PRM] / m_parameters[PHYS_DIAM_IN_PRM] );
/* Get and assign physical parameters */ lambda_g = ( C0 / ( m_parameters[FREQUENCY_PRM] ) )
get_coax_phys(); / sqrt( m_parameters[EPSILONR_PRM] * m_parameters[MUR_PRM] );
if( din != 0.0 )
{
Z0 = ( ZF0 / 2 / M_PI / sqrt( er ) ) * log( dout / din );
}
lambda_g = ( C0 / (m_freq) ) / sqrt( er * mur );
/* calculate electrical angle */ /* calculate electrical angle */
ang_l = (2.0 * M_PI * l) / lambda_g; /* in radians */ m_parameters[ANG_L_PRM] =
( 2.0 * M_PI * m_parameters[PHYS_LEN_PRM] ) / lambda_g; /* in radians */
setProperty( Z0_PRM, Z0 );
setProperty( ANG_L_PRM, ang_l );
show_results();
} }
/* /**
* synthesize() - synthesis function * \f$ D_{\mathrm{in}} = D_{\mathrm{out}} \cdot e^{-\frac{Z_0*\sqrt{\epsilon_r}}{2\pi \cdot Z_{0_{\mathrm{vaccum}}}}} \f$
*/ *
void COAX::synthesize() * \f$ D_{\mathrm{out}} = D_{\mathrm{in}} \cdot e^{ \frac{Z_0*\sqrt{\epsilon_r}}{2\pi \cdot Z_{0_{\mathrm{vaccum}}}}} \f$
*
* \f$ \lambda_g = \frac{c}{f \cdot \sqrt{ \epsilon_r \cdot \mu_r}} \f$
*
* \f$ L_{[\mathrm{m}]} = \frac{ \lambda_g cdot L_{[\mathrm{m}]}}{2\pi} \f$
* */
void COAX::calcSynthesize()
{ {
double lambda_g; double lambda_g;
/* Get and assign substrate parameters */
get_coax_sub();
/* Get and assign component parameters */
get_coax_comp();
/* Get and assign electrical parameters */
get_coax_elec();
/* Get and assign physical parameters */
get_coax_phys();
if( isSelected( PHYS_DIAM_IN_PRM ) ) if( isSelected( PHYS_DIAM_IN_PRM ) )
{ {
/* solve for din */ /* solve for din */
din = dout / exp( Z0 * sqrt( er ) / ZF0 * 2 * M_PI ); m_parameters[PHYS_DIAM_IN_PRM] =
setProperty( PHYS_DIAM_IN_PRM, din ); m_parameters[PHYS_DIAM_OUT_PRM]
/ exp( m_parameters[Z0_PRM] * sqrt( m_parameters[EPSILONR_PRM] ) / ZF0 * 2 * M_PI );
} }
else if( isSelected( PHYS_DIAM_OUT_PRM ) ) else if( isSelected( PHYS_DIAM_OUT_PRM ) )
{ {
/* solve for dout */ /* solve for dout */
dout = din * exp( Z0 * sqrt( er ) / ZF0 * 2 * M_PI ); m_parameters[PHYS_DIAM_OUT_PRM] =
setProperty( PHYS_DIAM_OUT_PRM, dout ); m_parameters[PHYS_DIAM_IN_PRM]
* exp( m_parameters[Z0_PRM] * sqrt( m_parameters[EPSILONR_PRM] ) / ZF0 * 2 * M_PI );
} }
lambda_g = ( C0 / (m_freq) ) / sqrt( er * mur ); lambda_g = ( C0 / ( m_parameters[FREQUENCY_PRM] ) )
/ sqrt( m_parameters[EPSILONR_PRM] * m_parameters[MUR_PRM] );
/* calculate physical length */ /* calculate physical length */
l = (lambda_g * ang_l) / (2.0 * M_PI); /* in m */ m_parameters[PHYS_LEN_PRM] = ( lambda_g * m_parameters[ANG_L_PRM] ) / ( 2.0 * M_PI ); /* in m */
setProperty( PHYS_LEN_PRM, l );
show_results();
} }
void COAX::showAnalyze()
{
setProperty( Z0_PRM, m_parameters[Z0_PRM] );
setProperty( ANG_L_PRM, m_parameters[ANG_L_PRM] );
// Check for errors
if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
{
setErrorLevel( Z0_PRM, TRANSLINE_ERROR );
}
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
{
setErrorLevel( ANG_L_PRM, TRANSLINE_ERROR );
}
// Find warnings to display - physical parameters
if( !std::isfinite( m_parameters[PHYS_DIAM_IN_PRM] ) || m_parameters[PHYS_DIAM_IN_PRM] <= 0.0 )
{
setErrorLevel( PHYS_DIAM_IN_PRM, TRANSLINE_WARNING );
}
if( !std::isfinite( m_parameters[PHYS_DIAM_OUT_PRM] )
|| m_parameters[PHYS_DIAM_OUT_PRM] <= 0.0 )
{
setErrorLevel( PHYS_DIAM_OUT_PRM, TRANSLINE_WARNING );
}
if( m_parameters[PHYS_DIAM_IN_PRM] > m_parameters[PHYS_DIAM_OUT_PRM] )
{
setErrorLevel( PHYS_DIAM_IN_PRM, TRANSLINE_WARNING );
setErrorLevel( PHYS_DIAM_OUT_PRM, TRANSLINE_WARNING );
}
if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] < 0.0 )
{
setErrorLevel( PHYS_LEN_PRM, TRANSLINE_WARNING );
}
}
void COAX::showSynthesize()
{
if( isSelected( PHYS_DIAM_IN_PRM ) )
setProperty( PHYS_DIAM_IN_PRM, m_parameters[PHYS_DIAM_IN_PRM] );
else if( isSelected( PHYS_DIAM_OUT_PRM ) )
setProperty( PHYS_DIAM_OUT_PRM, m_parameters[PHYS_DIAM_OUT_PRM] );
setProperty( PHYS_LEN_PRM, m_parameters[PHYS_LEN_PRM] );
// Check for errors
if( !std::isfinite( m_parameters[PHYS_DIAM_IN_PRM] ) || m_parameters[PHYS_DIAM_IN_PRM] <= 0.0 )
{
if( isSelected( PHYS_DIAM_IN_PRM ) )
setErrorLevel( PHYS_DIAM_IN_PRM, TRANSLINE_ERROR );
else
setErrorLevel( PHYS_DIAM_IN_PRM, TRANSLINE_WARNING );
}
if( !std::isfinite( m_parameters[PHYS_DIAM_OUT_PRM] )
|| m_parameters[PHYS_DIAM_OUT_PRM] <= 0.0 )
{
if( isSelected( PHYS_DIAM_OUT_PRM ) )
setErrorLevel( PHYS_DIAM_OUT_PRM, TRANSLINE_ERROR );
else
setErrorLevel( PHYS_DIAM_OUT_PRM, TRANSLINE_WARNING );
}
if( m_parameters[PHYS_DIAM_IN_PRM] > m_parameters[PHYS_DIAM_OUT_PRM] )
{
if( isSelected( PHYS_DIAM_IN_PRM ) )
setErrorLevel( PHYS_DIAM_IN_PRM, TRANSLINE_ERROR );
else if( isSelected( PHYS_DIAM_OUT_PRM ) )
setErrorLevel( PHYS_DIAM_OUT_PRM, TRANSLINE_ERROR );
}
if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] < 0.0 )
{
setErrorLevel( PHYS_LEN_PRM, TRANSLINE_ERROR );
}
// Check for warnings
if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
{
setErrorLevel( Z0_PRM, TRANSLINE_WARNING );
}
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
{
setErrorLevel( ANG_L_PRM, TRANSLINE_WARNING );
}
}
/* /*
* show_results() - show results * show_results() - show results
*/ */
@ -204,45 +223,57 @@ void COAX::show_results()
int m, n; int m, n;
char text[256], txt[256]; char text[256], txt[256];
atten_dielectric = alphad_coax() * l; m_parameters[LOSS_DIELECTRIC_PRM] = alphad_coax() * m_parameters[PHYS_LEN_PRM];
atten_cond = alphac_coax() * l; m_parameters[LOSS_CONDUCTOR_PRM] = alphac_coax() * m_parameters[PHYS_LEN_PRM];
setResult( 0, er, "" ); setResult( 0, m_parameters[EPSILONR_PRM], "" );
setResult( 1, atten_cond, "dB" ); setResult( 1, m_parameters[LOSS_CONDUCTOR_PRM], "dB" );
setResult( 2, atten_dielectric, "dB" ); setResult( 2, m_parameters[LOSS_DIELECTRIC_PRM], "dB" );
n = 1; n = 1;
fc = C0 / (M_PI * (dout + din) / (double) n); m_parameters[CUTOFF_FREQUENCY_PRM] =
if( fc > m_freq ) C0
/ ( M_PI * ( m_parameters[PHYS_DIAM_OUT_PRM] + m_parameters[MUR_PRM] ) / (double) n );
if( m_parameters[CUTOFF_FREQUENCY_PRM] > m_parameters[FREQUENCY_PRM] )
strcpy( text, "none" ); strcpy( text, "none" );
else else
{ {
strcpy( text, "H(1,1) " ); strcpy( text, "H(1,1) " );
m = 2; m = 2;
fc = C0 / ( 2 * (dout - din) / (double) (m - 1) ); m_parameters[CUTOFF_FREQUENCY_PRM] =
while( (fc <= m_freq) && ( m < 10 ) ) C0
/ ( 2 * ( m_parameters[PHYS_DIAM_OUT_PRM] - m_parameters[MUR_PRM] )
/ (double) ( m - 1 ) );
while( ( m_parameters[CUTOFF_FREQUENCY_PRM] <= m_parameters[FREQUENCY_PRM] ) && ( m < 10 ) )
{ {
sprintf( txt, "H(n,%d) ", m ); sprintf( txt, "H(n,%d) ", m );
strcat( text, txt ); strcat( text, txt );
m++; m++;
fc = C0 / ( 2 * (dout - din) / (double) (m - 1) ); m_parameters[CUTOFF_FREQUENCY_PRM] =
C0
/ ( 2 * ( m_parameters[PHYS_DIAM_OUT_PRM] - m_parameters[MUR_PRM] )
/ (double) ( m - 1 ) );
} }
} }
setResult( 3, text ); setResult( 3, text );
m = 1; m = 1;
fc = C0 / (2 * (dout - din) / (double) m); m_parameters[CUTOFF_FREQUENCY_PRM] =
if( fc > m_freq ) C0 / ( 2 * ( m_parameters[PHYS_DIAM_OUT_PRM] - m_parameters[MUR_PRM] ) / (double) m );
if( m_parameters[CUTOFF_FREQUENCY_PRM] > m_parameters[FREQUENCY_PRM] )
strcpy( text, "none" ); strcpy( text, "none" );
else else
{ {
strcpy( text, "" ); strcpy( text, "" );
while( (fc <= m_freq) && ( m < 10 ) ) while( ( m_parameters[CUTOFF_FREQUENCY_PRM] <= m_parameters[FREQUENCY_PRM] ) && ( m < 10 ) )
{ {
sprintf( txt, "E(n,%d) ", m ); sprintf( txt, "E(n,%d) ", m );
strcat( text, txt ); strcat( text, txt );
m++; m++;
fc = C0 / (2 * (dout - din) / (double) m); m_parameters[CUTOFF_FREQUENCY_PRM] =
C0
/ ( 2 * ( m_parameters[PHYS_DIAM_OUT_PRM] - m_parameters[MUR_PRM] )
/ (double) m );
} }
} }
setResult( 4, text ); setResult( 4, text );

View File

@ -25,35 +25,21 @@
#ifndef __COAX_H #ifndef __COAX_H
#define __COAX_H #define __COAX_H
#include <transline.h>
class COAX : public TRANSLINE class COAX : public TRANSLINE
{ {
public: COAX();
private:
double mur; // magnetic permeability of substrate
double din; // Inner diameter of cable
double dout; // Outer diameter of cable
double l; // Length of cable
double Z0; // characteristic impedance
double ang_l; // Electrical length in angle
double atten_dielectric; // Loss in dielectric (dB)
double atten_cond; // Loss in conductors (dB)
double fc; // Cutoff frequency for higher order modes
public: public:
void analyze() override; COAX();
void synthesize() override;
private: private:
void get_coax_sub(); void calcAnalyze() override;
void get_coax_comp(); void calcSynthesize() override;
void get_coax_phys(); void showAnalyze() override;
void get_coax_elec(); void showSynthesize() override;
void fixdin();
void fixdout();
double alphad_coax(); double alphad_coax();
double alphac_coax(); double alphac_coax();
void show_results(); void show_results() override;
}; };
#endif // __COAX_H #endif // __COAX_H

View File

@ -28,26 +28,14 @@
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <units.h>
#include <transline.h>
#include <coplanar.h> #include <coplanar.h>
#include <units.h>
COPLANAR::COPLANAR() : TRANSLINE() COPLANAR::COPLANAR() : TRANSLINE()
{ {
m_Name = "CoPlanar"; m_Name = "CoPlanar";
backMetal = false; backMetal = false;
Init();
// Initialize these variables mainly to avoid warnings from a static analyzer
h = 0.0; // height of substrate
t = 0.0; // thickness of top metal
w = 0.0; // width of line
s = 0.0; // width of gap between line and ground
len = 0.0; // length of line
Z0 = 0.0; // characteristic impedance
ang_l = 0.0; // Electrical length in angle
atten_dielectric = 0.0; // Loss in dielectric (dB)
atten_cond = 0.0; // Loss in conductors (dB)
er_eff = 1.0; // Effective dielectric constant
} }
@ -59,74 +47,67 @@ GROUNDEDCOPLANAR::GROUNDEDCOPLANAR() : COPLANAR()
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void COPLANAR::getProperties() void COPLANAR::calcAnalyze()
{ {
m_freq = getProperty( FREQUENCY_PRM ); m_parameters[SKIN_DEPTH_PRM] = skin_depth();
w = getProperty( PHYS_WIDTH_PRM );
s = getProperty( PHYS_S_PRM );
len = getProperty( PHYS_LEN_PRM );
h = getProperty( H_PRM );
t = getProperty( T_PRM );
er = getProperty( EPSILONR_PRM );
m_murC = getProperty( MURC_PRM );
m_tand = getProperty( TAND_PRM );
m_sigma = 1.0 / getProperty( RHO_PRM );
Z0 = getProperty( Z0_PRM );
ang_l = getProperty( ANG_L_PRM );
}
// -------------------------------------------------------------------
void COPLANAR::calc()
{
m_skindepth = skin_depth();
// other local variables (quasi-static constants) // other local variables (quasi-static constants)
double k1, kk1, kpk1, k2, k3, q1, q2, q3 = 0, qz, er0 = 0; double k1, kk1, kpk1, k2, k3, q1, q2, q3 = 0, qz, er0 = 0;
double zl_factor; double zl_factor;
// compute the necessary quasi-static approx. (K1, K3, er(0) and Z(0)) // compute the necessary quasi-static approx. (K1, K3, er(0) and Z(0))
k1 = w / (w + s + s); k1 = m_parameters[PHYS_WIDTH_PRM]
/ ( m_parameters[PHYS_WIDTH_PRM] + m_parameters[PHYS_S_PRM] + m_parameters[PHYS_S_PRM] );
kk1 = ellipk( k1 ); kk1 = ellipk( k1 );
kpk1 = ellipk( sqrt( 1 - k1 * k1 ) ); kpk1 = ellipk( sqrt( 1 - k1 * k1 ) );
q1 = kk1 / kpk1; q1 = kk1 / kpk1;
// backside is metal // backside is metal
if( backMetal ) if( backMetal )
{ {
k3 = tanh( (M_PI / 4) * (w / h) ) / tanh( (M_PI / 4) * (w + s + s) / h ); k3 = tanh( ( M_PI / 4 ) * ( m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM] ) )
/ tanh( ( M_PI / 4 )
* ( m_parameters[PHYS_WIDTH_PRM] + m_parameters[PHYS_S_PRM]
+ m_parameters[PHYS_S_PRM] )
/ m_parameters[H_PRM] );
q3 = ellipk( k3 ) / ellipk( sqrt( 1 - k3 * k3 ) ); q3 = ellipk( k3 ) / ellipk( sqrt( 1 - k3 * k3 ) );
qz = 1 / (q1 + q3); qz = 1 / ( q1 + q3 );
er0 = 1 + q3 * qz * (er - 1); er0 = 1 + q3 * qz * ( m_parameters[EPSILONR_PRM] - 1 );
zl_factor = ZF0 / 2 * qz; zl_factor = ZF0 / 2 * qz;
} }
// backside is air // backside is air
else else
{ {
k2 = sinh( (M_PI / 4) * (w / h) ) / sinh( (M_PI / 4) * (w + s + s) / h ); k2 = sinh( ( M_PI / 4 ) * ( m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM] ) )
/ sinh( ( M_PI / 4 )
* ( m_parameters[PHYS_WIDTH_PRM] + m_parameters[PHYS_S_PRM]
+ m_parameters[PHYS_S_PRM] )
/ m_parameters[H_PRM] );
q2 = ellipk( k2 ) / ellipk( sqrt( 1 - k2 * k2 ) ); q2 = ellipk( k2 ) / ellipk( sqrt( 1 - k2 * k2 ) );
er0 = 1 + (er - 1) / 2 * q2 / q1; er0 = 1 + ( m_parameters[EPSILONR_PRM] - 1 ) / 2 * q2 / q1;
zl_factor = ZF0 / 4 / q1; zl_factor = ZF0 / 4 / q1;
} }
// adds effect of strip thickness // adds effect of strip thickness
if( t > 0 ) if( m_parameters[T_PRM] > 0 )
{ {
double d, se, We, ke, qe; double d, se, We, ke, qe;
d = (t * 1.25 / M_PI) * ( 1 + log( 4 * M_PI * w / t ) ); d = ( m_parameters[T_PRM] * 1.25 / M_PI )
se = s - d; * ( 1 + log( 4 * M_PI * m_parameters[PHYS_WIDTH_PRM] / m_parameters[T_PRM] ) );
We = w + d; se = m_parameters[PHYS_S_PRM] - d;
We = m_parameters[PHYS_WIDTH_PRM] + d;
// modifies k1 accordingly (k1 = ke) // modifies k1 accordingly (k1 = ke)
ke = We / (We + se + se); // ke = k1 + (1 - k1 * k1) * d / 2 / s; ke = We / ( We + se + se ); // ke = k1 + (1 - k1 * k1) * d / 2 / s;
qe = ellipk( ke ) / ellipk( sqrt( 1 - ke * ke ) ); qe = ellipk( ke ) / ellipk( sqrt( 1 - ke * ke ) );
// backside is metal // backside is metal
if( backMetal ) if( backMetal )
{ {
qz = 1 / (qe + q3); qz = 1 / ( qe + q3 );
er0 = 1 + q3 * qz * (er - 1); er0 = 1 + q3 * qz * ( m_parameters[EPSILONR_PRM] - 1 );
zl_factor = ZF0 / 2 * qz; zl_factor = ZF0 / 2 * qz;
} }
// backside is air // backside is air
@ -136,177 +117,147 @@ void COPLANAR::calc()
} }
// modifies er0 as well // modifies er0 as well
er0 = er0 - (0.7 * (er0 - 1) * t / s) / ( q1 + (0.7 * t / s) ); er0 = er0
- ( 0.7 * ( er0 - 1 ) * m_parameters[T_PRM] / m_parameters[PHYS_S_PRM] )
/ ( q1 + ( 0.7 * m_parameters[T_PRM] / m_parameters[PHYS_S_PRM] ) );
} }
// pre-compute square roots // pre-compute square roots
double sr_er = sqrt( er ); double sr_er = sqrt( m_parameters[EPSILONR_PRM] );
double sr_er0 = sqrt( er0 ); double sr_er0 = sqrt( er0 );
// cut-off frequency of the TE0 mode // cut-off frequency of the TE0 mode
double fte = (C0 / 4) / ( h * sqrt( er - 1 ) ); double fte = ( C0 / 4 ) / ( m_parameters[H_PRM] * sqrt( m_parameters[EPSILONR_PRM] - 1 ) );
// dispersion factor G // dispersion factor G
double p = log( w / h ); double p = log( m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM] );
double u = 0.54 - (0.64 - 0.015 * p) * p; double u = 0.54 - ( 0.64 - 0.015 * p ) * p;
double v = 0.43 - (0.86 - 0.54 * p) * p; double v = 0.43 - ( 0.86 - 0.54 * p ) * p;
double G = exp( u * log( w / s ) + v ); double G = exp( u * log( m_parameters[PHYS_WIDTH_PRM] / m_parameters[PHYS_S_PRM] ) + v );
// loss constant factors (computed only once for efficiency's sake) // loss constant factors (computed only once for efficiency's sake)
double ac = 0; double ac = 0;
if( t > 0 ) if( m_parameters[T_PRM] > 0 )
{ {
// equations by GHIONE // equations by GHIONE
double n = (1 - k1) * 8 * M_PI / ( t * (1 + k1) ); double n = ( 1 - k1 ) * 8 * M_PI / ( m_parameters[T_PRM] * ( 1 + k1 ) );
double a = w / 2; double a = m_parameters[PHYS_WIDTH_PRM] / 2;
double b = a + s; double b = a + m_parameters[PHYS_S_PRM];
ac = ( M_PI + log( n * a ) ) / a + ( M_PI + log( n * b ) ) / b; ac = ( M_PI + log( n * a ) ) / a + ( M_PI + log( n * b ) ) / b;
} }
double ac_factor = ac / ( 4 * ZF0 * kk1 * kpk1 * (1 - k1 * k1) ); double ac_factor = ac / ( 4 * ZF0 * kk1 * kpk1 * ( 1 - k1 * k1 ) );
double ad_factor = ( er / (er - 1) ) * m_tand * M_PI / C0; double ad_factor = ( m_parameters[EPSILONR_PRM] / ( m_parameters[EPSILONR_PRM] - 1 ) )
* m_parameters[TAND_PRM] * M_PI / C0;
// .................................................... // ....................................................
double sr_er_f = sr_er0; double sr_er_f = sr_er0;
// add the dispersive effects to er0 // add the dispersive effects to er0
sr_er_f += (sr_er - sr_er0) / ( 1 + G * pow( m_freq / fte, -1.8 ) ); sr_er_f += ( sr_er - sr_er0 ) / ( 1 + G * pow( m_parameters[FREQUENCY_PRM] / fte, -1.8 ) );
// for now, the loss are limited to strip losses (no radiation // for now, the loss are limited to strip losses (no radiation
// losses yet) losses in neper/length // losses yet) losses in neper/length
atten_cond = 20.0 / log( 10.0 ) * len m_parameters[LOSS_CONDUCTOR_PRM] =
* ac_factor * sr_er0 * sqrt( M_PI * MU0 * m_freq / m_sigma ); 20.0 / log( 10.0 ) * m_parameters[PHYS_LEN_PRM] * ac_factor * sr_er0
atten_dielectric = 20.0 / log( 10.0 ) * len * sqrt( M_PI * MU0 * m_parameters[FREQUENCY_PRM] / m_parameters[SIGMA_PRM] );
* ad_factor * m_freq * (sr_er_f * sr_er_f - 1) / sr_er_f; m_parameters[LOSS_DIELECTRIC_PRM] = 20.0 / log( 10.0 ) * m_parameters[PHYS_LEN_PRM] * ad_factor
* m_parameters[FREQUENCY_PRM] * ( sr_er_f * sr_er_f - 1 )
/ sr_er_f;
ang_l = 2.0 * M_PI * len * sr_er_f * m_freq / C0; /* in radians */ m_parameters[ANG_L_PRM] = 2.0 * M_PI * m_parameters[PHYS_LEN_PRM] * sr_er_f
* m_parameters[FREQUENCY_PRM] / C0; /* in radians */
er_eff = sr_er_f * sr_er_f; m_parameters[EPSILON_EFF_PRM] = sr_er_f * sr_er_f;
Z0 = zl_factor / sr_er_f; m_parameters[Z0_PRM] = zl_factor / sr_er_f;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void COPLANAR::show_results() void COPLANAR::show_results()
{ {
setProperty( Z0_PRM, Z0 );
setProperty( ANG_L_PRM, ang_l );
setResult( 0, er_eff, "" ); setResult( 0, m_parameters[EPSILON_EFF_PRM], "" );
setResult( 1, atten_cond, "dB" ); setResult( 1, m_parameters[LOSS_CONDUCTOR_PRM], "dB" );
setResult( 2, atten_dielectric, "dB" ); setResult( 2, m_parameters[LOSS_DIELECTRIC_PRM], "dB" );
setResult( 3, m_skindepth / UNIT_MICRON, "µm" ); setResult( 3, m_parameters[SKIN_DEPTH_PRM] / UNIT_MICRON, "µm" );
}
// -------------------------------------------------------------------
void COPLANAR::analyze()
{
getProperties();
/* compute coplanar parameters */
calc();
/* print results in the subwindow */
show_results();
} }
#define MAX_ERROR 0.000001 #define MAX_ERROR 0.000001
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void COPLANAR::synthesize() /* @function calcSynthesize
*
* @TODO Add a warning in case the synthetizin algorithm did not converge.
* Add it for all transmission lines that uses @ref minimizeZ0Error1D .
*/
void COPLANAR::calcSynthesize()
{ {
double Z0_dest, Z0_current, Z0_result, increment, slope, error;
int iteration;
getProperties();
/* required value of Z0 */
Z0_dest = Z0;
double ang_l_tmp = getProperty( ANG_L_PRM );
// compute inital coplanar parameters. This function modify Z0 and ang_l
// (set to NaN in some cases)
calc();
if( std::isnan( Z0 ) ) // cannot be synthesized with current parameters
{
Z0 = Z0_dest;
ang_l= ang_l_tmp;
if( isSelected( PHYS_WIDTH_PRM ) ) if( isSelected( PHYS_WIDTH_PRM ) )
{ {
setProperty( PHYS_WIDTH_PRM, NAN ); minimizeZ0Error1D( &( m_parameters[PHYS_WIDTH_PRM] ) );
} }
else else
{ {
setProperty( PHYS_S_PRM, NAN ); minimizeZ0Error1D( &( m_parameters[PHYS_S_PRM] ) );
} }
}
setProperty( PHYS_LEN_PRM, NAN );
// -------------------------------------------------------------------
/* print results in the subwindow */ void COPLANAR::showSynthesize()
show_results(); {
return; if( isSelected( PHYS_WIDTH_PRM ) )
} setProperty( PHYS_WIDTH_PRM, m_parameters[PHYS_WIDTH_PRM] );
/* Newton's method */ if( isSelected( PHYS_S_PRM ) )
iteration = 0; setProperty( PHYS_S_PRM, m_parameters[PHYS_S_PRM] );
Z0_current = Z0;
error = fabs( Z0_dest - Z0_current ); setProperty( PHYS_LEN_PRM, m_parameters[PHYS_LEN_PRM] );
while( error > MAX_ERROR ) if( !std::isfinite( m_parameters[PHYS_S_PRM] ) || m_parameters[PHYS_S_PRM] <= 0 )
{ {
iteration++; if( isSelected( PHYS_S_PRM ) )
if( isSelected( PHYS_WIDTH_PRM ) ) setErrorLevel( PHYS_S_PRM, TRANSLINE_ERROR );
{ else
increment = w / 100.0; setErrorLevel( PHYS_S_PRM, TRANSLINE_WARNING );
w += increment; }
} if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || m_parameters[PHYS_WIDTH_PRM] <= 0 )
else {
{ if( isSelected( PHYS_WIDTH_PRM ) )
increment = s / 100.0; setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_ERROR );
s += increment; else
} setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_WARNING );
/* compute coplanar parameters */ }
calc(); if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] < 0 )
Z0_result = Z0; setErrorLevel( PHYS_LEN_PRM, TRANSLINE_ERROR );
/* f(w(n)) = Z0 - Z0(w(n)) */
/* f'(w(n)) = -f'(Z0(w(n))) */ if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
/* f'(Z0(w(n))) = (Z0(w(n)) - Z0(w(n+delw))/delw */ setErrorLevel( Z0_PRM, TRANSLINE_WARNING );
/* w(n+1) = w(n) - f(w(n))/f'(w(n)) */
slope = (Z0_result - Z0_current) / increment; if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
slope = (Z0_dest - Z0_current) / slope - increment; setErrorLevel( ANG_L_PRM, TRANSLINE_WARNING );
if( isSelected( PHYS_WIDTH_PRM ) ) }
w += slope;
else
s += slope; void COPLANAR::showAnalyze()
if( w <= 0.0 ) {
w = increment; setProperty( Z0_PRM, m_parameters[Z0_PRM] );
if( s <= 0.0 ) setProperty( ANG_L_PRM, m_parameters[ANG_L_PRM] );
s = increment;
/* find new error */ if( !std::isfinite( m_parameters[PHYS_S_PRM] ) || m_parameters[PHYS_S_PRM] <= 0 )
/* compute coplanar parameters */ setErrorLevel( PHYS_S_PRM, TRANSLINE_WARNING );
calc();
Z0_current = Z0; if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || m_parameters[PHYS_WIDTH_PRM] <= 0 )
error = fabs( Z0_dest - Z0_current ); setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_WARNING );
if( iteration > 100 ) if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] < 0 )
break; setErrorLevel( PHYS_LEN_PRM, TRANSLINE_WARNING );
}
if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
setProperty( PHYS_WIDTH_PRM, w ); setErrorLevel( Z0_PRM, TRANSLINE_ERROR );
setProperty( PHYS_S_PRM, s );
/* calculate physical length */ if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
ang_l = getProperty( ANG_L_PRM ); setErrorLevel( ANG_L_PRM, TRANSLINE_ERROR );
len = C0 / m_freq / sqrt( er_eff ) * ang_l / 2.0 / M_PI; /* in m */
setProperty( PHYS_LEN_PRM, len );
/* compute coplanar parameters */
calc();
/* print results in the subwindow */
show_results();
} }

View File

@ -25,39 +25,31 @@
#ifndef __COPLANAR_H #ifndef __COPLANAR_H
#define __COPLANAR_H #define __COPLANAR_H
#include <transline.h>
class COPLANAR : public TRANSLINE class COPLANAR : public TRANSLINE
{ {
public: COPLANAR(); public:
COPLANAR();
private:
double h; // height of substrate
double t; // thickness of top metal
double w; // width of line
double s; // width of gap between line and ground
double len; // length of line
double Z0; // characteristic impedance
double er_eff; // effective dielectric constant
double ang_l; // Electrical length in angle
double atten_dielectric; // Loss in dielectric (dB)
double atten_cond; // Loss in conductors (dB)
public: public:
void analyze() override; void calcSynthesize() override;
void synthesize() override;
protected: protected:
bool backMetal; bool backMetal;
private: private:
void calc(); void calcAnalyze() override;
void show_results(); void showSynthesize() override;
void getProperties(); void showAnalyze() override;
void show_results() override;
}; };
class GROUNDEDCOPLANAR : public COPLANAR class GROUNDEDCOPLANAR : public COPLANAR
{ {
public: GROUNDEDCOPLANAR(); public:
GROUNDEDCOPLANAR();
}; };
#endif // __COPLANAR_H #endif // __COPLANAR_H

View File

@ -34,32 +34,15 @@
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <units.h>
#include <transline.h>
#include <microstrip.h> #include <microstrip.h>
#include <transline.h>
#include <units.h>
MICROSTRIP::MICROSTRIP() : TRANSLINE() MICROSTRIP::MICROSTRIP() : TRANSLINE()
{ {
m_Name = "MicroStrip"; m_Name = "MicroStrip";
Init();
// Initialize these variables mainly to avoid warnings from a static analyzer
h = 0.0; // height of substrate
ht = 0.0; // height to the top of box
t = 0.0; // thickness of top metal
rough = 0.0; // Roughness of top metal
mur = 0.0; // magnetic permeability of substrate
w = 0.0; // width of line
l = 0.0; // length of line
Z0_0 = 0.0; // static characteristic impedance
Z0 = 0.0; // characteristic impedance
ang_l = 0.0; // Electrical length in angle
er_eff_0 = 0.0; // Static effective dielectric constant
er_eff = 0.0; // Effective dielectric constant
mur_eff = 0.0; // Effective mag. permeability
w_eff = 0.0; // Effective width of line
atten_dielectric = 0.0; // Loss in dielectric (dB)
atten_cond = 0.0; // Loss in conductors (dB)
Z0_h_1 = 0.0; // homogeneous stripline impedance
} }
@ -71,8 +54,8 @@ double MICROSTRIP::Z0_homogeneous( double u )
{ {
double freq, Z0_value; double freq, Z0_value;
freq = 6.0 + (2.0 * M_PI - 6.0) * exp( -pow( 30.666 / u, 0.7528 ) ); freq = 6.0 + ( 2.0 * M_PI - 6.0 ) * exp( -pow( 30.666 / u, 0.7528 ) );
Z0_value = ( ZF0 / (2.0 * M_PI) ) * log( freq / u + sqrt( 1.0 + 4.0 / (u * u) ) ); Z0_value = ( ZF0 / ( 2.0 * M_PI ) ) * log( freq / u + sqrt( 1.0 + 4.0 / ( u * u ) ) );
return Z0_value; return Z0_value;
} }
@ -88,7 +71,7 @@ double MICROSTRIP::delta_Z0_cover( double u, double h2h )
h2hp1 = 1.0 + h2h; h2hp1 = 1.0 + h2h;
P = 270.0 * ( 1.0 - tanh( 1.192 + 0.706 * sqrt( h2hp1 ) - 1.389 / h2hp1 ) ); P = 270.0 * ( 1.0 - tanh( 1.192 + 0.706 * sqrt( h2hp1 ) - 1.389 / h2hp1 ) );
Q = 1.0109 - atanh( (0.012 * u + 0.177 * u * u - 0.027 * u * u * u) / (h2hp1 * h2hp1) ); Q = 1.0109 - atanh( ( 0.012 * u + 0.177 * u * u - 0.027 * u * u * u ) / ( h2hp1 * h2hp1 ) );
return P * Q; return P * Q;
} }
@ -105,9 +88,8 @@ double MICROSTRIP::filling_factor( double u, double e_r )
u2 = u * u; u2 = u * u;
u3 = u2 * u; u3 = u2 * u;
u4 = u3 * u; u4 = u3 * u;
a = 1.0 + a = 1.0 + log( ( u4 + u2 / 2704 ) / ( u4 + 0.432 ) ) / 49.0 + log( 1.0 + u3 / 5929.741 ) / 18.7;
log( (u4 + u2 / 2704) / (u4 + 0.432) ) / 49.0 + log( 1.0 + u3 / 5929.741 ) / 18.7; b = 0.564 * pow( ( e_r - 0.9 ) / ( e_r + 3.0 ), 0.053 );
b = 0.564 * pow( (e_r - 0.9) / (e_r + 3.0), 0.053 );
q_inf = pow( 1.0 + 10.0 / u, -a * b ); q_inf = pow( 1.0 + 10.0 / u, -a * b );
return q_inf; return q_inf;
} }
@ -132,7 +114,7 @@ double MICROSTRIP::delta_q_thickness( double u, double t_h )
{ {
double q_t; double q_t;
q_t = (2.0 * log( 2.0 ) / M_PI) * ( t_h / sqrt( u ) ); q_t = ( 2.0 * log( 2.0 ) / M_PI ) * ( t_h / sqrt( u ) );
return q_t; return q_t;
} }
@ -145,7 +127,7 @@ double MICROSTRIP::e_r_effective( double e_r, double q )
{ {
double e_r_eff; double e_r_eff;
e_r_eff = 0.5 * (e_r + 1.0) + 0.5 * q * (e_r - 1.0); e_r_eff = 0.5 * ( e_r + 1.0 ) + 0.5 * q * ( e_r - 1.0 );
return e_r_eff; return e_r_eff;
} }
@ -160,8 +142,8 @@ double MICROSTRIP::delta_u_thickness( double u, double t_h, double e_r )
if( t_h > 0.0 ) if( t_h > 0.0 )
{ {
/* correction for thickness for a homogeneous microstrip */ /* correction for thickness for a homogeneous microstrip */
delta_u = (t_h / M_PI) * log( 1.0 + (4.0 * M_E) * pow( tanh( sqrt( delta_u = ( t_h / M_PI )
6.517 * u ) ), 2.0 ) / t_h ); * log( 1.0 + ( 4.0 * M_E ) * pow( tanh( sqrt( 6.517 * u ) ), 2.0 ) / t_h );
/* correction for strip on a substrate with relative permettivity e_r */ /* correction for strip on a substrate with relative permettivity e_r */
delta_u = 0.5 * delta_u * ( 1.0 + 1.0 / cosh( sqrt( e_r - 1.0 ) ) ); delta_u = 0.5 * delta_u * ( 1.0 + 1.0 / cosh( sqrt( e_r - 1.0 ) ) );
} }
@ -182,11 +164,11 @@ void MICROSTRIP::microstrip_Z0()
double Z0_h_r; double Z0_h_r;
double delta_u_1, delta_u_r, q_inf, q_c, q_t, e_r_eff, e_r_eff_t, q; double delta_u_1, delta_u_r, q_inf, q_c, q_t, e_r_eff, e_r_eff_t, q;
e_r = er; e_r = m_parameters[EPSILONR_PRM];
h2 = ht; h2 = m_parameters[H_T_PRM];
h2h = h2 / h; h2h = h2 / m_parameters[H_PRM];
u = w / h; u = m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM];
t_h = t / h; t_h = m_parameters[T_PRM] / m_parameters[H_PRM];
/* compute normalized width correction for e_r = 1.0 */ /* compute normalized width correction for e_r = 1.0 */
delta_u_1 = delta_u_thickness( u, t_h, 1.0 ); delta_u_1 = delta_u_thickness( u, t_h, 1.0 );
@ -205,7 +187,7 @@ void MICROSTRIP::microstrip_Z0()
/* thickness effect */ /* thickness effect */
q_t = delta_q_thickness( u, t_h ); q_t = delta_q_thickness( u, t_h );
/* resultant filling factor */ /* resultant filling factor */
q = (q_inf - q_t) * q_c; q = ( q_inf - q_t ) * q_c;
/* e_r corrected for thickness and non homogeneous material */ /* e_r corrected for thickness and non homogeneous material */
e_r_eff_t = e_r_effective( e_r, q ); e_r_eff_t = e_r_effective( e_r, q );
@ -215,11 +197,11 @@ void MICROSTRIP::microstrip_Z0()
/* characteristic impedance, corrected for thickness, cover */ /* characteristic impedance, corrected for thickness, cover */
/* and non homogeneous material */ /* and non homogeneous material */
Z0 = Z0_h_r / sqrt( e_r_eff_t ); m_parameters[Z0_PRM] = Z0_h_r / sqrt( e_r_eff_t );
w_eff = u * h; w_eff = u * m_parameters[H_PRM];
er_eff_0 = e_r_eff; er_eff_0 = e_r_eff;
Z0_0 = Z0; Z0_0 = m_parameters[Z0_PRM];
} }
@ -231,13 +213,13 @@ double MICROSTRIP::e_r_dispersion( double u, double e_r, double f_n )
{ {
double P_1, P_2, P_3, P_4, P; double P_1, P_2, P_3, P_4, P;
P_1 = 0.27488 + u * ( 0.6315 + 0.525 / pow( 1.0 + 0.0157 * f_n, 20.0 ) ) - 0.065683 * exp( P_1 = 0.27488 + u * ( 0.6315 + 0.525 / pow( 1.0 + 0.0157 * f_n, 20.0 ) )
-8.7513 * u ); - 0.065683 * exp( -8.7513 * u );
P_2 = 0.33622 * ( 1.0 - exp( -0.03442 * e_r ) ); P_2 = 0.33622 * ( 1.0 - exp( -0.03442 * e_r ) );
P_3 = 0.0363 * exp( -4.6 * u ) * ( 1.0 - exp( -pow( f_n / 38.7, 4.97 ) ) ); P_3 = 0.0363 * exp( -4.6 * u ) * ( 1.0 - exp( -pow( f_n / 38.7, 4.97 ) ) );
P_4 = 1.0 + 2.751 * ( 1.0 - exp( -pow( e_r / 15.916, 8.0 ) ) ); P_4 = 1.0 + 2.751 * ( 1.0 - exp( -pow( e_r / 15.916, 8.0 ) ) );
P = P_1 * P_2 * pow( (P_3 * P_4 + 0.1844) * f_n, 1.5763 ); P = P_1 * P_2 * pow( ( P_3 * P_4 + 0.1844 ) * f_n, 1.5763 );
return P; return P;
} }
@ -247,11 +229,8 @@ double MICROSTRIP::e_r_dispersion( double u, double e_r, double f_n )
* Z0_dispersion() - computes the dispersion correction factor for the * Z0_dispersion() - computes the dispersion correction factor for the
* characteristic impedance * characteristic impedance
*/ */
double MICROSTRIP::Z0_dispersion( double u, double MICROSTRIP::Z0_dispersion(
double e_r, double u, double e_r, double e_r_eff_0, double e_r_eff_f, double f_n )
double e_r_eff_0,
double e_r_eff_f,
double f_n )
{ {
double R_1, R_2, R_3, R_4, R_5, R_6, R_7, R_8, R_9, R_10, R_11, R_12, R_13, R_14, R_15, R_16, double R_1, R_2, R_3, R_4, R_5, R_6, R_7, R_8, R_9, R_10, R_11, R_12, R_13, R_14, R_15, R_16,
R_17, D, tmpf; R_17, D, tmpf;
@ -263,22 +242,23 @@ double MICROSTRIP::Z0_dispersion( double u,
R_5 = pow( f_n / 28.843, 12.0 ); R_5 = pow( f_n / 28.843, 12.0 );
R_6 = 22.2 * pow( u, 1.92 ); R_6 = 22.2 * pow( u, 1.92 );
R_7 = 1.206 - 0.3144 * exp( -R_1 ) * ( 1.0 - exp( -R_2 ) ); R_7 = 1.206 - 0.3144 * exp( -R_1 ) * ( 1.0 - exp( -R_2 ) );
R_8 = 1.0 + 1.275 * R_8 = 1.0
( 1.0 - exp( -0.004625 * R_3 * pow( e_r, 1.674 ) * pow( f_n / 18.365, 2.745 ) ) ); + 1.275
* ( 1.0
- exp( -0.004625 * R_3 * pow( e_r, 1.674 )
* pow( f_n / 18.365, 2.745 ) ) );
tmpf = pow( e_r - 1.0, 6.0 ); tmpf = pow( e_r - 1.0, 6.0 );
R_9 = 5.086 * R_4 * R_9 = 5.086 * R_4 * ( R_5 / ( 0.3838 + 0.386 * R_4 ) )
( R_5 / * ( exp( -R_6 ) / ( 1.0 + 1.2992 * R_5 ) ) * ( tmpf / ( 1.0 + 10.0 * tmpf ) );
(0.3838 + 0.386 *
R_4) ) * ( exp( -R_6 ) / (1.0 + 1.2992 * R_5) ) * ( tmpf / (1.0 + 10.0 * tmpf) );
R_10 = 0.00044 * pow( e_r, 2.136 ) + 0.0184; R_10 = 0.00044 * pow( e_r, 2.136 ) + 0.0184;
tmpf = pow( f_n / 19.47, 6.0 ); tmpf = pow( f_n / 19.47, 6.0 );
R_11 = tmpf / (1.0 + 0.0962 * tmpf); R_11 = tmpf / ( 1.0 + 0.0962 * tmpf );
R_12 = 1.0 / (1.0 + 0.00245 * u * u); R_12 = 1.0 / ( 1.0 + 0.00245 * u * u );
R_13 = 0.9408 * pow( e_r_eff_f, R_8 ) - 0.9603; R_13 = 0.9408 * pow( e_r_eff_f, R_8 ) - 0.9603;
R_14 = (0.9408 - R_9) * pow( e_r_eff_0, R_8 ) - 0.9603; R_14 = ( 0.9408 - R_9 ) * pow( e_r_eff_0, R_8 ) - 0.9603;
R_15 = 0.707* R_10* pow( f_n / 12.3, 1.097 ); R_15 = 0.707 * R_10 * pow( f_n / 12.3, 1.097 );
R_16 = 1.0 + 0.0503 * e_r * e_r * R_11 * ( 1.0 - exp( -pow( u / 15.0, 6.0 ) ) ); R_16 = 1.0 + 0.0503 * e_r * e_r * R_11 * ( 1.0 - exp( -pow( u / 15.0, 6.0 ) ) );
R_17 = R_7 * ( 1.0 - 1.1241 * (R_12 / R_16) * exp( -0.026 * pow( f_n, 1.15656 ) - R_15 ) ); R_17 = R_7 * ( 1.0 - 1.1241 * ( R_12 / R_16 ) * exp( -0.026 * pow( f_n, 1.15656 ) - R_15 ) );
D = pow( R_13 / R_14, R_17 ); D = pow( R_13 / R_14, R_17 );
@ -295,22 +275,22 @@ void MICROSTRIP::dispersion()
double e_r, e_r_eff_0; double e_r, e_r_eff_0;
double u, f_n, P, e_r_eff_f, D, Z0_f; double u, f_n, P, e_r_eff_f, D, Z0_f;
e_r = er; e_r = m_parameters[EPSILONR_PRM];
e_r_eff_0 = er_eff_0; e_r_eff_0 = er_eff_0;
u = w / h; u = m_parameters[PHYS_WIDTH_PRM] / m_parameters[H_PRM];
/* normalized frequency [GHz * mm] */ /* normalized frequency [GHz * mm] */
f_n = m_freq * h / 1e06; f_n = m_parameters[FREQUENCY_PRM] * m_parameters[H_PRM] / 1e06;
P = e_r_dispersion( u, e_r, f_n ); P = e_r_dispersion( u, e_r, f_n );
/* effective dielectric constant corrected for dispersion */ /* effective dielectric constant corrected for dispersion */
e_r_eff_f = e_r - (e_r - e_r_eff_0) / (1.0 + P); e_r_eff_f = e_r - ( e_r - e_r_eff_0 ) / ( 1.0 + P );
D = Z0_dispersion( u, e_r, e_r_eff_0, e_r_eff_f, f_n ); D = Z0_dispersion( u, e_r, e_r_eff_0, e_r_eff_f, f_n );
Z0_f = Z0_0 * D; Z0_f = Z0_0 * D;
er_eff = e_r_eff_f; er_eff = e_r_eff_f;
Z0 = Z0_f; m_parameters[Z0_PRM] = Z0_f;
} }
@ -324,20 +304,24 @@ double MICROSTRIP::conductor_losses()
double K, R_s, Q_c, alpha_c; double K, R_s, Q_c, alpha_c;
e_r_eff_0 = er_eff_0; e_r_eff_0 = er_eff_0;
delta = m_skindepth; delta = m_parameters[SKIN_DEPTH_PRM];
if( m_freq > 0.0 ) if( m_parameters[FREQUENCY_PRM] > 0.0 )
{ {
/* current distribution factor */ /* current distribution factor */
K = exp( -1.2 * pow( Z0_h_1 / ZF0, 0.7 ) ); K = exp( -1.2 * pow( Z0_h_1 / ZF0, 0.7 ) );
/* skin resistance */ /* skin resistance */
R_s = 1.0 / (m_sigma * delta); R_s = 1.0 / ( m_parameters[SIGMA_PRM] * delta );
/* correction for surface roughness */ /* correction for surface roughness */
R_s *= 1.0 + ( (2.0 / M_PI) * atan( 1.40 * pow( (rough / delta), 2.0 ) ) ); R_s *= 1.0
+ ( ( 2.0 / M_PI )
* atan( 1.40 * pow( ( m_parameters[ROUGH_PRM] / delta ), 2.0 ) ) );
/* strip inductive quality factor */ /* strip inductive quality factor */
Q_c = (M_PI * Z0_h_1 * w * m_freq) / (R_s * C0 * K); Q_c = ( M_PI * Z0_h_1 * m_parameters[PHYS_WIDTH_PRM] * m_parameters[FREQUENCY_PRM] )
alpha_c = ( 20.0 * M_PI / log( 10.0 ) ) * m_freq * sqrt( e_r_eff_0 ) / (C0 * Q_c); / ( R_s * C0 * K );
alpha_c = ( 20.0 * M_PI / log( 10.0 ) ) * m_parameters[FREQUENCY_PRM] * sqrt( e_r_eff_0 )
/ ( C0 * Q_c );
} }
else else
{ {
@ -357,13 +341,12 @@ double MICROSTRIP::dielectric_losses()
double e_r, e_r_eff_0; double e_r, e_r_eff_0;
double alpha_d; double alpha_d;
e_r = er; e_r = m_parameters[EPSILONR_PRM];
e_r_eff_0 = er_eff_0; e_r_eff_0 = er_eff_0;
alpha_d = alpha_d = ( 20.0 * M_PI / log( 10.0 ) ) * ( m_parameters[FREQUENCY_PRM] / C0 )
( 20.0 * M_PI / * ( e_r / sqrt( e_r_eff_0 ) ) * ( ( e_r_eff_0 - 1.0 ) / ( e_r - 1.0 ) )
log( 10.0 ) ) * * m_parameters[TAND_PRM];
(m_freq / C0) * ( e_r / sqrt( e_r_eff_0 ) ) * ( (e_r_eff_0 - 1.0) / (e_r - 1.0) ) * m_tand;
return alpha_d; return alpha_d;
} }
@ -374,10 +357,10 @@ double MICROSTRIP::dielectric_losses()
*/ */
void MICROSTRIP::attenuation() void MICROSTRIP::attenuation()
{ {
m_skindepth = skin_depth(); m_parameters[SKIN_DEPTH_PRM] = skin_depth();
atten_cond = conductor_losses() * l; atten_cond = conductor_losses() * m_parameters[PHYS_LEN_PRM];
atten_dielectric = dielectric_losses() * l; atten_dielectric = dielectric_losses() * m_parameters[PHYS_LEN_PRM];
} }
@ -386,7 +369,11 @@ void MICROSTRIP::attenuation()
*/ */
void MICROSTRIP::mur_eff_ms() void MICROSTRIP::mur_eff_ms()
{ {
mur_eff = (2.0 * mur) / ( (1.0 + mur) + ( (1.0 - mur) * pow( ( 1.0 + (10.0 * h / w) ), -0.5 ) ) ); double* mur = &m_parameters[MUR_PRM];
double* h = &m_parameters[H_PRM];
double* w = &m_parameters[PHYS_WIDTH_PRM];
mur_eff = ( 2.0 * *mur )
/ ( ( 1.0 + *mur ) + ( ( 1.0 - *mur ) * pow( ( 1.0 + ( 10.0 * *h / *w ) ), -0.5 ) ) );
} }
@ -396,24 +383,25 @@ double MICROSTRIP::synth_width()
double e_r, a, b; double e_r, a, b;
double w_h, width; double w_h, width;
e_r = er; e_r = m_parameters[EPSILONR_PRM];
a = ( (Z0 / ZF0 / 2 / a = ( ( m_parameters[Z0_PRM] / ZF0 / 2 / M_PI ) * sqrt( ( e_r + 1 ) / 2. ) )
M_PI) * sqrt( (e_r + 1) / 2. ) ) + ( (e_r - 1) / (e_r + 1) * ( 0.23 + (0.11 / e_r) ) ); + ( ( e_r - 1 ) / ( e_r + 1 ) * ( 0.23 + ( 0.11 / e_r ) ) );
b = ZF0 / 2 * M_PI / ( Z0 * sqrt( e_r ) ); b = ZF0 / 2 * M_PI / ( m_parameters[Z0_PRM] * sqrt( e_r ) );
if( a > 1.52 ) if( a > 1.52 )
{ {
w_h = 8 * exp( a ) / (exp( 2. * a ) - 2); w_h = 8 * exp( a ) / ( exp( 2. * a ) - 2 );
} }
else else
{ {
w_h = (2. / M_PI) * ( b - 1. - w_h = ( 2. / M_PI )
log( (2 * b) - 1. ) + ( (e_r - 1) / (2 * e_r) ) * (log( b - 1. ) + 0.39 - 0.61 / e_r) ); * ( b - 1. - log( ( 2 * b ) - 1. )
+ ( ( e_r - 1 ) / ( 2 * e_r ) ) * ( log( b - 1. ) + 0.39 - 0.61 / e_r ) );
} }
if( h > 0.0 ) if( m_parameters[H_PRM] > 0.0 )
width = w_h * h; width = w_h * m_parameters[H_PRM];
else else
width = 0; width = 0;
@ -434,13 +422,13 @@ void MICROSTRIP::line_angle()
/* velocity */ /* velocity */
v = C0 / sqrt( e_r_eff * mur_eff ); v = C0 / sqrt( e_r_eff * mur_eff );
/* wavelength */ /* wavelength */
lambda_g = v / m_freq; lambda_g = v / m_parameters[FREQUENCY_PRM];
/* electrical angles */ /* electrical angles */
ang_l = 2.0 * M_PI * l / lambda_g; /* in radians */ m_parameters[ANG_L_PRM] = 2.0 * M_PI * m_parameters[PHYS_LEN_PRM] / lambda_g; /* in radians */
} }
void MICROSTRIP::calc() void MICROSTRIP::calcAnalyze()
{ {
/* effective permeability */ /* effective permeability */
mur_eff_ms(); mur_eff_ms();
@ -455,167 +443,78 @@ void MICROSTRIP::calc()
} }
/*
* get_microstrip_sub () - get and assign microstrip substrate
* parameters into microstrip structure
*/
void MICROSTRIP::get_microstrip_sub()
{
er = getProperty( EPSILONR_PRM );
mur = getProperty( MUR_PRM );
h = getProperty( H_PRM );
ht = getProperty( H_T_PRM );
t = getProperty( T_PRM );
m_sigma = 1.0 / getProperty( RHO_PRM );
m_murC = getProperty( MURC_PRM );
m_tand = getProperty( TAND_PRM );
rough = getProperty( ROUGH_PRM );
}
/*
* get_microstrip_comp() - get and assign microstrip component
* parameters into microstrip structure
*/
void MICROSTRIP::get_microstrip_comp()
{
m_freq = getProperty( FREQUENCY_PRM );
}
/*
* get_microstrip_elec() - get and assign microstrip electrical
* parameters into microstrip structure
*/
void MICROSTRIP::get_microstrip_elec()
{
Z0 = getProperty( Z0_PRM );
ang_l = getProperty( ANG_L_PRM );
}
/*
* get_microstrip_phys() - get and assign microstrip physical
* parameters into microstrip structure
*/
void MICROSTRIP::get_microstrip_phys()
{
w = getProperty( PHYS_WIDTH_PRM );
l = getProperty( PHYS_LEN_PRM );
}
void MICROSTRIP::show_results() void MICROSTRIP::show_results()
{ {
setProperty( Z0_PRM, Z0 ); setProperty( Z0_PRM, m_parameters[Z0_PRM] );
setProperty( ANG_L_PRM, ang_l ); setProperty( ANG_L_PRM, m_parameters[ANG_L_PRM] );
setResult( 0, er_eff, "" ); setResult( 0, er_eff, "" );
setResult( 1, atten_cond, "dB" ); setResult( 1, atten_cond, "dB" );
setResult( 2, atten_dielectric, "dB" ); setResult( 2, atten_dielectric, "dB" );
setResult( 3, m_skindepth/UNIT_MICRON, "µm" ); setResult( 3, m_parameters[SKIN_DEPTH_PRM] / UNIT_MICRON, "µm" );
} }
/* void MICROSTRIP::showSynthesize()
* analysis function
*/
void MICROSTRIP::analyze()
{ {
/* Get and assign substrate parameters */ setProperty( PHYS_WIDTH_PRM, m_parameters[PHYS_WIDTH_PRM] );
get_microstrip_sub(); setProperty( PHYS_LEN_PRM, m_parameters[PHYS_LEN_PRM] );
/* Get and assign component parameters */ // Check for errors
get_microstrip_comp(); if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || ( m_parameters[PHYS_LEN_PRM] < 0 ) )
setErrorLevel( PHYS_LEN_PRM, TRANSLINE_ERROR );
/* Get and assign physical parameters */ if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || ( m_parameters[PHYS_WIDTH_PRM] <= 0 ) )
get_microstrip_phys(); setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_ERROR );
/* compute microstrip parameters */ // Check for warnings
calc();
/* print results in the subwindow */ if( !std::isfinite( m_parameters[Z0_PRM] ) || ( m_parameters[Z0_PRM] < 0 ) )
show_results(); setErrorLevel( Z0_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || ( m_parameters[ANG_L_PRM] < 0 ) )
setErrorLevel( ANG_L_PRM, TRANSLINE_WARNING );
} }
void MICROSTRIP::showAnalyze()
{
setProperty( Z0_PRM, m_parameters[Z0_PRM] );
setProperty( ANG_L_PRM, m_parameters[ANG_L_PRM] );
#define MAX_ERROR 0.000001 // Check for errors
if( !std::isfinite( m_parameters[Z0_PRM] ) || ( m_parameters[Z0_PRM] < 0 ) )
setErrorLevel( Z0_PRM, TRANSLINE_ERROR );
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || ( m_parameters[ANG_L_PRM] < 0 ) )
setErrorLevel( ANG_L_PRM, TRANSLINE_ERROR );
// Check for warnings
if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || ( m_parameters[PHYS_LEN_PRM] < 0 ) )
setErrorLevel( PHYS_LEN_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || ( m_parameters[PHYS_WIDTH_PRM] <= 0 ) )
setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_WARNING );
}
/* /*
* synthesis function * synthesis function
*/ */
void MICROSTRIP::synthesize() void MICROSTRIP::calcSynthesize()
{ {
double Z0_dest, Z0_current, Z0_result, increment, slope, error; double angl_dest, z0_dest;
int iteration; z0_dest = m_parameters[Z0_PRM];
angl_dest = m_parameters[ANG_L_PRM];
/* Get and assign substrate parameters */
get_microstrip_sub();
/* Get and assign component parameters */
get_microstrip_comp();
/* Get and assign electrical parameters */
get_microstrip_elec();
/* Get and assign physical parameters */
/* at present it is required only for getting strips length */
get_microstrip_phys();
/* calculate width and use for initial value in Newton's method */ /* calculate width and use for initial value in Newton's method */
w = synth_width(); m_parameters[PHYS_WIDTH_PRM] = synth_width();
minimizeZ0Error1D( &( m_parameters[PHYS_WIDTH_PRM] ) );
/* required value of Z0 */ m_parameters[Z0_PRM] = z0_dest;
Z0_dest = Z0; m_parameters[ANG_L_PRM] = angl_dest;
m_parameters[PHYS_LEN_PRM] = C0 / m_parameters[FREQUENCY_PRM] / sqrt( er_eff * mur_eff )
/* Newton's method */ * m_parameters[ANG_L_PRM] / 2.0 / M_PI; /* in m */
iteration = 0; calcAnalyze();
m_parameters[Z0_PRM] = z0_dest;
/* compute microstrip parameters */ m_parameters[ANG_L_PRM] = angl_dest;
calc(); m_parameters[PHYS_LEN_PRM] = C0 / m_parameters[FREQUENCY_PRM] / sqrt( er_eff * mur_eff )
Z0_current = Z0; * m_parameters[ANG_L_PRM] / 2.0 / M_PI; /* in m */
error = fabs( Z0_dest - Z0_current );
while( error > MAX_ERROR )
{
iteration++;
increment = (w / 100.0);
w += increment;
/* compute microstrip parameters */
calc();
Z0_result = Z0;
/* f(w(n)) = Z0 - Z0(w(n)) */
/* f'(w(n)) = -f'(Z0(w(n))) */
/* f'(Z0(w(n))) = (Z0(w(n)) - Z0(w(n+delw))/delw */
/* w(n+1) = w(n) - f(w(n))/f'(w(n)) */
slope = (Z0_result - Z0_current) / increment;
/* printf("%g\n",slope); */
w += (Z0_dest - Z0_current) / slope - increment;
/* printf("ms->w = %g\n", ms->w); */
/* find new error */
/* compute microstrip parameters */
calc();
Z0_current = Z0;
error = fabs( Z0_dest - Z0_current );
/* printf("Iteration = %d\n",iteration);
* printf("w = %g\t Z0 = %g\n",ms->w, Z0_current); */
if( iteration > 100 )
break;
}
setProperty( PHYS_WIDTH_PRM, w );
/* calculate physical length */
ang_l = getProperty( ANG_L_PRM );
l = C0 / m_freq / sqrt( er_eff * mur_eff ) * ang_l / 2.0 / M_PI; /* in m */
setProperty( PHYS_LEN_PRM, l );
/* compute microstrip parameters */
calc();
/* print results in the subwindow */
show_results();
} }

View File

@ -25,9 +25,12 @@
#ifndef __MICROSTRIP_H #ifndef __MICROSTRIP_H
#define __MICROSTRIP_H #define __MICROSTRIP_H
#include <transline.h>
class MICROSTRIP : public TRANSLINE class MICROSTRIP : public TRANSLINE
{ {
public: MICROSTRIP(); public:
MICROSTRIP();
friend class C_MICROSTRIP; friend class C_MICROSTRIP;
@ -52,10 +55,6 @@ private:
// private params // private params
double Z0_h_1; // homogeneous stripline impedance double Z0_h_1; // homogeneous stripline impedance
public:
void analyze() override;
void synthesize() override;
private: private:
double er_eff_freq(); double er_eff_freq();
double alpha_c(); double alpha_c();
@ -81,12 +80,11 @@ private:
void attenuation(); void attenuation();
void mur_eff_ms(); void mur_eff_ms();
void line_angle(); void line_angle();
void calc(); void show_results() override;
void get_microstrip_sub(); void showSynthesize() override;
void get_microstrip_comp(); void showAnalyze() override;
void get_microstrip_elec(); void calcAnalyze() override;
void get_microstrip_phys(); void calcSynthesize() override;
void show_results();
}; };
#endif // __MICROSTRIP_H #endif // __MICROSTRIP_H

View File

@ -25,27 +25,13 @@
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <units.h>
#include <transline.h>
#include <rectwaveguide.h> #include <rectwaveguide.h>
#include <units.h>
RECTWAVEGUIDE::RECTWAVEGUIDE() : TRANSLINE() RECTWAVEGUIDE::RECTWAVEGUIDE() : TRANSLINE()
{ {
m_Name = "RectWaveGuide"; m_Name = "RectWaveGuide";
Init();
// Initialize these here variables mainly to avoid warnings from a static analyzer
mur = 0.0; // magnetic permeability of substrate
a = 0.0; // width of waveguide
b = 0.0; // height of waveguide
l = 0.0; // length of waveguide
Z0 = 0.0; // characteristic impedance
Z0EH = 0.0; // characteristic impedance of field quantities*/
ang_l = 0.0; // Electrical length in angle
er_eff = 0.0; // Effective dielectric constant
mur_eff = 0.0; // Effective mag. permeability
atten_dielectric = 0.0; // Loss in dielectric (dB)
atten_cond = 0.0; // Loss in conductors (dB)
fc10 = 0.0; // Cutoff frequency for TE10 mode
} }
@ -56,7 +42,8 @@ double RECTWAVEGUIDE::kval_square()
{ {
double kval; double kval;
kval = 2.0* M_PI * m_freq * sqrt( mur * er ) / C0; kval = 2.0 * M_PI * m_parameters[FREQUENCY_PRM]
* sqrt( m_parameters[MUR_PRM] * m_parameters[EPSILONR_PRM] ) / C0;
return kval * kval; return kval * kval;
} }
@ -68,7 +55,8 @@ double RECTWAVEGUIDE::kval_square()
*/ */
double RECTWAVEGUIDE::kc_square( int m, int n ) double RECTWAVEGUIDE::kc_square( int m, int n )
{ {
return pow( (m * M_PI / a), 2.0 ) + pow( (n * M_PI / b), 2.0 ); return pow( ( m * M_PI / m_parameters[PHYS_A_PRM] ), 2.0 )
+ pow( ( n * M_PI / m_parameters[PHYS_B_PRM] ), 2.0 );
} }
@ -78,7 +66,8 @@ double RECTWAVEGUIDE::kc_square( int m, int n )
*/ */
double RECTWAVEGUIDE::fc( int m, int n ) double RECTWAVEGUIDE::fc( int m, int n )
{ {
return sqrt( kc_square( m, n ) / mur / er ) * C0 / 2.0 / M_PI; return sqrt( kc_square( m, n ) / m_parameters[MUR_PRM] / m_parameters[EPSILONR_PRM] ) * C0 / 2.0
/ M_PI;
} }
@ -91,10 +80,15 @@ double RECTWAVEGUIDE::alphac()
double Rs, f_c; double Rs, f_c;
double ac; double ac;
short m, n, mmax, nmax; short m, n, mmax, nmax;
double* a = &m_parameters[PHYS_A_PRM];
double* b = &m_parameters[PHYS_B_PRM];
double* f = &m_parameters[FREQUENCY_PRM];
double* murc = &m_parameters[MURC_PRM];
double* sigma = &m_parameters[SIGMA_PRM];
Rs = sqrt( M_PI * m_freq * m_murC * MU0 / m_sigma ); Rs = sqrt( M_PI * *f * *murc * MU0 / *sigma );
ac = 0.0; ac = 0.0;
mmax = (int) floor( m_freq / fc( 1, 0 ) ); mmax = (int) floor( *f / fc( 1, 0 ) );
nmax = mmax; nmax = mmax;
/* below from Ramo, Whinnery & Van Duzer */ /* below from Ramo, Whinnery & Van Duzer */
@ -105,24 +99,24 @@ double RECTWAVEGUIDE::alphac()
for( m = 1; m <= mmax; m++ ) for( m = 1; m <= mmax; m++ )
{ {
f_c = fc( m, n ); f_c = fc( m, n );
if( m_freq > f_c ) if( *f > f_c )
{ {
switch( n ) switch( n )
{ {
case 0: case 0:
ac += ( Rs / ( b * ZF0 * sqrt( 1.0 - pow( (f_c / m_freq), 2.0 ) ) ) ) * ac += ( Rs / ( *b * ZF0 * sqrt( 1.0 - pow( ( f_c / *f ), 2.0 ) ) ) )
( 1.0 + ( (2 * b / a) * pow( (f_c / m_freq), 2.0 ) ) ); * ( 1.0 + ( ( 2 * *b / *a ) * pow( ( f_c / *f ), 2.0 ) ) );
break; break;
default: default:
ac += ( (2. * Rs) / ( b * ZF0 * sqrt( 1.0 - pow( (f_c / m_freq), 2.0 ) ) ) ) * ac += ( ( 2. * Rs ) / ( *b * ZF0 * sqrt( 1.0 - pow( ( f_c / *f ), 2.0 ) ) ) )
( ( ( 1. + (b / a) ) * pow( (f_c / m_freq), 2.0 ) ) + * ( ( ( 1. + ( *b / *a ) ) * pow( ( f_c / *f ), 2.0 ) )
( ( 1. - + ( ( 1. - pow( ( f_c / *f ), 2.0 ) )
pow( (f_c / m_freq), * ( ( ( *b / *a )
2.0 ) ) * * ( ( ( *b / *a ) * pow( m, 2. ) )
( ( (b / a) * ( ( (b / a) * pow( m, 2. ) ) + pow( n, 2. ) ) ) / + pow( n, 2. ) ) )
( pow( (b * m / a), / ( pow( ( *b * m / *a ), 2.0 )
2.0 ) + pow( n, 2.0 ) ) ) ) ); + pow( n, 2.0 ) ) ) ) );
break; break;
} }
} }
@ -132,14 +126,14 @@ double RECTWAVEGUIDE::alphac()
/* TM(m,n) modes */ /* TM(m,n) modes */
for( n = 1; n <= nmax; n++ ) for( n = 1; n <= nmax; n++ )
{ {
for( m = 1; m<= mmax; m++ ) for( m = 1; m <= mmax; m++ )
{ {
f_c = fc( m, n ); f_c = fc( m, n );
if( m_freq > f_c ) if( *f > f_c )
{ {
ac += ( (2. * Rs) / ( b * ZF0 * sqrt( 1.0 - pow( (f_c / m_freq), 2.0 ) ) ) ) * ac += ( ( 2. * Rs ) / ( *b * ZF0 * sqrt( 1.0 - pow( ( f_c / *f ), 2.0 ) ) ) )
( ( ( pow( m, 2.0 ) * pow( (b / a), 3.0 ) ) + pow( n, 2. ) ) / * ( ( ( pow( m, 2.0 ) * pow( ( *b / *a ), 3.0 ) ) + pow( n, 2. ) )
( ( pow( (m * b / a), 2. ) ) + pow( n, 2.0 ) ) ); / ( ( pow( ( m * *b / *a ), 2. ) ) + pow( n, 2.0 ) ) );
} }
} }
} }
@ -173,7 +167,7 @@ double RECTWAVEGUIDE::alphad()
k_square = kval_square(); k_square = kval_square();
beta = sqrt( k_square - kc_square( 1, 0 ) ); beta = sqrt( k_square - kc_square( 1, 0 ) );
ad = (k_square * m_tand) / (2.0 * beta); ad = ( k_square * m_parameters[TAND_PRM] ) / ( 2.0 * beta );
ad = ad * 20.0 * log10( exp( 1. ) ); /* convert from Np/m to db/m */ ad = ad * 20.0 * log10( exp( 1. ) ); /* convert from Np/m to db/m */
return ad; return ad;
} }
@ -186,11 +180,11 @@ double RECTWAVEGUIDE::alphad()
*/ */
void RECTWAVEGUIDE::get_rectwaveguide_sub() void RECTWAVEGUIDE::get_rectwaveguide_sub()
{ {
er = getProperty( EPSILONR_PRM ); m_parameters[EPSILONR_PRM] = getProperty( EPSILONR_PRM );
mur = getProperty( MUR_PRM ); m_parameters[MUR_PRM] = getProperty( MUR_PRM );
m_murC = getProperty( MURC_PRM ); m_parameters[MURC_PRM] = getProperty( MURC_PRM );
m_sigma = 1.0 / getProperty( RHO_PRM ); m_parameters[SIGMA_PRM] = 1.0 / getProperty( RHO_PRM );
m_tand = getProperty( TAND_PRM ); m_parameters[TAND_PRM] = getProperty( TAND_PRM );
} }
@ -201,7 +195,7 @@ void RECTWAVEGUIDE::get_rectwaveguide_sub()
*/ */
void RECTWAVEGUIDE::get_rectwaveguide_comp() void RECTWAVEGUIDE::get_rectwaveguide_comp()
{ {
m_freq = getProperty( FREQUENCY_PRM ); m_parameters[FREQUENCY_PRM] = getProperty( FREQUENCY_PRM );
} }
@ -212,8 +206,8 @@ void RECTWAVEGUIDE::get_rectwaveguide_comp()
*/ */
void RECTWAVEGUIDE::get_rectwaveguide_elec() void RECTWAVEGUIDE::get_rectwaveguide_elec()
{ {
Z0 = getProperty( Z0_PRM ); m_parameters[Z0_PRM] = getProperty( Z0_PRM );
ang_l = getProperty( ANG_L_PRM ); m_parameters[ANG_L_PRM] = getProperty( ANG_L_PRM );
} }
@ -224,29 +218,20 @@ void RECTWAVEGUIDE::get_rectwaveguide_elec()
*/ */
void RECTWAVEGUIDE::get_rectwaveguide_phys() void RECTWAVEGUIDE::get_rectwaveguide_phys()
{ {
a = getProperty( PHYS_WIDTH_PRM ); m_parameters[PHYS_A_PRM] = getProperty( PHYS_A_PRM );
b = getProperty( PHYS_S_PRM ); m_parameters[PHYS_B_PRM] = getProperty( PHYS_B_PRM );
l = getProperty( PHYS_LEN_PRM ); m_parameters[PHYS_LEN_PRM] = getProperty( PHYS_LEN_PRM );
} }
/* /*
* analyze - analysis function * analyze - analysis function
*/ */
void RECTWAVEGUIDE::analyze() void RECTWAVEGUIDE::calcAnalyze()
{ {
double lambda_g; double lambda_g;
double k_square; double k_square;
/* Get and assign substrate parameters */
get_rectwaveguide_sub();
/* Get and assign component parameters */
get_rectwaveguide_comp();
/* Get and assign physical parameters */
get_rectwaveguide_phys();
k_square = kval_square(); k_square = kval_square();
if( kc_square( 1, 0 ) <= k_square ) if( kc_square( 1, 0 ) <= k_square )
@ -254,92 +239,124 @@ void RECTWAVEGUIDE::analyze()
/* propagating modes */ /* propagating modes */
// Z0 definition using fictive voltages and currents // Z0 definition using fictive voltages and currents
Z0 = 2.0* ZF0* sqrt( mur / er ) * (b / a) / sqrt( 1.0 - pow( (fc( 1, 0 ) / m_freq), 2.0 ) ); m_parameters[Z0_PRM] =
2.0 * ZF0 * sqrt( m_parameters[MUR_PRM] / m_parameters[EPSILONR_PRM] )
* ( m_parameters[PHYS_B_PRM] / m_parameters[PHYS_A_PRM] )
/ sqrt( 1.0 - pow( ( fc( 1, 0 ) / m_parameters[FREQUENCY_PRM] ), 2.0 ) );
/* calculate electrical angle */ /* calculate electrical angle */
lambda_g = 2.0 * M_PI / sqrt( k_square - kc_square( 1, 0 ) ); lambda_g = 2.0 * M_PI / sqrt( k_square - kc_square( 1, 0 ) );
ang_l = 2.0 * M_PI * l / lambda_g; /* in radians */ m_parameters[ANG_L_PRM] =
atten_cond = alphac() * l; 2.0 * M_PI * m_parameters[PHYS_LEN_PRM] / lambda_g; /* in radians */
atten_dielectric = alphad() * l; m_parameters[LOSS_CONDUCTOR_PRM] = alphac() * m_parameters[PHYS_LEN_PRM];
er_eff = ( 1.0 - pow( fc( 1, 0 ) / m_freq, 2.0 ) ); m_parameters[LOSS_DIELECTRIC_PRM] = alphad() * m_parameters[PHYS_LEN_PRM];
m_parameters[EPSILON_EFF_PRM] =
( 1.0 - pow( fc( 1, 0 ) / m_parameters[FREQUENCY_PRM], 2.0 ) );
} }
else else
{ {
/* evanascent modes */ /* evanascent modes */
Z0 = 0; m_parameters[Z0_PRM] = 0;
ang_l = 0; m_parameters[ANG_L_PRM] = 0;
er_eff = 0; m_parameters[EPSILON_EFF_PRM] = 0;
atten_dielectric = 0.0; m_parameters[LOSS_DIELECTRIC_PRM] = 0.0;
atten_cond = alphac_cutoff() * l; m_parameters[LOSS_CONDUCTOR_PRM] = alphac_cutoff() * m_parameters[PHYS_LEN_PRM];
} }
setProperty( Z0_PRM, Z0 );
setProperty( ANG_L_PRM, ang_l );
show_results();
} }
/* /*
* synthesize - synthesis function * synthesize - synthesis function
*/ */
void RECTWAVEGUIDE::synthesize() void RECTWAVEGUIDE::calcSynthesize()
{ {
double lambda_g, k_square, beta; double lambda_g, k_square, beta;
/* Get and assign substrate parameters */ if( isSelected( PHYS_B_PRM ) )
get_rectwaveguide_sub();
/* Get and assign component parameters */
get_rectwaveguide_comp();
/* Get and assign electrical parameters */
get_rectwaveguide_elec();
/* Get and assign physical parameters */
get_rectwaveguide_phys();
if( isSelected( PHYS_S_PRM ) )
{ {
/* solve for b */ /* solve for b */
b = Z0 * a * sqrt( 1.0 - pow( fc( 1, 0 ) / m_freq, 2.0 ) ) / ( 2.0 * ZF0 * sqrt( mur / er ) ); m_parameters[PHYS_B_PRM] =
setProperty( PHYS_S_PRM, b ); m_parameters[Z0_PRM] * m_parameters[PHYS_A_PRM]
* sqrt( 1.0 - pow( fc( 1, 0 ) / m_parameters[FREQUENCY_PRM], 2.0 ) )
/ ( 2.0 * ZF0 * sqrt( m_parameters[MUR_PRM] / m_parameters[EPSILONR_PRM] ) );
} }
else if( isSelected( PHYS_WIDTH_PRM ) ) else if( isSelected( PHYS_A_PRM ) )
{ {
/* solve for a */ /* solve for a */
a = sqrt( pow( 2.0 * ZF0 * b / Z0, 2.0 ) + pow( C0 / (2.0 * m_freq), 2.0 ) ); m_parameters[PHYS_A_PRM] =
setProperty( PHYS_WIDTH_PRM, a ); sqrt( pow( 2.0 * ZF0 * m_parameters[PHYS_B_PRM] / m_parameters[Z0_PRM], 2.0 )
+ pow( C0 / ( 2.0 * m_parameters[FREQUENCY_PRM] ), 2.0 ) );
} }
k_square = kval_square(); k_square = kval_square();
beta = sqrt( k_square - kc_square( 1, 0 ) ); beta = sqrt( k_square - kc_square( 1, 0 ) );
lambda_g = 2.0 * M_PI / beta; lambda_g = 2.0 * M_PI / beta;
l = (ang_l * lambda_g) / (2.0 * M_PI); /* in m */ m_parameters[PHYS_LEN_PRM] = ( m_parameters[ANG_L_PRM] * lambda_g ) / ( 2.0 * M_PI ); /* in m */
setProperty( PHYS_LEN_PRM, l );
if( kc_square( 1, 0 ) <= k_square ) if( kc_square( 1, 0 ) <= k_square )
{ {
/*propagating modes */ /*propagating modes */
beta = sqrt( k_square - kc_square( 1, 0 ) ); beta = sqrt( k_square - kc_square( 1, 0 ) );
lambda_g = 2.0 * M_PI / beta; lambda_g = 2.0 * M_PI / beta;
atten_cond = alphac() * l; m_parameters[LOSS_CONDUCTOR_PRM] = alphac() * m_parameters[PHYS_LEN_PRM];
atten_dielectric = alphad() * l; m_parameters[LOSS_DIELECTRIC_PRM] = alphad() * m_parameters[PHYS_LEN_PRM];
er_eff = ( 1.0 - pow( (fc( 1, 0 ) / m_freq), 2.0 ) ); m_parameters[EPSILON_EFF_PRM] =
( 1.0 - pow( ( fc( 1, 0 ) / m_parameters[FREQUENCY_PRM] ), 2.0 ) );
} }
else else
{ {
/*evanascent modes */ /*evanascent modes */
Z0 = 0; m_parameters[Z0_PRM] = 0;
ang_l = 0; m_parameters[ANG_L_PRM] = 0;
er_eff = 0; m_parameters[EPSILON_EFF_PRM] = 0;
atten_dielectric = 0.0; m_parameters[LOSS_DIELECTRIC_PRM] = 0.0;
atten_cond = alphac_cutoff() * l; m_parameters[LOSS_CONDUCTOR_PRM] = alphac_cutoff() * m_parameters[PHYS_LEN_PRM];
} }
}
show_results(); void RECTWAVEGUIDE::showSynthesize()
{
if( isSelected( PHYS_A_PRM ) )
setProperty( PHYS_A_PRM, m_parameters[PHYS_A_PRM] );
if( isSelected( PHYS_B_PRM ) )
setProperty( PHYS_B_PRM, m_parameters[PHYS_B_PRM] );
setProperty( PHYS_LEN_PRM, m_parameters[PHYS_LEN_PRM] );
// Check for errors
if( !std::isfinite( m_parameters[PHYS_A_PRM] ) || m_parameters[PHYS_A_PRM] <= 0 )
setErrorLevel( PHYS_A_PRM, TRANSLINE_ERROR );
if( !std::isfinite( m_parameters[PHYS_B_PRM] ) || m_parameters[PHYS_B_PRM] <= 00 )
setErrorLevel( PHYS_B_PRM, TRANSLINE_ERROR );
// Check for warnings
if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
setErrorLevel( Z0_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
setErrorLevel( ANG_L_PRM, TRANSLINE_WARNING );
}
void RECTWAVEGUIDE::showAnalyze()
{
setProperty( Z0_PRM, m_parameters[Z0_PRM] );
setProperty( ANG_L_PRM, m_parameters[ANG_L_PRM] );
// Check for errors
if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
setErrorLevel( Z0_PRM, TRANSLINE_ERROR );
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
setErrorLevel( ANG_L_PRM, TRANSLINE_ERROR );
// Check for warnings
if( !std::isfinite( m_parameters[PHYS_A_PRM] ) || m_parameters[PHYS_A_PRM] <= 0 )
setErrorLevel( PHYS_A_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[PHYS_B_PRM] ) || m_parameters[PHYS_B_PRM] <= 00 )
setErrorLevel( PHYS_B_PRM, TRANSLINE_WARNING );
} }
@ -353,12 +370,12 @@ void RECTWAVEGUIDE::show_results()
Z0EH = ZF0 * sqrt( kval_square() / ( kval_square() - kc_square( 1, 0 ) ) ); Z0EH = ZF0 * sqrt( kval_square() / ( kval_square() - kc_square( 1, 0 ) ) );
setResult( 0, Z0EH, "Ohm" ); setResult( 0, Z0EH, "Ohm" );
setResult( 1, er_eff, "" ); setResult( 1, m_parameters[EPSILON_EFF_PRM], "" );
setResult( 2, atten_cond, "dB" ); setResult( 2, m_parameters[LOSS_CONDUCTOR_PRM], "dB" );
setResult( 3, atten_dielectric, "dB" ); setResult( 3, m_parameters[LOSS_DIELECTRIC_PRM], "dB" );
// show possible TE modes (H modes) // show possible TE modes (H modes)
if( m_freq < fc( 1, 0 ) ) if( m_parameters[FREQUENCY_PRM] < fc( 1, 0 ) )
strcpy( text, "none" ); strcpy( text, "none" );
else else
{ {
@ -367,12 +384,12 @@ void RECTWAVEGUIDE::show_results()
{ {
for( n = 0; n <= max; n++ ) for( n = 0; n <= max; n++ )
{ {
if( (m == 0) && (n == 0) ) if( ( m == 0 ) && ( n == 0 ) )
continue; continue;
if( m_freq >= ( fc( m, n ) ) ) if( m_parameters[FREQUENCY_PRM] >= ( fc( m, n ) ) )
{ {
sprintf( txt, "H(%d,%d) ", m, n ); sprintf( txt, "H(%d,%d) ", m, n );
if( (strlen( text ) + strlen( txt ) + 5) < MAXSTRLEN ) if( ( strlen( text ) + strlen( txt ) + 5 ) < MAXSTRLEN )
strcat( text, txt ); strcat( text, txt );
else else
{ {
@ -386,19 +403,19 @@ void RECTWAVEGUIDE::show_results()
setResult( 4, text ); setResult( 4, text );
// show possible TM modes (E modes) // show possible TM modes (E modes)
if( m_freq < fc( 1, 1 ) ) if( m_parameters[FREQUENCY_PRM] < fc( 1, 1 ) )
strcpy( text, "none" ); strcpy( text, "none" );
else else
{ {
strcpy( text, "" ); strcpy( text, "" );
for( m = 1; m<= max; m++ ) for( m = 1; m <= max; m++ )
{ {
for( n = 1; n<= max; n++ ) for( n = 1; n <= max; n++ )
{ {
if( m_freq >= fc( m, n ) ) if( m_parameters[FREQUENCY_PRM] >= fc( m, n ) )
{ {
sprintf( txt, "E(%d,%d) ", m, n ); sprintf( txt, "E(%d,%d) ", m, n );
if( (strlen( text ) + strlen( txt ) + 5) < MAXSTRLEN ) if( ( strlen( text ) + strlen( txt ) + 5 ) < MAXSTRLEN )
strcat( text, txt ); strcat( text, txt );
else else
{ {

View File

@ -25,9 +25,16 @@
#ifndef __RECTWAVEGUIDE_H #ifndef __RECTWAVEGUIDE_H
#define __RECTWAVEGUIDE_H #define __RECTWAVEGUIDE_H
#include <transline.h>
#define PHYS_A_PRM PHYS_WIDTH_PRM
#define PHYS_B_PRM PHYS_S_PRM
class RECTWAVEGUIDE : public TRANSLINE class RECTWAVEGUIDE : public TRANSLINE
{ {
public: RECTWAVEGUIDE(); public:
RECTWAVEGUIDE();
private: private:
double mur; // magnetic permeability of substrate double mur; // magnetic permeability of substrate
@ -44,9 +51,6 @@ private:
double fc10; // Cutoff frequency for TE10 mode double fc10; // Cutoff frequency for TE10 mode
public: public:
void analyze() override;
void synthesize() override;
private: private:
double kval_square(); double kval_square();
double kc_square( int, int ); double kc_square( int, int );
@ -58,7 +62,11 @@ private:
void get_rectwaveguide_comp(); void get_rectwaveguide_comp();
void get_rectwaveguide_phys(); void get_rectwaveguide_phys();
void get_rectwaveguide_elec(); void get_rectwaveguide_elec();
void show_results(); void show_results() override;
void calcAnalyze() override;
void calcSynthesize() override;
void showAnalyze() override;
void showSynthesize() override;
}; };
#endif // __RECTWAVEGUIDE_H #endif // __RECTWAVEGUIDE_H

View File

@ -27,44 +27,13 @@
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <units.h>
#include <transline.h>
#include <stripline.h> #include <stripline.h>
#include <units.h>
STRIPLINE::STRIPLINE() : TRANSLINE() STRIPLINE::STRIPLINE() : TRANSLINE()
{ {
m_Name = "StripLine"; m_Name = "StripLine";
Init();
// Initialize these variables mainly to avoid warnings from a static analyzer
h = 0.0; // height of substrate
a = 0.0; // distance of strip to top metal
t = 0.0; // thickness of top metal
w = 0.0; // width of line
len = 0.0; // length of line
Z0 = 0.0; // characteristic impedance
ang_l = 0.0; // Electrical length in angle
er_eff = 0.0; // effective dielectric constant
atten_dielectric = 0.0; // Loss in dielectric (dB)
atten_cond = 0.0; // Loss in conductors (dB)
}
// -------------------------------------------------------------------
void STRIPLINE::getProperties()
{
m_freq = getProperty( FREQUENCY_PRM );
w = getProperty( PHYS_WIDTH_PRM );
len = getProperty( PHYS_LEN_PRM );
h = getProperty( H_PRM);
a = getProperty( STRIPLINE_A_PRM );
t = getProperty( T_PRM );
er = getProperty( EPSILONR_PRM );
m_murC = getProperty( MURC_PRM );
m_tand = getProperty( TAND_PRM );
m_sigma = 1.0 / getProperty( RHO_PRM );
Z0 = getProperty( Z0_PRM );
ang_l = getProperty( ANG_L_PRM );
} }
@ -73,33 +42,37 @@ void STRIPLINE::getProperties()
double STRIPLINE::lineImpedance( double height, double& ac ) double STRIPLINE::lineImpedance( double height, double& ac )
{ {
double ZL; double ZL;
double hmt = height - t; double hmt = height - m_parameters[T_PRM];
ac = sqrt( m_freq / m_sigma / 17.2 ); ac = sqrt( m_parameters[FREQUENCY_PRM] / m_parameters[SIGMA_PRM] / 17.2 );
if( w / hmt >= 0.35 ) if( m_parameters[PHYS_WIDTH_PRM] / hmt >= 0.35 )
{ {
ZL = w + ZL = m_parameters[PHYS_WIDTH_PRM]
( 2.0 * height * + ( 2.0 * height * log( ( 2.0 * height - m_parameters[T_PRM] ) / hmt )
log( (2.0 * height - t) / hmt ) - t * log( height * height / hmt / hmt - 1.0 ) ) / M_PI; - m_parameters[T_PRM] * log( height * height / hmt / hmt - 1.0 ) )
ZL = ZF0 * hmt / sqrt( er ) / 4.0 / ZL; / M_PI;
ZL = ZF0 * hmt / sqrt( m_parameters[EPSILONR_PRM] ) / 4.0 / ZL;
ac *= 2.02e-6 * er * ZL / hmt; ac *= 2.02e-6 * m_parameters[EPSILONR_PRM] * ZL / hmt;
ac *= 1.0 + 2.0 * w / hmt + (height + t) / hmt / M_PI* log( 2.0 * height / t - 1.0 ); ac *= 1.0 + 2.0 * m_parameters[PHYS_WIDTH_PRM] / hmt
+ ( height + m_parameters[T_PRM] ) / hmt / M_PI
* log( 2.0 * height / m_parameters[T_PRM] - 1.0 );
} }
else else
{ {
double tdw = t / w; double tdw = m_parameters[T_PRM] / m_parameters[PHYS_WIDTH_PRM];
if( t / w > 1.0 ) if( m_parameters[T_PRM] / m_parameters[PHYS_WIDTH_PRM] > 1.0 )
tdw = w / t; tdw = m_parameters[PHYS_WIDTH_PRM] / m_parameters[T_PRM];
double de = 1.0 + tdw / M_PI * ( 1.0 + log( 4.0 * M_PI / tdw ) ) + 0.236 * pow( tdw, 1.65 ); double de = 1.0 + tdw / M_PI * ( 1.0 + log( 4.0 * M_PI / tdw ) ) + 0.236 * pow( tdw, 1.65 );
if( t / w > 1.0 ) if( m_parameters[T_PRM] / m_parameters[PHYS_WIDTH_PRM] > 1.0 )
de *= t / 2.0; de *= m_parameters[T_PRM] / 2.0;
else else
de *= w / 2.0; de *= m_parameters[PHYS_WIDTH_PRM] / 2.0;
ZL = ZF0 / 2.0 / M_PI / sqrt( er ) * log( 4.0 * height / M_PI / de ); ZL = ZF0 / 2.0 / M_PI / sqrt( m_parameters[EPSILONR_PRM] )
* log( 4.0 * height / M_PI / de );
ac *= 0.01141 / ZL / de; ac *= 0.01141 / ZL / de;
ac *= de / height + 0.5 + tdw / 2.0 / M_PI + 0.5 / M_PI* log( 4.0 * M_PI / tdw ) ac *= de / height + 0.5 + tdw / 2.0 / M_PI + 0.5 / M_PI * log( 4.0 * M_PI / tdw )
+ 0.1947 * pow( tdw, 0.65 ) - 0.0767 * pow( tdw, 1.65 ); + 0.1947 * pow( tdw, 0.65 ) - 0.0767 * pow( tdw, 1.65 );
} }
@ -108,103 +81,110 @@ double STRIPLINE::lineImpedance( double height, double& ac )
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void STRIPLINE::calc() void STRIPLINE::calcAnalyze()
{ {
m_skindepth = skin_depth(); m_parameters[SKIN_DEPTH_PRM] = skin_depth();
er_eff = er; // no dispersion m_parameters[EPSILON_EFF_PRM] = m_parameters[EPSILONR_PRM]; // no dispersion
double ac1, ac2; double ac1, ac2;
Z0 = 2.0 / double t = m_parameters[T_PRM];
( 1.0 / lineImpedance( 2.0 * a + t, ac1 ) + 1.0 / lineImpedance( 2.0 * (h - a) - t, ac2 ) ); double a = m_parameters[STRIPLINE_A_PRM];
double h = m_parameters[H_PRM];
m_parameters[Z0_PRM] = 2.0
/ ( 1.0 / lineImpedance( 2.0 * a + t, ac1 )
+ 1.0 / lineImpedance( 2.0 * ( h - a ) - t, ac2 ) );
m_parameters[LOSS_CONDUCTOR_PRM] = m_parameters[PHYS_LEN_PRM] * 0.5 * ( ac1 + ac2 );
m_parameters[LOSS_DIELECTRIC_PRM] = 20.0 / log( 10.0 ) * m_parameters[PHYS_LEN_PRM]
* ( M_PI / C0 ) * m_parameters[FREQUENCY_PRM]
* sqrt( m_parameters[EPSILONR_PRM] )
* m_parameters[TAND_PRM];
atten_cond = len * 0.5 * (ac1 + ac2); m_parameters[ANG_L_PRM] = 2.0 * M_PI * m_parameters[PHYS_LEN_PRM]
atten_dielectric = 20.0 / log( 10.0 ) * len * (M_PI / C0) * m_freq * sqrt( er ) * m_tand; * sqrt( m_parameters[EPSILONR_PRM] ) * m_parameters[FREQUENCY_PRM]
/ C0; // in radians
ang_l = 2.0* M_PI* len* sqrt( er ) * m_freq / C0; // in radians
} }
void STRIPLINE::showAnalyze()
{
setProperty( Z0_PRM, m_parameters[Z0_PRM] );
setProperty( ANG_L_PRM, m_parameters[ANG_L_PRM] );
if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
{
setErrorLevel( Z0_PRM, TRANSLINE_ERROR );
}
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
{
setErrorLevel( ANG_L_PRM, TRANSLINE_ERROR );
}
if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] < 0 )
{
setErrorLevel( PHYS_LEN_PRM, TRANSLINE_WARNING );
}
if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || m_parameters[PHYS_WIDTH_PRM] < 0 )
{
setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_WARNING );
}
if( m_parameters[STRIPLINE_A_PRM] + m_parameters[T_PRM] >= m_parameters[H_PRM] )
{
setErrorLevel( STRIPLINE_A_PRM, TRANSLINE_WARNING );
setErrorLevel( T_PRM, TRANSLINE_WARNING );
setErrorLevel( H_PRM, TRANSLINE_WARNING );
setErrorLevel( Z0_PRM, TRANSLINE_ERROR );
}
}
void STRIPLINE::showSynthesize()
{
setProperty( PHYS_LEN_PRM, m_parameters[PHYS_LEN_PRM] );
setProperty( PHYS_WIDTH_PRM, m_parameters[PHYS_WIDTH_PRM] );
if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] < 0 )
{
setErrorLevel( PHYS_LEN_PRM, TRANSLINE_ERROR );
}
if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || m_parameters[PHYS_WIDTH_PRM] < 0 )
{
setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_ERROR );
}
if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
{
setErrorLevel( Z0_PRM, TRANSLINE_WARNING );
}
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
{
setErrorLevel( ANG_L_PRM, TRANSLINE_WARNING );
}
if( m_parameters[STRIPLINE_A_PRM] + m_parameters[T_PRM] >= m_parameters[H_PRM] )
{
setErrorLevel( STRIPLINE_A_PRM, TRANSLINE_WARNING );
setErrorLevel( T_PRM, TRANSLINE_WARNING );
setErrorLevel( H_PRM, TRANSLINE_WARNING );
setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_ERROR );
}
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void STRIPLINE::show_results() void STRIPLINE::show_results()
{ {
setProperty( Z0_PRM, Z0 );
setProperty( ANG_L_PRM, ang_l );
setResult( 0, er_eff, "" ); setResult( 0, m_parameters[EPSILON_EFF_PRM], "" );
setResult( 1, atten_cond, "dB" ); setResult( 1, m_parameters[LOSS_CONDUCTOR_PRM], "dB" );
setResult( 2, atten_dielectric, "dB" ); setResult( 2, m_parameters[LOSS_DIELECTRIC_PRM], "dB" );
setResult( 3, m_skindepth / UNIT_MICRON, "µm" ); setResult( 3, m_parameters[SKIN_DEPTH_PRM] / UNIT_MICRON, "µm" );
}
// -------------------------------------------------------------------
void STRIPLINE::analyze()
{
getProperties();
calc();
show_results();
} }
#define MAX_ERROR 0.000001 #define MAX_ERROR 0.000001
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void STRIPLINE::synthesize() void STRIPLINE::calcSynthesize()
{ {
double Z0_dest, Z0_current, Z0_result, increment, slope, error; minimizeZ0Error1D( &( m_parameters[PHYS_WIDTH_PRM] ) );
int iteration;
getProperties();
/* required value of Z0 */
Z0_dest = Z0;
/* Newton's method */
iteration = 0;
/* compute parameters */
calc();
Z0_current = Z0;
error = fabs( Z0_dest - Z0_current );
while( error > MAX_ERROR )
{
iteration++;
increment = w / 100.0;
w += increment;
/* compute parameters */
calc();
Z0_result = Z0;
/* f(w(n)) = Z0 - Z0(w(n)) */
/* f'(w(n)) = -f'(Z0(w(n))) */
/* f'(Z0(w(n))) = (Z0(w(n)) - Z0(w(n+delw))/delw */
/* w(n+1) = w(n) - f(w(n))/f'(w(n)) */
slope = (Z0_result - Z0_current) / increment;
slope = (Z0_dest - Z0_current) / slope - increment;
w += slope;
if( w <= 0.0 )
w = increment;
/* find new error */
/* compute parameters */
calc();
Z0_current = Z0;
error = fabs( Z0_dest - Z0_current );
if( iteration > 100 )
break;
}
setProperty( PHYS_WIDTH_PRM, w );
/* calculate physical length */
ang_l = getProperty( ANG_L_PRM );
len = C0 / m_freq / sqrt( er_eff ) * ang_l / 2.0 / M_PI; /* in m */
setProperty( PHYS_LEN_PRM, len );
/* compute parameters */
calc();
/* print results in the subwindow */
show_results();
} }

View File

@ -24,31 +24,21 @@
#ifndef __STRIPLINE_H #ifndef __STRIPLINE_H
#define __STRIPLINE_H #define __STRIPLINE_H
#include <transline.h>
class STRIPLINE : public TRANSLINE class STRIPLINE : public TRANSLINE
{ {
public: STRIPLINE();
private:
double h; // height of substrate
double a; // distance of strip to top metal
double t; // thickness of top metal
double w; // width of line
double len; // length of line
double Z0; // characteristic impedance
double ang_l; // electrical length in angle
double er_eff; // effective dielectric constant
double atten_dielectric; // loss in dielectric (dB)
double atten_cond; // loss in conductors (dB)
public: public:
void analyze() override; STRIPLINE();
void synthesize() override;
private: private:
void calcAnalyze() override;
void calcSynthesize() override;
void showSynthesize() override;
void showAnalyze() override;
double lineImpedance( double, double& ); double lineImpedance( double, double& );
void calc(); void show_results() override;
void show_results();
void getProperties();
}; };
#endif #endif

View File

@ -1,3 +1,4 @@
/* /*
* TRANSLINE.cpp - base for a transmission line implementation * TRANSLINE.cpp - base for a transmission line implementation
* *
@ -33,7 +34,7 @@
#ifndef M_PI_2 #ifndef M_PI_2
#define M_PI_2 (M_PI/2) #define M_PI_2 ( M_PI / 2 )
#endif #endif
@ -57,19 +58,20 @@ double GetPropertyInDialog( enum PRMS_ID aPrmId );
// Has meaning only for params that have a radio button // Has meaning only for params that have a radio button
bool IsSelectedInDialog( enum PRMS_ID aPrmId ); bool IsSelectedInDialog( enum PRMS_ID aPrmId );
/** Function SetPropertyBgColorInDialog
* Set the background color of a parameter
* @param aPrmId = param id to set
* @param aCol = new color
*/
void SetPropertyBgColorInDialog( enum PRMS_ID aPrmId, const KIGFX::COLOR4D* aCol );
/* Constructor creates a transmission line instance. */ /* Constructor creates a transmission line instance. */
TRANSLINE::TRANSLINE() TRANSLINE::TRANSLINE()
{ {
m_murC = 1.0; m_parameters[MURC_PRM] = 1.0;
m_Name = nullptr; m_Name = nullptr;
Init();
// 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
} }
@ -79,6 +81,22 @@ TRANSLINE::~TRANSLINE()
} }
void TRANSLINE::Init( void )
{
wxColour wxcol = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
okCol = KIGFX::COLOR4D( wxcol );
okCol.r = wxcol.Red() / 255.0;
okCol.g = wxcol.Green() / 255.0;
okCol.b = wxcol.Blue() / 255.0;
int i;
// Initialize these variables mainly to avoid warnings from a static analyzer
for( i = 0; i < EXTRA_PRMS_COUNT; ++i )
{
m_parameters[i] = 0;
}
}
/* Sets a named property to the given value, access through the /* Sets a named property to the given value, access through the
* application. * application.
*/ */
@ -87,6 +105,7 @@ void TRANSLINE::setProperty( enum PRMS_ID aPrmId, double value )
SetPropertyInDialog( aPrmId, value ); SetPropertyInDialog( aPrmId, value );
} }
/* /*
*Returns true if the param aPrmId is selected *Returns true if the param aPrmId is selected
* Has meaning only for params that have a radio button * Has meaning only for params that have a radio button
@ -115,14 +134,101 @@ double TRANSLINE::getProperty( enum PRMS_ID aPrmId )
return GetPropertyInDialog( aPrmId ); return GetPropertyInDialog( aPrmId );
} }
/* /** @function getProperties
* skin_depth - calculate skin depth *
* Get all properties from the UI. Computes some extra ones.
**/
void TRANSLINE::getProperties( void )
{
int i;
for( i = 0; i < DUMMY_PRM; ++i )
{
m_parameters[i] = getProperty( (PRMS_ID) i );
setErrorLevel( (PRMS_ID) i, TRANSLINE_OK );
}
m_parameters[SIGMA_PRM] = 1.0 / getProperty( RHO_PRM );
m_parameters[EPSILON_EFF_PRM] = 1.0;
m_parameters[SKIN_DEPTH_PRM] = skin_depth();
}
/** @function checkProperties
*
* Checks the input parameters (ie: negative length).
* Does not check for incompatibility between values as this depends on the line shape.
**/
void TRANSLINE::checkProperties( void )
{
// Do not check for values that are results of anylzing / synthesizing
// Do not check for transline specific incompatibilities ( like " conductor height sould be lesser than dielectric height")
if( !std::isfinite( m_parameters[EPSILONR_PRM] ) || m_parameters[EPSILONR_PRM] <= 0 )
setErrorLevel( EPSILONR_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[TAND_PRM] ) || m_parameters[TAND_PRM] < 0 )
setErrorLevel( TAND_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[RHO_PRM] ) || m_parameters[RHO_PRM] < 0 )
setErrorLevel( RHO_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[H_PRM] ) || m_parameters[H_PRM] < 0 )
setErrorLevel( H_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[TWISTEDPAIR_TWIST_PRM] )
|| m_parameters[TWISTEDPAIR_TWIST_PRM] < 0 )
setErrorLevel( TWISTEDPAIR_TWIST_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[STRIPLINE_A_PRM] ) || m_parameters[STRIPLINE_A_PRM] <= 0 )
setErrorLevel( STRIPLINE_A_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[H_T_PRM] ) || m_parameters[H_T_PRM] <= 0 )
setErrorLevel( H_T_PRM, TRANSLINE_WARNING );
// How can we check ROUGH_PRM ?
if( !std::isfinite( m_parameters[MUR_PRM] ) || m_parameters[MUR_PRM] < 0 )
setErrorLevel( MUR_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[TWISTEDPAIR_EPSILONR_ENV_PRM] )
|| m_parameters[TWISTEDPAIR_EPSILONR_ENV_PRM] <= 0 )
setErrorLevel( TWISTEDPAIR_EPSILONR_ENV_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[MURC_PRM] ) || m_parameters[MURC_PRM] < 0 )
setErrorLevel( MURC_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[FREQUENCY_PRM] ) || m_parameters[FREQUENCY_PRM] <= 0 )
setErrorLevel( FREQUENCY_PRM, TRANSLINE_WARNING );
}
void TRANSLINE::analyze()
{
getProperties();
checkProperties();
calcAnalyze();
showAnalyze();
show_results();
}
void TRANSLINE::synthesize()
{
getProperties();
checkProperties();
calcSynthesize();
showSynthesize();
show_results();
}
/**
* @function skin_depth
* calculate skin depth
*
* \f$ \frac{1}{\sqrt{ \pi \cdot f \cdot \mu \cdot \sigma }} \f$
*/ */
#include <cstdio> #include <cstdio>
double TRANSLINE::skin_depth() double TRANSLINE::skin_depth()
{ {
double depth; double depth;
depth = 1.0 / sqrt( M_PI * m_freq * m_murC * MU0 * m_sigma ); depth = 1.0
/ sqrt( M_PI * m_parameters[FREQUENCY_PRM] * m_parameters[MURC_PRM] * MU0
* m_parameters[SIGMA_PRM] );
return depth; return depth;
} }
@ -161,7 +267,7 @@ void TRANSLINE::ellipke( double arg, double& k, double& e )
{ {
fk = 1 / sqrt( 1 - arg ); fk = 1 / sqrt( 1 - arg );
fe = sqrt( 1 - arg ); fe = sqrt( 1 - arg );
da = -arg / (1 - arg); da = -arg / ( 1 - arg );
} }
a = 1; a = 1;
b = sqrt( 1 - da ); b = sqrt( 1 - da );
@ -170,8 +276,8 @@ void TRANSLINE::ellipke( double arg, double& k, double& e )
s = fr * c * c; s = fr * c * c;
for( i = 0; i < iMax; i++ ) for( i = 0; i < iMax; i++ )
{ {
t = (a + b) / 2; t = ( a + b ) / 2;
c = (a - b) / 2; c = ( a - b ) / 2;
b = sqrt( a * b ); b = sqrt( a * b );
a = t; a = t;
fr *= 2; fr *= 2;
@ -182,12 +288,13 @@ void TRANSLINE::ellipke( double arg, double& k, double& e )
if( i >= iMax ) if( i >= iMax )
{ {
k = 0; e = 0; k = 0;
e = 0;
} }
else else
{ {
k = M_PI_2 / a; k = M_PI_2 / a;
e = M_PI_2 * (1 - s) / a; e = M_PI_2 * ( 1 - s ) / a;
if( arg < 0 ) if( arg < 0 )
{ {
k *= fk; k *= fk;
@ -206,3 +313,122 @@ double TRANSLINE::ellipk( double k )
ellipke( k, r, lost ); ellipke( k, r, lost );
return r; return r;
} }
#define MAX_ERROR 0.000001
/**
* @function minimizeZ0Error1D
*
* Tries to find a parameter that minimizes the error ( on Z0 ).
* This function only works with a single parameter.
* Calls @ref calcAnalyze several times until the error is acceptable.
* While the error is unnacceptable, changes slightly the parameter.
*
* This function does not change Z0 / Angl_L.
*
* @param avar Parameter to synthesize
* @return 'true' if error < MAX_ERROR, else 'false'
*/
bool TRANSLINE::minimizeZ0Error1D( double* aVar )
{
double Z0_dest, Z0_current, Z0_result, angl_l_dest, increment, slope, error;
int iteration;
if( !std::isfinite( m_parameters[Z0_PRM] ) )
{
*aVar = NAN;
return false;
}
if( ( !std::isfinite( *aVar ) ) || ( *aVar == 0 ) )
{
*aVar = 0.001;
}
/* required value of Z0 */
Z0_dest = m_parameters[Z0_PRM];
/* required value of angl_l */
angl_l_dest = m_parameters[ANG_L_PRM];
/* Newton's method */
iteration = 0;
/* compute parameters */
calcAnalyze();
Z0_current = m_parameters[Z0_PRM];
error = fabs( Z0_dest - Z0_current );
while( error > MAX_ERROR )
{
iteration++;
increment = *aVar / 100.0;
*aVar += increment;
/* compute parameters */
calcAnalyze();
Z0_result = m_parameters[Z0_PRM];
/* f(w(n)) = Z0 - Z0(w(n)) */
/* f'(w(n)) = -f'(Z0(w(n))) */
/* f'(Z0(w(n))) = (Z0(w(n)) - Z0(w(n+delw))/delw */
/* w(n+1) = w(n) - f(w(n))/f'(w(n)) */
slope = ( Z0_result - Z0_current ) / increment;
slope = ( Z0_dest - Z0_current ) / slope - increment;
*aVar += slope;
if( *aVar <= 0.0 )
*aVar = increment;
/* find new error */
/* compute parameters */
calcAnalyze();
Z0_current = m_parameters[Z0_PRM];
error = fabs( Z0_dest - Z0_current );
if( iteration > 100 )
break;
}
/* Compute one last time, but with correct length */
m_parameters[Z0_PRM] = Z0_dest;
m_parameters[ANG_L_PRM] = angl_l_dest;
m_parameters[PHYS_LEN_PRM] = C0 / m_parameters[FREQUENCY_PRM]
/ sqrt( m_parameters[EPSILON_EFF_PRM] ) * m_parameters[ANG_L_PRM]
/ 2.0 / M_PI; /* in m */
calcAnalyze();
/* Restore parameters */
m_parameters[Z0_PRM] = Z0_dest;
m_parameters[ANG_L_PRM] = angl_l_dest;
m_parameters[PHYS_LEN_PRM] = C0 / m_parameters[FREQUENCY_PRM]
/ sqrt( m_parameters[EPSILON_EFF_PRM] ) * m_parameters[ANG_L_PRM]
/ 2.0 / M_PI; /* in m */
return error <= MAX_ERROR;
}
/**
* @function setErrorLevel
*
* set an error / warning level for a given parameter.
*
* @see TRANSLINE_OK
* @see TRANSLINE_WARNING
* @see TRANSLINE_ERROR
*
* @param aP parameter
* @param aErrorLevel Error level
*/
void TRANSLINE::setErrorLevel( PRMS_ID aP, char aErrorLevel )
{
switch( aErrorLevel )
{
case( TRANSLINE_WARNING ):
SetPropertyBgColorInDialog( aP, &warnCol );
break;
case( TRANSLINE_ERROR ):
SetPropertyBgColorInDialog( aP, &errCol );
break;
default:
SetPropertyBgColorInDialog( aP, &okCol );
break;
}
}

View File

@ -24,63 +24,109 @@
#ifndef __TRANSLINE_H #ifndef __TRANSLINE_H
#define __TRANSLINE_H #define __TRANSLINE_H
#include <gal/color4d.h>
#include <wx/wx.h>
#define TRANSLINE_OK 0
#define TRANSLINE_WARNING 1
#define TRANSLINE_ERROR 2
// IDs for lines parameters used in calculation: // IDs for lines parameters used in calculation:
// (Used to retrieve these parameters from UI. // (Used to retrieve these parameters from UI.
// DUMMY_PRM is used to skip a param line in dialogs. It is not really a parameter // DUMMY_PRM is used to skip a param line in dialogs. It is not really a parameter
enum PRMS_ID enum PRMS_ID
{ {
UNKNOWN_ID = 0, UNKNOWN_ID = -1,
EPSILONR_PRM, EPSILONR_PRM, // dielectric constant
TAND_PRM, TAND_PRM, // Dielectric Loss Tangent
RHO_PRM, RHO_PRM, // Conductivity of conductor
H_PRM, H_PRM, // height of substrate
TWISTEDPAIR_TWIST_PRM, TWISTEDPAIR_TWIST_PRM, // Twists per length
H_T_PRM, H_T_PRM,
STRIPLINE_A_PRM, STRIPLINE_A_PRM, // Stripline : distance from line to top metal
T_PRM, T_PRM, // thickness of top metal
ROUGH_PRM, ROUGH_PRM,
MUR_PRM, MUR_PRM, // magnetic permeability of substrate
TWISTEDPAIR_EPSILONR_ENV_PRM, TWISTEDPAIR_EPSILONR_ENV_PRM,
MURC_PRM, MURC_PRM, // magnetic permeability of conductor
FREQUENCY_PRM, FREQUENCY_PRM, // Frequency of operation
Z0_PRM, Z0_PRM, // characteristic impedance
Z0_E_PRM, Z0_E_PRM,
Z0_O_PRM, Z0_O_PRM,
ANG_L_PRM, ANG_L_PRM, // Electrical length in angle
PHYS_WIDTH_PRM, PHYS_WIDTH_PRM,
PHYS_DIAM_IN_PRM, PHYS_DIAM_IN_PRM, // Inner diameter of cable
PHYS_S_PRM, PHYS_S_PRM, // width of gap between line and ground
PHYS_DIAM_OUT_PRM, PHYS_DIAM_OUT_PRM, // Outer diameter of cable
PHYS_LEN_PRM, PHYS_LEN_PRM, // Length of cable
DUMMY_PRM DUMMY_PRM
}; };
// IDs for lines parameters used in calculation that are not given by the UI
enum EXTRA_PRMS_ID
{
EXTRA_PRMS_START = DUMMY_PRM - 1,
SIGMA_PRM, // Conductivity of the metal
SKIN_DEPTH_PRM, // Skin depth
LOSS_DIELECTRIC_PRM, // Loss in dielectric (dB)
LOSS_CONDUCTOR_PRM, // Loss in conductors (dB)
CUTOFF_FREQUENCY_PRM, // Cutoff frequency for higher order modes
EPSILON_EFF_PRM, // Effective dielectric constant
EXTRA_PRMS_COUNT,
};
class TRANSLINE class TRANSLINE
{ {
public: TRANSLINE(); public:
TRANSLINE();
virtual ~TRANSLINE(); virtual ~TRANSLINE();
const char *m_Name; const char* m_Name;
void setProperty( enum PRMS_ID aPrmId, double aValue); void setProperty( enum PRMS_ID aPrmId, double aValue );
double getProperty( enum PRMS_ID aPrmId ); double getProperty( enum PRMS_ID aPrmId );
void getProperties( void );
void checkProperties( void );
void setResult( int, double, const char* ); void setResult( int, double, const char* );
void setResult( int, const char* ); void setResult( int, const char* );
bool isSelected( enum PRMS_ID aPrmId ); bool isSelected( enum PRMS_ID aPrmId );
virtual void synthesize() { }; void Init();
virtual void analyze() { }; virtual void synthesize();
virtual void calc(){};
/** @brief Computation for analysis
*/
virtual void calcAnalyze(){};
/** @brief Computation for synthesis
**/
virtual void calcSynthesize(){};
/** @brief Shows synthesis results and checks for errors / warnings.
**/
virtual void showAnalyze(){};
/** @brief Shows analysis results and checks for errors / warnings.
**/
virtual void showSynthesize(){};
/** @brief Shows results
**/
virtual void show_results(){};
void analyze();
KIGFX::COLOR4D errCol = KIGFX::COLOR4D( 1, 0.63, 0.63, 1 );
KIGFX::COLOR4D warnCol = KIGFX::COLOR4D( 1, 1, 0.57, 1 );
KIGFX::COLOR4D okCol = KIGFX::COLOR4D( 1, 1, 1, 1 );
protected: protected:
double m_freq; // Frequency of operation double m_parameters[EXTRA_PRMS_COUNT];
double er; /* dielectric constant */ double len; // length of line
double m_tand; // Dielectric Loss Tangent double er_eff; // effective dielectric constant
double m_sigma; // Conductivity of the metal double ang_l; // Electrical length in angle
double m_murC; // magnetic permeability of conductor
double m_skindepth; // Skin depth
bool minimizeZ0Error1D( double* );
double skin_depth(); double skin_depth();
void ellipke( double, double&, double& ); void ellipke( double, double&, double& );
double ellipk( double ); double ellipk( double );
void setErrorLevel( PRMS_ID, char );
}; };
#endif /* __TRANSLINE_H */ #endif /* __TRANSLINE_H */

View File

@ -27,159 +27,181 @@
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <units.h>
#include <transline.h>
#include <twistedpair.h> #include <twistedpair.h>
#include <units.h>
TWISTEDPAIR::TWISTEDPAIR() : TRANSLINE() TWISTEDPAIR::TWISTEDPAIR() : TRANSLINE()
{ {
m_Name = "TwistedPair"; m_Name = "TwistedPair";
Init();
// Initialize these variables mainly to avoid warnings from a static analyzer
din = 0.0; // Inner diameter of conductor
dout = 0.0; // Outer diameter of insulator
twists = 0.0; // Twists per length
er_env = 0.0; // dielectric constant of environment*/
len = 0.0; // Length of cable
Z0 = 0.0; // characteristic impedance
ang_l = 0.0; // Electrical length in angle
atten_dielectric = 0.0; // Loss in dielectric (dB)
atten_cond = 0.0; // Loss in conductors (dB)
er_eff = 1.0; // Effective dielectric constant
} }
// ------------------------------------------------------------------- /**
void TWISTEDPAIR::getProperties() * \f$ \theta = \arctan\left( T \cdot \pi \cdot D_{out} \right) \f$
*
* Where :
* - \f$ \theta \f$ : pitch angle
* - \f$ T \f$ : Number of twists per unit length
* - \f$ D_{out} \f$ : Wire diameter with insulation
*
* \f$ e_{eff} = e_{env} \cdot \left( 0.25 + 0.0007 \cdot \theta^2 \right)\cdot\left(e_r-e_{env}\right) \f$
*
* Where :
* - \f$ e_{env} \f$ : relative dielectric constant of air ( or some other surronding material ),
* - \f$ e_r \f$ : relative dielectric constant of the film insulation,
* - \f$ e_{eff} \f$ : effective relative dielectric constant
*
* \f$ Z_0 = \frac{Z_\mathrm{VACCUM}}{\pi \cdot \sqrt{e_{eff}}}\cosh^{-1}\left(\frac{D_{out}}{D_{in}}\right) \f$
*
* - \f$ Z_0 \f$ : line impedance
* - \f$ Z_\mathrm{VACCUM} \f$ : vaccum impedance
* - \f$ D_{in} \f$ : Wire diameter without insulation
*
* Reference for above equations :
*
* [1] : P. Lefferson, ``Twisted Magnet Wire Transmission Line,''
* IEEE Transactions on Parts, Hybrids, and Packaging, vol. PHP-7, no. 4, pp. 148-154, Dec. 1971.
*
* The following URL can be used as reference : http://qucs.sourceforge.net/tech/node93.html
**/
void TWISTEDPAIR::calcAnalyze()
{ {
m_freq = getProperty( FREQUENCY_PRM );
din = getProperty( PHYS_DIAM_IN_PRM );
dout = getProperty( PHYS_DIAM_OUT_PRM );
len = getProperty( PHYS_LEN_PRM );
er = getProperty( EPSILONR_PRM ); double tw = atan( m_parameters[TWISTEDPAIR_TWIST_PRM] * M_PI
m_murC = getProperty( MURC_PRM ); * m_parameters[PHYS_DIAM_OUT_PRM] ); // pitch angle
m_tand = getProperty( TAND_PRM ); m_parameters[EPSILON_EFF_PRM] =
m_sigma = 1.0 / getProperty( RHO_PRM ); m_parameters[TWISTEDPAIR_EPSILONR_ENV_PRM]
twists = getProperty( TWISTEDPAIR_TWIST_PRM ); + ( 0.25 + 0.0007 * tw * tw )
er_env = getProperty( TWISTEDPAIR_EPSILONR_ENV_PRM ); * ( m_parameters[EPSILONR_PRM] - m_parameters[TWISTEDPAIR_EPSILONR_ENV_PRM] );
Z0 = getProperty( Z0_PRM );
ang_l = getProperty( ANG_L_PRM );
}
m_parameters[Z0_PRM] =
ZF0 / M_PI / sqrt( m_parameters[EPSILON_EFF_PRM] )
* acosh( m_parameters[PHYS_DIAM_OUT_PRM] / m_parameters[PHYS_DIAM_IN_PRM] );
// ------------------------------------------------------------------- m_parameters[LOSS_CONDUCTOR_PRM] =
void TWISTEDPAIR::calc() 10.0 / log( 10.0 ) * m_parameters[PHYS_LEN_PRM] / m_parameters[SKIN_DEPTH_PRM]
{ / m_parameters[SIGMA_PRM] / M_PI / m_parameters[Z0_PRM]
m_skindepth = skin_depth(); / ( m_parameters[PHYS_DIAM_IN_PRM] - m_parameters[SKIN_DEPTH_PRM] );
double tw = atan( twists * M_PI * dout ); // pitch angle m_parameters[LOSS_DIELECTRIC_PRM] = 20.0 / log( 10.0 ) * m_parameters[PHYS_LEN_PRM] * M_PI / C0
er_eff = er_env + (0.25 + 0.0007 * tw * tw) * (er - er_env); * m_parameters[FREQUENCY_PRM]
* sqrt( m_parameters[EPSILON_EFF_PRM] )
* m_parameters[TAND_PRM];
Z0 = ZF0 / M_PI / sqrt( er_eff ) * acosh( dout / din ); m_parameters[ANG_L_PRM] = 2.0 * M_PI * m_parameters[PHYS_LEN_PRM]
* sqrt( m_parameters[EPSILON_EFF_PRM] ) * m_parameters[FREQUENCY_PRM]
atten_cond = 10.0 / log( 10.0 ) * len / m_skindepth / m_sigma / M_PI / Z0 / (din - m_skindepth); / C0; // in radians
atten_dielectric = 20.0 / log( 10.0 ) * len * M_PI / C0* m_freq * sqrt( er_eff ) * m_tand;
ang_l = 2.0* M_PI* len* sqrt( er_eff ) * m_freq / C0; // in radians
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void TWISTEDPAIR::show_results() void TWISTEDPAIR::show_results()
{ {
setProperty( Z0_PRM, Z0 ); setResult( 0, m_parameters[EPSILON_EFF_PRM], "" );
setProperty( ANG_L_PRM, ang_l ); setResult( 1, m_parameters[LOSS_CONDUCTOR_PRM], "dB" );
setResult( 2, m_parameters[LOSS_DIELECTRIC_PRM], "dB" );
setResult( 0, er_eff, "" ); setResult( 3, m_parameters[SKIN_DEPTH_PRM] / UNIT_MICRON, "µm" );
setResult( 1, atten_cond, "dB" );
setResult( 2, atten_dielectric, "dB" );
setResult( 3, m_skindepth / UNIT_MICRON, "µm" );
} }
void TWISTEDPAIR::showAnalyze()
// -------------------------------------------------------------------
void TWISTEDPAIR::analyze()
{ {
getProperties(); setProperty( Z0_PRM, m_parameters[Z0_PRM] );
calc(); setProperty( ANG_L_PRM, m_parameters[ANG_L_PRM] );
show_results();
// Check for errors
if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
{
setErrorLevel( Z0_PRM, TRANSLINE_ERROR );
}
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
{
setErrorLevel( ANG_L_PRM, TRANSLINE_ERROR );
}
// Find warnings to display - physical parameters
if( !std::isfinite( m_parameters[PHYS_DIAM_IN_PRM] ) || m_parameters[PHYS_DIAM_IN_PRM] <= 0.0 )
{
setErrorLevel( PHYS_DIAM_IN_PRM, TRANSLINE_WARNING );
}
if( !std::isfinite( m_parameters[PHYS_DIAM_OUT_PRM] )
|| m_parameters[PHYS_DIAM_OUT_PRM] <= 0.0 )
{
setErrorLevel( PHYS_DIAM_OUT_PRM, TRANSLINE_WARNING );
}
if( m_parameters[PHYS_DIAM_IN_PRM] > m_parameters[PHYS_DIAM_OUT_PRM] )
{
setErrorLevel( PHYS_DIAM_IN_PRM, TRANSLINE_WARNING );
setErrorLevel( PHYS_DIAM_OUT_PRM, TRANSLINE_WARNING );
}
if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] < 0.0 )
{
setErrorLevel( PHYS_LEN_PRM, TRANSLINE_WARNING );
}
}
void TWISTEDPAIR::showSynthesize()
{
if( isSelected( PHYS_DIAM_IN_PRM ) )
setProperty( PHYS_DIAM_IN_PRM, m_parameters[PHYS_DIAM_IN_PRM] );
else if( isSelected( PHYS_DIAM_OUT_PRM ) )
setProperty( PHYS_DIAM_OUT_PRM, m_parameters[PHYS_DIAM_OUT_PRM] );
setProperty( PHYS_LEN_PRM, m_parameters[PHYS_LEN_PRM] );
// Check for errors
if( !std::isfinite( m_parameters[PHYS_DIAM_IN_PRM] ) || m_parameters[PHYS_DIAM_IN_PRM] <= 0.0 )
{
if( isSelected( PHYS_DIAM_IN_PRM ) )
setErrorLevel( PHYS_DIAM_IN_PRM, TRANSLINE_ERROR );
else
setErrorLevel( PHYS_DIAM_IN_PRM, TRANSLINE_WARNING );
}
if( !std::isfinite( m_parameters[PHYS_DIAM_OUT_PRM] )
|| m_parameters[PHYS_DIAM_OUT_PRM] <= 0.0 )
{
if( isSelected( PHYS_DIAM_OUT_PRM ) )
setErrorLevel( PHYS_DIAM_OUT_PRM, TRANSLINE_ERROR );
else
setErrorLevel( PHYS_DIAM_OUT_PRM, TRANSLINE_WARNING );
}
if( m_parameters[PHYS_DIAM_IN_PRM] > m_parameters[PHYS_DIAM_OUT_PRM] )
{
if( isSelected( PHYS_DIAM_IN_PRM ) )
setErrorLevel( PHYS_DIAM_IN_PRM, TRANSLINE_ERROR );
else if( isSelected( PHYS_DIAM_OUT_PRM ) )
setErrorLevel( PHYS_DIAM_OUT_PRM, TRANSLINE_ERROR );
}
if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || m_parameters[PHYS_LEN_PRM] < 0.0 )
{
setErrorLevel( PHYS_LEN_PRM, TRANSLINE_ERROR );
}
// Check for warnings
if( !std::isfinite( m_parameters[Z0_PRM] ) || m_parameters[Z0_PRM] < 0 )
{
setErrorLevel( Z0_PRM, TRANSLINE_WARNING );
}
if( !std::isfinite( m_parameters[ANG_L_PRM] ) || m_parameters[ANG_L_PRM] < 0 )
{
setErrorLevel( ANG_L_PRM, TRANSLINE_WARNING );
}
} }
#define MAX_ERROR 0.000001 #define MAX_ERROR 0.000001
// ------------------------------------------------------------------- // -------------------------------------------------------------------
void TWISTEDPAIR::synthesize() void TWISTEDPAIR::calcSynthesize()
{ {
double Z0_dest, Z0_current, Z0_result, increment, slope, error;
int iteration;
getProperties();
/* required value of Z0 */
Z0_dest = Z0;
/* Newton's method */
iteration = 0;
/* compute parameters */
calc();
Z0_current = Z0;
error = fabs( Z0_dest - Z0_current );
while( error > MAX_ERROR )
{
iteration++;
if( isSelected( PHYS_DIAM_IN_PRM ) ) if( isSelected( PHYS_DIAM_IN_PRM ) )
{ minimizeZ0Error1D( &( m_parameters[PHYS_DIAM_IN_PRM] ) );
increment = din / 100.0;
din += increment;
}
else else
{ minimizeZ0Error1D( &( m_parameters[PHYS_DIAM_OUT_PRM] ) );
increment = dout / 100.0;
dout += increment;
}
/* compute parameters */
calc();
Z0_result = Z0;
/* f(w(n)) = Z0 - Z0(w(n)) */
/* f'(w(n)) = -f'(Z0(w(n))) */
/* f'(Z0(w(n))) = (Z0(w(n)) - Z0(w(n+delw))/delw */
/* w(n+1) = w(n) - f(w(n))/f'(w(n)) */
slope = (Z0_result - Z0_current) / increment;
slope = (Z0_dest - Z0_current) / slope - increment;
if( isSelected( PHYS_DIAM_IN_PRM ) )
din += slope;
else
dout += slope;
if( din <= 0.0 )
din = increment;
if( dout <= 0.0 )
dout = increment;
/* find new error */
/* compute parameters */
calc();
Z0_current = Z0;
error = fabs( Z0_dest - Z0_current );
if( iteration > 100 )
break;
}
setProperty( PHYS_DIAM_IN_PRM, din );
setProperty( PHYS_DIAM_OUT_PRM, dout );
/* calculate physical length */
ang_l = getProperty( ANG_L_PRM );
len = C0 / m_freq / sqrt( er_eff ) * ang_l / 2.0 / M_PI; /* in m */
setProperty( PHYS_LEN_PRM, len );
/* compute parameters */
calc();
/* print results in the subwindow */
show_results();
} }

View File

@ -24,30 +24,19 @@
#ifndef __TWISTEDPAIR_H #ifndef __TWISTEDPAIR_H
#define __TWISTEDPAIR_H #define __TWISTEDPAIR_H
#include <transline.h>
class TWISTEDPAIR : public TRANSLINE class TWISTEDPAIR : public TRANSLINE
{ {
public: TWISTEDPAIR();
private:
double din; // Inner diameter of conductor
double dout; // Outer diameter of insulator
double twists; // Twists per length
double er_env; // dielectric constant of environment*/
double len; // Length of cable
double Z0; // characteristic impedance
double ang_l; // Electrical length in angle
double er_eff; // Effective dielectric constant
double atten_dielectric; // Loss in dielectric (dB)
double atten_cond; // Loss in conductors (dB)
public: public:
void analyze() override; TWISTEDPAIR();
void synthesize() override;
private: private:
void calc(); void calcAnalyze() override;
void show_results(); void calcSynthesize() override;
void getProperties(); void showAnalyze() override;
void showSynthesize() override;
void show_results() override;
}; };
#endif #endif

View File

@ -17,8 +17,9 @@
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <wx/wx.h>
#include <wx/filename.h> #include <wx/filename.h>
#include <wx/settings.h>
#include <wx/wx.h>
#include <pcb_calculator_frame_base.h> #include <pcb_calculator_frame_base.h>
@ -316,7 +317,7 @@ void PCB_CALCULATOR_FRAME::TranslineTypeSelection( enum TRANSLINE_TYPE_ID aType
} }
wxASSERT ( data ); wxASSERT ( data );
data->name->SetToolTip( prm->m_ToolTip ); data->name->SetToolTip( prm->m_ToolTip );
data->name->SetLabel( prm->m_Label ); data->name->SetLabel( prm->m_Label != "" ? prm->m_Label + ':' : "" );
prm->m_ValueCtrl = data->value; prm->m_ValueCtrl = data->value;
if( prm->m_Id != DUMMY_PRM ) if( prm->m_Id != DUMMY_PRM )
{ {
@ -436,6 +437,25 @@ void PCB_CALCULATOR_FRAME::OnTranslineSelection( wxCommandEvent& event )
// The new size must be taken in account // The new size must be taken in account
m_panelTransline->GetSizer()->Layout(); m_panelTransline->GetSizer()->Layout();
m_panelTransline->Refresh(); m_panelTransline->Refresh();
// Delete previous warnings / errors
wxColour background = wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW );
m_Value_EpsilonR->SetBackgroundColour( background );
m_Value_TanD->SetBackgroundColour( background );
m_Value_Rho->SetBackgroundColour( background );
m_Substrate_prm4_Value->SetBackgroundColour( background );
m_Substrate_prm5_Value->SetBackgroundColour( background );
m_Substrate_prm6_Value->SetBackgroundColour( background );
m_Substrate_prm7_Value->SetBackgroundColour( background );
m_Substrate_prm8_Value->SetBackgroundColour( background );
m_Substrate_prm9_Value->SetBackgroundColour( background );
m_Value_Frequency_Ctrl->SetBackgroundColour( background );
m_Phys_prm1_Value->SetBackgroundColour( background );
m_Phys_prm2_Value->SetBackgroundColour( background );
m_Phys_prm3_Value->SetBackgroundColour( background );
m_elec_prm1_label->SetBackgroundColour( background );
m_elec_prm2_label->SetBackgroundColour( background );
m_elec_prm3_label->SetBackgroundColour( background );
} }

View File

@ -107,21 +107,21 @@ TRANSLINE_IDENT::TRANSLINE_IDENT( enum TRANSLINE_TYPE_ID aType )
// Add common prms: // Add common prms:
// Default values are for FR4 // Default values are for FR4
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, EPSILONR_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, EPSILONR_PRM,
_( "Er:" ), _( "Epsilon R: substrate relative dielectric constant" ), _( "Er" ), _( "Epsilon R: substrate relative dielectric constant" ),
4.6, false ) ); 4.6, false ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, TAND_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, TAND_PRM,
_( "TanD:" ), _( "Tangent delta: dielectric loss factor." ), 2e-2, _( "TanD" ), _( "Tangent delta: dielectric loss factor." ), 2e-2,
false ) ); false ) );
// Default value is for copper // Default value is for copper
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, RHO_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, RHO_PRM,
_( "Rho:" ), _( "Rho" ),
_( "Electrical resistivity or specific electrical resistance of conductor (Ohm*meter)" ), _( "Electrical resistivity or specific electrical resistance of conductor (Ohm*meter)" ),
1.72e-8, false ) ); 1.72e-8, false ) );
// Default value is in GHz // Default value is in GHz
AddPrm( new TRANSLINE_PRM( PRM_TYPE_FREQUENCY, FREQUENCY_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_FREQUENCY, FREQUENCY_PRM,
_( "Frequency:" ), _( "Frequency of the input signal" ), 1.0, true ) ); _( "Frequency" ), _( "Frequency of the input signal" ), 1.0, true ) );
switch( m_Type ) switch( m_Type )
@ -136,30 +136,30 @@ TRANSLINE_IDENT::TRANSLINE_IDENT( enum TRANSLINE_TYPE_ID aType )
m_Messages.Add( _( "Skin Depth:" ) ); m_Messages.Add( _( "Skin Depth:" ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, H_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, H_PRM,
_( "H:" ), _( "Height of Substrate" ), 0.2, true ) ); _( "H" ), _( "Height of Substrate" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, H_T_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, H_T_PRM,
_( "H_t:" ), _( "Height of Box Top" ), 1e20, true ) ); _( "H_t" ), _( "Height of Box Top" ), 1e20, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, T_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, T_PRM,
_( "T:" ), _( "Strip Thickness" ), 0.035, true ) ); _( "T" ), _( "Strip Thickness" ), 0.035, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, ROUGH_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, ROUGH_PRM,
_( "Rough:" ), _( "Conductor Roughness" ), 0.0, true ) ); _( "Rough" ), _( "Conductor Roughness" ), 0.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MUR_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MUR_PRM,
_( "mu Rel S:" ), _( "mu Rel S" ),
_( "Relative Permeability (mu) of Substrate" ), 1, false ) ); _( "Relative Permeability (mu) of Substrate" ), 1, false ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM,
_( "mu Rel C:" ), _( "Relative Permeability (mu) of Conductor" ), 1, _( "mu Rel C" ), _( "Relative Permeability (mu) of Conductor" ), 1,
false ) ); false ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_WIDTH_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_WIDTH_PRM,
_( "W:" ), _( "Line Width" ), 0.2, true ) ); _( "W" ), _( "Line Width" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM,
_( "L:" ), _( "Line Length" ), 50.0, true ) ); _( "L" ), _( "Line Length" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_PRM,
_( "Z0:" ), _( "Characteristic Impedance" ), 50.0, true ) ); _( "Z0" ), _( "Characteristic Impedance" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, DUMMY_PRM ) ); AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, DUMMY_PRM ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM,
_( "Ang_l:" ), _( "Electrical Length" ), 0.0, true ) ); _( "Ang_l" ), _( "Electrical Length" ), 0.0, true ) );
break; break;
case CPW_TYPE: // coplanar waveguide case CPW_TYPE: // coplanar waveguide
@ -173,25 +173,25 @@ TRANSLINE_IDENT::TRANSLINE_IDENT( enum TRANSLINE_TYPE_ID aType )
m_Messages.Add( _( "Skin Depth:" ) ); m_Messages.Add( _( "Skin Depth:" ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, H_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, H_PRM,
_( "H:" ), _( "Height of Substrate" ), 0.2, true ) ); _( "H" ), _( "Height of Substrate" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, T_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, T_PRM,
_( "T:" ), _( "Strip Thickness" ), 0.035, true ) ); _( "T" ), _( "Strip Thickness" ), 0.035, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM,
_( "mu Rel C:" ), _( "Relative Permeability (mu) of Conductor" ), 1, _( "mu Rel C" ), _( "Relative Permeability (mu) of Conductor" ), 1,
false ) ); false ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_WIDTH_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_WIDTH_PRM,
_( "W:" ), _( "Line Width" ), 0.2, true ) ); _( "W" ), _( "Line Width" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_S_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_S_PRM,
_( "S:" ), _( "Gap Width" ), 0.2, true ) ); _( "S" ), _( "Gap Width" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM,
_( "L:" ), _( "Line Length" ), 50.0, true ) ); _( "L" ), _( "Line Length" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_PRM,
_( "Z0:" ), _( "Characteristic Impedance" ), 50.0, true ) ); _( "Z0" ), _( "Characteristic Impedance" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, DUMMY_PRM ) ); AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, DUMMY_PRM ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM,
_( "Ang_l:" ), _( "Electrical Length" ), 0.0, true ) ); _( "Ang_l" ), _( "Electrical Length" ), 0.0, true ) );
break; break;
case GROUNDED_CPW_TYPE: // grounded coplanar waveguide case GROUNDED_CPW_TYPE: // grounded coplanar waveguide
@ -205,25 +205,25 @@ TRANSLINE_IDENT::TRANSLINE_IDENT( enum TRANSLINE_TYPE_ID aType )
m_Messages.Add( _( "Skin Depth:" ) ); m_Messages.Add( _( "Skin Depth:" ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, H_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, H_PRM,
_( "H:" ), _( "Height of Substrate" ), 0.2, true ) ); _( "H" ), _( "Height of Substrate" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, T_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, T_PRM,
_( "T:" ), _( "Strip Thickness" ), 0.035, true ) ); _( "T" ), _( "Strip Thickness" ), 0.035, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM,
_( "mu Rel C:" ), _( "Relative Permeability (mu) of Conductor" ), 1, _( "mu Rel C" ), _( "Relative Permeability (mu) of Conductor" ), 1,
false ) ); false ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_WIDTH_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_WIDTH_PRM,
_( "W:" ), _( "Line Width" ), 0.2, true ) ); _( "W" ), _( "Line Width" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_S_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_S_PRM,
_( "S:" ), _( "Gap Width" ), 0.2, true ) ); _( "S" ), _( "Gap Width" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM,
_( "L:" ), _( "Line Length" ), 50.0, true ) ); _( "L" ), _( "Line Length" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_PRM,
_( "Z0:" ), _( "Characteristic Impedance" ), 50.0, true ) ); _( "Z0" ), _( "Characteristic Impedance" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, DUMMY_PRM ) ); AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, DUMMY_PRM ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM,
_( "Ang_l:" ), _( "Electrical Length" ), 0, true ) ); _( "Ang_l" ), _( "Electrical Length" ), 0, true ) );
break; break;
@ -240,23 +240,23 @@ TRANSLINE_IDENT::TRANSLINE_IDENT( enum TRANSLINE_TYPE_ID aType )
m_Messages.Add( _( "TM-Modes:" ) ); m_Messages.Add( _( "TM-Modes:" ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MUR_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MUR_PRM,
_( "mu Rel I:" ), _( "Relative Permeability (mu) of Insulator" ), 1, false ) ); _( "mu Rel I" ), _( "Relative Permeability (mu) of Insulator" ), 1, false ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM,
_( "mu Rel C:" ), _( "Relative Permeability (mu) of Conductor" ), 1, _( "mu Rel C" ), _( "Relative Permeability (mu) of Conductor" ), 1,
false ) ); false ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_WIDTH_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_WIDTH_PRM,
_( "a:" ), _( "Width of Waveguide" ), 10.0, true ) ); _( "a" ), _( "Width of Waveguide" ), 10.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_S_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_S_PRM,
_( "b:" ), _( "Height of Waveguide" ), 5.0, true ) ); _( "b" ), _( "Height of Waveguide" ), 5.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM,
_( "L:" ), _( "Waveguide Length" ), 50.0, true ) ); _( "L" ), _( "Waveguide Length" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_PRM,
_( "Z0:" ), _( "Characteristic Impedance" ), 50.0, true ) ); _( "Z0" ), _( "Characteristic Impedance" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, DUMMY_PRM ) ); AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, DUMMY_PRM ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM,
_( "Ang_l:" ), _( "Electrical Length" ), 0, true ) ); _( "Ang_l" ), _( "Electrical Length" ), 0, true ) );
break; break;
case COAX_TYPE: // coaxial cable case COAX_TYPE: // coaxial cable
@ -271,23 +271,23 @@ TRANSLINE_IDENT::TRANSLINE_IDENT( enum TRANSLINE_TYPE_ID aType )
m_Messages.Add( _( "TM-Modes:" ) ); m_Messages.Add( _( "TM-Modes:" ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MUR_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MUR_PRM,
_( "mu Rel I:" ), _( "Relative Permeability (mu) of Insulator" ), 1, false ) ); _( "mu Rel I" ), _( "Relative Permeability (mu) of Insulator" ), 1, false ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM,
_( "mu Rel C:" ), _( "Relative Permeability (mu) of Conductor" ), 1, _( "mu Rel C" ), _( "Relative Permeability (mu) of Conductor" ), 1,
false ) ); false ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_DIAM_IN_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_DIAM_IN_PRM,
_( "Din:" ), _( "Inner Diameter (conductor)" ), 1.0, true ) ); _( "Din" ), _( "Inner Diameter (conductor)" ), 1.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_DIAM_OUT_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_DIAM_OUT_PRM,
_( "Dout:" ), _( "Outer Diameter (insulator)" ), 8.0, true ) ); _( "Dout" ), _( "Outer Diameter (insulator)" ), 8.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM,
_( "L:" ), _( "Line Length" ), 50.0, true ) ); _( "L" ), _( "Line Length" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_PRM,
_( "Z0:" ), _( "Characteristic Impedance" ), 50.0, true ) ); _( "Z0" ), _( "Characteristic Impedance" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, DUMMY_PRM ) ); AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, DUMMY_PRM ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM,
_( "Ang_l:" ), _( "Electrical Length" ), 0.0, true ) ); _( "Ang_l" ), _( "Electrical Length" ), 0.0, true ) );
break; break;
case C_MICROSTRIP_TYPE: // coupled microstrip case C_MICROSTRIP_TYPE: // coupled microstrip
@ -304,30 +304,30 @@ TRANSLINE_IDENT::TRANSLINE_IDENT( enum TRANSLINE_TYPE_ID aType )
m_Messages.Add( _( "Skin Depth:" ) ); m_Messages.Add( _( "Skin Depth:" ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, H_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, H_PRM,
_( "H:" ), _( "Height of Substrate" ), 0.2, true ) ); _( "H" ), _( "Height of Substrate" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, H_T_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, H_T_PRM,
_( "H_t:" ), _( "Height of Box Top" ), 1e20, true ) ); _( "H_t" ), _( "Height of Box Top" ), 1e20, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, T_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, T_PRM,
_( "T:" ), _( "Strip Thickness" ), 0.035, true ) ); _( "T" ), _( "Strip Thickness" ), 0.035, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, ROUGH_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, ROUGH_PRM,
_( "Rough:" ), _( "Conductor Roughness" ), 0.0, true ) ); _( "Rough" ), _( "Conductor Roughness" ), 0.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM,
_( "mu Rel C:" ), _( "Relative Permeability (mu) of Conductor" ), 1, _( "mu Rel C" ), _( "Relative Permeability (mu) of Conductor" ), 1,
false ) ); false ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_WIDTH_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_WIDTH_PRM,
_( "W:" ), _( "Line Width" ), 0.2, true ) ); _( "W" ), _( "Line Width" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_S_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_S_PRM,
_( "S:" ), _( "Gap Width" ), 0.2, true ) ); _( "S" ), _( "Gap Width" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM,
_( "L:" ), _( "Line Length" ), 50.0, true ) ); _( "L" ), _( "Line Length" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_E_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_E_PRM,
_( "Zeven:" ), _( "Even mode impedance (lines driven by common voltages)" ), 50.0, true ) ); _( "Zeven" ), _( "Even mode impedance (lines driven by common voltages)" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_O_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_O_PRM,
_( "Zodd:" ), _( "Odd mode impedance (lines driven by opposite (differential) voltages)" ), 50.0, true ) ); _( "Zodd" ), _( "Odd mode impedance (lines driven by opposite (differential) voltages)" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM,
_( "Ang_l:" ), _( "Electrical Length" ), 0.0, true ) ); _( "Ang_l" ), _( "Electrical Length" ), 0.0, true ) );
break; break;
case STRIPLINE_TYPE: // stripline case STRIPLINE_TYPE: // stripline
@ -340,26 +340,26 @@ TRANSLINE_IDENT::TRANSLINE_IDENT( enum TRANSLINE_TYPE_ID aType )
m_Messages.Add( _( "Skin Depth:" ) ); m_Messages.Add( _( "Skin Depth:" ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, H_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, H_PRM,
_( "H:" ), _( "Height of Substrate" ), 0.2, true ) ); _( "H" ), _( "Height of Substrate" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, STRIPLINE_A_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, STRIPLINE_A_PRM,
_( "a:" ), _( "distance between strip and top metal" ), 0.2, _( "a" ), _( "distance between strip and top metal" ), 0.2,
true ) ); true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, T_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, T_PRM,
_( "T:" ), _( "Strip Thickness" ), 0.035, true ) ); _( "T" ), _( "Strip Thickness" ), 0.035, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM,
_( "mu Rel C:" ), _( "Relative Permeability (mu) of Conductor" ), 1, _( "mu Rel C" ), _( "Relative Permeability (mu) of Conductor" ), 1,
false ) ); false ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_WIDTH_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_WIDTH_PRM,
_( "W:" ), _( "Line Width" ), 0.2, true ) ); _( "W" ), _( "Line Width" ), 0.2, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM,
_( "L:" ), _( "Line Length" ), 50.0, true ) ); _( "L" ), _( "Line Length" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_PRM,
_( "Z0:" ), _( "Characteristic Impedance" ), 50, true ) ); _( "Z0" ), _( "Characteristic Impedance" ), 50, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, DUMMY_PRM ) ); AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, DUMMY_PRM ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM,
_( "Ang_l:" ), _( "Electrical Length" ), 0, true ) ); _( "Ang_l" ), _( "Electrical Length" ), 0, true ) );
break; break;
case TWISTEDPAIR_TYPE: // twisted pair case TWISTEDPAIR_TYPE: // twisted pair
@ -373,25 +373,25 @@ TRANSLINE_IDENT::TRANSLINE_IDENT( enum TRANSLINE_TYPE_ID aType )
m_Messages.Add( _( "Skin Depth:" ) ); m_Messages.Add( _( "Skin Depth:" ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, TWISTEDPAIR_TWIST_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, TWISTEDPAIR_TWIST_PRM,
_( "Twists:" ), _( "Number of Twists per Length" ), 0.0, false ) ); _( "Twists" ), _( "Number of Twists per Length" ), 0.0, false ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, MURC_PRM,
_( "mu Rel C:" ), _( "Relative Permeability (mu) of Conductor" ), 1, _( "mu Rel C" ), _( "Relative Permeability (mu) of Conductor" ), 1,
false ) ); false ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, TWISTEDPAIR_EPSILONR_ENV_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_SUBS, TWISTEDPAIR_EPSILONR_ENV_PRM,
_( "ErEnv:" ), _( "Relative Permittivity of Environment" ), 1, _( "ErEnv" ), _( "Relative Permittivity of Environment" ), 1,
false ) ); false ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_DIAM_IN_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_DIAM_IN_PRM,
_( "Din:" ), _( "Inner Diameter (conductor)" ), 1.0, true ) ); _( "Din" ), _( "Inner Diameter (conductor)" ), 1.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_DIAM_OUT_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_DIAM_OUT_PRM,
_( "Dout:" ), _( "Outer Diameter (insulator)" ), 8.0, true ) ); _( "Dout" ), _( "Outer Diameter (insulator)" ), 8.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_PHYS, PHYS_LEN_PRM,
_( "L:" ), _( "Cable Length" ), 50.0, true ) ); _( "L" ), _( "Cable Length" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, Z0_PRM,
_( "Z0:" ), _( "Characteristic Impedance" ), 50.0, true ) ); _( "Z0" ), _( "Characteristic Impedance" ), 50.0, true ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, DUMMY_PRM ) ); AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, DUMMY_PRM ) );
AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM, AddPrm( new TRANSLINE_PRM( PRM_TYPE_ELEC, ANG_L_PRM,
_( "Ang_l:" ), _( "Electrical Length" ), 0.0, true ) ); _( "Ang_l" ), _( "Electrical Length" ), 0.0, true ) );
break; break;
case END_OF_LIST_TYPE: // Not really used case END_OF_LIST_TYPE: // Not really used
@ -422,7 +422,7 @@ void TRANSLINE_IDENT::ReadConfig()
for( auto& param : m_prms_List ) for( auto& param : m_prms_List )
{ {
std::string id = std::to_string( param->m_Id ); std::string id = param->m_Label.ToStdString();
try try
{ {
@ -443,7 +443,13 @@ void TRANSLINE_IDENT::WriteConfig()
for( auto& param : m_prms_List ) for( auto& param : m_prms_List )
{ {
std::string id = std::to_string( param->m_Id ); std::string id = param->m_Label.ToStdString();
if( !std::isfinite( param->m_Value ) )
{
param->m_Value = 0;
}
cfg->m_TransLine.param_values[ name ][ id ] = param->m_Value; cfg->m_TransLine.param_values[ name ][ id ] = param->m_Value;
cfg->m_TransLine.param_units[ name ][ id ] = param->m_UnitSelection; cfg->m_TransLine.param_units[ name ][ id ] = param->m_UnitSelection;
} }