There were a couple of fatal flaws in the previous code. When I expand the circuit to a buck converter with two diodes connected in parallel as shown below, it doesn't work.
So essentially there are two freewheeling paths. In the previous algorithms, I had considered as current sources:
1. Inductors
2. Voltage sources without any resistance and inductance
3. Branches without any resistance and inductance and also no voltage - short branches or wires.
The 3rd point was wrong. A wire will carry any current and to fix the current through it will be wrong. For now, I think my assumption of a voltage source with zero impedance as a current source is acceptable because the sources should continue supplying what they were during an event to check which branches can change their status.
So, to include the third point, I came up with the concept of shortnode. A supernode will be a node having a zero impedance branch with a voltage. On the other hand, a short node is a node that has a zero impedance branch with no voltage - or a node with a "wire" connected to it. The significance of a short node will be that a "wire" will have two short nodes at the same voltage and in this manner, nodes connected through wires will end up as a group of short nodes. Similar to supernodes, a circuit could have many groups of short nodes. The only difference between a super node and a short node is that when performing KCL, is a node is encountered that is a short node, only the voltage of the first node in that group of short nodes will be included.
To expand on this. If there is a group of four short nodes. All these short nodes are connected by "wires" and so they are at the same voltage. So when performing KCL only one node voltage needs to be included. The reason is that there can be a large number of short nodes and therefore, to write separate equations V1-V2=0 will increase the number of equations well beyond the number of nodes, messing up the KCL.
Once this is done, the KCL is performed. All the node voltages are calculated and all the branch currents too. Except for the short branches or "wires". There is no way to calculate the current through them by the above method as they do not have a resistance. So, for this another KCL is written. The code for this is completely new and so is below (click on "view raw" below the code box to view the code in another window):
After this change, the code now works for the circuit shown above.
So essentially there are two freewheeling paths. In the previous algorithms, I had considered as current sources:
1. Inductors
2. Voltage sources without any resistance and inductance
3. Branches without any resistance and inductance and also no voltage - short branches or wires.
The 3rd point was wrong. A wire will carry any current and to fix the current through it will be wrong. For now, I think my assumption of a voltage source with zero impedance as a current source is acceptable because the sources should continue supplying what they were during an event to check which branches can change their status.
So, to include the third point, I came up with the concept of shortnode. A supernode will be a node having a zero impedance branch with a voltage. On the other hand, a short node is a node that has a zero impedance branch with no voltage - or a node with a "wire" connected to it. The significance of a short node will be that a "wire" will have two short nodes at the same voltage and in this manner, nodes connected through wires will end up as a group of short nodes. Similar to supernodes, a circuit could have many groups of short nodes. The only difference between a super node and a short node is that when performing KCL, is a node is encountered that is a short node, only the voltage of the first node in that group of short nodes will be included.
To expand on this. If there is a group of four short nodes. All these short nodes are connected by "wires" and so they are at the same voltage. So when performing KCL only one node voltage needs to be included. The reason is that there can be a large number of short nodes and therefore, to write separate equations V1-V2=0 will increase the number of equations well beyond the number of nodes, messing up the KCL.
Once this is done, the KCL is performed. All the node voltages are calculated and all the branch currents too. Except for the short branches or "wires". There is no way to calculate the current through them by the above method as they do not have a resistance. So, for this another KCL is written. The code for this is completely new and so is below (click on "view raw" below the code box to view the code in another window):
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# In the above nodal analysis, the inductor currents and the currents | |
# through branches containing a voltage source are considered as | |
# current sources. Finally, the branch currents calculated are the | |
# currents with resistances or stiff branches where inductance is negligible. | |
# But this leaves out the short branches or "wires". There is no means | |
# to calculate the current through them as they do not have a resistance. | |
# So the next part does that merely by using KCL, currents at a node | |
# must be zero. | |
# This is a list of the short branches or "wires" | |
short_branch_list=[] | |
for c1 in range(len(branch_info)): | |
if branch_info[c1][-1][0][0]==0.0 and branch_info[c1][-1][0][1]==0.0: | |
if ((1.0 not in branch_info[c1][-1][1]) and (-1.0 not in branch_info[c1][-1][1])): | |
short_branch_list.append(c1) | |
# This is a matrix showing the presence of short branches | |
connectivity_short=[] | |
# This is a vector with the remaining currents calculated | |
# above by nodal analysis at a node. | |
connectivity_src=[] | |
for c1 in range(len(list_of_nodes)): | |
row_vector=[] | |
connectivity_src.append(0.0) | |
for c1 in range(len(branch_info)): | |
row_vector.append(0.0) | |
connectivity_short.append(row_vector) | |
for c1 in range(len(list_of_nodes)): | |
for c2 in range(len(branch_info)): | |
# Check if this branch is a short branch | |
is_short_node="no" | |
if branch_info[c2][-1][0][0]==0.0 and branch_info[c2][-1][0][1]==0.0: | |
if ((1.0 not in branch_info[c2][-1][1]) and (-1.0 not in branch_info[c2][-1][1])): | |
is_short_node="yes" | |
# If it is, then this will apear in the connectivity matrix | |
# If the branch originates at the node, it is taken with | |
# a minus sign because it is on the other side of the KCL equation. | |
if list_of_nodes[c1]==branch_info[c2][0]: | |
connectivity_short[c1][c2]=-1.0 | |
if list_of_nodes[c1]==branch_info[c2][-2]: | |
connectivity_short[c1][c2]=1.0 | |
if is_short_node=="no": | |
# If it is not a short branch, add the currents calculated in KCL | |
# to the source vector. | |
if list_of_nodes[c1]==branch_info[c2][0]: | |
connectivity_src[c1]+=br_currents[c2] | |
if list_of_nodes[c1]==branch_info[c2][-2]: | |
connectivity_src[c1]-=br_currents[c2] | |
# Iterate through the short branch list | |
c2=0 | |
# Iterate through each node - each row of connectivity_short. | |
for c1 in range(len(list_of_nodes)): | |
# Check if the row and branch number of the short branch is 1.0 | |
# This should be because if it is a short branch, there should | |
# be a 1 or a -1 somewhere in that column for short branch number. | |
if not connectivity_short[c1][short_branch_list[c2]]: | |
# If not, go through all the remaining nodes to check | |
# if any subsequent row has a nonzero. | |
for c3 in range(c1+1, len(list_of_nodes)): | |
if connectivity_short[c3][short_branch_list[c2]]: | |
# If so, interchange the two rows. | |
for c4 in range(len(connectivity_short[c1])): | |
connectivity_short[c1][c4], connectivity_short[c3][c4] = connectivity_short[c3][c4], connectivity_short[c1][c4] | |
connectivity_src[c1], connectivity_src[c3] = connectivity_src[c3], connectivity_src[c1] | |
# If all the short branches are not exhausted, increment c2. | |
if c2<len(short_branch_list)-1: | |
c2+=1 | |
# The above row interchanges will gurantee the first rows | |
# equal to the number of short branches will have nonzero | |
# entries corresponding to the short branches. | |
# Now, a row operation will be performed to make all other rows zero. | |
# This will make connectivity_short upper triangular. | |
# Once again iterate through the short branch list | |
for c1 in range(len(short_branch_list)): | |
# Go through all the remaining rows with the aim | |
# of making all entries of the short branch zero. | |
for c2 in range(c1, len(list_of_nodes)-1): | |
if connectivity_short[c2][short_branch_list[c1]]: | |
for c3 in range(c1+1, len(list_of_nodes)): | |
if connectivity_short[c3][short_branch_list[c1]]: | |
short_factor=connectivity_short[c3][short_branch_list[c1]] | |
for c4 in short_branch_list: | |
connectivity_short[c3][c4]-=connectivity_short[c2][c4]*short_factor/connectivity_short[c2][short_branch_list[c1]] | |
connectivity_src[c3]-=connectivity_src[c2]*short_factor/connectivity_short[c2][short_branch_list[c1]] | |
# Initialize a list of short branch currents | |
short_branch_currents=[] | |
for c1 in short_branch_list: | |
short_branch_currents.append(0.0) | |
# Calculate the short branch currents in reverse as | |
# an the matrices were made upper triangular by previous row | |
# operation. | |
for c1 in range(len(short_branch_list)-1, -1, -1): | |
short_branch_currents[c1]=connectivity_src[c1] | |
for c2 in range(len(short_branch_list)-1, c1, -1): | |
short_branch_currents[c1]-=connectivity_short[c1][short_branch_list[c2]]*short_branch_currents[c2] | |
short_branch_currents[c1]=short_branch_currents[c1]/connectivity_short[c1][short_branch_list[c1]] | |
# The remaining elements in branch currents are filled. | |
# These were zero before. | |
for c1 in range(len(short_branch_list)): | |
br_currents[short_branch_list[c1]]=short_branch_currents[c1] |
After this change, the code now works for the circuit shown above.
No comments:
Post a Comment