ltbams 0.9.9__py3-none-any.whl → 1.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ams/__init__.py +4 -11
- ams/_version.py +3 -3
- ams/cases/5bus/pjm5bus_demo.xlsx +0 -0
- ams/cases/5bus/pjm5bus_jumper.xlsx +0 -0
- ams/cases/5bus/pjm5bus_uced.json +1062 -0
- ams/cases/5bus/pjm5bus_uced.xlsx +0 -0
- ams/cases/5bus/pjm5bus_uced_esd1.xlsx +0 -0
- ams/cases/5bus/pjm5bus_uced_ev.xlsx +0 -0
- ams/cases/ieee123/ieee123.xlsx +0 -0
- ams/cases/ieee123/ieee123_regcv1.xlsx +0 -0
- ams/cases/ieee14/ieee14.json +1166 -0
- ams/cases/ieee14/ieee14.raw +92 -0
- ams/cases/ieee14/ieee14_conn.xlsx +0 -0
- ams/cases/ieee14/ieee14_uced.xlsx +0 -0
- ams/cases/ieee39/ieee39.xlsx +0 -0
- ams/cases/ieee39/ieee39_uced.xlsx +0 -0
- ams/cases/ieee39/ieee39_uced_esd1.xlsx +0 -0
- ams/cases/ieee39/ieee39_uced_pvd1.xlsx +0 -0
- ams/cases/ieee39/ieee39_uced_vis.xlsx +0 -0
- ams/cases/matpower/benchmark.json +1594 -0
- ams/cases/matpower/case118.m +787 -0
- ams/cases/matpower/case14.m +129 -0
- ams/cases/matpower/case300.m +1315 -0
- ams/cases/matpower/case39.m +205 -0
- ams/cases/matpower/case5.m +62 -0
- ams/cases/matpower/case_ACTIVSg2000.m +9460 -0
- ams/cases/npcc/npcc.m +644 -0
- ams/cases/npcc/npcc_uced.xlsx +0 -0
- ams/cases/pglib/pglib_opf_case39_epri__api.m +243 -0
- ams/cases/wecc/wecc.m +714 -0
- ams/cases/wecc/wecc_uced.xlsx +0 -0
- ams/cli.py +6 -0
- ams/core/__init__.py +2 -0
- ams/core/documenter.py +652 -0
- ams/core/matprocessor.py +782 -0
- ams/core/model.py +330 -0
- ams/core/param.py +322 -0
- ams/core/service.py +918 -0
- ams/core/symprocessor.py +224 -0
- ams/core/var.py +59 -0
- ams/extension/__init__.py +5 -0
- ams/extension/eva.py +401 -0
- ams/interface.py +1085 -0
- ams/io/__init__.py +133 -0
- ams/io/json.py +82 -0
- ams/io/matpower.py +406 -0
- ams/io/psse.py +6 -0
- ams/io/pypower.py +103 -0
- ams/io/xlsx.py +80 -0
- ams/main.py +81 -4
- ams/models/__init__.py +24 -0
- ams/models/area.py +40 -0
- ams/models/bus.py +52 -0
- ams/models/cost.py +169 -0
- ams/models/distributed/__init__.py +3 -0
- ams/models/distributed/esd1.py +71 -0
- ams/models/distributed/ev.py +60 -0
- ams/models/distributed/pvd1.py +67 -0
- ams/models/group.py +231 -0
- ams/models/info.py +26 -0
- ams/models/line.py +238 -0
- ams/models/renewable/__init__.py +5 -0
- ams/models/renewable/regc.py +119 -0
- ams/models/reserve.py +94 -0
- ams/models/shunt.py +14 -0
- ams/models/static/__init__.py +2 -0
- ams/models/static/gen.py +165 -0
- ams/models/static/pq.py +61 -0
- ams/models/timeslot.py +69 -0
- ams/models/zone.py +49 -0
- ams/opt/__init__.py +12 -0
- ams/opt/constraint.py +175 -0
- ams/opt/exprcalc.py +127 -0
- ams/opt/expression.py +188 -0
- ams/opt/objective.py +174 -0
- ams/opt/omodel.py +432 -0
- ams/opt/optzbase.py +192 -0
- ams/opt/param.py +156 -0
- ams/opt/var.py +233 -0
- ams/pypower/__init__.py +8 -0
- ams/pypower/_compat.py +9 -0
- ams/pypower/core/__init__.py +8 -0
- ams/pypower/core/pips.py +894 -0
- ams/pypower/core/ppoption.py +244 -0
- ams/pypower/core/ppver.py +18 -0
- ams/pypower/core/solver.py +2451 -0
- ams/pypower/eps.py +6 -0
- ams/pypower/idx.py +174 -0
- ams/pypower/io.py +604 -0
- ams/pypower/make/__init__.py +11 -0
- ams/pypower/make/matrices.py +665 -0
- ams/pypower/make/pdv.py +506 -0
- ams/pypower/routines/__init__.py +7 -0
- ams/pypower/routines/cpf.py +513 -0
- ams/pypower/routines/cpf_callbacks.py +114 -0
- ams/pypower/routines/opf.py +1803 -0
- ams/pypower/routines/opffcns.py +1946 -0
- ams/pypower/routines/pflow.py +852 -0
- ams/pypower/toggle.py +1098 -0
- ams/pypower/utils.py +293 -0
- ams/report.py +212 -50
- ams/routines/__init__.py +23 -0
- ams/routines/acopf.py +117 -0
- ams/routines/cpf.py +65 -0
- ams/routines/dcopf.py +241 -0
- ams/routines/dcpf.py +209 -0
- ams/routines/dcpf0.py +196 -0
- ams/routines/dopf.py +150 -0
- ams/routines/ed.py +312 -0
- ams/routines/pflow.py +255 -0
- ams/routines/pflow0.py +113 -0
- ams/routines/routine.py +1033 -0
- ams/routines/rted.py +519 -0
- ams/routines/type.py +160 -0
- ams/routines/uc.py +376 -0
- ams/shared.py +63 -9
- ams/system.py +61 -22
- ams/utils/__init__.py +3 -0
- ams/utils/misc.py +77 -0
- ams/utils/paths.py +257 -0
- docs/Makefile +21 -0
- docs/make.bat +35 -0
- docs/source/_templates/autosummary/base.rst +5 -0
- docs/source/_templates/autosummary/class.rst +35 -0
- docs/source/_templates/autosummary/module.rst +65 -0
- docs/source/_templates/autosummary/module_toctree.rst +66 -0
- docs/source/api.rst +102 -0
- docs/source/conf.py +206 -0
- docs/source/examples/index.rst +34 -0
- docs/source/genmodelref.py +61 -0
- docs/source/genroutineref.py +47 -0
- docs/source/getting_started/copyright.rst +20 -0
- docs/source/getting_started/formats/index.rst +20 -0
- docs/source/getting_started/formats/matpower.rst +183 -0
- docs/source/getting_started/formats/psse.rst +46 -0
- docs/source/getting_started/formats/pypower.rst +223 -0
- docs/source/getting_started/formats/xlsx.png +0 -0
- docs/source/getting_started/formats/xlsx.rst +23 -0
- docs/source/getting_started/index.rst +76 -0
- docs/source/getting_started/install.rst +231 -0
- docs/source/getting_started/overview.rst +26 -0
- docs/source/getting_started/testcase.rst +45 -0
- docs/source/getting_started/verification.rst +13 -0
- docs/source/images/curent.ico +0 -0
- docs/source/images/dcopf_time.png +0 -0
- docs/source/images/sponsors/CURENT_Logo_NameOnTrans.png +0 -0
- docs/source/images/sponsors/CURENT_Logo_Transparent.png +0 -0
- docs/source/images/sponsors/CURENT_Logo_Transparent_Name.png +0 -0
- docs/source/images/sponsors/doe.png +0 -0
- docs/source/index.rst +108 -0
- docs/source/modeling/example.rst +159 -0
- docs/source/modeling/index.rst +17 -0
- docs/source/modeling/model.rst +210 -0
- docs/source/modeling/routine.rst +122 -0
- docs/source/modeling/system.rst +51 -0
- docs/source/release-notes.rst +398 -0
- ltbams-1.0.2.dist-info/METADATA +215 -0
- ltbams-1.0.2.dist-info/RECORD +188 -0
- {ltbams-0.9.9.dist-info → ltbams-1.0.2.dist-info}/WHEEL +1 -1
- ltbams-1.0.2.dist-info/top_level.txt +3 -0
- tests/__init__.py +0 -0
- tests/test_1st_system.py +33 -0
- tests/test_addressing.py +40 -0
- tests/test_andes_mats.py +61 -0
- tests/test_case.py +266 -0
- tests/test_cli.py +34 -0
- tests/test_export_csv.py +89 -0
- tests/test_group.py +83 -0
- tests/test_interface.py +216 -0
- tests/test_io.py +32 -0
- tests/test_jumper.py +27 -0
- tests/test_known_good.py +267 -0
- tests/test_matp.py +437 -0
- tests/test_model.py +54 -0
- tests/test_omodel.py +119 -0
- tests/test_paths.py +22 -0
- tests/test_report.py +251 -0
- tests/test_repr.py +21 -0
- tests/test_routine.py +178 -0
- tests/test_rtn_dcopf.py +101 -0
- tests/test_rtn_dcpf.py +77 -0
- tests/test_rtn_ed.py +279 -0
- tests/test_rtn_pflow.py +219 -0
- tests/test_rtn_rted.py +273 -0
- tests/test_rtn_uc.py +248 -0
- tests/test_service.py +73 -0
- ltbams-0.9.9.dist-info/LICENSE +0 -692
- ltbams-0.9.9.dist-info/METADATA +0 -859
- ltbams-0.9.9.dist-info/RECORD +0 -14
- ltbams-0.9.9.dist-info/top_level.txt +0 -1
- {ltbams-0.9.9.dist-info → ltbams-1.0.2.dist-info}/entry_points.txt +0 -0
ams/routines/pflow.py
ADDED
@@ -0,0 +1,255 @@
|
|
1
|
+
"""
|
2
|
+
Power flow routines using ANDES.
|
3
|
+
"""
|
4
|
+
import logging
|
5
|
+
from typing import Optional, Union, Type
|
6
|
+
from collections import OrderedDict
|
7
|
+
|
8
|
+
import numpy as np
|
9
|
+
|
10
|
+
from andes.utils.misc import elapsed
|
11
|
+
|
12
|
+
from ams.core.param import RParam
|
13
|
+
from ams.routines.routine import RoutineBase
|
14
|
+
from ams.opt import Var, Expression, Objective
|
15
|
+
from ams.interface import _to_andes_pflow, sync_adsys
|
16
|
+
|
17
|
+
logger = logging.getLogger(__name__)
|
18
|
+
|
19
|
+
|
20
|
+
class PFlow(RoutineBase):
|
21
|
+
"""
|
22
|
+
Power flow analysis using ANDES PFlow routine.
|
23
|
+
|
24
|
+
More settings can be changed via ``PFlow2._adsys.config`` and ``PFlow2._adsys.PFlow.config``.
|
25
|
+
|
26
|
+
All generator output powers, bus voltages, and angles are included in the variable definitions.
|
27
|
+
However, not all of these are unknowns; the definitions are provided for easy access.
|
28
|
+
|
29
|
+
References
|
30
|
+
----------
|
31
|
+
[1] M. L. Crow, Computational methods for electric power systems. 2015.
|
32
|
+
|
33
|
+
[2] ANDES Documentation - Simulation and Plot. [Online]. Available:
|
34
|
+
https://docs.andes.app/en/latest/_examples/ex1.html
|
35
|
+
"""
|
36
|
+
|
37
|
+
def __init__(self, system, config):
|
38
|
+
RoutineBase.__init__(self, system, config)
|
39
|
+
self.info = 'AC Power Flow'
|
40
|
+
self.type = 'PF'
|
41
|
+
self._adsys = None
|
42
|
+
|
43
|
+
self.config.add(OrderedDict((('tol', 1e-6),
|
44
|
+
('max_iter', 25),
|
45
|
+
('method', 'NR'),
|
46
|
+
('check_conn', 1),
|
47
|
+
('n_factorize', 4),
|
48
|
+
)))
|
49
|
+
self.config.add_extra("_help",
|
50
|
+
tol="convergence tolerance",
|
51
|
+
max_iter="max. number of iterations",
|
52
|
+
method="calculation method",
|
53
|
+
check_conn='check connectivity before power flow',
|
54
|
+
n_factorize="first N iterations to factorize Jacobian in dishonest method",
|
55
|
+
)
|
56
|
+
self.config.add_extra("_alt",
|
57
|
+
tol="float",
|
58
|
+
method=("NR", "dishonest", "NK"),
|
59
|
+
check_conn=(0, 1),
|
60
|
+
max_iter=">=10",
|
61
|
+
n_factorize=">0",
|
62
|
+
)
|
63
|
+
|
64
|
+
self.Bf = RParam(info='Bf matrix',
|
65
|
+
name='Bf', tex_name=r'B_{f}',
|
66
|
+
model='mats', src='Bf',
|
67
|
+
no_parse=True, sparse=True,)
|
68
|
+
self.Pfinj = RParam(info='Line power injection vector',
|
69
|
+
name='Pfinj', tex_name=r'P_{f}^{inj}',
|
70
|
+
model='mats', src='Pfinj',
|
71
|
+
no_parse=True,)
|
72
|
+
|
73
|
+
self.pg = Var(info='Gen active power',
|
74
|
+
unit='p.u.',
|
75
|
+
name='pg', tex_name=r'p_g',
|
76
|
+
model='StaticGen', src='p')
|
77
|
+
self.qg = Var(info='Gen reactive power',
|
78
|
+
unit='p.u.',
|
79
|
+
name='qg', tex_name=r'q_g',
|
80
|
+
model='StaticGen', src='q')
|
81
|
+
self.aBus = Var(info='Bus voltage angle',
|
82
|
+
unit='rad',
|
83
|
+
name='aBus', tex_name=r'\theta_{bus}',
|
84
|
+
model='Bus', src='a',)
|
85
|
+
self.vBus = Var(info='Bus voltage magnitude',
|
86
|
+
unit='p.u.',
|
87
|
+
name='vBus', tex_name=r'V_{bus}',
|
88
|
+
model='Bus', src='v',)
|
89
|
+
self.plf = Expression(info='Line flow',
|
90
|
+
name='plf', tex_name=r'p_{lf}',
|
91
|
+
unit='p.u.',
|
92
|
+
e_str='Bf@aBus + Pfinj',
|
93
|
+
model='Line', src=None,)
|
94
|
+
|
95
|
+
self.obj = Objective(name='obj',
|
96
|
+
info='place holder', unit='$',
|
97
|
+
sense='min', e_str='0',)
|
98
|
+
|
99
|
+
def init(self, **kwargs):
|
100
|
+
"""
|
101
|
+
Initialize the ANDES PFlow routine.
|
102
|
+
|
103
|
+
kwargs go to andes.system.System().
|
104
|
+
"""
|
105
|
+
self._adsys = _to_andes_pflow(self.system,
|
106
|
+
no_output=self.system.files.no_output,
|
107
|
+
config=self.config.as_dict(),
|
108
|
+
**kwargs)
|
109
|
+
self._adsys.setup()
|
110
|
+
self.om.init()
|
111
|
+
self.initialized = True
|
112
|
+
return self.initialized
|
113
|
+
|
114
|
+
def solve(self, **kwargs):
|
115
|
+
"""
|
116
|
+
Placeholder.
|
117
|
+
"""
|
118
|
+
return True
|
119
|
+
|
120
|
+
def run(self, **kwargs):
|
121
|
+
"""
|
122
|
+
Run the routine.
|
123
|
+
"""
|
124
|
+
if not self.initialized:
|
125
|
+
self.init()
|
126
|
+
|
127
|
+
t0, _ = elapsed()
|
128
|
+
_ = self._adsys.PFlow.run()
|
129
|
+
self.exit_code = self._adsys.exit_code
|
130
|
+
self.converged = self.exit_code == 0
|
131
|
+
_, s = elapsed(t0)
|
132
|
+
self.exec_time = float(s.split(" ")[0])
|
133
|
+
|
134
|
+
self.unpack()
|
135
|
+
return True
|
136
|
+
|
137
|
+
def _post_solve(self):
|
138
|
+
"""
|
139
|
+
Placeholder.
|
140
|
+
"""
|
141
|
+
return True
|
142
|
+
|
143
|
+
def unpack(self, **kwargs):
|
144
|
+
"""
|
145
|
+
Unpack the results from ANDES PFlow routine.
|
146
|
+
"""
|
147
|
+
# TODO: maybe also include the DC devices results
|
148
|
+
sys = self.system
|
149
|
+
# --- device results ---
|
150
|
+
bus_idx = sys.Bus.idx.v
|
151
|
+
sys.Bus.set(src='v', attr='v', idx=bus_idx,
|
152
|
+
value=self._adsys.Bus.get(src='v', attr='v', idx=bus_idx))
|
153
|
+
sys.Bus.set(src='a', attr='v', idx=bus_idx,
|
154
|
+
value=self._adsys.Bus.get(src='a', attr='v', idx=bus_idx))
|
155
|
+
pv_idx = sys.PV.idx.v
|
156
|
+
pv_u = sys.PV.get(src='u', attr='v', idx=pv_idx)
|
157
|
+
# NOTE: for p, we should consider the online status as p0 is a param
|
158
|
+
sys.PV.set(src='p', attr='v', idx=pv_idx,
|
159
|
+
value=pv_u * sys.PV.get(src='p0', attr='v', idx=pv_idx))
|
160
|
+
sys.PV.set(src='q', attr='v', idx=pv_idx,
|
161
|
+
value=self._adsys.PV.get(src='q', attr='v', idx=pv_idx))
|
162
|
+
slack_idx = sys.Slack.idx.v
|
163
|
+
sys.Slack.set(src='p', attr='v', idx=slack_idx,
|
164
|
+
value=self._adsys.Slack.get(src='p', attr='v', idx=slack_idx))
|
165
|
+
sys.Slack.set(src='q', attr='v', idx=slack_idx,
|
166
|
+
value=self._adsys.Slack.get(src='q', attr='v', idx=slack_idx))
|
167
|
+
# --- routine results ---
|
168
|
+
self.pg.optz.value = sys.StaticGen.get(src='p', attr='v', idx=self.pg.get_all_idxes())
|
169
|
+
self.qg.optz.value = sys.StaticGen.get(src='q', attr='v', idx=self.qg.get_all_idxes())
|
170
|
+
self.aBus.optz.value = sys.Bus.get(src='a', attr='v', idx=self.aBus.get_all_idxes())
|
171
|
+
self.vBus.optz.value = sys.Bus.get(src='v', attr='v', idx=self.vBus.get_all_idxes())
|
172
|
+
return True
|
173
|
+
|
174
|
+
def update(self, params=None, build_mats=False):
|
175
|
+
"""
|
176
|
+
This method updates the parameters in the optimization model. In this routine,
|
177
|
+
the `params` and `build_mats` arguments are not used because the parameters
|
178
|
+
are updated directly to the ANDES system.
|
179
|
+
"""
|
180
|
+
if not self.initialized:
|
181
|
+
self.init()
|
182
|
+
|
183
|
+
sync_adsys(self.system, self._adsys)
|
184
|
+
|
185
|
+
return True
|
186
|
+
|
187
|
+
def enable(self, name):
|
188
|
+
raise NotImplementedError
|
189
|
+
|
190
|
+
def disable(self, name):
|
191
|
+
raise NotImplementedError
|
192
|
+
|
193
|
+
def addRParam(self,
|
194
|
+
name: str,
|
195
|
+
tex_name: Optional[str] = None,
|
196
|
+
info: Optional[str] = None,
|
197
|
+
src: Optional[str] = None,
|
198
|
+
unit: Optional[str] = None,
|
199
|
+
model: Optional[str] = None,
|
200
|
+
v: Optional[np.ndarray] = None,
|
201
|
+
indexer: Optional[str] = None,
|
202
|
+
imodel: Optional[str] = None,):
|
203
|
+
"""
|
204
|
+
Not supported!
|
205
|
+
"""
|
206
|
+
raise NotImplementedError
|
207
|
+
|
208
|
+
def addService(self,
|
209
|
+
name: str,
|
210
|
+
value: np.ndarray,
|
211
|
+
tex_name: str = None,
|
212
|
+
unit: str = None,
|
213
|
+
info: str = None,
|
214
|
+
vtype: Type = None,):
|
215
|
+
"""
|
216
|
+
Not supported!
|
217
|
+
"""
|
218
|
+
raise NotImplementedError
|
219
|
+
|
220
|
+
def addConstrs(self,
|
221
|
+
name: str,
|
222
|
+
e_str: str,
|
223
|
+
info: Optional[str] = None,
|
224
|
+
is_eq: Optional[str] = False,):
|
225
|
+
"""
|
226
|
+
Not supported!
|
227
|
+
"""
|
228
|
+
raise NotImplementedError
|
229
|
+
|
230
|
+
def addVars(self,
|
231
|
+
name: str,
|
232
|
+
model: Optional[str] = None,
|
233
|
+
shape: Optional[Union[int, tuple]] = None,
|
234
|
+
tex_name: Optional[str] = None,
|
235
|
+
info: Optional[str] = None,
|
236
|
+
src: Optional[str] = None,
|
237
|
+
unit: Optional[str] = None,
|
238
|
+
horizon: Optional[RParam] = None,
|
239
|
+
nonneg: Optional[bool] = False,
|
240
|
+
nonpos: Optional[bool] = False,
|
241
|
+
cplx: Optional[bool] = False,
|
242
|
+
imag: Optional[bool] = False,
|
243
|
+
symmetric: Optional[bool] = False,
|
244
|
+
diag: Optional[bool] = False,
|
245
|
+
psd: Optional[bool] = False,
|
246
|
+
nsd: Optional[bool] = False,
|
247
|
+
hermitian: Optional[bool] = False,
|
248
|
+
boolean: Optional[bool] = False,
|
249
|
+
integer: Optional[bool] = False,
|
250
|
+
pos: Optional[bool] = False,
|
251
|
+
neg: Optional[bool] = False,):
|
252
|
+
"""
|
253
|
+
Not supported!
|
254
|
+
"""
|
255
|
+
raise NotImplementedError
|
ams/routines/pflow0.py
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
"""
|
2
|
+
Power flow routines using PYPOWER.
|
3
|
+
"""
|
4
|
+
import logging
|
5
|
+
from collections import OrderedDict
|
6
|
+
|
7
|
+
from ams.pypower import runpf
|
8
|
+
|
9
|
+
from ams.io.pypower import system2ppc
|
10
|
+
from ams.pypower.core import ppoption
|
11
|
+
from ams.core.param import RParam
|
12
|
+
|
13
|
+
from ams.routines.dcpf0 import DCPF0
|
14
|
+
from ams.opt import Var
|
15
|
+
|
16
|
+
logger = logging.getLogger(__name__)
|
17
|
+
|
18
|
+
|
19
|
+
class PFlow0(DCPF0):
|
20
|
+
"""
|
21
|
+
AC Power Flow using PYPOWER.
|
22
|
+
|
23
|
+
This class is deprecated as of version 0.9.12 and will be removed in 1.1.0.
|
24
|
+
|
25
|
+
Notes
|
26
|
+
-----
|
27
|
+
1. AC pwoer flow is solved with PYPOWER ``runpf`` function.
|
28
|
+
2. AC power flow formulation in AMS style is NOT DONE YET,
|
29
|
+
but this does not affect the results
|
30
|
+
because the data are passed to PYPOWER for solving.
|
31
|
+
"""
|
32
|
+
|
33
|
+
def __init__(self, system, config):
|
34
|
+
DCPF0.__init__(self, system, config)
|
35
|
+
self.info = "AC Power Flow"
|
36
|
+
self.type = "PF"
|
37
|
+
|
38
|
+
self.config.add(OrderedDict((('qlim', 0),
|
39
|
+
)))
|
40
|
+
self.config.add_extra("_help",
|
41
|
+
qlim="Enforce generator q limits",
|
42
|
+
)
|
43
|
+
self.config.add_extra("_alt",
|
44
|
+
qlim=(0, 1, 2),
|
45
|
+
)
|
46
|
+
|
47
|
+
self.qd = RParam(info="reactive power load in system base",
|
48
|
+
name="qd", tex_name=r"q_{d}",
|
49
|
+
unit="p.u.",
|
50
|
+
model="StaticLoad", src="q0",)
|
51
|
+
|
52
|
+
# --- bus ---
|
53
|
+
self.vBus = Var(info="bus voltage magnitude",
|
54
|
+
unit="p.u.",
|
55
|
+
name="vBus", tex_name=r"v_{Bus}",
|
56
|
+
model="Bus", src="v",)
|
57
|
+
# --- gen ---
|
58
|
+
self.qg = Var(info="reactive power generation",
|
59
|
+
unit="p.u.",
|
60
|
+
name="qg", tex_name=r"q_{g}",
|
61
|
+
model="StaticGen", src="q",)
|
62
|
+
# NOTE: omit AC power flow formulation here
|
63
|
+
|
64
|
+
def solve(self, method="newton", **kwargs):
|
65
|
+
"""
|
66
|
+
Solve the AC power flow using PYPOWER.
|
67
|
+
"""
|
68
|
+
ppc = system2ppc(self.system)
|
69
|
+
|
70
|
+
method_map = dict(newton=1, fdxb=2, fdbx=3, gauss=4)
|
71
|
+
alg = method_map.get(method)
|
72
|
+
if alg == 4:
|
73
|
+
msg = "Gauss method is not fully tested yet, not recommended!"
|
74
|
+
logger.warning(msg)
|
75
|
+
if alg is None:
|
76
|
+
msg = f"Invalid method `{method}` for PFlow."
|
77
|
+
raise ValueError(msg)
|
78
|
+
ppopt = ppoption(PF_ALG=alg, ENFORCE_Q_LIMS=self.config.qlim, **kwargs)
|
79
|
+
|
80
|
+
res, sstats = runpf(casedata=ppc, ppopt=ppopt)
|
81
|
+
return res, sstats
|
82
|
+
|
83
|
+
def run(self, **kwargs):
|
84
|
+
"""
|
85
|
+
Run AC power flow using PYPOWER.
|
86
|
+
|
87
|
+
Currently, four methods are supported: 'newton', 'fdxb', 'fdbx', 'gauss',
|
88
|
+
for Newton's method, fast-decoupled, XB, fast-decoupled, BX, and Gauss-Seidel,
|
89
|
+
respectively.
|
90
|
+
|
91
|
+
Note that gauss method is not recommended because it seems to be much
|
92
|
+
more slower than the other three methods and not fully tested yet.
|
93
|
+
|
94
|
+
Examples
|
95
|
+
--------
|
96
|
+
>>> ss = ams.load(ams.get_case('matpower/case14.m'))
|
97
|
+
>>> ss.PFlow.run()
|
98
|
+
|
99
|
+
Parameters
|
100
|
+
----------
|
101
|
+
force_init : bool
|
102
|
+
Force initialization.
|
103
|
+
no_code : bool
|
104
|
+
Disable showing code.
|
105
|
+
method : str
|
106
|
+
Method for solving the power flow.
|
107
|
+
|
108
|
+
Returns
|
109
|
+
-------
|
110
|
+
exit_code : int
|
111
|
+
Exit code of the routine.
|
112
|
+
"""
|
113
|
+
return super().run(**kwargs,)
|