ltbams 0.9.5__tar.gz → 0.9.6__tar.gz
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.
- {ltbams-0.9.5/ltbams.egg-info → ltbams-0.9.6}/PKG-INFO +1 -1
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/_version.py +3 -3
- ltbams-0.9.6/ams/core/matprocessor.py +518 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/interop/andes.py +81 -15
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/group.py +3 -3
- ltbams-0.9.6/ams/models/line.py +210 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/opt/omodel.py +10 -13
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/routines/pflow.py +1 -2
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/acopf.py +51 -89
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/dcopf.py +66 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/dcpf.py +29 -32
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/pflow.py +3 -11
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/routine.py +54 -34
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/rted.py +27 -16
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/system.py +5 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/release-notes.rst +20 -0
- {ltbams-0.9.5 → ltbams-0.9.6/ltbams.egg-info}/PKG-INFO +1 -1
- {ltbams-0.9.5 → ltbams-0.9.6}/ltbams.egg-info/SOURCES.txt +1 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_andes.py +93 -12
- ltbams-0.9.6/tests/test_mats.py +183 -0
- ltbams-0.9.6/tests/test_routine.py +175 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_service.py +1 -43
- ltbams-0.9.5/ams/core/matprocessor.py +0 -281
- ltbams-0.9.5/ams/models/line.py +0 -41
- ltbams-0.9.5/tests/test_routine.py +0 -95
- {ltbams-0.9.5 → ltbams-0.9.6}/CONTRIBUTING.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/LICENSE +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/MANIFEST.in +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/README.md +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/__main__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/5bus/pjm5bus_demo.xlsx +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/5bus/pjm5bus_uced.json +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/5bus/pjm5bus_uced.xlsx +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/5bus/pjm5bus_uced_esd1.xlsx +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee123/ieee123.xlsx +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee123/ieee123_regcv1.xlsx +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee14/ieee14.json +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee14/ieee14.raw +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee14/ieee14_uced.xlsx +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee39/ieee39.xlsx +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee39/ieee39_uced.xlsx +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee39/ieee39_uced_esd1.xlsx +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee39/ieee39_uced_pvd1.xlsx +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee39/ieee39_uced_vis.xlsx +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/matpower/case118.m +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/matpower/case14.m +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/matpower/case300.m +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/matpower/case39.m +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/matpower/case5.m +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/matpower/case_ACTIVSg2000.m +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/npcc/npcc.m +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/npcc/npcc_uced.xlsx +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/pglib/pglib_opf_case39_epri__api.m +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/wecc/wecc.m +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/wecc/wecc_uced.xlsx +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/cli.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/core/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/core/documenter.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/core/model.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/core/param.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/core/service.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/core/symprocessor.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/core/var.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/interop/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/io/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/io/json.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/io/matpower.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/io/psse.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/io/pypower.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/io/xlsx.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/main.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/area.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/bus.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/cost.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/distributed/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/distributed/esd1.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/distributed/pvd1.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/info.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/region.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/renewable/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/renewable/regc.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/reserve.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/shunt.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/static/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/static/gen.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/static/pq.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/timeslot.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/opt/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/_compat.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/core/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/core/pips.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/core/ppoption.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/core/ppver.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/core/solver.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/eps.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/idx.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/io.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/make/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/make/matrices.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/make/pdv.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/routines/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/routines/cpf.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/routines/cpf_callbacks.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/routines/opf.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/routines/opffcns.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/toggle.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/utils.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/report.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/cpf.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/dopf.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/ed.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/type.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/uc.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/shared.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/utils/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ams/utils/paths.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/Makefile +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/make.bat +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/_templates/autosummary/base.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/_templates/autosummary/class.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/_templates/autosummary/module.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/_templates/autosummary/module_toctree.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/api.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/conf.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/examples/index.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/copyright.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/formats/index.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/formats/matpower.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/formats/psse.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/formats/pypower.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/formats/xlsx.png +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/formats/xlsx.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/index.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/install.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/overview.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/testcase.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/verification.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/images/dcopf_time.png +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/images/sponsors/CURENT_Logo_NameOnTrans.png +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/images/sponsors/CURENT_Logo_Transparent.png +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/images/sponsors/CURENT_Logo_Transparent_Name.png +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/images/sponsors/doe.png +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/index.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/modeling/example.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/modeling/index.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/modeling/model.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/modeling/routine.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/modeling/system.rst +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ltbams.egg-info/dependency_links.txt +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ltbams.egg-info/entry_points.txt +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ltbams.egg-info/requires.txt +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/ltbams.egg-info/top_level.txt +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/requirements-extra.txt +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/requirements.txt +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/setup.cfg +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/setup.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/tests/__init__.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_1st_system.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_addressing.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_case.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_cli.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_dctypes.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_export_csv.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_group.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_known_good.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_model.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_paths.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_report.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_repr.py +0 -0
- {ltbams-0.9.5 → ltbams-0.9.6}/versioneer.py +0 -0
@@ -8,11 +8,11 @@ import json
|
|
8
8
|
|
9
9
|
version_json = '''
|
10
10
|
{
|
11
|
-
"date": "2024-
|
11
|
+
"date": "2024-04-21T17:14:28-0400",
|
12
12
|
"dirty": false,
|
13
13
|
"error": null,
|
14
|
-
"full-revisionid": "
|
15
|
-
"version": "0.9.
|
14
|
+
"full-revisionid": "fcc7e579c8f7453fae3ddebbd0eedbe4e463c1c9",
|
15
|
+
"version": "0.9.6"
|
16
16
|
}
|
17
17
|
''' # END VERSION_JSON
|
18
18
|
|
@@ -0,0 +1,518 @@
|
|
1
|
+
"""
|
2
|
+
Module for system matrix make.
|
3
|
+
"""
|
4
|
+
|
5
|
+
import logging
|
6
|
+
from typing import Optional
|
7
|
+
|
8
|
+
import numpy as np
|
9
|
+
|
10
|
+
from scipy.sparse import csr_matrix as c_sparse
|
11
|
+
from scipy.sparse import csc_matrix as csc_sparse
|
12
|
+
from scipy.sparse import lil_matrix as l_sparse
|
13
|
+
|
14
|
+
from andes.utils.misc import elapsed
|
15
|
+
from andes.thirdparty.npfunc import safe_div
|
16
|
+
|
17
|
+
from ams.opt.omodel import Param
|
18
|
+
|
19
|
+
logger = logging.getLogger(__name__)
|
20
|
+
|
21
|
+
|
22
|
+
class MParam(Param):
|
23
|
+
"""
|
24
|
+
Class for matrix parameters built from the system.
|
25
|
+
|
26
|
+
MParam is designed to be a subclass of RParam for routine parameters
|
27
|
+
management.
|
28
|
+
|
29
|
+
Parameters
|
30
|
+
----------
|
31
|
+
name : str, optional
|
32
|
+
Name of this parameter. If not provided, `name` will be set
|
33
|
+
to the attribute name.
|
34
|
+
tex_name : str, optional
|
35
|
+
LaTeX-formatted parameter name. If not provided, `tex_name`
|
36
|
+
will be assigned the same as `name`.
|
37
|
+
info : str, optional
|
38
|
+
A description of this parameter
|
39
|
+
unit : str, optional
|
40
|
+
Unit of the parameter.
|
41
|
+
v : np.ndarray, optional
|
42
|
+
Matrix value of the parameter.
|
43
|
+
owner : object, optional
|
44
|
+
Owner of the MParam, usually the MatProcessor instance.
|
45
|
+
"""
|
46
|
+
|
47
|
+
def __init__(self,
|
48
|
+
name: Optional[str] = None,
|
49
|
+
tex_name: Optional[str] = None,
|
50
|
+
info: Optional[str] = None,
|
51
|
+
unit: Optional[str] = None,
|
52
|
+
v: Optional[np.ndarray] = None,
|
53
|
+
sparse: Optional[bool] = False,
|
54
|
+
):
|
55
|
+
self.name = name
|
56
|
+
self.tex_name = tex_name if (tex_name is not None) else name
|
57
|
+
self.info = info
|
58
|
+
self.unit = unit
|
59
|
+
self._v = v
|
60
|
+
self.sparse = sparse
|
61
|
+
self.owner = None
|
62
|
+
|
63
|
+
@property
|
64
|
+
def v(self):
|
65
|
+
"""
|
66
|
+
Return the value of the parameter.
|
67
|
+
"""
|
68
|
+
# NOTE: scipy.sparse matrix will return 2D array
|
69
|
+
# so we squeeze it here if only one row
|
70
|
+
if isinstance(self._v, (c_sparse, l_sparse, csc_sparse)):
|
71
|
+
out = self._v.toarray()
|
72
|
+
if out.shape[0] == 1:
|
73
|
+
return np.squeeze(out)
|
74
|
+
else:
|
75
|
+
return out
|
76
|
+
return self._v
|
77
|
+
|
78
|
+
@property
|
79
|
+
def shape(self):
|
80
|
+
"""
|
81
|
+
Return the shape of the parameter.
|
82
|
+
"""
|
83
|
+
return self.v.shape
|
84
|
+
|
85
|
+
@property
|
86
|
+
def n(self):
|
87
|
+
"""
|
88
|
+
Return the szie of the parameter.
|
89
|
+
"""
|
90
|
+
return len(self.v)
|
91
|
+
|
92
|
+
@property
|
93
|
+
def class_name(self):
|
94
|
+
"""
|
95
|
+
Return the class name
|
96
|
+
"""
|
97
|
+
return self.__class__.__name__
|
98
|
+
|
99
|
+
|
100
|
+
class MatProcessor:
|
101
|
+
"""
|
102
|
+
Class for matrix processing in AMS system.
|
103
|
+
"""
|
104
|
+
|
105
|
+
def __init__(self, system):
|
106
|
+
self.system = system
|
107
|
+
self.initialized = False
|
108
|
+
|
109
|
+
self.Cft = MParam(name='Cft', tex_name=r'C_{ft}',
|
110
|
+
info='Line connectivity matrix',
|
111
|
+
v=None, sparse=True)
|
112
|
+
self.CftT = MParam(name='CftT', tex_name=r'C_{ft}^{T}',
|
113
|
+
info='Line connectivity matrix transpose',
|
114
|
+
v=None, sparse=True)
|
115
|
+
self.Cg = MParam(name='Cg', tex_name=r'C_g',
|
116
|
+
info='Generator connectivity matrix',
|
117
|
+
v=None, sparse=True)
|
118
|
+
self.Cl = MParam(name='Cl', tex_name=r'Cl',
|
119
|
+
info='Load connectivity matrix',
|
120
|
+
v=None, sparse=True)
|
121
|
+
self.Csh = MParam(name='Csh', tex_name=r'C_{sh}',
|
122
|
+
info='Shunt connectivity matrix',
|
123
|
+
v=None, sparse=True)
|
124
|
+
|
125
|
+
self.Bbus = MParam(name='Bbus', tex_name=r'B_{bus}',
|
126
|
+
info='Bus admittance matrix',
|
127
|
+
v=None, sparse=True)
|
128
|
+
self.Bf = MParam(name='Bf', tex_name=r'B_{f}',
|
129
|
+
info='Bf matrix',
|
130
|
+
v=None, sparse=True)
|
131
|
+
self.Pbusinj = MParam(name='Pbusinj', tex_name=r'P_{bus}^{inj}',
|
132
|
+
info='Bus power injection vector',
|
133
|
+
v=None,)
|
134
|
+
self.Pfinj = MParam(name='Pfinj', tex_name=r'P_{f}^{inj}',
|
135
|
+
info='Line power injection vector',
|
136
|
+
v=None,)
|
137
|
+
|
138
|
+
self.PTDF = MParam(name='PTDF', tex_name=r'P_{TDF}',
|
139
|
+
info='Power transfer distribution factor',
|
140
|
+
v=None)
|
141
|
+
self.LODF = MParam(name='LODF', tex_name=r'O_{TDF}',
|
142
|
+
info='Line outage distribution factor',
|
143
|
+
v=None)
|
144
|
+
|
145
|
+
def build(self):
|
146
|
+
"""
|
147
|
+
Build the system matrices.
|
148
|
+
It build connectivity matrices first: Cg, Cl, Csh, Cft, and CftT.
|
149
|
+
Then build bus matrices: Bf, Bbus, Pfinj, and Pbusinj.
|
150
|
+
|
151
|
+
Returns
|
152
|
+
-------
|
153
|
+
initialized : bool
|
154
|
+
True if the matrices are built successfully.
|
155
|
+
"""
|
156
|
+
t_mat, _ = elapsed()
|
157
|
+
|
158
|
+
# --- connectivity matrices ---
|
159
|
+
_ = self.build_cg()
|
160
|
+
_ = self.build_cl()
|
161
|
+
_ = self.build_csh()
|
162
|
+
_ = self.build_cft()
|
163
|
+
|
164
|
+
# --- bus matrices ---
|
165
|
+
_ = self.build_bf()
|
166
|
+
_ = self.build_bbus()
|
167
|
+
_ = self.build_pfinj()
|
168
|
+
_ = self.build_pbusinj()
|
169
|
+
_, s_mat = elapsed(t_mat)
|
170
|
+
|
171
|
+
logger.debug(f"Built system matrices in {s_mat}.")
|
172
|
+
self.initialized = True
|
173
|
+
return self.initialized
|
174
|
+
|
175
|
+
@property
|
176
|
+
def class_name(self):
|
177
|
+
"""
|
178
|
+
Return the class name
|
179
|
+
"""
|
180
|
+
return self.__class__.__name__
|
181
|
+
|
182
|
+
@property
|
183
|
+
def n(self):
|
184
|
+
"""
|
185
|
+
To fit the RParam style.
|
186
|
+
"""
|
187
|
+
return 2
|
188
|
+
|
189
|
+
def build_cg(self):
|
190
|
+
"""
|
191
|
+
Build generator connectivity matrix Cg, and store it in the MParam `Cg`.
|
192
|
+
|
193
|
+
Returns
|
194
|
+
-------
|
195
|
+
Cg : scipy.sparse.csr_matrix
|
196
|
+
Generator connectivity matrix.
|
197
|
+
"""
|
198
|
+
system = self.system
|
199
|
+
|
200
|
+
# common variables
|
201
|
+
nb = system.Bus.n
|
202
|
+
ng = system.StaticGen.n
|
203
|
+
|
204
|
+
# bus indices: idx -> uid
|
205
|
+
idx_gen = system.StaticGen.get_idx()
|
206
|
+
u_gen = system.StaticGen.get(src='u', attr='v', idx=idx_gen)
|
207
|
+
on_gen = np.flatnonzero(u_gen) # uid of online generators
|
208
|
+
on_gen_idx = [idx_gen[i] for i in on_gen] # idx of online generators
|
209
|
+
on_gen_bus = system.StaticGen.get(src='bus', attr='v', idx=on_gen_idx)
|
210
|
+
|
211
|
+
row = np.array([system.Bus.idx2uid(x) for x in on_gen_bus])
|
212
|
+
col = np.array([idx_gen.index(x) for x in on_gen_idx])
|
213
|
+
self.Cg._v = c_sparse((np.ones(len(on_gen_idx)), (row, col)), (nb, ng))
|
214
|
+
return self.Cg._v
|
215
|
+
|
216
|
+
def build_cl(self):
|
217
|
+
"""
|
218
|
+
Build load connectivity matrix Cl, and store it in the MParam `Cl`.
|
219
|
+
|
220
|
+
Returns
|
221
|
+
-------
|
222
|
+
Cl : scipy.sparse.csr_matrix
|
223
|
+
Load connectivity matrix.
|
224
|
+
"""
|
225
|
+
system = self.system
|
226
|
+
|
227
|
+
# common variables
|
228
|
+
nb = system.Bus.n
|
229
|
+
npq = system.PQ.n
|
230
|
+
|
231
|
+
# load indices: idx -> uid
|
232
|
+
idx_load = system.PQ.idx.v
|
233
|
+
u_load = system.PQ.get(src='u', attr='v', idx=idx_load)
|
234
|
+
on_load = np.flatnonzero(u_load)
|
235
|
+
on_load_idx = [idx_load[i] for i in on_load]
|
236
|
+
on_load_bus = system.PQ.get(src='bus', attr='v', idx=on_load_idx)
|
237
|
+
|
238
|
+
row = np.array([system.Bus.idx2uid(x) for x in on_load_bus])
|
239
|
+
col = np.array([system.PQ.idx2uid(x) for x in on_load_idx])
|
240
|
+
self.Cl._v = c_sparse((np.ones(len(on_load_idx)), (row, col)), (nb, npq))
|
241
|
+
return self.Cl._v
|
242
|
+
|
243
|
+
def build_csh(self):
|
244
|
+
"""
|
245
|
+
Build shunt connectivity matrix Csh, and store it in the MParam `Csh`.
|
246
|
+
|
247
|
+
Returns
|
248
|
+
-------
|
249
|
+
Csh : spmatrix
|
250
|
+
Shunt connectivity matrix.
|
251
|
+
"""
|
252
|
+
system = self.system
|
253
|
+
|
254
|
+
# common variables
|
255
|
+
nb = system.Bus.n
|
256
|
+
nsh = system.Shunt.n
|
257
|
+
|
258
|
+
# shunt indices: idx -> uid
|
259
|
+
idx_shunt = system.Shunt.idx.v
|
260
|
+
u_shunt = system.Shunt.get(src='u', attr='v', idx=idx_shunt)
|
261
|
+
on_shunt = np.flatnonzero(u_shunt)
|
262
|
+
on_shunt_idx = [idx_shunt[i] for i in on_shunt]
|
263
|
+
on_shunt_bus = system.Shunt.get(src='bus', attr='v', idx=on_shunt_idx)
|
264
|
+
|
265
|
+
row = np.array([system.Bus.idx2uid(x) for x in on_shunt_bus])
|
266
|
+
col = np.array([system.Shunt.idx2uid(x) for x in on_shunt_idx])
|
267
|
+
self.Csh._v = c_sparse((np.ones(len(on_shunt_idx)), (row, col)), (nb, nsh))
|
268
|
+
return self.Csh._v
|
269
|
+
|
270
|
+
def build_cft(self):
|
271
|
+
"""
|
272
|
+
Build line connectivity matrix Cft and its transpose CftT.
|
273
|
+
The Cft and CftT are stored in the MParam `Cft` and `CftT`, respectively.
|
274
|
+
|
275
|
+
Returns
|
276
|
+
-------
|
277
|
+
Cft : scipy.sparse.csr_matrix
|
278
|
+
Line connectivity matrix.
|
279
|
+
"""
|
280
|
+
system = self.system
|
281
|
+
|
282
|
+
# common variables
|
283
|
+
nb = system.Bus.n
|
284
|
+
nl = system.Line.n
|
285
|
+
|
286
|
+
# line indices: idx -> uid
|
287
|
+
idx_line = system.Line.idx.v
|
288
|
+
u_line = system.Line.get(src='u', attr='v', idx=idx_line)
|
289
|
+
on_line = np.flatnonzero(u_line)
|
290
|
+
on_line_idx = [idx_line[i] for i in on_line]
|
291
|
+
on_line_bus1 = system.Line.get(src='bus1', attr='v', idx=on_line_idx)
|
292
|
+
on_line_bus2 = system.Line.get(src='bus2', attr='v', idx=on_line_idx)
|
293
|
+
|
294
|
+
data_line = np.ones(2*len(on_line_idx))
|
295
|
+
data_line[len(on_line_idx):] = -1
|
296
|
+
row_line = np.array([system.Bus.idx2uid(x) for x in on_line_bus1 + on_line_bus2])
|
297
|
+
col_line = np.array([system.Line.idx2uid(x) for x in on_line_idx + on_line_idx])
|
298
|
+
self.Cft._v = c_sparse((data_line, (row_line, col_line)), (nb, nl))
|
299
|
+
self.CftT._v = self.Cft._v.T
|
300
|
+
return self.Cft._v
|
301
|
+
|
302
|
+
def build_bf(self):
|
303
|
+
"""
|
304
|
+
Build DC Bf matrix and store it in the MParam `Bf`.
|
305
|
+
|
306
|
+
Returns
|
307
|
+
-------
|
308
|
+
Bf : scipy.sparse.csr_matrix
|
309
|
+
Bf matrix.
|
310
|
+
"""
|
311
|
+
system = self.system
|
312
|
+
|
313
|
+
# common variables
|
314
|
+
nb = system.Bus.n
|
315
|
+
nl = system.Line.n
|
316
|
+
|
317
|
+
# line parameters
|
318
|
+
idx_line = system.Line.idx.v
|
319
|
+
b = self._calc_b()
|
320
|
+
|
321
|
+
# build Bf such that Bf * Va is the vector of real branch powers injected
|
322
|
+
# at each branch's "from" bus
|
323
|
+
f = system.Bus.idx2uid(system.Line.get(src='bus1', attr='v', idx=idx_line))
|
324
|
+
t = system.Bus.idx2uid(system.Line.get(src='bus2', attr='v', idx=idx_line))
|
325
|
+
ir = np.r_[range(nl), range(nl)] # double set of row indices
|
326
|
+
self.Bf._v = c_sparse((np.r_[b, -b], (ir, np.r_[f, t])), (nl, nb))
|
327
|
+
return self.Bf._v
|
328
|
+
|
329
|
+
def build_bbus(self):
|
330
|
+
"""
|
331
|
+
Build Bdc matrix and store it in the MParam `Bbus`.
|
332
|
+
|
333
|
+
Returns
|
334
|
+
-------
|
335
|
+
Bdc : scipy.sparse.csr_matrix
|
336
|
+
DC bus admittance matrix.
|
337
|
+
"""
|
338
|
+
self.Bbus._v = self.Cft._v * self.Bf._v
|
339
|
+
return self.Bbus._v
|
340
|
+
|
341
|
+
def build_pfinj(self):
|
342
|
+
"""
|
343
|
+
Build DC Pfinj vector and store it in the MParam `Pfinj`.
|
344
|
+
|
345
|
+
Returns
|
346
|
+
-------
|
347
|
+
Pfinj : np.ndarray
|
348
|
+
Line power injection vector.
|
349
|
+
"""
|
350
|
+
idx_line = self.system.Line.idx.v
|
351
|
+
b = self._calc_b()
|
352
|
+
phi = self.system.Line.get(src='phi', attr='v', idx=idx_line)
|
353
|
+
self.Pfinj._v = b * (-phi)
|
354
|
+
return self.Pfinj._v
|
355
|
+
|
356
|
+
def build_pbusinj(self):
|
357
|
+
"""
|
358
|
+
Build DC Pbusinj vector and store it in the MParam `Pbusinj`.
|
359
|
+
|
360
|
+
Returns
|
361
|
+
-------
|
362
|
+
Pbusinj : np.ndarray
|
363
|
+
Bus power injection vector.
|
364
|
+
"""
|
365
|
+
self.Pbusinj._v = self.Cft._v * self.Pfinj._v
|
366
|
+
return self.Pbusinj._v
|
367
|
+
|
368
|
+
def _calc_b(self):
|
369
|
+
"""
|
370
|
+
Calculate DC series susceptance for each line.
|
371
|
+
|
372
|
+
Returns
|
373
|
+
-------
|
374
|
+
b : np.ndarray
|
375
|
+
Series susceptance for each line.
|
376
|
+
"""
|
377
|
+
system = self.system
|
378
|
+
nl = system.Line.n
|
379
|
+
|
380
|
+
# line parameters
|
381
|
+
idx_line = system.Line.idx.v
|
382
|
+
x = system.Line.get(src='x', attr='v', idx=idx_line)
|
383
|
+
u_line = system.Line.get(src='u', attr='v', idx=idx_line)
|
384
|
+
b = u_line / x # series susceptance
|
385
|
+
|
386
|
+
# in DC, tap is assumed to be 1
|
387
|
+
tap0 = system.Line.get(src='tap', attr='v', idx=idx_line)
|
388
|
+
tap = np.ones(nl)
|
389
|
+
i = np.flatnonzero(tap0)
|
390
|
+
tap[i] = tap0[i] # assign non-zero tap ratios
|
391
|
+
b = b / tap # adjusted series susceptance
|
392
|
+
|
393
|
+
return b
|
394
|
+
|
395
|
+
def build_ptdf(self):
|
396
|
+
"""
|
397
|
+
Build the DC PTDF matrix and store it in the MParam `PTDF`.
|
398
|
+
|
399
|
+
`PTDF[m, n]` means the increased line flow on line `m` when there is
|
400
|
+
1 p.u. power injection at bus `n`.
|
401
|
+
|
402
|
+
It requires DC Bbus and Bf.
|
403
|
+
|
404
|
+
Note that there is discrepency between the PTDF-based line flow and
|
405
|
+
DCOPF calcualted line flow. The gap is ignorable for small cases.
|
406
|
+
|
407
|
+
Returns
|
408
|
+
-------
|
409
|
+
PTDF : np.ndarray
|
410
|
+
Power transfer distribution factor.
|
411
|
+
"""
|
412
|
+
system = self.system
|
413
|
+
|
414
|
+
# common variables
|
415
|
+
nb = system.Bus.n
|
416
|
+
nl = system.Line.n
|
417
|
+
|
418
|
+
# use first slack bus as reference slack bus
|
419
|
+
slack = system.Slack.bus.v[0]
|
420
|
+
|
421
|
+
# use first bus for voltage angle reference
|
422
|
+
noref_idx = system.Bus.idx.v[1:]
|
423
|
+
noref = system.Bus.idx2uid(noref_idx)
|
424
|
+
|
425
|
+
noslack = [system.Bus.idx2uid(bus) for bus in system.Bus.idx.v if bus != slack]
|
426
|
+
|
427
|
+
# build other matrices if not built
|
428
|
+
if not self.initialized:
|
429
|
+
logger.debug("System matrices are not built. Building now.")
|
430
|
+
self.build()
|
431
|
+
# use dense representation
|
432
|
+
Bbus, Bf = self.Bbus.v, self.Bf.v
|
433
|
+
|
434
|
+
# initialize PTDF matrix
|
435
|
+
H = np.zeros((nl, nb))
|
436
|
+
# calculate PTDF
|
437
|
+
H[:, noslack] = np.linalg.solve(Bbus[np.ix_(noslack, noref)].T, Bf[:, noref].T).T
|
438
|
+
# store PTDF
|
439
|
+
self.PTDF._v = H
|
440
|
+
|
441
|
+
return self.PTDF._v
|
442
|
+
|
443
|
+
def build_lodf(self):
|
444
|
+
"""
|
445
|
+
Build the DC LODF matrix and store it in the MParam `LODF`.
|
446
|
+
|
447
|
+
`LODF[m, n]` means the increased line flow on line `m` when there is
|
448
|
+
1 p.u. line flow decrease on line `n` due to line `n` outage.
|
449
|
+
|
450
|
+
It requires DC PTDF and Cft.
|
451
|
+
|
452
|
+
Returns
|
453
|
+
-------
|
454
|
+
LODF : np.ndarray
|
455
|
+
Line outage distribution factor.
|
456
|
+
"""
|
457
|
+
system = self.system
|
458
|
+
|
459
|
+
# common variables
|
460
|
+
nl = system.Line.n
|
461
|
+
|
462
|
+
# build PTDF if not built
|
463
|
+
if self.PTDF._v is None:
|
464
|
+
self.build_ptdf()
|
465
|
+
|
466
|
+
H = self.PTDF._v * self.Cft._v
|
467
|
+
h = np.diag(H, 0)
|
468
|
+
LODF = safe_div(H, np.ones((nl, nl)) - np.ones((nl, 1)) * h.T)
|
469
|
+
LODF = LODF - np.diag(np.diag(LODF)) - np.eye(nl, nl)
|
470
|
+
|
471
|
+
self.LODF._v = LODF
|
472
|
+
return self.LODF._v
|
473
|
+
|
474
|
+
def build_otdf(self, line=None):
|
475
|
+
"""
|
476
|
+
Build the DC OTDF matrix.
|
477
|
+
|
478
|
+
`OTDF_k[m, n]` means the PTDF[m, n] with line `k` outage.
|
479
|
+
|
480
|
+
It requires ... ...
|
481
|
+
|
482
|
+
Parameters
|
483
|
+
----------
|
484
|
+
line : int, str, optional
|
485
|
+
Outage line idx to build the OTDF. If not provided, use the
|
486
|
+
first line `System.Line.idx.v[0]`.
|
487
|
+
|
488
|
+
Returns
|
489
|
+
-------
|
490
|
+
OTDF : np.ndarray
|
491
|
+
Line outage distribution factor.
|
492
|
+
"""
|
493
|
+
system = self.system
|
494
|
+
|
495
|
+
if line is None:
|
496
|
+
line = system.Line.idx.v[0]
|
497
|
+
elif isinstance(line, list):
|
498
|
+
logger.warning("Multiple line is given, only the first one is used.")
|
499
|
+
line = line[0]
|
500
|
+
line_uid = system.Line.idx2uid(line)
|
501
|
+
|
502
|
+
# build LODF if not built
|
503
|
+
if self.LODF._v is None:
|
504
|
+
self.build_lodf()
|
505
|
+
|
506
|
+
# common variables
|
507
|
+
nb = system.Bus.n
|
508
|
+
nl = system.Line.n
|
509
|
+
|
510
|
+
# initialize OTDF matrix
|
511
|
+
OTDF = np.zeros((nl, nb))
|
512
|
+
|
513
|
+
line_lodf = self.LODF._v[:, line_uid] # LODF for the outage line
|
514
|
+
line_ptdf = self.PTDF._v[line_uid, :] # PTDF for the outage line
|
515
|
+
OTDF += self.PTDF._v # Add PTDF to OTDF
|
516
|
+
OTDF += line_lodf[:, np.newaxis] * line_ptdf # Add LODF * PTDF for the outage line
|
517
|
+
|
518
|
+
return OTDF
|