39std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>&
47std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>&
76 if( !std::isfinite( Z0_param ) )
82 if( ( !std::isfinite( var ) ) || ( var == 0 ) )
86 double Z0_dest = Z0_param;
89 double angl_l_dest = ANG_L_param;
96 double Z0_current = Z0_param;
98 double error = fabs( Z0_dest - Z0_current );
103 double increment = var / 100.0;
108 double Z0_result = Z0_param;
114 double slope = ( Z0_result - Z0_current ) / increment;
115 slope = ( Z0_dest - Z0_current ) / slope - increment;
124 Z0_current = Z0_param;
125 error = fabs( Z0_dest - Z0_current );
127 if( iteration > 250 )
132 if( aRecalculateLength )
135 ANG_L_param = angl_l_dest;
137 * ANG_L_param / 2.0 /
M_PI );
142 ANG_L_param = angl_l_dest;
144 * ANG_L_param / 2.0 /
M_PI );
162 return std::sqrt( aEpsilonEff ) * ( 1.0e10 / 2.99e8 );
181 if( !std::isfinite( fSpec ) || fSpec <= 0.0 )
190 ds.
Fit( epsRSpec, tanDSpec, fSpec );
193 catch(
const std::invalid_argument& )
221 const double wBarEff = aU + ( 2.0 /
M_PI ) * std::log( 17.08 * ( 0.5 * aU + 0.92 ) );
225 const double denom = wBarEff *
M_PI - 4.0;
227 if( denom <= 0.0 || !std::isfinite( denom ) )
230 const double vBar = ( 2.0 /
M_PI ) * std::atan( ( 2.0 *
M_PI / denom ) * ( aHBarTop - 1.0 ) );
231 const double halfPi = 0.5 *
M_PI * vBar;
238 const double q1 = 1.0 - std::log( wBarEff *
M_PI - 1.0 ) / ( 2.0 * wBarEff );
239 const double inner = 2.0 * wBarEff * std::cos( halfPi ) / ( 2.0 * aHBarTop - 1.0 + vBar )
240 + std::sin( halfPi );
242 if( inner <= 0.0 || !std::isfinite( inner ) )
245 const double correction = ( 1.0 - vBar ) / ( 2.0 * wBarEff ) * std::log( inner );
246 return std::max( 0.0, 1.0 - q1 -
correction );
252 const double logEighth = std::log( 0.125 * aU );
254 if( !std::isfinite( logEighth ) || logEighth == 0.0 )
257 const double q1 = 0.5 + 0.9 / (
M_PI * logEighth );
258 const double bj = ( aHBarTop + 1.0 ) / ( aHBarTop + 0.25 * aU - 1.0 );
260 if( bj <= 0.0 || !std::isfinite( bj ) )
263 const double acosArg = std::sqrt( bj / aHBarTop ) * ( aHBarTop - 1.0 + 0.125 * aU );
265 if( acosArg < -1.0 || acosArg > 1.0 )
268 const double correction = ( std::log( bj ) * std::acos( acosArg ) ) / ( 4.0 * logEighth );
269 return std::max( 0.0, 1.0 - q1 -
correction );
273std::pair<double, double>
275 double aEpsRSubstrate,
double aWOverH,
280 return { aEpsEffUncoated, aTanDeltaSubstrate };
285 if(
C <= 0.0 || h <= 0.0 || !std::isfinite(
C ) || !std::isfinite( h ) )
286 return { aEpsEffUncoated, aTanDeltaSubstrate };
294 if( !std::isfinite( epsMask ) || epsMask <= 1.0 )
295 return { aEpsEffUncoated, aTanDeltaSubstrate };
297 if( !std::isfinite( tanDMask ) || tanDMask < 0.0 )
298 return { aEpsEffUncoated, aTanDeltaSubstrate };
300 if( aEpsRSubstrate <= 1.0 || !std::isfinite( aEpsRSubstrate ) )
301 return { aEpsEffUncoated, aTanDeltaSubstrate };
309 return { aEpsEffUncoated, aTanDeltaSubstrate };
315 const double epsEffCoated = aEpsEffUncoated + deltaQ * ( epsMask - 1.0 );
320 const double qSub = std::clamp( ( aEpsEffUncoated - 1.0 ) / ( aEpsRSubstrate - 1.0 ), 0.0, 1.0 );
325 const double deltaQCapped = std::min( deltaQ, std::max( 0.0, 1.0 - qSub ) );
327 double tanDCoated = aTanDeltaSubstrate;
329 if( epsEffCoated > 0.0 )
331 tanDCoated = ( qSub * aEpsRSubstrate * aTanDeltaSubstrate
332 + deltaQCapped * epsMask * tanDMask )
336 return { epsEffCoated, tanDCoated };
342 static constexpr double NR_EPSI = 2.2204460492503131e-16;
345 double k = 0.0, e = 0.0;
352 else if( std::isinf( arg ) && arg < 0 )
359 double a, b, c, fr, s, fk = 1, fe = 1, t, da = arg;
364 fk = 1 / sqrt( 1 - arg );
365 fe = sqrt( 1 - arg );
366 da = -arg / ( 1 - arg );
375 for( i = 0; i < iMax; i++ )
384 if( c / a < NR_EPSI )
396 e = M_PI_2 * ( 1 - s ) / a;
Kramers-Kronig-consistent wideband dielectric model after Djordjevic et al.
void Fit(double aEpsRSpec, double aTanDSpec, double aFSpec, double aF1=1.0e3, double aF2=1.0e12)
Fit the model from a single (epsR, tan delta) datapoint at f_spec.
double GetDispersedEpsilonR(double aF) const
Dispersed permittivity at aF. Returns raw EPSILONR when the model is inactive.
double GetDispersedTanDelta(double aF) const
Dispersed loss tangent at aF. Returns raw TAND when the model is inactive.
std::unordered_map< TRANSLINE_PARAMETERS, std::pair< double, TRANSLINE_STATUS > > & GetSynthesisResults()
Gets the output parameters following synthesis.
virtual void SetAnalysisResults()=0
Sets values in the output analysis results structure.
virtual void SetSynthesisResults()=0
Sets values in the output synthesis results structure.
double GetParameter(const TRANSLINE_PARAMETERS aParam) const
Gets the given calculation property.
void InitProperties(const std::initializer_list< TRANSLINE_PARAMETERS > &aParams)
Initialises the properties used (as inputs or outputs) by the calculation.
std::optional< DIELECTRIC_DJORDJEVIC_SARKAR > m_dsModel
Fitted Djordjevic-Sarkar model. Empty unless DIELECTRIC_MODEL_SEL selects it.
static std::pair< double, double > EllipticIntegral(double arg)
Computes the complete elliptic integral of first kind K() and the second kind E() using the arithmeti...
void SetParameter(const TRANSLINE_PARAMETERS aParam, const double aValue)
Sets the given calculation property.
void SetSynthesisResult(TRANSLINE_PARAMETERS aParam, const double aValue, const TRANSLINE_STATUS aStatus=TRANSLINE_STATUS::OK)
Sets a synthesis result.
void UpdateDielectricModel()
Refit the Djordjevic-Sarkar model from the current parameter map.
static constexpr double m_maxError
The maximum error for Z0 optimisations.
std::pair< double, double > ApplySoldermaskCorrection(double aEpsEffUncoated, double aTanDeltaSubstrate, double aEpsRSubstrate, double aWOverH, double aF) const
Apply a three-layer (substrate / soldermask / air) correction to an un-coated (eps_eff,...
double SkinDepth() const
Calculate skin depth.
static double WanHoorfarQ2(double aU, double aHBarTop)
Wan-Hoorfar 2000 eq.
virtual void Analyse()=0
Analyses the transmission line using the current parameter set.
virtual double GetSoldermaskDeltaQ(double, double) const
Incremental filling factor Delta q_mask representing the fraction of the un-coated above-trace air re...
double & GetParameterRef(const TRANSLINE_PARAMETERS aParam)
Adds a constant to the given parameter.
std::unordered_map< TRANSLINE_PARAMETERS, double > m_parameters
All input and output properties used by the calculation.
bool MinimiseZ0Error1D(TRANSLINE_PARAMETERS aOptimise, TRANSLINE_PARAMETERS aMeasure, bool aRecalculateLength=false)
minimizeZ0Error1D
void SetAnalysisResult(TRANSLINE_PARAMETERS aParam, const double aValue, const TRANSLINE_STATUS aStatus=TRANSLINE_STATUS::OK)
Sets an analysis result.
std::unordered_map< TRANSLINE_PARAMETERS, std::pair< double, TRANSLINE_STATUS > > m_synthesisStatus
Synthesis results.
static double UnitPropagationDelay(double aEpsilonEff)
Calculates the unit propagation delay (ps/cm) for the given effective permittivity.
std::unordered_map< TRANSLINE_PARAMETERS, std::pair< double, TRANSLINE_STATUS > > & GetAnalysisResults()
Gets the output parameters following analysis.
std::unordered_map< TRANSLINE_PARAMETERS, std::pair< double, TRANSLINE_STATUS > > m_analysisStatus
Analysis results.
constexpr double correction
TRANSLINE_STATUS
Parameter status values.
TRANSLINE_PARAMETERS
All possible parameters used (as inputs or outputs) by the transmission line calculations.