예제 #1
0
파일: dc_analysis.py 프로젝트: vovkd/ahkab
def build_x0_from_user_supplied_ic(circ, voltages_dict, currents_dict):
	"""Builds a numpy.matrix of appropriate size (reduced!) from the values supplied
	in voltages_dict and currents_dict. What is not found in the dictionary is set to 0.
	
	Parameters:
	circ: the circuit instance
	voltages_dict: keys are the external nodes, values are the node voltages.
	currents_dict: keys are the elements names (eg l1, v4), the values are the currents
		
	Note: this simulator uses the normal convention.
	
	Returns:
	The x0 matrix
	"""
	nv = len(circ.nodes_dict) #number of voltage variables
	voltage_defined_elements = [ x for x in circ.elements if circuit.is_elem_voltage_defined(x) ]
	ni = len(voltage_defined_elements) #number of current variables
	current_labels_list = [ elem.letter_id + elem.descr for elem in voltage_defined_elements ]
	
	x0 = numpy.mat(numpy.zeros((nv + ni, 1)))
	
	for ext_node, value in voltages_dict.iteritems():
		int_node = circ.ext_node_to_int(ext_node)
		x0[int_node, 0] = value
	
	for current_label, value in currents_dict.iteritems():
		index = current_labels_list.index(current_label)
		x0[nv + index, 0] = value

	return x0[1:, :]
예제 #2
0
파일: dc_analysis.py 프로젝트: vovkd/ahkab
def build_x0_from_user_supplied_ic(circ, voltages_dict, currents_dict):
    """Builds a numpy.matrix of appropriate size (reduced!) from the values supplied
	in voltages_dict and currents_dict. What is not found in the dictionary is set to 0.
	
	Parameters:
	circ: the circuit instance
	voltages_dict: keys are the external nodes, values are the node voltages.
	currents_dict: keys are the elements names (eg l1, v4), the values are the currents
		
	Note: this simulator uses the normal convention.
	
	Returns:
	The x0 matrix
	"""
    nv = len(circ.nodes_dict)  # number of voltage variables
    voltage_defined_elements = [x for x in circ.elements if circuit.is_elem_voltage_defined(x)]
    ni = len(voltage_defined_elements)  # number of current variables
    current_labels_list = [elem.letter_id + elem.descr for elem in voltage_defined_elements]

    x0 = numpy.mat(numpy.zeros((nv + ni, 1)))

    for ext_node, value in voltages_dict.iteritems():
        int_node = circ.ext_node_to_int(ext_node)
        x0[int_node, 0] = value

    for current_label, value in currents_dict.iteritems():
        index = current_labels_list.index(current_label)
        x0[nv + index, 0] = value

    return x0[1:, :]
예제 #3
0
def build_Tass_static_vector(circ, Tf, points, step, tick, n_of_var, verbose=3):
    Tass_vector = []
    nv = len(circ.nodes_dict)
    printing.print_info_line(("Building Tass...", 5), verbose, print_nl=False)

    tick.reset()
    tick.display(verbose > 2)
    for index in xrange(0, points):
            Tt = numpy.zeros((n_of_var, 1))
            v_eq = 0
            time = index * step
            for elem in circ:
                    if (isinstance(elem, devices.VSource) or isinstance(elem, devices.ISource)) and elem.is_timedependent:
                        if isinstance(elem, devices.VSource):
                                Tt[nv - 1 + v_eq, 0] = -1.0 * elem.V(time)
                        elif isinstance(elem, devices.ISource):
                                if elem.n1:
                                        Tt[elem.n1 - 1, 0] = \
                                            Tt[elem.n1 - 1, 0] + elem.I(time)
                                if elem.n2:
                                        Tt[elem.n2 - 1, 0] = \
                                            Tt[elem.n2 - 1, 0] - elem.I(time)
                    if circuit.is_elem_voltage_defined(elem):
                            v_eq = v_eq + 1
            tick.step(verbose > 2)
            Tass_vector.append(Tf + Tt)
    tick.hide(verbose > 2)
    printing.print_info_line(("done.", 5), verbose)

    return Tass_vector
예제 #4
0
    def __init__(self, circ, start, stop, sweepvar, stype, outfile):
        """Holds a set of DC results.
            circ: the circuit instance of the simulated circuit
            start: the sweep start value
            stop: the sweep stop value
            sweepvar: the swept variable
            stype: type of sweep
            outfile: the file to write the results to. 
                     (Use "stdout" to write to std output)
        """
        solution.__init__(self, circ, outfile)
        self.start, self.stop = start, stop
        self.stype = stype

        nv_1 = len(circ.nodes_dict
                   ) - 1  # numero di soluzioni di tensione (al netto del ref)
        self.variables = [sweepvar]
        self.units = case_insensitive_dict()
        if self.variables[0][0] == 'V':
            self.units.update({self.variables[0]: 'V'})
        if self.variables[0][0] == 'I':
            self.units.update({self.variables[0]: 'A'})

        for index in range(nv_1):
            varname = "V%s" % (str(circ.nodes_dict[index + 1]), )
            self.variables += [varname]
            self.units.update({varname: "V"})
            if circ.is_int_node_internal_only(index + 1):
                self.skip_nodes_list.append(index)

        for elem in circ:
            if circuit.is_elem_voltage_defined(elem):
                varname = "I(%s)" % (elem.part_id.upper(), )
                self.variables += [varname]
                self.units.update({varname: "A"})
예제 #5
0
    def __init__(self, circ, tstart, tstop, op, method, outfile):
        """Holds a set of TRANSIENT results.
            circ: the circuit instance of the simulated circuit
            tstart: the sweep starting angular frequency
            tstop: the sweep stopping frequency
            op: the op used to start the tran analysis
            outfile: the file to write the results to. 
                     (Use "stdout" to write to std output)
        """
        solution.__init__(self, circ, outfile)
        self.start_op = op
        self.tstart, self.tstop = tstart, tstop
        self.method = method

        self._lock = False

        nv_1 = len(circ.nodes_dict
                   ) - 1  # numero di soluzioni di tensione (al netto del ref)
        self.variables = ["T"]
        self.units.update({"T": "s"})

        for index in range(nv_1):
            varname = ("V%s" % (str(circ.nodes_dict[index + 1]), )).upper()
            self.variables += [varname]
            self.units.update({varname: "V"})
            if circ.is_int_node_internal_only(index + 1):
                self.skip_nodes_list.append(index)

        for elem in circ:
            if circuit.is_elem_voltage_defined(elem):
                varname = ("I(%s)" % (elem.part_id.upper(), )).upper()
                self.variables += [varname]
                self.units.update({varname: "A"})
예제 #6
0
파일: dc_analysis.py 프로젝트: vovkd/ahkab
def modify_x0_for_ic(circ, x0):
    """Modifies a supplied x0.
	"""

    if isinstance(x0, results.op_solution):
        x0 = x0.asmatrix()
        return_obj = True
    else:
        return_obj = False

    nv = len(circ.nodes_dict)  # number of voltage variables
    voltage_defined_elements = [x for x in circ.elements if circuit.is_elem_voltage_defined(x)]

    # setup voltages this may _not_ work properly
    for elem in circ.elements:
        if isinstance(elem, devices.capacitor) and elem.ic or isinstance(elem, devices.diode) and elem.ic:
            x0[elem.n1 - 1, 0] = x0[elem.n2 - 1, 0] + elem.ic

            # setup the currents
    for elem in voltage_defined_elements:
        if isinstance(elem, devices.inductor) and elem.ic:
            x0[nv - 1 + voltage_defined_elements.index(elem), 0] = elem.ic

    if return_obj:
        xnew = results.op_solution(x=x0, error=numpy.mat(numpy.zeros(x0.shape)), circ=circ, outfile=None)
        xnew.netlist_file = None
        xnew.netlist_title = "Self-generated OP to be used as tran IC"
    else:
        xnew = x0

    return xnew
예제 #7
0
파일: bfpss.py 프로젝트: itdaniher/ahkab
def build_Tt(circ, points, step, tick, n_of_var, verbose=3):
    nv = len(circ.nodes_dict)
    printing.print_info_line(("Building Tt...", 5), verbose, print_nl=False)
    tick.reset()
    tick.display(verbose > 2)
    Tt = numpy.zeros((points * n_of_var, 1))
    for index in xrange(1, points):
        v_eq = 0
        time = index * step
        for elem in circ:
            if (isinstance(elem, devices.VSource) or isinstance(
                    elem, devices.ISource)) and elem.is_timedependent:
                if isinstance(elem, devices.VSource):
                    Tt[index * n_of_var + nv - 1 + v_eq, 0] = - \
                        1.0 * elem.V(time)
                elif isinstance(elem, devices.ISource):
                    if elem.n1:
                        Tt[index * n_of_var + elem.n1 - 1, 0] = \
                            Tt[index * n_of_var + elem.n1 - 1, 0] + \
                            elem.I(time)
                    if elem.n2:
                        Tt[index * n_of_var + elem.n2 - 1, 0] = \
                            Tt[index * n_of_var + elem.n2 - 1, 0] - \
                                elem.I(time)
            if circuit.is_elem_voltage_defined(elem):
                v_eq = v_eq + 1
            # print Tt[index*n_of_var:(index+1)*n_of_var]
        tick.step(verbose > 2)
    tick.hide(verbose > 2)
    printing.print_info_line(("done.", 5), verbose)

    return Tt
예제 #8
0
def modify_x0_for_ic(circ, x0):
    """Modifies a supplied x0.
    """

    if isinstance(x0, results.op_solution):
        x0 = x0.asmatrix()
        return_obj = True
    else:
        return_obj = False

    nv = len(circ.nodes_dict)  # number of voltage variables
    voltage_defined_elements = [
        x for x in circ if circuit.is_elem_voltage_defined(x)
    ]

    # setup voltages this may _not_ work properly
    for elem in circ:
        if isinstance(elem, devices.Capacitor) and elem.ic or \
                isinstance(elem, diode.diode) and elem.ic:
            x0[elem.n1 - 1, 0] = x0[elem.n2 - 1, 0] + elem.ic

    # setup the currents
    for elem in voltage_defined_elements:
        if isinstance(elem, devices.Inductor) and elem.ic:
            x0[nv - 1 + voltage_defined_elements.index(elem), 0] = elem.ic

    if return_obj:
        xnew = results.op_solution(x=x0, \
            error=numpy.mat(numpy.zeros(x0.shape)), circ=circ, outfile=None)
        xnew.netlist_file = None
        xnew.netlist_title = "Self-generated OP to be used as tran IC"
    else:
        xnew = x0

    return xnew
예제 #9
0
파일: results.py 프로젝트: manasdas17/ahkab
    def __init__(self, circ, method, period, outfile, t_array=None, x_array=None):
        """Holds a set of TRANSIENT results.
            circ: the circuit instance of the simulated circuit
            tstart: the sweep starting angular frequency
            tstop: the sweep stopping frequency
            op: the op used to start the tran analysis
            outfile: the file to write the results to. 
                     (Use "stdout" to write to std output)
        """
        solution.__init__(self, circ, outfile)
        self.period = period
        self.method = method

        # We have mixed current and voltage results
        nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
        self.variables = ["T"]
        self.units.update({"T":"s"})
    
        for index in range(nv_1):
            varname = "V%s" % (str(circ.nodes_dict[index + 1]),)
            self.variables += [varname]
            self.units.update({varname:"V"})
            if circ.is_int_node_internal_only(index+1):
                self.skip_nodes_list.append(index)

        for elem in circ: 
            if circuit.is_elem_voltage_defined(elem):
                varname = "I(%s)" % (elem.part_id.upper(),)
                self.variables += [varname]
                self.units.update({varname:"A"})

        if t_array is not None and x_array is not None:
            self.set_results(t_array, x_array)
예제 #10
0
파일: results.py 프로젝트: manasdas17/ahkab
    def __init__(self, circ, tstart, tstop, op, method, outfile):
        """Holds a set of TRANSIENT results.
            circ: the circuit instance of the simulated circuit
            tstart: the sweep starting angular frequency
            tstop: the sweep stopping frequency
            op: the op used to start the tran analysis
            outfile: the file to write the results to. 
                     (Use "stdout" to write to std output)
        """
        solution.__init__(self, circ, outfile)
        self.start_op = op
        self.tstart, self.tstop = tstart, tstop
        self.method = method

        self._lock = False
    
        nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
        self.variables = ["T"]
        self.units.update({"T":"s"})
    
        for index in range(nv_1):
            varname = ("V%s" % (str(circ.nodes_dict[index + 1]),)).upper()
            self.variables += [varname]
            self.units.update({varname:"V"})
            if circ.is_int_node_internal_only(index+1):
                self.skip_nodes_list.append(index)

        for elem in circ: 
            if circuit.is_elem_voltage_defined(elem):
                varname = ("I(%s)" % (elem.part_id.upper(),)).upper()
                self.variables += [varname]
                self.units.update({varname:"A"})
예제 #11
0
파일: results.py 프로젝트: manasdas17/ahkab
    def __init__(self, circ, start, stop, sweepvar, stype, outfile):
        """Holds a set of DC results.
            circ: the circuit instance of the simulated circuit
            start: the sweep start value
            stop: the sweep stop value
            sweepvar: the swept variable
            stype: type of sweep
            outfile: the file to write the results to. 
                     (Use "stdout" to write to std output)
        """
        solution.__init__(self, circ, outfile)
        self.start, self.stop = start, stop
        self.stype = stype
    
        nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
        self.variables = [sweepvar]
        self.units = case_insensitive_dict()        
        if self.variables[0][0] == 'V':
            self.units.update({self.variables[0]:'V'})
        if self.variables[0][0] == 'I':
            self.units.update({self.variables[0]:'A'})
    
        for index in range(nv_1):
            varname = "V%s" % (str(circ.nodes_dict[index + 1]),)
            self.variables += [varname]
            self.units.update({varname:"V"})
            if circ.is_int_node_internal_only(index+1):
                self.skip_nodes_list.append(index)

        for elem in circ: 
            if circuit.is_elem_voltage_defined(elem):
                varname = "I(%s)" % (elem.part_id.upper(),)
                self.variables += [varname]
                self.units.update({varname:"A"})
