Skip to content

Commit

Permalink
Merge pull request #522 from CURENT/develop
Browse files Browse the repository at this point in the history
Minor version bump.
  • Loading branch information
cuihantao committed Mar 25, 2024
2 parents 3adca81 + 7a87ad5 commit 5ab784b
Show file tree
Hide file tree
Showing 21 changed files with 268 additions and 39 deletions.
8 changes: 4 additions & 4 deletions CONTRIBUTING.rst
Expand Up @@ -13,7 +13,7 @@ Types of Contributions
Report Bugs
~~~~~~~~~~~

Report bugs at https://github.com/cuihantao/andes/issues.
Report bugs at https://github.com/curent/andes/issues.

If you are reporting a bug, please include:

Expand Down Expand Up @@ -42,7 +42,7 @@ or even on the web in blog posts, articles, and such.
Submit Feedback
~~~~~~~~~~~~~~~

The best way to send feedback is to file an issue at https://github.com/cuihantao/andes/issues.
The best way to send feedback is to file an issue at https://github.com/curent/andes/issues.

If you are proposing a feature:

Expand Down Expand Up @@ -97,8 +97,8 @@ Before you submit a pull request, check that it meets these guidelines:
2. If the pull request adds functionality, the docs should be updated. Put
your new functionality into a function with a docstring, and add the
feature to the list in README.rst.
3. The pull request should work for Python 3.6 and up. Check
https://github.com/cuihantao/andes/actions
3. The pull request should work for Python 3.8 and up. Check
https://github.com/curent/andes/actions
and make sure that the tests pass for all supported Python versions.

============
Expand Down
10 changes: 5 additions & 5 deletions andes/io/matpower.py
Expand Up @@ -272,20 +272,20 @@ def mpc2system(mpc: dict, system) -> bool:
if (data[8] == 0.0) or (data[8] == 1.0 and data[9] == 0.0):
# not a transformer
tf = False
ratio = 1
angle = 0
tap_raio = 1
phase_shift = 0
else:
tf = True
ratio = data[8]
angle = data[9] * deg2rad
tap_raio = data[8]
phase_shift = data[9] * deg2rad

vf = system.Bus.Vn.v[system.Bus.idx2uid(fbus)]
vt = system.Bus.Vn.v[system.Bus.idx2uid(tbus)]
system.add('Line', u=status, name=f'Line {fbus:.0f}-{tbus:.0f}',
Vn1=vf, Vn2=vt,
bus1=fbus, bus2=tbus,
r=r, x=x, b=b,
trans=tf, tap=ratio, phi=angle,
trans=tf, tap=tap_raio, phi=phase_shift,
rate_a=rate_a, rate_b=rate_b, rate_c=rate_c)

if ('bus_name' in mpc) and (len(mpc['bus_name']) == len(system.Bus.name.v)):
Expand Down
16 changes: 14 additions & 2 deletions andes/io/psse.py
Expand Up @@ -402,8 +402,16 @@ def _parse_fshunt_v33(raw, system):


def _parse_gen_v33(raw, system, sw):
# 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11, 12, 13, 14, 15, 16,17,18,19
# I,ID,PG,QG,QT,QB,VS,IREG,MBASE,ZR,ZX,RT,XT,GTAP,STAT,RMPCT,PT,PB,O1,F1
"""
Helper function for parsing static generator section.
"""

# 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
# I, ID, PG, QG, QT, QB, VS, IREG, MBASE, ZR, ZX, RT, XT, GTAP, STAT,
# 15, 16, 17, 18, 19, ..., 26, 27
# RMPCT, PT, PB, O1, F1, ..., O4, F4, WMOD, WPF
# The columns above for v33 is different from the manual of v34.5, which includes two new columns:
# `NREG`` at 8 and `BSLOD` before `O1`

mva = system.config.mva
out = defaultdict(list)
Expand All @@ -417,6 +425,7 @@ def _parse_gen_v33(raw, system, sw):
gen_mva = data[8]
gen_idx += 1
status = data[14]
wmod = data[26] if len(data) >= 26 else 0

