Skip to content

Commit

Permalink
docs: add demo (#38)
Browse files Browse the repository at this point in the history
Signed-off-by: jaapschoutenalliander <[email protected]>
  • Loading branch information
jaapschoutenalliander authored Feb 11, 2025
1 parent e21ddfd commit 938307d
Show file tree
Hide file tree
Showing 7 changed files with 307 additions and 3 deletions.
3 changes: 1 addition & 2 deletions docs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
# SPDX-License-Identifier: MPL-2.0

# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
SOURCEDIR = .
BUILDDIR = _build

# Put it first so that "make" without argument is like "make help".
Expand Down
284 changes: 284 additions & 0 deletions docs/demos/connecting_new_consumer.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Connecting a new consumer\n",
"\n",
"This demo shows how to use power-grid-model-ds to simulate a new consumer to be connected to the grid\n",
"\n",
"1. First we create an extension of the Grid objects with properties we want to use in this context\n",
"2. We create a random grid structure for the purpose of the demo\n",
"3. We define functions that add a new consumer to the grid and simulate its impact"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from dataclasses import dataclass\n",
"\n",
"import numpy as np\n",
"from numpy.typing import NDArray\n",
"\n",
"from power_grid_model_ds import Grid\n",
"from power_grid_model_ds.arrays import LineArray, NodeArray\n",
"\n",
"\n",
"class ExtendedNodeArray(NodeArray):\n",
" \"\"\"Extends the node array with the simulated voltage and coordinates\"\"\"\n",
"\n",
" _defaults = {\"u\": 0}\n",
"\n",
" u: NDArray[np.float64]\n",
" x_coor: NDArray[np.float64]\n",
" y_coor: NDArray[np.float64]\n",
"\n",
" @property\n",
" def is_overloaded(self):\n",
" return np.logical_or(self.u > 1.1 * self.u_rated, self.u < 0.9 * self.u_rated)\n",
"\n",
"\n",
"class ExtendedLineArray(LineArray):\n",
" \"\"\"Extends the line array with current output\"\"\"\n",
"\n",
" _defaults = {\"i_from\": 0}\n",
"\n",
" i_from: NDArray[np.float64]\n",
"\n",
" @property\n",
" def is_overloaded(self):\n",
" return self.i_from > self.i_n\n",
"\n",
"\n",
"@dataclass\n",
"class ExtendedGrid(Grid):\n",
" node: ExtendedNodeArray\n",
" line: ExtendedLineArray"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from power_grid_model_ds.generators import RadialGridGenerator\n",
"\n",
"grid_generator = RadialGridGenerator(grid_class=ExtendedGrid, nr_nodes=20, nr_sources=1, nr_nops=10)\n",
"grid = grid_generator.run(seed=0)\n",
"\n",
"grid.set_feeder_ids()\n",
"\n",
"grid.node.x_coor = np.random.uniform(100, 500, len(grid.node))\n",
"grid.node.y_coor = np.random.uniform(100, 500, len(grid.node))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"First we create a new consumer, with a location and a load demand"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from power_grid_model import LoadGenType\n",
"\n",
"from power_grid_model_ds.arrays import SymLoadArray\n",
"from power_grid_model_ds.enums import NodeType\n",
"\n",
"\n",
"def create_new_consumer_arrays(\n",
" u_rated: float, x_coor: float, y_coor: float, p_specified: float, q_specified: float\n",
") -> tuple[ExtendedNodeArray, SymLoadArray]:\n",
" new_consumer = ExtendedNodeArray(\n",
" u_rated=[u_rated],\n",
" node_type=[NodeType.UNSPECIFIED],\n",
" x_coor=[x_coor],\n",
" y_coor=[y_coor],\n",
" )\n",
" new_consumer_load = SymLoadArray(\n",
" node=[new_consumer.get_empty_value(\"id\")],\n",
" status=[1],\n",
" type=[LoadGenType.const_power],\n",
" p_specified=[p_specified],\n",
" q_specified=[q_specified],\n",
" )\n",
" return new_consumer, new_consumer_load\n",
"\n",
"\n",
"new_consumer, new_consumer_load = create_new_consumer_arrays(10_500, 300, 300, 1_000_000, 200_000)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now lets define some functions that add the new consumer by connecting it to the closest node"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from power_grid_model_ds._core.load_flow import PowerGridModelInterface\n",
"\n",
"R_PER_KM = 0.1\n",
"X_PER_KM = 0.1\n",
"\n",
"\n",
"def find_closest_node(grid: ExtendedGrid, x: float, y: float) -> int:\n",
" dist = np.sqrt((grid.node.x_coor - x) ** 2 + (grid.node.y_coor - y) ** 2)\n",
" return np.argmin(dist)\n",
"\n",
"\n",
"def connect_new_consumer(\n",
" grid: ExtendedGrid,\n",
" new_consumer: ExtendedNodeArray,\n",
" new_consumer_load: SymLoadArray,\n",
"):\n",
" closest_node_idx = find_closest_node(\n",
" grid=grid,\n",
" x=new_consumer.x_coor[0],\n",
" y=new_consumer.y_coor[0],\n",
" )\n",
" closest_node = grid.node[closest_node_idx]\n",
"\n",
" grid.append(new_consumer)\n",
" new_consumer_load.node = new_consumer.id\n",
" grid.append(new_consumer_load)\n",
"\n",
" dist = np.sqrt((closest_node.x_coor - new_consumer.x_coor) ** 2 + (closest_node.y_coor - new_consumer.y_coor) ** 2)\n",
"\n",
" new_line = ExtendedLineArray(\n",
" from_node=[closest_node.id],\n",
" to_node=[new_consumer.id],\n",
" from_status=[1],\n",
" to_status=[1],\n",
" r1=[R_PER_KM * dist / 1_000],\n",
" x1=[X_PER_KM * dist / 1_000],\n",
" c1=[0],\n",
" tan1=[0],\n",
" i_n=[200],\n",
" )\n",
" grid.append(new_line)\n",
"\n",
"\n",
"def update_grid(grid: ExtendedGrid):\n",
" # Set the new feeder ids\n",
" grid.set_feeder_ids()\n",
"\n",
" # Update the loadflow\n",
" core_interface = PowerGridModelInterface(grid=grid)\n",
"\n",
" core_interface.create_input_from_grid()\n",
" core_interface.calculate_power_flow()\n",
" core_interface.update_grid()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"connect_new_consumer(grid, new_consumer, new_consumer_load)\n",
"update_grid(grid)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can inspect the results\n",
"\n",
"- The grid has been extended (graph and arrays)\n",
"- Load values have been updated on node and line arrays\n",
"- The feeder ids have been updated for the new consumer"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(grid.node)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(grid.line)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(f\"Overloaded nodes: {grid.node[grid.node.is_overloaded].id}\")\n",
"print(f\"Overloaded lines: {grid.line[grid.line.is_overloaded].id}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now simulate more consumers being added, as to see how this will lead to overloads"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for _ in range(10):\n",
" new_consumer, new_consumer_load = create_new_consumer_arrays(\n",
" 10_500, np.random.uniform(0, 500), np.random.uniform(0, 500), 1_000_000, 200_000\n",
" )\n",
" connect_new_consumer(grid, new_consumer, new_consumer_load)\n",
"update_grid(grid)\n",
"\n",
"print(f\"Overloaded nodes: {grid.node[grid.node.is_overloaded].id}\")\n",
"print(f\"Overloaded lines: {grid.line[grid.line.is_overloaded].id}\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"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.12.6"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
3 changes: 3 additions & 0 deletions docs/demos/connecting_new_consumer.ipynb.license
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
SPDX-FileCopyrightText: Contributors to the Power Grid Model project <[email protected]>

SPDX-License-Identifier: MPL-2.0
15 changes: 15 additions & 0 deletions docs/demos/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.. SPDX-FileCopyrightText: Contributors to the Power Grid Model project <[email protected]>
..
.. SPDX-License-Identifier: MPL-2.0
Demos
======================
These showcase integrated examples of how to use the PGM-DS library.
They are designed to help users understand the practical applications of the library,
demonstrating key features and common use cases.

.. toctree::
:maxdepth: 1
:caption: Contents:

connecting_new_consumer
2 changes: 2 additions & 0 deletions docs/examples/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
Examples
======================

These example explain the PGM-DS interface and how to use it.

.. toctree::
:maxdepth: 1
:caption: Contents:
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pip install power-grid-model-ds
:maxdepth: 2
quick_start
demos/index
model_structure
model_interface
examples/index
Expand Down
2 changes: 1 addition & 1 deletion docs/make.bat
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set SOURCEDIR=.
set BUILDDIR=_build

%SPHINXBUILD% >NUL 2>NUL
Expand Down

0 comments on commit 938307d

Please sign in to comment.