Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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')