Example #1
0
    def solve(self, freqs, refnode = gnd, complexfreq = False):
        toolkit = self.toolkit

        x = self.toolkit.zeros(self.cir.n) ## FIXME, this should be replaced by DC-analysis
        self.loopprobe['vinj'].ipar.vac = 1 
        self.loopprobe['iinj'].ipar.iac = 0 

        ac_vinj = AC(self.cir, toolkit=toolkit)

        res_vinj = ac_vinj.solve(freqs, refnode = refnode, 
                                 complexfreq=complexfreq,
                                 u = self.cir.u(x, analysis='feedback'))

        self.loopprobe['vinj'].ipar.vac = 0 
        self.loopprobe['iinj'].ipar.iac = 1 

        ac_iinj = AC(self.cir, toolkit=toolkit)

        res_iinj = ac_iinj.solve(freqs, refnode = refnode, 
                                 complexfreq=complexfreq,
                                 u = self.cir.u(x, analysis='feedback'))

        B = res_vinj.i(self.loopprobe_name + '.vinj.plus')
        D = res_vinj.v(self.loopprobe_name + '.inp', self.loopprobe_name + '.inn')
        A = res_iinj.i(self.loopprobe_name + '.vinj.plus')
        C = res_iinj.v(self.loopprobe_name + '.inp', self.loopprobe_name + '.inn')

        T = (2*(A*D - B*C) - A + D) / (2*(B*C - A*D) + A - D + 1)
        
        result = InternalResultDict()
        result['F'] = 1 + T
        result['T'] = T
        result['loopgain'] = -T
        
        return result
Example #2
0
    def solve_abcd(self, freqs, refnode=gnd, complexfreq=False):
        (inp, inn), (outp, outn) = self.ports

        toolkit = self.toolkit

        ## Add voltage source at input port and create
        ## copies with output open and shorted respectively
        circuit_vs_open = copy(self.cir)

        circuit_vs_open["VS_TwoPort"] = VS(inp, inn, vac=1)

        circuit_vs_shorted = copy(circuit_vs_open)

        circuit_vs_shorted["VL_TwoPort"] = VS(outp, outn, vac=0)

        ## Run AC-analysis on the two circuits
        ac_open = AC(circuit_vs_open, toolkit=toolkit)
        ac_shorted = AC(circuit_vs_shorted, toolkit=toolkit)

        res_open = ac_open.solve(freqs, refnode=refnode, complexfreq=complexfreq)

        res_shorted = ac_shorted.solve(freqs, refnode=refnode, complexfreq=complexfreq)

        A = res_open.v(inp, inn) / res_open.v(outp, outn)
        B = res_shorted.v(inp, inn) / res_shorted.i("VL_TwoPort.plus")
        C = res_open.i("VS_TwoPort.minus") / res_open.v(outp, outn)
        D = res_shorted.i("VS_TwoPort.minus") / res_shorted.i("VL_TwoPort.plus")

        return np.array([[A, B], [C, D]], dtype=object)
Example #3
0
    def solve_abcd(self, freqs, refnode = gnd, complexfreq = False):
        (inp, inn), (outp, outn) = self.ports
                
        toolkit = self.toolkit

        ## Add voltage source at input port and create
        ## copies with output open and shorted respectively
        circuit_vs_open = copy(self.cir)

        circuit_vs_open['VS_TwoPort'] = VS(inp, inn, vac=1)

        circuit_vs_shorted = copy(circuit_vs_open)

        circuit_vs_shorted['VL_TwoPort'] = VS(outp, outn, vac=0)

        ## Run AC-analysis on the two circuits
        ac_open = AC(circuit_vs_open, toolkit=toolkit)
        ac_shorted = AC(circuit_vs_shorted, toolkit=toolkit)

        res_open = ac_open.solve(freqs, refnode = refnode, 
                                 complexfreq=complexfreq)

        res_shorted = ac_shorted.solve(freqs, refnode = refnode, 
                                     complexfreq=complexfreq)
        
        A = res_open.v(inp, inn) / res_open.v(outp, outn)
        B = res_shorted.v(inp, inn) / res_shorted.i('VL_TwoPort.plus')
        C = res_open.i('VS_TwoPort.minus') / res_open.v(outp, outn)
        D = res_shorted.i('VS_TwoPort.minus') / res_shorted.i('VL_TwoPort.plus')

        return np.array([[A,B],[C,D]], dtype=object)
