Ejemplo n.º 1
0
Archivo: bfpss.py Proyecto: vovkd/ahkab
def bfpss(circ, period, step=None, mna=None, Tf=None, D=None, points=None, autonomous=False, x0=None,  data_filename='stdout', vector_norm=lambda v: max(abs(v)), verbose=3):
	"""Performs a PSS analysis. 
	
	Time step is constant, IE will be used as DF
	
	Parameters:
	circ is the circuit description class
	period is the period of the solution
	mna, D, Tf are not compulsory they will be computed if they're set to None
	step is the time step between consecutive points
	points is the number of points to be used
	step and points are mutually exclusive options:
	- if step is specified, the number of points will be automatically determined 
	- if points is set, the step will be automatically determined
	- if none of them is set, options.shooting_default_points will be used as points
	autonomous has to be False, autonomous circuits are not supported
	x0 is the initial guess to be used. Needs work.
	data_filename is the output filename. Defaults to stdout.
	verbose is set to zero (print errors only) if datafilename == 'stdout'.

	Returns: nothing
	"""
	if data_filename == "stdout":
		verbose = 0
	
	printing.print_info_line(("Starting periodic steady state analysis:",3), verbose)
	printing.print_info_line(("Method: brute-force",3), verbose)
	
	if mna is None or Tf is None:
		(mna, Tf) = dc_analysis.generate_mna_and_N(circ)
		mna = utilities.remove_row_and_col(mna)
		Tf = utilities.remove_row(Tf, rrow=0)
	elif not mna.shape[0] == Tf.shape[0]:
		printing.print_general_error("mna matrix and N vector have different number of rows.")
		sys.exit(0)
	
	if D is None:
		D = transient.generate_D(circ, [mna.shape[0], mna.shape[0]])
		D = utilities.remove_row_and_col(D)
	elif not mna.shape == D.shape:
		printing.print_general_error("mna matrix and D matrix have different sizes.")
		sys.exit(0)
	
	(points, step) = check_step_and_points(step, points, period)
	
	n_of_var = mna.shape[0]
	locked_nodes = circ.get_locked_nodes()
	tick = ticker.ticker(increments_for_step=1)


	CMAT = build_CMAT(mna, D, step, points, tick, n_of_var=n_of_var, \
		verbose=verbose)

	x = build_x(mna, step, points, tick, x0=x0, n_of_var=n_of_var, \
		verbose=verbose)

	Tf = build_Tf(Tf, points, tick, n_of_var=n_of_var, verbose=verbose)
	
	# time variable component: Tt this is always the same in each iter. So we build it once for all
	# this holds all time-dependent sources (both V/I).
	Tt = build_Tt(circ, points, step, tick, n_of_var=n_of_var, verbose=verbose)

	# Indices to differentiate between currents and voltages in the convergence check
	nv_indices = []
	ni_indices = []
	nv_1 = len(circ.nodes_dict) - 1
	ni = n_of_var - nv_1
	for i in range(points):
		nv_indices += (i*mna.shape[0]*numpy.ones(nv_1) + numpy.arange(nv_1)).tolist()
		ni_indices += (i*mna.shape[0]*numpy.ones(ni) + numpy.arange(nv_1, n_of_var)).tolist()

	converged = False

	printing.print_info_line(("Solving... ",3), verbose, print_nl=False)
	tick.reset()
	tick.display(verbose > 2)
	J = numpy.mat(numpy.zeros(CMAT.shape))
	T = numpy.mat(numpy.zeros((CMAT.shape[0], 1)))
	# td is a numpy matrix that will hold the damping factors
	td = numpy.mat(numpy.zeros((points, 1)))
	iteration = 0 # newton iteration counter
	
	while True:
		if iteration: # the first time are already all zeros
			J[:, :] = 0
			T[:, 0] = 0
			td[:, 0] = 0
		for index in xrange(1, points):
			for elem in circ.elements:
				# build all dT(xn)/dxn (stored in J) and T(x)
				if elem.is_nonlinear:
					oports = elem.get_output_ports()
					for opindex in range(len(oports)):
						dports = elem.get_drive_ports(opindex)
						v_ports = []
						for dpindex in range(len(dports)):
							dn1, dn2 = dports[dpindex]
							v = 0 # build v: remember we trashed the 0 row and 0 col of mna -> -1
							if dn1:
								v = v + x[index*n_of_var + dn1 - 1, 0]
							if dn2:
								v = v - x[index*n_of_var + dn2 - 1, 0]
							v_ports.append(v)
						# all drive ports are ready.
						n1, n2 = oports[opindex][0], oports[opindex][1]
						if n1:
							T[index*n_of_var + n1 - 1, 0] = T[index*n_of_var + n1 - 1, 0] + elem.i(opindex, v_ports)
						if n2:
							T[index*n_of_var + n2 - 1, 0] = T[index*n_of_var + n2 - 1, 0] - elem.i(opindex, v_ports)
						for dpindex in range(len(dports)):
							dn1, dn2 = dports[dpindex]
							if n1:
								if dn1:
									J[index*n_of_var + n1-1, index*n_of_var + dn1-1] = \
									J[index*n_of_var + n1-1, index*n_of_var + dn1-1] + elem.g(opindex, v_ports, dpindex)
								if dn2:
									J[index*n_of_var + n1-1, index*n_of_var + dn2-1] =\
									J[index*n_of_var + n1-1, index * n_of_var + dn2-1] - 1.0*elem.g(opindex, v_ports, dpindex)
							if n2:
								if dn1:	
									J[index*n_of_var + n2-1, index*n_of_var + dn1-1] = \
									J[index*n_of_var + n2-1, index*n_of_var + dn1-1] - 1.0*elem.g(opindex, v_ports, dpindex)
								if dn2:
									J[index*n_of_var + n2-1, index*n_of_var + dn2-1] =\
									J[index*n_of_var + n2-1, index*n_of_var + dn2-1] + elem.g(opindex, v_ports, dpindex)

		J = J + CMAT
		residuo = CMAT*x + T + Tf + Tt
		dx = -1 * (numpy.linalg.inv(J) *  residuo)
		#td
		for index in xrange(points):
			td[index, 0] = dc_analysis.get_td(dx[index*n_of_var:(index+1)*n_of_var, 0], locked_nodes, n=-1)
		x = x + min(abs(td))[0, 0] * dx
		# convergence check
		converged = convergence_check(dx, x, nv_indices, ni_indices, vector_norm)
		if converged:
			break
		tick.step(verbose > 2)
	
		if options.shooting_max_nr_iter and iteration == options.shooting_max_nr_iter:
			printing.print_general_error("Hitted SHOOTING_MAX_NR_ITER (" + str(options.shooting_max_nr_iter) + "), iteration halted.")
			converged = False
			break
		else:
			iteration = iteration + 1

	tick.hide(verbose > 2)
	if converged:
		printing.print_info_line(("done.", 3), verbose)
		t = numpy.mat(numpy.arange(points)*step)
		t = t.reshape((1, points))
		x = x.reshape((points, n_of_var))
		sol = results.pss_solution(circ=circ, method="brute-force", period=period, outfile=data_filename, t_array=t, x_array=x.T)
	else:
		print "failed."
		sol = None
	return sol
