Source code for skrf.tlineFunctions

# -*- coding: utf-8 -*-
"""
.. module:: skrf.tlineFunctions
===============================================
tlineFunctions (:mod:`skrf.tlineFunctions`)
===============================================

This module provides functions related to transmission line theory.

Impedance and Reflection Coefficient
--------------------------------------
These functions relate basic transmission line quantities such as
characteristic impedance, input impedance, reflection coefficient, etc.
Each function has two names. One is a long-winded but readable name and
the other is a short-hand variable-like names. Below is a table relating
these two names with each other as well as common mathematical symbols.

====================  ======================  ================================
Symbol                Variable Name           Long Name
====================  ======================  ================================
:math:`Z_l`           z_l                     load_impedance
:math:`Z_{in}`        z_in                    input_impedance
:math:`\\Gamma_0`      Gamma_0                 reflection_coefficient
:math:`\\Gamma_{in}`   Gamma_in                reflection_coefficient_at_theta
:math:`\\theta`        theta                   electrical_length
====================  ======================  ================================

There may be a bit of confusion about the difference between the load
impedance the input impedance. This is because the load impedance **is**
the input impedance at the load. An illustration may provide some
useful reference.

Below is a (bad) illustration of a section of uniform transmission line
of characteristic impedance :math:`Z_0`, and electrical length
:math:`\\theta`. The line is terminated on the right with some
load impedance, :math:`Z_l`. The input impedance :math:`Z_{in}` and
input reflection coefficient :math:`\\Gamma_{in}` are
looking in towards the load from the distance :math:`\\theta` from the
load.

.. math::
        Z_0, \\theta

        \\text{o===============o=}[Z_l]

        \\to\\qquad\\qquad\\qquad\\quad\\qquad \\qquad \\to \\qquad \\quad

        Z_{in},\\Gamma_{in}\\qquad\\qquad\\qquad\\qquad\\quad Z_l,\\Gamma_0

So, to clarify the confusion,

.. math::
        Z_{in}= Z_{l},\\qquad\\qquad
        \\Gamma_{in}=\\Gamma_l \\text{ at }  \\theta=0


Short names
+++++++++++++
.. autosummary::
        :toctree: generated/

        theta

        zl_2_Gamma0
        zl_2_zin
        zl_2_Gamma_in
        zl_2_swr
        zl_2_total_loss

        Gamma0_2_zl
        Gamma0_2_Gamma_in
        Gamma0_2_zin
        Gamma0_2_swr

Long-names
++++++++++++++
.. autosummary::
        :toctree: generated/

        electrical_length

        distance_2_electrical_length
        electrical_length_2_distance

        reflection_coefficient_at_theta
        reflection_coefficient_2_input_impedance
        reflection_coefficient_2_input_impedance_at_theta
        reflection_coefficient_2_propagation_constant

        input_impedance_at_theta
        load_impedance_2_reflection_coefficient
        load_impedance_2_reflection_coefficient_at_theta

        voltage_current_propagation



Distributed Circuit and Wave Quantities
----------------------------------------
.. autosummary::
        :toctree: generated/

        distributed_circuit_2_propagation_impedance
        propagation_impedance_2_distributed_circuit

Transmission Line Physics
---------------------------------
.. autosummary::
        :toctree: generated/

        skin_depth
        surface_resistivity
"""

from . constants import NumberLike, INF, ONE
import numpy as npy
from numpy import pi, sqrt, exp, array, imag, real

from scipy.constants import mu_0
from . import mathFunctions as mf