param = {'Sn': gen_mva, 'Vn': vn, 'u': status,
'bus': bus, 'subidx': subidx,
Expand All @@ -428,6 +437,7 @@ def _parse_gen_v33(raw, system, sw):
'v0': data[6],
'ra': data[9], # ra - armature resistance
'xs': data[10], # xs - synchronous reactance
'wmod': wmod, # generator control mode
}

if data[0] in sw.keys():
Expand All @@ -443,12 +453,14 @@ def _parse_gen_v33(raw, system, sw):

def _parse_line_v33(raw, system):
#
# 0,1, 2,3,4,5, 6, 7, 8, 9,10,11,12,13, 14,15,16
# I,J,CKT,R,X,B,RATEA,RATEB,RATEC,GI,BI,GJ,BJ,ST,LEN,O1,F1,...,O4,F4
#

out = defaultdict(list)
for data in raw['branch']:
param = {
'u': data[13],
'bus1': data[0], 'bus2': data[1],
'r': data[3], 'x': data[4], 'b': data[5],
'rate_a': data[6], 'rate_b': data[7], 'rate_c': data[8],
Expand Down
167 changes: 167 additions & 0 deletions andes/models/line/line.py
Expand Up @@ -3,8 +3,10 @@
"""

import numpy as np

from andes.core import (ModelData, IdxParam, NumParam, DataParam,
Model, ExtAlgeb, ConstService)
from andes.shared import spmatrix


class LineData(ModelData):
Expand Down Expand Up @@ -241,3 +243,168 @@ def get_tf_idx(self):
"""

return np.array(self.idx.v)[self.istf]

def build_y(self):
"""
Build bus admittance matrix. Store the matrix in ``self.Y``.
Returns
-------
Y : spmatrix
Bus admittance matrix.
"""

nb = self.system.Bus.n

y1 = self.u.v * (self.g1.v + self.b1.v * 1j)
y2 = self.u.v * (self.g2.v + self.b2.v * 1j)
y12 = self.u.v / (self.r.v + self.x.v * 1j)
m = self.tap.v * np.exp(1j * self.phi.v)
m2 = self.tap.v**2
mconj = np.conj(m)

# build self and mutual admittances into Y
self.Y = spmatrix((y12 + y1 / m2), self.a1.a, self.a1.a, (nb, nb), 'z')
self.Y -= spmatrix(y12 / mconj, self.a1.a, self.a2.a, (nb, nb), 'z')
self.Y -= spmatrix(y12 / m, self.a2.a, self.a1.a, (nb, nb), 'z')
self.Y += spmatrix(y12 + y2, self.a2.a, self.a2.a, (nb, nb), 'z')

return self.Y

def build_b(self, method='fdpf'):
"""
build Bp and Bpp matrices for fast decoupled power flow and DC power flow.
Results are saved to ``self.Bp`` and ``self.Bpp`` without return.
"""
self.build_Bp(method)
self.build_Bpp(method)

def build_Bp(self, method='fdpf'):
"""
Function for building B' matrix.
The result is saved to ``self.Bp`` and returned
Parameters
----------
method : str
Method for building B' matrix. Choose from 'fdpf', 'fdbx', 'dcpf'.
Returns
-------
Bp : spmatrix
B' matrix.
"""
nb = self.system.Bus.n

if method not in ("fdpf", "fdbx", "dcpf"):
raise ValueError(f"Invalid method {method}; choose from 'fdpf', 'fdbx', 'dcpf'")

# Build B prime matrix -- FDPF
# `y1`` neglects line charging shunt, and g1 is usually 0 in HV lines
# `y2`` neglects line charging shunt, and g2 is usually 0 in HV lines
y1 = self.u.v * self.g1.v
y2 = self.u.v * self.g2.v

# `m` neglected tap ratio
m = np.exp(self.phi.v * 1j)
mconj = np.conj(m)
m2 = np.ones(self.n)

if method in ('fdxb', 'dcpf'):
# neglect line resistance in Bp in XB method
y12 = self.u.v / (self.x.v * 1j)
else:
y12 = self.u.v / (self.r.v + self.x.v * 1j)

self.Bdc = spmatrix((y12 + y1) / m2, self.a1.a, self.a1.a, (nb, nb), 'z')
self.Bdc -= spmatrix(y12 / mconj, self.a1.a, self.a2.a, (nb, nb), 'z')
self.Bdc -= spmatrix(y12 / m, self.a2.a, self.a1.a, (nb, nb), 'z')
self.Bdc += spmatrix(y12 + y2, self.a2.a, self.a2.a, (nb, nb), 'z')
self.Bdc = self.Bdc.imag()

for item in range(nb):
if abs(self.Bdc[item, item]) == 0:
self.Bdc[item, item] = 1e-6 + 0j

return self.Bdc

def build_Bpp(self, method='fdpf'):
"""
Function for building B'' matrix.
The result is saved to ``self.Bpp`` and returned
Parameters
----------
method : str
Method for building B'' matrix. Choose from 'fdpf', 'fdbx', 'dcpf'.
Returns
-------
Bpp : spmatrix
B'' matrix.
"""

nb = self.system.Bus.n

if method not in ("fdpf", "fdbx", "dcpf"):
raise ValueError(f"Invalid method {method}; choose from 'fdpf', 'fdbx', 'dcpf'")

# Build B double prime matrix
# y1 neglected line charging shunt, and g1 is usually 0 in HV lines
# y2 neglected line charging shunt, and g2 is usually 0 in HV lines
# m neglected phase shifter
y1 = self.u.v * (self.g1.v + self.b1.v * 1j)
y2 = self.u.v * (self.g2.v + self.b2.v * 1j)

m = self.tap.v
m2 = abs(m)**2

if method in ('fdbx', 'fdpf', 'dcpf'):
# neglect line resistance in Bpp in BX method
y12 = self.u.v / (self.x.v * 1j)
else:
y12 = self.u.v / (self.r.v + self.x.v * 1j)

self.Bpp = spmatrix((y12 + y1) / m2, self.a1.a, self.a1.a, (nb, nb), 'z')
self.Bpp -= spmatrix(y12 / np.conj(m), self.a1.a, self.a2.a, (nb, nb), 'z')
self.Bpp -= spmatrix(y12 / m, self.a2.a, self.a1.a, (nb, nb), 'z')
self.Bpp += spmatrix(y12 + y2, self.a2.a, self.a2.a, (nb, nb), 'z')
self.Bpp = self.Bpp.imag()

for item in range(nb):
if abs(self.Bpp[item, item]) == 0:
self.Bpp[item, item] = 1e-6 + 0j

return self.Bpp

def build_Bdc(self):
"""
The MATPOWER-flavor Bdc matrix for DC power flow. Saves results to `self.Bdc`.
The method neglects line charging and line resistance. It retains tap ratio.
Returns
-------
Bdc : spmatrix
Bdc matrix.
"""

nb = self.system.Bus.n

y12 = self.u.v / (self.x.v * 1j)
y12 = y12 / self.tap.v

self.Bdc = spmatrix(y12, self.a1.a, self.a1.a, (nb, nb), 'z')
self.Bdc -= spmatrix(y12, self.a1.a, self.a2.a, (nb, nb), 'z')
self.Bdc -= spmatrix(y12, self.a2.a, self.a1.a, (nb, nb), 'z')
self.Bdc += spmatrix(y12, self.a2.a, self.a2.a, (nb, nb), 'z')
self.Bdc = self.Bdc.imag()

for item in range(nb):
if abs(self.Bdc[item, item]) == 0:
self.Bdc[item, item] = 1e-6

return self.Bdc
13 changes: 13 additions & 0 deletions andes/models/static/pv.py
Expand Up @@ -36,6 +36,19 @@ def __init__(self):
self.ra = NumParam(default=0.0, info='armature resistance', tex_name='r_a')
self.xs = NumParam(default=0.3, info='armature reactance', tex_name='x_s')

# `wmod`: generator model included in PSS/E file; not yet used in ANDES
# 0: conventional
# 1: renewable standard QT/ QB limits
# 2: renewable +, - Qlimits based on WPF
# 3: renewable, fixed Qlimit based on WPF
# 4: Infeed machine
self.wmod = NumParam(default=0,
info='Machine ctrl. mode [PSS/E]',
tex_name=r'w_{mod}',
unit='int',
export=False,
)


class PVModel(Model):
"""
Expand Down
10 changes: 6 additions & 4 deletions andes/routines/eig.py
Expand Up @@ -103,16 +103,18 @@ def _reduce(self, fx, fy, gx, gy, Tf, dense=True):
spmatrix
The reduced state matrix
"""
gyx = matrix(gx)
self.solver.linsolve(gy, gyx)
self.gyx = matrix(gx)
self.solver.linsolve(gy, self.gyx)

Tfnz = Tf + np.ones_like(Tf) * np.equal(Tf, 0.0)
iTf = spdiag((1 / Tfnz).tolist())

self.fxy = (fx - fy * self.gyx)

if dense:
return iTf * (fx - fy * gyx)
return iTf * self.fxy
else:
return sparse(iTf * (fx - fy * gyx))
return sparse(iTf * self.fxy)

def _reorder(self):
"""
Expand Down
4 changes: 2 additions & 2 deletions andes/system.py
@@ -1,8 +1,8 @@
"""
System class for power system data and methods
System class for power system data and methods.
"""

# [ANDES] (C)2015-2022 Hantao Cui
# [ANDES] (C)2015-2024 Hantao Cui
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down
2 changes: 1 addition & 1 deletion andes/variables/dae.py
Expand Up @@ -282,7 +282,7 @@ class DAE:
+===========+=============================================+
| m | The number of algebraic variables/equations |
+-----------+---------------------------------------------+
| n | The number of algebraic variables/equations |
| n | The number of state variables/equations |
+-----------+---------------------------------------------+
| o | The number of limiter state flags |
+-----------+---------------------------------------------+
Expand Down
2 changes: 1 addition & 1 deletion docs/source/conf.py
Expand Up @@ -125,7 +125,7 @@

html_context = {
"github_url": "https://github.com",
"github_user": "cuihantao",
"github_user": "curent",
"github_repo": "andes",
"github_version": "master",
"doc_path": "docs/source",
Expand Down
4 changes: 2 additions & 2 deletions docs/source/examples/index.rst
Expand Up @@ -6,9 +6,9 @@ Examples
A collection of examples are presented to supplement the tutorial. The
examples below are identical to the Jupyter Notebook in the ``examples``
folder of the repository
`here <https://github.com/cuihantao/andes/tree/master/examples>`__. You
`here <https://github.com/curent/andes/tree/master/examples>`__. You
can run the examples in a live Jupyter Notebook online using
`Binder <https://mybinder.org/v2/gh/cuihantao/andes/master>`__.
`Binder <https://mybinder.org/v2/gh/curent/andes/master>`__.

.. toctree::
:maxdepth: 2
Expand Down
4 changes: 2 additions & 2 deletions docs/source/getting_started/install.rst
Expand Up @@ -112,15 +112,15 @@ from either your fork or the original repository. Clone the repository with

.. code:: bash
git clone https://github.com/cuihantao/andes
git clone https://github.com/curent/andes
.. note::

Replace the URL with yours to use your fork. With ``git``, you can later easily
update the source code and perform version control.

Alternatively, you can download the ANDES source code from
https://github.com/cuihantao/andes and extract all files to the path of your
https://github.com/curent/andes and extract all files to the path of your
choice. Although works, this method is discouraged because tracking changes and
pushing back code edits will require significant manual efforts.

Expand Down

0 comments on commit 5ab784b

Please sign in to comment.