Python Modified Nodal Analysis test
This commit is contained in:
parent
2fe03bf8bf
commit
daf176e918
329
test.py
Normal file
329
test.py
Normal file
|
|
@ -0,0 +1,329 @@
|
|||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from numpy import linalg
|
||||
from math import pi, sin
|
||||
|
||||
def Create_MNA(mat_cons):
|
||||
Y = np.zeros(mat_cons[0])
|
||||
B = np.zeros(mat_cons[1])
|
||||
C = np.zeros(mat_cons[2])
|
||||
D = np.zeros(mat_cons[3])
|
||||
|
||||
return [Y,B,C,D]
|
||||
|
||||
class Voltage_Supply:
|
||||
def __init__(self, func, a, b):
|
||||
self.node_a = a - 1
|
||||
self.node_b = b - 1
|
||||
self.v = 0
|
||||
self.func = func
|
||||
self.branch_current_node = 0
|
||||
self.vp = 0
|
||||
self.ip = 0
|
||||
|
||||
def set_voltages_currents(self, v, c):
|
||||
if self.node_b > 0 and self.node_a > 0:
|
||||
self.vp = v[self.node_a] - v[self.node_b]
|
||||
elif self.node_b <= 0 and self.node_a > 0:
|
||||
self.vp = v[self.node_a]
|
||||
elif self.node_b > 0 and self.node_b <= 0:
|
||||
self.vp = v[self.node_b]
|
||||
|
||||
if self.needs_branches:
|
||||
self.ip = c[self.branch_current_node]
|
||||
|
||||
def set_time(self, t):
|
||||
self.v = self.func(t)
|
||||
|
||||
def needs_branches(self):
|
||||
return True
|
||||
|
||||
def set_branch_current_node(self, a):
|
||||
self.branch_current_node = a
|
||||
|
||||
def get_matrix(self, mat_cons):
|
||||
Y,B,C,D = Create_MNA(mat_cons)
|
||||
|
||||
if self.node_b >= 0:
|
||||
B[self.node_b][self.branch_current_node] = 1
|
||||
C[self.branch_current_node][self.node_b] = 1
|
||||
if self.node_a >= 0:
|
||||
B[self.node_a][self.branch_current_node] = -1
|
||||
C[self.branch_current_node][self.node_a] = -1
|
||||
|
||||
M = np.block([[Y,B],[C,D]])
|
||||
RHS_Top = np.zeros((mat_cons[0][0], 1))
|
||||
RHS_Bot = np.zeros((mat_cons[2][0], 1))
|
||||
RHS_Bot[self.branch_current_node] = self.v
|
||||
|
||||
RHS = np.block([[RHS_Top], [RHS_Bot]])
|
||||
|
||||
return [M, RHS]
|
||||
|
||||
class Resistance:
|
||||
def __init__(self, func, a, b):
|
||||
self.node_a = a - 1
|
||||
self.node_b = b - 1
|
||||
self.r = 0
|
||||
self.func = func
|
||||
self.vp = 0
|
||||
self.ip = 0
|
||||
|
||||
def set_voltages_currents(self, v, c):
|
||||
if self.node_b > 0 and self.node_a > 0:
|
||||
self.vp = v[self.node_a] - v[self.node_b]
|
||||
elif self.node_b <= 0 and self.node_a > 0:
|
||||
self.vp = v[self.node_a]
|
||||
elif self.node_b > 0 and self.node_b <= 0:
|
||||
self.vp = v[self.node_b]
|
||||
|
||||
def set_time(self, t):
|
||||
self.r = self.func(t)
|
||||
|
||||
def needs_branches(self):
|
||||
return False
|
||||
|
||||
def get_matrix(self, mat_cons):
|
||||
Y,B,C,D = Create_MNA(mat_cons)
|
||||
|
||||
a = self.node_a
|
||||
b = self.node_b
|
||||
|
||||
if b >= 0:
|
||||
Y[b,b] = self.r
|
||||
if a >= 0:
|
||||
Y[a,a] = self.r
|
||||
|
||||
if a >= 0 and b >= 0:
|
||||
Y[a,b] = -self.r
|
||||
Y[b,a] = -self.r
|
||||
|
||||
M = np.block([[Y,B], [C,D]])
|
||||
RHS = np.zeros((mat_cons[0][0] + mat_cons[2][0], 1))
|
||||
|
||||
return [M, RHS]
|
||||
|
||||
class Inductor:
|
||||
def __init__(self, func, a, b):
|
||||
self.node_a = a - 1
|
||||
self.node_b = b - 1
|
||||
self.l = 0
|
||||
self.func = func
|
||||
self.previous_t = 0.0
|
||||
self.current_t = 0.0
|
||||
self.vp = 0
|
||||
self.ip = 0
|
||||
|
||||
def set_voltages_currents(self, v, c):
|
||||
if self.node_b > 0 and self.node_a > 0:
|
||||
self.vp = v[self.node_a] - v[self.node_b]
|
||||
elif self.node_b <= 0 and self.node_a > 0:
|
||||
self.vp = v[self.node_a]
|
||||
elif self.node_b > 0 and self.node_b <= 0:
|
||||
self.vp = -v[self.node_b]
|
||||
|
||||
if self.needs_branches:
|
||||
self.ip = c[self.branch_current_node]
|
||||
|
||||
def set_time(self, t):
|
||||
self.previous_t = self.current_t
|
||||
self.current_t = t
|
||||
self.l = self.func(t)
|
||||
|
||||
def needs_branches(self):
|
||||
return True
|
||||
|
||||
def set_branch_current_node(self, a):
|
||||
self.branch_current_node = a
|
||||
|
||||
def get_matrix(self, mat_cons):
|
||||
Y,B,C,D = Create_MNA(mat_cons)
|
||||
|
||||
a = self.node_a
|
||||
b = self.node_b
|
||||
h = self.current_t - self.previous_t
|
||||
lh = self.l / h
|
||||
|
||||
if self.node_b >= 0:
|
||||
B[self.node_b][self.branch_current_node] = -1
|
||||
C[self.branch_current_node][self.node_b] = -1
|
||||
if self.node_a >= 0:
|
||||
B[self.node_a][self.branch_current_node] = 1
|
||||
C[self.branch_current_node][self.node_a] = 1
|
||||
|
||||
D[self.branch_current_node][self.branch_current_node] = -lh
|
||||
|
||||
M = np.block([[Y,B],[C,D]])
|
||||
RHS_Top = np.zeros((mat_cons[0][0], 1))
|
||||
RHS_Bot = np.zeros((mat_cons[2][0], 1))
|
||||
RHS_Bot[self.branch_current_node] = -lh * self.ip
|
||||
|
||||
RHS = np.block([[RHS_Top], [RHS_Bot]])
|
||||
|
||||
return [M, RHS]
|
||||
|
||||
class Capacitor:
|
||||
def __init__(self, func, a, b):
|
||||
self.node_a = a - 1
|
||||
self.node_b = b - 1
|
||||
self.c = 0
|
||||
self.func = func
|
||||
self.previous_t = 0.0
|
||||
self.current_t = 0.0
|
||||
self.vp = 0
|
||||
self.ip = 0
|
||||
|
||||
def set_voltages_currents(self, v, c):
|
||||
if self.node_b > 0 and self.node_a > 0:
|
||||
self.vp = v[self.node_a] - v[self.node_b]
|
||||
elif self.node_b <= 0 and self.node_a > 0:
|
||||
self.vp = v[self.node_a]
|
||||
elif self.node_b > 0 and self.node_b <= 0:
|
||||
self.vp = -v[self.node_b]
|
||||
|
||||
def set_time(self, t):
|
||||
self.previous_t = self.current_t
|
||||
self.current_t = t
|
||||
self.c = self.func(t)
|
||||
|
||||
def needs_branches(self):
|
||||
return False
|
||||
|
||||
def set_branch_current_node(self, a):
|
||||
self.branch_current_node = a
|
||||
|
||||
def get_matrix(self, mat_cons):
|
||||
Y,B,C,D = Create_MNA(mat_cons)
|
||||
|
||||
a = self.node_a
|
||||
b = self.node_b
|
||||
|
||||
h = self.current_t - self.previous_t
|
||||
ch = self.c / h
|
||||
|
||||
if b >= 0:
|
||||
Y[b,b] = ch
|
||||
if a >= 0:
|
||||
Y[a,a] = ch
|
||||
|
||||
if a >= 0 and b >= 0:
|
||||
Y[a,b] = -ch
|
||||
Y[b,a] = -ch
|
||||
|
||||
M = np.block([[Y,B],[C,D]])
|
||||
RHS_Top = np.zeros((mat_cons[0][0], 1))
|
||||
RHS_Bot = np.zeros((mat_cons[2][0], 1))
|
||||
|
||||
if a > 0:
|
||||
RHS_Top[a] = ch * self.vp
|
||||
if b > 0:
|
||||
RHS_Top[b] = - ch * self.vp
|
||||
|
||||
RHS = np.block([[RHS_Top], [RHS_Bot]])
|
||||
|
||||
return [M, RHS]
|
||||
|
||||
def run( netlist, t0, t1, points):
|
||||
counter = 0
|
||||
nodes = list()
|
||||
for j in netlist:
|
||||
if j.needs_branches():
|
||||
j.set_branch_current_node(counter)
|
||||
counter += 1
|
||||
nodes.append(j.node_a)
|
||||
nodes.append(j.node_b)
|
||||
|
||||
max_node = max(nodes) + 1
|
||||
|
||||
Y = (max_node,max_node)
|
||||
B = (max_node,counter)
|
||||
C = (counter,max_node)
|
||||
D = (counter,counter)
|
||||
|
||||
M = (max_node+counter, max_node+counter)
|
||||
RHS = (max_node+counter, 1)
|
||||
|
||||
mat_cons = [Y,B,C,D]
|
||||
|
||||
t_space = np.linspace(t0,t1,points)[1:]
|
||||
|
||||
answer_array = list()
|
||||
answer_array.append(list())
|
||||
|
||||
for i in range(0,M[0]):
|
||||
answer_array.append(list())
|
||||
|
||||
for t in range(0, len(t_space)):
|
||||
mat = np.zeros(M)
|
||||
rhs = np.zeros(RHS)
|
||||
for i in netlist:
|
||||
i.set_time(t_space[t])
|
||||
m, r = i.get_matrix(mat_cons)
|
||||
mat += m
|
||||
rhs += r
|
||||
|
||||
ans = linalg.lstsq(mat,rhs)[0]
|
||||
|
||||
voltages = ans[:max_node]
|
||||
currents = ans[max_node:]
|
||||
|
||||
voltages = [v[0] for v in voltages]
|
||||
currents = [c[0] for c in currents]
|
||||
|
||||
for j in netlist:
|
||||
j.set_voltages_currents(voltages, currents)
|
||||
|
||||
answer_array[0].append(t_space[t])
|
||||
for i in range(0, len(ans)):
|
||||
answer_array[i+1].append(ans[i][0])
|
||||
|
||||
return answer_array
|
||||
|
||||
def R_func(t):
|
||||
return 1/1000.0
|
||||
|
||||
def V1_func(t):
|
||||
#if t > 0.00001 * 0.5:
|
||||
# return 5
|
||||
#else:
|
||||
# return 0
|
||||
v = 0
|
||||
for i in range(1, 10, 2):
|
||||
v += (10.0/i)*sin(2*pi*i*1000000.0*t)
|
||||
return v
|
||||
|
||||
def L_func(t):
|
||||
return 1.0e-9
|
||||
|
||||
def C_func(t):
|
||||
return 1000.0e-12
|
||||
|
||||
def C1_func(t):
|
||||
return 1.0e-12
|
||||
|
||||
def V2_func(t):
|
||||
if t == 0.0:
|
||||
return -2.5
|
||||
else:
|
||||
return 0
|
||||
|
||||
netlist = [
|
||||
Voltage_Supply(V1_func, 0, 1),
|
||||
#Inductor(L_func, 1, 2),
|
||||
Capacitor(C1_func, 1, 2),
|
||||
Resistance(R_func, 1, 2),
|
||||
Capacitor(C_func, 2, 0),
|
||||
Resistance(R_func, 2, 0)
|
||||
#Voltage_Supply(V2_func, 0, 3)
|
||||
]
|
||||
|
||||
|
||||
ans = run(netlist, 0.0, 0.00001, 100000)
|
||||
|
||||
plt.plot(ans[0],ans[1], 'r')
|
||||
plt.plot(ans[0],ans[2], 'g')
|
||||
#plt.plot(t, outs[3])
|
||||
plt.show()
|
||||
|
||||
plt.plot(ans[0], ans[3], 'r')
|
||||
plt.show()
|
||||
Loading…
Reference in New Issue
Block a user