예제 #12
0
파일: results.py 프로젝트: manasdas17/ahkab
    def __init__(self, circ, ostart, ostop, opoints, stype, op, outfile):
        """Holds a set of AC results.
            circ: the circuit instance of the simulated circuit
            ostart: the sweep starting angular frequency
            ostop: the sweep stopping frequency
            stype: the sweep type
            op: the linearization op used to compute the results
        """
        solution.__init__(self, circ, outfile)
        self.linearization_op = op
        self.stype = stype
        self.ostart, self.ostop, self.opoints = ostart, ostop, opoints
    
        nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
        self.variables += ["w"]
        self.units.update({"w": "rad/s"})
    
        for index in range(nv_1):
            varname_abs = "|V%s|" % (str(circ.nodes_dict[index + 1]),)
            varname_arg = "arg(V%s)" % (str(circ.nodes_dict[index + 1]),)
            self.variables += [varname_abs]
            self.variables += [varname_arg]
            self.units.update({varname_abs: "V"})
            self.units.update({varname_arg: ""})
            if circ.is_int_node_internal_only(index+1):
                self.skip_nodes_list.append(index)

        for elem in circ: 
            if circuit.is_elem_voltage_defined(elem):
                varname_abs = "|I(%s)|" % (elem.part_id.upper(),)
                varname_arg = "arg(I(%s))" % (elem.part_id.upper(),)
                self.variables += [varname_abs]
                self.variables += [varname_arg]
                self.units.update({varname_abs: "A"})
                self.units.update({varname_arg: ""})
예제 #13
0
파일: bfpss.py 프로젝트: vovkd/ahkab
def build_Tt(circ, points, step, tick, n_of_var, verbose=3):
	nv = len(circ.nodes_dict)
	printing.print_info_line(("Building Tt...", 5), verbose, print_nl=False)
	tick.reset()
	tick.display(verbose > 2)	
	Tt = numpy.zeros((points*n_of_var, 1))
	for index in xrange(1, points):
		v_eq = 0
		time = index * step
		for elem in circ.elements:
			if (isinstance(elem, devices.vsource) or isinstance(elem, devices.isource)) and elem.is_timedependent:
				if isinstance(elem, devices.vsource):
					Tt[index*n_of_var + nv - 1 + v_eq, 0] = -1.0 * elem.V(time)
				elif isinstance(elem, devices.isource):
					if elem.n1:
						Tt[index*n_of_var + elem.n1-1, 0] = \
						Tt[index*n_of_var + elem.n1-1, 0] + elem.I(time)
					if elem.n2:
						Tt[index*n_of_var + elem.n2-1, 0] = \
						Tt[index*n_of_var + elem.n2-1, 0] - elem.I(time)
			if circuit.is_elem_voltage_defined(elem):
				v_eq = v_eq +1
			#print Tt[index*n_of_var:(index+1)*n_of_var]
		tick.step(verbose > 2)
	tick.hide(verbose > 2)
	printing.print_info_line(("done.", 5), verbose)
	
	return Tt
예제 #14
0
def print_elements_ops(circ, x):
    tot_power = 0
    i_index = 0
    nv_1 = len(circ.nodes_dict) - 1
    print "OP INFORMATION:"
    for elem in circ:
        ports_v_v = []
        if hasattr(elem, "print_op_info"):
            if elem.is_nonlinear:
                oports = elem.get_output_ports()
                for index in range(len(oports)):
                    dports = elem.get_drive_ports(index)
                    ports_v = []
                    for port in dports:
                        tempv = 0
                        if port[0]:
                            tempv = x[port[0] - 1]
                        if port[1]:
                            tempv = tempv - x[port[1] - 1]
                        ports_v.append(tempv)
                ports_v_v.append(ports_v)
            else:
                port = (elem.n1, elem.n2)
                tempv = 0
                if port[0]:
                    tempv = x[port[0] - 1]
                if port[1]:
                    tempv = tempv - x[port[1] - 1]
                ports_v_v = ((tempv, ), )
            elem.print_op_info(ports_v_v)
            print "-------------------"
        if isinstance(elem, devices.GISource):
            v = 0
            v = v + x[elem.n1 - 1] if elem.n1 != 0 else v
            v = v - x[elem.n2 - 1] if elem.n2 != 0 else v
            vs = 0
            vs = vs + x[elem.n1 - 1] if elem.n1 != 0 else vs
            vs = vs - x[elem.n2 - 1] if elem.n2 != 0 else vs
            tot_power = tot_power - v * vs * elem.alpha
        elif isinstance(elem, devices.ISource):
            v = 0
            v = v + x[elem.n1 - 1] if elem.n1 != 0 else v
            v = v - x[elem.n2 - 1] if elem.n2 != 0 else v
            tot_power = tot_power - v * elem.I()
        elif isinstance(elem, devices.VSource) or isinstance(
                elem, devices.EVSource):
            v = 0
            v = v + x[elem.n1 - 1] if elem.n1 != 0 else v
            v = v - x[elem.n2 - 1] if elem.n2 != 0 else v
            tot_power = tot_power - v * x[nv_1 + i_index, 0]
            i_index = i_index + 1
        elif circuit.is_elem_voltage_defined(elem):
            i_index = i_index + 1
    print "TOTAL POWER: " + str(float(tot_power)) + " W"

    return None
예제 #15
0
    def get_elements_op(self, circ, x):
        tot_power = 0
        i_index = 0
        nv_1 = len(circ.nodes_dict) - 1
        op_info = []
        for elem in circ:
            ports_v_v = []
            if hasattr(elem, "get_op_info"):
                if elem.is_nonlinear:
                    oports = elem.get_output_ports()
                    for index in range(len(oports)):
                        dports = elem.get_drive_ports(index)
                        ports_v = []
                        for port in dports:
                            tempv = 0
                            if port[0]:
                                tempv = x[port[0] - 1]
                            if port[1]:
                                tempv = tempv - x[port[1] - 1]
                            ports_v.append(tempv)
                    ports_v_v.append(ports_v)
                else:
                    port = (elem.n1, elem.n2)
                    tempv = 0
                    if port[0]:
                        tempv = x[port[0] - 1]
                    if port[1]:
                        tempv = tempv - x[port[1] - 1]
                    ports_v_v = ((tempv, ), )
                op_info += [elem.get_op_info(ports_v_v)]
            if isinstance(elem, devices.GISource):
                v = 0
                v = v + x[elem.n1 - 1] if elem.n1 != 0 else v
                v = v - x[elem.n2 - 1] if elem.n2 != 0 else v
                vs = 0
                vs = vs + x[elem.n1 - 1] if elem.n1 != 0 else vs
                vs = vs - x[elem.n2 - 1] if elem.n2 != 0 else vs
                tot_power = tot_power - v * vs * elem.alpha
            elif isinstance(elem, devices.ISource):
                v = 0
                v = v + x[elem.n1 - 1] if elem.n1 != 0 else v
                v = v - x[elem.n2 - 1] if elem.n2 != 0 else v
                tot_power = tot_power - v * elem.I()
            elif isinstance(elem, devices.VSource) or \
                 isinstance(elem, devices.EVSource):
                v = 0
                v = v + x[elem.n1 - 1] if elem.n1 != 0 else v
                v = v - x[elem.n2 - 1] if elem.n2 != 0 else v
                tot_power = tot_power - v * x[nv_1 + i_index, 0]
                i_index = i_index + 1
            elif circuit.is_elem_voltage_defined(elem):
                i_index = i_index + 1

        op_info.append("TOTAL POWER: %e W\n" % (tot_power, ))
        return op_info
예제 #16
0
파일: dc_analysis.py 프로젝트: vovkd/ahkab
def print_elements_ops(circ, x):
    tot_power = 0
    i_index = 0
    nv_1 = len(circ.nodes_dict) - 1
    print "OP INFORMATION:"
    for elem in circ.elements:
        ports_v_v = []
        if hasattr(elem, "print_op_info"):
            if elem.is_nonlinear:
                oports = elem.get_output_ports()
                for index in range(len(oports)):
                    dports = elem.get_drive_ports(index)
                    ports_v = []
                    for port in dports:
                        tempv = 0
                        if port[0]:
                            tempv = x[port[0] - 1]
                        if port[1]:
                            tempv = tempv - x[port[1] - 1]
                        ports_v.append(tempv)
                ports_v_v.append(ports_v)
            else:
                port = (elem.n1, elem.n2)
                tempv = 0
                if port[0]:
                    tempv = x[port[0] - 1]
                if port[1]:
                    tempv = tempv - x[port[1] - 1]
                ports_v_v = ((tempv,),)
            elem.print_op_info(ports_v_v)
            print "-------------------"
        if isinstance(elem, devices.gisource):
            v = 0
            v = v + x[elem.n1 - 1] if elem.n1 != 0 else v
            v = v - x[elem.n2 - 1] if elem.n2 != 0 else v
            vs = 0
            vs = vs + x[elem.n1 - 1] if elem.n1 != 0 else vs
            vs = vs - x[elem.n2 - 1] if elem.n2 != 0 else vs
            tot_power = tot_power - v * vs * elem.alpha
        elif isinstance(elem, devices.isource):
            v = 0
            v = v + x[elem.n1 - 1] if elem.n1 != 0 else v
            v = v - x[elem.n2 - 1] if elem.n2 != 0 else v
            tot_power = tot_power - v * elem.I()
        elif isinstance(elem, devices.vsource) or isinstance(elem, devices.evsource):
            v = 0
            v = v + x[elem.n1 - 1] if elem.n1 != 0 else v
            v = v - x[elem.n2 - 1] if elem.n2 != 0 else v
            tot_power = tot_power - v * x[nv_1 + i_index, 0]
            i_index = i_index + 1
        elif circuit.is_elem_voltage_defined(elem):
            i_index = i_index + 1
    print "TOTAL POWER: " + str(float(tot_power)) + " W"

    return None
예제 #17
0
파일: results.py 프로젝트: manasdas17/ahkab
    def get_elements_op(self, circ, x):
        tot_power = 0
        i_index = 0
        nv_1 = len(circ.nodes_dict) - 1
        op_info = []
        for elem in circ:
            ports_v_v = []
            if hasattr(elem, "get_op_info"):
                if elem.is_nonlinear:
                    oports = elem.get_output_ports()
                    for index in range(len(oports)):
                        dports = elem.get_drive_ports(index)
                        ports_v = []                
                        for port in dports:                 
                            tempv = 0                       
                            if port[0]:
                                tempv = x[port[0]-1]
                            if port[1]:
                                tempv = tempv - x[port[1]-1]
                            ports_v.append(tempv)
                    ports_v_v.append(ports_v)
                else:
                    port = (elem.n1, elem.n2)   
                    tempv = 0                       
                    if port[0]:
                        tempv = x[port[0]-1]
                    if port[1]:
                        tempv = tempv - x[port[1]-1]                
                    ports_v_v = ((tempv,),)
                op_info += [elem.get_op_info(ports_v_v)]
            if isinstance(elem, devices.GISource):
                v = 0
                v = v + x[elem.n1-1] if elem.n1 != 0 else v
                v = v - x[elem.n2-1] if elem.n2 != 0 else v
                vs = 0
                vs = vs + x[elem.n1-1] if elem.n1 != 0 else vs
                vs = vs - x[elem.n2-1] if elem.n2 != 0 else vs
                tot_power = tot_power - v*vs*elem.alpha
            elif isinstance(elem, devices.ISource):
                v = 0
                v = v + x[elem.n1-1] if elem.n1 != 0 else v
                v = v - x[elem.n2-1] if elem.n2 != 0 else v
                tot_power = tot_power - v*elem.I()
            elif isinstance(elem, devices.VSource) or \
                 isinstance(elem, devices.EVSource):
                v = 0
                v = v + x[elem.n1-1] if elem.n1 != 0 else v
                v = v - x[elem.n2-1] if elem.n2 != 0 else v
                tot_power = tot_power - v*x[nv_1 + i_index, 0]
                i_index = i_index + 1
            elif circuit.is_elem_voltage_defined(elem):
                i_index = i_index + 1

        op_info.append("TOTAL POWER: %e W\n" % (tot_power,))
        return op_info
예제 #18
0
def print_results_header(circ,
                         fp,
                         print_int_nodes=False,
                         print_time=False,
                         print_omega=False):
    """Prints the header of the results.
	circ, a circuit instance
	fp, the file pointer to which the header should be written
	print_int_nodes=False, Print internal nodes
	print_time=False, Print the time (it's always the first column)
	
	Returns: None
	"""
    voltage_labels = []
    for n in range(1, len(circ.nodes_dict)):
        if (print_int_nodes or not circ.is_int_node_internal_only(n)):
            if print_omega == False:
                iter_voltage_labels = ["V" + circ.nodes_dict[n]]
            else:
                iter_voltage_labels = [
                    "|V" + circ.nodes_dict[n] + "|",
                    "arg(V" + circ.nodes_dict[n] + ")"
                ]
            voltage_labels = voltage_labels + iter_voltage_labels

    current_labels = []
    for elem in circ.elements:
        if circuit.is_elem_voltage_defined(elem):
            if print_omega == False:
                iter_current_labels = [
                    "I(" + elem.letter_id.upper() + elem.descr + ")"
                ]
            else:
                iter_current_labels = [
                    "|I(" + elem.letter_id.upper() + elem.descr + ")|",
                    "arg(I(" + elem.letter_id.upper() + elem.descr + "))"
                ]
            current_labels = current_labels + iter_current_labels

    labels = voltage_labels + current_labels

    if print_time:
        labels.insert(0, "#T")
    elif print_omega:
        labels.insert(0, "#w")
    else:
        labels[0] = "#" + labels[0]

    for lab in labels:
        fp.write(lab + "\t")
    fp.write("\n")
    fp.flush()

    return None
예제 #19
0
파일: results.py 프로젝트: vovkd/ahkab
	def __init__(self, circ, ostart, ostop, opoints, stype, op, outfile):
		"""Holds a set of AC results.
			circ: the circuit instance of the simulated circuit
			ostart: the sweep starting angular frequency
			ostop: the sweep stopping frequency
			stype: the sweep type
			op: the linearization op used to compute the results
		"""
		self.timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
		self.netlist_file = circ.filename
		self.netlist_title = circ.title
		self.vea = options.vea
		self.ver = options.ver
		self.iea = options.iea
		self.ier = options.ier
		self.gmin = options.gmin
		self.temp = constants.T
		self.linearization_op = op
		self.stype = stype
		self.ostart, self.ostop, self.opoints = ostart, ostop, opoints
		self.filename = outfile

		self._init_file_done = False

		#We have mixed current and voltage results
		# per primi vengono tanti valori di tensioni quanti sono i nodi del circuito meno uno,
		# quindi tante correnti quanti sono gli elementi definiti in tensione presenti
		# (per questo, per misurare una corrente, si può fare uso di generatori di tensione da 0V)
	
		nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
		self.skip_nodes_list = []	# nodi da saltare, solo interni
		self.variables = ["w"]
		self.units = case_insensitive_dict()
		self.units.update({"w":"rad/s"})
	
		for index in range(nv_1):
			varname_abs = "|V%s|" % (str(circ.nodes_dict[index + 1]),)
			varname_arg = "arg(V%s)" % (str(circ.nodes_dict[index + 1]),)
			self.variables += [varname_abs]
			self.variables += [varname_arg]
			self.units.update({varname_abs:"V"})
			self.units.update({varname_arg:""})
			if circ.is_int_node_internal_only(index+1):
				skip_nodes_list.append(index)

		for elem in circ.elements: 
			if circuit.is_elem_voltage_defined(elem):
				varname_abs = "|I(%s)|" % (elem.letter_id.upper()+elem.descr,)
				varname_arg = "arg(I(%s))" % (elem.letter_id.upper()+elem.descr,)
				self.variables += [varname_abs]
				self.variables += [varname_arg]
				self.units.update({varname_abs:"A"})
				self.units.update({varname_arg:""})
