Electronic Circuit Simulation - Sparse Matrix Optimization (part 2) [Python] by drifter1

View this thread on steempeak.com
· @drifter1 · (edited)
$21.31
Electronic Circuit Simulation - Sparse Matrix Optimization (part 2) [Python]
<html>
https://i.postimg.cc/qqVXH41R/circuit-sim-series.jpg<br>
[Custom Thumbnail]<br>
All the Code of the series can be found at the <strong>Github repository</strong>:
https://github.com/drifter1/circuitsim
<hr>
<h1>Introduction</h1>&nbsp;&nbsp;&nbsp;&nbsp;Hello it's a me again @drifter1! Today we continue with the <strong>Electronic Circuit Simulation series</strong>, a tutorial series where we will be implementing a full-on electronic circuit simulator (like SPICE) studying the whole concept and mainly physics behind it! Following the theoretical approach of the previous part, we will today <strong>implement the CSR and CSC formats of Sparse Matrices in Python</strong>, by also using CSC to <strong>optimize our Static Analysis Simulator</strong>...
<h2>Requirements:</h2>
<ul>
<li>Physics and more specifically <strong>Electromagnetism Knowledge</strong></li>
<li>Knowing <strong>how to solve Linear Systems</strong> using Linear Algebra</li>
<li>Some understanding of the <strong>Programming Language Python</strong></li>
</ul>
<h2>Difficulty:</h2>Talking about the <strong>series in general</strong> this series can be rated:
<ul><li>Intermediate to Advanced</li></ul>
<strong>Today's topic(s)</strong> can be rated:
<ul><li>Intermediate</li></ul>
<hr>
<h1>Actual Tutorial Content</h1>
<h2>Sparse Matrices using SciPy</h2>&nbsp;&nbsp;&nbsp;&nbsp;As we described in the previous article, Sparse Matrices are very important as they will make storing the A-matrix more memory efficient. The incremental construction of the matrix is done using either one of the formats: DOK, LIL or COO. Because we want to use the matrix later on in calculations, meaning that we want to convert the sparse matrix into CSR or CSC format, we will use COO, as this format allows a fast conversion to CSR or CSC. So, let's get started!
<h3>Create Sparse Matrix - COO Format</h3>&nbsp;&nbsp;&nbsp;&nbsp;First of all, to use all these different structures and functions that are provided by the SciPy library we have to <strong>import the package</strong> using:<br>
<pre><code>import scipy.sparse as sparse</code></pre><br>
&nbsp;&nbsp;&nbsp;&nbsp;What exactly is COO again? COO is a Coordinate List that basically <strong>stores a list of (row, column, value) tuples or triplets</strong>. To create such a matrix in Python we have to feed in 3 arrays/lists:<br>
<ol>
<li>The rows of all non-zero values</li>
<li>The columns of all non-zero values</li>
<li>The actual non-zero values</li>
</ol><br>
So, a general <strong>coo_matrix</strong> is defined as:<br>
<pre><code>A = sparse.coo_matrix((data, (rows, cols)), shape=(dim, dim))</code></pre><br>
&nbsp;&nbsp;&nbsp;&nbsp;To create these three lists or arrays more efficiently and with less need of Code, we can create a structure that keeps those three arrays/lists and appends values to them. Let's call this structure <strong>Triplet</strong>. Whenever we want to insert an entry, we will basically add the row, column and value (or data) to the corresponding lists rows, cols and data. Such a class looks like this:<br>
<pre><code>class Triplet:
    def __init__(self):
        self.rows = []
        self.cols = []
        self.data = []<br>
    def insert(self, row, col, data):
        self.rows.append(row)
        self.cols.append(col)
        self.data.append(data)<br>
    def __repr__(self):
        return "rows: " + str(self.rows) + "\ncols: " + str(self.cols)
               + "\ndata: " + str(self.data)</code></pre><br>