[docs]def skin_depth(f: NumberLike, rho: float, mu_r: float): """ Skin depth for a material. The skin depth is calculated as: .. math:: \delta = \\sqrt{\\frac{ \\rho }{ \\pi f \\mu_r \\mu_0 }} See www.microwaves101.com [#]_ or wikipedia [#]_ for more info. Parameters ---------- f : number or array-like frequency, in Hz rho : number of array-like bulk resistivity of material, in ohm*m mu_r : number or array-like relative permeability of material Returns ------- skin depth : number or array-like the skin depth, in meter References ---------- .. [#] https://www.microwaves101.com/encyclopedias/skin-depth .. [#] http://en.wikipedia.org/wiki/Skin_effect See Also -------- surface_resistivity """ return sqrt(rho/(pi*f*mu_r*mu_0))
[docs]def surface_resistivity(f: NumberLike, rho: float, mu_r: float): """ Surface resistivity. The surface resistivity is calculated as: .. math:: \\frac{ \\rho }{ \delta } where :math:`\delta` is the skin depth from :func:`skin_depth`. See www.microwaves101.com [#]_ or wikipedia [#]_ for more info. Parameters ---------- f : number or array-like frequency, in Hz rho : number or array-like bulk resistivity of material, in ohm*m mu_r : number or array-like relative permeability of material Returns ------- surface resistivity : number of array-like Surface resistivity in ohms/square References ---------- .. [#] https://www.microwaves101.com/encyclopedias/sheet-resistance .. [#] https://en.wikipedia.org/wiki/Sheet_resistance See Also -------- skin_depth """ return rho/skin_depth(rho=rho, f=f, mu_r=mu_r)
[docs]def distributed_circuit_2_propagation_impedance(distributed_admittance: NumberLike, distributed_impedance: NumberLike): """ Convert distributed circuit values to wave quantities. This converts complex distributed impedance and admittance to propagation constant and characteristic impedance. The relation is .. math:: Z_0 = \\sqrt{ \\frac{Z^{'}}{Y^{'}}} \\quad\\quad \\gamma = \\sqrt{ Z^{'} Y^{'}} Parameters ---------- distributed_admittance : number, array-like distributed admittance distributed_impedance : number, array-like distributed impedance Returns ------- propagation_constant : number, array-like distributed impedance characteristic_impedance : number, array-like distributed impedance See Also -------- propagation_impedance_2_distributed_circuit : opposite conversion """ propagation_constant = \ sqrt(distributed_impedance*distributed_admittance) characteristic_impedance = \ sqrt(distributed_impedance/distributed_admittance) return (propagation_constant, characteristic_impedance)
[docs]def propagation_impedance_2_distributed_circuit(propagation_constant: NumberLike, characteristic_impedance: NumberLike): """ Convert wave quantities to distributed circuit values. Convert complex propagation constant and characteristic impedance to distributed impedance and admittance. The relation is, .. math:: Z^{'} = \\gamma Z_0 \\quad\\quad Y^{'} = \\frac{\\gamma}{Z_0} Parameters ---------- propagation_constant : number, array-like distributed impedance characteristic_impedance : number, array-like distributed impedance Returns ------- distributed_admittance : number, array-like distributed admittance distributed_impedance : number, array-like distributed impedance See Also -------- distributed_circuit_2_propagation_impedance : opposite conversion """ distributed_admittance = propagation_constant/characteristic_impedance distributed_impedance = propagation_constant*characteristic_impedance return (distributed_admittance, distributed_impedance)
[docs]def electrical_length(gamma: NumberLike, f: NumberLike, d: NumberLike, deg: bool = False): """ Electrical length of a section of transmission line. .. math:: \\theta = \\gamma(f) \\cdot d Parameters ---------- gamma : number, array-like or function propagation constant. See Notes. If passed as a function, takes frequency in Hz as a sole argument. f : number or array-like frequency at which to calculate d : number or array-like length of line, in meters deg : Boolean return in degrees or not. Returns ------- theta : number or array-like electrical length in radians or degrees, depending on value of deg. See Also -------- electrical_length_2_distance : opposite conversion Note ---- The convention has been chosen that forward propagation is represented by the positive imaginary part of the value returned by the gamma function. """ # if gamma is not a function, create a dummy function which return gamma if not callable(gamma): _gamma = gamma def gamma(f0): return _gamma # typecast to a 1D array f = array(f, dtype=float).reshape(-1) d = array(d, dtype=float).reshape(-1) if deg == False: return gamma(f)*d elif deg == True: return mf.radian_2_degree(gamma(f)*d )
[docs]def electrical_length_2_distance(theta: NumberLike, gamma: NumberLike, f0: NumberLike, deg: bool = True): """ Convert electrical length to a physical distance. .. math:: d = \\frac{\\theta}{\\gamma(f_0)} Parameters ---------- theta : number or array-like electrical length. units depend on `deg` option gamma : number, array-like or function propagation constant. See Notes. If passed as a function, takes frequency in Hz as a sole argument. f0 : number or array-like frequency at which to calculate gamma deg : Boolean return in degrees or not. Returns ------- d : number or array-like (real) physical distance in m Note ---- The convention has been chosen that forward propagation is represented by the positive imaginary part of the value returned by the gamma function. See Also -------- distance_2_electrical_length: opposite conversion """ # if gamma is not a function, create a dummy function which return gamma if not callable(gamma): _gamma = gamma def gamma(f0): return _gamma if deg: theta = mf.degree_2_radian(theta) return real(theta / gamma(f0))
[docs]def load_impedance_2_reflection_coefficient(z0: NumberLike, zl: NumberLike): """ Reflection coefficient from a load impedance. Return the reflection coefficient for a given load impedance, and characteristic impedance. For a transmission line of characteristic impedance :math:`Z_0` terminated with load impedance :math:`Z_l`, the complex reflection coefficient is given by, .. math:: \\Gamma = \\frac {Z_l - Z_0}{Z_l + Z_0} Parameters ---------- z0 : number or array-like characteristic impedance zl : number or array-like load impedance (aka input impedance) Returns ------- gamma : number or array-like reflection coefficient See Also -------- Gamma0_2_zl : reflection coefficient to load impedance Note ---- Inputs are typecasted to 1D complex array. """ # typecast to a complex 1D array. this makes everything easier z0 = array(z0, dtype=complex).reshape(-1) zl = array(zl, dtype=complex).reshape(-1) # handle singularity by numerically representing inf as big number zl[(zl == npy.inf)] = INF return ((zl - z0)/(zl + z0))
[docs]def reflection_coefficient_2_input_impedance(z0: NumberLike, Gamma: NumberLike): """ Input impedance from a load reflection coefficient. Calculate the input impedance given a reflection coefficient and characteristic impedance. .. math:: Z_0 \\left(\\frac {1 + \\Gamma}{1-\\Gamma} \\right) Parameters ---------- Gamma : number or array-like complex reflection coefficient z0 : number or array-like characteristic impedance Returns ------- zin : number or array-like input impedance """ # typecast to a complex 1D array. this makes everything easier Gamma = array(Gamma, dtype=complex).reshape(-1) z0 = array(z0, dtype=complex).reshape(-1) # handle singularity by numerically representing inf as close to 1 Gamma[(Gamma == 1)] = ONE return z0*((1.0 + Gamma)/(1.0 - Gamma))
[docs]def reflection_coefficient_at_theta(Gamma0: NumberLike, theta: NumberLike): """ Reflection coefficient at a given electrical length. .. math:: \\Gamma_{in} = \\Gamma_0 e^{-2 \\theta} Parameters ---------- Gamma0 : number or array-like reflection coefficient at theta=0 theta : number or array-like electrical length (may be complex) Returns ------- Gamma_in : number or array-like input reflection coefficient """ Gamma0 = array(Gamma0, dtype=complex).reshape(-1) theta = array(theta, dtype=complex).reshape(-1) return Gamma0 * exp(-2*theta)
[docs]def input_impedance_at_theta(z0: NumberLike, zl: NumberLike, theta: NumberLike): """ Input impedance from load impedance at a given electrical length. Input impedance of load impedance zl at a given electrical length, given characteristic impedance z0. Parameters ---------- z0 : number or array-like characteristic impedance zl : number or array-like load impedance theta : number or array-like electrical length of the line (may be complex) Returns ------- zin : number or array-like input impedance at theta """ Gamma0 = load_impedance_2_reflection_coefficient(z0=z0, zl=zl) Gamma_in = reflection_coefficient_at_theta(Gamma0=Gamma0, theta=theta) return reflection_coefficient_2_input_impedance(z0=z0, Gamma=Gamma_in)
[docs]def load_impedance_2_reflection_coefficient_at_theta(z0: NumberLike, zl: NumberLike, theta: NumberLike): """ Reflection coefficient of load at a given electrical length. Reflection coefficient of load impedance zl at a given electrical length, given characteristic impedance z0. Parameters ---------- z0 : number or array-like characteristic impedance. zl : number or array-like load impedance theta : number or array-like electrical length of the line (may be complex). Returns ------- Gamma_in : number or array-like input reflection coefficient at theta """ Gamma0 = load_impedance_2_reflection_coefficient(z0=z0, zl=zl) Gamma_in = reflection_coefficient_at_theta(Gamma0=Gamma0, theta=theta) return Gamma_in
[docs]def reflection_coefficient_2_input_impedance_at_theta(z0: NumberLike, Gamma0: NumberLike, theta: NumberLike): """ Input impedance from load reflection coefficient at a given electrical length. Calculate the input impedance at electrical length theta, given a reflection coefficient and characteristic impedance of the medium. Parameters ---------- z0 : number or array-like characteristic impedance. Gamma: number or array-like reflection coefficient theta: number or array-like electrical length of the line, (may be complex) Returns ------- zin: number or array-like input impedance at theta """ Gamma_in = reflection_coefficient_at_theta(Gamma0=Gamma0, theta=theta) zin = reflection_coefficient_2_input_impedance(z0=z0, Gamma=Gamma_in) return zin
[docs]def reflection_coefficient_2_propagation_constant(Gamma_in: NumberLike, Gamma_l: NumberLike, d: NumberLike): """ Propagation constant from line input and load reflection coefficients. Calculate the propagation constant of a line of length d, given the reflection coefficient and characteristic impedance of the medium. .. math:: \\Gamma_{in} = \\Gamma_l e^{-2 j \\gamma \\cdot d} \\to \\gamma = -\\frac{1}{2 d} \\ln \\left ( \\frac{ \\Gamma_{in} }{ \\Gamma_l } \\right ) Parameters ---------- Gamma_in : number or array-like input reflection coefficient Gamma_l : number or array-like load reflection coefficient d : number or array-like length of line, in meters Returns ------- gamma : number (complex) or array-like propagation constant (see notes) Note ---- The convention has been chosen that forward propagation is represented by the positive imaginary part of gamma. """ gamma = -1/(2*d) * npy.log(Gamma_in/Gamma_l) # the imaginary part of gamma (=beta) cannot be negative with the given # definition of gamma. Thus one should take the first modulo positive value gamma.imag = gamma.imag % (pi/d) return gamma
[docs]def Gamma0_2_swr(Gamma0: NumberLike): """ Standing Wave Ratio (SWR) for a given reflection coefficient. Standing Wave Ratio value is defined by: .. math:: VSWR = \\frac{1 + |\\Gamma_0|}{1 - |\\Gamma_0|} Parameters ---------- Gamma0 : number or array-like Reflection coefficient Returns ------- swr : number or array-like Standing Wave Ratio. """ return (1 + npy.abs(Gamma0)) / (1 - npy.abs(Gamma0))
[docs]def zl_2_swr(z0: NumberLike, zl: NumberLike): """ Standing Wave Ratio (SWR) for a given load impedance. Standing Wave Ratio value is defined by: .. math:: VSWR = \\frac{1 + |\\Gamma|}{1 - |\Gamma|} where .. math:: \\Gamma = \\frac{Z_L - Z_0}{Z_L + Z_0} Parameters ---------- z0 : number or array-like line characteristic impedance [Ohm] zl : number or array-like load impedance [Ohm] Returns ------- swr : number or array-like Standing Wave Ratio. """ Gamma0 = load_impedance_2_reflection_coefficient(z0, zl) return Gamma0_2_swr(Gamma0)
[docs]def voltage_current_propagation(v1: NumberLike, i1: NumberLike, z0: NumberLike, theta: NumberLike): """ Voltages and currents calculated on electrical length theta of a transmission line. Give voltage v2 and current i1 at theta, given voltage v1 and current i1 at theta=0 and given characteristic parameters gamma and z0. :: i1 i2 ○-->---------------------->--○ v1 gamma,z0 v2 ○----------------------------○ <------------ d -------------> theta=0 theta Uses (inverse) ABCD parameters of a transmission line. Parameters ---------- v1 : array-like (nfreqs,) total voltage at z=0 i1 : array-like (nfreqs,) total current at z=0, directed toward the transmission line z0: array-like (nfreqs,) characteristic impedance theta : number or array-like (nfreq, ntheta) electrical length of the line (may be complex). Return ------ v2 : array-like (nfreqs, ntheta) total voltage at z=d i2 : array-like (nfreqs, ndtheta total current at z=d, directed outward the transmission line """ # outer product by broadcasting of the electrical length # theta = gamma[:, npy.newaxis] * d # (nbfreqs x nbd) # ABCD parameters of a transmission line (gamma, z0) A = npy.cosh(theta) B = z0*npy.sinh(theta) C = npy.sinh(theta)/z0 D = npy.cosh(theta) # transpose and de-transpose operations are necessary # for linalg.inv to inverse square matrices ABCD = npy.array([[A, B],[C, D]]).transpose() inv_ABCD = npy.linalg.inv(ABCD).transpose() v2 = inv_ABCD[0,0] * v1 + inv_ABCD[0,1] * i1 i2 = inv_ABCD[1,0] * v1 + inv_ABCD[1,1] * i1 return v2, i2
[docs]def zl_2_total_loss(z0: NumberLike, zl: NumberLike, theta: NumberLike): ''' Total loss of a terminated transmission line (in natural unit). The total loss expressed in terms of the load impedance is [#]_ : .. math:: TL = \\frac{R_{in}}{R_L} \\left| \\cosh \\theta + \\frac{Z_L}{Z_0} \\sinh\\theta \\right|^2 Parameters ---------- z0 : number or array-like characteristic impedance. zl : number or array-like load impedance theta : number or array-like electrical length of the line (may be complex). Returns ------- total_loss: number or array-like total loss in natural unit References ---------- .. [#] Steve Stearns (K6OIK), Transmission Line Power Paradox and Its Resolution. ARRL PacificonAntenna Seminar, Santa Clara, CA, October 10-12, 2014. https://www.fars.k6ya.org/docs/K6OIK-A_Transmission_Line_Power_Paradox_and_Its_Resolution.pdf ''' Rin = npy.real(zl_2_zin(z0, zl, theta)) total_loss = Rin/npy.real(zl)*npy.abs(npy.cosh(theta) + zl/z0*npy.sinh(theta))**2 return total_loss
# short hand convenience. # admittedly these follow no logical naming scheme, but they closely # correspond to common symbolic conventions, and are convenient theta = electrical_length distance_2_electrical_length = electrical_length zl_2_Gamma0 = load_impedance_2_reflection_coefficient Gamma0_2_zl = reflection_coefficient_2_input_impedance zl_2_zin = input_impedance_at_theta zl_2_Gamma_in = load_impedance_2_reflection_coefficient_at_theta Gamma0_2_Gamma_in = reflection_coefficient_at_theta Gamma0_2_zin = reflection_coefficient_2_input_impedance_at_theta