In this project, you will implement a basic DC circuit solver. The solving engine will be built on a basic matrix linear algebra library using a multiply-linked list to represent a sparse matrix. The circuit description and simulation commands will be read from a file.
Syntax | Description |
---|---|
<name> | name formed by ASCII characters ‘0’-‘9’,‘a’-‘z’,‘A-Z’,’_’ |
<ws> | any sequence of whitespace characters |
<nn1>,<nn2> | integer specified using ASCII characters ‘0’-‘9’ |
<value> | floating point value specified using characters ‘0’-‘9’,’.’,‘e’,‘E,’+’,’-’ |
<NL> | UNIX newline |
R<name><ws><nn1><ws><nn2><ws><value><NL>
You may ignore any devices whose terminals are shorted (i.e. ignore device if nn1==nn2)
V<alphanumname><ws><nn1><ws><value><NL>
Voltage source may only exist from ground to a node. You may assume no two voltage sources are connected to the same node.
P<ws><nn1><NL>
These designate which node results should be printed.
R1 1 2 2
R2 1 3 4
R3 2 3 5.2
R4 3 4 6
R5 2 4 3
V1 1 6
V2 4 2
P 1
The name of your program should be cs and should be called with the input file as an argument.
cs <filename>
Example:
cs circuit.cs
Assume is initially a zero matrix of size where is the number of nodes. Assume is .
For each component connected between some i and j (if the component’s terminals are shorted, i=j, you may ignore it)
Add to and
Add to and
Then, for each source node node i.
Set row in to all zeros, then set
set
To solve the circuit,
Terms are implemented with a minmum of these 7 elements of information:
value is a float
row,col are integers
up,down,left,right are pointers to the next non-zero term in each direction or NULL pointers if non exists
A given matrix is implemented as a multiply-linked list such that each term is part of two linked list, one row-wise and one column-wise.
Implement Base ADT functions first. You must write functions to create and destroy stand-alone nodes, insert and delete nodes from a linked list, and mutators to modify node data or pointers, deallocation of all nodes in a list, deep copy and shallow copy of a list. I strongly recommend these as well: print node, print column,print row, print matrix.
A note on invalid input files: If an input file is invalid, your program behavior may be undefined and this is excused, except that invalid memory access/segmentation faults is not excused
global variables are not allowed on this project
Report guidelines will be posted at a later time.
Example files will be posted, though it is not guaranteed that they are comprehensive tests.
• AddToElementValue(A,r,c,s)
modifies matrix , adding scalar to element:
• SetElementValue(A,r,c,s)
modifies matrix , sets . Should remove and destroy element if s=0
• GetElementValue(A,r,c)
returns value
• FindLargestInCol(A,c)
returns pointer to term with largest value (maximum absolute value)
• RowSwap(A,r1,r2)
modifies A by performing a row swap
• ScaleRow(A,r,s)
modifies A by multiplying row r by scalar s
• RowCombine(A,r1,r2,s)
modifies row r1 of A by adding row r2 scaled by scalar s
• AugmentMatrix(A,B)
augments B to right of A, modifying A and emptying B in the process (moves nodes from B to A appropriately)
• CopySubMatrix(A,B,rowStart,rowEnd,columnStart,columnEnd)
deep copies submatrix of B to an empty A, if A is not empty then A is first emptied
PSEUDO CODE
//computes same as u in Matlab: [~,u]=lu(A);
for colItr 1 to m,
//find value largest possible pivot value in column
largestNodePtr = FindMaxAbsInCol(list,col#);
//if largest value is zero matrix is singular
if (GetElementValue(largestNodePtr)) == 0,
error('Matrix is Singular');
//swap current row with lagest pivot value row
RowSwap(A,colItr,GetRowIndex(largestColumnNodePtr));
//create zeros below pivot point
for itrR = (colItr +1) to m,
RowCombine(itrR,colItr,
-1*GetElementValue(A,itrR,colItr)
/GetElementValue(A,colItr,colItr));
end
end
//now finish computing rref(A)
//make all pivots points ones by dividing each row by the pivot value
// then reduce matrix by creating zeros above pivot points
for diagonalItr = 1:n
ScaleRow(A,diagonalItr, 1/GetElementValue(A,diagonalItr,diagonalItr));
for rowItr =1 1 to (colItr-1)
RowCombine(A, rowItr,diagonalItr, -(A(rowItr,diagonalItr));
end
end
Let the voltage source be and
Eqn1@Node1:
Eqn2@Node2:
Eqn3@Node3:
In matrix form, we write this as
Look at how the order of of the equations is represented in the matrix and can be reordered:
Likewise, we can combine and manipulate rows in the matrix just corresponding to manipulations of the original equations, but in a compact written form.
Such simple row operations operations can be used to solve for x as follows.
Manipulating the equations can accomplish the matrix inversion . As it turns out, performing the same manipulations on that make into an identity matrix provides the solution for in terms of all provided values. To make this easier, we write next to as one matrix and call it the augmented matrix, .
Row2 = Row2 + Row1
Row2 = Row2
Row2 = Row 2 + Row3
Now, with just simplification of expressions…
(only for symbolic computation, in your numerical solver this step would not exist)
Your program’s initial effort is to directly generate this matrix:
Though it is shown symbolically here, you are provided numerical values and will perform numerical computation to make the A matrix an identity matrix (all-zeros except ones on the diagonal)
Using Row1 to eliminate the first-column element in Row2
Row2 = Row2 + Row1
Scaling Row2 so that the second-column element is 1
Row2 = Row2
Row2 = Row 2 + Row3
At this point in your program, the left matrix is an identity matrix the computation is done since it is numerical.
See circuit at http://matlabbyexamples.blogspot.com/2011_11_01_archive.html
Example input file:
R1 1 2 2
R2 1 3 4
R3 2 3 5.2
R4 3 4 6
R5 2 4 3
VS1 1 6
VS2 4 0
P 1
Results by running the matlab code exactly as provided on the website.
>> A A = 1.0000 0 0 0 -0.5000 1.0256 -0.1923 -0.3333 -0.2500 -0.1923 0.6090 -0.1667 0 0 0 1.0000 B = 6 0 0 2
Therefore the initial augmented matrix that you should generate is
1.0000 0 0 0 6
-0.5000 1.0256 -0.1923 -0.3333 0
-0.2500 -0.1923 0.6090 -0.1667 0
0 0 0 1.0000 2
Finally the provided matlab code produces the following result:
>> Vo=A\B;
disp(Vo);
6.0000
4.4000
4.4000
2.0000
>>
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
-0.500000 +1.025600 -0.192300 -0.333300 +0.000000
-0.250000 -0.192300 +0.609000 -0.166700 +0.000000
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
*** Working on Coumn 1 ***
No intial row-swap Required for pivot column 1
Scale: Row1=1.0*Row1
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
-0.500000 +1.025600 -0.192300 -0.333300 +0.000000
-0.250000 -0.192300 +0.609000 -0.166700 +0.000000
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Combine: Row2=Row2+0.5*Row1
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.025600 -0.192300 -0.333300 +3.000000
-0.250000 -0.192300 +0.609000 -0.166700 +0.000000
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Combine: Row3=Row3+0.25*Row1
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.025600 -0.192300 -0.333300 +3.000000
+0.000000 -0.192300 +0.609000 -0.166700 +1.500000
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Row4 pivot column is already 0
*** Working on Coumn 2 ***
No intial row-swap Required for pivot column 2
Scale: Row2=0.9750390015600623*Row2
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.000000 -0.187500 -0.324980 +2.925117
+0.000000 -0.192300 +0.609000 -0.166700 +1.500000
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Combine: Row3=Row3+0.1923*Row2
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.000000 -0.187500 -0.324980 +2.925117
+0.000000 +0.000000 +0.572944 -0.229194 +2.062500
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Row4 pivot column is already 0
*** Working on Coumn 3 ***
No intial row-swap Required for pivot column 3
Scale: Row3=1.745372036958253*Row3
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.000000 -0.187500 -0.324980 +2.925117
+0.000000 +0.000000 +1.000000 -0.400028 +3.599830
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Row4 pivot column is already 0
Scale: Row4=1.0*Row4
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.000000 -0.187500 -0.324980 +2.925117
+0.000000 +0.000000 +1.000000 -0.400028 +3.599830
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
*** Working on Coumn 4 ***
Combine: Row3=Row3+0.40002836229560057*Row4
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.000000 -0.187500 -0.324980 +2.925117
+0.000000 +0.000000 +1.000000 +0.000000 +4.399887
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Combine: Row2=Row2+0.32498049921996874*Row4
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.000000 -0.187500 +0.000000 +3.575078
+0.000000 +0.000000 +1.000000 +0.000000 +4.399887
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Row1 pivot column is already 0
*** Working on Coumn 3 ***
Combine: Row2=Row2+0.18749999999999997*Row3
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.000000 +0.000000 +0.000000 +4.400057
+0.000000 +0.000000 +1.000000 +0.000000 +4.399887
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Row1 pivot column is already 0
*** Working on Coumn 2 ***
Row1 pivot column is already 0
Same as above, but with input Row2 and input Row3 swapped, requiring a swap when working on pivot column 2 to get the largest possible pivot-position value.
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
-0.250000 -0.192300 +0.609000 -0.166700 +0.000000
-0.500000 +1.025600 -0.192300 -0.333300 +0.000000
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
*** Working on Coumn 1 ***
No intial row-swap Required for pivot column 1
Scale: Row1=1.0*Row1
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
-0.250000 -0.192300 +0.609000 -0.166700 +0.000000
-0.500000 +1.025600 -0.192300 -0.333300 +0.000000
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Combine: Row2=Row2+0.25*Row1
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 -0.192300 +0.609000 -0.166700 +1.500000
-0.500000 +1.025600 -0.192300 -0.333300 +0.000000
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Combine: Row3=Row3+0.5*Row1
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 -0.192300 +0.609000 -0.166700 +1.500000
+0.000000 +1.025600 -0.192300 -0.333300 +3.000000
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Row4 pivot column is already 0
*** Working on Coumn 2 ***
Swap: Row 3 into pivot row 2
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.025600 -0.192300 -0.333300 +3.000000
+0.000000 -0.192300 +0.609000 -0.166700 +1.500000
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Scale: Row2=0.9750390015600623*Row2
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.000000 -0.187500 -0.324980 +2.925117
+0.000000 -0.192300 +0.609000 -0.166700 +1.500000
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Combine: Row3=Row3+0.1923*Row2
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.000000 -0.187500 -0.324980 +2.925117
+0.000000 +0.000000 +0.572944 -0.229194 +2.062500
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Row4 pivot column is already 0
*** Working on Coumn 3 ***
No intial row-swap Required for pivot column 3
Scale: Row3=1.745372036958253*Row3
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.000000 -0.187500 -0.324980 +2.925117
+0.000000 +0.000000 +1.000000 -0.400028 +3.599830
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Row4 pivot column is already 0
Scale: Row4=1.0*Row4
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.000000 -0.187500 -0.324980 +2.925117
+0.000000 +0.000000 +1.000000 -0.400028 +3.599830
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
*** Working on Coumn 4 ***
Combine: Row3=Row3+0.40002836229560057*Row4
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.000000 -0.187500 -0.324980 +2.925117
+0.000000 +0.000000 +1.000000 +0.000000 +4.399887
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Combine: Row2=Row2+0.32498049921996874*Row4
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.000000 -0.187500 +0.000000 +3.575078
+0.000000 +0.000000 +1.000000 +0.000000 +4.399887
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Row1 pivot column is already 0
*** Working on Coumn 3 ***
Combine: Row2=Row2+0.18749999999999997*Row3
+1.000000 +0.000000 +0.000000 +0.000000 +6.000000
+0.000000 +1.000000 +0.000000 +0.000000 +4.400057
+0.000000 +0.000000 +1.000000 +0.000000 +4.399887
+0.000000 +0.000000 +0.000000 +1.000000 +2.000000
Row1 pivot column is already 0
*** Working on Coumn 2 ***
Row1 pivot column is already 0
Write four equations for four unknown variables (in this case two are known immediately by noticing the voltage components).
Let the nodes voltages be ,,, and
Let the voltage source be and
Eqn1@Node1:
Eqn2@Node2:
Eqn3@Node3:
Current out due to voltage V2 = Current in due to surrounding voltages
use this one
Eqn4@Node4:
All together
In matrix form, we write this as
The augmented matrix would be as follows:
first column elimination:
and so on … (gets messy, refer to numerical step-by-step solution)