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>
/* /*
@ -39,8 +40,8 @@ double DoubleFromString( const wxString& TextValue )
double value = 0; double value = 0;
/* Acquire the 'right' decimal point separator */ /* Acquire the 'right' decimal point separator */
const struct lconv* lc = localeconv(); const struct lconv* lc = localeconv();
wxChar decimal_point = lc->decimal_point[0]; wxChar decimal_point = lc->decimal_point[0];
wxString buf( TextValue.Strip( wxString::both ) ); wxString buf( TextValue.Strip( wxString::both ) );
/* Convert the period in decimal point */ /* Convert the period in decimal point */
@ -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,16 +85,22 @@ 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,15 +119,15 @@ 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 );
} }
// 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
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,13 +216,13 @@ 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
}; };
wxASSERT( ( aLineNumber >= 0 ) && ( aLineNumber < MSG_CNT_MAX ) ); wxASSERT( ( aLineNumber >= 0 ) && ( aLineNumber < MSG_CNT_MAX ) );
@ -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 );
} }
@ -194,24 +240,23 @@ void PCB_CALCULATOR_FRAME::SetResult( int aLineNumber, const wxString & aText )
* @return true if the param aPrmId is selected * @return 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
*/ */
bool PCB_CALCULATOR_FRAME::IsPrmSelected( enum PRMS_ID aPrmId ) 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:
case PHYS_DIAM_IN_PRM: case PHYS_DIAM_IN_PRM:
return m_radioBtnPrm1->GetValue(); return m_radioBtnPrm1->GetValue();
break; break;
case PHYS_S_PRM: case PHYS_S_PRM:
case PHYS_DIAM_OUT_PRM: case PHYS_DIAM_OUT_PRM:
return m_radioBtnPrm2->GetValue(); return m_radioBtnPrm2->GetValue();
break; break;
} }
return false; return false;
} }

View File

