ism-transceiver-915mhz/sim/test_series.py

98 lines
3.1 KiB
Python

import numpy as np
import skrf
from skrf.media import DistributedCircuit
import skrf.frequency as freq
import skrf.network as net
import skrf.util
from scipy.interpolate import interp1d
def series(a, b):
try:
# one side should hopefully be invertible
newz = a.z + b.z
except e:
raise e
# not using this part for now
## there's a formula for calculating the inverse of a sum:
## (A + B)^-1 = A^-1 - 1/(1+g)*A^-1B^-1
## where g = trace(BA^-1)
## z = y^-1
## y = (za + zb)^-1 = za^-1 - 1/(1+g)*za^-1*zb*za^-1 =
## ya - 1/(1+g)*ya*zb*ya, g = trace(zb*ya)
## so we never need to calculate za
#g = np.trace(np.matmul(a.y, b.z), axis1=1, axis2=2)
#newy = a.y - 1./(1./+g)*np.matmul(np.matmul(a.y, b.z), a.y)
#newz = np.linalg.inv(newy)
ret = net.Network.from_z(newz, frequency=a.frequency)
noiseless = not a.noisy and not b.noisy
if noiseless:
return ret
if a.noisy:
an = a.n
af = a.f_noise
else:
an = np.zeros(b.n.shape)
af = b.f_noise
if b.noisy:
bn = b.n
bf = b.f_noise
else:
bn = np.zeros(a.n.shape)
bf = a.f_noise
if bf != af:
# TODO interpolate noise values for b into a frequency ranges
# bn = ???
raise NotImplementedError
a_real = interp1d(a.frequency.f, a.a.real,
axis=0, kind=net.Network.noise_interp_kind)
a_imag = interp1d(a.frequency.f, a.a.imag,
axis=0, kind=net.Network.noise_interp_kind)
a_abcd = a_real(af.f) + 1.j * a_imag(af.f)
b_real = interp1d(b.frequency.f, b.a.real,
axis=0, kind=net.Network.noise_interp_kind)
b_imag = interp1d(b.frequency.f, b.a.imag,
axis=0, kind=net.Network.noise_interp_kind)
b_abcd = b_real(bf.f) + 1.j * b_imag(bf.f)
# calculate noise
# based on https://onlinelibrary.wiley.com/doi/pdf/10.1002/9781119073093.app3
a1 = 1
b1 = (b_abcd[:,0,0] - a_abcd[:,0,0])/(a_abcd[:,1,0] + b_abcd[:,1,0])
c1 = 0
d1 = b_abcd[:,1,0]/(a_abcd[:,1,0] + b_abcd[:,1,0])
a2 = 1
b2 = (a_abcd[:,0,0] - b_abcd[:,0,0])/(a_abcd[:,1,0] + b_abcd[:,1,0])
c2 = 0
d2 = a_abcd[:,1,0]/(a_abcd[:,1,0] + b_abcd[:,1,0])
ee = (a1*np.conj(a1)*an[:,0,0] + b1*np.conj(b1)*bn[:,1,1] +
a2*np.conj(a2)*bn[:,1,1] + b2*np.conj(b2)*bn[:,1,1] +
a1*np.conj(b1)*an[:,0,1] + b1*np.conj(a1)*an[:,1,0] +
a2*np.conj(b2)*bn[:,0,1] + b2*np.conj(a2)*bn[:,1,0])
ii = (c1*np.conj(c1)*an[:,0,0] + d1*np.conj(d1)*an[:,1,1] +
c2*np.conj(c2)*bn[:,0,0] + d2*np.conj(d2)*bn[:,1,1] +
c1*np.conj(d1)*an[:,0,1] + d1*np.conj(c1)*an[:,1,0] +
c2*np.conj(d2)*bn[:,0,1] + d2*np.conj(c2)*bn[:,1,0])
ei = (a1*np.conj(c1)*an[:,0,0] + b1*np.conj(d1)*an[:,1,1] +
a2*np.conj(c2)*bn[:,0,0] + b2*np.conj(d2)*bn[:,1,1] +
a1*np.conj(d1)*an[:,0,1] + b1*np.conj(c1)*an[:,1,0] +
a2*np.conj(d2)*bn[:,0,1] + b2*np.conj(c2)*bn[:,1,0])
ie = np.conj(ei)
ret.noise = np.moveaxis(np.array([[ee, ei], [ie, ii]]), 2, 0)
ret.noise_freq = af
return ret
f = freq.Frequency(0.4, 2, 1001)
tem = DistributedCircuit(f, z0=50)
bjt = net.Network('BFU520_Spar_NF_400MHz-2GHz/BFU520_05V0_005mA_NF_SP.s2p').interpolate(f)
inductor = tem.shunt_inductor(1e-9)
print(series(bjt, inductor).n)