"""
cpw (:mod:`skrf.media.cpw`)
========================================
.. autosummary::
:toctree: generated/
CPW
"""
from scipy.constants import epsilon_0, mu_0
from scipy.special import ellipk
from numpy import pi, sqrt, log, zeros, ones
from .media import Media
from ..tlineFunctions import surface_resistivity
from ..constants import NumberLike
from typing import Union, TYPE_CHECKING
if TYPE_CHECKING:
from .. frequency import Frequency
[docs]class CPW(Media):
"""
A Coplanar Waveguide.
This class was made from the technical documentation [#]_ provided
by the qucs project [#]_ .
The variables and properties of this class are coincident with
their derivations.
Parameters
----------
frequency : :class:`~skrf.frequency.Frequency` object, optional
frequency band of the media. The default is None.
z0 : number, array-like, optional
the port impedance for media. The default is None.
Only needed if its different from the characteristic impedance
of the transmission.
w : number, or array-like, optional
width of center conductor, in m. Default is 70.
s : number, or array-like
width of gap, in m. Default is 4.
ep_r : number, or array-like, optional
relative permativity of substrate. Default is 3.
t : number, or array-like, optional
conductor thickness, in m.
Default is None (metalization thickness neglected)
rho : number, or array-like, optional
resistivity of conductor. Default is None
References
----------
.. [#] http://qucs.sourceforge.net/docs/technical.pdf
.. [#] http://www.qucs.sourceforge.net/
"""
[docs] def __init__(self, frequency: Union['Frequency', None] = None,
z0: Union[NumberLike, None] = None,
w: NumberLike = 70, s: NumberLike = 4,
ep_r: NumberLike = 3, t: Union[NumberLike, None] = None,
rho: Union[NumberLike, None] = None,
*args, **kwargs):
Media.__init__(self, frequency=frequency,z0=z0)
self.w, self.s, self.ep_r, self.t, self.rho =\
w, s, ep_r, t, rho
def __str__(self) -> str:
f=self.frequency
output = \
'Coplanar Waveguide Media. %i-%i %s. %i points'%\
(f.f_scaled[0],f.f_scaled[-1],f.unit, f.npoints) + \
'\n W= %.2em, S= %.2em'% \
(self.w,self.s)
return output
def __repr__(self) -> str:
return self.__str__()
@property
def ep_re(self) -> NumberLike:
"""
Effective permittivity of the CPW (also known as Keff).
If the thickness of the dielectric substrate is large,
the effective dielectric constant of the even mode can be approx as:
.. math::
\\varepsilon_{eff} = \\frac{\\varepsilon_r + 1}{2}
The effective permittivity can be defined as in the case of a
microstrip line, that is as the square of ratio
of the capacitance per unit length to the phase velocity.
"""
return (self.ep_r+1)/2.0
@property
def k1(self) -> NumberLike:
"""
Intermediary parameter. see qucs docs on cpw lines.
Defined as:
.. math::
k = \\frac{w}{w + 2s}
"""
return self.w/(self.w +2*self.s)
@property
def K_ratio(self) -> NumberLike:
"""
Intermediary parameter. see qucs docs on cpw lines.
K_ratio is the ratio of two elliptic integrals.
"""
k1 = self.k1
# k prime
k_p = sqrt(1 - k1**2)
if (0 <= k1 <= 1/sqrt(2)):
return pi/log(2*(1 + sqrt(k1))/(1 - sqrt(k1)))
elif (1/sqrt(2) < k1 <= 1):
return (log(2*(1 + sqrt(k_p))/(1 - sqrt(k_p)) ))/pi
@property
def alpha_conductor(self) -> NumberLike:
"""
Losses due to conductor resistivity.
Returns
-------
alpha_conductor : array-like
lossyness due to conductor losses
See Also
--------
surface_resistivity : calculates surface resistivity
"""
if self.rho is None or self.t is None:
raise(AttributeError('must provide values conductivity and conductor thickness to calculate this. see initializer help'))
t, k1, ep_re = self.t, self.k1,self.ep_re
r_s = surface_resistivity(f=self.frequency.f, rho=self.rho, \
mu_r=1)
a = self.w/2.
b = self.s+self.w/2.
K = ellipk # complete elliptical integral of first kind
K_p = lambda x: ellipk(sqrt(1-x**2)) # ellipk's compliment
return ((r_s * sqrt(ep_re)/(480*pi*K(k1)*K_p(k1)*(1-k1**2) ))*\
(1./a * (pi+log((8*pi*a*(1-k1))/(t*(1+k1)))) +\
1./b * (pi+log((8*pi*b*(1-k1))/(t*(1+k1))))))
@property
def Z0(self) -> NumberLike:
"""
Characteristic impedance
"""
return (30.*pi / sqrt(self.ep_re) * self.K_ratio)*ones(len(self.frequency.f), dtype='complex')
@property
def gamma(self) -> NumberLike:
"""
Propagation constant.
See Also
--------
alpha_conductor : calculates losses to conductors
"""
beta = 1j*2*pi*self.frequency.f*sqrt(self.ep_re*epsilon_0*mu_0)
alpha = zeros(len(beta))
if self.rho is not None and self.t is not None:
alpha = self.alpha_conductor
return beta+alpha