def solve(self, freqs, outbranches, currentoutput=False, complexfreq=False, refnode=gnd): toolkit = self.toolkit n = self.cir.n x = self.toolkit.zeros(n) # This should be the x-vector at the DC operating point ## Complex frequency variable if complexfreq: s = freqs else: s = 2j*self.toolkit.pi*freqs epar = self.epar G = self.cir.G(x, epar) C = self.cir.C(x, epar) ## Refer the voltages to the gnd node by removing ## the rows and columns that corresponds to this node irefnode = self.cir.get_node_index(refnode) G,C = remove_row_col((G,C), irefnode, self.toolkit) # Calculate the reciprocal G and C matrices Yreciprocal = G.T + s*C.T Yreciprocal = self.toolkit.toMatrix(Yreciprocal) result = [] for branch in outbranches: ## Stimuli if currentoutput: u = zeros(n, dtype=int) ibranch = self.cir.get_branch_index(branch) u[ibranch] = -1 else: u = self.toolkit.zeros(n, dtype=int) ## The signed is swapped because the u-vector appears in the lhs u[self.cir.get_node_index(branch.plus)] = -1 u[self.cir.get_node_index(branch.minus)] = 1 u, = remove_row_col((u,), irefnode, self.toolkit) ## Calculate transimpedances from currents in each nodes to output result.append(self.toolkit.linearsolver(Yreciprocal, -u)) return result
def solve(self, freqs, refnode=gnd, complexfreq = False, u = None): G, C, CY, u, x, ss = self.dc_steady_state(freqs, refnode, complexfreq = complexfreq, u = u) ## Refer the voltages to the reference node by removing ## the rows and columns that corresponds to this node irefnode = self.cir.get_node_index(refnode) G,C,CY,u = remove_row_col((G,C,CY,u), irefnode, self.toolkit) def acsolve(s): return self.toolkit.linearsolver(s*C + G, -u) xac = self.ss_map_function(acsolve, ss, refnode) self.result = CircuitResultAC(self.cir, x, xac, ss * xac, sweep_values = freqs, sweep_label='frequency', sweep_unit='Hz') return self.result
def solve(self, freqs, refnode=gnd, complexfreq = False, u = None): G, C, CY, u, x, ss = self.dc_steady_state(freqs, refnode, complexfreq = complexfreq, u = u) tk = self.toolkit def noisesolve(s): # Calculate the reciprocal G and C matrices Yreciprocal = G.T + s*C.T Yreciprocal2, uu = (tk.toMatrix(A) for A in (Yreciprocal, u)) ## Calculate transimpedances from currents in each nodes to output zm = tk.linearsolver(Yreciprocal2, -uu) xn2out = tk.dot(tk.dot(zm.reshape(1, tk.size(zm)), CY), tk.conj(zm)) ## Etract gain gain = None if isinstance(self.inputsrc, VS): gain = self.cir.extract_i(zm, instjoin(self.inputsrc_name, 'plus'), refnode=refnode, refnode_removed=True) elif isinstance(self.inputsrc, IS): plus_node = instjoin(self.inputsrc_name, 'plus') minus_node = instjoin(self.inputsrc_name, 'minus') gain = self.cir.extract_v(zm, self.cir.get_node(plus_node), self.cir.get_node(minus_node), refnode=refnode, refnode_removed=True) return xn2out[0], gain # Calculate output voltage noise if self.outputnodes != None: ioutp, ioutn = (self.cir.get_node_index(node) for node in self.outputnodes) u[ioutp] = -1 u[ioutn] = 1 # Calculate output current noise else: plus_term = instjoin(self.outputsrc_name, 'plus') branch = self.cir.get_terminal_branch(plus_term)[0] ibranch = self.cir.get_branch_index(branch) u[ibranch] = -1 ## Refer the voltages to the gnd node by removing ## the rows and columns that corresponds to this node irefnode = self.cir.nodes.index(refnode) G,C,CY,u = remove_row_col((G,C,CY,u), irefnode, tk) xn2out, gain = self.noise_map_function(noisesolve, ss, refnode) # Store results result = InternalResultDict() if self.outputnodes != None: result['Svnout'] = xn2out elif self.outputsrc != None: result['Sinout'] = xn2out # Calculate the gain from the input voltage source by using the # transimpedance vector to find the transfer from the branch voltage of # the input source to the output if isinstance(self.inputsrc, VS): result['gain'] = gain result['Svninp'] = xn2out / abs(gain)**2 elif isinstance(self.inputsrc, IS): result['gain'] = gain result['Sininp'] = xn2out / abs(gain)**2 return result