KiCad PCB EDA Suite
Loading...
Searching...
No Matches
dielectric_djordjevic_sarkar.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.TXT for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
25
26#include <stdexcept>
27
28
29void DIELECTRIC_DJORDJEVIC_SARKAR::Fit( double aEpsRSpec, double aTanDSpec, double aFSpec,
30 double aF1, double aF2 )
31{
32 if( aF1 <= 0.0 )
33 throw std::invalid_argument( "DIELECTRIC_DJORDJEVIC_SARKAR: f1 must be positive" );
34
35 if( aF2 <= aF1 )
36 throw std::invalid_argument( "DIELECTRIC_DJORDJEVIC_SARKAR: f2 must exceed f1" );
37
38 if( aFSpec < aF1 || aFSpec > aF2 )
39 throw std::invalid_argument( "DIELECTRIC_DJORDJEVIC_SARKAR: f_spec outside [f1, f2]" );
40
41 m_f1 = aF1;
42 m_f2 = aF2;
43
44 // Short-circuit makes TanDeltaAt return an exact 0.0 and skips the complex-log below.
45 if( aTanDSpec == 0.0 )
46 {
47 m_lossless = true;
48 m_epsInf = aEpsRSpec;
49 m_m = 0.0;
50 return;
51 }
52
53 // Djordjevic et al., IEEE Trans. EMC 43(4):662-667, Nov. 2001, eqs. (9)-(11).
54 // Equivalent form in Svensson and Dermer, IEEE Trans. Adv. Packag. 24(2):191-196, May 2001.
55 // Mirrored by scikit-rf skrf/media/definedAEpTandZ0.py (djordjevicsvensson).
56 const std::complex<double> j{ 0.0, 1.0 };
57 const std::complex<double> k = std::log( ( aF2 + j * aFSpec ) / ( aF1 + j * aFSpec ) );
58
59 m_m = -aTanDSpec * aEpsRSpec / k.imag();
60 m_epsInf = aEpsRSpec * ( 1.0 + aTanDSpec * k.real() / k.imag() );
61 m_lossless = false;
62}
63
64
65std::complex<double> DIELECTRIC_DJORDJEVIC_SARKAR::ComplexEpsilonAt( double aF ) const
66{
67 if( m_lossless )
68 return { m_epsInf, 0.0 };
69
70 // Djordjevic et al. 2001, eq. (8). Kramers-Kronig consistent by construction.
71 const std::complex<double> j{ 0.0, 1.0 };
72
73 return m_epsInf + m_m * std::log( ( m_f2 + j * aF ) / ( m_f1 + j * aF ) );
74}
75
76
78{
79 return ComplexEpsilonAt( aF ).real();
80}
81
82
84{
85 if( m_lossless )
86 return 0.0;
87
88 const std::complex<double> eps = ComplexEpsilonAt( aF );
89
90 return -eps.imag() / eps.real();
91}
std::complex< double > ComplexEpsilonAt(double aF) const
Complex relative permittivity at aF. Imag part is non-positive (loss).
double TanDeltaAt(double aF) const
Loss tangent tan delta = -Im(eps) / Re(eps) at aF.
double EpsilonRealAt(double aF) const
Real part of relative permittivity at aF.
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.