Example #4
0
    def solve(self, freqs, refnode=gnd, complexfreq=False):
        toolkit = self.toolkit

        x = self.toolkit.zeros(
            self.cir.n)  ## FIXME, this should be replaced by DC-analysis
        self.loopprobe['vinj'].ipar.vac = 1
        self.loopprobe['iinj'].ipar.iac = 0

        ac_vinj = AC(self.cir, toolkit=toolkit)

        res_vinj = ac_vinj.solve(freqs,
                                 refnode=refnode,
                                 complexfreq=complexfreq,
                                 u=self.cir.u(x, analysis='feedback'))

        self.loopprobe['vinj'].ipar.vac = 0
        self.loopprobe['iinj'].ipar.iac = 1

        ac_iinj = AC(self.cir, toolkit=toolkit)

        res_iinj = ac_iinj.solve(freqs,
                                 refnode=refnode,
                                 complexfreq=complexfreq,
                                 u=self.cir.u(x, analysis='feedback'))

        B = res_vinj.i(self.loopprobe_name + '.vinj.plus')
        D = res_vinj.v(self.loopprobe_name + '.inp',
                       self.loopprobe_name + '.inn')
        A = res_iinj.i(self.loopprobe_name + '.vinj.plus')
        C = res_iinj.v(self.loopprobe_name + '.inp',
                       self.loopprobe_name + '.inn')

        T = (2 * (A * D - B * C) - A + D) / (2 * (B * C - A * D) + A - D + 1)

        result = InternalResultDict()
        result['F'] = 1 + T
        result['T'] = T
        result['loopgain'] = -T

        return result
Example #5
0
    def solve_s(self, freqs, complexfreq = False):
        """Calculate scattering (s) parameters of circuit

        >>> c = SubCircuit()
        >>> n1 = c.add_node('net1')
        >>> n2 = c.add_node('net2')
        >>> c['R1'] = R(n1, n2, r=9e3)
        >>> c['R2'] = R(n2, gnd, r=1e3)


        >>> an = TwoPortAnalysis(c, n1, gnd, n2, gnd)
        >>> twoport = an.solve_s(freqs = 0)
        >>> mu = 1/twoport.A[0,0]
        >>> print mu
        (0.1+0j)

        """

        ## The s-parameters of an n-port are defined as
        ## B = S * A
        ## where A and B are column-vectors of size n of 
        ## the ingoing and outgoing waves respectively
        ## S is an NxN matrix containing the s-parameters
        ## The elements of the A and B vectors are defined as:
        ## 
        ## a_n = (v_n + Z0 * i_n) / 2 * 1 / sqrt(|Re Z0|)
        ## b_n = (v_n - Z0 * i_n) / 2 * 1 / sqrt(|Re Z0|)
        ## 
        ## where v is the port-voltage and i the current flowing 
        ## into the device, Z0 is an arbitrary chosen impedance
        ##
        ## The straight-forward method to calculate the S matrix
        ## that is used here is to run n AC-analyses and in each
        ## analysis connect a voltage source of voltage 2V
        ## in series with a resistor with resistance R0 ohm
        ## (The chosen Z0 value is real). The other ports
        ## are terminated with resistance R0.
        ## The s-parameters S_k_n can now be calculated as:
        ## S_k_n = b_k / a_n
        ## where
        ## a_n = ((2-R0*i_n) + R0 * i+n) / 2 / sqrt(R0) = 1 / sqrt(R0)
        ## b_k = (v_k + v_k) / 2 / sqrt(R0) = v_k / sqrt(R0) | k != n
        ## b_n = ((2-R0*i_n) - R0*i_n) / 2 / sqrt(R0) = {i_n = (v_n - 2)/R0} =
        ## (2-2*R0*(v_n-2)/R0)/2/sqrt(R0) = (1 - v_n - 2) / sqrt(R0) =
        ## = (v_n - 1) / sqrt(R0)
        ## => S_k_n = b_k / a_n = v_k | k != n
        ## S_n_n = b_n / a_n = v_n - 1
        ##
        ##
        toolkit = self.toolkit

        # Reference impedance
        g0 = 1

        N = len(self.ports)

        portnumbers = range(N)

        S = np.zeros((N,N), dtype=object)
        
        circuit = copy(self.cir)

        refnode = self.ports[0][1]

        ## Place power sources at the ports
        for n, sourceport in enumerate(self.ports):
            circuit['_is%d'%n] = ISInternal(sourceport[1], sourceport[0], i=0,iac = 0, toolkit=toolkit)
            circuit['_rl%d'%n] = G(sourceport[1], sourceport[0], g = g0, noisy=False, toolkit=toolkit)
            
        if toolkit.symbolic:
            ## For now just one frequency is allowed
            assert not isiterable(freqs)

            Gmat, C, CY, u, x, ss = dc_steady_state(circuit, freqs, 
                                             refnode,
                                             toolkit,
                                             complexfreq = complexfreq,
                                             epar = self.epar)
           ## 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)
            Gmat,C,CY,u = remove_row_col((Gmat,C,CY,u), irefnode, toolkit)

            Y = C * ss + Gmat
            detY =  toolkit.det(Y)

        for n, sourceport in enumerate(self.ports):
            ## Add stimulus to the port
            circuit['_is%d'%n].ipar.iac = 2 * g0

            ## If symbolic the s-parameters are calculated using co-factors
            if toolkit.symbolic:
                u_wrefnode = circuit.u(x, analysis='internalac', epar=self.epar)
                (u,) = circuit.remove_refnode((u_wrefnode,), refnode)
                ## Calculate s-parameters using cofactors
                for k, port in enumerate(self.ports):
                    resname = "v(%s,%s)"%(port[0], port[1])

                    res = linearsolver_partial(Y, u, refnode, [resname],
                                               circuit, toolkit, detY=detY)
                    if k == n:
                        S[k,n] = res[resname] - 1
                    else:
                        S[k,n] = res[resname]

            else:
                ## Run AC-analysis
                acana = AC(circuit, toolkit=toolkit, analysis='internalac')
                res = acana.solve(freqs, refnode=refnode,
                                  complexfreq = complexfreq)
                ## Obtain s-parameters
                for k, port in enumerate(self.ports):
                    if k == n:
                        S[k,n] = res.v(port[0], port[1]) - 1
                    else:
                        S[k,n] = res.v(port[0], port[1])

            ## Clear stimulus to the port
            circuit['_is%d'%n].ipar.iac = 0

        ## Find noise wave correlation matrix
        ## The method works as follows:
        ## 1. terminate all ports with z0
        ## 2. calculate transimpedances from a current source in each node
        ##    to the port voltages by using the adjoint Y-matrix.
        ##    As seen above the outgoing wave b is b=V(port_k) / sqrt(z0)
        ##    for a terminated port.
        ## 3. Form a transform matrix T where the columns are the transimpedance
        ##    vectors divided by sqrt(z0)
        ## 4. Calculate the correlation matrix as:
        ##    CS = T * CY * T+

        ## Calculate transimpedances
        branchlist = [Branch(*port) for port in self.ports]
        
        transimpana = TransimpedanceAnalysis(circuit, toolkit=toolkit)

        zmlist = transimpana.solve(freqs, branchlist, refnode=refnode,
                                   complexfreq=complexfreq)

        T = np.matrix(zmlist) * g0**0.5
        
        ## Complex frequency variable
        if complexfreq:
            s = freqs
        else:
            s = 2j*np.pi*freqs

        ## Calculate CY of circuit
        x = np.zeros(circuit.n)
        CY = circuit.CY(x, np.imag(s), epar = self.epar)
        irefnode = circuit.get_node_index(refnode)
        CY, = remove_row_col((CY,), irefnode, self.toolkit)

        ## Calculate noise wave correlation matrix
        CS = np.array(T * CY * T.H)

        return NPortS(S, CS, z0=1/toolkit.integer(g0))