Let's recall our <strong>classic example circuit</strong> that gives us the system:<br>
https://steemitimages.com/640x0/https://quicklatex.com/cache3/f6/ql_2a03bbd062a53d2b4ae667bf91d417f6_l3.png<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;Thinking about the creation procedure, <strong>the [1, 1] entry is basically a sum between 0.25 and 0.5</strong>, which are caused by each of the two resistances. So, during the creation <strong>we will have duplicate entries for such cases</strong>! That's also a very important reason to why we are using COO in the first place, cause the other matrices don't store the duplicates and just keep the last occurrence. In other cases, this might be helpful, but for us it is not at all! After converting the COO matrix to CSR or CSC, the duplicates are summed up together, giving us exactly what we want...<br><br>
So, let's <strong>fill in the triplets lists</strong>:<br>
<pre><code>triplets = Triplet()<br>
# add impact of R1
triplets.insert(0, 0, 0.25)
triplets.insert(0, 1, -0.25)
triplets.insert(1, 0, -0.25)
triplets.insert(1, 1, 0.25)<br>
# add impact of R2
triplets.insert(1, 1, 0.5)<br>
# add impact of V1
triplets.insert(0, 2, 1)
triplets.insert(2, 0, 1)<br>
print(triplets, "\n")</code></pre><br>
This last print gives us:<br>
https://i.postimg.cc/3rXdhNHg/image.png<br><br>
We can clearly see that there are two entries for [1, 1], as we expected!<br><br>
Last but not least let's also <strong>setup the actual matrix</strong>:<br>
<pre><code>mtx = sparse.coo_matrix(
    (triplets.data, (triplets.rows, triplets.cols)), shape=(3, 3))</code></pre><br>
It will also be wise to delete the triplets using:<br>
<pre><code>del triplets</code></pre>
<h3>Convert to more efficient Format (CSR/CSC)</h3>&nbsp;&nbsp;&nbsp;&nbsp;Converting the COO format to CSR or CSC can be done veeeery easily using only one function call:<br>
<ul>
<li>tocsr() - convert to CSR format</li>
<li>tocsc() - convert to CSC format</li>
</ul>
<br>
Doing each of these and printing out the format we have...<br>
https://i.postimg.cc/tTHD1Jvh/image.png<br><br>
https://i.postimg.cc/PrqyvByF/image.png<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;Can you guess, which one is CSR and which CSC? That's quite easy I think! We don't sort the entries, and so the "convertion" procedure left behind a very important mark. If you remember from last time, we loop through the matrix in either row-major order, which gives us CSR or column-major order, which gives us CSC. So, seeing that the first loops through each row and the second through each column first, we can understand that the first is CSR, whilst the second is CSC, even without knowing which function was used!<br><br>
In code those two conversions are:<br>
<pre><code># convert to CSR
A = mtx.tocsr()<br>
# convert to CSC
A = mtx.tocsc()
</code></pre><br>
To <strong>print out the dense matrix</strong> we can use "todense()", which for both cases gives us:<br>
https://i.postimg.cc/qqvFRgg1/image.png
<h3>Solving Linear System</h3>We first have to define the numpy array of b:<br>
<pre><code>b = np.array([0, 2, 3])</code></pre><br>
&nbsp;&nbsp;&nbsp;&nbsp;Solving the system is basically again just calling a function from a specific part of scipy.sparse that has to do with linear algebra solving. For now, we will use a direct solve approach that of course has to take in a sparse matrix (A) and dense matrix (b). More specifically this function can be imported from:<br>
<pre><code>from scipy.sparse.linalg.dsolve import linsolve</code></pre><br>
Using this function to solve our system looks like this:<br>
<pre><code>x = linsolve.spsolve(A, b)</code></pre><br>
Printing out the solution x we get:<br>
https://i.postimg.cc/4dsfWvFn/image.png<br><br>
which are the same results that we got without sparse matrices!<br><br>
On GitHub I include the whole code for CSR and CSC...
<hr>
<h2>Optimizing the Static Analysis Simulator</h2>&nbsp;&nbsp;&nbsp;&nbsp;To optimize our current simulator, we basically only have to define the same Triplet class and insert the corresponding (row, column, value) pairs into the triplets lists.  So, we will no longer have a numpy array for A, but will setup an instance of the Triplet class using:<br>
<pre><code>triplets = Triplet()</code></pre><br>
&nbsp;&nbsp;&nbsp;&nbsp;While looping through the components and adding entries to the A-matrix, we will actually have to use the "insert()" function of Triplet. For example for voltage sources we now have:<br>
<pre><code>elif component.comp_type == 'V':
    # affects the B and C matrices of A
    if high != 0:
        triplets.insert(high-1, g2Index, 1)
        triplets.insert(g2Index, high-1, 1)
    if low != 0:
        triplets.insert(low-1, g2Index, -1)
        triplets.insert(g2Index, low-1, -1)<br>
    # affects b-matrix
    b[g2Index] = value<br>
    # increase G2 counter
    g2Index = g2Index + 1
