Tuesday, February 12, 2013

Circuit Parameters - VII

A few changes to the code for taking circuit parameters.

  1. I forgot completely "jump" labels. They do not need an object, but the code should ignore them while reading the cells or they will generate "Component not found" errors.
  2. Take the circuit layour file name as input from the user and generate the parameters files uniquely for the circuit.

The next stage is to generate the loop matrix for the circuit. The loops have been identified. However, every loop will interact with other loops. So, this has been coded.

Next stage is to read the parameters of every component and generate the ODE for solving the circuit KVL laws.

Anyway, here is the code (click on "view raw" below the code box for code in a new window)



Friday, February 8, 2013

Circuit Parameters - VI

There is a couple of major design flaw in the previous approach.

  1. The component names are automatically generated. It is always better to let the user name the components as they may correspond to PCB designs etc.
  2. Any change in the circuit topology, even an extension of a branch would be seen a new circuit with default values. Better to check if any of the components in the new circuit have parameters in the parameter file and start with those parameters.

So, a change in the code. The components will now be names followed by an underscore ("_") and then the name of the component. Example: Resistor_R1, voltagesource_v1. Case is not important in the component names though it is in the tags.

The unique identifier continues to be cell position. However, for a particular component type, the same tag can't be used. For example: resistor_r1 and resistor_r1 would be illegal. However, two different components could have the same tag. For example: Resistor_br and inductor_br are OK. If the user want to name the components according to function, this might be a good option.

Here is the code (click on "view raw" below the box to see the entire code):


Thursday, February 7, 2013

Circuit Parameters - V

Couple of updates to the previous code:

1. Some elements will also have a polarity. In this case, the voltage source definitely will have one. The capacitor could also have but I'll consider an ac capacitor for now.

2. There will have to be provision to check if everytime the program is run, whether the circuit has changed. If the circuit is the same but the parameters need to be updated, then nw_params.csv should not be filled with default values as the user will have to update everything all over again or will have to remember to copy nw_params.csv to another backup file. A more elaborate method can be thought of later where the actual topology can be read - nodes, branches, loops etc and if that remains the same along with elements in every branch, then circuit can be considered the same. Because otherwise a small change to a branch such as lengthening with more "wire" elements will be seen as a new circuit. For that matter, even if major changes are to be made, only the changed elements can be considered. All this is user interface and will come later.


So anyway, here is the updated code (click on "view raw" below the code box for code going out of the window):




Wednesday, February 6, 2013

Circuit Paramaters - IV

Now that the basic concept of entering parameters is established, this is the code for it.

Depending on the components found from the circuit spreadsheet, another spreadsheet is created with rows corresponding to every device found. Each device will have default parameters. So the user will have to change those. After all changes, the user can save it as another CSV file.

Each row in the spreadsheet will have the first three elements as - Component type (Resistor, Inductor etc), Component Reference (R1, L2 etc), Cell Position.

As before, the Cell position can be used to access the component object from the component object dictionary. The component classes will have a function to take the parameters which will be column 4 onwards.

Here is the code (click on "view raw" to see the part going out of the box):


Tuesday, February 5, 2013

Circuit Parameters - III

The next step is to take a sample circuit with a voltage source, resistors, inductors and capacitors and to automate the naming of the elements.

The unique  identification all these elements have is their position in the spreadsheet - only one element can occupy a cell. So the first part is to write a small function that will translate the cell information from [row, column] form to the form that can be read of from the spreadsheet.

That function is here:


So the string that marks the cell position being an immutable element can be the key in a dictionary. A dictionary can be made of all elements found in the circuit and these can be accessed at any time by the position.

Now an identification is chosen, what will be the value of this dictionary item? Ideally, it would be great if it could be the object itself. Then every element will be an object uniquely identified by its position and with the same methods for transferring data to and from the main solver.

This program seems to do this (click on "View Raw" below the code box to see the code going out of the window):


In this file, network_reader is the Python code that contains the circuit interpreter done so far. Each class so far contains only the information of its index (or serial number) and the position in the spreadsheet.
--------------------------------------------------------------------------------------
class Resistor:
    def __init__(self, res_index, res_pos):
        self.res_number=res_index
        self.res_pos=res_pos
    def display(self):
        print "Resistor is ",
        print "R"+str(self.res_number),
        print " located at ",
        print self.res_pos
--------------------------------------------------------------------------------------

All the class references are added to the dictionary:
--------------------------------------------------------------------------------------
component_list={"Resistor":Resistor, "Inductor":Inductor, "Capacitor":Capacitor, "Voltage_Source":Voltage_Source}
--------------------------------------------------------------------------------------

This is what component list looks like:
--------------------------------------------------------------------------------------
>>> component_list
{'Voltage_Source': <class __main__.Voltage_Source at 0x02C9F810>, 'Resistor': <class __main__.Resistor at 0x02C9F768>, 'Inductor': <class __main__.Inductor at 0x02C9F7A0>, 'Capacitor': <class __main__.Capacitor at 0x02C9F7D8>}
--------------------------------------------------------------------------------------