예제 #20
0
	def __init__(self, circ, ostart, ostop, opoints, stype, op, outfile):
		"""Holds a set of AC results.
			circ: the circuit instance of the simulated circuit
			ostart: the sweep starting angular frequency
			ostop: the sweep stopping frequency
			stype: the sweep type
			op: the linearization op used to compute the results
		"""
		self.timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
		self.netlist_file = circ.filename
		self.netlist_title = circ.title
		self.vea = options.vea
		self.ver = options.ver
		self.iea = options.iea
		self.ier = options.ier
		self.gmin = options.gmin
		self.temp = constants.T
		self.linearization_op = op
		self.stype = stype
		self.ostart, self.ostop, self.opoints = ostart, ostop, opoints
		self.filename = outfile

		self._init_file_done = False

		#We have mixed current and voltage results
		# per primi vengono tanti valori di tensioni quanti sono i nodi del circuito meno uno,
		# quindi tante correnti quanti sono gli elementi definiti in tensione presenti
		# (per questo, per misurare una corrente, si può fare uso di generatori di tensione da 0V)
	
		nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
		self.skip_nodes_list = []	# nodi da saltare, solo interni
		self.variables = ["w"]
		self.units = case_insensitive_dict()
		self.units.update({"w":"rad/s"})
	
		for index in range(nv_1):
			varname_abs = "|V%s|" % (str(circ.nodes_dict[index + 1]),)
			varname_arg = "arg(V%s)" % (str(circ.nodes_dict[index + 1]),)
			self.variables += [varname_abs]
			self.variables += [varname_arg]
			self.units.update({varname_abs:"V"})
			self.units.update({varname_arg:""})
			if circ.is_int_node_internal_only(index+1):
				skip_nodes_list.append(index)

		for elem in circ.elements: 
			if circuit.is_elem_voltage_defined(elem):
				varname_abs = "|I(%s)|" % (elem.letter_id.upper()+elem.descr,)
				varname_arg = "arg(I(%s))" % (elem.letter_id.upper()+elem.descr,)
				self.variables += [varname_abs]
				self.variables += [varname_arg]
				self.units.update({varname_abs:"A"})
				self.units.update({varname_arg:""})
예제 #21
0
파일: results.py 프로젝트: vovkd/ahkab
	def __init__(self, x, error, circ, outfile, iterations=0):
		"""Holds a set of Operating Point results.
			x: the result set
			error: the residual error after solution,
			circ: the circuit instance of the simulated circuit
			print_int_nodes: a boolean to be set True if you wish to see voltage values 
			of the internal nodes added automatically by the simulator.
		"""
		self.timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
		self.netlist_file = circ.filename
		self.netlist_title = circ.title
		self.vea = options.vea
		self.ver = options.ver
		self.iea = options.iea
		self.ier = options.ier
		self.gmin = options.gmin
		self.temp = constants.T # in Kelvin
		self.filename = outfile
		self.iterations = iterations

		#We have mixed current and voltage results
		# per primi vengono tanti valori di tensioni quanti sono i nodi del circuito meno uno,
		# quindi tante correnti quanti sono gli elementi definiti in tensione presenti
		# (per questo, per misurare una corrente, si può fare uso di generatori di tensione da 0V)
	
		nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
		self.skip_nodes_list = []	      # nodi da saltare, solo interni
		self.variables = []
		self.results = case_insensitive_dict()
		self.errors = case_insensitive_dict()
		self.units = case_insensitive_dict()
		self.x = x
	
		for index in range(nv_1):
			varname = ("V" + str(circ.nodes_dict[index + 1])).upper()
			self.variables += [varname]
			self.results.update({varname:x[index, 0]})
			self.errors.update({varname:error[index, 0]})
			self.units.update({varname:"V"})
			#if circ.is_int_node_internal_only(index+1):
			#	self.skip_nodes_list.append(index)

		for elem in circ.elements:
			if circuit.is_elem_voltage_defined(elem):
				index = index + 1
				varname = ("I("+elem.letter_id.upper()+elem.descr+")").upper()
				self.variables += [varname]
				self.results.update({varname:x[index, 0]})
				self.errors.update({varname:error[index, 0]})
				self.units.update({varname:"A"})

		self.op_info = self.get_elements_op(circ, x)
예제 #22
0
	def __init__(self, x, error, circ, outfile, iterations=0):
		"""Holds a set of Operating Point results.
			x: the result set
			error: the residual error after solution,
			circ: the circuit instance of the simulated circuit
			print_int_nodes: a boolean to be set True if you wish to see voltage values 
			of the internal nodes added automatically by the simulator.
		"""
		self.timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
		self.netlist_file = circ.filename
		self.netlist_title = circ.title
		self.vea = options.vea
		self.ver = options.ver
		self.iea = options.iea
		self.ier = options.ier
		self.gmin = options.gmin
		self.temp = constants.T # in Kelvin
		self.filename = outfile
		self.iterations = iterations

		#We have mixed current and voltage results
		# per primi vengono tanti valori di tensioni quanti sono i nodi del circuito meno uno,
		# quindi tante correnti quanti sono gli elementi definiti in tensione presenti
		# (per questo, per misurare una corrente, si può fare uso di generatori di tensione da 0V)
	
		nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
		self.skip_nodes_list = []	      # nodi da saltare, solo interni
		self.variables = []
		self.results = case_insensitive_dict()
		self.errors = case_insensitive_dict()
		self.units = case_insensitive_dict()
		self.x = x
	
		for index in range(nv_1):
			varname = ("V" + str(circ.nodes_dict[index + 1])).upper()
			self.variables += [varname]
			self.results.update({varname:x[index, 0]})
			self.errors.update({varname:error[index, 0]})
			self.units.update({varname:"V"})
			#if circ.is_int_node_internal_only(index+1):
			#	self.skip_nodes_list.append(index)

		for elem in circ.elements:
			if circuit.is_elem_voltage_defined(elem):
				index = index + 1
				varname = ("I("+elem.letter_id.upper()+elem.descr+")").upper()
				self.variables += [varname]
				self.results.update({varname:x[index, 0]})
				self.errors.update({varname:error[index, 0]})
				self.units.update({varname:"A"})

		self.op_info = self.get_elements_op(circ, x)
예제 #23
0
	def __init__(self, circ, start, stop, sweepvar, stype, outfile):
		"""Holds a set of DC results.
			circ: the circuit instance of the simulated circuit
			start: the sweep start value
			stop: the sweep stop value
			sweepvar: the swept variable
			stype: type of sweep
			outfile: the file to write the results to. 
			         (Use "stdout" to write to std output)
		"""
		self.timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
		self.netlist_file = circ.filename
		self.netlist_title = circ.title
		self.vea = options.vea
		self.ver = options.ver
		self.iea = options.iea
		self.ier = options.ier
		self.gmin = options.gmin
		self.temp = constants.T
		self.start, self.stop = start, stop
		self.stype = stype
		self.filename = outfile

		self._init_file_done = False

		#We have mixed current and voltage results
		# per primi vengono tanti valori di tensioni quanti sono i nodi del circuito meno uno,
		# quindi tante correnti quanti sono gli elementi definiti in tensione presenti
		# (per questo, per misurare una corrente, si può fare uso di generatori di tensione da 0V)
	
		nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
		self.skip_nodes_list = []	# nodi da saltare, solo interni
		self.variables = [sweepvar]
		self.units = case_insensitive_dict()		
		if self.variables[0][0] == 'V':
			self.units.update({self.variables[0]:'V'})
		if self.variables[0][0] == 'I':
			self.units.update({self.variables[0]:'A'})
	
		for index in range(nv_1):
			varname = "V%s" % (str(circ.nodes_dict[index + 1]),)
			self.variables += [varname]
			self.units.update({varname:"V"})
			if circ.is_int_node_internal_only(index+1):
				skip_nodes_list.append(index)

		for elem in circ.elements: 
			if circuit.is_elem_voltage_defined(elem):
				varname = "I(%s)" % (elem.letter_id.upper()+elem.descr,)
				self.variables += [varname]
				self.units.update({varname:"A"})
예제 #24
0
파일: results.py 프로젝트: vovkd/ahkab
	def __init__(self, circ, start, stop, sweepvar, stype, outfile):
		"""Holds a set of DC results.
			circ: the circuit instance of the simulated circuit
			start: the sweep start value
			stop: the sweep stop value
			sweepvar: the swept variable
			stype: type of sweep
			outfile: the file to write the results to. 
			         (Use "stdout" to write to std output)
		"""
		self.timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
		self.netlist_file = circ.filename
		self.netlist_title = circ.title
		self.vea = options.vea
		self.ver = options.ver
		self.iea = options.iea
		self.ier = options.ier
		self.gmin = options.gmin
		self.temp = constants.T
		self.start, self.stop = start, stop
		self.stype = stype
		self.filename = outfile

		self._init_file_done = False

		#We have mixed current and voltage results
		# per primi vengono tanti valori di tensioni quanti sono i nodi del circuito meno uno,
		# quindi tante correnti quanti sono gli elementi definiti in tensione presenti
		# (per questo, per misurare una corrente, si può fare uso di generatori di tensione da 0V)
	
		nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
		self.skip_nodes_list = []	# nodi da saltare, solo interni
		self.variables = [sweepvar]
		self.units = case_insensitive_dict()		
		if self.variables[0][0] == 'V':
			self.units.update({self.variables[0]:'V'})
		if self.variables[0][0] == 'I':
			self.units.update({self.variables[0]:'A'})
	
		for index in range(nv_1):
			varname = "V%s" % (str(circ.nodes_dict[index + 1]),)
			self.variables += [varname]
			self.units.update({varname:"V"})
			if circ.is_int_node_internal_only(index+1):
				skip_nodes_list.append(index)

		for elem in circ.elements: 
			if circuit.is_elem_voltage_defined(elem):
				varname = "I(%s)" % (elem.letter_id.upper()+elem.descr,)
				self.variables += [varname]
				self.units.update({varname:"A"})
예제 #25
0
def print_dc_results(x, error, circ, print_int_nodes=False, print_error=True):
    """Prints out a set of DC results.
	x: the result set
	error: the residual error after solution,
	circ: the circuit instance of the simulated circuit
	print_int_nodes: a boolean to be set True if you wish to see voltage values 
	of the internal nodes added automatically by the simulator.
	
	Returns: None
	"""
    #We have mixed current and voltage results
    # per primi vengono tanti valori di tensioni quanti sono i nodi del circuito meno uno,
    # quindi tante correnti quanti sono gli elementi definiti in tensione presenti
    # (per questo, per misurare una corrente, si può fare uso di generatori di tensione da 0V)

    nv_1 = len(circ.nodes_dict
               ) - 1  # numero di soluzioni di tensione (al netto del ref)
    skip_nodes_list = []  # nodi da saltare, solo interni

    # descrizioni dei componenti non definibili in tensione
    idescr = [ (elem.letter_id.upper() + elem.descr) \
     for elem in circ.elements if circuit.is_elem_voltage_defined(elem) ] #cleaner ??

    print_array = []
    #print "Solution:"
    for index in xrange(x.shape[0]):
        if index < nv_1:
            if print_int_nodes or not circ.is_int_node_internal_only(index +
                                                                     1):
                line_array = [
                    "V" + str(circ.nodes_dict[index + 1]) + ":",
                    str(x[index, 0]), "V"
                ]
                if print_error:
                    line_array.append("(" + str(float(error[index])) + ")")
            else:
                skip_nodes_list.append(index)
        else:
            line_array = [
                "I(" + idescr[index - nv_1] + "):",
                str(x[index, 0]), "A"
            ]
            if print_error:
                line_array.append("(" + str(float(error[index])) + ")")
        print_array.append(line_array)

    table_print(print_array)

    return None
예제 #26
0
	def __init__(self, circ, tstart, tstop, op, method, outfile):
		"""Holds a set of TRANSIENT results.
			circ: the circuit instance of the simulated circuit
			tstart: the sweep starting angular frequency
			tstop: the sweep stopping frequency
			op: the op used to start the tran analysis
			outfile: the file to write the results to. 
			         (Use "stdout" to write to std output)
		"""
		self.timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
		self.netlist_file = circ.filename
		self.netlist_title = circ.title
		self.vea = options.vea
		self.ver = options.ver
		self.iea = options.iea
		self.ier = options.ier
		self.gmin = options.gmin
		self.temp = constants.T
		self.start_op = op
		self.tstart, self.tstop = tstart, tstop
		self.filename = outfile
		self.method = method

		self._init_file_done = False
		self._lock = False

		#We have mixed current and voltage results
		# per primi vengono tanti valori di tensioni quanti sono i nodi del circuito meno uno,
		# quindi tante correnti quanti sono gli elementi definiti in tensione presenti
		# (per questo, per misurare una corrente, si può fare uso di generatori di tensione da 0V)
	
		nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
		self.skip_nodes_list = []	# nodi da saltare, solo interni
		self.variables = ["T"]
		self.units = case_insensitive_dict()
		self.units.update({"T":"s"})
	
		for index in range(nv_1):
			varname = ("V%s" % (str(circ.nodes_dict[index + 1]),)).upper()
			self.variables += [varname]
			self.units.update({varname:"V"})
			if circ.is_int_node_internal_only(index+1):
				skip_nodes_list.append(index)

		for elem in circ.elements: 
			if circuit.is_elem_voltage_defined(elem):
				varname = ("I(%s)" % (elem.letter_id.upper()+elem.descr,)).upper()
				self.variables += [varname]
				self.units.update({varname:"A"})