Example #6
0
    def solve_s(self, freqs, complexfreq=False):
        """Calculate scattering (s) parameters of circuit

        >>> c = SubCircuit()
        >>> n1 = c.add_node('net1')
        >>> n2 = c.add_node('net2')
        >>> c['R1'] = R(n1, n2, r=9e3)
        >>> c['R2'] = R(n2, gnd, r=1e3)


        >>> an = TwoPortAnalysis(c, n1, gnd, n2, gnd)
        >>> twoport = an.solve_s(freqs = 0)
        >>> mu = 1/twoport.A[0,0]
        >>> print mu
        (0.1+0j)

        """

        ## The s-parameters of an n-port are defined as
        ## B = S * A
        ## where A and B are column-vectors of size n of
        ## the ingoing and outgoing waves respectively
        ## S is an NxN matrix containing the s-parameters
        ## The elements of the A and B vectors are defined as:
        ##
        ## a_n = (v_n + Z0 * i_n) / 2 * 1 / sqrt(|Re Z0|)
        ## b_n = (v_n - Z0 * i_n) / 2 * 1 / sqrt(|Re Z0|)
        ##
        ## where v is the port-voltage and i the current flowing
        ## into the device, Z0 is an arbitrary chosen impedance
        ##
        ## The straight-forward method to calculate the S matrix
        ## that is used here is to run n AC-analyses and in each
        ## analysis connect a voltage source of voltage 2V
        ## in series with a resistor with resistance R0 ohm
        ## (The chosen Z0 value is real). The other ports
        ## are terminated with resistance R0.
        ## The s-parameters S_k_n can now be calculated as:
        ## S_k_n = b_k / a_n
        ## where
        ## a_n = ((2-R0*i_n) + R0 * i+n) / 2 / sqrt(R0) = 1 / sqrt(R0)
        ## b_k = (v_k + v_k) / 2 / sqrt(R0) = v_k / sqrt(R0) | k != n
        ## b_n = ((2-R0*i_n) - R0*i_n) / 2 / sqrt(R0) = {i_n = (v_n - 2)/R0} =
        ## (2-2*R0*(v_n-2)/R0)/2/sqrt(R0) = (1 - v_n - 2) / sqrt(R0) =
        ## = (v_n - 1) / sqrt(R0)
        ## => S_k_n = b_k / a_n = v_k | k != n
        ## S_n_n = b_n / a_n = v_n - 1
        ##
        ##
        toolkit = self.toolkit

        # Reference impedance
        g0 = 1

        N = len(self.ports)

        portnumbers = range(N)

        S = np.zeros((N, N), dtype=object)

        circuit = copy(self.cir)

        refnode = self.ports[0][1]

        ## Place power sources at the ports
        for n, sourceport in enumerate(self.ports):
            circuit["_is%d" % n] = ISInternal(sourceport[1], sourceport[0], i=0, iac=0, toolkit=toolkit)
            circuit["_rl%d" % n] = G(sourceport[1], sourceport[0], g=g0, noisy=False, toolkit=toolkit)

        if toolkit.symbolic:
            ## For now just one frequency is allowed
            assert not isiterable(freqs)

            Gmat, C, CY, u, x, ss = dc_steady_state(
                circuit, freqs, refnode, toolkit, complexfreq=complexfreq, epar=self.epar
            )
            ## 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)
            Gmat, C, CY, u = remove_row_col((Gmat, C, CY, u), irefnode, toolkit)

            Y = C * ss + Gmat
            detY = toolkit.det(Y)

        for n, sourceport in enumerate(self.ports):
            ## Add stimulus to the port
            circuit["_is%d" % n].ipar.iac = 2 * g0

            ## If symbolic the s-parameters are calculated using co-factors
            if toolkit.symbolic:
                u_wrefnode = circuit.u(x, analysis="internalac", epar=self.epar)
                (u,) = circuit.remove_refnode((u_wrefnode,), refnode)
                ## Calculate s-parameters using cofactors
                for k, port in enumerate(self.ports):
                    resname = "v(%s,%s)" % (port[0], port[1])

                    res = linearsolver_partial(Y, u, refnode, [resname], circuit, toolkit, detY=detY)
                    if k == n:
                        S[k, n] = res[resname] - 1
                    else:
                        S[k, n] = res[resname]

            else:
                ## Run AC-analysis
                acana = AC(circuit, toolkit=toolkit, analysis="internalac")
                res = acana.solve(freqs, refnode=refnode, complexfreq=complexfreq)
                ## Obtain s-parameters
                for k, port in enumerate(self.ports):
                    if k == n:
                        S[k, n] = res.v(port[0], port[1]) - 1
                    else:
                        S[k, n] = res.v(port[0], port[1])

            ## Clear stimulus to the port
            circuit["_is%d" % n].ipar.iac = 0

        ## Find noise wave correlation matrix
        ## The method works as follows:
        ## 1. terminate all ports with z0
        ## 2. calculate transimpedances from a current source in each node
        ##    to the port voltages by using the adjoint Y-matrix.
        ##    As seen above the outgoing wave b is b=V(port_k) / sqrt(z0)
        ##    for a terminated port.
        ## 3. Form a transform matrix T where the columns are the transimpedance
        ##    vectors divided by sqrt(z0)
        ## 4. Calculate the correlation matrix as:
        ##    CS = T * CY * T+

        ## Calculate transimpedances
        branchlist = [Branch(*port) for port in self.ports]

        transimpana = TransimpedanceAnalysis(circuit, toolkit=toolkit)

        zmlist = transimpana.solve(freqs, branchlist, refnode=refnode, complexfreq=complexfreq)

        T = np.matrix(zmlist) * g0 ** 0.5

        ## Complex frequency variable
        if complexfreq:
            s = freqs
        else:
            s = 2j * np.pi * freqs

        ## Calculate CY of circuit
        x = np.zeros(circuit.n)
        CY = circuit.CY(x, np.imag(s), epar=self.epar)
        irefnode = circuit.get_node_index(refnode)
        CY, = remove_row_col((CY,), irefnode, self.toolkit)

        ## Calculate noise wave correlation matrix
        CS = np.array(T * CY * T.H)

        return NPortS(S, CS, z0=1 / toolkit.integer(g0))