The next step is to generate a dictionary of all the components found in the spreadsheet:
--------------------------------------------------------------------------------------
components_found={}
for c1 in range(len(tst_mat)):
    for c2 in range(len(tst_mat[0])):
        if tst_mat[c1][c2]:
            if tst_mat[c1][c2].lower()!="wire":
                if tst_mat[c1][c2] in component_list.keys():
                    if tst_mat[c1][c2] not in components_found:
                        components_found[tst_mat[c1][c2]]=[nw_rd.csv_element([c1, c2])]
                    else:
                        components_found[tst_mat[c1][c2]].append(nw_rd.csv_element([c1, c2]))
                else:
                    print "Error! Component at %s doesn't exist." %nw_rd.csv_element([c1, c2])
--------------------------------------------------------------------------------------

And this is what the dictionary looks like:
--------------------------------------------------------------------------------------
>>> components_found
{'Voltage_Source': ['4A'], 'Resistor': ['1B', '1F'], 'Inductor': ['1C', '1H'], 'Capacitor': ['4E']}
--------------------------------------------------------------------------------------

From this list, each component can be given a name as they have a specific index in a list.

Finally, to create a dictionary of all the components found. Here the unique identification will be the position in the spreadsheet:
--------------------------------------------------------------------------------------
component_objects={}
for items in components_found.keys():
    for c1 in range(len(components_found[items])):
        component_objects[components_found[items][c1]]=component_list[items](c1+1, components_found[items][c1])
--------------------------------------------------------------------------------------

A quick explanation to what I have done:

1. components_found[items] are the different types of components - voltage source, resistors etc.
2. components_found[items][c1] are the positions of each of these components. So these are the keys of the dictionary component_objects.
3. component_list[items] is the value of the dictionary item corresponding to the component type - and this is a class constructor. This contructor takes the values of the index and the position.
This is the final result:
--------------------------------------------------------------------------------------
>>>
Inductor is  L1  located at  1C
Resistor is  R1  located at  1B
Resistor is  R2  located at  1F
Inductor is  L2  located at  1H
Capacitor is  C1  located at  4E
Voltage Source is  V1  located at  4A
--------------------------------------------------------------------------------------

For the circuit below

Monday, February 4, 2013

Circuit Parameters - II

The next step is to write the code such that all elements are identified and parameters are obtained. In C++ the concept that I followed was that every element was an object - a resistor, an inverter etc. There was three levels of data transfer to these objects. The first was when they were initialized. The second was when the parameters and initial conditions they contained was transferred to the system matrices for solving the ODEs and third was when the results of the ODE was transferred back to the objects to update the values of voltage/current etc.

In C++, the objects were created manually. In Python, I would like the objects to be created automatically from the network layout in the CSV file.

So, testing how to do this first step. A little piece of code to see how automatically the objects can be created and stored. This code is too ridiculously simple to put on Git, so this is it:

-----------------------------------------------------------------------------------------------------------------
#! /usr/bin/env python
import sys, math

class Resistor:
    def __init__(self, res_index):
        self.res_number=res_index
    def display(self):
        print "Resistor is ",
        print "R"+str(self.res_number)

res_list=[]
for c1 in range(1, 5):
    res_name="R"+str(c1)
    res_name=Resistor(c1)
    res_list.append(res_name)

print res_list
for res in res_list:
    res.display()
-----------------------------------------------------------------------------------------------------------------

Here, I am creating a class "Resistor" which has only one data element - its index. So the resistors will be called R1, R2, etc.

I create a list of resistors res_list and create resistors R1 to R4. Also, objects are created with that tag and added to res_list.

Here is the output:
-----------------------------------------------------------------------------------------------------------------
>>>
[<__main__.Resistor instance at 0x02A1F4E0>, <__main__.Resistor instance at 0x02A1F508>, <__main__.Resistor instance at 0x02A1F530>, <__main__.Resistor instance at 0x02A1F558>]
Resistor is  R1
Resistor is  R2
Resistor is  R3
Resistor is  R4
-----------------------------------------------------------------------------------------------------------------

res_list is a list with instances of the class Resistor. But importantly, when I access the method display of the class Resistor by res.display(), it does give me the correct resistor labels.

So now let me put everything in the spreadsheet into objects.

Friday, February 1, 2013

Circuit Parameters

After loop identification, now comes the time to input the parameters of the circuit.

One very nice thing about most circuit simulators is the dialog box that opens up with each element with all the parameters. So essentially, I need to put these features into my circuit simulator:

1. The user should only indicate the element at a given position.
2. We need to then generate a list of all the elements found, names for them, their positions in the spreadsheet and finally their parameters with some to be defaults.
3. With the case of elements like diodes, IGBTs and others that have polarities or certain ways in which they are connected, the polarity can be specified in the separate dialog.

For multiport elements like machines, transformers, there will have to be more than one tag and these will have to be translated. Things would have been much more convenient with a GUI.

This will be my first approach:

1. Create an index of names - "Resistor", "Inductor", "Capacitor", "Voltage_Source" etc.
2. The network interpreter will divide the circuit into three types of elements - "wire", "jump" and elements such as the above.
3. Each time an element is found, it will be assigned a name that creates an object of it - like R1, R2, C1, etc.
4. The program will create another spreadsheet with all the element names, their positions and parameter values in separate columns.
5. The user has to modify these values and continue with the simulation.

For passive circuits with only resistors, inductors, capacitors and voltage sources, I don't see much of a problem. However, there would be a problem with machines for example, a three-phase synchronous generator. So the stator will have three connections and the rotor will have two. How do I map these connections on a spreadsheet?