@ -21,15 +21,15 @@
* @file pcb_calculator.h * @file pcb_calculator.h
*/ */
#ifndef PCB_CALCULATOR_H #ifndef PCB_CALCULATOR_H
#define PCB_CALCULATOR_H #define PCB_CALCULATOR_H
#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;
@ -42,29 +42,28 @@ public:
REGULATOR_LIST m_RegulatorList; // the list of known regulator REGULATOR_LIST m_RegulatorList; // the list of known regulator
private: private:
bool m_RegulatorListChanged; // set to true when m_RegulatorList bool m_RegulatorListChanged; // set to true when m_RegulatorList
// was modified, and the corresponging file // was modified, and the corresponging file
// must be rewritten // must be rewritten
enum // Which dimension is controlling the track enum // Which dimension is controlling the track
{ // width / current calculations: { // width / current calculations:
TW_MASTER_CURRENT, // the maximum current, TW_MASTER_CURRENT, // the maximum current,
TW_MASTER_EXT_WIDTH, // the external trace width, TW_MASTER_EXT_WIDTH, // the external trace width,
TW_MASTER_INT_WIDTH // or the internal trace width? TW_MASTER_INT_WIDTH // or the internal trace width?
} m_TWMode; } m_TWMode;
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:
@ -72,7 +71,6 @@ public:
~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
@ -226,8 +224,8 @@ private:
* Displays the results of the calculation. * Displays the results of the calculation.
*/ */
void VSDisplayValues( double aViaResistance, double aVoltageDrop, double aPowerLoss, void VSDisplayValues( double aViaResistance, double aVoltageDrop, double aPowerLoss,
double aEstimatedAmpacity, double aThermalResistance, double aCapacitance, double aEstimatedAmpacity, double aThermalResistance, double aCapacitance,
double aTimeDegradation, double aInductance, double aReactance ); double aTimeDegradation, double aInductance, double aReactance );
// Electrical spacing panel: // Electrical spacing panel:
void OnElectricalSpacingUnitsSelection( wxCommandEvent& event ) override; void OnElectricalSpacingUnitsSelection( wxCommandEvent& event ) override;
@ -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.
@ -373,17 +377,20 @@ public:
* @return true if the param aPrmId is selected * @return 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
*/ */
bool IsPrmSelected( enum PRMS_ID aPrmId ); bool IsPrmSelected( enum PRMS_ID aPrmId );
// Board classes panel: // Board classes panel:
void OnBoardClassesUnitsSelection( wxCommandEvent& event ) override; void OnBoardClassesUnitsSelection( wxCommandEvent& event ) override;
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;
}
}; };
extern const wxString DataFileNameExt; extern const wxString DataFileNameExt;
#endif // PCB_CALCULATOR_H #endif // PCB_CALCULATOR_H

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 );
} }
@ -495,36 +469,42 @@ void C_MICROSTRIP::conductor_losses()
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;
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;
@ -636,45 +609,46 @@ void C_MICROSTRIP::synth_width()
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;
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,42 +25,42 @@
#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:
double h; // height of substrate double h; // height of substrate
double ht; // height to the top of box double ht; // height to the top of box
double t; // thickness of top metal double t; // thickness of top metal
double rough; // Roughness of top metal double rough; // Roughness of top metal
double w; // width of lines double w; // width of lines
double w_t_e; // even-mode thickness-corrected line width double w_t_e; // even-mode thickness-corrected line width
double w_t_o; // odd-mode thickness-corrected line width double w_t_o; // odd-mode thickness-corrected line width
double l; // length of lines double l; // length of lines
double s; // spacing of lines double s; // spacing of lines
double Z0_e_0; // static even-mode impedance double Z0_e_0; // static even-mode impedance
double Z0_o_0; // static odd-mode impedance double Z0_o_0; // static odd-mode impedance
double Z0e; // even-mode impedance double Z0e; // even-mode impedance
double Z0o; // odd-mode impedance double Z0o; // odd-mode impedance
double c_e; // even-mode capacitance double c_e; // even-mode capacitance
double c_o; // odd-mode capacitance double c_o; // odd-mode capacitance
double ang_l_e; // even-mode electrical length in angle double ang_l_e; // even-mode electrical length in angle
double ang_l_o; // odd-mode electrical length in angle double ang_l_o; // odd-mode electrical length in angle
double er_eff_e; // even-mode effective dielectric constant double er_eff_e; // even-mode effective dielectric constant
double er_eff_o; // odd-mode effective dielectric constant double er_eff_o; // odd-mode effective dielectric constant
double er_eff_e_0; // static even-mode effective dielectric constant double er_eff_e_0; // static even-mode effective dielectric constant
double er_eff_o_0; // static odd-mode effective dielectric constant double er_eff_o_0; // static odd-mode effective dielectric constant
double w_eff; // Effective width of line double w_eff; // Effective width of line
double atten_dielectric_e; // even-mode dielectric losses (dB) double atten_dielectric_e; // even-mode dielectric losses (dB)
double atten_cond_e; // even-mode conductors losses (dB) double atten_cond_e; // even-mode conductors losses (dB)
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 );
@ -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 );
@ -95,4 +94,4 @@ private:
MICROSTRIP* aux_ms; MICROSTRIP* aux_ms;
}; };
#endif // _C_MICROSTRIP_H_ #endif // _C_MICROSTRIP_H_

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,133 +56,224 @@ 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
*/ */
void COAX::show_results() 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,105 +28,86 @@
#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
} }
GROUNDEDCOPLANAR::GROUNDEDCOPLANAR() : COPLANAR() GROUNDEDCOPLANAR::GROUNDEDCOPLANAR() : COPLANAR()
{ {
m_Name = "GrCoPlanar"; m_Name = "GrCoPlanar";
backMetal = true; backMetal = true;
} }
// ------------------------------------------------------------------- // -------------------------------------------------------------------
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] ) )
q3 = ellipk( k3 ) / ellipk( sqrt( 1 - k3 * k3 ) ); / tanh( ( M_PI / 4 )
qz = 1 / (q1 + q3); * ( m_parameters[PHYS_WIDTH_PRM] + m_parameters[PHYS_S_PRM]
er0 = 1 + q3 * qz * (er - 1); + m_parameters[PHYS_S_PRM] )
/ m_parameters[H_PRM] );
q3 = ellipk( k3 ) / ellipk( sqrt( 1 - k3 * k3 ) );
qz = 1 / ( q1 + q3 );
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] ) )
q2 = ellipk( k2 ) / ellipk( sqrt( 1 - k2 * k2 ) ); / sinh( ( M_PI / 4 )
er0 = 1 + (er - 1) / 2 * q2 / q1; * ( 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 ) );
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; if( isSelected( PHYS_WIDTH_PRM ) )
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; minimizeZ0Error1D( &( m_parameters[PHYS_WIDTH_PRM] ) );
ang_l= ang_l_tmp;
if( isSelected( PHYS_WIDTH_PRM ) )
{
setProperty( PHYS_WIDTH_PRM, NAN );
}
else
{
setProperty( PHYS_S_PRM, NAN );
}
setProperty( PHYS_LEN_PRM, NAN );
/* print results in the subwindow */
show_results();
return;
} }
else
/* Newton's method */
iteration = 0;
Z0_current = Z0;
error = fabs( Z0_dest - Z0_current );
while( error > MAX_ERROR )
{ {
iteration++; minimizeZ0Error1D( &( m_parameters[PHYS_S_PRM] ) );
if( isSelected( PHYS_WIDTH_PRM ) )
{
increment = w / 100.0;
w += increment;
}
else
{
increment = s / 100.0;
s += increment;
}
/* compute coplanar 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_WIDTH_PRM ) )
w += slope;
else
s += slope;
if( w <= 0.0 )
w = increment;
if( s <= 0.0 )
s = increment;
/* find new error */
/* compute coplanar parameters */
calc();
Z0_current = Z0;
error = fabs( Z0_dest - Z0_current );
if( iteration > 100 )
break;
} }
}
setProperty( PHYS_WIDTH_PRM, w );
setProperty( PHYS_S_PRM, s ); // -------------------------------------------------------------------
/* calculate physical length */ void COPLANAR::showSynthesize()
ang_l = getProperty( ANG_L_PRM ); {
len = C0 / m_freq / sqrt( er_eff ) * ang_l / 2.0 / M_PI; /* in m */ if( isSelected( PHYS_WIDTH_PRM ) )
setProperty( PHYS_LEN_PRM, len ); setProperty( PHYS_WIDTH_PRM, m_parameters[PHYS_WIDTH_PRM] );
/* compute coplanar parameters */ if( isSelected( PHYS_S_PRM ) )
calc(); setProperty( PHYS_S_PRM, m_parameters[PHYS_S_PRM] );
/* print results in the subwindow */ setProperty( PHYS_LEN_PRM, m_parameters[PHYS_LEN_PRM] );
show_results();
if( !std::isfinite( m_parameters[PHYS_S_PRM] ) || m_parameters[PHYS_S_PRM] <= 0 )
{
if( isSelected( PHYS_S_PRM ) )
setErrorLevel( PHYS_S_PRM, TRANSLINE_ERROR );
else
setErrorLevel( PHYS_S_PRM, TRANSLINE_WARNING );
}
if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || m_parameters[PHYS_WIDTH_PRM] <= 0 )
{
if( isSelected( PHYS_WIDTH_PRM ) )
setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_ERROR );
else
setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_WARNING );
}
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[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 COPLANAR::showAnalyze()
{
setProperty( Z0_PRM, m_parameters[Z0_PRM] );
setProperty( ANG_L_PRM, m_parameters[ANG_L_PRM] );
if( !std::isfinite( m_parameters[PHYS_S_PRM] ) || m_parameters[PHYS_S_PRM] <= 0 )
setErrorLevel( PHYS_S_PRM, TRANSLINE_WARNING );
if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || m_parameters[PHYS_WIDTH_PRM] <= 0 )
setErrorLevel( PHYS_WIDTH_PRM, TRANSLINE_WARNING );
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[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 );
} }

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,14 +229,11 @@ 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;
R_1 = 0.03891 * pow( e_r, 1.4 ); R_1 = 0.03891 * pow( e_r, 1.4 );
R_2 = 0.267 * pow( u, 7.0 ); R_2 = 0.267 * pow( u, 7.0 );
@ -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,36 +25,35 @@
#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;
private: private:
double h; // height of substrate double h; // height of substrate
double ht; // height to the top of box double ht; // height to the top of box
double t; // thickness of top metal double t; // thickness of top metal
double rough; // Roughness of top metal double rough; // Roughness of top metal
double mur; // magnetic permeability of substrate double mur; // magnetic permeability of substrate
double w; // width of line double w; // width of line
double l; // length of line double l; // length of line
double Z0_0; // static characteristic impedance double Z0_0; // static characteristic impedance
double Z0; // characteristic impedance double Z0; // characteristic impedance
double ang_l; // Electrical length in angle double ang_l; // Electrical length in angle
double er_eff_0; // Static effective dielectric constant double er_eff_0; // Static effective dielectric constant
double er_eff; // Effective dielectric constant double er_eff; // Effective dielectric constant
double mur_eff; // Effective mag. permeability double mur_eff; // Effective mag. permeability
double w_eff; // Effective width of line double w_eff; // Effective width of line
double atten_dielectric; // Loss in dielectric (dB) double atten_dielectric; // Loss in dielectric (dB)
double atten_cond; // Loss in conductors (dB) double atten_cond; // Loss in conductors (dB)
// 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();
@ -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;
} }
@ -88,13 +77,18 @@ double RECTWAVEGUIDE::fc( int m, int n )
*/ */
double RECTWAVEGUIDE::alphac() 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,28 +25,32 @@
#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
double a; // width of waveguide double a; // width of waveguide
double b; // height of waveguide double b; // height of waveguide
double l; // length of waveguide double l; // length of waveguide
double Z0; // characteristic impedance double Z0; // characteristic impedance
double Z0EH; // characteristic impedance of field quantities*/ double Z0EH; // characteristic impedance of field quantities*/
double ang_l; // Electrical length in angle double ang_l; // Electrical length in angle
double er_eff; // Effective dielectric constant double er_eff; // Effective dielectric constant
double mur_eff; // Effective mag. permeability double mur_eff; // Effective mag. permeability
double atten_dielectric; // Loss in dielectric (dB) double atten_dielectric; // Loss in dielectric (dB)
double atten_cond; // Loss in conductors (dB) double atten_cond; // Loss in conductors (dB)
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
@ -55,21 +56,22 @@ double GetPropertyInDialog( enum PRMS_ID aPrmId );
// 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
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,19 +267,19 @@ 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 );
c = sqrt( da ); c = sqrt( da );
fr = 0.5; fr = 0.5;
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;
s += fr * c * c; s += fr * c * c;
if( c / a < NR_EPSI ) if( c / a < NR_EPSI )
@ -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 setResult( int, double, const char* );
void setResult( int, const char* );
bool isSelected( enum PRMS_ID aPrmId );
virtual void synthesize() { };
virtual void analyze() { }; void getProperties( void );
void checkProperties( void );
void setResult( int, double, const char* );
void setResult( int, const char* );
bool isSelected( enum PRMS_ID aPrmId );
void Init();
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; if( isSelected( PHYS_DIAM_IN_PRM ) )
int iteration; minimizeZ0Error1D( &( m_parameters[PHYS_DIAM_IN_PRM] ) );
else
getProperties(); minimizeZ0Error1D( &( m_parameters[PHYS_DIAM_OUT_PRM] ) );
/* 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 ) )
{
increment = din / 100.0;
din += increment;
}
else
{
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;
} }