def __pade_approximation(self, nodeName, L, M, debug=0): assert L == M - 1 num_moments = L+M+1 if debug: "DATA L=%s M=%s num_moments=%s" % (L, M, num_moments) if debug: print "num_moments", num_moments #scaling = 766423.0 node_index = self.TranslateNode(nodeName) node_moments = [] # step 1: calculate the Moments g_inverse = numpy.linalg.inverse(self.G) if debug: print "g_inverse", g_inverse last_moment = numpy.matrixmultiply(g_inverse, self.B) if debug: print "last_moment", last_moment, node_index node_moments.append(last_moment[node_index-1][0]) # test commit for i in range(num_moments-1): intermediate = -1 * numpy.matrixmultiply(g_inverse, self.C) last_moment = numpy.matrixmultiply( intermediate, last_moment ) moment = self.Scaling * last_moment[node_index-1][0] node_moments.append(moment) last_moment = self.Scaling * last_moment if debug: print "last_moment", last_moment print "suggested scaling =", node_moments[0]/node_moments[1] if debug: print "node_moments=", node_moments # Call the general pade algorithm a_coef, b_coef = MathHelpers.my_pade(node_moments, complex=False) # Return results return a_coef, b_coef, node_moments
def __tran_awe(self, name, nodeName, L, M, stop, step, mode, size, tr, width): # stop : stopping time # step: size of the time step # L: order of the numerator # M: order of the denominator # mode: one of "IMPULSE", "IDEAL_STEP", "STEP", "PULSE", "RAMP" # size: height of the step or pulse # tr: rise and fall time of the STEP or PULSE # width: width of the PULSE self.__CurAnalysis = self.AC a_coef, b_coef, node_moments = self.__pade_approximation(\ nodeName, L, M, debug=0) # now, calculate the poles of the sequence poles = MathHelpers.zroots(1j*b_coef, sort=0) print "L=%s M=%s POLES=%s" % (L, M, poles) # calculate the residues of the sequence # using the formula given in the paper p_rows = [] for i in range(M+1): p_rows.append([]) for j in range(M): p_rows[i].append(poles[j]**-(i+1)) if i == 0: p_rows[i].append(-1+0j) else: p_rows[i].append(0+0j) p_matrix = numpy.array(p_rows) rhs = -1*numpy.array(node_moments[0:L+2]) residues = numpy.linalg.solve_linear_equations( p_matrix, rhs ) #NOTE: residues are in the form: [k1, k2, ... km, c] # : poles are in the form: [p1, p2, ... pm] # i.e. H(s) = c + (k1 / (s+p1)) + (k2 / (s+p2)) + ... # L-1{ H(s) } = c*sigma(t) + k1*exp(-p1*t) + k2*exp(-p2*t) = h(t) # L-1{ H(s) / s } = INTEGRAL{ h(t) } # The residues actually contains both the actual residues # and the direct coupling c impulse = residues[-1] residues = residues[0:-1] # Now we calculate all of the responses that we may need # first, record the impulse response c0, poles0, residues0 = [], copy.copy(poles), copy.copy(residues) c0.insert(0, impulse) # integrate once to get step response and record c, poles, residues = MathHelpers.integrate([], poles, residues, impulse) c1, poles1, residues1 = copy.copy(c), copy.copy(poles), \ copy.copy(residues) c1.insert(0, 0.0) # integrate again to get the ramp response and record c2, poles2, residues2 = MathHelpers.integrate(c, poles, residues) c2.insert(0, 0.0) # Setup some shorthands and calculate required values impulse_response = lambda t: MathHelpers.pole_residue_solver(\ t*self.Scaling, c0, poles0, residues0) step_response = lambda t: MathHelpers.pole_residue_solver(\ t*self.Scaling, c1, poles1, residues1) ramp_response = lambda t: MathHelpers.pole_residue_solver(\ t*self.Scaling, c2, poles2, residues2) u = MathHelpers.step_function slope = (size / tr) / self.Scaling # Calculate the answers by looping through the time # steps result = [] for i in range(int(stop/step)): t = step*i k = slope if mode == "ramp": answer = k * ramp_response(t) elif mode == "impulse": answer = impulse_response(t) elif mode == "step": answer = k * ramp_response(t) \ - k * ramp_response(t-tr) * u(t-tr) elif mode == "ideal_step": answer = size * step_response(t) elif mode == "pulse": answer = answer3 = k * ramp_response(t) \ - k * ramp_response(t-tr) * u(t-tr) \ - k * ramp_response(t-tr-width) * u(t-tr-width) \ + k * ramp_response(t-2*tr-width) * u(t-2*tr-width) else: assert 0, "UNRECOGNIZED MODE %s" % mode # Add the (time, answer) pair... NOTE: we must # extract the real value from the answer result.append((t, answer.real)) # Add the results to the most recent plot g = self.__Plotter g("set output \"data.ps\"") g("set terminal postscript color") g("set terminal postscript solid") d = Gnuplot.Data(result, title='AWE(%s/%s)' % (L,M), with='lines')