pownet.core package

Submodules

pownet.core.data_processor module

data_processor.py: This file contains the DataProcessor class that processes the data provided by the user.

class pownet.core.data_processor.DataProcessor(input_folder, model_name, year, frequency)[source]

Bases: object

calc_line_capacity()[source]

Calculate the capacity of line segments. The unit is in MW. Line capacity is the minimum of the thermal limit and the steady-state stability limit (a function of distance).

Note the calculated values are overwritten by user provided values in the transmission.csv file.

Return type:

None

calc_line_susceptance()[source]

Calculate the susceptance of line segments. The unit is in Siemens (S).

Return type:

None

calc_stability_limit(source_kv, sink_kv, distance, n_circuits)[source]

Calculates the theoretical steady-state stability limit of the transmission line.

This method applies the classical Power Transfer Equation for a lossless line (Chapter 5 of Power System Analysis and Design, Eq. 5.4.27).

Formula: P_max_circuit = (V_S * V_R) / X_total

Where: P_max_circuit: The maximum Real Power transfer per circuit in MW.

(Assumes Power Factor = 1.0, so MW = MVA).

V_S, V_R: The Line-to-Line voltages at sending and receiving ends in kV. X_total: The total reactance of the line in Ohms.

Calculated as (Reactance_per_km * distance).

Note on “Perfect Condition”: This calculates the static stability limit (steady-state). Practical operations typically constrain flow to a safety margin (e.g., 30-45 degrees load angle) well below this theoretical maximum.

Parameters:
  • source_kv (int) – Voltage level of the source bus in kV.

  • sink_kv (int) – Voltage level of the sink bus in kV.

  • distance (float) – Length of the transmission line in km.

  • n_circuits (int) – Number of parallel circuits (e.g., 2 for double-circuit).

Returns:

The combined stability limit for all circuits in MW.

Returns infinity if distance is 0 (co-located buses).

Return type:

int

calc_thermal_limit(source_kv, sink_kv, n_circuits)[source]

Calculates the thermal rating (MVA) of the transmission line based on conductor ampacity (Chapter 5 of Power System Analysis and Design 5th See Example 5.6b).

Let ‘n_conductors’ parameter in ‘transmission_params’ represents the number of sub-conductors per phase (bundling factor).

Formula: S_thermal = sqrt(3) * V_line_LL * I_phase_max

Return type:

int

Where: S_thermal: The total Apparent Power capacity of the circuit in MVA.

(Note: S_thermal = P_real_power only when Power Factor = 1.0)

V_line_LL: The Line-to-Line voltage in kV (the standard voltage rating, e.g., 115 kV). I_phase_max: The maximum current capacity per phase in kilo-Amps (kA).

Calculated as (Ampacity per wire * Bundling Factor).

Args: source_kv (int): Voltage level of the source bus (kV). sink_kv (int): Voltage level of the sink bus (kV). n_circuits (int): Number of distinct circuits (e.g., double circuit tower = 2).

Returns: int: The maximum thermal capacity in MVA.

check_user_line_capacities()[source]

The user can provide their own line capacities under user_line_cap column in transmission.csv. If this is the case, then it will be used instead of the calculated line capacities.

Return type:

None

create_cycle_map()[source]

Create a cycle map for the power system. This is used to create the cycle constraints in the optimization model. The cycle map is a dictionary where the key is the cycle name and the value is a list of nodes in the cycle.

Return type:

None

create_ess_derate_factors(derate_factor=1.0)[source]

Creates derate factors for ESS units.

Return type:

None

create_ess_derated_capacity()[source]

Creates a dataframe of hourly derated capacity of ess units.

Return type:

None

create_thermal_derate_factors(derate_factor=1.0)[source]

Creates derate factors for thermal units.

Return type:

None

create_thermal_derated_capacity()[source]

Creates a dataframe of hourly derated capacity of thermal units.

Return type:

None

execute_data_pipeline()[source]
Return type:

None

load_transmission_data()[source]
Return type:

None

run_all_processing_steps()[source]

Run all the data processing steps

Return type:

None

write_cycle_map()[source]

Save the cycle map to a json file in model_library/{model_name}. The key is the cycle name and the value is a list of nodes in the cycle.

Return type:

None

write_data()[source]

Write the processed data as csv files sharing a prefix pownet_ to the model folder

Return type:

None

write_ess_derated_capacity()[source]
Return type:

None

write_thermal_derate_factors()[source]
Return type:

None

write_thermal_derated_capacity()[source]
Return type:

None

write_transmission_data()[source]
Return type:

None

pownet.core.model_builder module

builder.py: This module contains the ModelBuilder class, which is responsible for constructing and updating the optimization model for the power system.

