37std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>&
45std::unordered_map<TRANSLINE_PARAMETERS, std::pair<double, TRANSLINE_STATUS>>&
74 if( !std::isfinite( Z0_param ) )
80 if( ( !std::isfinite( var ) ) || ( var == 0 ) )
84 double Z0_dest = Z0_param;
87 double angl_l_dest = ANG_L_param;
94 double Z0_current = Z0_param;
96 double error = fabs( Z0_dest - Z0_current );
101 double increment = var / 100.0;
106 double Z0_result = Z0_param;
112 double slope = ( Z0_result - Z0_current ) / increment;
113 slope = ( Z0_dest - Z0_current ) / slope - increment;
122 Z0_current = Z0_param;
123 error = fabs( Z0_dest - Z0_current );
125 if( iteration > 250 )
130 if( aRecalculateLength )
133 ANG_L_param = angl_l_dest;
135 * ANG_L_param / 2.0 /
M_PI );
140 ANG_L_param = angl_l_dest;
142 * ANG_L_param / 2.0 /
M_PI );
160 return std::sqrt( aEpsilonEff ) * ( 1.0e10 / 2.99e8 );
179 if( !std::isfinite( fSpec ) || fSpec <= 0.0 )
188 ds.
Fit( epsRSpec, tanDSpec, fSpec );
191 catch(
const std::invalid_argument& )
219 const double wBarEff = aU + ( 2.0 /
M_PI ) * std::log( 17.08 * ( 0.5 * aU + 0.92 ) );
223 const double denom = wBarEff *
M_PI - 4.0;
225 if( denom <= 0.0 || !std::isfinite( denom ) )
228 const double vBar = ( 2.0 /
M_PI ) * std::atan( ( 2.0 *
M_PI / denom ) * ( aHBarTop - 1.0 ) );
229 const double halfPi = 0.5 *
M_PI * vBar;
236 const double q1 = 1.0 - std::log( wBarEff *
M_PI - 1.0 ) / ( 2.0 * wBarEff );
237 const double inner = 2.0 * wBarEff * std::cos( halfPi ) / ( 2.0 * aHBarTop - 1.0 + vBar )
238 + std::sin( halfPi );
240 if( inner <= 0.0 || !std::isfinite( inner ) )
243 const double correction = ( 1.0 - vBar ) / ( 2.0 * wBarEff ) * std::log( inner );
244 return std::max( 0.0, 1.0 - q1 -
correction );
250 const double logEighth = std::log( 0.125 * aU );
252 if( !std::isfinite( logEighth ) || logEighth == 0.0 )
255 const double q1 = 0.5 + 0.9 / (
M_PI * logEighth );
256 const double bj = ( aHBarTop + 1.0 ) / ( aHBarTop + 0.25 * aU - 1.0 );
258 if( bj <= 0.0 || !std::isfinite( bj ) )
261 const double acosArg = std::sqrt( bj / aHBarTop ) * ( aHBarTop - 1.0 + 0.125 * aU );
263 if( acosArg < -1.0 || acosArg > 1.0 )
266 const double correction = ( std::log( bj ) * std::acos( acosArg ) ) / ( 4.0 * logEighth );
267 return std::max( 0.0, 1.0 - q1 -
correction );
271std::pair<double, double>
273 double aEpsRSubstrate,
double aWOverH,
278 return { aEpsEffUncoated, aTanDeltaSubstrate };
283 if(
C <= 0.0 || h <= 0.0 || !std::isfinite(
C ) || !std::isfinite( h ) )
284 return { aEpsEffUncoated, aTanDeltaSubstrate };
292 if( !std::isfinite( epsMask ) || epsMask <= 1.0 )
293 return { aEpsEffUncoated, aTanDeltaSubstrate };
295 if( !std::isfinite( tanDMask ) || tanDMask < 0.0 )
296 return { aEpsEffUncoated, aTanDeltaSubstrate };
298 if( aEpsRSubstrate <= 1.0 || !std::isfinite( aEpsRSubstrate ) )
299 return { aEpsEffUncoated, aTanDeltaSubstrate };
307 return { aEpsEffUncoated, aTanDeltaSubstrate };
313 const double epsEffCoated = aEpsEffUncoated + deltaQ * ( epsMask - 1.0 );
318 const double qSub = std::clamp( ( aEpsEffUncoated - 1.0 ) / ( aEpsRSubstrate - 1.0 ), 0.0, 1.0 );
323 const double deltaQCapped = std::min( deltaQ, std::max( 0.0, 1.0 - qSub ) );
325 double tanDCoated = aTanDeltaSubstrate;
327 if( epsEffCoated > 0.0 )
329 tanDCoated = ( qSub * aEpsRSubstrate * aTanDeltaSubstrate
330 + deltaQCapped * epsMask * tanDMask )
334 return { epsEffCoated, tanDCoated };
340 static constexpr double NR_EPSI = 2.2204460492503131e-16;
343 double k = 0.0, e = 0.0;
350 else if( std::isinf( arg ) && arg < 0 )
357 double a, b, c, fr, s, fk = 1, fe = 1, t, da = arg;
362 fk = 1 / sqrt( 1 - arg );
363 fe = sqrt( 1 - arg );
364 da = -arg / ( 1 - arg );
373 for( i = 0; i < iMax; i++ )
382 if( c / a < NR_EPSI )
394 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.