def __init__(self, pNodeLeft, nNodeLeft, pNodeRight, nNodeRight, Z0, Td, loss=None): """ Arguments: pNodeLeft -- positive node on the left side to tline nNodeLeft -- negative node on the left side to tline pNodeRight -- positive node on the right side to tline nNodeRight -- negative node on the right side to tline Z0 --> characteristic impedance in Ohms Td --> time delay in seconds x.loss --> (optional) loss factor times length, is unitless """ if loss == None: simulator_.TLine_.__init__(self, str(pNodeLeft), str(nNodeLeft), str(pNodeRight), str(nNodeRight), units.float(Z0), units.float(Td)) else: simulator_.TLine_.__init__(self, str(pNodeLeft), str(nNodeLeft), str(pNodeRight), str(nNodeRight), units.float(Z0), units.float(Td), units.float(loss))
def tran(self, tstep, tstop, tmax=0.0, restart=False): """ Runs a Transient analysis and sets the value of the circuit's results array accordingly. It is equivalent to the Spice3 tran command. Arguments: tstep -- desired plotting increment, the actual time-steps will vary from step to step, this is simply a suggestion tstop -- the last time point to simulate tmax -- maximum step size, it is set to tstep if not defined or 0.0 restart -- start a new simulation (False forces the simulator to continue from the last transient simulation) -- default = False Example: >>> import eispice >>> cct = eispice.Circuit("Circuit Tran Test") >>> cct.Vx = eispice.V(1, eispice.GND, 1) >>> cct.Rx = eispice.R(1, eispice.GND, '1') >>> cct.tran('0.1n','1n', '0.5n') >>> cct.check_v(1, '1','0.5n') True """ self.tran_(units.float(tstep), units.float(tstop), units.float(tmax), restart) self._results()
def __init__(self, x=1, y=1, X=20, Y=10, h=0.002, er=4.7, N=20, M=20): """ +--- X -----+ +.-----------. || | || o |+ Y| point || || |y || || || || +'-----------'+ +-- x --+ Arguments: x -- x location of test point (inch) -- default = 1 y -- y location of test point (inch) -- default = 1 X -- X dimmension of plane (inch) -- default = 20 Y -- Y dimmension of plane (inch) -- default = 10 h -- distance between planes (inch) -- default = 0.002 er -- permitivity of the dielectric -- deafault = 4.7 N -- size of bedspring grid in X dimmension -- default = 20 M -- size of bedspring grid in Y dimmension -- default = 20 """ self.x = units.float(x) self.y = units.float(y) self.X = units.float(X) self.Y = units.float(Y) self.h = units.float(h) self.M = M self.N = N # Plane capacitance e0 = 2.24896371e-13 # F/in self.Cp = e0 * er * ((self.X * self.Y) / self.h) # Propigation time accross plane c = 1.18028527e10 # in/sec v = c / numpy.sqrt(er) self.tpdx = self.X / v self.tpdy = self.Y / v def Cs(p, q, r): return numpy.cos(numpy.pi * p * q / r) self.A = numpy.ndarray((M, N), dtype=numpy.double) for m in range(0, self.M): for n in range(0, self.N): if (m == 0) and (n == 0): a = 1 elif ((m == 0) and (n > 0)) or ((n == 0) and (m > 0)): a = 2 else: a = 4 self.A[m, n] = a * Cs(m, self.x, self.X)**2 * Cs( n, self.y, self.Y)**2
def __init__(self, states=[0, 1, 0], v1=0, v2=1, tb=10e-9, tr=1e-9, tj=10e-12, resolution=1e3): """ Arguments: states -- list of digital states v1 -- voltage level in in state "0" (volt) v2 -- voltage level in in state "1" (volt) tb -- width of single bit (seconds) tr -- rise/fall times -- 20%-80% -- (seconds) tj -- jitter -- standard deviation -- (seconds) resolution -- time points per bit """ v1 = units.float(v1) v2 = units.float(v2) tb = units.float(tb) tr = units.float(tr) tj = units.float(tj) length = len(states) * tb time = numpy.arange(0.0, length, tb / resolution) voltage = numpy.zeros(len(time)) state0 = states[0] td = -length if state0 == 0: v1, v2 = v2, v1 for i in range(0, len(time)): tn = time[i] state = states[int(i / resolution)] if state0 < state: state0 = state td = tn + random.gauss(tj * 6, tj) v1, v2 = v2, v1 if state0 > state: state0 = state td = tn + random.gauss(tj * 6, tj) v1, v2 = v2, v1 voltage[i] = v1 + _gauss(v1, v2, td, tr, tn) time = time - tj * 6 Waveform.__init__(self, time, voltage, tb, tr)
def __init__(self, length, Zc, er=4.3): """ Arguments: length -- length of T-Line (inches) Zc -- characteristic impedance (Ohms) er -- permitivity (unitless) -- default = 4.3 """ TwoPort.__init__(self) self.length = units.float(length) self.Zc = units.float(Zc) self.er = er
def __init__(self, start, stop, steps=100): """ Arguments: start -- start LogFuency stop -- stop LogFuency steps -- number of steps per decade -- default = 100 """ start = numpy.log10(units.float(start)) stop = numpy.log10(units.float(stop)) steps = (stop - start)*steps Freq.__init__(self, numpy.logspace(start, stop, num = steps))
def handleRange(self, key, typ, min, max): key = key.replace(" ", "_").lower() if not hasattr(self, key): setattr(self, key, {}) dic = getattr(self, key) dic['typ'] = units.float(typ) dic['min'] = units.float(min) dic['max'] = units.float(max) if dic['min'] == None: dic['min'] = dic['typ'] if dic['max'] == None: dic['max'] = dic['typ']
def handleRange(self, key, typ, min, max): key = key.replace(" ","_").lower() if not hasattr(self, key): setattr(self, key, {}) dic = getattr(self, key) dic['typ'] = units.float(typ) dic['min'] = units.float(min) dic['max'] = units.float(max) if dic['min'] == None: dic['min'] = dic['typ'] if dic['max'] == None: dic['max'] = dic['typ']
def __init__(self, pNode, nNode, dcValue=0.0, wave=None): """ Arguments: pNode -- positive node name nNode -- negative node name dcValue -- DC Value in Volts wave -- (optional) waveform """ if wave == None: simulator_.VoltageSource_.__init__(self, str(pNode), str(nNode), units.float(dcValue)) else: simulator_.VoltageSource_.__init__(self, str(pNode), str(nNode), units.float(dcValue), wave)
def check_v(self, name, value, time=0.0): """ Raises an exception if the value of the voltage at time (seconds) does not equal the value supplied +/-0.01%. Arguments: name -- name of the node value -- value to check against time -- time point to check at (seconds) -- default = 0.0 """ value = units.float(value) time = units.float(time) name = str(name) return self._check(name, value, time, self.v[name](time))
def __init__(self, value=10e-9): """ Arguments: value -- capacitance (F) -- default = 10nF """ OnePort.__init__(self) self.value = units.float(value)
def __init__(self, value=10e-6): """ Arguments: value -- inductance (H) -- default = 10uF """ OnePort.__init__(self) self.value = units.float(value)
def __init__(self, value=10): """ Arguments: value -- resistance (Ohms) -- default = 10 """ OnePort.__init__(self) self.value = units.float(value)
def check_i(self, name, value, time=0.0): """ Raises an exception if the value of the current at time (seconds) does not equal the value supplied +/-0.01%. Arguments: name -- name of the device value -- value to check against time -- time point to check at (seconds) -- default = 0.0 type -- either Voltage or Current -- default = Voltage """ value = units.float(value) time = units.float(time) name = str(name) return self._check(name, value, time, self.i[name](time))
def __init__(self, pNode, nNode, R): """ Arguments: pNode -- positive node name nNode -- negative node name R -- resistance in Ohms """ simulator_.Resistor_.__init__(self, str(pNode), str(nNode), units.float(R))
def __init__(self, pNode, nNode, L): """ Arguments: pNode -- positive node name nNode -- negative node name L -- inductance in Henrys """ simulator_.Inductor_.__init__(self, str(pNode), str(nNode), units.float(L))
def __init__(self, pNode, nNode, C): """ Arguments: pNode -- positive node name nNode -- negative node name C -- capacitance in Farads """ simulator_.Capacitor_.__init__(self, str(pNode), str(nNode), units.float(C))
def __init__(self, pNode, nNode, controlDevice, value): """ Arguments: pNode -- positive node name nNode -- negative node name controlDevice -- name of control voltage source (string) value -- gain """ equation = ('i(%s)*%e' % (str(controlDevice), units.float(value))) simulator_.Behavioral_.__init__(self, str(pNode), str(nNode), Voltage, equation)
def handle(self, key, typ, min, max): key = units.float(key) if key == None: return self.typ.append([key, units.float(typ)]) if units.float(min) == None: self.min.append([key, units.float(typ)]) else: self.min.append([key, units.float(min)]) if units.float(max) == None: self.max.append([key, units.float(typ)]) else: self.max.append([key, units.float(max)])
def __init__(self, pNode, nNode, pControlNode, nControlNode, value): """ Arguments: pNode -- positive node name nNode -- negative node name pNode -- positive control node name nNode -- negative control node name value -- gain """ equation = ('v(%s,%s)*%e' % (str(pControlNode), str(nControlNode), units.float(value))) simulator_.Behavioral_.__init__(self, str(pNode), str(nNode), Voltage, equation)
def Lvia(d='12mil', h='50mil', s='100mil'): """ Creates a Via Inductance Model for a pair of vias. - Based on <http://www.sigcon.com/Pubs/news/6_08.htm> by Howard Johnson Arguments: d -- via drill diameter (inches) -- default = 12mil h -- length of via between layers used (inches) -- default = 50mil s -- distance from via to via (inches) -- default = 100mil Example: >>> Lvia('10mil', '62mil', '20mil').Z(freq.LogF('10MHz', '100MHz', 2)) array([ 0.+0.0548682j , 0.+0.54868201j]) """ d = units.float(d) h = units.float(h) s = units.float(s) l = 5.08 * 2 * h * (numpy.log(2 * s / d)) * 1e-9 return L(l)
def handleNA(self, key, typ_dv, typ_dt): key_dv = 'dv_' + key.lower()[-1] key_dt = 'dt_' + key.lower()[-1] if not hasattr(self, key_dv): setattr(self, key_dv, {}) if not hasattr(self, key_dt): setattr(self, key_dt, {}) dic_dv = getattr(self, key_dv) dic_dt = getattr(self, key_dt) dic_dv['typ'] = units.float(typ_dv) dic_dv['min'] = units.float(typ_dv) dic_dv['max'] = units.float(typ_dv) dic_dt['typ'] = units.float(typ_dt) dic_dt['min'] = units.float(typ_dt) dic_dt['max'] = units.float(typ_dt)
def __init__(self, length, L, C, R0=0.0, G0=0.0, Rs=0.0, Gd=0.0): """ Arguments: length -- length of T-Line (inches) L -- inductance per meter (H/m) C -- capacitance per meter (C/m) R0 -- series resistance per meter (Ohm/m) -- default = 0 G0 -- parallel conductance per meter (S/m) -- default = 0 Rs -- skin effect resistance (Ohm/(m*sqrt(Hz)) -- default = 0 Gd -- dielectric loss conductance (S/(m*Hz) -- default = 0 """ TwoPort.__init__(self) self.length = units.float(length) / 39.3700787 self.L = units.float(L) self.C = units.float(C) self.R0 = units.float(R0) self.G0 = units.float(G0) self.Rs = units.float(Rs) self.Gd = units.float(Gd)
def res(value, tol=1): """ Returns the closest standard resistor value. Arguments: value -- resistance value, float or string with units tol -- tolerance, 1, 2, 5, 10 (in percentage) -- deafault 1 Example: >>> R = res('89.8') >>> print "%0.1f" % R 90.9 """ if tol == 1: N = 96 figs = 1 elif tol == 2: N = 48 figs = 1 elif tol == 5: N = 24 figs = 0 elif tol == 10: N = 12 figs = 0 else: raise RuntimeError, 'Tolearnce must be 1%, 2%, 5%, or 10%' value = units.float(value) dec = (math.floor(math.log10(value)) - 1) value = value / 10**dec i = round(math.log10(value) * N) return 10**dec * round(10**(i / N), figs)
def _eye(tn, tb, tr): tb = units.float(tb) tr = units.float(tr) return (tn - 2 * tr) % tb
def handle(self, key, typ, min, max): self.data['typ'].append([units.float(key), units.float(typ)]) if units.float(min) == None: self.data['min'].append([units.float(key), units.float(typ)]) else: self.data['min'].append([units.float(key), units.float(min)]) if units.float(max) == None: self.data['max'].append([units.float(key), units.float(typ)]) else: self.data['max'].append([units.float(key), units.float(max)])
def __init__(self, signal, model, R, L, C): self.signal = signal self.model = model self.R = units.float(R) self.L = units.float(L) self.C = units.float(C)
def __init__(self, cNode, bNode, eNode, sNode=GND, area=1.0, IS=1.0e-16, BF=100, NF=1.0, VAF=1e100, IKF=1e100, ISE=0, NE=1.5, BR=1, NR=1, VAR=1e100, IKR=1e100, ISC=0, NC=2, RB=0, IRB=1e100, RBM=None, RE=0, RC=0, CJE=0, VJE=0.75, MJE=0.33, TF=0, XTF=0, VTF=1e100, ITF=0, PTF=0, CJC=0, VJC=0.75, MJC=0.33, XCJC=1, TR=0, CJS=0, VJS=0.75, MJS=0, XTB=0, EG=1.11, XTI=3, KF=0, AF=1, FC=0.5, TNOM=27): """ Arguments: cNode -- collector node name bNode -- base node name eNode -- emitter node name bNode -- substrate node name -- default = GND area -- area factor (for spice3f5 compatibility) -- default = 1.0 """ cNode = str(cNode) bNode = str(bNode) eNode = str(eNode) sNode = str(sNode) area = units.float(area) IS = units.float(area) BF = units.float(area) NF = units.float(area) VAF = units.float(area) IKF = units.float(area) ISE = units.float(area) NE = units.float(area) BR = units.float(area) NR = units.float(area) VAR = units.float(area) IKR = units.float(area) ISC = units.float(area) NC = units.float(area) RB = units.float(area) IRB = units.float(area) if RBM == None: RBM = RB RBM = units.float(area) RE = units.float(area) RC = units.float(area) CJE = units.float(area) VJE = units.float(area) MJE = units.float(area) TF = units.float(area) XTF = units.float(area) TR = units.float(area) CJS = units.float(area) VJS = units.float(area) MJS = units.float(area) XTB = units.float(area) EG = units.float(area) XTI = units.float(area) KF = units.float(area) AF = units.float(area) FC = units.float(area) TNOM = units.float(area) # Local Variables k = 1.3806503e-23 # Boltzmann's Constant (1/JK) q = 1.60217646e-19 # Electron Charge (C) Vt = ((k * (TNOM + 273.15)) / q) # Thermal Voltage # Parasitic Resistance if RE != 0: self.Re = R(eNode, self.node('re'), area * RE) eNode = self.node('re') if RC != 0: self.Rc = R(eNode, self.node('rc'), area * RC) cNode = self.node('rc') #~ if RB != 0: #~ Rb = #~ self.Rb = R(eNode, self.node('rc'), area*RC) #~ cNode = self.node('rc') # Saturation and Breakdown Current #~ Ibe = '(%e*(exp(v(%s,%s)/%e)-1))' % (IS/BF, rNode, nNode, NF*Vt) #~ Ibe = '(%e*(exp(v(%s,%s)/%e)-1))' % (IS/BF, rNode, nNode, NF*Vt) #~ self.Isb = B(rNode, nNode, Current, Is + '+' + Ib) warnings.warn("BJT Model not complete.")
def handleValue(self, key, name): key = key.replace(" ","_").lower() setattr(self, key, units.float(name))
def __init__(self, cNode, bNode, eNode, sNode=GND, area=1.0, IS=1.0e-16, BF=100, NF=1.0, VAF=1e100, IKF=1e100, ISE=0, NE=1.5, BR=1, NR=1, VAR=1e100, IKR=1e100, ISC=0, NC=2, RB=0, IRB=1e100, RBM=None, RE=0, RC=0, CJE=0, VJE=0.75, MJE=0.33, TF=0, XTF=0, VTF=1e100, ITF=0, PTF=0, CJC=0, VJC=0.75, MJC=0.33, XCJC=1, TR=0, CJS=0, VJS=0.75, MJS=0, XTB=0, EG=1.11, XTI=3, KF=0, AF=1, FC=0.5, TNOM=27): """ Arguments: cNode -- collector node name bNode -- base node name eNode -- emitter node name bNode -- substrate node name -- default = GND area -- area factor (for spice3f5 compatibility) -- default = 1.0 """ cNode = str(cNode) bNode = str(bNode) eNode = str(eNode) sNode = str(sNode) area = units.float(area) IS = units.float(area) BF = units.float(area) NF = units.float(area) VAF = units.float(area) IKF = units.float(area) ISE = units.float(area) NE = units.float(area) BR = units.float(area) NR = units.float(area) VAR = units.float(area) IKR = units.float(area) ISC = units.float(area) NC = units.float(area) RB = units.float(area) IRB = units.float(area) if RBM == None: RBM = RB RBM = units.float(area) RE = units.float(area) RC = units.float(area) CJE = units.float(area) VJE = units.float(area) MJE = units.float(area) TF = units.float(area) XTF = units.float(area) TR = units.float(area) CJS = units.float(area) VJS = units.float(area) MJS = units.float(area) XTB = units.float(area) EG = units.float(area) XTI = units.float(area) KF = units.float(area) AF = units.float(area) FC = units.float(area) TNOM = units.float(area) # Local Variables k = 1.3806503e-23 # Boltzmann's Constant (1/JK) q = 1.60217646e-19 # Electron Charge (C) Vt = ((k*(TNOM+273.15))/q) # Thermal Voltage # Parasitic Resistance if RE != 0: self.Re = R(eNode, self.node('re'), area*RE) eNode = self.node('re') if RC != 0: self.Rc = R(eNode, self.node('rc'), area*RC) cNode = self.node('rc') #~ if RB != 0: #~ Rb = #~ self.Rb = R(eNode, self.node('rc'), area*RC) #~ cNode = self.node('rc') # Saturation and Breakdown Current #~ Ibe = '(%e*(exp(v(%s,%s)/%e)-1))' % (IS/BF, rNode, nNode, NF*Vt) #~ Ibe = '(%e*(exp(v(%s,%s)/%e)-1))' % (IS/BF, rNode, nNode, NF*Vt) #~ self.Isb = B(rNode, nNode, Current, Is + '+' + Ib) warnings.warn("BJT Model not complete.")
def __init__(self, iNodes, iRef, oNodes, oRef, length, R0, L0, C0, G0=None, Rs=None, Gd=None, fgd=1e100, fK=1e9, M=6): """ Arguments: iNodes -- list/tuple or single string of input nodes iRef -- name of the input refrence node oNodes -- list/tuple or single string of output nodes iRef -- name of the output refrence node length -- length of the t-line in meters R0 -- DC resistance matrix or float from single T-Line (ohm/m) L0 -- DC inductance matrix or float from single T-Line (H/m) C0 -- DC capacitance matrix or float from single T-Line (F/m) G0 -- (optional) DC shunt conductance matrix (S/m) Rs -- (optional) Skin-effect resistance matrix (Ohm/m*sqrt(Hz)) Gd -- (optional) Dielectric-loss conductance matrix (S/m*Hz) fgd -- (optional) Cut-Off for Dielectric loss (Hz) fK -- (optional) Cut-Off for T-Line Model (Hz) M -- (optional) Order of Approximation of Curve Fit (unitless) """ warnings.warn("W-Element Model not complete.") # Makes it possible to send a single string for a non-coupled T-Line if isinstance(iNodes, str): iNodes = (iNodes, ) if isinstance(oNodes, str): oNodes = (oNodes, ) if len(iNodes) != len(oNodes): raise (RuntimeError, "Must have the same number of input and output nodes.") nodes = len(iNodes) # Do some parameter checking here that is tough to do in C, also # create zeroed matracies if G and/or R aren't defined. if nodes > 1: if G0 is None: G0 = array(zeros((nodes, nodes))) if Rs is None: Rs = array(zeros((nodes, nodes))) if Gd is None: Gd = array(zeros((nodes, nodes))) R0 = array(units.floatList2D(R0)) L0 = array(units.floatList2D(L0)) C0 = array(units.floatList2D(C0)) G0 = array(units.floatList2D(G0)) Rs = array(units.floatList2D(Rs)) Gd = array(units.floatList2D(Gd)) if (R0.shape[0] != nodes) or (R0.shape[1] != nodes): raise ( RuntimeError, "R0 must be a square matrix with as many rows as nodes.") if (L0.shape[0] != nodes) or (L0.shape[1] != nodes): raise ( RuntimeError, "L0 must be a square matrix with as many rows as nodes.") if (C0.shape[0] != nodes) or (C0.shape[1] != nodes): raise ( RuntimeError, "C0 must be a square matrix with as many rows as nodes.") if (G0.shape[0] != nodes) or (G0.shape[1] != nodes): raise ( RuntimeError, "G0 must be a square matrix with as many rows as nodes.") if (Rs.shape[0] != nodes) or (Rs.shape[1] != nodes): raise ( RuntimeError, "Rs must be a square matrix with as many rows as nodes.") if (Gd.shape[0] != nodes) or (Gd.shape[1] != nodes): raise ( RuntimeError, "Gd must be a square matrix with as many rows as nodes.") else: if G0 is None: G0 = 0.0 if Rs is None: Rs = 0.0 if Gd is None: Gd = 0.0 R0 = array((units.float(R0), )) L0 = array((units.float(L0), )) C0 = array((units.float(C0), )) G0 = array((units.float(G0), )) Rs = array((units.float(Rs), )) Gd = array((units.float(Gd), )) nodeNames = tuple([str(i) for i in iNodes] + [str(iRef)] + [str(i) for i in oNodes] + [str(oRef)]) simulator_.TLineW_.__init__(self, nodeNames, int(M), units.float(length), L0, C0, R0, G0, Rs, Gd, units.float(fgd), units.float(fK))
def __init__(self, pNode, nNode, area=1.0, IS=1.0e-14, RS=0, N=1, TT=0, CJO=0, VJ=1, M=0.5, EG=1.11, XTI=3.0, KF=0, AF=1, FC=0.5, BV=1e100, IBV=1e-3, TNOM=27): """ Arguments: pNode -- positive node name nNode -- negative node name area -- area factor (for spice3f5 compatibility) -- default = 1.0 IS -- saturation current (A) -- default = 1.0e-14 RS -- ohmic resistance (Ohms) -- default = 0 N -- emission coefficient -- default = 1 TT -- transit-time (sec) -- default = 0 CJO -- zero-bias junction capacitance (F) -- default = 0 VJ -- junction potential -- default = 0.5 M -- grading coefficient (V) -- default = 1 EG -- reserved for possible future use XTI -- reserved for possible future use KF -- reserved for possible future use AF -- reserved for possible future use FC -- Coefficient for Cd formula -- default = 0.5 BV -- reverse breakdown voltage (V) -- default = 1e100 IBV -- current at breakdown voltage (A) -- default = 1e-3 TNOM -- parameter measurement temperature (degC) -- default = 27 """ pNode = str(pNode) nNode = str(nNode) area = units.float(area) IS = units.float(IS) RS = units.float(RS) N = units.float(N) TT = units.float(TT) CJO = units.float(CJO) VJ = units.float(VJ) M = units.float(M) BV = units.float(BV) IBV = units.float(IBV) TNOM = units.float(TNOM) # Parasitic Resistance if RS != 0: self.Rs = R(pNode, self.node('r'), area*RS) pNode = self.node('r') # Local Variables k = 1.3806503e-23 # Boltzmann's Constant (1/JK) q = 1.60217646e-19 # Electron Charge (C) Vt = ((k*(TNOM+273.15))/q) # Thermal Voltage # Saturation and Breakdown Current Is = ('(if(v(%s,%s)>=%e)*(%e*(exp(v(%s,%s)/%e)-1)))' % (pNode, nNode, -BV, area*IS, pNode, nNode, N*Vt)) Ib = ('(if(v(%s,%s)<%e)*(%e*(exp((-%e-v(%s,%s))/%e)-1)))' % (pNode, nNode, -BV, area*IS, BV, pNode, nNode,Vt)) self.Isb = B(pNode, nNode, Current, Is + '+' + Ib) # Junction (Depletion) and Diffusion Capacitance Cd = '(%e*(exp(v(%s,%s)/%e)))' % (area*TT*IS/N*Vt, pNode, nNode, N*Vt) Cj1 = ('(if(v(%s,%s)<%e)*(%e/((1-v(%s,%s)/%e)^%e)))' % (pNode, nNode, FC*VJ, area*CJO, pNode, nNode, VJ, M)) Cj2 = ('(if(v(%s,%s)>=%e)*%e*(1-%e+%e*v(%s,%s)))' % (pNode, nNode, FC*VJ, (area*CJO/((1-FC)**(M+1))), FC*(1+M), (M/VJ), pNode, nNode)) self.Cjd = B(pNode, nNode, Capacitor, Cd + '+' + Cj1 + '+' + Cj2)
def __init__(self, iNodes, iRef, oNodes, oRef, length, R0, L0, C0, G0=None, Rs=None, Gd=None, fgd=1e100, fK=1e9, M=6): """ Arguments: iNodes -- list/tuple or single string of input nodes iRef -- name of the input refrence node oNodes -- list/tuple or single string of output nodes iRef -- name of the output refrence node length -- length of the t-line in meters R0 -- DC resistance matrix or float from single T-Line (ohm/m) L0 -- DC inductance matrix or float from single T-Line (H/m) C0 -- DC capacitance matrix or float from single T-Line (F/m) G0 -- (optional) DC shunt conductance matrix (S/m) Rs -- (optional) Skin-effect resistance matrix (Ohm/m*sqrt(Hz)) Gd -- (optional) Dielectric-loss conductance matrix (S/m*Hz) fgd -- (optional) Cut-Off for Dielectric loss (Hz) fK -- (optional) Cut-Off for T-Line Model (Hz) M -- (optional) Order of Approximation of Curve Fit (unitless) """ warnings.warn("W-Element Model not complete.") # Makes it possible to send a single string for a non-coupled T-Line if isinstance(iNodes, str): iNodes = (iNodes, ) if isinstance(oNodes, str): oNodes = (oNodes, ) if len(iNodes) != len(oNodes): raise (RuntimeError, "Must have the same number of input and output nodes.") nodes = len(iNodes) # Do some parameter checking here that is tough to do in C, also # create zeroed matracies if G and/or R aren't defined. if nodes > 1: if G0 is None: G0 = array(zeros((nodes, nodes))) if Rs is None: Rs = array(zeros((nodes, nodes))) if Gd is None: Gd = array(zeros((nodes, nodes))) R0 = array(units.floatList2D(R0)) L0 = array(units.floatList2D(L0)) C0 = array(units.floatList2D(C0)) G0 = array(units.floatList2D(G0)) Rs = array(units.floatList2D(Rs)) Gd = array(units.floatList2D(Gd)) if (R0.shape[0] != nodes) or (R0.shape[1] != nodes): raise (RuntimeError, "R0 must be a square matrix with as many rows as nodes.") if (L0.shape[0] != nodes) or (L0.shape[1] != nodes): raise (RuntimeError, "L0 must be a square matrix with as many rows as nodes.") if (C0.shape[0] != nodes) or (C0.shape[1] != nodes): raise (RuntimeError, "C0 must be a square matrix with as many rows as nodes.") if (G0.shape[0] != nodes) or (G0.shape[1] != nodes): raise (RuntimeError, "G0 must be a square matrix with as many rows as nodes.") if (Rs.shape[0] != nodes) or (Rs.shape[1] != nodes): raise (RuntimeError, "Rs must be a square matrix with as many rows as nodes.") if (Gd.shape[0] != nodes) or (Gd.shape[1] != nodes): raise (RuntimeError, "Gd must be a square matrix with as many rows as nodes.") else: if G0 is None: G0 = 0.0 if Rs is None: Rs = 0.0 if Gd is None: Gd = 0.0 R0 = array((units.float(R0),)) L0 = array((units.float(L0),)) C0 = array((units.float(C0),)) G0 = array((units.float(G0),)) Rs = array((units.float(Rs),)) Gd = array((units.float(Gd),)) nodeNames = tuple([str(i) for i in iNodes] + [str(iRef)] + [str(i) for i in oNodes] + [str(oRef)]) simulator_.TLineW_.__init__(self, nodeNames, int(M), units.float(length), L0, C0, R0, G0, Rs, Gd, units.float(fgd), units.float(fK))
def __call__(self, time): if self.time == None: return self.all return float(interpolate.interp1d.__call__(self, units.float(time)))
def __init__(self, pNode, nNode, area=1.0, IS=1.0e-14, RS=0, N=1, TT=0, CJO=0, VJ=1, M=0.5, EG=1.11, XTI=3.0, KF=0, AF=1, FC=0.5, BV=1e100, IBV=1e-3, TNOM=27): """ Arguments: pNode -- positive node name nNode -- negative node name area -- area factor (for spice3f5 compatibility) -- default = 1.0 IS -- saturation current (A) -- default = 1.0e-14 RS -- ohmic resistance (Ohms) -- default = 0 N -- emission coefficient -- default = 1 TT -- transit-time (sec) -- default = 0 CJO -- zero-bias junction capacitance (F) -- default = 0 VJ -- junction potential -- default = 0.5 M -- grading coefficient (V) -- default = 1 EG -- reserved for possible future use XTI -- reserved for possible future use KF -- reserved for possible future use AF -- reserved for possible future use FC -- Coefficient for Cd formula -- default = 0.5 BV -- reverse breakdown voltage (V) -- default = 1e100 IBV -- current at breakdown voltage (A) -- default = 1e-3 TNOM -- parameter measurement temperature (degC) -- default = 27 """ pNode = str(pNode) nNode = str(nNode) area = units.float(area) IS = units.float(IS) RS = units.float(RS) N = units.float(N) TT = units.float(TT) CJO = units.float(CJO) VJ = units.float(VJ) M = units.float(M) BV = units.float(BV) IBV = units.float(IBV) TNOM = units.float(TNOM) # Parasitic Resistance if RS != 0: self.Rs = R(pNode, self.node('r'), area * RS) pNode = self.node('r') # Local Variables k = 1.3806503e-23 # Boltzmann's Constant (1/JK) q = 1.60217646e-19 # Electron Charge (C) Vt = ((k * (TNOM + 273.15)) / q) # Thermal Voltage # Saturation and Breakdown Current Is = ('(if(v(%s,%s)>=%e)*(%e*(exp(v(%s,%s)/%e)-1)))' % (pNode, nNode, -BV, area * IS, pNode, nNode, N * Vt)) Ib = ('(if(v(%s,%s)<%e)*(%e*(exp((-%e-v(%s,%s))/%e)-1)))' % (pNode, nNode, -BV, area * IS, BV, pNode, nNode, Vt)) self.Isb = B(pNode, nNode, Current, Is + '+' + Ib) # Junction (Depletion) and Diffusion Capacitance Cd = '(%e*(exp(v(%s,%s)/%e)))' % (area * TT * IS / N * Vt, pNode, nNode, N * Vt) Cj1 = ('(if(v(%s,%s)<%e)*(%e/((1-v(%s,%s)/%e)^%e)))' % (pNode, nNode, FC * VJ, area * CJO, pNode, nNode, VJ, M)) Cj2 = ('(if(v(%s,%s)>=%e)*%e*(1-%e+%e*v(%s,%s)))' % (pNode, nNode, FC * VJ, (area * CJO / ((1 - FC)**(M + 1))), FC * (1 + M), (M / VJ), pNode, nNode)) self.Cjd = B(pNode, nNode, Capacitor, Cd + '+' + Cj1 + '+' + Cj2)