예제 #1
0
    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
예제 #2
0
    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
예제 #3
0
    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