class pownet.core.model_builder.ModelBuilder(inputs)[source]

Bases: object

build(step_k, init_conds)[source]

Build the initial optimization model by delegating to specialized builders.

Return type:

PowerSystemModel

get_phydro()[source]

Get the hydro power variable from the model.

Return type:

tupledict

update(step_k, init_conds)[source]

Update the existing model for a new step_k by delegating to specialized builders.

Return type:

PowerSystemModel

update_daily_hydropower_capacity(step_k, new_capacity)[source]

Update the daily hydro capacity in the model.

Return type:

PowerSystemModel

pownet.core.output module

output.py: the OutputProcessor class processes modeling outputs in typical formats.

class pownet.core.output.OutputProcessor[source]

Bases: object

get_co2_emission(hourly_generation, co2_map=None)[source]

Return the CO2 emissions for timestep. From Chowdhury, Dang, Nguyen, Koh, & Galelli. (2021).

coal: 1.04 Mton/MWh gas: 0.47 Mton/MWh oil : 0.73 Mton/MWh solid_waste: 0.170 Mton/MWh

From https://www.eia.gov/environment/emissions/co2_vol_mass.php: solid_waste: 49.89 kg/MMBtu (From 49.89 kg/MMBtu * 3.412 MMBtu/MWh * 1 Mton/1000 kg = 0.170 Mton/MWh)

get_contract_generation(node_variables, unit_contract)[source]
Return type:

DataFrame

get_contract_hourly_cost(node_variables, unit_contract, contract_costs)[source]
Return type:

DataFrame

get_contract_hourly_generation(node_variables, unit_contract)[source]
Return type:

DataFrame

get_daily_demand(input_demand)[source]
Return type:

Series

get_daily_generation(node_variables)[source]
Return type:

DataFrame

get_energy_storage_daily_state(node_variables, max_storage)[source]
Return type:

DataFrame

get_energy_storage_hourly_charge(node_variables)[source]
Return type:

DataFrame

get_energy_storage_hourly_discharge(node_variables)[source]
Return type:

DataFrame

get_energy_storage_hourly_state(node_variables, max_storage)[source]
Return type:

DataFrame

get_fuel_mix(hourly_generation)[source]

Return the fuel mix (%) for the whole simulation period.

Return type:

DataFrame

get_gen_by_fuel(hourly_generation)[source]

Return the total generation for the whole simulation period.

Return type:

DataFrame

get_hourly_curtailment(node_variables, unit_type)[source]
Return type:

DataFrame

get_hourly_demand(input_demand)[source]
Return type:

Series

get_hourly_generation(node_variables)[source]
Return type:

DataFrame

get_import_values(node_variables)[source]

Return the import values for each timestep. Columns are generators. Index is the hour in the simulation year

Return type:

DataFrame

get_max_line_usage(flow_variables, line_locations, rated_line_capacities)[source]

Calculates the maximum utilization for each transmission line.

This function takes the flow results from an optimization model, determines the peak flow on each line over the entire simulation horizon, and then calculates the utilization of each line as a percentage of its rated capacity. It also merges location data for the lines.

Parameters:
  • flow_variables (pd.DataFrame) – DataFrame containing flow values for each line at each timestep. Expected columns: ‘node_a’, ‘node_b’, ‘value’ (flow magnitude), and ‘hour’.

  • line_locations (pd.DataFrame) – DataFrame containing location or other metadata for each line. Expected to be indexed by a MultiIndex (‘source’, ‘sink’).

  • rated_line_capacities (dict[tuple[str, str], int]) – Dictionary mapping line tuples (source_node, sink_node) to their rated power capacity (e.g., in MW).

Returns:

A DataFrame indexed by (‘source’, ‘sink’) with columns

including ‘max_line_usage’ (peak flow / rated capacity), columns from line_locations, and ‘rated_capacity’.

Return type:

pd.DataFrame

get_monthly_demand(input_demand)[source]
Return type:

Series

get_monthly_generation(node_variables)[source]
Return type:

DataFrame

get_nondispatch_hourly_capacity_factor(unit_type, node_variables, contracted_capacities, energy_storage_attach)[source]

Return the capacity factor which is a function of generation and storage charging.

Return type:

DataFrame

get_thermal_unit_daily_dispatch(node_variables)[source]
Return type:

DataFrame

get_thermal_unit_daily_duration(node_variables)[source]

Return the daily online duration of each thermal unit. Rows are days and columns are units.

Return type:

DataFrame

get_thermal_unit_daily_startup_frequency(node_variables)[source]

Return the frequency of startups for each thermal unit over the whole simulation period.

