diff --git a/.codecov.yml b/.codecov.yml index 7a83f416..6a437d86 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -12,8 +12,6 @@ cli: pycoverage: report_type: "xml" -codecov: - token: 5fc2d41f-bcba-455d-a843-f85beb76d28f ignore: - "ams/_version.py" - "ams/pypower/**" \ No newline at end of file diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml new file mode 100644 index 00000000..1dacf30f --- /dev/null +++ b/.github/workflows/codecov.yml @@ -0,0 +1,50 @@ +name: Code coverage + +on: [push, pull_request] + +jobs: + build: + name: Report coverage + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: conda-incubator/setup-miniconda@v3 + with: + python-version: 3.11 + mamba-version: "*" + miniforge-version: "latest" + channels: conda-forge,defaults + channel-priority: true + activate-environment: anaconda-client-env + - shell: bash -el {0} + name: Install dependencies + run: | + mamba install -y nbmake pytest-xdist line_profiler # add'l packages for notebook tests. + mamba install --file requirements.txt --file requirements-extra.txt + python -m pip install -e . + - shell: bash -el {0} + name: Test with pytest and collect coverage + run: | + pytest --cov=./ --cov-report=xml + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + - name: Check secret presence + id: check_secret + run: | + echo "is_set=false" >> $GITHUB_OUTPUT + if [ ! -z "${{ secrets.CODACY_PROJECT_TOKEN }}" ]; then + echo "is_set=true" >> $GITHUB_OUTPUT + fi + + - name: Upload coverage to Codacy + if: steps.check_secret.outputs.is_set == 'true' + uses: codacy/codacy-coverage-reporter-action@v1.3.0 + with: + project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} + coverage-reports: coverage.xml + env: + CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml index a46c9a51..db207c14 100644 --- a/.github/workflows/pythonapp.yml +++ b/.github/workflows/pythonapp.yml @@ -38,19 +38,6 @@ jobs: name: Test notebooks. run: | pytest --nbmake examples --ignore=examples/demonstration - - shell: bash -el {0} - name: Test with pytest and collect coverage - run: | - pytest --cov=./ --cov-report=xml - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - - name: Upload coverage to Codacy - run: | - bash <(curl -Ls https://coverage.codacy.com/get.sh) report -r coverage.xml - env: - CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }} - name: Build a distribution if tagged if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') && matrix.os == 'ubuntu-latest' && matrix.python-version == '3.9' run: | diff --git a/.gitignore b/.gitignore index 3efdd590..34fef577 100644 --- a/.gitignore +++ b/.gitignore @@ -38,4 +38,8 @@ icebar ~$*.xlsx # conda -.conda/* \ No newline at end of file +.conda/* + +# coverage +.coverage +coverage.xml \ No newline at end of file diff --git a/README.md b/README.md index 41fe8672..74597430 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Python Software for Power System Dispatch Modeling and Co-Simulation with Dynani |---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Downloads | [![PyPI Version](https://img.shields.io/pypi/v/ltbams.svg)](https://pypi.python.org/pypi/ltbams) | Try on Binder | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/curent/ams/master) | | -| Code Quality |[![Codacy Badge](https://app.codacy.com/project/badge/Grade/69456da1b8634f2f984bd769e35f0050)](https://app.codacy.com/gh/CURENT/ams/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)| [![codecov](https://codecov.io/gh/CURENT/ams/graph/badge.svg?token=RZI5GLLBQH)](https://codecov.io/gh/CURENT/ams) | +| Code Quality |[![Codacy Badge](https://app.codacy.com/project/badge/Grade/69456da1b8634f2f984bd769e35f0050)](https://app.codacy.com/gh/CURENT/ams/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)| [![Codacy Badge](https://app.codacy.com/project/badge/Coverage/69456da1b8634f2f984bd769e35f0050)](https://app.codacy.com/gh/CURENT/ams/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_coverage) | | Build Status | [![GitHub Action Status](https://github.com/CURENT/ams/workflows/Python%20application/badge.svg)](https://github.com/curent/ams/actions) | | Structure | [![Structure](https://img.shields.io/badge/code_base-visualize-blue)](https://mango-dune-07a8b7110.1.azurestaticapps.net/?repo=CURENT%2Fams) @@ -48,6 +48,14 @@ Use the following resources to get involved. - Try in Jupyter Notebook on [Binder][Binder] +# Installation + +AMS is released as ``ltbams`` on PyPI. To install the latest release, use pip as follows: + +```bash +pip install ltbams +``` + # Sponsors and Contributors AMS is the dispatch simulation engine for the CURENT Largescale Testbed (LTB). More information about CURENT LTB can be found at the [LTB Repository][LTB Repository]. @@ -63,12 +71,9 @@ See [GitHub contributors][GitHub contributors] for the contributor list. AMS is licensed under the [GPL v3 License](./LICENSE). # Related Projects -- [CVXPY](https://github.com/cvxpy/cvxpy) -- [Visualizations of Mittelmann benchmarks](https://mattmilten.github.io/mittelmann-plots/) -- [CBC Solver](https://github.com/coin-or/Cbc) -- [MATPOWER](https://github.com/MATPOWER/matpower) -- [PYPOWER](https://github.com/rwl/PYPOWER) -- [pandapower](https://github.com/e2nIEE/pandapower) +- [Popular Open Source Libraries for Power System Analysis](https://github.com/jinningwang/best-of-ps) +- [G-PST Tools Portal](https://g-pst.github.io/tools/): An open tools portal with a classification approach +- [Open Source Software (OSS) for Electricity Market Research, Teaching, and Training](https://www2.econ.iastate.edu/tesfatsi/ElectricOSS.htm) Some commercial solvers provide academic licenses, such as COPT, GUROBI, CPLEX, and MOSEK. diff --git a/ams/interop/andes.py b/ams/interop/andes.py index f1af05c9..778b18bb 100644 --- a/ams/interop/andes.py +++ b/ams/interop/andes.py @@ -96,9 +96,9 @@ def to_andes(system, setup=False, addfile=None, -------- >>> import ams >>> import andes - >>> sp = ams.load(ams.get_case('ieee14/ieee14_rted.xlsx'), setup=True) + >>> sp = ams.load(ams.get_case('ieee14/ieee14_uced.xlsx'), setup=True) >>> sa = sp.to_andes(setup=False, - ... addfile=andes.get_case('ieee14/ieee14_wt3.xlsx'), + ... addfile=andes.get_case('ieee14/ieee14_full.xlsx'), ... overwrite=True, no_output=True) Notes @@ -279,9 +279,10 @@ def parse_addfile(adsys, amsys, addfile): # add dynamic models for name, df in df_models.items(): # drop rows that all nan + df.replace(['', ' '], np.NaN, inplace=True) # replace empty string with nan df.dropna(axis=0, how='all', inplace=True) # if the dynamic model also exists in AMS, use AMS parameters for overlap - if name in amsys.models.keys(): + if (name in amsys.models.keys()) and amsys.models[name].n > 0: if df.shape[0] != amsys.models[name].n: msg = f'<{name}> has different number of rows in addfile.' logger.warning(msg) @@ -903,7 +904,6 @@ def make_link_table(adsys): ssa_key0 = pd.merge(left=ssa_key0, how='left', on='stg_idx', right=ssa_rg[['stg_idx', 'rg_idx']]) - pd.set_option('future.no_silent_downcasting', True) ssa_key0 = ssa_key0.fillna(value=False) dyr = ssa_key0['syg_idx'].astype(bool) + ssa_key0['dg_idx'].astype(bool) + ssa_key0['rg_idx'].astype(bool) non_dyr = np.logical_not(dyr) diff --git a/ams/routines/routine.py b/ams/routines/routine.py index bd79c851..adbfe8e2 100644 --- a/ams/routines/routine.py +++ b/ams/routines/routine.py @@ -693,9 +693,14 @@ def _post_add_check(self): """ Post-addition check. """ + # --- reset routine status --- self.initialized = False self.exec_time = 0.0 self.exit_code = 0 + # --- reset symprocessor status --- + self._syms = False + # --- reset optimization model status --- + self.om.initialized = False def addRParam(self, name: str, @@ -786,8 +791,9 @@ def addService(self, model : str, optional Model name. """ - item = ValueService(name=name, value=value, tex_name=tex_name, unit=unit, - info=info, vtype=vtype, model=model) + item = ValueService(name=name, tex_name=tex_name, + unit=unit, info=info, + vtype=vtype, value=value) # add the service as an routine attribute setattr(self, name, item) diff --git a/docs/source/examples/index.rst b/docs/source/examples/index.rst index 336babfe..32c9230c 100644 --- a/docs/source/examples/index.rst +++ b/docs/source/examples/index.rst @@ -23,3 +23,4 @@ folder of the repository ../_examples/ex5.ipynb ../_examples/ex6.ipynb ../_examples/ex7.ipynb + ../_examples/ex8.ipynb diff --git a/docs/source/getting_started/formats/xlsx.png b/docs/source/getting_started/formats/xlsx.png new file mode 100644 index 00000000..d0389c44 Binary files /dev/null and b/docs/source/getting_started/formats/xlsx.png differ diff --git a/docs/source/getting_started/formats/xlsx.rst b/docs/source/getting_started/formats/xlsx.rst index b1df0555..4db880a0 100644 --- a/docs/source/getting_started/formats/xlsx.rst +++ b/docs/source/getting_started/formats/xlsx.rst @@ -3,14 +3,23 @@ AMS xlsx ---------- -The AMS xlsx format allows one to use Excel for convenient viewing and -editing. If you do not use Excel, there are alternatives such as the free and -open-source `LibreOffice `_. +AMS sticks to the same XLSX format as ANDES, where each workbook represents a +model and each row represents a device instance. Format definition ................. -The AMS xlsx format contains multiple workbooks (also known as "sheets") shown -as tabs at the bottom. The name of a workbook is a *model* name, and each +As indicated in the image below, the AMS xlsx format contains multiple workbooks +(also known as "sheets") shown as tabs at the bottom. +The name of a workbook is a *model* name, and each workbook contains the parameters of all *devices* that are *instances* of the model. + +.. image:: xlsx.png + :width: 600 + :alt: Example workbook for Bus + +.. note:: Power Flow Data are the bridge between AMS and ANDES cases. + More discussion can be found in the Examples - Interoperation with ANDES. + +For more XLSX format details, please refer to the `ANDES XLSX format `_. diff --git a/docs/source/index.rst b/docs/source/index.rst index 34a33ced..e490f68a 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -9,9 +9,9 @@ AMS documentation **Useful Links**: `Source Repository`_ | `Report Issues`_ | `Q&A`_ | `LTB Repository`_ | `ANDES Repository`_ -.. _`Source Repository`: https://github.com/jinningwang/ams -.. _`Report Issues`: https://github.com/jinningwang/ams/issues -.. _`Q&A`: https://github.com/jinningwang/ams/discussions +.. _`Source Repository`: https://github.com/CURENT/ams +.. _`Report Issues`: https://github.com/CURENT/ams/issues +.. _`Q&A`: https://github.com/CURENT/ams/discussions .. _`ANDES Repository`: https://github.com/CURENT/andes .. _`LTB Repository`: https://github.com/CURENT/ diff --git a/docs/source/modeling/routine.rst b/docs/source/modeling/routine.rst index cfa14569..26ec9234 100644 --- a/docs/source/modeling/routine.rst +++ b/docs/source/modeling/routine.rst @@ -15,13 +15,8 @@ Further, to facilitate the routine definition, AMS developed a class .. autoclass:: ams.core.param.RParam :noindex: -.. currentmodule:: ams.routines -.. autosummary:: - :recursive: - :toctree: _generated - - RoutineData - RoutineModel +.. autoclass:: ams.routines.RoutineModel + :noindex: Optimization model ------------------ diff --git a/docs/source/release-notes.rst b/docs/source/release-notes.rst index 269efce1..1bc45377 100644 --- a/docs/source/release-notes.rst +++ b/docs/source/release-notes.rst @@ -9,6 +9,12 @@ The APIs before v3.0.0 are in beta and may change without prior notice. Pre-v1.0.0 ========== +v0.8.6 (2024-02-xx) + +- Add ex8 to demonstrate how to customize existing formulations +- Fix ``addService`` +- Fix ANDES file converter issue + v0.8.5 (2024-01-31) - Improve quality of coverage and format diff --git a/examples/ex1.ipynb b/examples/ex1.ipynb index de4dd2fd..0ad120d3 100644 --- a/examples/ex1.ipynb +++ b/examples/ex1.ipynb @@ -51,8 +51,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "Last run time: 2024-01-24 09:37:17\n", - "ams:0.8.1.post5+ge752692\n" + "Last run time: 2024-02-19 08:36:36\n", + "ams:0.8.5.post1.dev0+gf07da80\n" ] } ], @@ -127,10 +127,10 @@ "output_type": "stream", "text": [ "Parsing input file \"/Users/jinningwang/Documents/work/ams/ams/cases/5bus/pjm5bus_uced.xlsx\"...\n", - "Input file parsed in 0.1218 seconds.\n", + "Input file parsed in 0.1072 seconds.\n", "Zero line rates detacted in rate_a, rate_b, rate_c, adjusted to 999.\n", "If expect a line outage, please set 'u' to 0.\n", - "System set up in 0.0021 seconds.\n" + "System set up in 0.0022 seconds.\n" ] } ], @@ -164,33 +164,33 @@ { "data": { "text/plain": [ - "OrderedDict([('Summary', Summary (3 devices) at 0x105584d30),\n", - " ('Bus', Bus (5 devices) at 0x1056110d0),\n", - " ('PQ', PQ (3 devices) at 0x12f9b8df0),\n", - " ('PV', PV (3 devices) at 0x12f9caa60),\n", - " ('Slack', Slack (1 device) at 0x12f9e0910),\n", - " ('Shunt', Shunt (0 devices) at 0x12f9eb3d0),\n", - " ('Line', Line (7 devices) at 0x12f9eb880),\n", - " ('PVD1', PVD1 (0 devices) at 0x12f9f4f70),\n", - " ('ESD1', ESD1 (0 devices) at 0x12fa065b0),\n", - " ('REGCA1', REGCA1 (0 devices) at 0x12fa06b20),\n", - " ('REGCV1', REGCV1 (0 devices) at 0x12fa11160),\n", - " ('REGCV2', REGCV2 (0 devices) at 0x12fa11940),\n", - " ('Area', Area (3 devices) at 0x12fa11e80),\n", - " ('Region', Region (2 devices) at 0x12fa1e640),\n", - " ('SFR', SFR (2 devices) at 0x12fa1edf0),\n", - " ('SR', SR (2 devices) at 0x12fa2e490),\n", - " ('NSR', NSR (2 devices) at 0x12fa2e8b0),\n", - " ('VSGR', VSGR (0 devices) at 0x12fa2ecd0),\n", - " ('GCost', GCost (4 devices) at 0x12fa3a160),\n", - " ('SFRCost', SFRCost (4 devices) at 0x12fa3a7f0),\n", - " ('SRCost', SRCost (4 devices) at 0x12fa3ad90),\n", - " ('NSRCost', NSRCost (4 devices) at 0x12fa471f0),\n", - " ('VSGCost', VSGCost (0 devices) at 0x12fa47610),\n", - " ('DCost', DCost (3 devices) at 0x12fa47910),\n", - " ('TimeSlot', TimeSlot (0 devices) at 0x12fa47e80),\n", - " ('EDTSlot', EDTSlot (24 devices) at 0x12fa50940),\n", - " ('UCTSlot', UCTSlot (24 devices) at 0x12fa50d60)])" + "OrderedDict([('Summary', Summary (3 devices) at 0x1478df070),\n", + " ('Bus', Bus (5 devices) at 0x1478df9d0),\n", + " ('PQ', PQ (3 devices) at 0x1478f81f0),\n", + " ('PV', PV (3 devices) at 0x147906250),\n", + " ('Slack', Slack (1 device) at 0x147906cd0),\n", + " ('Shunt', Shunt (0 devices) at 0x147916790),\n", + " ('Line', Line (7 devices) at 0x147916c40),\n", + " ('PVD1', PVD1 (0 devices) at 0x147933370),\n", + " ('ESD1', ESD1 (0 devices) at 0x147933970),\n", + " ('REGCA1', REGCA1 (0 devices) at 0x147933ee0),\n", + " ('REGCV1', REGCV1 (0 devices) at 0x147940520),\n", + " ('REGCV2', REGCV2 (0 devices) at 0x147940d00),\n", + " ('Area', Area (3 devices) at 0x14794c280),\n", + " ('Region', Region (2 devices) at 0x14794ca00),\n", + " ('SFR', SFR (2 devices) at 0x1479591f0),\n", + " ('SR', SR (2 devices) at 0x147959850),\n", + " ('NSR', NSR (2 devices) at 0x147959c70),\n", + " ('VSGR', VSGR (0 devices) at 0x1479640d0),\n", + " ('GCost', GCost (4 devices) at 0x147964520),\n", + " ('SFRCost', SFRCost (4 devices) at 0x147964bb0),\n", + " ('SRCost', SRCost (4 devices) at 0x147974190),\n", + " ('NSRCost', NSRCost (4 devices) at 0x1479745b0),\n", + " ('VSGCost', VSGCost (0 devices) at 0x1479749d0),\n", + " ('DCost', DCost (3 devices) at 0x147974cd0),\n", + " ('TimeSlot', TimeSlot (0 devices) at 0x14797d280),\n", + " ('EDTSlot', EDTSlot (24 devices) at 0x14797dd00),\n", + " ('UCTSlot', UCTSlot (24 devices) at 0x14798a160)])" ] }, "execution_count": 5, @@ -269,7 +269,7 @@ " PQ_1\n", " 1.0\n", " PQ 1\n", - " 1\n", + " Bus_2\n", " 230.0\n", " 3.0\n", " 0.9861\n", @@ -283,7 +283,7 @@ " PQ_2\n", " 1.0\n", " PQ 2\n", - " 2\n", + " Bus_3\n", " 230.0\n", " 3.0\n", " 0.9861\n", @@ -297,7 +297,7 @@ " PQ_3\n", " 1.0\n", " PQ 3\n", - " 3\n", + " Bus_4\n", " 230.0\n", " 4.0\n", " 1.3147\n", @@ -311,11 +311,11 @@ "" ], "text/plain": [ - " idx u name bus Vn p0 q0 vmax vmin owner ctrl\n", - "uid \n", - "0 PQ_1 1.0 PQ 1 1 230.0 3.0 0.9861 1.1 0.9 None 1.0\n", - "1 PQ_2 1.0 PQ 2 2 230.0 3.0 0.9861 1.1 0.9 None 1.0\n", - "2 PQ_3 1.0 PQ 3 3 230.0 4.0 1.3147 1.1 0.9 None 1.0" + " idx u name bus Vn p0 q0 vmax vmin owner ctrl\n", + "uid \n", + "0 PQ_1 1.0 PQ 1 Bus_2 230.0 3.0 0.9861 1.1 0.9 None 1.0\n", + "1 PQ_2 1.0 PQ 2 Bus_3 230.0 3.0 0.9861 1.1 0.9 None 1.0\n", + "2 PQ_3 1.0 PQ 3 Bus_4 230.0 4.0 1.3147 1.1 0.9 None 1.0" ] }, "execution_count": 6, @@ -343,23 +343,23 @@ { "data": { "text/plain": [ - "OrderedDict([('DCPF', DCPF at 0x12f9b8490),\n", - " ('PFlow', PFlow at 0x12fa5fa00),\n", - " ('CPF', CPF at 0x12fa73070),\n", - " ('ACOPF', ACOPF at 0x12fa736a0),\n", - " ('DCOPF', DCOPF at 0x12fa73fa0),\n", - " ('ED', ED at 0x12fca9100),\n", - " ('EDDG', EDDG at 0x12fcb40a0),\n", - " ('EDES', EDES at 0x12fcc7ac0),\n", - " ('RTED', RTED at 0x12fe09fd0),\n", - " ('RTEDDG', RTEDDG at 0x12fe1c0d0),\n", - " ('RTEDES', RTEDES at 0x12fe42760),\n", - " ('RTEDVIS', RTEDVIS at 0x12fe684f0),\n", - " ('UC', UC at 0x12fe7ac40),\n", - " ('UCDG', UCDG at 0x160845430),\n", - " ('UCES', UCES at 0x160866370),\n", - " ('DOPF', DOPF at 0x16088dd60),\n", - " ('DOPFVIS', DOPFVIS at 0x1608b0070)])" + "OrderedDict([('DCPF', DCPF at 0x1478df0a0),\n", + " ('PFlow', PFlow at 0x14798ad60),\n", + " ('CPF', CPF at 0x14799b3d0),\n", + " ('ACOPF', ACOPF at 0x14799ba00),\n", + " ('DCOPF', DCOPF at 0x1479b3340),\n", + " ('ED', ED at 0x1479ca160),\n", + " ('EDDG', EDDG at 0x147b163d0),\n", + " ('EDES', EDES at 0x147b28df0),\n", + " ('RTED', RTED at 0x147b61340),\n", + " ('RTEDDG', RTEDDG at 0x147b61400),\n", + " ('RTEDES', RTEDES at 0x147b83a90),\n", + " ('RTEDVIS', RTEDVIS at 0x147ba9820),\n", + " ('UC', UC at 0x147bbaf70),\n", + " ('UCDG', UCDG at 0x161db9760),\n", + " ('UCES', UCES at 0x161ddd6a0),\n", + " ('DOPF', DOPF at 0x161e100d0),\n", + " ('DOPFVIS', DOPFVIS at 0x161e223a0)])" ] }, "execution_count": 7, @@ -396,7 +396,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "Routine initialized in 0.0130 seconds.\n" + "Routine initialized in 0.0114 seconds.\n" ] }, { @@ -466,7 +466,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "RTED solved as optimal in 0.0173 seconds, converged after 9 iterations using solver ECOS.\n" + "RTED solved as optimal in 0.0171 seconds, converged after 9 iterations using solver ECOS.\n" ] }, { diff --git a/examples/ex2.ipynb b/examples/ex2.ipynb index caf3d407..3111dbb8 100644 --- a/examples/ex2.ipynb +++ b/examples/ex2.ipynb @@ -36,8 +36,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "Last run time: 2024-01-29 20:44:33\n", - "ams:0.8.1.post37.dev0+gf76a132\n" + "Last run time: 2024-02-19 08:36:57\n", + "ams:0.8.5.post1.dev0+gf07da80\n" ] } ], @@ -82,10 +82,10 @@ "output_type": "stream", "text": [ "Parsing input file \"/Users/jinningwang/Documents/work/ams/ams/cases/5bus/pjm5bus_uced.xlsx\"...\n", - "Input file parsed in 0.1167 seconds.\n", + "Input file parsed in 0.0956 seconds.\n", "Zero line rates detacted in rate_a, rate_b, rate_c, adjusted to 999.\n", "If expect a line outage, please set 'u' to 0.\n", - "System set up in 0.0026 seconds.\n" + "System set up in 0.0019 seconds.\n" ] } ], @@ -270,7 +270,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "Routine initialized in 0.0141 seconds.\n", + "Routine initialized in 0.0113 seconds.\n", "RTED solved as optimal in 0.0166 seconds, converged after 9 iterations using solver ECOS.\n" ] }, @@ -416,7 +416,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "RTED solved as optimal in 0.0025 seconds, converged after 9 iterations using solver ECOS.\n" + "RTED solved as optimal in 0.0018 seconds, converged after 9 iterations using solver ECOS.\n" ] }, { @@ -471,7 +471,7 @@ { "data": { "text/plain": [ - "StaticLoad (3 devices) at 0x1379130d0" + "StaticLoad (3 devices) at 0x1490457f0" ] }, "execution_count": 14, @@ -690,7 +690,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "RTED solved as optimal in 0.0020 seconds, converged after 9 iterations using solver ECOS.\n" + "RTED solved as optimal in 0.0019 seconds, converged after 9 iterations using solver ECOS.\n" ] }, { @@ -1007,7 +1007,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "RTED solved as optimal in 0.0164 seconds, converged after 8 iterations using solver ECOS.\n" + "RTED solved as optimal in 0.0160 seconds, converged after 8 iterations using solver ECOS.\n" ] }, { @@ -1421,7 +1421,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "RTED solved as optimal in 0.0159 seconds, converged after 8 iterations using solver ECOS.\n" + "RTED solved as optimal in 0.0191 seconds, converged after 8 iterations using solver ECOS.\n" ] }, { @@ -1492,10 +1492,10 @@ "output_type": "stream", "text": [ "Parsing input file \"/Users/jinningwang/Documents/work/ams/ams/cases/5bus/pjm5bus_uced.xlsx\"...\n", - "Input file parsed in 0.0386 seconds.\n", + "Input file parsed in 0.0412 seconds.\n", "Zero line rates detacted in rate_a, rate_b, rate_c, adjusted to 999.\n", "If expect a line outage, please set 'u' to 0.\n", - "System set up in 0.0025 seconds.\n" + "System set up in 0.0024 seconds.\n" ] } ], @@ -1514,7 +1514,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "Routine initialized in 0.0101 seconds.\n" + "Routine initialized in 0.0115 seconds.\n" ] }, { @@ -1628,7 +1628,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "RTED solved as optimal in 0.0158 seconds, converged after 10 iterations using solver ECOS.\n" + "RTED solved as optimal in 0.0157 seconds, converged after 10 iterations using solver ECOS.\n" ] }, { @@ -1749,8 +1749,8 @@ "output_type": "stream", "text": [ "Disabled constraints: plflb, plfub\n", - "Routine initialized in 0.0086 seconds.\n", - "RTED solved as optimal in 0.0141 seconds, converged after 9 iterations using solver ECOS.\n" + "Routine initialized in 0.0092 seconds.\n", + "RTED solved as optimal in 0.0140 seconds, converged after 9 iterations using solver ECOS.\n" ] }, { @@ -1870,8 +1870,8 @@ "name": "stderr", "output_type": "stream", "text": [ - "Routine initialized in 0.0101 seconds.\n", - "RTED solved as optimal in 0.0149 seconds, converged after 10 iterations using solver ECOS.\n" + "Routine initialized in 0.0079 seconds.\n", + "RTED solved as optimal in 0.0147 seconds, converged after 10 iterations using solver ECOS.\n" ] }, { @@ -1952,7 +1952,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "Routine initialized in 0.0103 seconds.\n" + "Routine initialized in 0.0090 seconds.\n" ] }, { @@ -2026,10 +2026,10 @@ "output_type": "stream", "text": [ "Parsing input file \"/Users/jinningwang/Documents/work/ams/ams/cases/5bus/pjm5bus_uced.xlsx\"...\n", - "Input file parsed in 0.0946 seconds.\n", + "Input file parsed in 0.0887 seconds.\n", "Zero line rates detacted in rate_a, rate_b, rate_c, adjusted to 999.\n", "If expect a line outage, please set 'u' to 0.\n", - "System set up in 0.0027 seconds.\n" + "System set up in 0.0019 seconds.\n" ] } ], @@ -2075,8 +2075,8 @@ "name": "stderr", "output_type": "stream", "text": [ - "Routine initialized in 0.0108 seconds.\n", - "RTED solved as optimal in 0.0155 seconds, converged after 9 iterations using solver ECOS.\n" + "Routine initialized in 0.0099 seconds.\n", + "RTED solved as optimal in 0.0141 seconds, converged after 9 iterations using solver ECOS.\n" ] }, { @@ -2175,7 +2175,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "RTED solved as optimal in 0.0200 seconds, converged after 325 iterations using solver SCS.\n" + "RTED solved as optimal in 0.0162 seconds, converged after 325 iterations using solver SCS.\n" ] }, { @@ -2283,8 +2283,8 @@ "name": "stderr", "output_type": "stream", "text": [ - "Routine initialized in 0.0057 seconds.\n", - "DCOPF solved as optimal in 0.0092 seconds, converged after 225 iterations using solver SCS.\n" + "Routine initialized in 0.0049 seconds.\n", + "DCOPF solved as optimal in 0.0082 seconds, converged after 225 iterations using solver SCS.\n" ] }, { diff --git a/examples/ex3.ipynb b/examples/ex3.ipynb index 4cf5e99a..e206cc32 100644 --- a/examples/ex3.ipynb +++ b/examples/ex3.ipynb @@ -36,8 +36,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "Last run time: 2024-01-29 20:44:50\n", - "ams:0.8.1.post37.dev0+gf76a132\n" + "Last run time: 2024-02-19 08:37:09\n", + "ams:0.8.5.post1.dev0+gf07da80\n" ] } ], @@ -73,10 +73,10 @@ "output_type": "stream", "text": [ "Parsing input file \"/Users/jinningwang/Documents/work/ams/ams/cases/5bus/pjm5bus_uced.xlsx\"...\n", - "Input file parsed in 0.1210 seconds.\n", + "Input file parsed in 0.0981 seconds.\n", "Zero line rates detacted in rate_a, rate_b, rate_c, adjusted to 999.\n", "If expect a line outage, please set 'u' to 0.\n", - "System set up in 0.0020 seconds.\n" + "System set up in 0.0031 seconds.\n" ] } ], diff --git a/examples/ex4.ipynb b/examples/ex4.ipynb index 504dde4a..4a92d188 100644 --- a/examples/ex4.ipynb +++ b/examples/ex4.ipynb @@ -45,8 +45,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "Last run time: 2024-01-29 20:45:03\n", - "ams:0.8.1.post37.dev0+gf76a132\n" + "Last run time: 2024-02-19 08:37:28\n", + "ams:0.8.5.post1.dev0+gf07da80\n" ] } ], @@ -89,10 +89,10 @@ "output_type": "stream", "text": [ "Parsing input file \"/Users/jinningwang/Documents/work/ams/ams/cases/ieee14/ieee14_uced.xlsx\"...\n", - "Input file parsed in 0.1268 seconds.\n", + "Input file parsed in 0.1071 seconds.\n", "Zero line rates detacted in rate_a, rate_b, rate_c, adjusted to 999.\n", "If expect a line outage, please set 'u' to 0.\n", - "System set up in 0.0023 seconds.\n", + "System set up in 0.0022 seconds.\n", "-> Systen size:\n", "Base: 100 MVA; Frequency: 60 Hz\n", "14 Buses; 20 Lines; 5 Static Generators\n", @@ -131,7 +131,7 @@ "output_type": "stream", "text": [ "Parsing input file \"/Users/jinningwang/Documents/work/ams/ams/cases/ieee14/ieee14.json\"...\n", - "Input file parsed in 0.0042 seconds.\n", + "Input file parsed in 0.0022 seconds.\n", "Zero line rates detacted in rate_a, rate_b, rate_c, adjusted to 999.\n", "If expect a line outage, please set 'u' to 0.\n", "System set up in 0.0027 seconds.\n", @@ -169,10 +169,10 @@ "output_type": "stream", "text": [ "Parsing input file \"/Users/jinningwang/Documents/work/ams/ams/cases/matpower/case14.m\"...\n", - "Input file parsed in 0.0066 seconds.\n", + "Input file parsed in 0.0070 seconds.\n", "Zero line rates detacted in rate_a, rate_b, rate_c, adjusted to 999.\n", "If expect a line outage, please set 'u' to 0.\n", - "System set up in 0.0048 seconds.\n", + "System set up in 0.0056 seconds.\n", "-> Systen size:\n", "Base: 100.0 MVA; Frequency: 60 Hz\n", "14 Buses; 20 Lines; 5 Static Generators\n", @@ -224,10 +224,10 @@ "output_type": "stream", "text": [ "Parsing input file \"/Users/jinningwang/Documents/work/ams/ams/cases/ieee14/ieee14.raw\"...\n", - "Input file parsed in 0.0096 seconds.\n", + "Input file parsed in 0.0091 seconds.\n", "Zero line rates detacted in rate_a, rate_b, rate_c, adjusted to 999.\n", "If expect a line outage, please set 'u' to 0.\n", - "System set up in 0.0021 seconds.\n", + "System set up in 0.0022 seconds.\n", "-> Systen size:\n", "Base: 100.0 MVA; Frequency: 60.0 Hz\n", "14 Buses; 20 Lines; 5 Static Generators\n", diff --git a/examples/ex5.ipynb b/examples/ex5.ipynb index 78fd5a0f..e602a69b 100644 --- a/examples/ex5.ipynb +++ b/examples/ex5.ipynb @@ -40,9 +40,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "Last run time: 2024-01-29 20:45:23\n", - "andes:1.8.10.post31+gfa2e2e5c\n", - "ams:0.8.1.post37.dev0+gf76a132\n" + "Last run time: 2024-02-19 08:36:14\n", + "andes:1.9.0\n", + "ams:0.8.5.post1.dev0+gf07da80\n" ] } ], @@ -80,10 +80,10 @@ "output_type": "stream", "text": [ "Parsing input file \"/Users/jinningwang/Documents/work/ams/ams/cases/ieee14/ieee14_uced.xlsx\"...\n", - "Input file parsed in 0.1181 seconds.\n", + "Input file parsed in 0.1334 seconds.\n", "Zero line rates detacted in rate_a, rate_b, rate_c, adjusted to 999.\n", "If expect a line outage, please set 'u' to 0.\n", - "System set up in 0.0021 seconds.\n" + "System set up in 0.0019 seconds.\n" ] } ], @@ -102,7 +102,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "Routine initialized in 0.0136 seconds.\n" + "Routine initialized in 0.0141 seconds.\n" ] }, { @@ -129,7 +129,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "RTED solved as optimal in 0.0200 seconds, converged after 11 iterations using solver ECOS.\n" + "RTED solved as optimal in 0.0194 seconds, converged after 11 iterations using solver ECOS.\n" ] }, { @@ -151,7 +151,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Convert to ANDES" + "## Convert to ANDES Case" ] }, { @@ -174,9 +174,9 @@ "text": [ "Parsing additional file \"/Users/jinningwang/Documents/work/andes/andes/cases/ieee14/ieee14_full.xlsx\"...\n", "Following PFlow models in addfile will be overwritten: , , , , , , \n", - "Addfile parsed in 0.0847 seconds.\n", - "System converted to ANDES in 0.1945 seconds.\n", - "AMS system 0x109a2c2b0 is linked to the ANDES system 0x109a2be20.\n" + "Addfile parsed in 0.0471 seconds.\n", + "System converted to ANDES in 0.1425 seconds.\n", + "AMS system 0x104242760 is linked to the ANDES system 0x160757c10.\n" ] } ], @@ -266,7 +266,8 @@ "source": [ "In the interface class ``dyn``, the link table is stored in ``dyn.link``.\n", "\n", - "It describes the mapping relationships between power flow devices and dynamic devices." + "It describes the mapping relationships between power flow devices and dynamic devices.\n", + "Note that a converted ANDES case has consistent power flow devices with the source AMS case." ] }, { @@ -406,8 +407,8 @@ "name": "stderr", "output_type": "stream", "text": [ - "Routine initialized in 0.0041 seconds.\n", - "ACOPF solved in 0.2367 seconds, converged after 12 iterations using solver PYPOWER-PIPS.\n", + "Routine initialized in 0.0032 seconds.\n", + "ACOPF solved in 0.2399 seconds, converged after 12 iterations using solver PYPOWER-PIPS.\n", "Attribute already exists in .\n", " is converted to AC.\n" ] @@ -465,7 +466,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "Send results to ANDES <0x109a2be20>...\n", + "Send results to ANDES <0x160757c10>...\n", "Send to Bus.v0\n", "Send to StaticGen.u\n", "Send to StaticGen.p0\n" @@ -490,7 +491,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Run ANDES" + "### Run Simulations in ANDES" ] }, { diff --git a/examples/ex6.ipynb b/examples/ex6.ipynb index 22dd6be6..2b6dd65a 100644 --- a/examples/ex6.ipynb +++ b/examples/ex6.ipynb @@ -37,8 +37,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "Last run time: 2024-01-29 20:45:29\n", - "ams:0.8.1.post37.dev0+gf76a132\n" + "Last run time: 2024-02-19 08:37:37\n", + "ams:0.8.5.post1.dev0+gf07da80\n" ] } ], @@ -75,10 +75,10 @@ "output_type": "stream", "text": [ "Parsing input file \"/Users/jinningwang/Documents/work/ams/ams/cases/5bus/pjm5bus_demo.xlsx\"...\n", - "Input file parsed in 0.1208 seconds.\n", + "Input file parsed in 0.1013 seconds.\n", "Zero line rates detacted in rate_a, rate_b, rate_c, adjusted to 999.\n", "If expect a line outage, please set 'u' to 0.\n", - "System set up in 0.0022 seconds.\n" + "System set up in 0.0019 seconds.\n" ] } ], @@ -372,9 +372,9 @@ { "data": { "text/plain": [ - "OrderedDict([('TimeSlot', TimeSlot (0 devices) at 0x13ae9b160),\n", - " ('EDTSlot', EDTSlot (6 devices) at 0x13ae9bbe0),\n", - " ('UCTSlot', UCTSlot (6 devices) at 0x13aea6040)])" + "OrderedDict([('TimeSlot', TimeSlot (0 devices) at 0x1640de250),\n", + " ('EDTSlot', EDTSlot (6 devices) at 0x1640decd0),\n", + " ('UCTSlot', UCTSlot (6 devices) at 0x1640ed130)])" ] }, "execution_count": 7, @@ -554,7 +554,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "Routine initialized in 0.0199 seconds.\n" + "Routine initialized in 0.0182 seconds.\n" ] }, { @@ -581,7 +581,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "ED solved as optimal in 0.0247 seconds, converged after 9 iterations using solver ECOS.\n" + "ED solved as optimal in 0.0241 seconds, converged after 9 iterations using solver ECOS.\n" ] }, { diff --git a/examples/ex7.ipynb b/examples/ex7.ipynb index 635c455c..96e7657f 100644 --- a/examples/ex7.ipynb +++ b/examples/ex7.ipynb @@ -42,8 +42,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "Last run time: 2024-01-29 20:45:39\n", - "ams:0.8.1.post37.dev0+gf76a132\n" + "Last run time: 2024-02-19 08:37:45\n", + "ams:0.8.5.post1.dev0+gf07da80\n" ] } ], @@ -79,7 +79,7 @@ "output_type": "stream", "text": [ "Parsing input file \"/Users/jinningwang/Documents/work/ams/ams/cases/5bus/pjm5bus_demo.xlsx\"...\n", - "Input file parsed in 0.1613 seconds.\n", + "Input file parsed in 0.0972 seconds.\n", "Zero line rates detacted in rate_a, rate_b, rate_c, adjusted to 999.\n", "If expect a line outage, please set 'u' to 0.\n", "System set up in 0.0020 seconds.\n" @@ -101,8 +101,8 @@ "name": "stderr", "output_type": "stream", "text": [ - "Routine initialized in 0.0075 seconds.\n", - "DCOPF solved as optimal in 0.0092 seconds, converged after 9 iterations using solver ECOS.\n" + "Routine initialized in 0.0090 seconds.\n", + "DCOPF solved as optimal in 0.0093 seconds, converged after 9 iterations using solver ECOS.\n" ] }, { @@ -145,7 +145,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "Report saved to \"pjm5bus_demo_out.txt\" in 0.0008 seconds.\n" + "Report saved to \"pjm5bus_demo_out.txt\" in 0.0024 seconds.\n" ] }, { @@ -179,12 +179,12 @@ "name": "stdout", "output_type": "stream", "text": [ - "AMS 0.8.1.post37.dev0+gf76a132\n", + "AMS 0.8.5.post1.dev0+gf07da80\n", "Copyright (C) 2023-2024 Jinning Wang\n", "\n", "AMS comes with ABSOLUTELY NO WARRANTY\n", "Case file: /Users/jinningwang/Documents/work/ams/ams/cases/5bus/pjm5bus_demo.xlsx\n", - "Report time: 01/29/2024 08:45:40 PM\n", + "Report time: 02/19/2024 08:37:46 AM\n", "\n", "\n", "========== System Statistics ==========\n", @@ -267,8 +267,8 @@ "name": "stderr", "output_type": "stream", "text": [ - "Routine initialized in 0.0167 seconds.\n", - "ED solved as optimal in 0.0222 seconds, converged after 9 iterations using solver ECOS.\n" + "Routine initialized in 0.0179 seconds.\n", + "ED solved as optimal in 0.0244 seconds, converged after 9 iterations using solver ECOS.\n" ] }, { diff --git a/examples/ex8.ipynb b/examples/ex8.ipynb new file mode 100644 index 00000000..5c518e00 --- /dev/null +++ b/examples/ex8.ipynb @@ -0,0 +1,590 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Customzie Formulation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Encapsuled the optimization problem calss, AMS provides direct access to the optimization formulation, where users have the option to customize the formulation without playing with the source code.\n", + "\n", + "In this example, we will walk through the optimization problem structure and show how to customize the formulation." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "import ams\n", + "\n", + "import datetime" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Last run time: 2024-02-20 10:49:56\n", + "ams:0.8.5.post44.dev0+gf8df7b6\n" + ] + } + ], + "source": [ + "print(\"Last run time:\", datetime.datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\"))\n", + "\n", + "print(f'ams:{ams.__version__}')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "ams.config_logger(stream_level=20)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Inspect the Optimization Problem Structure" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Parsing input file \"/Users/jinningwang/Documents/work/ams/ams/cases/5bus/pjm5bus_demo.xlsx\"...\n", + "Input file parsed in 0.1247 seconds.\n", + "Zero line rates detacted in rate_a, rate_b, rate_c, adjusted to 999.\n", + "If expect a line outage, please set 'u' to 0.\n", + "System set up in 0.0020 seconds.\n" + ] + } + ], + "source": [ + "sp = ams.load(ams.get_case('5bus/pjm5bus_demo.xlsx'),\n", + " setup=True,\n", + " no_output=True,)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In AMS, a `RoutineModel` collects the descriptive dispatch formulations.\n", + "`DCOPF`, `RTED`, etc, are the subclasses of `RoutineModel`." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Routine initialized in 0.0088 seconds.\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sp.DCOPF.init()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "After successful initialization, the attribute `om` is populated with CVXPY-based optimization problem.\n", + "\n", + "The user can even hack to the source `prob` attribute to customize it if necessary." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "cvxpy.problems.problem.Problem" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(sp.DCOPF.om.prob)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Customize Built-in Formulation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To maintain the consistency, AMS provides a set of built-in formulation customization methods to streamline the customization process.\n", + "\n", + "Here we extend DCOPF with consideration of CO2 emission.\n", + "To simplify the demonstration, following assumptions are made:\n", + "1. Variable `eg` is the CO2 emission of each generator. It is proportional to the generation, described by a parameter `ke` in the unit t/p.u..\n", + "1. Total CO2 emmission is limited by a constant cap `te`, in the unit $t$.\n", + "1. A tax `ce` is imposed on each unit of CO2 emission in the unit of $/p.u., and the tax is included in the objective function." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Add services\n", + "\n", + "Services are used to store values or build matrix for easier formulation." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sp.DCOPF.addService(name='te', tex_name='t_e',\n", + " unit='t', info='emission cap',\n", + " value=12)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "ValueService: DCOPF.te" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sp.DCOPF.te" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Add parameters\n", + "\n", + "We need the following parameters to be defined as `RParam`: `ke` and `ce`. They should be 1D array in the same length as the number of generators and `te` is a scalar.\n", + "\n", + "For a general `RParam`, it has attributes `model`, `indexer`, and `imodel` to describe its source model and index model. The definition of `c2` in DCOPF source code is a good example.\n", + "However, for ones defined through API, since there is no model containing it, all above attributes are not applicable, and the user should be aware of the sequence of the parameters.\n", + "\n", + "Considering the sequence can be indexed by the generator index, it is used to reference the variables order.\n", + "Assuming `ke` is reciprocal to the generator capacity, and `ce` is the same for each generator, we can define the parameters as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "# get the generator indices\n", + "stg_idx = sp.DCOPF.pg.get_idx()\n", + "\n", + "# get the value of pmax\n", + "pmax = sp.DCOPF.get(src='pmax', attr='v', idx=stg_idx)\n", + "\n", + "# assume the emission factor is 1 for all generators\n", + "ke = np.ones_like(pmax)\n", + "\n", + "# assume tax is reciprocal of pmax\n", + "ce = np.reciprocal(pmax)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sp.DCOPF.addRParam(name='ke', tex_name='k_e',\n", + " info='gen emission factor',\n", + " model=None, src=None, unit=None,\n", + " v=ke)\n", + "\n", + "sp.DCOPF.addRParam(name='ce', tex_name='c_e',\n", + " info='gen emission tax',\n", + " model=None, src=None, unit=None,\n", + " v=ce)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Add constraints\n", + "\n", + "The CO2 emission cap is a simple linear inequality constraint.\n", + "\n", + "If wish to revise an existing built-in constraint, you can redefine the constraint `e_str` attribute." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sp.DCOPF.addConstrs(name='eub', info='emission upper bound',\n", + " e_str='sum(mul(ke, pg)) - te', type='uq',)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Revise the objective function\n", + "\n", + "The `e_str` can be revised to include the CO2 emission tax.\n", + "Here we only need to append the tax term to the original objective function." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "sp.DCOPF.obj.e_str += '+ sum(mul(ce, pg))'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Finalize the Customization\n", + "\n", + "After revising the problem, remember to initialize it before solving." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Routine initialized in 0.0057 seconds.\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sp.DCOPF.init()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Solve it and Check the Results" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "DCOPF solved as optimal in 0.0110 seconds, converged after 9 iterations using solver ECOS.\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sp.DCOPF.run(solver='ECOS')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Inspect the results." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0.2, 5.2, 4.4, 0.2])" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sp.DCOPF.pg.v" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5.297571428627165" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sp.DCOPF.obj.v" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load the original problem as a baseline for comparison." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Parsing input file \"/Users/jinningwang/Documents/work/ams/ams/cases/5bus/pjm5bus_demo.xlsx\"...\n", + "Input file parsed in 0.0367 seconds.\n", + "Zero line rates detacted in rate_a, rate_b, rate_c, adjusted to 999.\n", + "If expect a line outage, please set 'u' to 0.\n", + "System set up in 0.0021 seconds.\n" + ] + } + ], + "source": [ + "sp0 = ams.load(ams.get_case('5bus/pjm5bus_demo.xlsx'),\n", + " setup=True,\n", + " no_output=True,)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Routine initialized in 0.0066 seconds.\n", + "DCOPF solved as optimal in 0.0098 seconds, converged after 9 iterations using solver ECOS.\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sp0.DCOPF.run(solver='ECOS')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From the comparasion, we can see that the generation schedule changes." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2.1, 5.2, 0.7, 2. ])" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sp0.DCOPF.pg.v" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2.3445000004668826" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sp0.DCOPF.obj.v" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "ams", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "d2b3bf80176349caa68dc4a3c77bd06eaade8abc678330f7d1c813c53380e5d2" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}