Ejemplo n.º 2
0
def shooting(circ,
             period,
             step=None,
             mna=None,
             Tf=None,
             D=None,
             points=None,
             autonomous=False,
             data_filename='stdout',
             vector_norm=lambda v: max(abs(v)),
             verbose=3):
    """Performs a periodic steady state analysis based on the algorithm described in
	Brambilla, A.; D'Amore, D., "Method for steady-state simulation of 
	strongly nonlinear circuits in the time domain," Circuits and 
	Systems I: Fundamental Theory and Applications, IEEE Transactions on, 
	vol.48, no.7, pp.885-889, Jul 2001
	URL: http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=933329&isnumber=20194
	
	The results have been computed again by me, the formulas are not exactly the 
	same, but the idea behind the shooting algorithm is.
	
	This method allows us to have a period with many points without having to
	invert a huge matrix (and being limited to the maximum matrix size).

	A tran is performed to initialize the solver.
	
	We compute the change in the last point, calculating several matrices in
	the process.
	From that, with the same matrices we calculate the changes in all points, 
	starting from 0 (which is the same as the last one), then 1, ...

	Key points:
	- Only not autonomous circuits are supported.
	- The time step is constant
	- Implicit euler is used as DF
	
	Parameters:
	circ is the circuit description class
	period is the period of the solution
	mna, D, Tf are not compulsory they will be computed if they're set to None
	step is the time step between consecutive points
	points is the number of points to be used
	step and points are mutually exclusive options:
	- if step is specified, the number of points will be automatically determined 
	- if points is set, the step will be automatically determined
	- if none of them is set, options.shooting_default_points will be used as points
	autonomous has to be False, autonomous circuits are not supported
	data_filename is the output filename. Defaults to stdout.
	verbose is set to zero (print errors only) if datafilename == 'stdout'.

	Returns: nothing
	"""

    if data_filename == "stdout":
        verbose = 0

    printing.print_info_line(("Starting periodic steady state analysis:", 3),
                             verbose)
    printing.print_info_line(("Method: shooting", 3), verbose)

    if mna is None or Tf is None:
        (mna, Tf) = dc_analysis.generate_mna_and_N(circ)
        mna = utilities.remove_row_and_col(mna)
        Tf = utilities.remove_row(Tf, rrow=0)
    elif not mna.shape[0] == Tf.shape[0]:
        printing.print_general_error(
            "mna matrix and N vector have different number of rows.")
        sys.exit(0)

    if D is None:
        D = transient.generate_D(circ, [mna.shape[0], mna.shape[0]])
        D = utilities.remove_row_and_col(D)
    elif not mna.shape == D.shape:
        printing.print_general_error(
            "mna matrix and D matrix have different sizes.")
        sys.exit(0)

    (points, step) = check_step_and_points(step, points, period)
    print "points", points
    print "step", step

    n_of_var = mna.shape[0]
    locked_nodes = circ.get_locked_nodes()

    printing.print_info_line((
        "Starting transient analysis for algorithm init: tstop=%g, tstep=%g... "
        % (10 * points * step, step), 3),
                             verbose,
                             print_nl=False)
    xtran = transient.transient_analysis(circ=circ, tstart=0, tstep=step, tstop=10*points*step, method="TRAP", x0=None, mna=mna, N=Tf, \
           D=D, use_step_control=False, data_filename=data_filename+".tran", return_req_dict={"points":points}, verbose=0)
    if xtran is None:
        print "failed."
        return None
    printing.print_info_line(("done.", 3), verbose)

    x = []
    for index in range(points):
        x.append(xtran[index * n_of_var:(index + 1) * n_of_var, 0])

    tick = ticker.ticker(increments_for_step=1)

    MAass_static, MBass = build_static_MAass_and_MBass(mna, D, step)

    # This contains
    # the time invariant part, Tf
    # time variable component: Tt this is always the same, since the time interval is the same
    # this holds all time-dependent sources (both V/I).
    Tass_static_vector = build_Tass_static_vector(circ, Tf, points, step, tick,
                                                  n_of_var, verbose)

    converged = False
    printing.print_info_line(("Solving... ", 3), verbose, print_nl=False)
    tick.reset()
    tick.display(verbose > 2)

    iteration = 0  # newton iteration counter
    conv_counter = 0

    while True:
        dx = []
        Tass_variable_vector = []
        MAass_variable_vector = []
        for index in range(points):
            if index == 0:
                xn_minus_1 = x[points - 1]
            else:
                xn_minus_1 = x[index - 1]
            MAass_variable, Tass_variable = get_variable_MAass_and_Tass(
                circ, x[index], xn_minus_1, mna, D, step, n_of_var)
            MAass_variable_vector.append(MAass_variable + MAass_static)
            Tass_variable_vector.append(Tass_variable +
                                        Tass_static_vector[index])

        dxN = compute_dxN(circ,
                          MAass_variable_vector,
                          MBass,
                          Tass_variable_vector,
                          n_of_var,
                          points,
                          verbose=verbose)
        td = dc_analysis.get_td(dxN, locked_nodes, n=-1)
        x[points - 1] = td * dxN + x[points - 1]

        for index in range(points - 1):
            if index == 0:
                dxi_minus_1 = dxN
            else:
                dxi_minus_1 = dx[index - 1]
            dx.append(
                compute_dx(MAass_variable_vector[index], MBass,
                           Tass_variable_vector[index], dxi_minus_1))
            td = dc_analysis.get_td(dx[index], locked_nodes, n=-1)
            x[index] = td * dx[index] + x[index]
        dx.append(dxN)

        if (vector_norm_wrapper(dx, vector_norm) <
                min(options.ver, options.ier) * vector_norm_wrapper(
                    x, vector_norm) + min(options.vea, options.iea)):  #\
            #and (dc_analysis.vector_norm(residuo) < options.er*dc_analysis.vector_norm(x) + options.ea):
            if conv_counter == 3:
                converged = True
                break
            else:
                conv_counter = conv_counter + 1
        elif vector_norm(dx[points - 1]) is numpy.nan:  #needs work fixme
            raise OverflowError
            #break
        else:
            conv_counter = 0
            tick.step(verbose > 2)

        if options.shooting_max_nr_iter and iteration == options.shooting_max_nr_iter:
            printing.print_general_error("Hitted SHOOTING_MAX_NR_ITER (" +
                                         str(options.shooting_max_nr_iter) +
                                         "), iteration halted.")
            converged = False
            break
        else:
            iteration = iteration + 1

    tick.hide(verbose > 2)
    if converged:
        printing.print_info_line(("done.", 3), verbose)
        t = numpy.mat(numpy.arange(points) * step)
        t = t.reshape((1, points))
        xmat = x[0]
        for index in xrange(1, points):
            xmat = numpy.concatenate((xmat, x[index]), axis=1)
        sol = results.pss_solution(circ=circ,
                                   method="shooting",
                                   period=period,
                                   outfile=data_filename,
                                   t_array=t,
                                   x_array=xmat)
        #print_results(circ, x, fdata, points, step)
    else:
        print "failed."
        sol = None
    return sol