예제 #27
0
파일: results.py 프로젝트: vovkd/ahkab
	def __init__(self, circ, tstart, tstop, op, method, outfile):
		"""Holds a set of TRANSIENT results.
			circ: the circuit instance of the simulated circuit
			tstart: the sweep starting angular frequency
			tstop: the sweep stopping frequency
			op: the op used to start the tran analysis
			outfile: the file to write the results to. 
			         (Use "stdout" to write to std output)
		"""
		self.timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
		self.netlist_file = circ.filename
		self.netlist_title = circ.title
		self.vea = options.vea
		self.ver = options.ver
		self.iea = options.iea
		self.ier = options.ier
		self.gmin = options.gmin
		self.temp = constants.T
		self.start_op = op
		self.tstart, self.tstop = tstart, tstop
		self.filename = outfile
		self.method = method

		self._init_file_done = False
		self._lock = False

		#We have mixed current and voltage results
		# per primi vengono tanti valori di tensioni quanti sono i nodi del circuito meno uno,
		# quindi tante correnti quanti sono gli elementi definiti in tensione presenti
		# (per questo, per misurare una corrente, si può fare uso di generatori di tensione da 0V)
	
		nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
		self.skip_nodes_list = []	# nodi da saltare, solo interni
		self.variables = ["T"]
		self.units = case_insensitive_dict()
		self.units.update({"T":"s"})
	
		for index in range(nv_1):
			varname = ("V%s" % (str(circ.nodes_dict[index + 1]),)).upper()
			self.variables += [varname]
			self.units.update({varname:"V"})
			if circ.is_int_node_internal_only(index+1):
				skip_nodes_list.append(index)

		for elem in circ.elements: 
			if circuit.is_elem_voltage_defined(elem):
				varname = ("I(%s)" % (elem.letter_id.upper()+elem.descr,)).upper()
				self.variables += [varname]
				self.units.update({varname:"A"})
예제 #28
0
	def __init__(self, circ, nkeys, outfile):
		"""Holds a set of MONTE CARLO results.
			circ: the circuit instance of the simulated circuit
			nkeys: number of random number needed for each point
			outfile: the file to write the results to. 
			         (Use "stdout" to write to std output)
		"""
		self.timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
		self.netlist_file = circ.filename
		self.netlist_title = circ.title
		self.vea = options.vea
		self.ver = options.ver
		self.iea = options.iea
		self.ier = options.ier
		self.gmin = options.gmin
		self.temp = constants.T
		self.nkeys = nkeys
		self.filename = outfile

		#We have mixed current and voltage results
		# per primi vengono tanti valori di tensioni quanti sono i nodi del circuito meno uno,
		# quindi tante correnti quanti sono gli elementi definiti in tensione presenti
		# (per questo, per misurare una corrente, si può fare uso di generatori di tensione da 0V)
	
		self.variables = []
		nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
		self.skip_nodes_list = []	# nodi da saltare, solo interni
		self.units = case_insensitive_dict()		
	
		for index in range(nv_1):
			varname = "V%s" % (str(circ.nodes_dict[index + 1]),)
			self.variables += [varname]
			self.units.update({varname:"V"})
			if circ.is_int_node_internal_only(index+1):
				skip_nodes_list.append(index)

		for elem in circ.elements: 
			if circuit.is_elem_voltage_defined(elem):
				varname = "I(%s)" % (elem.letter_id.upper()+elem.descr,)
				self.variables += [varname]
				self.units.update({varname:"A"})

		# the keys get stored along with the simulation results
		for i in range(self.nkeys):
			varname = "MCKEY%d" % (i,)
			self.variables += [varname]
			self.units.update({varname:""})
		csvlib.write_headers(self.filename, copy.copy(self.variables))
예제 #29
0
파일: results.py 프로젝트: vovkd/ahkab
	def __init__(self, circ, nkeys, outfile):
		"""Holds a set of MONTE CARLO results.
			circ: the circuit instance of the simulated circuit
			nkeys: number of random number needed for each point
			outfile: the file to write the results to. 
			         (Use "stdout" to write to std output)
		"""
		self.timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime())
		self.netlist_file = circ.filename
		self.netlist_title = circ.title
		self.vea = options.vea
		self.ver = options.ver
		self.iea = options.iea
		self.ier = options.ier
		self.gmin = options.gmin
		self.temp = constants.T
		self.nkeys = nkeys
		self.filename = outfile

		#We have mixed current and voltage results
		# per primi vengono tanti valori di tensioni quanti sono i nodi del circuito meno uno,
		# quindi tante correnti quanti sono gli elementi definiti in tensione presenti
		# (per questo, per misurare una corrente, si può fare uso di generatori di tensione da 0V)
	
		self.variables = []
		nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
		self.skip_nodes_list = []	# nodi da saltare, solo interni
		self.units = case_insensitive_dict()		
	
		for index in range(nv_1):
			varname = "V%s" % (str(circ.nodes_dict[index + 1]),)
			self.variables += [varname]
			self.units.update({varname:"V"})
			if circ.is_int_node_internal_only(index+1):
				skip_nodes_list.append(index)

		for elem in circ.elements: 
			if circuit.is_elem_voltage_defined(elem):
				varname = "I(%s)" % (elem.letter_id.upper()+elem.descr,)
				self.variables += [varname]
				self.units.update({varname:"A"})

		# the keys get stored along with the simulation results
		for i in range(self.nkeys):
			varname = "MCKEY%d" % (i,)
			self.variables += [varname]
			self.units.update({varname:""})
		csvlib.write_headers(self.filename, copy.copy(self.variables))
예제 #30
0
파일: printing.py 프로젝트: vovkd/ahkab
def print_results_header(circ, fp, print_int_nodes=False, print_time=False, print_omega=False):
    """Prints the header of the results.
	circ, a circuit instance
	fp, the file pointer to which the header should be written
	print_int_nodes=False, Print internal nodes
	print_time=False, Print the time (it's always the first column)
	
	Returns: None
	"""
    voltage_labels = []
    for n in range(1, len(circ.nodes_dict)):
        if print_int_nodes or not circ.is_int_node_internal_only(n):
            if print_omega == False:
                iter_voltage_labels = ["V" + circ.nodes_dict[n]]
            else:
                iter_voltage_labels = ["|V" + circ.nodes_dict[n] + "|", "arg(V" + circ.nodes_dict[n] + ")"]
            voltage_labels = voltage_labels + iter_voltage_labels

    current_labels = []
    for elem in circ.elements:
        if circuit.is_elem_voltage_defined(elem):
            if print_omega == False:
                iter_current_labels = ["I(" + elem.letter_id.upper() + elem.descr + ")"]
            else:
                iter_current_labels = [
                    "|I(" + elem.letter_id.upper() + elem.descr + ")|",
                    "arg(I(" + elem.letter_id.upper() + elem.descr + "))",
                ]
            current_labels = current_labels + iter_current_labels

    labels = voltage_labels + current_labels

    if print_time:
        labels.insert(0, "#T")
    elif print_omega:
        labels.insert(0, "#w")
    else:
        labels[0] = "#" + labels[0]

    for lab in labels:
        fp.write(lab + "\t")
    fp.write("\n")
    fp.flush()

    return None
예제 #31
0
def build_x0_from_user_supplied_ic(circ, icdict):
    """Builds a numpy.matrix of appropriate size (reduced!) from the values supplied
    in voltages_dict and currents_dict.

    Supplying a custom x0 can be useful:
    - To aid convergence in tough circuits.
    - To start a transient simulation from a particular x0

    Parameters:
    circ: the circuit instance
    icdict: a dictionary assembled as follows:
            - to specify a nodal voltage: {'V(node)':<voltage value>}
              Eg {'V(n1)':2.3, 'V(n2)':0.45, ...}
              All unspecified voltages default to 0.
            - to specify a branch current: 'I(<element>)':<voltage value>}
              ie. the elements names are sorrounded by I(...).
              Eg. {'I(L1)':1.03e-3, I(V4):2.3e-6, ...}
              All unspecified currents default to 0.

    Notes: this simulator uses the normal convention.

    Returns:
    The x0 matrix assembled according to icdict
    """
    Vregex = re.compile("V\s*\(\s*(\w?)\s*\)", re.IGNORECASE | re.DOTALL)
    Iregex = re.compile("I\s*\(\s*(\w?)\s*\)", re.IGNORECASE | re.DOTALL)
    nv = len(circ.nodes_dict)  # number of voltage variables
    voltage_defined_elem_names = \
        [elem.part_id for elem in circ if circuit.is_elem_voltage_defined(
            elem)]
    voltage_defined_elem_names = map(str.lower, voltage_defined_elem_names)
    ni = len(voltage_defined_elem_names)  # number of current variables
    x0 = numpy.mat(numpy.zeros((nv + ni, 1)))
    for label, value in icdict.iteritems():
        if Vregex.search(label):
            ext_node = Vregex.findall(label)[0]
            int_node = circ.ext_node_to_int(ext_node)
            x0[int_node, 0] = value
        elif Iregex.search(label):
            element_name = Iregex.findall(label)[0]
            index = voltage_defined_elem_names.index(element_name)
            x0[nv + index, 0] = value
        else:
            raise ValueError, "Unrecognized label " + label
    return x0[1:, :]
예제 #32
0
파일: symbolic.py 프로젝트: vovkd/ahkab
def get_variables(circ):
	"""Returns a sympy matrix with the circuit variables to be solved for.
	"""
	nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
	
	# descrizioni dei componenti non definibili in tensione
	idescr = [ (elem.letter_id.upper() + elem.descr) \
		for elem in circ.elements if circuit.is_elem_voltage_defined(elem) ]

	mna_size = nv_1 + len(idescr)
	x = smzeros((mna_size, 1))

	for i in range(mna_size):
		if i < nv_1:
			x[i, 0] = sympy.Symbol("V" + str(circ.nodes_dict[i + 1]))
		else:
			x[i, 0] = sympy.Symbol("I["+idescr[i - nv_1]+"]")
	return x
예제 #33
0
def get_variables(circ):
	"""Returns a sympy matrix with the circuit variables to be solved for.
	"""
	nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
	
	# descrizioni dei componenti non definibili in tensione
	idescr = [ (elem.letter_id.upper() + elem.descr) \
		for elem in circ.elements if circuit.is_elem_voltage_defined(elem) ]

	mna_size = nv_1 + len(idescr)
	x = smzeros((mna_size, 1))

	for i in range(mna_size):
		if i < nv_1:
			x[i, 0] = sympy.Symbol("V" + str(circ.nodes_dict[i + 1]))
		else:
			x[i, 0] = sympy.Symbol("I["+idescr[i - nv_1]+"]")
	return x
예제 #34
0
파일: printing.py 프로젝트: vovkd/ahkab
def print_dc_results(x, error, circ, print_int_nodes=False, print_error=True):
    """Prints out a set of DC results.
	x: the result set
	error: the residual error after solution,
	circ: the circuit instance of the simulated circuit
	print_int_nodes: a boolean to be set True if you wish to see voltage values 
	of the internal nodes added automatically by the simulator.
	
	Returns: None
	"""
    # We have mixed current and voltage results
    # per primi vengono tanti valori di tensioni quanti sono i nodi del circuito meno uno,
    # quindi tante correnti quanti sono gli elementi definiti in tensione presenti
    # (per questo, per misurare una corrente, si può fare uso di generatori di tensione da 0V)

    nv_1 = len(circ.nodes_dict) - 1  # numero di soluzioni di tensione (al netto del ref)
    skip_nodes_list = []  # nodi da saltare, solo interni

    # descrizioni dei componenti non definibili in tensione
    idescr = [
        (elem.letter_id.upper() + elem.descr) for elem in circ.elements if circuit.is_elem_voltage_defined(elem)
    ]  # cleaner ??

    print_array = []
    # print "Solution:"
    for index in xrange(x.shape[0]):
        if index < nv_1:
            if print_int_nodes or not circ.is_int_node_internal_only(index + 1):
                line_array = ["V" + str(circ.nodes_dict[index + 1]) + ":", str(x[index, 0]), "V"]
                if print_error:
                    line_array.append("(" + str(float(error[index])) + ")")
            else:
                skip_nodes_list.append(index)
        else:
            line_array = ["I(" + idescr[index - nv_1] + "):", str(x[index, 0]), "A"]
            if print_error:
                line_array.append("(" + str(float(error[index])) + ")")
        print_array.append(line_array)

    table_print(print_array)

    return None
예제 #35
0
    def __init__(self, x, error, circ, outfile, iterations=0):
        """Holds a set of Operating Point results.
            x: the result set
            error: the residual error after solution,
            circ: the circuit instance of the simulated circuit
            print_int_nodes: a boolean to be set True if you wish to see voltage values 
            of the internal nodes added automatically by the simulator.
        """
        solution.__init__(self, circ, outfile)
        self.iterations = iterations

        # We have mixed current and voltage results
        # per primi vengono tanti valori di tensioni quanti sono i nodi del circuito meno
        # uno, quindi tante correnti quanti sono gli elementi definiti in tensione presenti
        # (per questo, per misurare una corrente, si può fare uso di generatori di tensione
        # da 0V)

        nv_1 = len(circ.nodes_dict
                   ) - 1  # numero di soluzioni di tensione (al netto del ref)
        self.results = case_insensitive_dict()
        self.errors = case_insensitive_dict()
        self.x = x

        for index in range(nv_1):
            varname = ("V" + str(circ.nodes_dict[index + 1])).upper()
            self.variables += [varname]
            self.results.update({varname: x[index, 0]})
            self.errors.update({varname: error[index, 0]})
            self.units.update({varname: "V"})
            if circ.is_int_node_internal_only(index + 1):
                self.skip_nodes_list.append(index)

        for elem in circ:
            if circuit.is_elem_voltage_defined(elem):
                index = index + 1
                varname = ("I(" + elem.part_id.upper() + ")").upper()
                self.variables += [varname]
                self.results.update({varname: x[index, 0]})
                self.errors.update({varname: error[index, 0]})
                self.units.update({varname: "A"})

        self.op_info = self.get_elements_op(circ, x)
