mline-scripts/microstrip.py

334 lines
12 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/python3
import numpy as np
import scipy.optimize as opt
np.seterr(under='ignore')
### STATIC approx
def eps_re(u, e_r):
'''
Calculate effective dielectric constant
using the expressions given in
E. Hammerstad and O. Jensen, "Accurate Models for
Microstrip Computer-Aided Design," 1980 IEEE MTT-S
International Microwave symposium Digest, Washington,
DC, USA, 1980, pp. 407-409.
doi: 10.1109/MWSYM.1980.1124303
e_re = eps_re(u, e_r):
u <- ratio W/h
e_r <- substrate relative dielectric constant
e_re -> effective relative dielectric constant
of microstrip line
'''
a = 1 + np.log((u**4 + (u/52)**2)/(u**4+0.432))/49 +\
np.log(1+(u/18.1)**3)/18.7
b = 0.564*( (e_r-0.9)/(e_r+3) )**(0.053)
e_re = 0.5*(e_r+1)+0.5*(e_r-1)*(1+10/u)**(-a*b)
return e_re
def getZc(u, e_r):
'''
Calculate characteristic impedance Zc
using the expressions given in
E. Hammerstad and O. Jensen, "Accurate Models for
Microstrip Computer-Aided Design," 1980 IEEE MTT-S
International Microwave symposium Digest, Washington,
DC, USA, 1980, pp. 407-409.
doi: 10.1109/MWSYM.1980.1124303
(neglected thickness of copper)
Zc = getZc(u, e_r)
u <- ratio W/h
e_r <- substrate relative dielectric constant
Zc -> characteristic impedance of microstrip line
'''
F = 6 + (2*np.pi-6)*np.exp(-(30.666/u)**0.7528)
e_re = eps_re(u, e_r)
Zc = (120*np.pi)/(2*np.pi*np.sqrt(e_re))*np.log(\
F/u + np.sqrt(1 + (2/u)**2))
return Zc
### Dispersion correction
def eps_f(W,h,e_r,f):
'''
Calculate effective dieletric constant using formulas given by:
M. Kirschning and R. H. Jansen, "Accurate Model for Effective
Dielectric Constant of Microstrip with Validity up to Millimeter-Wave
Frequencies," Electronics Letters, vol. 8, no. 6, pp. 272-273,
Mar. 1982.
R. H. Jansen and M. Kirschning, "Arguments and an accurate Model
for the Power-Current Formulation of Microstrip Characteristic
Impedance," Archiv für Elektronik und Übertragungstechnik (AEÜ),
vol. 37, pp. 108-112, 1983.
http://qucs.sourceforge.net/tech/node75.html
e_re = eps_f(W,h,e_r,f)
W <- width of microstrip (mm)
h <- height of substrate (mm)
e_r <- substrate relative dielectric cosntatn
f <- frequency (GHz)
e_re -> effective dielectric constant of microstrip line
'''
fn = f*h
u = W/h
P1 = 0.27488 + (0.6315+0.525/(1+0.0157*fn)**20)*u - 0.065683*np.exp(\
-8.7513*u)
P2 = 0.33622*(1-np.exp(-0.03442*e_r))
P3 = 0.0363*np.exp(-4.6*u)*(1-np.exp(-(fn/38.7)**4.97))
P4 = 1+2.751*(1-np.exp(-(e_r/15.916)**8))
Pf = P1*P2*((0.1844+P3*P4)*fn)**1.5763
eps0 = eps_re(u,e_r)
return e_r - (e_r - eps0)/(1+Pf)
def getZcf(W,h,e_r,f,R=False):
'''
Calculate characteristic impedance using formulas given by:
M. Kirschning and R. H. Jansen, "Accurate Model for Effective
Dielectric Constant of Microstrip with Validity up to Millimeter-Wave
Frequencies," Electronics Letters, vol. 8, no. 6, pp. 272-273,
Mar. 1982.
R. H. Jansen and M. Kirschning, "Arguments and an accurate Model
for the Power-Current Formulation of Microstrip Characteristic
Impedance," Archiv für Elektronik und Übertragungstechnik (AEÜ),
vol. 37, pp. 108-112, 1983.
http://qucs.sourceforge.net/tech/node75.html
Zc = Zcf(W,h,e_r,f,R=False)
W <- width of microstrip (mm)
h <- height of substrate (mm)
e_r <- substrate relative dielectric cosntatn
f <- frequency (GHz)
R=False <- flag telling whether to return R17 or not
Zc -> characteristic impedance of microstrip line
R17 -> parameter used to calculate impedance and coupled line
return only if R=True
'''
fn = f*h
u = W/h
ef = eps_f(W,h,e_r,f)
e0 = eps_re(u,e_r)
R1 = 0.03891*e_r**1.4
R2 = 0.267*u**7
R3 = 4.766*np.exp(-3.228*u**0.641)
R4 = 0.016 + (0.0514*e_r)**4.524
R5 = (fn/28.843)**12.0
R6 = 22.20*u**1.92
R7 = 1.206-0.3144*np.exp(-R1)*(1-np.exp(-R2))
R8 = 1+1.275*(1-np.exp(-0.004625*R3*e_r**1.674)*(fn/18.365)**2.745)
R9 = 5.086*R4*R5*np.exp(-R6)*(e_r-1)**6/\
((0.3838+0.386*R4)*(1+1.2992*R5)*(1+10*(e_r-1)**6))
R10 = 0.00044*e_r**2.136+0.0184
R11 = (fn/19.47)**6/(1+0.0962*(fn/19.47)**6)
R12 = 1/(1+0.00245*u**2)
R13 = 0.9408*ef**R8-0.9603
R14 = (0.9408-R9)*e0**R8-0.9603
R15 = 0.707*R10*(fn/12.3)**1.097
R16 = 1+0.0503*e_r**2*R11*(1-np.exp(-(u/15)**6))
R17 = R7*(1-1.1241*R12*np.exp(-0.026*fn**1.15656-R15)/R16)
Z0 = getZc(u,e_r)
Zc = Z0*(R13/R14)**R17
if R:
return (Zc, R17)
else:
return Zc
def getWf(Zk,h,e_r,f):
'''
Calculate width of microstrip line when also
taking in to account dispersion.
W = getWf(Zk,h,e_r,f)
Zk <- characteristic impedance (ohms)
h <- substrate height
e_r <- substrate relative di. costant
f <- frequency (GHz)
W -> widht of microstrip line (mm)
'''
u = opt.root_scalar(lambda X: Zk-getZcf(X,h,e_r,f),x0=h,\
method='brentq', bracket=[0.01,100])
return u.root
### coupled lines
def mcl_eps(W,h,s,e_r,f):
'''
Calculate effective odd and even permittivity of parallel
coupled microstrip lines.
M. Kirschning, R. H. Jansen, and N. H. L. Koster,
"Coupled microstrip parallel-gap model for improved filter and coupler design,"
Electronics Letters, vol. 19, no. 10, pp. 377379, May 1983,
doi: 10.1049/el:19830261.
even, odd = mcl_eps(W,h,s,e_r,f):
W <- width of microstrip (mm)
h <- height of substrate (mm)
s <- spacing between lines (mm)
e_r <- substrate relative dielectric cosntatn
f <- frequency (GHz)
even -> even mode dielectric constant
odd -> odd mode dielectric constant
'''
u = W/h
g = s/h
fn = f*h
eps0 = eps_re(u,e_r)
v = u * (20+g**2)/(10+g**2)+ g*np.exp(-g)
ae = 1+np.log((v**4+(v/52)**2)/(v**4+0.432))/49+np.log(1+(v/18.1)**3)/18.7
be = 0.564*((e_r-0.9)/(e_r+3))**0.053
even0 = 0.5*(e_r+1)+0.5*(e_r-1)*(1+10/v)**(-ae*be)
ao = 0.7287*(eps0-0.5*(e_r+1))*(1-np.exp(-0.179*u))
bo = 0.747*e_r/(0.15+e_r)
co = bo - (bo-0.207)*np.exp(-0.414*u)
do = 0.593+0.694*np.exp(-0.562*u)
odd0 = (0.5*(e_r+1)+ao-eps0)*np.exp(-co*g**do)+eps0
P1 = 0.27488+(0.6315+0.525/(1+0.0157*fn)**20)*u-0.065683*np.exp(-8.7513*u)
P2 = 0.33622*(1-np.exp(-0.03442*e_r))
P3 = 0.0363*np.exp(-4.6*u)*(1-np.exp(-(fn/38.7)**4.97))
P4 = 1+2.751*(1-np.exp(-(e_r/15.916)**8))
P5 = 0.334*np.exp(-3.3*(e_r/15)**3)+0.746
P6 = P5*np.exp(-(fn/18)**0.368)
P7 = 1+4.069*P6*g**0.479*np.exp(-1.347*g**0.595-0.17*g**2.5)
Fe = P1*P2*((P3*P4+0.1844*P7)*fn)**1.5763
even = e_r - (e_r - even0)/(1+Fe)
P8 = 0.7168*(1+1.076/(1+0.0576*(e_r-1)))
P9 = P8-0.7913*(1-np.exp(-(fn/20)**1.424))*np.arctan(2.481*(e_r/8)**0.946)
P10 = 0.242*(e_r - 1)**0.55
P11 = 0.6366*(np.exp(-0.3401*fn)-1)*np.arctan(1.263*(u/3)**1.629)
P12 = P9 + (1-P9)/(1+1.183*u**1.376)
P13 = 1.695 * P10/(0.414+1.605*P10)
P14 = 0.8928+0.1072*(1-np.exp(-0.42*(fn/20)**3.215))
P15 = np.abs(1-0.8928*(1+P11)*np.exp(-P13*g**1.092)*P12/P14)
Fo = P1*P2*((P3*P4+1.844)*fn*P15)**1.5763
odd = e_r - (e_r - odd0)/(1+Fo)
return even,odd,even0,odd0
def mclZcf(W,h,s,e_r,f):
'''
Calculate odd and even characteristic impedance of parallel
coupled microstrip lines.
M. Kirschning, R. H. Jansen, and N. H. L. Koster,
"Coupled microstrip parallel-gap model for improved filter and coupler design,"
Electronics Letters, vol. 19, no. 10, pp. 377379, May 1983,
doi: 10.1049/el:19830261.
even, odd = mcl_eps(W,h,s,e_r,f):
W <- width of microstrip (mm)
h <- height of substrate (mm)
s <- spacing between lines (mm)
e_r <- substrate relative dielectric cosntatn
f <- frequency (GHz)
Ze -> even mode charachterstic impedance
Zo -> odd mode characteristic impedance
'''
u = W/h
g = s/h
fn = f*h
eps0 = eps_re(u,e_r)
epsf = eps_f(W,h,e_r,f)
even,odd,even0,odd0 = mcl_eps(W,h,s,e_r,f)
Z0 = getZc(u,e_r)
Z0f, Q0 = getZcf(W,h,e_r,f,R=True)
Q1 = 0.8695*u**0.194
Q2 = 1+0.7519*g+0.189*g**2.31
Q3 = 0.1975+(16.6 + (8.4/g)**6)**-0.387 +np.log(g**10/(1+(g/3.4)**10))/241
Q4 = 2*Q1/Q2/(np.exp(-g)*u**Q3+(2-np.exp(-g))*u**-Q3)
Ze0 = np.sqrt(eps0/even0)*Z0/(1-Z0/377*np.sqrt(eps0)*Q4)
Q5 = 1.794 + 1.14*np.log(1+0.638/(g+0.517*g**2.43))
Q6 = 0.2305+np.log(g**10/(1+(g/5.8)**10))/281.3+np.log(1+0.598*g**1.154)/5.1
Q7 = (10+190*g**2)/(1+82.3*g**3)
#print(-6.5-0.95*np.log(g)-(g/0.15)**5)
Q8 = np.exp(-6.5-0.95*np.log(g)-(g/0.15)**5)
Q9 = np.log(Q7)*(Q8+1/16.5)
Q10 = (Q2*Q4-Q5*np.exp(np.log(u)*Q6*u**-Q9))/Q2
Zo0 = np.sqrt(eps0/odd0)*Z0/(1-Z0/377*np.sqrt(eps0)*Q10)
# dispersion accounted
Q11 = 0.893*(1-0.3/(1+0.7*(e_r-1)))
Q12 = 2.121*(fn/20)**4.91*np.exp(-2.87*g)*g**0.902/(1+Q11*(fn/20)**4.91)
Q13 = 1+0.038*(e_r/8)**5.1
Q14 = 1+1.203*(e_r/15)**4/(1+(e_r/15)**4)
Q15 = 1.887*np.exp(-1.5*g**0.84)*g**Q14/(1+0.41*(fn/15)**3*u**(2/Q13)/(0.125+u**(1.625/Q13)))
Q16 = Q15 * (1+ 9/(1+0.403*(e_r-1)**2))
Q17 = 0.394*(1-np.exp(-1.47*(u/7)**0.672))*(1-np.exp(-4.25*(fn/20)**1.87))
Q18 = 0.61*(1-np.exp(-2.13*(u/8)**1.593))/(1+6.544*g**4.17)
Q19 = 0.21*g**4/(1+0.18*g**4.9)/(1+0.1*u**2)/(1+(fn/24)**3)
Q20 = Q19 * (0.09+1/(1+0.1*(e_r-1)**2.7))
Q21 = np.abs(1-42.54*g**0.133*np.exp(-0.812*g)*u**2.5/(1+0.033*u**2.5))
re = (fn/28.843)**12
qe = 0.016+(0.0514*e_r*Q21)**4.524
pe = 4.766*np.exp(-3.228*u**0.641)
de = 5.086*qe*re*np.exp(-22.2*u**1.92)*(e_r-1)**6/(0.3838+0.386*qe)/(1+1.2992*re)/(1+10*(e_r-1)**6)
Ce = 1+1.275*(1-np.exp(-0.004625*pe*e_r**1.674*(fn/18.365)**2.745))-Q12+Q16-Q17+Q18+Q20
Ze = Ze0*( (0.9408*epsf**Ce-0.9603)/( (0.9408-de)*eps0**Ce-0.9603))**Q0
Q29 = 15.16/(1+0.196*(e_r-1)**2)
Q28 = 0.149*(e_r-1)**3/(94.5+0.038*(e_r-1)**3)
Q27 = 0.4*g**0.84*(1+(2.5*(e_r-1)**1.5)/(5+(e_r-1)**1.5))
Q26 = 30 - ( 22.2*((e_r-1)/13)**13)/(1+3*((e_r-1)/13)**12) - Q29
Q25 = (0.3*fn**2)/(10+fn**2)*(1+(2.333*(e_r-1)**2)/(5+(e_r-1)**2))
Q24 = 2.506*Q28*u**0.894/(3.575+u**0.894)*((1+1.3*u)*fn/99.25)**4.29
Q23 = 1+0.005*fn*Q27/(1+0.812*(fn/15)**1.9)/(1+0.025*u**2)
Q22 = 0.925*(fn/Q26)**1.536/(1+0.3*(fn/30)**1.536)
Zo = Z0f+(Zo0*(odd/odd0)**Q22 - Z0f*Q23)/(1+Q24+(0.46*g)**2.2*Q25)
return Ze,Zo
def get_mcl(Ze, Zo, h, e_r, f):
'''
Find width W and gap s of parallel coupled microstrip lines
[W, s] = get_mcl(Ze, Zo, h, e_r, f):
Ze <- even mode characteristic impedance (ohm)
Zo <- odd mode ch. impedance (ohm)
h <- height of substrate (mm)
e_r <- relative permitivity of substrate
f <- frequency (GHz)
W -> strip width (mm)
s -> gap (mm)
'''
Z = np.array([Ze,Zo])
u = opt.root(lambda X: Z - np.array(mclZcf(X[0],h,X[1],e_r,f)), [h/2,h/5],method='lm')
return u.x
def open_end(W, h, e_r, f):
'''
Calculate open end displacment dl of microstrip open end.
Kirschning, M., R. H. Jansen, and N. H. L. Koster.
"Accurate model for open end effect of microstrip lines."
Electronics Letters 17.3 (1981): 123-125.
dl = open_end(W,h,e_r,f)
W <- width of microstrip line (mm)
h <- height of substrate (mm)
e_r <- relative dielectric constant of substrate
f <- frequency (GHz)
'''
epsf = eps_f(W,h,e_r,f)
u = W/h
x1 = 0.434907*(epsf**0.81+0.26)/(epsf**0.81-0.189)*(u**0.8544+0.236)/(u**0.8544+0.87)
x2 = 1 + u**0.371/(2.358*e_r+1)
x3 = 1 + 0.5274*np.arctan(0.084*u**(1.9413/x2))/epsf**0.9236
x4 = 1 + 0.0377*np.arctan(0.067*u**1.456)*(6-5*np.exp(0.036*(1-e_r)))
x5 = 1 - 0.218*np.exp(-7.5*u)
return x1*x3*x5/x4 *h