</code></pre><br>
&nbsp;&nbsp;&nbsp;&nbsp;After the loop, we will use the triplet lists: data, rows and cols, to setup the actual sparse matrix in COO format, by then converting it to CSC format:<br>
<pre><code># setup sparse matrix A
    mtx = sparse.coo_matrix(
        (triplets.data, (triplets.rows, triplets.cols)), shape=(matrixSize, matrixSize))<br>
    del triplets<br>
    # convert to CSC
    A = mtx.tocsc()</code></pre><br>
The solving function of course has to be replaced with the new "sparse" one:<br>
<pre><code>def solveSystem(A, b):
    x = linsolve.spsolve(A, b)
    return x</code></pre><br>
Running our Simulator for the simple example we get:<br>
https://i.postimg.cc/T2qKr11t/image.png<br><br>
And so nothing really changed!<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;Running it for some of the other examples we would also see no different in the result values. So, what was this all for? As we also explained last time, Sparse matrices are of no use in such small Netlists, but will be essential for us when solving larger Netlists! Let's try to run the first Netlist from the following website:<br>
http://tiger.cs.tsinghua.edu.cn/PGBench/index.html<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;Before we do so, we should first make sure to comment-out any printing...also let's point out that I forgot to take care of comments in the corresponding article, and that having zero g2-components and so g2Count = 0, would cause an indexing error. So, we have to tweak the following things:<br>
<pre><code>...<br><br>
# read netlist
    for line in file:
        # split line
        parts = line.split()<r>
        # <strong>comment or option</strong>
        if(parts[0][0] == '*' or parts[0][0] == '.'):
            continue<br><br>
...<br><br>
# <strong>Group 2 component index</strong>
    if(g2Count > 0 ):
        g2Index = matrixSize - g2Count
    else:
        g2Index = 0<br>
