1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """Converts internal to external bus numbering.
18 """
19
20 import sys
21
22 from copy import deepcopy
23
24 from numpy import arange, concatenate
25
26 from idx_bus import BUS_I
27 from idx_gen import GEN_BUS
28 from idx_brch import F_BUS, T_BUS
29 from idx_area import PRICE_REF_BUS
30
31 from pypower.get_reorder import get_reorder
32 from pypower.set_reorder import set_reorder
33 from pypower.run_userfcn import run_userfcn
34
35
36 -def int2ext(ppc, val_or_field=None, oldval=None, ordering=None, dim=0):
37 """Converts internal to external bus numbering.
38
39 This function performs several different tasks, depending on the
40 arguments passed.
41
42 1. C{ppc = int2ext(ppc)}
43
44 If the input is a single PYPOWER case dict, then it restores all
45 buses, generators and branches that were removed because of being
46 isolated or off-line, and reverts to the original generator ordering
47 and original bus numbering. This requires that the 'order' key
48 created by L{ext2int} be in place.
49
50 Example::
51 ppc = int2ext(ppc)
52
53 2. C{val = int2ext(ppc, val, oldval, ordering)}
54
55 C{val = int2ext(ppc, val, oldval, ordering, dim)}
56
57 C{ppc = int2ext(ppc, field, ordering)}
58
59 C{ppc = int2ext(ppc, field, ordering, dim)}
60
61 For a case dict using internal indexing, this function can be
62 used to convert other data structures as well by passing in 2 to 4
63 extra parameters in addition to the case dict. If the values passed
64 in the 2nd argument (C{val}) is a column vector, it will be converted
65 according to the ordering specified by the 4th argument (C{ordering},
66 described below). If C{val} is an n-dimensional matrix, then the
67 optional 5th argument (C{dim}, default = 0) can be used to specify
68 which dimension to reorder. The 3rd argument (C{oldval}) is used to
69 initialize the return value before converting C{val} to external
70 indexing. In particular, any data corresponding to off-line gens
71 or branches or isolated buses or any connected gens or branches
72 will be taken from C{oldval}, with C{val} supplying the rest of the
73 returned data.
74
75 If the 2nd argument is a string or list of strings, it
76 specifies a field in the case dict whose value should be
77 converted as described above. In this case, the corresponding
78 C{oldval} is taken from where it was stored by L{ext2int} in
79 ppc["order"]["ext"] and the updated case dict is returned.
80 If C{field} is a list of strings, they specify nested fields.
81
82 The C{ordering} argument is used to indicate whether the data
83 corresponds to bus-, gen- or branch-ordered data. It can be one
84 of the following three strings: 'bus', 'gen' or 'branch'. For
85 data structures with multiple blocks of data, ordered by bus,
86 gen or branch, they can be converted with a single call by
87 specifying C{ordering} as a list of strings.
88
89 Any extra elements, rows, columns, etc. beyond those indicated
90 in C{ordering}, are not disturbed.
91
92 @see: L{ext2int}
93
94 @author: Ray Zimmerman (PSERC Cornell)
95 @author: Richard Lincoln
96 """
97 ppc = deepcopy(ppc)
98 if val_or_field is None:
99 if 'order' not in ppc:
100 sys.stderr.write('int2ext: ppc does not have the "order" field '
101 'require for conversion back to external numbering.\n')
102 o = ppc["order"]
103
104 if o["state"] == 'i':
105
106 if 'userfcn' in ppc:
107 ppc = run_userfcn(ppc["userfcn"], 'int2ext', ppc)
108
109
110 o["int"] = {}
111 o["int"]["bus"] = ppc["bus"].copy()
112 o["int"]["branch"] = ppc["branch"].copy()
113 o["int"]["gen"] = ppc["gen"].copy()
114 ppc["bus"] = o["ext"]["bus"].copy()
115 ppc["branch"] = o["ext"]["branch"].copy()
116 ppc["gen"] = o["ext"]["gen"].copy()
117 if 'gencost' in ppc:
118 o["int"]["gencost"] = ppc["gencost"].copy()
119 ppc["gencost"] = o["ext"]["gencost"].copy()
120 if 'areas' in ppc:
121 o["int"]["areas"] = ppc["areas"].copy()
122 ppc["areas"] = o["ext"]["areas"].copy()
123 if 'A' in ppc:
124 o["int"]["A"] = ppc["A"].copy()
125 ppc["A"] = o["ext"]["A"].copy()
126 if 'N' in ppc:
127 o["int"]["N"] = ppc["N"].copy()
128 ppc["N"] = o["ext"]["N"].copy()
129
130
131 ppc["bus"][o["bus"]["status"]["on"], :] = \
132 o["int"]["bus"]
133 ppc["branch"][o["branch"]["status"]["on"], :] = \
134 o["int"]["branch"]
135 ppc["gen"][o["gen"]["status"]["on"], :] = \
136 o["int"]["gen"][o["gen"]["i2e"], :]
137 if 'areas' in ppc:
138 ppc["areas"][o["areas"]["status"]["on"], :] = \
139 o["int"]["areas"]
140
141
142 ppc["bus"][o["bus"]["status"]["on"], BUS_I] = \
143 o["bus"]["i2e"] \
144 [ ppc["bus"][o["bus"]["status"]["on"], BUS_I].astype(int) ]
145 ppc["branch"][o["branch"]["status"]["on"], F_BUS] = \
146 o["bus"]["i2e"][ ppc["branch"] \
147 [o["branch"]["status"]["on"], F_BUS].astype(int) ]
148 ppc["branch"][o["branch"]["status"]["on"], T_BUS] = \
149 o["bus"]["i2e"][ ppc["branch"] \
150 [o["branch"]["status"]["on"], T_BUS].astype(int) ]
151 ppc["gen"][o["gen"]["status"]["on"], GEN_BUS] = \
152 o["bus"]["i2e"][ ppc["gen"] \
153 [o["gen"]["status"]["on"], GEN_BUS].astype(int) ]
154 if 'areas' in ppc:
155 ppc["areas"][o["areas"]["status"]["on"], PRICE_REF_BUS] = \
156 o["bus"]["i2e"][ ppc["areas"] \
157 [o["areas"]["status"]["on"], PRICE_REF_BUS].astype(int) ]
158
159 if 'ext' in o: del o['ext']
160 o["state"] = 'e'
161 ppc["order"] = o
162 else:
163 sys.stderr.write('int2ext: ppc claims it is already using '
164 'external numbering.\n')
165 else:
166 if isinstance(val_or_field, str) or isinstance(val_or_field, list):
167
168 field = val_or_field
169 if 'int' not in ppc['order']:
170 ppc['order']['int'] = {}
171
172 if isinstance(field, str):
173 key = '["%s"]' % field
174 else:
175 key = '["%s"]' % '"]["'.join(field)
176
177 v_int = ppc["order"]["int"]
178 for fld in field:
179 if fld not in v_int:
180 v_int[fld] = {}
181 v_int = v_int[fld]
182
183 exec 'ppc["order"]["int"]%s = ppc%s.copy()' % (key, key)
184 exec 'ppc%s = int2ext(ppc, ppc%s, ppc["order"]["ext"]%s, ordering, dim)' % (key, key, key)
185
186 else:
187
188 val = val_or_field.copy()
189 o = ppc["order"]
190 if isinstance(ordering, str):
191 if ordering == 'gen':
192 v = get_reorder(val, o[ordering]["i2e"], dim)
193 else:
194 v = val
195 val = set_reorder(oldval, v, o[ordering]["status"]["on"], dim)
196 else:
197 be = 0
198 bi = 0
199 new_v = []
200 for ord in ordering:
201 ne = o["ext"][ord].shape[0]
202 ni = ppc[ord].shape[0]
203 v = get_reorder(val, bi + arange(ni), dim)
204 oldv = get_reorder(oldval, be + arange(ne), dim)
205 new_v.append( int2ext(ppc, v, oldv, ord, dim) )
206 be = be + ne
207 bi = bi + ni
208 ni = val.shape[dim]
209 if ni > bi:
210 v = get_reorder(val, arange(bi, ni), dim)
211 new_v.append(v)
212 val = concatenate(new_v, dim)
213 return val
214
215 return ppc
216
217
218 -def int2ext1(i2e, bus, gen, branch, areas):
219 """Converts from the consecutive internal bus numbers back to the originals
220 using the mapping provided by the I2E vector returned from C{ext2int}.
221
222 @see: L{ext2int}
223 @see: U{http://www.pserc.cornell.edu/matpower/}
224 """
225 bus[:, BUS_I] = i2e[ bus[:, BUS_I].astype(int) ]
226 gen[:, GEN_BUS] = i2e[ gen[:, GEN_BUS].astype(int) ]
227 branch[:, F_BUS] = i2e[ branch[:, F_BUS].astype(int) ]
228 branch[:, T_BUS] = i2e[ branch[:, T_BUS].astype(int) ]
229
230 if areas != None and len(areas) > 0:
231 areas[:, PRICE_REF_BUS] = i2e[ areas[:, PRICE_REF_BUS].astype(int) ]
232 return bus, gen, branch, areas
233
234 return bus, gen, branch
235