Return type:

DataFrame

get_thermal_unit_hourly_dispatch(node_variables)[source]
Return type:

DataFrame

get_thermal_unit_hourly_status(node_variables)[source]
Return type:

DataFrame

get_thermal_unit_mean_hourly_status(node_variables)[source]

The hourly status of thermal units for each hour over the simulation period.

Return type:

DataFrame

get_thermal_unit_startup_frequency(node_variables)[source]

Return the frequency of startups for each thermal unit over the whole simulation period.

Return type:

DataFrame

get_thermal_unit_total_duration(node_variables)[source]

Return the total online duration of each thermal unit over the whole simulation period.

Return type:

DataFrame

get_thermal_unit_total_duration_and_frequency(node_variables)[source]

Return data for histogram of frequency of startups and duration of committed hours in a year.

Return type:

DataFrame

get_unit_hourly_generation(node_variables)[source]
Return type:

DataFrame

get_variables(node_variables, variables)[source]

Return unit-level shortfall variables.

Return type:

DataFrame

load(inputs)[source]

Load the input data.

Return type:

None

pownet.core.record module

record.py: The SystemRecord class processes stores the modeling outputs from each iteration. TODO: self.current_hydro, self.current_import for model coupling

class pownet.core.record.SystemRecord(system_input, batch_mode=True, keep_record_each_step=False)[source]

Bases: object

This class stores modeling outputs from each iteration. The results are stored in three dataframes: node_vars, flow_vars, and syswide_vars. The initial conditions are also stored in the class.

get_flow_variables()[source]

Return the flow variables.

Return type:

DataFrame

get_init_conds()[source]

Return the initial conditions for the simulation.

Return type:

dict[str, dict]

get_lmp()[source]

Return the locational marginal prices (LMP) data.

Return type:

DataFrame

get_model_stats()[source]
Return type:

DataFrame

get_node_variables()[source]

Return node-specific variables. These variables include dispatch, unit status, unit switching, etc.

Return type:

DataFrame

get_objvals()[source]

Return the objective values from each iteration.

Return type:

list[float]

get_runtimes()[source]

Return the model runtime from each iteration.

Return type:

list[float]

get_systemwide_variables()[source]

Return the system variables. We currently only have the system-wide spinning reserve shortfall.

Return type:

DataFrame

keep(runtime, objval, solution, step_k, lmp=None)[source]

Keep the simulation results at the current simulation period step_k.

Parameters:
  • runtime (float) – The runtime of the model.

  • objval (float) – The objective value of the model.

  • solution (pd.DataFrame) – The solution dataframe from the model.

  • step_k (int) – The current simulation period.

  • lmp (dict[str, float], optional) – The locational marginal prices. Defaults to None.

Return type:

None

Returns:

None

write_init_conds(output_folder)[source]
Return type:

None

write_simulation_results(output_folder)[source]

Write CSV files containing modeling results to the output directory.

Parameters:

output_folder (str) – The directory where the output files will be saved.

Return type:

None

Returns:

None

pownet.core.simulation module

simulation.py: Main class to run the simulation of the power system model

class pownet.core.simulation.Simulator(input_folder, model_name, model_year, frequency=50, use_spin_var=True, dc_opf='kirchhoff', spin_reserve_factor=0.15, spin_reserve_mw=None, line_loss_factor=0.075, line_capacity_factor=0.9, load_shortfall_penalty_factor=1000, load_curtail_penalty_factor=10, spin_shortfall_penalty_factor=1000)[source]

Bases: object

Main class to run the simulation of the power system model

get_flow_variables()[source]

Return the flow variables.

Return type:

DataFrame

get_node_variables()[source]

Return the node-specific variables.

Return type:

DataFrame

get_systemwide_variables()[source]

Return the system variables

Return type:

DataFrame

plot_fuelmix(chart_type, output_folder=None)[source]

Plot the fuel mix of the power system

Parameters:
  • chart_type (str) – The type of chart to plot. Choose between ‘bar’ and ‘area’.

  • output_folder (str) – The folder to save the plot.

Return type:

None

Returns:

None

plot_lmp(output_folder=None)[source]

Plot the locational marginal prices

Parameters:

output_folder (str) – The folder to save the plot.

Return type:

None

Returns:

None

plot_thermal_units(output_folder=None)[source]

Plot the status of the thermal units

Parameters:

output_folder (str) – The folder to save the plot.

Return type:

None

Returns:

None

run(sim_horizon, steps_to_run, num_sim_days=365, to_process_inputs=True, solver='gurobi', log_to_console=True, mipgap=0.001, timelimit=600, num_threads=0, find_lmp=False)[source]