예제 #36
0
파일: results.py 프로젝트: manasdas17/ahkab
    def __init__(self, x, error, circ, outfile, iterations=0):
        """Holds a set of Operating Point results.
            x: the result set
            error: the residual error after solution,
            circ: the circuit instance of the simulated circuit
            print_int_nodes: a boolean to be set True if you wish to see voltage values 
            of the internal nodes added automatically by the simulator.
        """
        solution.__init__(self, circ, outfile)
        self.iterations = iterations

        # We have mixed current and voltage results
        # per primi vengono tanti valori di tensioni quanti sono i nodi del circuito meno 
        # uno, quindi tante correnti quanti sono gli elementi definiti in tensione presenti
        # (per questo, per misurare una corrente, si può fare uso di generatori di tensione 
        # da 0V)
    
        nv_1 = len(circ.nodes_dict) - 1 # numero di soluzioni di tensione (al netto del ref)
        self.results = case_insensitive_dict()
        self.errors = case_insensitive_dict()
        self.x = x
    
        for index in range(nv_1):
            varname = ("V" + str(circ.nodes_dict[index + 1])).upper()
            self.variables += [varname]
            self.results.update({varname: x[index, 0]})
            self.errors.update({varname: error[index, 0]})
            self.units.update({varname: "V"})
            if circ.is_int_node_internal_only(index+1):
                self.skip_nodes_list.append(index)

        for elem in circ:
            if circuit.is_elem_voltage_defined(elem):
                index = index + 1
                varname = ("I("+elem.part_id.upper()+")").upper()
                self.variables += [varname]
                self.results.update({varname: x[index, 0]})
                self.errors.update({varname: error[index, 0]})
                self.units.update({varname: "A"})

        self.op_info = self.get_elements_op(circ, x)
예제 #37
0
    def __init__(self,
                 circ,
                 method,
                 period,
                 outfile,
                 t_array=None,
                 x_array=None):
        """Holds a set of TRANSIENT results.
            circ: the circuit instance of the simulated circuit
            tstart: the sweep starting angular frequency
            tstop: the sweep stopping frequency
            op: the op used to start the tran analysis
            outfile: the file to write the results to. 
                     (Use "stdout" to write to std output)
        """
        solution.__init__(self, circ, outfile)
        self.period = period
        self.method = method

        # We have mixed current and voltage results
        nv_1 = len(circ.nodes_dict
                   ) - 1  # numero di soluzioni di tensione (al netto del ref)
        self.variables = ["T"]
        self.units.update({"T": "s"})

        for index in range(nv_1):
            varname = "V%s" % (str(circ.nodes_dict[index + 1]), )
            self.variables += [varname]
            self.units.update({varname: "V"})
            if circ.is_int_node_internal_only(index + 1):
                self.skip_nodes_list.append(index)

        for elem in circ:
            if circuit.is_elem_voltage_defined(elem):
                varname = "I(%s)" % (elem.part_id.upper(), )
                self.variables += [varname]
                self.units.update({varname: "A"})

        if t_array is not None and x_array is not None:
            self.set_results(t_array, x_array)
예제 #38
0
파일: ac.py 프로젝트: vovkd/ahkab
def generate_Nac(circ):
	"""Generate the vector holding the contribution of AC sources.
	"""
	n_of_nodes = len(circ.nodes_dict)
	Nac = numpy.mat(numpy.zeros((n_of_nodes, 1)), dtype=complex)
	j = numpy.complex('j')
	# process isources
	for elem in circ.elements:
		if isinstance(elem, devices.isource) and elem.abs_ac is not None:
			#convenzione normale!
			N[elem.n1, 0] = N[elem.n1, 0] + elem.abs_ac*numpy.exp(j*elem.arg_ac)
			N[elem.n2, 0] = N[elem.n2, 0] - elem.abs_ac*numpy.exp(j*elem.arg_ac)
	# process vsources
	# for each vsource, introduce a new variable: the current flowing through it.
	# then we introduce a KVL equation to be able to solve the circuit
	for elem in circ.elements:
		if circuit.is_elem_voltage_defined(elem):
			index = Nac.shape[0] 
			Nac = utilities.expand_matrix(Nac, add_a_row=True, add_a_col=False)
			if isinstance(elem, devices.vsource) and elem.abs_ac is not None:
				Nac[index, 0] = -1.0*elem.abs_ac*numpy.exp(j*elem.arg_ac)
	return Nac
예제 #39
0
def generate_Nac(circ):
	"""Generate the vector holding the contribution of AC sources.
	"""
	n_of_nodes = len(circ.nodes_dict)
	Nac = numpy.mat(numpy.zeros((n_of_nodes, 1)), dtype=complex)
	j = numpy.complex('j')
	# process isources
	for elem in circ.elements:
		if isinstance(elem, devices.isource) and elem.abs_ac is not None:
			#convenzione normale!
			N[elem.n1, 0] = N[elem.n1, 0] + elem.abs_ac*numpy.exp(j*elem.arg_ac)
			N[elem.n2, 0] = N[elem.n2, 0] - elem.abs_ac*numpy.exp(j*elem.arg_ac)
	# process vsources
	# for each vsource, introduce a new variable: the current flowing through it.
	# then we introduce a KVL equation to be able to solve the circuit
	for elem in circ.elements:
		if circuit.is_elem_voltage_defined(elem):
			index = Nac.shape[0] 
			Nac = utilities.expand_matrix(Nac, add_a_row=True, add_a_col=False)
			if isinstance(elem, devices.vsource) and elem.abs_ac is not None:
				Nac[index, 0] = -1.0*elem.abs_ac*numpy.exp(j*elem.arg_ac)
	return Nac
예제 #40
0
파일: shooting.py 프로젝트: vovkd/ahkab
def build_Tass_static_vector(circ,
                             Tf,
                             points,
                             step,
                             tick,
                             n_of_var,
                             verbose=3):
    Tass_vector = []
    nv = len(circ.nodes_dict)
    printing.print_info_line(("Building Tass...", 5), verbose, print_nl=False)

    tick.reset()
    tick.display(verbose > 2)
    for index in xrange(0, points):
        Tt = numpy.zeros((n_of_var, 1))
        v_eq = 0
        time = index * step
        for elem in circ.elements:
            if (isinstance(elem, devices.vsource) or isinstance(
                    elem, devices.isource)) and elem.is_timedependent:
                if isinstance(elem, devices.vsource):
                    Tt[nv - 1 + v_eq, 0] = -1.0 * elem.V(time)
                elif isinstance(elem, devices.isource):
                    if elem.n1:
                        Tt[elem.n1-1, 0] = \
                        Tt[elem.n1-1, 0] + elem.I(time)
                    if elem.n2:
                        Tt[elem.n2-1, 0] = \
                        Tt[elem.n2-1, 0] - elem.I(time)
            if circuit.is_elem_voltage_defined(elem):
                v_eq = v_eq + 1
        tick.step(verbose > 2)
        Tass_vector.append(Tf + Tt)
    tick.hide(verbose > 2)
    printing.print_info_line(("done.", 5), verbose)

    return Tass_vector
예제 #41
0
    def __init__(self, circ, ostart, ostop, opoints, stype, op, outfile):
        """Holds a set of AC results.
            circ: the circuit instance of the simulated circuit
            ostart: the sweep starting angular frequency
            ostop: the sweep stopping frequency
            stype: the sweep type
            op: the linearization op used to compute the results
        """
        solution.__init__(self, circ, outfile)
        self.linearization_op = op
        self.stype = stype
        self.ostart, self.ostop, self.opoints = ostart, ostop, opoints

        nv_1 = len(circ.nodes_dict
                   ) - 1  # numero di soluzioni di tensione (al netto del ref)
        self.variables += ["w"]
        self.units.update({"w": "rad/s"})

        for index in range(nv_1):
            varname_abs = "|V%s|" % (str(circ.nodes_dict[index + 1]), )
            varname_arg = "arg(V%s)" % (str(circ.nodes_dict[index + 1]), )
            self.variables += [varname_abs]
            self.variables += [varname_arg]
            self.units.update({varname_abs: "V"})
            self.units.update({varname_arg: ""})
            if circ.is_int_node_internal_only(index + 1):
                self.skip_nodes_list.append(index)

        for elem in circ:
            if circuit.is_elem_voltage_defined(elem):
                varname_abs = "|I(%s)|" % (elem.part_id.upper(), )
                varname_arg = "arg(I(%s))" % (elem.part_id.upper(), )
                self.variables += [varname_abs]
                self.variables += [varname_arg]
                self.units.update({varname_abs: "A"})
                self.units.update({varname_arg: ""})
예제 #42
0
파일: symbolic.py 프로젝트: itdaniher/ahkab
def generate_mna_and_N(circ, opts, ac=False, verbose=3):
    """Generates a symbolic Modified Nodal Analysis matrix and N vector.
    """
    #   print options
    n_of_nodes = len(circ.nodes_dict)
    mna = smzeros(n_of_nodes)
    N = smzeros((n_of_nodes, 1))
    s = sympy.Symbol('s', complex=True)
    subs_g = {}

    for elem in circ:
        if isinstance(elem, devices.Resistor):
            # we use conductances instead of 1/R because there is a significant
            # overhead handling many 1/R terms in sympy.
            if elem.is_symbolic:
                R = sympy.Symbol(elem.part_id.upper(),
                                 real=True,
                                 positive=True)
                G = sympy.Symbol('G' + elem.part_id[1:],
                                 real=True,
                                 positive=True)
                # but we keep track of which is which and substitute back after
                # solving.
                subs_g.update({G: 1 / R})
            else:
                R = elem.value
                G = 1.0 / R
            mna[elem.n1, elem.n1] = mna[elem.n1, elem.n1] + G
            mna[elem.n1, elem.n2] = mna[elem.n1, elem.n2] - G
            mna[elem.n2, elem.n1] = mna[elem.n2, elem.n1] - G
            mna[elem.n2, elem.n2] = mna[elem.n2, elem.n2] + G
        elif isinstance(elem, devices.Capacitor):
            if ac:
                if elem.is_symbolic:
                    capa = sympy.Symbol(elem.part_id.upper(),
                                        real=True,
                                        positive=True)
                else:
                    capa = elem.value
                mna[elem.n1, elem.n1] = mna[elem.n1, elem.n1] + s * capa
                mna[elem.n1, elem.n2] = mna[elem.n1, elem.n2] - s * capa
                mna[elem.n2, elem.n2] = mna[elem.n2, elem.n2] + s * capa
                mna[elem.n2, elem.n1] = mna[elem.n2, elem.n1] - s * capa
            else:
                pass
        elif isinstance(elem, devices.Inductor):
            pass
        elif isinstance(elem, devices.GISource):
            if elem.is_symbolic:
                alpha = sympy.Symbol(elem.part_id.upper(), real=True)
            else:
                alpha = elem.value
            mna[elem.n1, elem.sn1] = mna[elem.n1, elem.sn1] + alpha
            mna[elem.n1, elem.sn2] = mna[elem.n1, elem.sn2] - alpha
            mna[elem.n2, elem.sn1] = mna[elem.n2, elem.sn1] - alpha
            mna[elem.n2, elem.sn2] = mna[elem.n2, elem.sn2] + alpha
        elif isinstance(elem, devices.ISource):
            if elem.is_symbolic:
                IDC = sympy.Symbol(elem.part_id.upper(), real=True)
            else:
                IDC = elem.dc_value
            N[elem.n1, 0] = N[elem.n1, 0] + IDC
            N[elem.n2, 0] = N[elem.n2, 0] - IDC
        elif isinstance(elem, mosq.mosq_device) or isinstance(
                elem, ekv.ekv_device):
            gm = sympy.Symbol('gm_' + elem.part_id, real=True, positive=True)
            mna[elem.n1, elem.ng] = mna[elem.n1, elem.ng] + gm
            mna[elem.n1, elem.n2] = mna[elem.n1, elem.n2] - gm
            mna[elem.n2, elem.ng] = mna[elem.n2, elem.ng] - gm
            mna[elem.n2, elem.n2] = mna[elem.n2, elem.n2] + gm
            if opts['r0s']:
                r0 = sympy.Symbol('r0_' + elem.part_id,
                                  real=True,
                                  positive=True)
                mna[elem.n1, elem.n1] = mna[elem.n1, elem.n1] + 1 / r0
                mna[elem.n1, elem.n2] = mna[elem.n1, elem.n2] - 1 / r0
                mna[elem.n2, elem.n1] = mna[elem.n2, elem.n1] - 1 / r0
                mna[elem.n2, elem.n2] = mna[elem.n2, elem.n2] + 1 / r0
        elif isinstance(elem, diode.diode):
            gd = sympy.Symbol("g" + elem.part_id, positive=True)
            mna[elem.n1, elem.n1] = mna[elem.n1, elem.n1] + gd
            mna[elem.n1, elem.n2] = mna[elem.n1, elem.n2] - gd
            mna[elem.n2, elem.n1] = mna[elem.n2, elem.n1] - gd
            mna[elem.n2, elem.n2] = mna[elem.n2, elem.n2] + gd
        elif isinstance(elem, devices.InductorCoupling):
            pass
            # this is taken care of within the inductors
        elif circuit.is_elem_voltage_defined(elem):
            pass
            # we'll add its lines afterwards
        elif verbose:
            printing.print_warning("Skipped elem %s: not implemented." %
                                   (elem.part_id.upper(), ))

    pre_vde = mna.shape[0]
    for elem in circ:
        if circuit.is_elem_voltage_defined(elem):
            index = mna.shape[0]  # get_matrix_size(mna)[0]
            mna = expand_matrix(mna, add_a_row=True, add_a_col=True)
            N = expand_matrix(N, add_a_row=True, add_a_col=False)
            # KCL
            mna[elem.n1, index] = +1
            mna[elem.n2, index] = -1
            # KVL
            mna[index, elem.n1] = +1
            mna[index, elem.n2] = -1
            if isinstance(elem, devices.VSource):
                if elem.is_symbolic:
                    VDC = sympy.Symbol(elem.part_id.upper(), real=True)
                else:
                    VDC = elem.dc_value
                N[index, 0] = -VDC
            elif isinstance(elem, devices.EVSource):
                if elem.is_symbolic:
                    alpha = sympy.Symbol(elem.part_id.upper(), real=True)
                else:
                    alpha = elem.alpha
                mna[index, elem.sn1] = -alpha
                mna[index, elem.sn2] = +alpha
            elif isinstance(elem, devices.Inductor):
                if ac:
                    if elem.is_symbolic:
                        L = sympy.Symbol(elem.part_id.upper(),
                                         real=True,
                                         positive=True)
                    else:
                        L = elem.L
                    mna[index, index] = -s * L
                else:
                    pass
                    # already so: commented out
                    # N[index,0] = 0
            elif isinstance(elem, devices.HVSource):
                printing.print_warning(
                    "symbolic.py: BUG - hvsources are not implemented yet.")
                sys.exit(33)

    for elem in circ:
        if circuit.is_elem_voltage_defined(elem):
            if isinstance(elem, devices.Inductor):
                if ac:
                    # find its index to know which column corresponds to its
                    # current
                    this_index = circ.find_vde_index(elem.part_id, verbose=0)
                    for cd in elem.coupling_devices:
                        if cd.is_symbolic:
                            M = sympy.Symbol(cd.part_id,
                                             real=True,
                                             positive=True)
                        else:
                            M = cd.K
                        # get `part_id` of the other inductor (eg. "L32")
                        other_id_wdescr = cd.get_other_inductor(elem.part_id)
                        # find its index to know which column corresponds to
                        # its current
                        other_index = circ.find_vde_index(other_id_wdescr,
                                                          verbose=0)
                        # add the term.
                        mna[pre_vde + this_index,
                            pre_vde + other_index] += -s * M
                else:
                    pass

    # all done
    return (mna, N, subs_g)