...</code></pre><br>
Running thupg1.spice we get:<br>
https://i.postimg.cc/PrH24SH1/image.png<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;Not much information out of this, but still running it is impressive! It took up most of my computer's RAM, but before this optimization I couldn't run it at all, which tells something I think!
<hr>
<h2>RESOURCES</h2>
<h3>References:</h3>
<ol>
<li>https://scipy-lectures.org/advanced/scipy_sparse/coo_matrix.html</li>
<li>https://scipy-lectures.org/advanced/scipy_sparse/csr_matrix.html</li>
<li>https://scipy-lectures.org/advanced/scipy_sparse/csc_matrix.html</li>
<li>https://scipy-lectures.org/advanced/scipy_sparse/solvers.html</li>
<li>https://docs.scipy.org/doc/scipy/reference/sparse.html</li>
</ol>
<br>
Mathematical Equations were made using <a href="https://www.quicklatex.com/">quicklatex</a>
<hr>
<h2>Previous parts of the series</h2>
<h3>Introduction and Electromagnetism Background</h3>
<ul>
<li><a href="https://steemit.com/utopian-io/@drifter1/electronic-circuit-simulation-introduction-python">Introduction</a></li>
<li><a href="https://steemit.com/utopian-io/@drifter1/electronic-circuit-simulation-electromagnetism-background-part-1-python">Electromagnetism Background (part 1)</a></li>
<li><a href="https://steemit.com/utopian-io/@drifter1/electronic-circuit-simulation-electromagnetism-background-part-2-python">Electromagnetism Background (part 2)</a></li>
</ul>
<h3>Mesh and Nodal Analysis</h3>
<ul>
<li><a href="https://steemit.com/utopian-io/@drifter1/electronic-circuit-simulation-mesh-analysis-python">Mesh Analysis</a></li>
<li><a href="https://steemit.com/utopian-io/@drifter1/electronic-circuit-simulation-nodal-analysis-python">Nodal Analysis</a></li>
<li><a href="https://steemit.com/utopian-io/@drifter1/electronic-circuit-simulation-modified-mesh-analysis-by-inspection-python">Modified Mesh Analysis by Inspection</a></li>
<li><a href="https://steemit.com/utopian-io/@drifter1/electronic-circuit-simulation-modified-nodal-analysis-by-inspection-python">Modified Nodal Analysis by Inspection</a></li>
</ul>
<h3>Modified Nodal Analysis</h3>
<ul>
<li><a href="https://steemit.com/utopian-io/@drifter1/electronic-circuit-simulation-incidence-matrix-and-modified-kirchhoff-laws-python">Incidence Matrix and Modified Kirchhoff Laws</a></li>
<li><a href="https://steemit.com/utopian-io/@drifter1/electronic-circuit-simulation-modified-nodal-analysis-part-1-python">Modified Nodal Analysis (part 1)</a></li>
<li><a href="https://steemit.com/utopian-io/@drifter1/electronic-circuit-simulation-modified-nodal-analysis-part-2-python">Modified Nodal Analysis (part 2)</a></li>
</ul>
<h3>Static Analysis</h3>
<ul>
<li><a href="https://steemit.com/utopian-io/@drifter1/electronic-circuit-simulation-static-analysis-implementation-part-1-python">Static Analysis Implementation (part 1)</a></li>
<li><a href="https://steemit.com/utopian-io/@drifter1/electronic-circuit-simulation-static-analysis-implementation-part-2-python">Static Analysis Implementation (part 2)</a></li>
<li><a href="https://steemit.com/utopian-io/@drifter1/electronic-circuit-simulation-static-analysis-implementation-part-3-python">Static Analysis Implementation (part 3)</a></li>
</ul>
<h3>Sparse Matrix Optimization</h3>
<ul>
<li><a href="https://steemit.com/utopian-io/@drifter1/electronic-circuit-simulation-sparse-matrix-optimization-part-1-python">Sparse Matrix Optimization (part 1)</a></li>
</ul>
<hr>
<h2>Final words | Next up on the project</h2>&nbsp;&nbsp;&nbsp;&nbsp;And this is actually it for today's post and I hope that you enjoyed it!<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;The articles from now on will be about <strong>Transient Analysis</strong> and "component extensions"...<br><br>
So, see ya next time!
<hr>
<h2>GitHub Account:</h2>
https://github.com/drifter1<br>
https://steemitimages.com/0x0/https://media.giphy.com/media/ybITzMzIyabIs/giphy.gif
<br>
Keep on drifting! ;)
</html>
πŸ‘  , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , and 48 others
properties (23)
post_id74,837,068
authordrifter1
permlinkelectronic-circuit-simulation-sparse-matrix-optimization-part-2-python
categoryutopian-io
json_metadata{"community":"busy","app":"busy\/2.5.6","format":"markdown","tags":["utopian-io","tutorials","busy","programming","physics"],"users":["drifter1"],"links":["https:\/\/github.com\/drifter1\/circuitsim","\/@drifter1","http:\/\/tiger.cs.tsinghua.edu.cn\/PGBench\/index.html","https:\/\/scipy-lectures.org\/advanced\/scipy_sparse\/coo_matrix.html","https:\/\/scipy-lectures.org\/advanced\/scipy_sparse\/csr_matrix.html","https:\/\/scipy-lectures.org\/advanced\/scipy_sparse\/csc_matrix.html","https:\/\/scipy-lectures.org\/advanced\/scipy_sparse\/solvers.html","https:\/\/docs.scipy.org\/doc\/scipy\/reference\/sparse.html","https:\/\/www.quicklatex.com\/","https:\/\/steemit.com\/utopian-io\/@drifter1\/electronic-circuit-simulation-introduction-python"],"image":["https:\/\/i.postimg.cc\/qqVXH41R\/circuit-sim-series.jpg","https:\/\/steemitimages.com\/640x0\/https:\/\/quicklatex.com\/cache3\/f6\/ql_2a03bbd062a53d2b4ae667bf91d417f6_l3.png","https:\/\/i.postimg.cc\/3rXdhNHg\/image.png","https:\/\/i.postimg.cc\/tTHD1Jvh\/image.png","https:\/\/i.postimg.cc\/PrqyvByF\/image.png","https:\/\/i.postimg.cc\/qqvFRgg1\/image.png","https:\/\/i.postimg.cc\/4dsfWvFn\/image.png","https:\/\/i.postimg.cc\/T2qKr11t\/image.png","https:\/\/i.postimg.cc\/PrH24SH1\/image.png","https:\/\/steemitimages.com\/0x0\/https:\/\/media.giphy.com\/media\/ybITzMzIyabIs\/giphy.gif"]}
created2019-05-16 10:46:27
last_update2019-05-16 18:29:57
depth0
children4
net_rshares38,908,587,755,431
last_payout2019-05-23 10:46:27
cashout_time1969-12-31 23:59:59
total_payout_value16.180 SBD
curator_payout_value5.134 SBD
pending_payout_value0.000 SBD
promoted0.000 SBD
body_length14,136
author_reputation59,186,440,518,630
root_title"Electronic Circuit Simulation - Sparse Matrix Optimization (part 2) [Python]"
beneficiaries[]
max_accepted_payout1,000,000.000 SBD
percent_steem_dollars10,000
author_curate_reward""
vote details (112)
@portugalcoin ·
$5.41
Thank you for your contribution @drifter1.
We have been analyzing your tutorial and we suggest the following points:

