1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """Total load in each load zone.
18 """
19
20 from sys import stderr
21
22 from numpy import zeros, ones, array, arange
23 from numpy import flatnonzero as find
24
25 from scipy.sparse import csr_matrix as sparse
26
27 from isload import isload
28
29 from idx_bus import PD, QD, BUS_AREA, BUS_I
30 from idx_gen import QMAX, QMIN, GEN_BUS, GEN_STATUS, PMIN
31
32
33 -def total_load(bus, gen=None, load_zone=None, which_type=None):
34 """Returns vector of total load in each load zone.
35
36 @param bus: standard C{bus} matrix with C{nb} rows, where the fixed active
37 and reactive loads are specified in columns C{PD} and C{QD}
38
39 @param gen: (optional) standard C{gen} matrix with C{ng} rows, where the
40 dispatchable loads are specified by columns C{PG}, C{QG}, C{PMIN},
41 C{QMIN} and C{QMAX} (in rows for which C{isload(GEN)} returns C{True}).
42 If C{gen} is empty, it assumes there are no dispatchable loads.
43
44 @param load_zone: (optional) C{nb} element vector where the value of
45 each element is either zero or the index of the load zone
46 to which the corresponding bus belongs. If C{load_zone(b) = k}
47 then the loads at bus C{b} will added to the values of C{Pd[k]} and
48 C{Qd[k]}. If C{load_zone} is empty, the default is defined as the areas
49 specified in the C{bus} matrix, i.e. C{load_zone = bus[:, BUS_AREA]}
50 and load will have dimension C{= max(bus[:, BUS_AREA])}. If
51 C{load_zone = 'all'}, the result is a scalar with the total system
52 load.
53
54 @param which_type: (default is 'BOTH' if C{gen} is provided, else 'FIXED')
55 - 'FIXED' : sum only fixed loads
56 - 'DISPATCHABLE' : sum only dispatchable loads
57 - 'BOTH' : sum both fixed and dispatchable loads
58
59 @see: L{scale_load}
60
61 @author: Ray Zimmerman (PSERC Cornell)
62 @author: Richard Lincoln
63 """
64 nb = bus.shape[0]
65
66 if gen is None:
67 gen = array([])
68 if load_zone is None:
69 load_zone = array([], int)
70
71
72 if len(gen) == 0:
73 which_type = 'FIXED'
74
75 if (which_type == None) and (len(gen) > 0):
76 which_type = 'BOTH'
77
78 if (which_type[0] != 'F') and (which_type[0] != 'D') and (which_type[0] != 'B'):
79 stderr.write("total_load: which_type should be 'FIXED, 'DISPATCHABLE or 'BOTH'\n")
80
81 want_Q = True
82 want_fixed = (which_type[0] == 'B') | (which_type[0] == 'F')
83 want_disp = (which_type[0] == 'B') | (which_type[0] == 'D')
84
85
86 if isinstance(load_zone, basestring) & (load_zone == 'all'):
87 load_zone = ones(nb, int)
88 elif len(load_zone) == 0:
89 load_zone = bus[:, BUS_AREA].astype(int)
90
91 nz = max(load_zone)
92
93
94 if want_fixed:
95 Pdf = bus[:, PD]
96 if want_Q:
97 Qdf = bus[:, QD]
98 else:
99 Pdf = zeros(nb)
100 if want_Q:
101 Qdf = zeros(nb)
102
103
104 if want_disp:
105 ng = gen.shape[0]
106 is_ld = isload(gen) & (gen[:, GEN_STATUS] > 0)
107 ld = find(is_ld)
108
109
110 i2e = bus[:, BUS_I].astype(int)
111 e2i = zeros(max(i2e) + 1)
112 e2i[i2e] = arange(nb)
113
114 gbus = gen[:, GEN_BUS].astype(int)
115 Cld = sparse((is_ld, (e2i[gbus], arange(ng))), (nb, ng))
116 Pdd = -Cld * gen[:, PMIN]
117 if want_Q:
118 Q = zeros(ng)
119 Q[ld] = (gen[ld, QMIN] == 0) * gen[ld, QMAX] + \
120 (gen[ld, QMAX] == 0) * gen[ld, QMIN]
121 Qdd = -Cld * Q
122 else:
123 Pdd = zeros(nb)
124 if want_Q:
125 Qdd = zeros(nb)
126
127
128 Pd = zeros(nz)
129 if want_Q:
130 Qd = zeros(nz)
131
132 for k in range(1, nz + 1):
133 idx = find(load_zone == k)
134 Pd[k - 1] = sum(Pdf[idx]) + sum(Pdd[idx])
135 if want_Q:
136 Qd[k - 1] = sum(Qdf[idx]) + sum(Qdd[idx])
137
138 return Pd, Qd
139