예제 #43
0
파일: dc_guess.py 프로젝트: vovkd/ahkab
def get_dc_guess(circ, verbose=3):
	"""This method tries to build a DC guess, according to what the
	elements suggest.
	A element can suggest its guess through the elem.dc_guess field.
	
	verbose: verbosity level (from 0 silent to 5 debug)
	
	Returns: the dc_guess (matrix) or None
	"""
	if verbose: 
		sys.stdout.write("Calculating guess: ")
		sys.stdout.flush()
	
	# A DC guess has meaning only if the circuit has NL elements
	if not circ.is_nonlinear():
		if verbose:
			print "skipped. (linear circuit)"
		return None
	
	
	if verbose > 3:
		print ""

	nv = len(circ.nodes_dict)
	M = numpy.mat(numpy.zeros((1, nv)))
	T = numpy.mat(numpy.zeros((1, 1)))
	index = 0
	v_eq = 0 # number of current equations
	one_element_with_dc_guess_found = False

	for elem in circ.elements:
		# In the meanwhile, check how many current equations are 
		# required to solve the circuit
		if circuit.is_elem_voltage_defined(elem):
			v_eq = v_eq + 1
		# This is the main focus: build a system of equations (M*x = T)
		if hasattr(elem, "dc_guess") and elem.dc_guess is not None:
			if not one_element_with_dc_guess_found:
				one_element_with_dc_guess_found = True
			if elem.is_nonlinear:
				port_index = 0
				for (n1, n2) in elem.ports:
					if n1 == n2:
						continue
					if index:
						M = utilities.expand_matrix(M, add_a_row=True, add_a_col=False)
						T = utilities.expand_matrix(T, add_a_row=True, add_a_col=False)
					M[index, n1] = +1
					M[index, n2] = -1
					T[index] = elem.dc_guess[port_index]
					port_index = port_index + 1
					index = index + 1
			else:
				if elem.n1 == elem.n2:
					continue
				if index:
					M = utilities.expand_matrix(M, add_a_row=True, add_a_col=False)
					T = utilities.expand_matrix(T, add_a_row=True, add_a_col=False)
				M[index, elem.n1] = +1
				M[index, elem.n2] = -1
				T[index] = elem.dc_guess[0]
				index = index + 1
	
	if verbose == 5:
		print "DBG: get_dc_guess(): M and T, no reduction"
		print M
		print T
	M = utilities.remove_row_and_col(M, rrow=10*M.shape[0], rcol=0)
	
	if not one_element_with_dc_guess_found:
		if verbose == 5:
			print "DBG: get_dc_guess(): no element has a dc_guess"
		elif verbose <= 3:
			print "skipped."
		return None
	
	# We wish to find the linearly dependent lines of the M matrix.
	# The matrix is made by +1, -1, 0 elements. 
	# Hence, if two lines are linearly dependent, one of these equations
	# has to be satisfied: (L1, L2 are two lines)
	# L1 + L2 = 0 (vector)
	# L2 - L1 = 0 (vector)
	# This is tricky, because I wish to remove lines of the matrix while
	# browsing it.
	# We browse the matrix by line from bottom up and compare each line 
	# with the upper lines. If a linearly dep. line is found, we remove 
	# the current line.
	# Then break from the loop, get the next line (bottom up), which is
	# the same we were considering before; compare with the upper lines..
	# Not optimal, but it works.
	for i in range(M.shape[0]-1, -1, -1):
		for j in range(i-1, -1, -1):
			#print i, j, M[i, :], M[j, :]
			dummy1 = M[i, :] - M[j, :]
			dummy2 = M[i, :] + M[j, :]
			if not dummy1.any() or not dummy2.any():
				#print "REM:", M[i, :]
				M = utilities.remove_row(M, rrow=i)
				T = utilities.remove_row(T, rrow=i)
				break
	if verbose == 5:
		print "DBG: get_dc_guess(): M and T, after removing LD lines"
		print M
		print T
			
	# Remove empty columns:
	# If a column is empty, we have no guess regarding the corresponding
	# node. It makes the matrix singular. -> Remove the col & remember
	# that we are _not_ calculating a guess for it.
	removed_index = []
	for i in range(M.shape[1]-1, -1, -1):
		if not M[:, i].any():
			M = utilities.remove_row_and_col(M, rrow=M.shape[0], rcol=i)
			removed_index.append(i)
	
	if verbose > 3:
		print "DBG: get_dc_guess(): M and T, after removing empty columns."
		print M
		print "T\n", T

	# Now, we have a set of equations to be solved.
	# There are three cases:
	# 1. The M matrix has a different number of rows and columns.
	#    We use the Moore-Penrose matrix inverse to get 
	#    the shortest length least squares solution to the problem
	#          M*x + T = 0
	# 2. The matrix is square.
	#    It seems that if the circuit is not pathological,
	#    we are likely to find a solution (the matrix has det != 0).
	#    I'm not sure about this though.
	
	if M.shape[0] != M.shape[1]:
		Rp = numpy.mat(numpy.linalg.pinv(M)) * T
	else: # case M.shape[0] == M.shape[1], use normal
		if numpy.linalg.det(M) != 0:
			try:
				Rp = numpy.linalg.inv(M) * T
			except numpy.linalg.linalg.LinAlgError:
				eig = numpy.linalg.eig(M)[0]
				cond = abs(eig).max()/abs(eig).min()
				if verbose:
					print "cond=" +str(cond)+". No guess."
				return None
		else:
			if verbose:
				print "Guess matrix is singular. No guess."
			return None
			

	# Now we want to:
	# 1. Add voltages for the nodes for which we have no clue to guess.
	# 2. Append to each vector of guesses the values for currents in 
	#    voltage defined elem.
	# Both them are set to 0
	for index in removed_index:
		Rp = numpy.concatenate(( \
		numpy.concatenate((Rp[:index, 0], \
		numpy.mat(numpy.zeros((1, 1)))), axis=0), \
		Rp[index:, 0]), axis=0)
	# add the 0s for the currents due to the voltage defined 
	# elements (we have no guess for those...)
	if v_eq > 0:
		Rp = numpy.concatenate((Rp, numpy.mat(numpy.zeros((v_eq, 1)))), axis=0)
	
	if verbose == 5:
		print circ.nodes_dict
	
	if verbose and verbose < 4:
		print "done."
	if verbose > 3:
		print "Guess:"
		print Rp
	
	return Rp
예제 #44
0
파일: dc_guess.py 프로젝트: vovkd/ahkab
def get_dc_guess(circ, verbose=3):
    """This method tries to build a DC guess, according to what the
	elements suggest.
	A element can suggest its guess through the elem.dc_guess field.
	
	verbose: verbosity level (from 0 silent to 5 debug)
	
	Returns: the dc_guess (matrix) or None
	"""
    if verbose:
        sys.stdout.write("Calculating guess: ")
        sys.stdout.flush()

    # A DC guess has meaning only if the circuit has NL elements
    if not circ.is_nonlinear():
        if verbose:
            print "skipped. (linear circuit)"
        return None

    if verbose > 3:
        print ""

    nv = len(circ.nodes_dict)
    M = numpy.mat(numpy.zeros((1, nv)))
    T = numpy.mat(numpy.zeros((1, 1)))
    index = 0
    v_eq = 0  # number of current equations
    one_element_with_dc_guess_found = False

    for elem in circ.elements:
        # In the meanwhile, check how many current equations are
        # required to solve the circuit
        if circuit.is_elem_voltage_defined(elem):
            v_eq = v_eq + 1
        # This is the main focus: build a system of equations (M*x = T)
        if hasattr(elem, "dc_guess") and elem.dc_guess is not None:
            if not one_element_with_dc_guess_found:
                one_element_with_dc_guess_found = True
            if elem.is_nonlinear:
                port_index = 0
                for (n1, n2) in elem.ports:
                    if n1 == n2:
                        continue
                    if index:
                        M = utilities.expand_matrix(M,
                                                    add_a_row=True,
                                                    add_a_col=False)
                        T = utilities.expand_matrix(T,
                                                    add_a_row=True,
                                                    add_a_col=False)
                    M[index, n1] = +1
                    M[index, n2] = -1
                    T[index] = elem.dc_guess[port_index]
                    port_index = port_index + 1
                    index = index + 1
            else:
                if elem.n1 == elem.n2:
                    continue
                if index:
                    M = utilities.expand_matrix(M,
                                                add_a_row=True,
                                                add_a_col=False)
                    T = utilities.expand_matrix(T,
                                                add_a_row=True,
                                                add_a_col=False)
                M[index, elem.n1] = +1
                M[index, elem.n2] = -1
                T[index] = elem.dc_guess[0]
                index = index + 1

    if verbose == 5:
        print "DBG: get_dc_guess(): M and T, no reduction"
        print M
        print T
    M = utilities.remove_row_and_col(M, rrow=10 * M.shape[0], rcol=0)

    if not one_element_with_dc_guess_found:
        if verbose == 5:
            print "DBG: get_dc_guess(): no element has a dc_guess"
        elif verbose <= 3:
            print "skipped."
        return None

    # We wish to find the linearly dependent lines of the M matrix.
    # The matrix is made by +1, -1, 0 elements.
    # Hence, if two lines are linearly dependent, one of these equations
    # has to be satisfied: (L1, L2 are two lines)
    # L1 + L2 = 0 (vector)
    # L2 - L1 = 0 (vector)
    # This is tricky, because I wish to remove lines of the matrix while
    # browsing it.
    # We browse the matrix by line from bottom up and compare each line
    # with the upper lines. If a linearly dep. line is found, we remove
    # the current line.
    # Then break from the loop, get the next line (bottom up), which is
    # the same we were considering before; compare with the upper lines..
    # Not optimal, but it works.
    for i in range(M.shape[0] - 1, -1, -1):
        for j in range(i - 1, -1, -1):
            #print i, j, M[i, :], M[j, :]
            dummy1 = M[i, :] - M[j, :]
            dummy2 = M[i, :] + M[j, :]
            if not dummy1.any() or not dummy2.any():
                #print "REM:", M[i, :]
                M = utilities.remove_row(M, rrow=i)
                T = utilities.remove_row(T, rrow=i)
                break
    if verbose == 5:
        print "DBG: get_dc_guess(): M and T, after removing LD lines"
        print M
        print T

    # Remove empty columns:
    # If a column is empty, we have no guess regarding the corresponding
    # node. It makes the matrix singular. -> Remove the col & remember
    # that we are _not_ calculating a guess for it.
    removed_index = []
    for i in range(M.shape[1] - 1, -1, -1):
        if not M[:, i].any():
            M = utilities.remove_row_and_col(M, rrow=M.shape[0], rcol=i)
            removed_index.append(i)

    if verbose > 3:
        print "DBG: get_dc_guess(): M and T, after removing empty columns."
        print M
        print "T\n", T

    # Now, we have a set of equations to be solved.
    # There are three cases:
    # 1. The M matrix has a different number of rows and columns.
    #    We use the Moore-Penrose matrix inverse to get
    #    the shortest length least squares solution to the problem
    #          M*x + T = 0
    # 2. The matrix is square.
    #    It seems that if the circuit is not pathological,
    #    we are likely to find a solution (the matrix has det != 0).
    #    I'm not sure about this though.

    if M.shape[0] != M.shape[1]:
        Rp = numpy.mat(numpy.linalg.pinv(M)) * T
    else:  # case M.shape[0] == M.shape[1], use normal
        if numpy.linalg.det(M) != 0:
            try:
                Rp = numpy.linalg.inv(M) * T
            except numpy.linalg.linalg.LinAlgError:
                eig = numpy.linalg.eig(M)[0]
                cond = abs(eig).max() / abs(eig).min()
                if verbose:
                    print "cond=" + str(cond) + ". No guess."
                return None
        else:
            if verbose:
                print "Guess matrix is singular. No guess."
            return None

    # Now we want to:
    # 1. Add voltages for the nodes for which we have no clue to guess.
    # 2. Append to each vector of guesses the values for currents in
    #    voltage defined elem.
    # Both them are set to 0
    for index in removed_index:
        Rp = numpy.concatenate(( \
        numpy.concatenate((Rp[:index, 0], \
        numpy.mat(numpy.zeros((1, 1)))), axis=0), \
        Rp[index:, 0]), axis=0)
    # add the 0s for the currents due to the voltage defined
    # elements (we have no guess for those...)
    if v_eq > 0:
        Rp = numpy.concatenate((Rp, numpy.mat(numpy.zeros((v_eq, 1)))), axis=0)

    if verbose == 5:
        print circ.nodes_dict

    if verbose and verbose < 4:
        print "done."
    if verbose > 3:
        print "Guess:"
        print Rp

    return Rp
