-
Notifications
You must be signed in to change notification settings - Fork 0
/
solver.py
115 lines (85 loc) · 2.78 KB
/
solver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
from numpy import *
def solve(model):
"""
solves the simulation model using newton raphson
"""
# calculate power injection vector
s = model.s_g - model.s_d
# create working variables
y = model.y
v = transpose(model.v)
vmagnitude = abs(v)
vangle = angle(v)
# calculate selection vectors for the different bus types
pv = model.pvNodeIds
pq = model.pqNodeIds
pvpq = pv
for pqbus in pq:
pvpq.append(pqbus)
# check for initial optimium
if check(v, y, s):
print "Found optimum"
# do the NR iterations
iterationNr = 0
while iterationNr < 10 and not check(v, y, s):
iterationNr += 1
# Calc Jacobian
j = calculateJacobian(y, v, pv, pq, pvpq)
# calculate power mismatch
mis = dot(dot(y, v), v) - s
realMis = real(mis)[ix_(pvpq)]
imagMis = imag(mis)[ix_(pq)]
x_mis = hstack([realMis, imagMis])
#print "Mismatch is size " + str(shape(x_mis))
# solve power flow and calculate new voltages
vtemp = (-1) * linalg.solve(j, x_mis)
# update voltages
vangle_new = vtemp[0:len(pvpq)]
vmagnitude_new = vtemp[len(pvpq):len(pvpq) + len(pq)]
for i in range(0, len(vangle_new)):
vangle[i] += vangle_new[i]
for i in range(0, len(vmagnitude_new)):
vmagnitude[i] += vmagnitude_new[i]
v = vmagnitude * exp(1j*vangle)
#print "Voltage after iteration " + str(iterationNr) + ": " + str(v)
def calculateJacobian(y, v, pv, pq, pvpq):
"""
calculates the jacobian matrix for the NR method
"""
# dS_dVm
i = dot(y, v)
diagV = diag(v)
diagVNorm = diag(v / absolute(v))
diagIconj = conjugate(diag(i))
# diag(V) (Y diag(V / ||V||))* + diag(I)* diag(V / ||V||)
dS_dVm = dot(diagV, conjugate(dot(y, diagVNorm))) + \
dot(diagIconj, diagVNorm)
# calculate_dS_dVa
dS_dVa = complex(
0, 1) * dot(diagV, conjugate(diag(i) - dot(y, diag(v))))
j11 = real(dS_dVa[ix_(pvpq, pvpq)])
j12 = real(dS_dVm[ix_(pvpq, pq)])
j21 = imag(dS_dVa[ix_(pq, pvpq)])
j22 = imag(dS_dVm[ix_(pq, pq)])
j1 = hstack([j11, j12])
j2 = hstack([j21, j22])
j = vstack([j1, j2])
#print "Jacobian is size: " + str(shape(j))
return j
def check(v, y, s):
"""
check if the NR method already converged
"""
# tolerance
tol = 1.0e-6
# check mismatch
mis = dot(conjugate(dot(y, v)), v) - s
realmis = real(mis)
imagmis = imag(mis)
xmis = concatenate((realmis, imagmis))
norm_x_mis = linalg.norm(xmis, ord=inf)
print "[SOLVER] Power mismatch: " + str(norm_x_mis)
if (norm_x_mis < tol):
return True
print "[SOLVER] Power mismatch within tolerance"
return False