Beispiel #1
0
    def run(self, circuit):
        """
        Calculates a DC sweep by solving nodal equations

        The parameter to be swept is specified in the analysis options
        """
        # for now just print some fixed stuff
        print('******************************************************')
        print('                 DC sweep analysis')
        print('******************************************************')
        if hasattr(circuit, 'title'):
            print('\n', circuit.title, '\n')

        if glVar.sparse:
            nd = nodalSP
        else:
            nd = nodal
            print('Using dense matrices\n')

        # Only works with flattened circuits
        if not circuit._flattened:
            circuit.flatten()
            circuit.init()

        # get device (if any)
        paramunit = None
        # tempFlag indicates if we are doing a global temperature sweep
        tempFlag = False
        if self.device:
            # Device specified, try to find it
            try:
                dev = circuit.elemDict[self.device]
            except KeyError:
                raise analysis.AnalysisError('Could not find: {0}'.format(
                    self.device))
            if self.param:
                try:
                    pinfo = dev.paramDict[self.param]
                except KeyError:
                    raise analysis.AnalysisError('Unrecognized parameter: ' +
                                                 self.param)
                else:
                    if not pinfo[2] == float:
                        raise analysis.AnalysisError(
                            'Parameter must be float: ' + self.param)
            else:
                raise analysis.AnalysisError(
                    "Don't know what parameter to sweep!")
            paramunit = pinfo[1]
        else:
            # No device, check if temperature sweep
            if self.param != 'temp':
                raise analysis.AnalysisError(
                    'Only temperature sweep supported if no device specified')
            paramunit = 'C'
            tempFlag = True

        # Create nodal object: for now assume devices do not change
        # topology during sweep
        nd.make_nodal_circuit(circuit)
        dc = nd.DCNodal(circuit)
        x = dc.get_guess()

        sweepvar = np.linspace(start=self.start, stop=self.stop, num=self.num)
        circuit.dC_sweep = sweepvar
        if tempFlag:
            circuit.dC_var = 'Global temperature sweep: temp'
        else:
            circuit.dC_var = 'Device: ' + dev.instanceName \
                + '  Parameter: ' + self.param
        circuit.dC_unit = paramunit
        print('System dimension: {0}'.format(circuit.nD_dimension))
        print('Sweep: ', circuit.dC_var)

        xVec = np.zeros((circuit.nD_dimension, self.num))
        tIter = 0
        tRes = 0.
        for i, value in enumerate(sweepvar):
            if tempFlag:
                for elem in circuit.nD_elemList:
                    # Only sweep temperature if not explicitly given
                    # for a device
                    if not elem.is_set('temp'):
                        try:
                            elem.set_temp_vars(value)
                        except AttributeError:
                            # It is OK if element independent of temperature
                            pass
            else:
                setattr(dev, self.param, value)
                # re-process parameters (topology must not change, for
                # now at least)
                dev.process_params()
                # Re-generate nodal attributes.
                nd.restore_RCnumbers(dev)
                nd.process_nodal_element(dev, circuit)

            # re-process linear matrix
            dc.refresh()
            sV = dc.get_source()

            # solve equations
            try:
                (x, res, iterations) = solve(x, sV, dc.convergence_helpers)
            except NoConvergenceError as ce:
                print(ce)
                return
            # Save result
            xVec[:, i] = x
            # Keep some info about iterations
            tIter += iterations
            tRes += res
            if self.verbose:
                print('{0} = {1}'.format(self.param, value))
                print('Number of iterations = ', iterations)
                print('Residual = ', res)

        # Calculate average residual and iterations
        avei = tIter / len(sweepvar)
        aver = tRes / len(sweepvar)
        print('Average iterations: {0}'.format(avei))
        print('Average residual: {0}\n'.format(aver))

        # Save results in nodes
        circuit.nD_ref.dC_v = np.zeros(self.num)
        for i, term in enumerate(circuit.nD_termList):
            term.dC_v = xVec[i, :]

        # Restore original attribute values ------------------------
        if tempFlag:
            for elem in circuit.nD_elemList:
                if not elem.is_set('temp'):
                    elem.set_attributes()
                    try:
                        elem.set_temp_vars(value)
                    except AttributeError:
                        # It is OK if element independent of temperature
                        pass
        else:
            dev.set_attributes()
            # re-process parameters (topology must not change, for
            # now at least)
            dev.process_params()
            # Re-generate nodal attributes.
            nd.restore_RCnumbers(dev)
            nd.process_nodal_element(dev, circuit)
        # -----------------------------------------------------------

        # Process output requests.
        analysis.process_requests(
            circuit, 'dc', sweepvar,
            '{0} [{1}]'.format(circuit.dC_var, circuit.dC_unit), 'dC_v')

        def getvec(termname):
            return circuit.find_term(termname).dC_v

        if self.shell:
            analysis.ipython_drop(
                """
Available commands:
    sweepvar: vector with swept parameter
    getvec(<terminal>) to retrieve results
""", globals(), locals())
Beispiel #2
0
    def run(self, circuit):
        """
        Calculates a AC sweep by solving nodal equations around

        The parameter to be swept is specified in the analysis options
        """
        # for now just print some fixed stuff
        print('******************************************************')
        print('                 AC sweep analysis')
        print('******************************************************')
        if hasattr(circuit, 'title'):
            print('\n', circuit.title, '\n')

        # Only works with flattened circuits
        if not circuit._flattened:
            circuit.flatten()
            circuit.init()

        nd.make_nodal_circuit(circuit)
        dc = nd.DCNodal(circuit)
        x0 = dc.get_guess()
        sV = dc.get_source()
        print('System dimension: {0}'.format(circuit.nD_dimension))
        # solve equations
        try: 
            print('Calculating DC operating point ... ', end='')
            sys.stdout.flush()
            (x, res, iterations) = solve(x0, sV, dc.convergence_helpers)
            print('Succeded.\n')
        except NoConvergenceError as ce:
            print('Failed.\n')
            print(ce)
            return
        dc.save_OP(x)

        # Create frequency vector
        if self.log:
            fvec = np.logspace(start = np.log10(self.start), 
                               stop = np.log10(self.stop), 
                               num = self.num)
        else:
            fvec = np.linspace(start = self.start, 
                               stop = self.stop, 
                               num = self.num)

        # Perform analysis
        nd.run_AC(circuit, fvec)

        # Process output requests.  
        analysis.process_requests(circuit, 'ac', 
                                  fvec, 'Frequency [Hz]',
                                  'aC_V', log = self.log)
        analysis.process_requests(circuit, 'ac_mag', 
                                  fvec, 'Frequency [Hz]',
                                  'aC_V', lambda x: abs(x), log = self.log)
        analysis.process_requests(circuit, 'ac_phase', 
                                  fvec, 'Frequency [Hz]',
                                  'aC_V', 
                                  lambda v: 180./np.pi * np.angle(v),
                                  'degrees', self.log)
        analysis.process_requests(circuit, 'ac_dB', 
                                  fvec, 'Frequency [Hz]',
                                  'aC_V', 
                                  lambda v: 20. * np.log10(v),
                                  'dB', self.log)

        def getvec(termname):
            return circuit.termDict[termname].aC_V

        if self.shell:
            analysis.ipython_drop("""
Available commands:
    fvec: frequency vector
    getvec(<terminal>) to retrieve AC result vector
""", globals(), locals())
Beispiel #3
0
    def run(self, circuit):
        """
        Calculates transient analysis by solving nodal equations
        """
        # for now just print some fixed stuff
        print('******************************************************')
        print('                 Transient analysis')
        print('******************************************************')
        if hasattr(circuit, 'title'):
            print('\n', circuit.title, '\n')

        if glVar.sparse:
            nd = nodalSP
        else:
            nd = nodal
            print('Using dense matrices\n')

        # Only works with flattened circuits
        if not circuit._flattened:
            circuit.flatten()
            circuit.init()

        # Select integration method
        if self.im == 'BE':
            imo = BEuler()
        elif self.im == 'trap':
            imo = Trapezoidal()
        else:
            raise analysis.AnalysisError(
                'Unknown integration method: {0}'.format(self.im))

        # Create nodal objects and solve for initial state
        nd.make_nodal_circuit(circuit)
        dc = nd.DCNodal(circuit)
        tran = nd.TransientNodal(circuit, imo)
        x = dc.get_guess()
        # Use sources including transient values for t == 0
        sV = tran.get_source(0.)
        # solve DC equations
        try: 
            print('Calculating DC operating point ... ', end='')
            sys.stdout.flush()
            (x, res, iterations) = solve(x, sV, dc.convergence_helpers)
            print('Succeded.\n')
        except NoConvergenceError as ce:
            print('Failed.\n')
            print(ce)
            return
        dc.save_OP(x)
        tran.set_IC(self.tstep)
        # Release memory in dc object?
        del(dc)

        # Create time vector
        timeVec = np.arange(start=0., stop = self.tstop, step = self.tstep, 
                            dtype=float)
        nsamples = len(timeVec)
        circuit.tran_timevec = timeVec

        # Get terminals to plot/save from circuit. 
        termSet = circuit.get_requested_terms('tran')

        # Special treatment for ground terminal
        termSet1 = set(termSet)
        if circuit.nD_ref in termSet1:
            termSet1.remove(circuit.nD_ref)
            circuit.nD_ref.tran_v = np.zeros(nsamples)

        # Allocate vectors for results
        if self.saveall:
            for term in circuit.nD_termList:
                term.tran_v = np.empty(nsamples)
                term.tran_v[0] = x[term.nD_namRC]                
            circuit.nD_ref.tran_v = np.zeros(nsamples)
        else:
            # Only save requested nodes
            for term in termSet1:
                term.tran_v = np.empty(nsamples)
                term.tran_v[0] = x[term.nD_namRC]

        # Save initial values
        xOld = x
        tIter = 0
        tRes = 0.
        dots = 50
        print('System dimension: {0}'.format(circuit.nD_dimension))
        print('Number of samples: {0}'.format(nsamples))
        print('Integration method: {0}'.format(self.im))
        if self.verbose:
            print('-------------------------------------------------')
            print(' Step    | Time (s)     | Iter.    | Residual    ')
            print('-------------------------------------------------')
        else:
            print('Printing one dot every {0} samples:'.format(dots))
            sys.stdout.flush()

        for i in xrange(1, nsamples):
            tran.accept(xOld)
            sV = tran.get_rhs(timeVec[i])
            # solve equations: use previous time-step solution as an
            # initial guess
            if i > 1:
                # Re-use factorized Jacobian: This saves the time to
                # evaluate the function and Jacobian plus the time for
                # factorization. Only sparse implementation stores
                # factorized Jacobian
                xOld -= tran.get_chord_deltax(sV)
            try: 
                (x, res, iterations) = solve(xOld, sV, 
                                             tran.convergence_helpers)
            except NoConvergenceError as ce:
                print(ce)
                return

            # Save results
            xOld[:] = x
            if self.saveall:
                for term in circuit.nD_termList:
                    term.tran_v[i] = x[term.nD_namRC]                
            else:
                # Only save requested nodes
                for term in termSet1:
                    term.tran_v[i] = x[term.nD_namRC]
            # Keep some info about iterations
            tIter += iterations
            tRes += res
            if self.verbose:
                print('{0:8} | {1:12} | {2:8} | {3:12}'.format(
                        i, timeVec[i], iterations, res))
            elif not i%dots:
                print('.', end='')
                sys.stdout.flush()

        # Calculate average residual and iterations
        avei = float(tIter) / nsamples
        aver = tRes / nsamples
        print('\nAverage iterations: {0}'.format(avei))
        print('Average residual: {0}\n'.format(aver))

        # Process output requests.  
        analysis.process_requests(circuit, 'tran', 
                                  timeVec, 'Time [s]', 'tran_v')

        def getvec(termname):
            return circuit.find_term(termname).tran_v

        if self.shell:
            analysis.ipython_drop("""
Available commands:
    timeVec: time vector
    getvec(<terminal>) to retrieve results (if result saved)
""", globals(), locals())
Beispiel #4
0
    def run(self, circuit):
        """
        Calculates transient analysis by solving nodal equations
        """
        # for now just print some fixed stuff
        print('******************************************************')
        print('                 Transient analysis')
        print('******************************************************')
        if hasattr(circuit, 'title'):
            print('\n', circuit.title, '\n')

        if glVar.sparse:
            nd = nodalSP
        else:
            nd = nodal
            print('Using dense matrices\n')

        # Only works with flattened circuits
        if not circuit._flattened:
            circuit.flatten()
            circuit.init()

        # Select integration method
        if self.im == 'BE':
            imo = BEuler()
        elif self.im == 'trap':
            imo = Trapezoidal()
        else:
            raise analysis.AnalysisError(
                'Unknown integration method: {0}'.format(self.im))

        # Create nodal objects and solve for initial state
        nd.make_nodal_circuit(circuit)
        dc = nd.DCNodal(circuit)
        tran = nd.TransientNodal(circuit, imo)
        x = dc.get_guess()
        # Use sources including transient values for t == 0
        sV = tran.get_source(0.)
        # solve DC equations
        try: 
            print('Calculating DC operating point ... ', end='')
            sys.stdout.flush()
            (x, res, iterations) = solve(x, sV, dc.convergence_helpers)
            print('Succeded.\n')
        except NoConvergenceError as ce:
            print('Failed.\n')
            print(ce)
            return
        dc.save_OP(x)
        tran.set_IC(self.tstep)
        # Release memory in dc object?
        del(dc)

        # Create time vector
        timeVec = np.arange(start=0., stop = self.tstop, step = self.tstep, 
                            dtype=float)
        nsamples = len(timeVec)
        circuit.tran_timevec = timeVec

        # Get terminals to plot/save from circuit. 
        termSet = circuit.get_requested_terms('tran')

        # Special treatment for ground terminal
        termSet1 = set(termSet)
        if circuit.nD_ref in termSet1:
            termSet1.remove(circuit.nD_ref)
            circuit.nD_ref.tran_v = np.zeros(nsamples)

        # Allocate vectors for results
        if self.saveall:
            for term in circuit.nD_termList:
                term.tran_v = np.empty(nsamples)
                term.tran_v[0] = x[term.nD_namRC]                
            circuit.nD_ref.tran_v = np.zeros(nsamples)
        else:
            # Only save requested nodes
            for term in termSet1:
                term.tran_v = np.empty(nsamples)
                term.tran_v[0] = x[term.nD_namRC]

        # Save initial values
        xOld = x
        tIter = 0
        tRes = 0.
        dots = 50
        print('System dimension: {0}'.format(circuit.nD_dimension))
        print('Number of samples: {0}'.format(nsamples))
        print('Integration method: {0}'.format(self.im))
        if self.verbose:
            print('-------------------------------------------------')
            print(' Step    | Time (s)     | Iter.    | Residual    ')
            print('-------------------------------------------------')
        else:
            print('Printing one dot every {0} samples:'.format(dots))
            sys.stdout.flush()

        for i in xrange(1, nsamples):
            tran.accept(xOld)
            sV = tran.get_rhs(timeVec[i])
            # solve equations: use previous time-step solution as an
            # initial guess
            if i > 1:
                # Re-use factorized Jacobian: This saves the time to
                # evaluate the function and Jacobian plus the time for
                # factorization. Only sparse implementation stores
                # factorized Jacobian
                xOld += tran.get_chord_deltax(sV)
            try: 
                (x, res, iterations) = solve(xOld, sV, 
                                             tran.convergence_helpers)
            except NoConvergenceError as ce:
                print(ce)
                return

            # Save results
            xOld[:] = x
            if self.saveall:
                for term in circuit.nD_termList:
                    term.tran_v[i] = x[term.nD_namRC]                
            else:
                # Only save requested nodes
                for term in termSet1:
                    term.tran_v[i] = x[term.nD_namRC]
            # Keep some info about iterations
            tIter += iterations
            tRes += res
            if self.verbose:
                print('{0:8} | {1:12} | {2:8} | {3:12}'.format(
                        i, timeVec[i], iterations, res))
            elif not i%dots:
                print('.', end='')
                sys.stdout.flush()

        # Calculate average residual and iterations
        avei = float(tIter) / nsamples
        aver = tRes / nsamples
        print('\nAverage iterations: {0}'.format(avei))
        print('Average residual: {0}\n'.format(aver))

        # Process output requests.  
        analysis.process_requests(circuit, 'tran', 
                                  timeVec, 'Time [s]', 'tran_v')

        def getvec(termname):
            return circuit.find_term(termname).tran_v

        if self.shell:
            analysis.ipython_drop("""
Available commands:
    timeVec: time vector
    getvec(<terminal>) to retrieve results (if result saved)
""", globals(), locals())
Beispiel #5
0
    def run(self, circuit):
        """
        Calculates a DC sweep by solving nodal equations

        The parameter to be swept is specified in the analysis options
        """
        # for now just print some fixed stuff
        print('******************************************************')
        print('                 DC sweep analysis')
        print('******************************************************')
        if hasattr(circuit, 'title'):
            print('\n', circuit.title, '\n')

        if glVar.sparse:
            nd = nodalSP
        else:
            nd = nodal
            print('Using dense matrices\n')

        # Only works with flattened circuits
        if not circuit._flattened:
            circuit.flatten()
            circuit.init()

        # get device (if any)
        paramunit = None
        # tempFlag indicates if we are doing a global temperature sweep
        tempFlag = False
        if self.device:
            # Device specified, try to find it
            try:
                dev = circuit.elemDict[self.device]
            except KeyError: 
                raise analysis.AnalysisError(
                    'Could not find: {0}'.format(self.device))
            if self.param:
                try:
                    pinfo = dev.paramDict[self.param]
                except KeyError:
                    raise analysis.AnalysisError('Unrecognized parameter: ' 
                                                 + self.param)
                else:
                    if not pinfo[2] == float:
                        raise analysis.AnalysisError(
                            'Parameter must be float: ' + self.param)
            else:
                raise analysis.AnalysisError(
                    "Don't know what parameter to sweep!")
            paramunit = pinfo[1]
        else:
            # No device, check if temperature sweep
            if self.param != 'temp':
                raise analysis.AnalysisError(
                    'Only temperature sweep supported if no device specified')
            paramunit = 'C'
            tempFlag = True

        # Create nodal object: for now assume devices do not change
        # topology during sweep
        nd.make_nodal_circuit(circuit)
        dc = nd.DCNodal(circuit)
        x = dc.get_guess()

        sweepvar = np.linspace(start = self.start, stop = self.stop, 
                               num = self.num)
        circuit.dC_sweep = sweepvar
        if tempFlag:
            circuit.dC_var = 'Global temperature sweep: temp'
        else:
            circuit.dC_var = 'Device: ' + dev.instanceName \
                + '  Parameter: ' + self.param
        circuit.dC_unit = paramunit
        print('System dimension: {0}'.format(circuit.nD_dimension))
        print('Sweep: ', circuit.dC_var)
        
        xVec = np.zeros((circuit.nD_dimension, self.num))
        tIter = 0
        tRes = 0.
        for i, value in enumerate(sweepvar):
            if tempFlag:
                for elem in circuit.nD_elemList:
                    # Only sweep temperature if not explicitly given
                    # for a device
                    if not elem.is_set('temp'):
                        try:
                            elem.set_temp_vars(value)
                        except AttributeError:
                            # It is OK if element independent of temperature
                            pass
            else:
                setattr(dev, self.param, value)
                # re-process parameters (topology must not change, for
                # now at least)
                dev.process_params()
                # Re-generate nodal attributes. 
                nd.restore_RCnumbers(dev)
                nd.process_nodal_element(dev, circuit)

            # re-process linear matrix
            dc.refresh()
            sV = dc.get_source()

            # solve equations
            try: 
                (x, res, iterations) = solve(x, sV, dc.convergence_helpers)
            except NoConvergenceError as ce:
                print(ce)
                return
            # Save result
            xVec[:,i] = x
            # Keep some info about iterations
            tIter += iterations
            tRes += res
            if self.verbose:
                print('{0} = {1}'.format(self.param , value))
                print('Number of iterations = ', iterations)
                print('Residual = ', res)

        # Calculate average residual and iterations
        avei = tIter / len(sweepvar)
        aver = tRes / len(sweepvar)
        print('Average iterations: {0}'.format(avei))
        print('Average residual: {0}\n'.format(aver))

        # Save results in nodes
        circuit.nD_ref.dC_v = np.zeros(self.num)
        for i,term in enumerate(circuit.nD_termList):
            term.dC_v = xVec[i,:]

        # Restore original attribute values ------------------------
        if tempFlag:
            for elem in circuit.nD_elemList:
                if not elem.is_set('temp'):
                    elem.set_attributes()
                    try:
                        elem.set_temp_vars(value)
                    except AttributeError:
                        # It is OK if element independent of temperature
                        pass
        else:
            dev.set_attributes()
            # re-process parameters (topology must not change, for
            # now at least)
            dev.process_params()
            # Re-generate nodal attributes. 
            nd.restore_RCnumbers(dev)
            nd.process_nodal_element(dev, circuit)
        # -----------------------------------------------------------

        # Process output requests.  
        analysis.process_requests(circuit, 'dc', sweepvar, 
                                  '{0} [{1}]'.format(circuit.dC_var, 
                                                     circuit.dC_unit), 
                                  'dC_v')

        def getvec(termname):
            return circuit.find_term(termname).dC_v

        if self.shell:
            analysis.ipython_drop("""
Available commands:
    sweepvar: vector with swept parameter
    getvec(<terminal>) to retrieve results
""", globals(), locals())
Beispiel #6
0
    def run(self, circuit):
        """
        Calculates a AC sweep by solving nodal equations around

        The parameter to be swept is specified in the analysis options
        """
        # for now just print some fixed stuff
        print('******************************************************')
        print('                 AC sweep analysis')
        print('******************************************************')
        if hasattr(circuit, 'title'):
            print('\n', circuit.title, '\n')

        # Only works with flattened circuits
        if not circuit._flattened:
            circuit.flatten()
            circuit.init()

        nd.make_nodal_circuit(circuit)
        dc = nd.DCNodal(circuit)
        x0 = dc.get_guess()
        sV = dc.get_source()
        print('System dimension: {0}'.format(circuit.nD_dimension))
        # solve equations
        try:
            print('Calculating DC operating point ... ', end='')
            sys.stdout.flush()
            (x, res, iterations) = solve(x0, sV, dc.convergence_helpers)
            print('Succeded.\n')
        except NoConvergenceError as ce:
            print('Failed.\n')
            print(ce)
            return
        dc.save_OP(x)

        # Create frequency vector
        if self.log:
            fvec = np.logspace(start=np.log10(self.start),
                               stop=np.log10(self.stop),
                               num=self.num)
        else:
            fvec = np.linspace(start=self.start, stop=self.stop, num=self.num)

        # Perform analysis
        nd.run_AC(circuit, fvec)

        # Process output requests.
        analysis.process_requests(circuit,
                                  'ac',
                                  fvec,
                                  'Frequency [Hz]',
                                  'aC_V',
                                  log=self.log)
        analysis.process_requests(circuit,
                                  'ac_mag',
                                  fvec,
                                  'Frequency [Hz]',
                                  'aC_V',
                                  lambda x: abs(x),
                                  log=self.log)
        analysis.process_requests(circuit, 'ac_phase', fvec, 'Frequency [Hz]',
                                  'aC_V', lambda v: 180. / np.pi * np.angle(v),
                                  'degrees', self.log)
        analysis.process_requests(circuit, 'ac_dB', fvec, 'Frequency [Hz]',
                                  'aC_V', lambda v: 20. * np.log10(v), 'dB',
                                  self.log)

        def getvec(termname):
            return circuit.find_term(termname).aC_V

        if self.shell:
            analysis.ipython_drop(
                """
Available commands:
    fvec: frequency vector
    getvec(<terminal>) to retrieve AC result vector
""", globals(), locals())