예제 #45
0
def generate_mna_and_N(circ, verbose=3):
    """La vecchia versione usava il sistema visto a lezione, quella nuova mira ad essere
    magari meno elegante, ma funzionale, flessibile e comprensibile.
    MNA e N vengono creati direttamente della dimensione det. dal numero dei nodi, poi se
    ci sono voltage sources vengono allargate.

    Il vettore incognita � fatto cos�:
    x vettore colonna di lunghezza (N_nodi - 1) + N_vsources, i primi N_nodi valori di x, corrispondono
    alle tensioni ai nodi, gli altri alle correnti nei generatori di tensione.
    Le tensioni nodali sono ordinate tramite i numeri interni dei nodi, in ordine CRESCENTE, saltando
    il nodo 0, preso a riferimento.
    L'ordine delle correnti nei gen di tensione � det. dall'ordine in cui essi vengono incontrati
    scorrendo `circ`. Viene sempre usata la convenzione normale.

    Il sistema � cos� fatto: MNA*x + N = 0

    Richiede in ingresso la descrizione del circuito, circ.
    Restituisce: (MNA, N)
    """
    n_of_nodes = len(circ.nodes_dict)
    mna = numpy.mat(numpy.zeros((n_of_nodes, n_of_nodes)))
    N = numpy.mat(numpy.zeros((n_of_nodes, 1)))
    for elem in circ:
        if elem.is_nonlinear:
            continue
        elif isinstance(elem, devices.Resistor):
            mna[elem.n1, elem.n1] = mna[elem.n1, elem.n1] + 1.0 / elem.value
            mna[elem.n1, elem.n2] = mna[elem.n1, elem.n2] - 1.0 / elem.value
            mna[elem.n2, elem.n1] = mna[elem.n2, elem.n1] - 1.0 / elem.value
            mna[elem.n2, elem.n2] = mna[elem.n2, elem.n2] + 1.0 / elem.value
        elif isinstance(elem, devices.Capacitor):
            pass  # In a capacitor I(V) = 0
        elif isinstance(elem, devices.GISource):
            mna[elem.n1, elem.sn1] = mna[elem.n1, elem.sn1] + elem.alpha
            mna[elem.n1, elem.sn2] = mna[elem.n1, elem.sn2] - elem.alpha
            mna[elem.n2, elem.sn1] = mna[elem.n2, elem.sn1] - elem.alpha
            mna[elem.n2, elem.sn2] = mna[elem.n2, elem.sn2] + elem.alpha
        elif isinstance(elem, devices.ISource):
            if not elem.is_timedependent:  # convenzione normale!
                N[elem.n1, 0] = N[elem.n1, 0] + elem.I()
                N[elem.n2, 0] = N[elem.n2, 0] - elem.I()
            else:
                pass  # vengono aggiunti volta per volta
        elif isinstance(elem, devices.InductorCoupling):
            pass
            # this is taken care of within the inductors
        elif circuit.is_elem_voltage_defined(elem):
            pass
            # we'll add its lines afterwards
        else:
            print "dc_analysis.py: BUG - Unknown linear element. Ref. #28934"
    # process vsources
    # i generatori di tensione non sono pilotabili in tensione: g � infinita
    # for each vsource, introduce a new variable: the current flowing through it.
    # then we introduce a KVL equation to be able to solve the circuit
    for elem in circ:
        if circuit.is_elem_voltage_defined(elem):
            index = mna.shape[0]  # get_matrix_size(mna)[0]
            mna = utilities.expand_matrix(mna, add_a_row=True, add_a_col=True)
            N = utilities.expand_matrix(N, add_a_row=True, add_a_col=False)
            # KCL
            mna[elem.n1, index] = 1.0
            mna[elem.n2, index] = -1.0
            # KVL
            mna[index, elem.n1] = +1.0
            mna[index, elem.n2] = -1.0
            if isinstance(elem, devices.VSource) and not elem.is_timedependent:
                # corretto, se � def una parte tempo-variabile ci pensa
                # mdn_solver a scegliere quella giusta da usare.
                N[index, 0] = -1.0 * elem.V()
            elif isinstance(elem, devices.VSource) and elem.is_timedependent:
                pass  # taken care step by step
            elif isinstance(elem, devices.EVSource):
                mna[index, elem.sn1] = -1.0 * elem.alpha
                mna[index, elem.sn2] = +1.0 * elem.alpha
            elif isinstance(elem, devices.Inductor):
                # N[index,0] = 0 pass, it's already zero
                pass
            elif isinstance(elem, devices.HVSource):
                print "dc_analysis.py: BUG - hvsources are not implemented yet."
                sys.exit(33)
            else:
                print "dc_analysis.py: BUG - found an unknown voltage_def elem."
                print elem
                sys.exit(33)

    # Seems a good place to run some sanity check
    # for the time being we do not halt the execution
    check_ground_paths(mna, circ, reduced_mna=False, verbose=verbose)

    # all done
    return (mna, N)
예제 #46
0
파일: dc_analysis.py 프로젝트: vovkd/ahkab
def dc_solve(
    mna, Ndc, circ, Ntran=None, Gmin=None, x0=None, time=None, MAXIT=None, locked_nodes=None, skip_Tt=False, verbose=3
):
    """Tries to perform a DC analysis of the circuit. 
	The system we want to solve is:
	(mna+Gmin)*x + N + T(x) = 0
	
	mna is the reduced mna matrix with the required KVL rows
	N is Ndc + Ntran
	T(x) will be built.
	
	circ is the circuit instance from which mna, N were built.
	
	x0 is the (optional) initial guess. If not specified, the all-zeros vector will be used
	
	This method is used ever by transient analysis. For transient analysis, time has to be set.
	In "real" DC analysis, time may be left to None. See circuit.py for more info about the default
	behaviour of time variant sources that also have a dc value.
	
	MAXIT is the maximum number of NR iteration to be supplied to mdn_solver.
	
	locked_nodes: array of tuples of nodes controlling non linear elements of the circuit.
	This is generated by circ.get_locked_nodes() and will be generated that way if left to none.
	However, if you are doing lots of simulations of the same circuit (a transient analysis), it's
	a good idea to generate it only once.

	Returns:
	(x, error, converged, tot_iterations)
	"""
    if MAXIT == None:
        MAXIT = options.dc_max_nr_iter
    if locked_nodes is None:
        locked_nodes = circ.get_locked_nodes()
    mna_size = mna.shape[0]
    nv = len(circ.nodes_dict)
    tot_iterations = 0

    if Gmin is None:
        Gmin = 0

    if Ntran is None:
        Ntran = 0

        # time variable component: Tt this is always the same in each iter. So we build it once for all.
    Tt = numpy.mat(numpy.zeros((mna_size, 1)))
    v_eq = 0
    if not skip_Tt:
        for elem in circ.elements:
            if (isinstance(elem, devices.vsource) or isinstance(elem, devices.isource)) and elem.is_timedependent:
                if isinstance(elem, devices.vsource):
                    Tt[nv - 1 + v_eq, 0] = -1 * elem.V(time)
                elif isinstance(elem, devices.isource):
                    if elem.n1:
                        Tt[elem.n1 - 1, 0] = Tt[elem.n1 - 1, 0] + elem.I(time)
                    if elem.n2:
                        Tt[elem.n2 - 1, 0] = Tt[elem.n2 - 1, 0] - elem.I(time)
            if circuit.is_elem_voltage_defined(elem):
                v_eq = v_eq + 1
                # update N to include the time variable sources
    Ndc = Ndc + Tt

    # initial guess, if specified, otherwise it's zero
    if x0 is not None:
        if isinstance(x0, results.op_solution):
            x = x0.asmatrix()
        else:
            x = x0
    else:
        x = numpy.mat(numpy.zeros((mna_size, 1)))  # has n-1 rows because of discard of ^^^

    converged = False
    standard_solving, gmin_stepping, source_stepping = get_solve_methods()
    standard_solving, gmin_stepping, source_stepping = set_next_solve_method(
        standard_solving, gmin_stepping, source_stepping, verbose
    )

    printing.print_info_line(("Solving... ", 3), verbose, print_nl=False)

    while not converged:
        if standard_solving["enabled"]:
            mna_to_pass = mna + Gmin
            N_to_pass = Ndc + Ntran * (Ntran is not None)
        elif gmin_stepping["enabled"]:
            # print "gmin index:", str(gmin_stepping["index"])+", gmin:", str( 10**(gmin_stepping["factors"][gmin_stepping["index"]]))
            printing.print_info_line(
                ("Setting Gmin to: " + str(10 ** gmin_stepping["factors"][gmin_stepping["index"]]), 6), verbose
            )
            mna_to_pass = (
                build_gmin_matrix(circ, 10 ** (gmin_stepping["factors"][gmin_stepping["index"]]), mna_size, verbose)
                + mna
            )
            N_to_pass = Ndc + Ntran * (Ntran is not None)
        elif source_stepping["enabled"]:
            printing.print_info_line(
                (
                    "Setting sources to "
                    + str(source_stepping["factors"][source_stepping["index"]] * 100)
                    + "% of their actual value",
                    6,
                ),
                verbose,
            )
            mna_to_pass = mna + Gmin
            N_to_pass = source_stepping["factors"][source_stepping["index"]] * Ndc + Ntran * (Ntran is not None)
        try:
            (x, error, converged, n_iter, convergence_by_node) = mdn_solver(
                x,
                mna_to_pass,
                circ,
                T=N_to_pass,
                nv=nv,
                print_steps=(verbose > 0),
                locked_nodes=locked_nodes,
                time=time,
                MAXIT=MAXIT,
                debug=(verbose == 6),
            )
            tot_iterations += n_iter
        except numpy.linalg.linalg.LinAlgError:
            n_iter = 0
            converged = False
            print "failed."
            printing.print_general_error("J Matrix is singular")
        except OverflowError:
            n_iter = 0
            converged = False
            print "failed."
            printing.print_general_error("Overflow")

        if not converged:
            if verbose == 6:
                for ivalue in range(len(convergence_by_node)):
                    if not convergence_by_node[ivalue] and ivalue < nv - 1:
                        print "Convergence problem node %s" % (circ.int_node_to_ext(ivalue),)
                    elif not convergence_by_node[ivalue] and ivalue >= nv - 1:
                        e = circ.find_vde(ivalue)
                        print "Convergence problem current in %s%s" % (e.letter_id, e.descr)
            if n_iter == MAXIT - 1:
                printing.print_general_error("Error: MAXIT exceeded (" + str(MAXIT) + ")")
            if more_solve_methods_available(standard_solving, gmin_stepping, source_stepping):
                standard_solving, gmin_stepping, source_stepping = set_next_solve_method(
                    standard_solving, gmin_stepping, source_stepping, verbose
                )
            else:
                # print "Giving up."
                x = None
                error = None
                break
        else:
            printing.print_info_line(("[%d iterations]" % (n_iter,), 6), verbose)
            if source_stepping["enabled"] and source_stepping["index"] != 9:
                converged = False
                source_stepping["index"] = source_stepping["index"] + 1
            elif gmin_stepping["enabled"] and gmin_stepping["index"] != 9:
                gmin_stepping["index"] = gmin_stepping["index"] + 1
                converged = False
            else:
                printing.print_info_line((" done.", 3), verbose)
    return (x, error, converged, tot_iterations)
예제 #47
0
def dc_solve(mna,
             Ndc,
             circ,
             Ntran=None,
             Gmin=None,
             x0=None,
             time=None,
             MAXIT=None,
             locked_nodes=None,
             skip_Tt=False,
             verbose=3):
    """Tries to perform a DC analysis of the circuit.
    The system we want to solve is:
    (mna+Gmin)*x + N + T(x) = 0

    mna is the reduced mna matrix with the required KVL rows
    N is Ndc + Ntran
    T(x) will be built.

    circ is the circuit instance from which mna, N were built.

    x0 is the (optional) initial guess. If not specified, the all-zeros vector will be used

    This method is used ever by transient analysis. For transient analysis, time has to be set.
    In "real" DC analysis, time may be left to None. See circuit.py for more info about the default
    behaviour of time variant sources that also have a dc value.

    MAXIT is the maximum number of NR iteration to be supplied to mdn_solver.

    locked_nodes: array of tuples of nodes controlling non linear elements of the circuit.
    This is generated by circ.get_locked_nodes() and will be generated that way if left to none.
    However, if you are doing lots of simulations of the same circuit (a transient analysis), it's
    a good idea to generate it only once.

    Returns:
    (x, error, converged, tot_iterations)
    """
    if MAXIT == None:
        MAXIT = options.dc_max_nr_iter
    if locked_nodes is None:
        locked_nodes = circ.get_locked_nodes()
    mna_size = mna.shape[0]
    nv = len(circ.nodes_dict)
    tot_iterations = 0

    if Gmin is None:
        Gmin = 0

    if Ntran is None:
        Ntran = 0

    # time variable component: Tt this is always the same in each iter. So we
    # build it once for all.
    Tt = numpy.mat(numpy.zeros((mna_size, 1)))
    v_eq = 0
    if not skip_Tt:
        for elem in circ:
            if (isinstance(elem, devices.VSource) or isinstance(
                    elem, devices.ISource)) and elem.is_timedependent:
                if isinstance(elem, devices.VSource):
                    Tt[nv - 1 + v_eq, 0] = -1 * elem.V(time)
                elif isinstance(elem, devices.ISource):
                    if elem.n1:
                        Tt[elem.n1 - 1, 0] = Tt[elem.n1 - 1, 0] + elem.I(time)
                    if elem.n2:
                        Tt[elem.n2 - 1, 0] = Tt[elem.n2 - 1, 0] - elem.I(time)
            if circuit.is_elem_voltage_defined(elem):
                v_eq = v_eq + 1
    # update N to include the time variable sources
    Ndc = Ndc + Tt

    # initial guess, if specified, otherwise it's zero
    if x0 is not None:
        if isinstance(x0, results.op_solution):
            x = x0.asmatrix()
        else:
            x = x0
    else:
        x = numpy.mat(numpy.zeros((mna_size, 1)))
        # has n-1 rows because of discard of ^^^

    converged = False
    standard_solving, gmin_stepping, source_stepping = get_solve_methods()
    standard_solving, gmin_stepping, source_stepping = set_next_solve_method(
        standard_solving, gmin_stepping, source_stepping, verbose)

    printing.print_info_line(("Solving... ", 3), verbose, print_nl=False)

    while (not converged):
        if standard_solving["enabled"]:
            mna_to_pass = mna + Gmin
            N_to_pass = Ndc + Ntran * (Ntran is not None)
        elif gmin_stepping["enabled"]:
            # print "gmin index:", str(gmin_stepping["index"])+", gmin:", str(
            # 10**(gmin_stepping["factors"][gmin_stepping["index"]]))
            printing.print_info_line(
                ("Setting Gmin to: " +
                 str(10**gmin_stepping["factors"][gmin_stepping["index"]]), 6),
                verbose)
            mna_to_pass = build_gmin_matrix(
                circ, 10**(gmin_stepping["factors"][gmin_stepping["index"]]),
                mna_size, verbose) + mna
            N_to_pass = Ndc + Ntran * (Ntran is not None)
        elif source_stepping["enabled"]:
            printing.print_info_line(("Setting sources to " + str(
                source_stepping["factors"][source_stepping["index"]] * 100) +
                                      "% of their actual value", 6), verbose)
            mna_to_pass = mna + Gmin
            N_to_pass = source_stepping["factors"][
                source_stepping["index"]] * Ndc + Ntran * (Ntran is not None)
        try:
            (x, error, converged, n_iter,
             convergence_by_node) = mdn_solver(x,
                                               mna_to_pass,
                                               circ,
                                               T=N_to_pass,
                                               nv=nv,
                                               print_steps=(verbose > 0),
                                               locked_nodes=locked_nodes,
                                               time=time,
                                               MAXIT=MAXIT,
                                               debug=(verbose == 6))
            tot_iterations += n_iter
        except numpy.linalg.linalg.LinAlgError:
            n_iter = 0
            converged = False
            print "failed."
            printing.print_general_error("J Matrix is singular")
        except OverflowError:
            n_iter = 0
            converged = False
            print "failed."
            printing.print_general_error("Overflow")

        if not converged:
            if verbose == 6:
                for ivalue in range(len(convergence_by_node)):
                    if not convergence_by_node[ivalue] and ivalue < nv - 1:
                        print "Convergence problem node %s" % (
                            circ.int_node_to_ext(ivalue), )
                    elif not convergence_by_node[ivalue] and ivalue >= nv - 1:
                        e = circ.find_vde(ivalue)
                        print "Convergence problem current in %s" % e.part_id
            if n_iter == MAXIT - 1:
                printing.print_general_error("Error: MAXIT exceeded (" +
                                             str(MAXIT) + ")")
            if more_solve_methods_available(standard_solving, gmin_stepping,
                                            source_stepping):
                standard_solving, gmin_stepping, source_stepping = set_next_solve_method(
                    standard_solving, gmin_stepping, source_stepping, verbose)
            else:
                # print "Giving up."
                x = None
                error = None
                break
        else:
            printing.print_info_line(("[%d iterations]" % (n_iter, ), 6),
                                     verbose)
            if (source_stepping["enabled"] and source_stepping["index"] != 9):
                converged = False
                source_stepping["index"] = source_stepping["index"] + 1
            elif (gmin_stepping["enabled"] and gmin_stepping["index"] != 9):
                gmin_stepping["index"] = gmin_stepping["index"] + 1
                converged = False
            else:
                printing.print_info_line((" done.", 3), verbose)
    return (x, error, converged, tot_iterations)