Run the simulation of the power system model

Parameters:
  • sim_horizon (int) – The simulation horizon in hours.

  • steps_to_run (int) – The number of steps to run the simulation.

  • to_process_inputs (bool) – Whether to process the input data.

  • solver (str) – The solver to use for optimization.

  • log_to_console (bool) – Whether to log the optimization output to the console.

  • mipgap (float) – The MIP gap for the optimization.

  • timelimit (int) – The time limit for the optimization in seconds.

  • num_threads (int) – The number of threads to use for optimization.

  • find_lmp (bool) – Whether to find the locational marginal prices.

Returns:

The system record object containing the simulation results.

Return type:

SystemRecord

write_results(output_folder)[source]

Write the simulation results to files

Return type:

None

pownet.core.user_constraint module

class pownet.core.user_constraint.UserConstraint(model)[source]

Bases: object

add_constraints_to_model(step_k=1)[source]
register_constraint(constraint, constr_name, **kwargs)[source]
register_constraint_with_update(constraint, constr_name, **kwargs)[source]
remove_constraints(constr_names)[source]
update_constraints(step_k)[source]

pownet.core.visualizer module

visualizer.py: This module contains the Visualizer class, which provides methods to visualize the output from PowNet.

class pownet.core.visualizer.Visualizer(model_id)[source]

Bases: object

plot_fuelmix_area(dispatch, demand, output_folder=None)[source]

Create an area plot of the fuel mix.

Parameters:
  • dispatch (pd.DataFrame) – The dispatch of each generator.

  • demand (pd.Series) – The demand of the system.

  • output_folder (str) – If specified, then the plot is saved in the folder.

Return type:

None

Returns:

None

plot_fuelmix_bar(dispatch, demand, output_folder=None)[source]

Create a bar plot of the fuel mix.

Parameters:
  • dispatch (pd.DataFrame) – The dispatch of each generator.

  • demand (pd.Series) – The demand of the system.

  • output_folder (str) – If specified, then the plot is saved in the folder.

Return type:

None

Returns:

None

plot_generation_by_contracts(contract_generation)[source]
Return type:

None

plot_line_usage(max_line_usage, output_folder=None)[source]

Flow variables must have the max_line_usage column

Return type:

None

plot_lmp(lmp_df, output_folder=None, max_ylim=200)[source]

Plots unique locational marginal price (LMP) timeseries. For each unique LMP timeseries, a representative node is chosen based on ordering in the dataframe.

Parameters:
  • lmp_df (pd.DataFrame) – LMP timeseries.

  • output_folder (str) – If specified, then the plot is saved in the folder.

  • max_ylim (float) – Maximum y-axis limit.

Return type:

None

Returns:

None

plot_mean_thermal_unit_hourly_status(thermal_unit_mean_hourly_status, output_folder=None)[source]
Return type:

None

plot_power_flow(flow_variables, figsize_per_line=(10, 2), fixed_legend_height_inches=0.5)[source]

Plots the power flow on transmission lines over time.

Each unique transmission line (node_a to node_b) gets its own subplot. The y-axis label for each subplot is the line segment name. Legend is placed at the top center of the figure, occupying a fixed absolute height. Power flow is colored: - Green: Positive flow - Red: Negative flow - Black: Zero flow

Parameters:
  • flow_variables (pd.DataFrame) – DataFrame with simulation results. Expected columns: ‘node_a’, ‘node_b’, ‘value’, ‘type’ (‘fwd’ or ‘bwd’), ‘hour’.

  • figsize_per_line (tuple) – Tuple specifying (width, height_for_each_subplot_plot_area).

  • fixed_legend_height_inches (float) – Absolute height in inches for the legend area at the top.

Return type:

None

plot_thermal_units(thermal_dispatch, unit_status, thermal_rated_capacity, output_folder=None)[source]

Plot the on/off status of individual thermal units

Parameters:
  • thermal_dispatch (pd.DataFrame) – The dispatch of each thermal unit.

  • unit_status (pd.DataFrame) – The status of each thermal unit.

  • thermal_rated_capacity (dict[str, float]) – Rated capacity of each thermal unit.

  • output_folder (str) – If specified, then the plot is saved in the folder.

Return type:

None

Returns:

None

plot_unit_storage_state(hourly_storage_charge, hourly_storage_discharge, hourly_storage_state, output_folder=None)[source]

Plot the hourly activity of the energy storage units.

Parameters:
  • hourly_storage_charge (pd.Series) – Hourly charge data.

  • hourly_storage_discharge (pd.Series) – Hourly discharge data.

  • hourly_storage_state (pd.Series) – Hourly storage state data.

Return type:

None