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())
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())
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())
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())
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())
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())