-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #12 from PowerGridModel/feature/pgm-tpf
New benchmark tpf-pgm migrated from internal repo
- Loading branch information
Showing
4 changed files
with
372 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Introduction\n", | ||
"\n", | ||
"This notebook presents a benchmark between Power Grid Model and the Tensor Power Flow. N.B., the performance gain of TPF is made purely out of the data formulation, no advantage of Intel MKL or CUDA is taken." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import warnings\n", | ||
"from time import time\n", | ||
"from tqdm import tqdm\n", | ||
"\n", | ||
"import numpy as np\n", | ||
"import power_grid_model as pgm\n", | ||
"from generate_fictional_dataset import generate_fictional_grid_pgm_tpf\n", | ||
"from plotter import BenchmarkPlotter\n", | ||
"from power_grid_model.validation import errors_to_string, validate_batch_data, validate_input_data\n", | ||
"from tensorpowerflow import GridTensor\n", | ||
"\n", | ||
"warnings.filterwarnings(\"ignore\")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Configurations for grids: PGM method dictionary for exact methods\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"pgm_method_dict = {\n", | ||
" \"iterative_current\": \"PGM Iterative Current\",\n", | ||
" \"newton_raphson\": \"PGM Newton-Raphson\",\n", | ||
"}" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Benchmark experiment function: " | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 3, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"def experiment(n_feeder=20, n_node_per_feeder=50, n_step=1000, log=False):\n", | ||
" def log_print(*args):\n", | ||
" if log:\n", | ||
" print(*args)\n", | ||
"\n", | ||
" # fictional grid parameters\n", | ||
" cable_length_km_min = 0.8\n", | ||
" cable_length_km_max = 1.2\n", | ||
" load_p_w_min = 0.4e6 * 0.8\n", | ||
" load_p_w_max = 0.4e6 * 1.2\n", | ||
" pf = 0.95\n", | ||
"\n", | ||
" load_scaling_min = 0.5\n", | ||
" load_scaling_max = 1.5\n", | ||
"\n", | ||
" # gen grid data\n", | ||
" fictional_dataset = generate_fictional_grid_pgm_tpf(\n", | ||
" n_node_per_feeder=n_node_per_feeder,\n", | ||
" n_feeder=n_feeder,\n", | ||
" cable_length_km_min=cable_length_km_min,\n", | ||
" cable_length_km_max=cable_length_km_max,\n", | ||
" load_p_w_max=load_p_w_max,\n", | ||
" load_p_w_min=load_p_w_min,\n", | ||
" pf=pf,\n", | ||
" n_step=n_step,\n", | ||
" load_scaling_min=load_scaling_min,\n", | ||
" load_scaling_max=load_scaling_max,\n", | ||
" )\n", | ||
" # unpack data\n", | ||
" pgm_dataset = fictional_dataset[\"pgm_dataset\"]\n", | ||
" pgm_update_dataset = fictional_dataset[\"pgm_update_dataset\"]\n", | ||
" tpf_node_data = fictional_dataset[\"tpf_grid_nodes\"]\n", | ||
" tpf_line_data = fictional_dataset[\"tpf_grid_lines\"]\n", | ||
" tpf_time_series_p = fictional_dataset[\"tpf_time_series_p\"]\n", | ||
" tpf_time_series_q = fictional_dataset[\"tpf_time_series_q\"]\n", | ||
"\n", | ||
" # validate data\n", | ||
" log_print(errors_to_string(validate_input_data(pgm_dataset)))\n", | ||
" log_print(errors_to_string(validate_batch_data(pgm_dataset, pgm_update_dataset)))\n", | ||
"\n", | ||
" res_pgm = []\n", | ||
" # create grids, run pf's and time them\n", | ||
" # pgm - all 4 methods\n", | ||
" pgm_methods = [\"iterative_current\", \"newton_raphson\"]\n", | ||
" for method in pgm_methods:\n", | ||
" pgm_start_time = time()\n", | ||
" model_instance = pgm.PowerGridModel(pgm_dataset)\n", | ||
" start = time()\n", | ||
" _ = model_instance.calculate_power_flow(\n", | ||
" symmetric=True,\n", | ||
" calculation_method=method,\n", | ||
" update_data=pgm_update_dataset,\n", | ||
" output_component_types=[\"node\", \"line\"],\n", | ||
" max_iterations=10000,\n", | ||
" )\n", | ||
" end = time()\n", | ||
" pgm_end_time = time()\n", | ||
" res_pgm.append(end - start)\n", | ||
" log_print(f\"{pgm_method_dict[method]}: {end - start}\")\n", | ||
" log_print(f\"Total time{pgm_method_dict[method]}: {pgm_end_time - pgm_start_time}\")\n", | ||
"\n", | ||
" # tpf\n", | ||
" tpf_time_start = time()\n", | ||
" tpf_instance = GridTensor(\n", | ||
" node_file_path=\"\",\n", | ||
" lines_file_path=\"\",\n", | ||
" from_file=False,\n", | ||
" nodes_frame=tpf_node_data,\n", | ||
" lines_frame=tpf_line_data,\n", | ||
" gpu_mode=False,\n", | ||
" )\n", | ||
" tpf_time_end = time()\n", | ||
"\n", | ||
" tpf_functions = [\"run_pf_tensor\"]\n", | ||
" res_tpf = []\n", | ||
" for function_name in tpf_functions:\n", | ||
" start = time()\n", | ||
" _ = getattr(tpf_instance, function_name)(active_power=tpf_time_series_p, reactive_power=tpf_time_series_q)\n", | ||
" end = time()\n", | ||
" res_tpf.append(end - start)\n", | ||
" log_print(f\"TensorPowerFlow.{function_name}: {end - start}\")\n", | ||
"\n", | ||
" log_print(f\"TensorPowerFlow instancing: {tpf_time_end - tpf_time_start}\")\n", | ||
"\n", | ||
" return {\"entry pgm\": pgm_methods, \"result pgm\": res_pgm, \"entry tpf\": tpf_functions, \"result tpf\": res_tpf}" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Now run the different experiment configurations." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"exp_options = [[20, 1], [20, 5], [20, 10], [20, 25], [40, 25], [40, 50]]\n", | ||
"for n in tqdm([10, 100, 1000, 10000], desc=\"Overall Progress\"):\n", | ||
" plotter = BenchmarkPlotter(n_steps=n)\n", | ||
" for option in tqdm(exp_options, desc=f\"Processing n={n}\"):\n", | ||
" res = experiment(option[0], option[1], n)\n", | ||
" plotter.add(res, option[0] * option[1])\n", | ||
" plotter.plot()" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"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.0" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# SPDX-FileCopyrightText: Contributors to the Power Grid Model project <[email protected]> | ||
# | ||
# SPDX-License-Identifier: MPL-2.0 | ||
|
||
from matplotlib import pyplot as plt | ||
|
||
|
||
class BenchmarkPlotter: | ||
def __init__(self, n_steps=1000): | ||
self.data_pgm_ic = [] | ||
self.data_pgm_nr = [] | ||
self.data_tpf_tf = [] | ||
self.n_nodes = [] | ||
self.n_steps = n_steps | ||
|
||
def add(self, res, n_nodes): | ||
res_pgm = res["result pgm"] | ||
res_tpf = res["result tpf"] | ||
self.data_pgm_ic.append(res_pgm[0]) | ||
self.data_pgm_nr.append(res_pgm[1]) | ||
self.data_tpf_tf.append(res_tpf[0]) | ||
self.n_nodes.append(n_nodes) | ||
|
||
def plot(self, log_scale=False): | ||
plt.figure(figsize=(8, 5)) | ||
_, ax = plt.subplots() | ||
data_lists = [ | ||
self.data_pgm_ic, | ||
self.data_pgm_nr, | ||
self.data_tpf_tf, | ||
] | ||
labels = ["pgm ic", "pgm nr", "tpf"] | ||
styles = ["--", "--", "--", "--", "-"] | ||
for data_list, label, style in zip(data_lists, labels, styles): | ||
if log_scale: | ||
ax.semilogy(self.n_nodes, data_list, label=label, linestyle=style) | ||
else: | ||
ax.plot(self.n_nodes, data_list, label=label, linestyle=style) | ||
|
||
ax.set_title(f"PGM vs TPF {self.n_steps} steps") | ||
ax.set_xlabel("Number of Nodes") | ||
ax.set_ylabel("Execution Time (s)") | ||
|
||
ax.legend() | ||
# plt.savefig(f"data/benchmark_{self.n_steps}.pdf") | ||
plt.show() |