Ejemplo n.º 3
0
def shooting(circ, period, step=None, x0=None, points=None, autonomous=False,
             mna=None, Tf=None, D=None, outfile='stdout', vector_norm=lambda v: max(abs(v)), verbose=3):
    """Performs a periodic steady state analysis based on the algorithm described in
    Brambilla, A.; D'Amore, D., "Method for steady-state simulation of
    strongly nonlinear circuits in the time domain," Circuits and
    Systems I: Fundamental Theory and Applications, IEEE Transactions on,
    vol.48, no.7, pp.885-889, Jul 2001
    URL: http://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=933329&isnumber=20194

    The results have been computed again by me, the formulas are not exactly the
    same, but the idea behind the shooting algorithm is.

    This method allows us to have a period with many points without having to
    invert a huge matrix (and being limited to the maximum matrix size).

    A tran is performed to initialize the solver.

    We compute the change in the last point, calculating several matrices in
    the process.
    From that, with the same matrices we calculate the changes in all points,
    starting from 0 (which is the same as the last one), then 1, ...

    Key points:
    - Only not autonomous circuits are supported.
    - The time step is constant
    - Implicit euler is used as DF

    Parameters:
    circ is the circuit description class
    period is the period of the solution
    mna, D, Tf are not compulsory they will be computed if they're set to None
    step is the time step between consecutive points
    points is the number of points to be used
    step and points are mutually exclusive options:
    - if step is specified, the number of points will be automatically determined
    - if points is set, the step will be automatically determined
    - if none of them is set, options.shooting_default_points will be used as points
    autonomous has to be False, autonomous circuits are not supported
    outfile is the output filename. Defaults to stdout.
    verbose is set to zero (print errors only) if datafilename == 'stdout'.

    Returns: nothing
    """

    if outfile == "stdout":
        verbose = 0

    printing.print_info_line(
        ("Starting periodic steady state analysis:", 3), verbose)
    printing.print_info_line(("Method: shooting", 3), verbose)

    if isinstance(x0, results.op_solution):
        x0 = x0.asmatrix()
    if mna is None or Tf is None:
        (mna, Tf) = dc_analysis.generate_mna_and_N(circ, verbose=verbose)
        mna = utilities.remove_row_and_col(mna)
        Tf = utilities.remove_row(Tf, rrow=0)
    elif not mna.shape[0] == Tf.shape[0]:
        printing.print_general_error(
            "mna matrix and N vector have different number of rows.")
        sys.exit(0)

    if D is None:
        D = transient.generate_D(circ, [mna.shape[0], mna.shape[0]])
        D = utilities.remove_row_and_col(D)
    elif not mna.shape == D.shape:
        printing.print_general_error(
            "mna matrix and D matrix have different sizes.")
        sys.exit(0)

    (points, step) = check_step_and_points(step, points, period)
    print "points", points
    print "step", step

    n_of_var = mna.shape[0]
    locked_nodes = circ.get_locked_nodes()

    printing.print_info_line(
        ("Starting transient analysis for algorithm init: tstop=%g, tstep=%g... " % (10 * points * step, step), 3), verbose, print_nl=False)
    xtran = transient.transient_analysis(
        circ=circ, tstart=0, tstep=step, tstop=10 * points * step, method="TRAP", x0=None, mna=mna, N=Tf,
        D=D, use_step_control=False, outfile=outfile + ".tran", return_req_dict={"points": points}, verbose=0)
    if xtran is None:
        print "failed."
        return None
    printing.print_info_line(("done.", 3), verbose)

    x = []
    for index in range(points):
        x.append(xtran[index * n_of_var:(index + 1) * n_of_var, 0])

    tick = ticker.ticker(increments_for_step=1)

    MAass_static, MBass = build_static_MAass_and_MBass(mna, D, step)

    # This contains
    # the time invariant part, Tf
    # time variable component: Tt this is always the same, since the time interval is the same
    # this holds all time-dependent sources (both V/I).
    Tass_static_vector = build_Tass_static_vector(
        circ, Tf, points, step, tick, n_of_var, verbose)

    converged = False
    printing.print_info_line(("Solving... ", 3), verbose, print_nl=False)
    tick.reset()
    tick.display(verbose > 2)

    iteration = 0  # newton iteration counter
    conv_counter = 0

    while True:
        dx = []
        Tass_variable_vector = []
        MAass_variable_vector = []
        for index in range(points):
            if index == 0:
                xn_minus_1 = x[points - 1]
            else:
                xn_minus_1 = x[index - 1]
            MAass_variable, Tass_variable = get_variable_MAass_and_Tass(
                circ, x[index], xn_minus_1, mna, D, step, n_of_var)
            MAass_variable_vector.append(MAass_variable + MAass_static)
            Tass_variable_vector.append(
                Tass_variable + Tass_static_vector[index])

        dxN = compute_dxN(circ, MAass_variable_vector, MBass,
                          Tass_variable_vector, n_of_var, points, verbose=verbose)
        td = dc_analysis.get_td(dxN, locked_nodes, n=-1)
        x[points - 1] = td * dxN + x[points - 1]

        for index in range(points - 1):
            if index == 0:
                dxi_minus_1 = dxN
            else:
                dxi_minus_1 = dx[index - 1]
            dx.append(
                compute_dx(MAass_variable_vector[index], MBass, Tass_variable_vector[index], dxi_minus_1))
            td = dc_analysis.get_td(dx[index], locked_nodes, n=-1)
            x[index] = td * dx[index] + x[index]
        dx.append(dxN)

        if (vector_norm_wrapper(dx, vector_norm) < min(options.ver, options.ier) * vector_norm_wrapper(x, vector_norm) + min(options.vea, options.iea)):  # \
        # and (dc_analysis.vector_norm(residuo) <
        # options.er*dc_analysis.vector_norm(x) + options.ea):
            if conv_counter == 3:
                converged = True
                break
            else:
                conv_counter = conv_counter + 1
        elif vector_norm(dx[points - 1]) is numpy.nan:  # needs work fixme
            raise OverflowError
            # break
        else:
            conv_counter = 0
            tick.step(verbose > 2)

        if options.shooting_max_nr_iter and iteration == options.shooting_max_nr_iter:
            printing.print_general_error(
                "Hitted SHOOTING_MAX_NR_ITER (" + str(options.shooting_max_nr_iter) + "), iteration halted.")
            converged = False
            break
        else:
            iteration = iteration + 1

    tick.hide(verbose > 2)
    if converged:
        printing.print_info_line(("done.", 3), verbose)
        t = numpy.mat(numpy.arange(points) * step)
        t = t.reshape((1, points))
        xmat = x[0]
        for index in xrange(1, points):
            xmat = numpy.concatenate((xmat, x[index]), axis=1)
        sol = results.pss_solution(
            circ=circ, method="shooting", period=period, outfile=outfile, t_array=t, x_array=xmat)
        # print_results(circ, x, fdata, points, step)
    else:
        print "failed."
        sol = None
    return sol
