def get_variables(circ): """Get a sympy matrix containing the circuit variables to be solved for. **Parameters:** circ : circuit instance The circuit **Returns:** vars : sympy matrix, shape (n, 1) The variables in a column vector. """ # numero di soluzioni di tensione (al netto del ref) nv_1 = circ.get_nodes_number() - 1 # descrizioni dei componenti non definibili in tensione idescr = [elem.part_id.upper() for elem in circ 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] = _symbol_factory("V" + str(circ.nodes_dict[i + 1])) else: x[i, 0] = _symbol_factory("I[" + idescr[i - nv_1] + "]") return x
def _expand_matrix(mat, add_a_row=False, add_a_col=False): if add_a_row: row = smzeros(1, mat.shape[1]) mat = mat.row_insert(mat.shape[0], row) if add_a_col: col = sympy.zeros(mat.shape[0], 1) mat = mat.col_insert(mat.shape[1], col) return mat
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
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)
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)) 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 = _symbol_factory( elem.part_id.upper(), real=True, positive=True) G = _symbol_factory('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 = _symbol_factory( 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 = _symbol_factory(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 = _symbol_factory(elem.part_id.upper()) 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 = _symbol_factory('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 = _symbol_factory( '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 = _symbol_factory("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 = _symbol_factory(elem.part_id.upper()) else: VDC = elem.dc_value N[index, 0] = -VDC elif isinstance(elem, devices.EVSource): if elem.is_symbolic: alpha = _symbol_factory(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 = _symbol_factory( 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 = _symbol_factory( 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)
def generate_mna_and_N(circ, opts, ac=False, subs=None, verbose=3): """Generate a symbolic Modified Nodal Analysis matrix and N vector. Only elements that have an ``is_symbolic`` attribute set to ``True`` (the default) are considered symbolically. Simply set the attribute to ``False`` to employ the numeric value. This allows to simplify and speed up the work of the symbolic solver. The formulation can be performed using conductances or resistances. The choice is made setting the global ``options.symb_formulate_with_gs`` value to ``True``. A formulation done in terms of resistors, may result in many separate :math:`1/R` terms in the matrices. Historically, ``sympy`` choked on those, because of a long-standing bug in polys. Now the issue seems to have been solved and the two computations should be symbolically equivalent albeit computationally different (as expected). The option value ``options.symb_formulate_with_gs`` is provided to restore the old functionality in case you use an old version of ``sympy``. **Parameters:** circ : circuit instance The circuit. opts : dict The options to be used for the generation of the matrices. As of now, the only supported option is ``'r0s'`` which can be set to either ``True`` or ``False``, and selects whether the equivalent output resistance of the transistors should be taken into account or not. ac : bool, optional Flag to trigger the inclusion of frequency-dependent elements. Defaults to ``False`` currently (but may change). subs : dict, optional The substitution dictionary, composed by mappings of ``<symbol>``:``<sympy expression>``. verbose : int, optional Verbosity flag, from ``0`` (silent) to ``6`` (very logorrhoic). Defaults to ``3``. **Returns:** mna, N : Sympy matrices The MNA matrix and the contant term of symbolic type. subs_gs : dict of symbols In case the formulation of the MNA is performed in terms of conducatances, this dictionary is to be used to substitute away the conducatances for the resistor symbols, after the circuit is solved but before the results are shown to the user. ``sympy``'s ``sub()`` can take care of that for you. If not necessary, this dictionary is empty. .. note:: Setting ``opts['r0s'] = True``, ie considering all the transistors output resistances, can significantly slow down -- or even prevent by consuming all available memory -- the solution of complex circuits with several active elements. We recommend a combination of the following: * setting the above option in simple circuits only, * inserting explicitely the :math:`r_0` you wish to consider at circuit level, * beefing up your machine with extra RAM and extra computing power, * being patient. """ n_of_nodes = circ.get_nodes_number() mna = smzeros(n_of_nodes) N = smzeros(n_of_nodes, 1) 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 = _symbol_factory(elem.part_id.upper(), real=True, positive=True) if R in subs: # instant substitution R = subs[R] if options.symb_formulate_with_gs: G = _symbol_factory('Gxxx' + str(R)[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: G = 1.0/R else: G = 1.0/elem.value 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 = _symbol_factory( elem.part_id.upper(), real=True, positive=True) if capa in subs: # instant substitution capa = subs[capa] 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 = _symbol_factory(elem.part_id.upper(), real=True) if alpha in subs: # instant substitution alpha = subs[alpha] 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 = _symbol_factory(elem.part_id.upper()) if IDC in subs: # instant substitution IDC = subs[IDC] 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 = _symbol_factory('gm_' + elem.part_id, real=True, positive=True) if gm in subs: # instant substitution gm = subs[gm] 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 = _symbol_factory( 'r0_' + elem.part_id, real=True, positive=True) if r0 in subs: # instant substitution r0 = subs[r0] 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 = _symbol_factory("g" + elem.part_id, positive=True) if gd in subs: # instant substitution gd = subs[gd] 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.FISource): # These are added after all VDEs have been accounted for pass 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 = _symbol_factory(elem.part_id.upper()) if VDC in subs: # instant substitution VDC = subs[VDC] else: VDC = elem.dc_value N[index, 0] = -VDC elif isinstance(elem, devices.EVSource): if elem.is_symbolic: alpha = _symbol_factory(elem.part_id.upper(), real=True) if alpha in subs: # instant substitution alpha = subs[alpha] else: alpha = elem.alpha mna[index, elem.sn1] = -alpha mna[index, elem.sn2] = +alpha elif isinstance(elem, devices.HVSource): if elem.is_symbolic: alpha = _symbol_factory(elem.part_id.upper(), real=True) if alpha in subs: # instant substitution alpha = subs[alpha] else: alpha = elem.alpha source_index = circ.find_vde_index(elem.source_id) mna[index, n_of_nodes + source_index] = +alpha elif isinstance(elem, devices.Inductor): if ac: if elem.is_symbolic: L = _symbol_factory( elem.part_id.upper(), real=True, positive=True) if L in subs: # instant substitution L = subs[L] else: L = elem.L mna[index, index] = -s * L else: pass # already so: commented out # N[index,0] = 0 else: raise circuit.CircuitError('Element %s is not supported. ' + 'Please report this bug.' % elem.__class__) for elem in circ: if ac and isinstance(elem, devices.Inductor): # 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 = _symbol_factory( cd.part_id, real=True, positive=True) if M in subs: # instant substitution M = subs[M] 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 elif isinstance(elem, devices.FISource): source_current_index = circ.find_vde_index(elem.source_id, verbose=0) if elem.is_symbolic: F = _symbol_factory(elem.part_id, real=True) if F in subs: # instant substitution F = subs[F] else: F = elem.alpha mna[elem.n1, pre_vde + source_current_index] += +F mna[elem.n2, pre_vde + source_current_index] += -F else: pass # all done return mna, N, subs_g
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)