"""
coaxial (:mod:`skrf.media.coaxial`)
============================================================
A coaxial transmission line defined from its electrical or geometrical/physical properties
.. autosummary::
:toctree: generated/
Coaxial
"""
from __future__ import annotations
from typing import TYPE_CHECKING
from numpy import array, exp, expm1, imag, log, size, sqrt
from scipy.constants import c, epsilon_0, mu_0, pi
from ..constants import INF, NumberLike
from ..mathFunctions import db_2_np, db_per_100feet_2_db_per_100meter, feet_2_meter
from ..tlineFunctions import skin_depth, surface_resistivity
from .distributedCircuit import DistributedCircuit
from .media import DefinedGammaZ0, Media
if TYPE_CHECKING:
from ..frequency import Frequency
[docs]
class Coaxial(DistributedCircuit, Media):
"""
A coaxial transmission line defined in terms of its inner/outer
diameters and permittivity.
Parameters
----------
frequency : :class:`~skrf.frequency.Frequency` object
Frequency band.
z0_port : number, array-like, or None
`z0_port` is the port impedance for networks generated by the media.
If `z0_port` is not None, the networks generated by the media are
renormalized (or in other words embedded) from the characteristic
impedance z0 of the media to `z0_port`.
Else if `z0_port` is None, the networks port impedances will be the raw
characteristic impedance z0 of the media.
(Default is None)
z0_override : number, array-like, or None
`z0_override` override the characteristic impedance for the media.
If `z0_override` is not None, the networks generated by the media have
their characteristic impedance `z0` overrided by `z0_override`.
(Default is None)
z0 : number, array-like, or None
deprecated parameter, alias to `z0_override` if `z0_override` is None.
Emmit a deprecation warning.
Dint : number, or array-like
inner conductor diameter, in m
Dout : number, or array-like
outer conductor diameter, in m
epsilon_r : number, or array-like, optional
relative permittivity of the dielectric medium.
Default is 1.
tan_delta : number, or array-like, optional
loss tangent of the dielectric medium.
Default is 0.
sigma : number, or array-like, optional.
conductors electrical conductivity, in S/m.
Default is infinity (non lossy metal).
TODO : different conductivity in case of different conductor kind
Note
----
Dint, Dout, epsilon_r, tan_delta, sigma can all be vectors as long
as they are the same length
References
----------
.. [#] Pozar, D.M.; , "Microwave Engineering", Wiley India Pvt. Limited, 1 sept. 2009
"""
## CONSTRUCTOR
[docs]
def __init__(self, frequency: Frequency | None = None,
z0_port: NumberLike | None = None,
z0_override: NumberLike | None = None,
z0: NumberLike | None = None,
Dint: NumberLike = .81e-3, Dout: NumberLike = 5e-3,
epsilon_r: NumberLike = 1, tan_delta: NumberLike = 0,
sigma: NumberLike = INF,
*args, **kwargs):
Media.__init__(self, frequency = frequency,
z0_port = z0_port, z0_override = z0_override, z0 = z0)
self.Dint, self.Dout = Dint,Dout
self.epsilon_r, self.tan_delta, self.sigma = epsilon_r, tan_delta, sigma
self.epsilon_prime = epsilon_0*self.epsilon_r
self.epsilon_second = epsilon_0*self.epsilon_r*self.tan_delta
[docs]
@classmethod
def from_attenuation_VF(cls, frequency: Frequency | None = None,
z0_port: NumberLike | None = None, z0: float = 50,
att=0, unit='dB/m', VF=1) -> Media:
"""
Init from electrical properties of the line: attenuation and velocity factor.
Attenuation can be expressed in dB/m, dB/100m, dB/ft, dB/100ft, Neper/m or Neper/ft.
Default unit is dB/m. A different unit is set by the `unit` parameter.
Parameters
----------
frequency : :class:`~skrf.frequency.Frequency` object
z0_port : number, array-like, or None
`z0_port` is the port impedance for networks generated by the media.
If `z0_port` is not None, the networks generated by the media are
renormalized (or in other words embedded) from the characteristic
impedance z0 of the media to `z0_port`.
Else if `z0_port` is None, the networks port impedances will be the raw
characteristic impedance z0 of the media.
(Default is None)
z0 : number
desired characteristic impedance
att : number, or array-like. optional
Attenuation of the coaxial line. The default is 0.
If passed as an array, should be of same size than the frequency.
unit : string, optional
Unit of the attenuation. Can be: 'dB/m', dB/100m'', 'dB/ft', 'dB/100ft',
'Neper/m' or 'Neper/ft' (or 'Np/m', 'Np/ft'). The default is 'dB/m'.
VF : number, or array-like. optional
Velocity Factor VF [VF]_. The default is 1.
If passed as an array, should be of same size than the frequency.
Returns
-------
media : :class:`~skrf.media.media.Media`
References
----------
.. [VF] : https://www.microwaves101.com/encyclopedias/light-phase-and-group-velocities
"""
# test size of parameters
if size(array(att, dtype="object")) not in (1, size(frequency.f)):
raise ValueError('Attenuation should be scalar or of same size that the frequency.')
# create gamma
if unit in ('dB/m', 'db/m'):
alpha = db_2_np(att)
elif unit in ('dB/100m', 'db/100m'):
alpha = db_2_np(att/100)
elif unit in ('dB/ft', 'dB/feet'):
alpha = db_2_np(att/feet_2_meter())
elif unit in ('dB/100ft', 'dB/100feet'):
alpha = db_2_np(db_per_100feet_2_db_per_100meter(att)/100)
elif unit in ('Np/m', 'np/m', 'n/m'):
alpha = att
elif unit in ('Neper/feet', 'Neper/ft',
'Np/feet', 'Np/ft',
'np/feet', 'np/ft',
'N/feet', 'N/ft'):
alpha = att/feet_2_meter()
else:
raise ValueError('Incorrect attenuation unit. Please see documentation. ', unit)
beta = 2 * pi * frequency.f / c / VF
gamma = alpha + 1j*beta
# return media object from z0 and gamma
return DefinedGammaZ0(frequency=frequency, gamma=gamma,
z0_port=z0_port, z0=z0)
[docs]
@classmethod
def from_Z0_Dout(cls, frequency: Frequency | None = None,
z0_port: NumberLike | None = None, z0: float = 50,
epsilon_r: NumberLike = 1, Dout: NumberLike = 5e-3,
**kw) -> Media:
"""
Init from characteristic impedance and outer diameter.
Parameters
----------
frequency : :class:`~skrf.frequency.Frequency` object
z0_port : number, array-like, or None
`z0_port` is the port impedance for networks generated by the media.
If `z0_port` is not None, the networks generated by the media are
renormalized (or in other words embedded) from the characteristic
impedance z0 of the media to `z0_port`.
Else if `z0_port` is None, the networks port impedances will be the raw
characteristic impedance z0 of the media.
(Default is None)
z0 : number
desired characteristic impedance
Dout : number, or array-like
outer conductor diameter, in m
epsilon_r=1 : number, or array-like
relative permittivity of the dielectric medium
**kw :
passed to __init__
Returns
-------
media : :class:`~skrf.media.media.Media`
"""
ep= epsilon_0*epsilon_r
if imag(z0) !=0:
raise NotImplementedError()
b = Dout/2.
b_over_a = exp(2*pi*z0*sqrt(ep/mu_0))
a = b/b_over_a
Dint = 2*a
return cls(frequency=frequency, z0_port = z0_port, Dint=Dint, Dout=Dout,
epsilon_r=epsilon_r, **kw)
@property
def Rs(self) -> NumberLike:
"""
Surface resistivity in Ohm/area.
Returns
-------
Rs : number or array
surface resistivity
"""
f = self.frequency.f
rho = 1./self.sigma
mu_r =1
return surface_resistivity(f=f,rho=rho, mu_r=mu_r)
@property
def a(self) -> NumberLike:
"""
Inner radius of the coaxial line
Returns
-------
a : float
Inner radius
"""
return self.Dint/2.
@property
def b(self) -> NumberLike:
"""
Outer radius of the coaxial line
Returns
-------
b : float
Outer radius
"""
return self.Dout/2.
# derivation of distributed circuit parameters
@property
def R(self) -> NumberLike:
"""
Distributed resistance R, in Ohm/m.
See [#]_ for more information.
Returns
-------
R : number, or array-like
distributed resistance, in Ohm/m
References
-------
.. [#] https://www.microwaves101.com/encyclopedias/a-more-exact-coax-attenuation-solution
"""
rho = 1/self.sigma
delta = skin_depth(f=self.frequency.f, rho=rho, mu_r=1)
# Avoid infinites at DC
delta[delta > 1e6] = 1e6
Rin = rho / (2*pi*delta*self.a + 2*pi*delta**2*expm1(-self.a/delta))
# Outer shield is assumed to be much thicker than skin depth
Rout = rho / (2*pi*delta*self.b)
return Rin + Rout
@property
def L(self) -> NumberLike:
"""
Distributed inductance L, in H/m
Returns
-------
L : number, or array-like
distributed inductance, in H/m
"""
return mu_0/(2.*pi)*log(self.b/self.a)
@property
def C(self) -> NumberLike:
"""
Distributed capacitance C, in F/m
Returns
-------
C : number, or array-like
distributed capacitance, in F/m
"""
return 2.*pi*self.epsilon_prime/log(self.b/self.a)
@property
def G(self) -> NumberLike:
"""
Distributed conductance G, in S/m
Returns
-------
G : number, or array-like
distributed conductance, in S/m
"""
f = self.frequency.f
return f*self.epsilon_second/log(self.b/self.a)
def __str__(self):
f=self.frequency
f_s = f'Coaxial Media. {f.f_scaled[0]}-{f.f_scaled[-1]}{f.unit}, '\
f'{f.npoints} points.'
z0 = self.z0
z0_s = f'z0 = ({z0[0].real:.1f}, {z0[0].imag:.1f}j)-'\
f'({z0[-1].real:.1f}, {z0[-1].imag:.1f}j) Ohm'
if self.z0_port is not None:
z0_port = self.z0_port
z0_port_s = \
f'z0_port = ({z0_port[0].real:.1f}, {z0_port[0].imag:.1f}j)-'\
f'({z0_port[-1].real:.1f}, {z0_port[-1].imag:.1f}j) Ohm\n'
else:
z0_port_s = 'z0_port is not defined.'
try:
output = \
f'Coaxial Media. {f_s}\n'\
f'Dint = {self.Dint * 1e3:.2f} mm,'\
f' Dout = {self.Dout * 1e3:.2f} mm\n' \
f'{z0_s}\n{z0_port_s}'
except(TypeError):
output = \
f'Coaxial Media. {f_s}\n'\
f'Dint = {self.Dint[0] * 1e3:.2f} mm,'\
f' Dout = {self.Dout[0] * 1e3:.2f} mm\n' \
f'{z0_s}\n{z0_port_s}'
return output