Ejemplo n.º 4
0
def bfpss(circ,
          period,
          step=None,
          points=None,
          autonomous=False,
          x0=None,
          mna=None,
          Tf=None,
          D=None,
          outfile='stdout',
          vector_norm=lambda v: max(abs(v)),
          verbose=3):
    """Performs a PSS analysis.

    Time step is constant, IE will be used as DF

    Parameters:
    circ is the circuit description class
    period is the period of the solution
    mna, D, Tf are not compulsory they will be computed if they're set to None
    step is the time step between consecutive points
    points is the number of points to be used
    step and points are mutually exclusive options:
    - if step is specified, the number of points will be automatically determined
    - if points is set, the step will be automatically determined
    - if none of them is set, options.shooting_default_points will be used as points
    autonomous has to be False, autonomous circuits are not supported
    x0 is the initial guess to be used. Needs work.
    outfile is the output filename. Defaults to stdout.
    verbose is set to zero (print errors only) if datafilename == 'stdout'.

    Returns: nothing
    """
    if outfile == "stdout":
        verbose = 0

    printing.print_info_line(("Starting periodic steady state analysis:", 3),
                             verbose)
    printing.print_info_line(("Method: brute-force", 3), verbose)

    if mna is None or Tf is None:
        (mna, Tf) = dc_analysis.generate_mna_and_N(circ, verbose=verbose)
        mna = utilities.remove_row_and_col(mna)
        Tf = utilities.remove_row(Tf, rrow=0)
    elif not mna.shape[0] == Tf.shape[0]:
        printing.print_general_error(
            "mna matrix and N vector have different number of rows.")
        sys.exit(0)

    if D is None:
        D = transient.generate_D(circ, [mna.shape[0], mna.shape[0]])
        D = utilities.remove_row_and_col(D)
    elif not mna.shape == D.shape:
        printing.print_general_error(
            "mna matrix and D matrix have different sizes.")
        sys.exit(0)

    (points, step) = check_step_and_points(step, points, period)

    n_of_var = mna.shape[0]
    locked_nodes = circ.get_locked_nodes()
    tick = ticker.ticker(increments_for_step=1)

    CMAT = build_CMAT(mna,
                      D,
                      step,
                      points,
                      tick,
                      n_of_var=n_of_var,
                      verbose=verbose)

    x = build_x(mna,
                step,
                points,
                tick,
                x0=x0,
                n_of_var=n_of_var,
                verbose=verbose)

    Tf = build_Tf(Tf, points, tick, n_of_var=n_of_var, verbose=verbose)

    # time variable component: Tt this is always the same in each iter. So we build it once for all
    # this holds all time-dependent sources (both V/I).
    Tt = build_Tt(circ, points, step, tick, n_of_var=n_of_var, verbose=verbose)

    # Indices to differentiate between currents and voltages in the
    # convergence check
    nv_indices = []
    ni_indices = []
    nv_1 = len(circ.nodes_dict) - 1
    ni = n_of_var - nv_1
    for i in range(points):
        nv_indices += (i * mna.shape[0] * numpy.ones(nv_1) + \
                      numpy.arange(nv_1)).tolist()
        ni_indices += (i * mna.shape[0] * numpy.ones(ni) + \
                      numpy.arange(nv_1, n_of_var)).tolist()

    converged = False

    printing.print_info_line(("Solving... ", 3), verbose, print_nl=False)
    tick.reset()
    tick.display(verbose > 2)
    J = numpy.mat(numpy.zeros(CMAT.shape))
    T = numpy.mat(numpy.zeros((CMAT.shape[0], 1)))
    # td is a numpy matrix that will hold the damping factors
    td = numpy.mat(numpy.zeros((points, 1)))
    iteration = 0  # newton iteration counter

    while True:
        if iteration:  # the first time are already all zeros
            J[:, :] = 0
            T[:, 0] = 0
            td[:, 0] = 0
        for index in xrange(1, points):
            for elem in circ:
                # build all dT(xn)/dxn (stored in J) and T(x)
                if elem.is_nonlinear:
                    oports = elem.get_output_ports()
                    for opindex in range(len(oports)):
                        dports = elem.get_drive_ports(opindex)
                        v_ports = []
                        for dpindex in range(len(dports)):
                            dn1, dn2 = dports[dpindex]
                            v = 0  # build v: remember we trashed the 0 row and 0 col of mna -> -1
                            if dn1:
                                v = v + x[index * n_of_var + dn1 - 1, 0]
                            if dn2:
                                v = v - x[index * n_of_var + dn2 - 1, 0]
                            v_ports.append(v)
                        # all drive ports are ready.
                        n1, n2 = oports[opindex][0], oports[opindex][1]
                        if n1:
                            T[index * n_of_var + n1 - 1, 0] = T[index * n_of_var + n1 - 1, 0] + \
                                                              elem.i(opindex, v_ports)
                        if n2:
                            T[index * n_of_var + n2 - 1, 0] = T[index * n_of_var + n2 - 1, 0] - \
                                                              elem.i(opindex, v_ports)
                        for dpindex in range(len(dports)):
                            dn1, dn2 = dports[dpindex]
                            if n1:
                                if dn1:
                                    J[index * n_of_var + n1 - 1, index * n_of_var + dn1 - 1] = \
                                        J[index * n_of_var + n1 - 1, index * n_of_var + dn1 - 1] + \
                                            elem.g(opindex, v_ports, dpindex)
                                if dn2:
                                    J[index * n_of_var + n1 - 1, index * n_of_var + dn2 - 1] =\
                                        J[index * n_of_var + n1 - 1, index * n_of_var + dn2 - 1] - 1.0 * \
                                            elem.g(opindex, v_ports, dpindex)
                            if n2:
                                if dn1:
                                    J[index * n_of_var + n2 - 1, index * n_of_var + dn1 - 1] = \
                                        J[index * n_of_var + n2 - 1, index * n_of_var + dn1 - 1] - 1.0 * \
                                            elem.g(opindex, v_ports, dpindex)
                                if dn2:
                                    J[index * n_of_var + n2 - 1, index * n_of_var + dn2 - 1] =\
                                        J[index * n_of_var + n2 - 1, index * n_of_var + dn2 - 1] + \
                                            elem.g(opindex, v_ports, dpindex)

        J = J + CMAT
        residuo = CMAT * x + T + Tf + Tt
        dx = -1 * (numpy.linalg.inv(J) * residuo)
        # td
        for index in xrange(points):
            td[index, 0] = dc_analysis.get_td(dx[index * n_of_var:(index + 1) *
                                                 n_of_var, 0],
                                              locked_nodes,
                                              n=-1)
        x = x + min(abs(td))[0, 0] * dx
        # convergence check
        converged = convergence_check(dx, x, nv_indices, ni_indices,
                                      vector_norm)
        if converged:
            break
        tick.step(verbose > 2)

        if options.shooting_max_nr_iter and iteration == options.shooting_max_nr_iter:
            printing.print_general_error("Hitted SHOOTING_MAX_NR_ITER (" +
                                         str(options.shooting_max_nr_iter) +
                                         "), iteration halted.")
            converged = False
            break
        else:
            iteration = iteration + 1

    tick.hide(verbose > 2)
    if converged:
        printing.print_info_line(("done.", 3), verbose)
        t = numpy.mat(numpy.arange(points) * step)
        t = t.reshape((1, points))
        x = x.reshape((points, n_of_var))
        sol = results.pss_solution(circ=circ,
                                   method="brute-force",
                                   period=period,
                                   outfile=outfile,
                                   t_array=t,
                                   x_array=x.T)
    else:
        print "failed."
        sol = None
    return sol