- Excellent work in the elaboration of this tutorial. Thanks for your good work on building this tutorial.

Looking forward to your upcoming tutorials.

Your contribution has been evaluated according to [Utopian policies and guidelines](https://join.utopian.io/guidelines), as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, [click here](https://review.utopian.io/result/8/1-1-1-1-1-3-1-3-).

---- 
Need help? Chat with us on [Discord](https://discord.gg/uTyJkNm).

[[utopian-moderator]](https://join.utopian.io/)
πŸ‘  , , , , , , , , , , , , , , , , ,
properties (23)
post_id74,864,343
authorportugalcoin
permlinkre-drifter1-electronic-circuit-simulation-sparse-matrix-optimization-part-2-python-20190516t201014495z
categoryutopian-io
json_metadata{"tags":["utopian-io"],"users":["drifter1"],"links":["https:\/\/join.utopian.io\/guidelines","https:\/\/review.utopian.io\/result\/8\/1-1-1-1-1-3-1-3-","https:\/\/discord.gg\/uTyJkNm","https:\/\/join.utopian.io\/"],"app":"steemit\/0.1"}
created2019-05-16 20:10:15
last_update2019-05-16 20:10:15
depth1
children1
net_rshares9,918,192,473,370
last_payout2019-05-23 20:10:15
cashout_time1969-12-31 23:59:59
total_payout_value4.108 SBD
curator_payout_value1.304 SBD
pending_payout_value0.000 SBD
promoted0.000 SBD
body_length721
author_reputation214,343,891,436,406
root_title"Electronic Circuit Simulation - Sparse Matrix Optimization (part 2) [Python]"
beneficiaries[]
max_accepted_payout1,000,000.000 SBD
percent_steem_dollars10,000
author_curate_reward""
vote details (18)
@utopian-io ·
Thank you for your review, @portugalcoin! Keep up the good work!
properties (22)
post_id74,995,583
authorutopian-io
permlinkre-re-drifter1-electronic-circuit-simulation-sparse-matrix-optimization-part-2-python-20190516t201014495z-20190519t125705z
categoryutopian-io
json_metadata{"app":"beem\/0.20.17"}
created2019-05-19 12:57:09
last_update2019-05-19 12:57:09
depth2
children0
net_rshares0
last_payout2019-05-26 12:57:09
cashout_time1969-12-31 23:59:59
total_payout_value0.000 SBD
curator_payout_value0.000 SBD
pending_payout_value0.000 SBD
promoted0.000 SBD
body_length64
author_reputation152,913,012,544,965
root_title"Electronic Circuit Simulation - Sparse Matrix Optimization (part 2) [Python]"
beneficiaries[]
max_accepted_payout1,000,000.000 SBD
percent_steem_dollars10,000
@steem-ua ·
#### Hi @drifter1!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
**Feel free to join our [@steem-ua Discord server](https://discord.gg/KpBNYGz)**
πŸ‘  
properties (23)
post_id74,865,767
authorsteem-ua
permlinkre-electronic-circuit-simulation-sparse-matrix-optimization-part-2-python-20190516t204807z
categoryutopian-io
json_metadata{"app":"beem\/0.20.19"}
created2019-05-16 20:48:09
last_update2019-05-16 20:48:09
depth1
children0
net_rshares13,464,677,950
last_payout2019-05-23 20:48:09
cashout_time1969-12-31 23:59:59
total_payout_value0.000 SBD
curator_payout_value0.000 SBD
pending_payout_value0.000 SBD
promoted0.000 SBD
body_length287
author_reputation23,203,609,903,979
root_title"Electronic Circuit Simulation - Sparse Matrix Optimization (part 2) [Python]"
beneficiaries[]
max_accepted_payout1,000,000.000 SBD
percent_steem_dollars10,000
author_curate_reward""
vote details (1)
@utopian-io ·
Hey, @drifter1!

**Thanks for contributing on Utopian**.
We’re already looking forward to your next contribution!

**Get higher incentives and support Utopian.io!**
 Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via [SteemPlus](https://chrome.google.com/webstore/detail/steemplus/mjbkjgcplmaneajhcbegoffkedeankaj?hl=en) or [Steeditor](https://steeditor.app)).

**Want to chat? Join us on Discord https://discord.gg/h52nFrV.**

<a href='https://steemconnect.com/sign/account-witness-vote?witness=utopian-io&approve=1'>Vote for Utopian Witness!</a>
πŸ‘  
properties (23)
post_id74,883,312
authorutopian-io
permlinkre-electronic-circuit-simulation-sparse-matrix-optimization-part-2-python-20190517t052520z
categoryutopian-io
json_metadata{"app":"beem\/0.20.17"}
created2019-05-17 05:25:21
last_update2019-05-17 05:25:21
depth1
children0
net_rshares13,194,654,203
last_payout2019-05-24 05:25:21
cashout_time1969-12-31 23:59:59
total_payout_value0.000 SBD
curator_payout_value0.000 SBD
pending_payout_value0.000 SBD
promoted0.000 SBD
body_length590
author_reputation152,913,012,544,965
root_title"Electronic Circuit Simulation - Sparse Matrix Optimization (part 2) [Python]"
beneficiaries[]
max_accepted_payout1,000,000.000 SBD
percent_steem_dollars10,000
author_curate_reward""
vote details (1)