예제 #48
0
파일: dc_analysis.py 프로젝트: vovkd/ahkab
def generate_mna_and_N(circ):
    """La vecchia versione usava il sistema visto a lezione, quella nuova mira ad essere 
	magari meno elegante, ma funzionale, flessibile e comprensibile. 
	MNA e N vengono creati direttamente della dimensione det. dal numero dei nodi, poi se 
	ci sono voltage sources vengono allargate.
	
	Il vettore incognita � fatto cos�:
	x vettore colonna di lunghezza (N_nodi - 1) + N_vsources, i primi N_nodi valori di x, corrispondono
	alle tensioni ai nodi, gli altri alle correnti nei generatori di tensione.
	Le tensioni nodali sono ordinate tramite i numeri interni dei nodi, in ordine CRESCENTE, saltando
	il nodo 0, preso a riferimento.
	L'ordine delle correnti nei gen di tensione � det. dall'ordine in cui essi vengono incontrati 
	scorrendo circ.elements. Viene sempre usata la convenzione normale.
	
	Il sistema � cos� fatto: MNA*x + N = 0
	
	Richiede in ingresso la descrizione del circuito, circ.
	Restituisce: (MNA, N)
	"""
    n_of_nodes = len(circ.nodes_dict)
    mna = numpy.mat(numpy.zeros((n_of_nodes, n_of_nodes)))
    N = numpy.mat(numpy.zeros((n_of_nodes, 1)))
    for elem in circ.elements:
        if elem.is_nonlinear:
            continue
        elif isinstance(elem, devices.resistor):
            mna[elem.n1, elem.n1] = mna[elem.n1, elem.n1] + 1.0 / elem.R
            mna[elem.n1, elem.n2] = mna[elem.n1, elem.n2] - 1.0 / elem.R
            mna[elem.n2, elem.n1] = mna[elem.n2, elem.n1] - 1.0 / elem.R
            mna[elem.n2, elem.n2] = mna[elem.n2, elem.n2] + 1.0 / elem.R
        elif isinstance(elem, devices.capacitor):
            pass  # In a capacitor I(V) = 0
        elif isinstance(elem, devices.gisource):
            mna[elem.n1, elem.sn1] = mna[elem.n1, elem.sn1] + elem.alpha
            mna[elem.n1, elem.sn2] = mna[elem.n1, elem.sn2] - elem.alpha
            mna[elem.n2, elem.sn1] = mna[elem.n2, elem.sn1] - elem.alpha
            mna[elem.n2, elem.sn2] = mna[elem.n2, elem.sn2] + elem.alpha
        elif isinstance(elem, devices.isource):
            if not elem.is_timedependent:  # convenzione normale!
                N[elem.n1, 0] = N[elem.n1, 0] + elem.I()
                N[elem.n2, 0] = N[elem.n2, 0] - elem.I()
            else:
                pass  # vengono aggiunti volta per volta
        elif isinstance(elem, devices.inductor_coupling):
            pass
            # this is taken care of within the inductors
        elif circuit.is_elem_voltage_defined(elem):
            pass
            # we'll add its lines afterwards
        else:
            print "dc_analysis.py: BUG - Unknown linear element. Ref. #28934"
            # process vsources
            # i generatori di tensione non sono pilotabili in tensione: g � infinita
            # for each vsource, introduce a new variable: the current flowing through it.
            # then we introduce a KVL equation to be able to solve the circuit
    for elem in circ.elements:
        if circuit.is_elem_voltage_defined(elem):
            index = mna.shape[0]  # get_matrix_size(mna)[0]
            mna = utilities.expand_matrix(mna, add_a_row=True, add_a_col=True)
            N = utilities.expand_matrix(N, add_a_row=True, add_a_col=False)
            # KCL
            mna[elem.n1, index] = 1.0
            mna[elem.n2, index] = -1.0
            # KVL
            mna[index, elem.n1] = +1.0
            mna[index, elem.n2] = -1.0
            if isinstance(elem, devices.vsource) and not elem.is_timedependent:
                # corretto, se � def una parte tempo-variabile ci pensa
                # mdn_solver a scegliere quella giusta da usare.
                N[index, 0] = -1.0 * elem.V()
            elif isinstance(elem, devices.vsource) and elem.is_timedependent:
                pass  # taken care step by step
            elif isinstance(elem, devices.evsource):
                mna[index, elem.sn1] = -1.0 * elem.alpha
                mna[index, elem.sn2] = +1.0 * elem.alpha
            elif isinstance(elem, devices.inductor):
                # N[index,0] = 0 pass, it's already zero
                pass
            elif isinstance(elem, devices.hvsource):
                print "dc_analysis.py: BUG - hvsources are not implemented yet."
                sys.exit(33)
            else:
                print "dc_analysis.py: BUG - found an unknown voltage_def elem."
                print elem
                sys.exit(33)

                # Seems a good place to run some sanity check
                # for the time being we do not halt the execution
    check_ground_paths(mna, circ, reduced_mna=False)

    # all done
    return (mna, N)
예제 #49
0
파일: symbolic.py 프로젝트: vovkd/ahkab
def generate_mna_and_N(circ, opts, ac=False):
	"""Generates a symbolic Modified Nodal Analysis matrix and N vector.
	"""
	#print options
	n_of_nodes = len(circ.nodes_dict)
	mna = smzeros(n_of_nodes)
	N = smzeros((n_of_nodes, 1))
	s = sympy.Symbol("s", complex=True)
	subs_g = {}
	#process_elements() 	
	for elem in circ.elements:
		#if elem.is_nonlinear and not (isinstance(elem, mosq.mosq_device) or isinstance(elem, ekv.ekv_device)): 
		#	print "Skipped elem "+elem.letter_id.upper()+elem.descr + ": not implemented."	
		#	continue
		if isinstance(elem, devices.resistor):
			# we use conductances instead of 1/R because there is a significant
			# overhead handling many 1/R terms in sympy.
			if elem.is_symbolic:
				R = sympy.Symbol(elem.letter_id.upper()+elem.descr, real=True)
				G = sympy.Symbol("G"+elem.descr, real=True)
				# but we keep track of which is which and substitute back after solving.
				subs_g.update({G:1/R})
			else:
				R = elem.R
				G = 1.0/R
			#mna[elem.n1, elem.n1] = mna[elem.n1, elem.n1] + 1/R
			#mna[elem.n1, elem.n2] = mna[elem.n1, elem.n2] - 1/R
			#mna[elem.n2, elem.n1] = mna[elem.n2, elem.n1] - 1/R
			#mna[elem.n2, elem.n2] = mna[elem.n2, elem.n2] + 1/R
			mna[elem.n1, elem.n1] = mna[elem.n1, elem.n1] + G
			mna[elem.n1, elem.n2] = mna[elem.n1, elem.n2] - G
			mna[elem.n2, elem.n1] = mna[elem.n2, elem.n1] - G
			mna[elem.n2, elem.n2] = mna[elem.n2, elem.n2] + G
		elif isinstance(elem, devices.capacitor):
			if ac:
				if elem.is_symbolic:
					capa = sympy.Symbol(elem.letter_id.upper()+elem.descr, real=True)
				else:
					capa = elem.C
				mna[elem.n1, elem.n1] = mna[elem.n1, elem.n1] + s*capa
				mna[elem.n1, elem.n2] = mna[elem.n1, elem.n2] - s*capa
				mna[elem.n2, elem.n2] = mna[elem.n2, elem.n2] + s*capa
				mna[elem.n2, elem.n1] = mna[elem.n2, elem.n1] - s*capa
			else:
				pass
		elif isinstance(elem, devices.inductor):
			pass
		elif isinstance(elem, devices.gisource):
			if elem.is_symbolic:
				alpha = sympy.Symbol(elem.letter_id+elem.descr, real=True)
			else:
				alpha = elem.alpha
			mna[elem.n1, elem.sn1] = mna[elem.n1, elem.sn1] + alpha
			mna[elem.n1, elem.sn2] = mna[elem.n1, elem.sn2] - alpha
			mna[elem.n2, elem.sn1] = mna[elem.n2, elem.sn1] - alpha
			mna[elem.n2, elem.sn2] = mna[elem.n2, elem.sn2] + alpha
		elif isinstance(elem, devices.isource):
			if elem.is_symbolic:
				IDC = sympy.Symbol(elem.letter_id.upper()+elem.descr, real=True)
			else:
				IDC = elem.idc
			N[elem.n1, 0] = N[elem.n1, 0] + IDC
			N[elem.n2, 0] = N[elem.n2, 0] - IDC
		elif isinstance(elem, mosq.mosq_device) or isinstance(elem, ekv.ekv_device):
			gm = sympy.Symbol('gm_'+elem.letter_id+elem.descr, real=True)
			mna[elem.n1, elem.ng] = mna[elem.n1, elem.ng] + gm
			mna[elem.n1, elem.n2] = mna[elem.n1, elem.n2] - gm
			mna[elem.n2, elem.ng] = mna[elem.n2, elem.ng] - gm
			mna[elem.n2, elem.n2] = mna[elem.n2, elem.n2] + gm
			if opts['r0s']:
				r0 = sympy.Symbol('r0_'+elem.letter_id+elem.descr, real=True)
				mna[elem.n1, elem.n1] = mna[elem.n1, elem.n1] + 1/r0
				mna[elem.n1, elem.n2] = mna[elem.n1, elem.n2] - 1/r0
				mna[elem.n2, elem.n1] = mna[elem.n2, elem.n1] - 1/r0
				mna[elem.n2, elem.n2] = mna[elem.n2, elem.n2] + 1/r0
		elif isinstance(elem, diode.diode):
			gd = sympy.Symbol("g"+elem.letter_id+elem.descr)
			mna[elem.n1, elem.n1] = mna[elem.n1, elem.n1] + gd
			mna[elem.n1, elem.n2] = mna[elem.n1, elem.n2] - gd
			mna[elem.n2, elem.n1] = mna[elem.n2, elem.n1] - gd
			mna[elem.n2, elem.n2] = mna[elem.n2, elem.n2] + gd
		elif isinstance(elem, devices.inductor_coupling):
			pass
			# this is taken care of within the inductors
		elif circuit.is_elem_voltage_defined(elem):
			pass
			#we'll add its lines afterwards
		else:
			printing.print_warning("Skipped elem %s: not implemented." % (elem.letter_id.upper()+elem.descr,))

	pre_vde = mna.shape[0]
	for elem in circ.elements:
		if circuit.is_elem_voltage_defined(elem):
			index = mna.shape[0] #get_matrix_size(mna)[0]
			mna = expand_matrix(mna, add_a_row=True, add_a_col=True)
			N = expand_matrix(N, add_a_row=True, add_a_col=False)
			# KCL
			mna[elem.n1, index] = +1
			mna[elem.n2, index] = -1
			# KVL
			mna[index, elem.n1] = +1
			mna[index, elem.n2] = -1
			if isinstance(elem, devices.vsource):
				if elem.is_symbolic:
					VDC = sympy.Symbol(elem.letter_id.upper() + elem.descr, real=True)
				else:
					VDC = elem.vdc
				N[index, 0] = -VDC
			elif isinstance(elem, devices.evsource):
				if elem.is_symbolic:
					alpha = sympy.Symbol(elem.letter_id.upper() + elem.descr, real=True)
				else:
					alpha = elem.alpha
				mna[index, elem.sn1] = -alpha
				mna[index, elem.sn2] = +alpha
			elif isinstance(elem, devices.inductor):
				if ac:
					if elem.is_symbolic:
						L = sympy.Symbol(elem.letter_id.upper() + elem.descr, real=True)
					else:
						L = elem.L
					mna[index, index] = -s*L
				else: 
					pass
					# already so: commented out				
					# N[index,0] = 0
			elif isinstance(elem, devices.hvsource):
				printing.print_warning("symbolic.py: BUG - hvsources are not implemented yet.")
				sys.exit(33)
	
	for elem in circ.elements:
		if circuit.is_elem_voltage_defined(elem):
			if isinstance(elem, devices.inductor):
				if ac:
					# find its index to know which column corresponds to its current
					this_index = circ.find_vde_index("L"+elem.descr, verbose=0)
					for cd in elem.coupling_devices:
						if cd.is_symbolic:
							M = sympy.Symbol("M" + cd.descr, real=True)
						else:
							M = cd.K
						# get id+descr of the other inductor (eg. "L32")
						other_id_wdescr = cd.get_other_inductor("L"+elem.descr)
						# find its index to know which column corresponds to its current
						other_index = circ.find_vde_index(other_id_wdescr, verbose=0)
						# add the term.
						#print "other_index: "+str(other_index)
						#print "this_index: "+str(this_index)
						mna[pre_vde+this_index,pre_vde+other_index] += -s*M
						#print mna
				else: 
					pass
					# already so: commented out				
					# N[index,0] = 0
			
	
	#all done
	return (mna, N, subs_g)