def solve(self, refnode=gnd, period=1e-3, x0=None, timestep=1e-6, maxiterations=20): self.period = period toolkit = self.toolkit irefnode = self.cir.get_node_index(refnode) n = self.cir.n dt = timestep if x0 is None: x = toolkit.zeros(n - 1) # currently without reference node ! else: x = x0 # reference node not included ! # create vector with timepoints and a more fitting dt times, dt = toolkit.linspace(0, period, num=int(period / dt), endpoint=True, retstep=True) alpha = 1 def func(x): x = self.solve_timestep(x, times[0], dt) x0 = copy(x) Jshoot = np.mat(toolkit.eye(n - 1)) C = copy(np.mat(self._C)) ## Save C and transient jacobian for PAC analysis self.Cvec = [copy(self._C)] self.Jtvec = [copy(self._Jf)] self.times = times for t in times[1:]: x = copy(self.solve_timestep(x, t, dt)) self.Cvec.append(copy(self._C)) self.Jtvec.append(copy(self._Jf)) Jshoot = np.mat(self._Jf).I * C * Jshoot C = copy(np.mat(self._C)) residual = x0 - x D = np.mat(toolkit.eye(n - 1)) return residual, D - alpha * Jshoot ## Find periodic steady state x-vector x0_ss = analysis.fsolve(func, x, maxiter=maxiterations, toolkit=self.toolkit) X = [x0_ss] for t in times: x = self.solve_timestep(X[-1], t, dt) X.append(copy(x)) X = toolkit.array(X[1:]).T # Insert reference node voltage X = toolkit.concatenate((X[:irefnode], toolkit.zeros((1, len(times))), X[irefnode:])) tpss = analysis.CircuitResult(self.cir, x=X, xdot=None, sweep_values=times, sweep_label="time", sweep_unit="s") freqs, FX = freq_analysis(X[:, :-1], times[:-1]) fpss = analysis.CircuitResult( self.cir, x=FX, xdot=None, sweep_values=freqs, sweep_label="freq", sweep_unit="Hz" ) return InternalResultDict({"tpss": tpss, "fpss": fpss})
def solve_timestep(self, x0, t, dt, refnode=gnd): toolkit = self.toolkit concatenate, array = toolkit.concatenate, toolkit.array n = self.cir.n analysis_name = self.par.analysis ## 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) def func(x): x = concatenate((x[:irefnode], array([0.0]), x[irefnode:])) xlast = concatenate((x0[:irefnode], array([0.0]), x0[irefnode:])) C = self.cir.C(x) Geq = C / dt ueq = -self.cir.q(xlast) / dt f = self.cir.i(x) + self.cir.q(x) / dt + self.cir.u( t, analysis=analysis_name) + ueq J = self.cir.G(x) + Geq (f, J, C) = remove_row_col((f, J, C), irefnode, self.toolkit) self._Jf, self._C = J, C return f, J x = analysis.fsolve(func, x0, reltol=self.par.reltol, toolkit=self.toolkit) # Insert reference node voltage #x = concatenate((x[:irefnode], array([0.0]), x[irefnode:])) return x
def solve_timestep(self, x0, t, dt, refnode=gnd): toolkit = self.toolkit concatenate, array = toolkit.concatenate, toolkit.array n = self.cir.n analysis_name = self.par.analysis ## 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) def func(x): x = concatenate((x[:irefnode], array([0.0]), x[irefnode:])) xlast = concatenate((x0[:irefnode], array([0.0]), x0[irefnode:])) C = self.cir.C(x) Geq = C / dt ueq = -self.cir.q(xlast) / dt f = self.cir.i(x) + self.cir.q(x) / dt + self.cir.u(t, analysis=analysis_name) + ueq J = self.cir.G(x) + Geq (f, J, C) = remove_row_col((f, J, C), irefnode, self.toolkit) self._Jf, self._C = J, C return f, J x = analysis.fsolve(func, x0, reltol=self.par.reltol, toolkit=self.toolkit) # Insert reference node voltage # x = concatenate((x[:irefnode], array([0.0]), x[irefnode:])) return x
def solve(self, refnode=gnd, period=1e-3, x0=None, timestep=1e-6, maxiterations=20): self.period = period toolkit = self.toolkit irefnode = self.cir.get_node_index(refnode) n = self.cir.n dt = timestep if x0 is None: x = toolkit.zeros(n - 1) #currently without reference node ! else: x = x0 # reference node not included ! #create vector with timepoints and a more fitting dt times, dt = toolkit.linspace(0, period, num=int(period / dt), endpoint=True, retstep=True) alpha = 1 def func(x): x = self.solve_timestep(x, times[0], dt) x0 = copy(x) Jshoot = np.mat(toolkit.eye(n - 1)) C = copy(np.mat(self._C)) ## Save C and transient jacobian for PAC analysis self.Cvec = [copy(self._C)] self.Jtvec = [copy(self._Jf)] self.times = times for t in times[1:]: x = copy(self.solve_timestep(x, t, dt)) self.Cvec.append(copy(self._C)) self.Jtvec.append(copy(self._Jf)) Jshoot = np.mat(self._Jf).I * C * Jshoot C = copy(np.mat(self._C)) residual = x0 - x D = np.mat(toolkit.eye(n - 1)) return residual, D - alpha * Jshoot ## Find periodic steady state x-vector x0_ss = analysis.fsolve(func, x, maxiter=maxiterations, toolkit=self.toolkit) X = [x0_ss] for t in times: x = self.solve_timestep(X[-1], t, dt) X.append(copy(x)) X = toolkit.array(X[1:]).T # Insert reference node voltage X = toolkit.concatenate((X[:irefnode], toolkit.zeros( (1, len(times))), X[irefnode:])) tpss = analysis.CircuitResult(self.cir, x=X, xdot=None, sweep_values=times, sweep_label='time', sweep_unit='s') freqs, FX = freq_analysis(X[:, :-1], times[:-1]) fpss = analysis.CircuitResult(self.cir, x=FX, xdot=None, sweep_values=freqs, sweep_label='freq', sweep_unit='Hz') return InternalResultDict({'tpss': tpss, 'fpss': fpss})