Skip to content

Commit

Permalink
Merge pull request #83 from CURENT/develop
Browse files Browse the repository at this point in the history
Prep for v0.9.7
  • Loading branch information
jinningwang authored May 24, 2024
2 parents fcc7e57 + 783f8c7 commit bc97bef
Show file tree
Hide file tree
Showing 55 changed files with 1,029 additions and 364 deletions.
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
AMS: Python Software for Dispatch Modeling and Co-Simulation with Dynanic
AMS: Python Software for Scheduling Modeling and Co-Simulation with Dynanic

Copyright (c) 2023-2024 Jinning Wang

Expand Down Expand Up @@ -649,7 +649,7 @@ to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

AMS, a python software for dispatch modeling and co-simulation with dynanic
AMS, a python software for scheduling modeling and co-simulation with dynanic
Copyright (C) 2023 Jinning Wang

This program is free software: you can redistribute it and/or modify
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# LTB AMS

Python Software for Power System Dispatch Modeling and Co-Simulation with Dynanic, serving as the market simulator for the [CURENT Largescale Testbed][LTB Repository].
Python Software for Power System Scheduling Modeling and Co-Simulation with Dynanic, serving as the market simulator for the [CURENT Largescale Testbed][LTB Repository].

[![License: GPL-3.0](https://img.shields.io/badge/License-GPL--3.0-blue.svg)](https://github.com/CURENT/ams/blob/master/LICENSE)
![platforms](https://anaconda.org/conda-forge/ltbams/badges/platforms.svg)
Expand Down Expand Up @@ -31,7 +31,7 @@ Python Software for Power System Dispatch Modeling and Co-Simulation with Dynani

With the built-in interface with dynamic simulation engine, ANDES, AMS enables Dynamics Interfaced Stability Constrained Production Cost and Market Operation Modeling.

AMS produces credible dispatch results and competitive performance.
AMS produces credible scheduling results and competitive performance.
The following results show the comparison of DCOPF between AMS and other tools.

| Cost [\$] | AMS | MATPOWER | pandapower |
Expand Down Expand Up @@ -79,7 +79,7 @@ pip install git+https://github.com/CURENT/ams.git
```

# Sponsors and Contributors
AMS is the dispatch simulation engine for the CURENT Largescale Testbed (LTB).
AMS is the scheduling simulation engine for the CURENT Largescale Testbed (LTB).
More information about CURENT LTB can be found at the [LTB Repository][LTB Repository].

This work was supported in part by the Engineering Research Center Program of the National Science Foundation and the Department of Energy
Expand Down
3 changes: 2 additions & 1 deletion ams/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
from ams import opt # NOQA
from ams import pypower # NOQA
from ams import report # NOQA
from ams import extension # NOQA

from ams.main import config_logger, load, run # NOQA
from ams.utils.paths import get_case # NOQA
from ams.shared import ppc2df # NOQA

__author__ = 'Jining Wang'

__all__ = ['io', 'utils', 'models', 'system']
__all__ = ['io', 'utils', 'models', 'system', 'extension']
Binary file added ams/cases/5bus/pjm5bus_uced_ev.xlsx
Binary file not shown.
117 changes: 69 additions & 48 deletions ams/core/matprocessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ def _calc_b(self):

return b

def build_ptdf(self):
def build_ptdf(self, dtype='float64', no_store=False):
"""
Build the DC PTDF matrix and store it in the MParam `PTDF`.
Expand All @@ -404,17 +404,22 @@ def build_ptdf(self):
Note that there is discrepency between the PTDF-based line flow and
DCOPF calcualted line flow. The gap is ignorable for small cases.
Try to use 'float32' for dtype if memory is a concern.
Parameters
----------
dtype : str, optional
Data type of the PTDF matrix. Default is 'float64'.
no_store : bool, optional
If True, the PTDF will not be stored into `MatProcessor.PTDF._v`.
Returns
-------
PTDF : np.ndarray
Power transfer distribution factor.
"""
system = self.system

# common variables
nb = system.Bus.n
nl = system.Line.n

# use first slack bus as reference slack bus
slack = system.Slack.bus.v[0]

Expand All @@ -428,19 +433,22 @@ def build_ptdf(self):
if not self.initialized:
logger.debug("System matrices are not built. Building now.")
self.build()

# use dense representation
Bbus, Bf = self.Bbus.v, self.Bf.v
Bbus = self.Bbus._v.todense().astype(dtype)
Bf = self.Bf._v.todense().astype(dtype)

# initialize PTDF matrix
H = np.zeros((nl, nb))
H = np.zeros((system.Line.n, system.Bus.n), dtype=dtype)
# calculate PTDF
H[:, noslack] = np.linalg.solve(Bbus[np.ix_(noslack, noref)].T, Bf[:, noref].T).T
# store PTDF
self.PTDF._v = H

return self.PTDF._v
if not no_store:
self.PTDF._v = H

return H

def build_lodf(self):
def build_lodf(self, dtype='float64', no_store=False):
"""
Build the DC LODF matrix and store it in the MParam `LODF`.
Expand All @@ -449,70 +457,83 @@ def build_lodf(self):
It requires DC PTDF and Cft.
Try to use 'float32' for dtype if memory is a concern.
Parameters
----------
dtype : str, optional
Data type of the LODF matrix. Default is 'float64'.
no_store : bool, optional
If True, the LODF will not be stored into `MatProcessor.LODF._v`.
Returns
-------
LODF : np.ndarray
Line outage distribution factor.
"""
system = self.system

# common variables
nl = system.Line.n
nl = self.system.Line.n

# build PTDF if not built
if self.PTDF._v is None:
self.build_ptdf()
ptdf = self.build_ptdf(dtype=dtype, no_store=True)
else:
ptdf = self.PTDF._v

H = self.PTDF._v * self.Cft._v
H = ptdf * self.Cft._v
h = np.diag(H, 0)
LODF = safe_div(H, np.ones((nl, nl)) - np.ones((nl, 1)) * h.T)
LODF = LODF - np.diag(np.diag(LODF)) - np.eye(nl, nl)

self.LODF._v = LODF
return self.LODF._v
if not no_store:
self.LODF._v = LODF.astype(dtype)
return LODF.astype(dtype)

def build_otdf(self, line=None):
def build_otdf(self, line=None, dtype='float64'):
"""
Build the DC OTDF matrix.
Build the DC OTDF matrix for line outage:
:math:`OTDF_k = PTDF + LODF[:, k] @ PTDF[k, ]`,
where k is the outage line locations.
`OTDF_k[m, n]` means the PTDF[m, n] with line `k` outage.
OTDF_k[m, n] means the increased line flow on line `m` when there is
1 p.u. line flow decrease on line `k` due to line `k` outage.
It requires ... ...
Note that the OTDF is not stored in the MatProcessor.
Try to use 'float32' for dtype if memory is a concern.
Parameters
----------
line : int, str, optional
Outage line idx to build the OTDF. If not provided, use the
first line `System.Line.idx.v[0]`.
line : int, str, list, optional
Lines index for which the OTDF is calculated. It takes both single
or multiple line indices.
If not given, the first line is used by default.
dtype : str, optional
Data type of the OTDF matrix. Default is 'float64'.
Returns
-------
OTDF : np.ndarray
Line outage distribution factor.
"""
system = self.system

if line is None:
line = system.Line.idx.v[0]
elif isinstance(line, list):
logger.warning("Multiple line is given, only the first one is used.")
line = line[0]
line_uid = system.Line.idx2uid(line)
if self.PTDF._v is None:
ptdf = self.build_ptdf(dtype=dtype, no_store=True)
else:
ptdf = self.PTDF._v

# build LODF if not built
if self.LODF._v is None:
self.build_lodf()
lodf = self.build_lodf(dtype=dtype, no_store=True)
else:
lodf = self.LODF._v

# common variables
nb = system.Bus.n
nl = system.Line.n

# initialize OTDF matrix
OTDF = np.zeros((nl, nb))

line_lodf = self.LODF._v[:, line_uid] # LODF for the outage line
line_ptdf = self.PTDF._v[line_uid, :] # PTDF for the outage line
OTDF += self.PTDF._v # Add PTDF to OTDF
OTDF += line_lodf[:, np.newaxis] * line_ptdf # Add LODF * PTDF for the outage line
if line is None:
luid = [0]
elif isinstance(line, (int, str)):
try:
luid = [self.system.Line.idx2uid(line)]
except ValueError:
raise ValueError(f"Line {line} not found.")
elif isinstance(line, list):
luid = self.system.Line.idx2uid(line)

return OTDF
otdf = ptdf + lodf[:, luid] @ ptdf[luid, :]
return otdf.astype(dtype)
2 changes: 1 addition & 1 deletion ams/core/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

class Model:
"""
Base class for power system dispatch models.
Base class for power system scheduling models.
This class is revised from ``andes.core.model.Model``.
"""
Expand Down
2 changes: 1 addition & 1 deletion ams/core/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ def v(self):
n_gen = self.u.n
n_ts = self.u.horizon.n
tout = np.zeros((n_gen, n_ts))
t = self.rtn.config.t # dispatch interval
t = self.rtn.config.t # scheduling interval

# minimum online/offline duration
td = np.ceil(self.u2.v/t).astype(int)
Expand Down
Loading

0 comments on commit bc97bef

Please sign in to comment.