Model Structure
The Model
directory forms the core of the MicroGridsPy application for developers. It contains a set of Python modules that together constitute the architecture of the Pyomo optimization model. Each module is specialized to handle different aspects of the optimization process. Below is a concise overview of each file within the Model
folder:
__pycache__
: A directory that holds the bytecode compiled Python files, which are used to speed up module loading. This directory is automatically generated and should not be altered manually.Constraints.py
: This file defines the constraints of the optimization problem, ensuring that the solutions conform to the predefined logical and mathematical rules.Demand.py
: Manages the demand simulation advanced features thorugh build-in demand archetypes.Grid_Availability.py
: This module generates the electrical grid’s availability matrix, crucial for planning around periods when the grid is not operational.Initialize.py
: Prepares the initial settings and variables necessary for the model, setting the stage for the optimization process.MicroGrids.py
: Acts as the primary script for developers to run the model, invoking the necessary modules and coordinating the execution flow.Model_Creation.py
: Entrusted with assembling the model instance, defining the structural elements, and populating initial set, parameters and variables.Model_Resolution.py
: Dedicated to the resolution of the optimization model, it triggers the solver and oversees the entire solution procedure.Plots.py
: A utility module aimed at creating graphical representations of the model’s outputs.RE_calculation.py
: Calculates the production of renewable energy, downloading and processing the time series data for sources like wind and solar from the NASA POWER project website.Results.py
: Manages the formatting and storage of the model’s outcomes, preparing them for analysis or reporting purposes.tmpjvcss8hv.pyomo.lp
: An intermediary file that represents the linear programming formulation of the model, useful for debugging or in-depth examination by developers.
In the forthcoming sections, we will explore in detail the functionalities and significance of each module, offering insights into their contributions to the model’s optimization mechanism.
Model Creation Module
The Model_Creation
module is where the MicroGridsPy’s model components are defined and structured. It lays down the framework of parameters, sets, and variables, which are crucial for the optimization process.
Parameters
The module begins by importing necessary Pyomo classes and initialization functions from an external Initialize.py
module:
from pyomo.environ import Param, RangeSet, Any, NonNegativeReals, NonNegativeIntegers, Var, Set, Reals, Binary
from Initialize import *
The Model_Creation
function then initializes a series of parameters. Parameters in Pyomo are symbolic representations of values that define the characteristics of the optimization model. They can be mutable or immutable and can be indexed to represent arrays of parameters.
def Model_Creation(model):
#%% PARAMETERS
##############
# RES Time Series Estimation parameters
model.base_URL= Param(within=Any)
model.loc_id = Param(within=Any)
# ...
# Several other parameters follow here
# Project parameters
model.Periods = Param(within=NonNegativeIntegers)
# ...
# Additional project parameters follow
Sets
After defining parameters, the module creates several sets. Sets are collections of objects, often numbers or strings, that index the model’s variables and constraints. For instance, the periods set ranges from 1 to the number of periods in each year:
#%% Sets
#########
model.periods = RangeSet(1, model.Periods)
# ... additional sets follow
Variables
Variables represent the decision variables of the optimization problem. In this module, variables are defined for each component of the energy system, such as the units of renewable energy sources (RES), the energy production from RES, the state of charge (SOC) for batteries, and the energy produced by diesel generators.
#%% VARIABLES
#############
# Variables associated with the RES
model.RES_Units = Var(model.steps, model.renewable_sources, within=NonNegativeReals)
# ... additional variables follow
Example Usage
Here’s an example of how a developer might utilize this module to set up an optimization model for a mini-grid:
from pyomo.environ import ConcreteModel
from Model_Creation import Model_Creation
# Create a Pyomo model instance
model = ConcreteModel()
# Call the Model_Creation function to set up the model
Model_Creation(model)
# The model is now ready to be populated with data and solved.
Insights
The Model_Creation
encapsulates the essence of the system being modeled, from the estimation of renewable energy production and demand to the detailed configurations of the project itself.
By structuring the model in this way, MicroGridsPy ensures that the optimization framework is robust, extendable, and maintainable. It also encapsulates complex optimization features like multi-objective optimization and MILP formulations, making it a powerful tool for energy system optimization.
Initialization Module
The Initialize
module in MicroGridsPy sets the stage for the entire optimization model. It is responsible for parsing input data, initializing model parameters, defining sets, and creating the initial conditions required for the optimization process to commence.
Parsing Input Data
Input data is parsed from various CSV files and the Parameters.dat file, which include essential data such as scenarios, periods, years, and generator types.
# Example of parsing Scenarios, Periods, Years from Parameters.dat
n_scenarios = int((re.findall('\d+',Data_import[i])[0]))
n_years = int((re.findall('\d+',Data_import[i])[0]))
n_periods = int((re.findall('\d+',Data_import[i])[0]))
# ... and more
Initializing Parameters
Parameters are defined using the parsed data. These parameters serve as constants throughout the model and influence the optimization’s behavior and outcomes.
# Example of defining parameters for Scenarios and Periods
scenario = [i for i in range(1,n_scenarios+1)]
period = [i for i in range(1,n_periods+1)]
# ... and more
Defining Investment Steps
The module calculates the number of investment steps and assigns each year to its corresponding step. This is crucial for models that incorporate multi-year capacity expansion.
def Initialize_Upgrades_Number(model):
# ... logic to determine the number of upgrades
return int(n_upgrades)
Creating Multi-Indexed DataFrames
Multi-indexed DataFrames are created for time-series data such as demand and renewable energy output. These DataFrames facilitate the handling of time-dependent data in the model.
# Example of creating a Multi-indexed DataFrame for Energy Demand
frame = [scenario,year,period]
index = pd.MultiIndex.from_product(frame, names=['scenario','year','period'])
Energy_Demand.index = index
# ... and more
Setting Up Initialization Functions
Initialization functions are defined for various model components such as demand, renewable energy production, and grid availability. These functions are used during the model creation phase to populate the model with data.
def Initialize_Demand(model, s, y, t):
return float(Energy_Demand[0][(s,y,t)])
# ... more initialization functions
Grid Connection and Availability
The module also deals with the grid connection, including setting up parameters for grid investment costs, operation, and maintenance costs, as well as determining grid availability.
if Grid_Availability_Simulation:
grid_avail(average_n_outages, average_outage_duration, n_years, year_grid_connection,n_scenarios, n_periods)
# ... and more
The Initialize
module provides a comprehensive setup for the optimization model, ensuring that all necessary data is loaded and parameters are set before the optimization begins. It acts as the preparatory stage, converting raw data into a structured format that the model can interpret and utilize. This module underscores the importance of initial conditions in the optimization process and ensures that the model’s execution is based on accurate and up-to-date information.
Demand Module
The Demand
module is tasked with the generation of load curves for the MicroGridsPy model. It leverages a data-driven approach, utilizing predefined archetypes that reflect the energy consumption patterns of different household tiers and service structures.
Importing Data
Data importation is the first step in the load curve generation process. The module reads key parameters such as latitude, cooling periods, and household tiers from a Parameters.dat file. These parameters are crucial for selecting the correct archetype for demand calculation.
# Example of how the latitude parameter is used to determine the geographical zone archetype
if "param: lat" in value:
lat = (value[value.index('=')+1:value.index(';')])
# ... rest of the code
if 10 <= lat <=20:
F = 'F1'
# ... other conditions
Demand Calculation
With the parameters set, the demand_calculation function computes the demand for each household tier and service. It aggregates hourly loads according to the defined periods to align with the model’s time resolution.
# Code snippet showing the aggregation of load data
def aggregate_load(load_data, periods):
# ... aggregation logic
return aggregated_load
Household and Service Classes
Two classes, household and service, encapsulate the logic for calculating the load demands for households and services respectively. These classes take the number of entities and their respective archetypes to output the demand.
class household:
# ... class methods
def load_demand(self, h_load):
load = self.number/100 * h_load
return load
class service:
# ... class methods
Load Profile Generation
The module generates a load profile for the specified number of years by combining the demand from all households and services. It accounts for annual demand growth to reflect the changes over the project’s lifespan.
# Example of how load profiles are generated and grown annually
for column in load_total:
if column == 0:
continue
else:
load_total[column] = load_total[column-1]*(1+demand_growth/100)
Exporting Results
Once the load curves are computed, the excel_export function exports the data to a CSV file, which will be used as input for the optimization model.
# Exporting the DataFrame to a CSV file
def excel_export(load, years):
# ... export logic
Execution
The module concludes with the demand_generation function, which executes the demand calculation and exports the final load curves. This function also prints out the time taken to perform the calculations.
def demand_generation():
# ... generation logic
print("Load demand calculation started...")
# ... more logic
print('\n\nLoad demand calculation completed...')
Module Execution
The Demand.py module can be run as a standalone script to generate demand profiles. However, in the context of MicroGridsPy, it is typically called during the model setup phase.
Insights
The demand generation process within MicroGridsPy is a sophisticated sequence that simulates realistic energy consumption patterns based on various factors. This module’s output provides a crucial input for the optimization model, enabling it to make informed decisions about energy resource allocation and system design.
RES Time Series Estimation Module
Introduction
The RES Time Series Estimation module is a core component of the MicroGridsPy framework. It is designed to accurately estimate solar and wind energy potential using data from NASA’s POWER API. This module processes and interpolates the collected data to create a representative Typical Meteorological Year (TMY) for energy modeling.
Data Collection and URL Generation
The module starts by importing necessary parameters, including geographical coordinates and technological specifications. It constructs URLs for accessing NASA’s POWER API data, tailored for both daily and hourly resolutions.
# Sample function to create API URLs
def URL_creation_d(Data_import):
# Logic to construct daily and hourly data URLs
return URL_1, URL_2
Data Processing and Interpolation
After data retrieval, the module processes the JSON responses. Bilinear interpolation is applied to estimate relevant daily and hourly parameters such as temperature, wind speed, and solar irradiance.
# Function for data processing and interpolation
def data_2D_interpolation(jsdata, ...):
# Bilinear interpolation logic for daily and hourly data
return param_daily_interp, param_hourly_interp
Typical Meteorological Year (TMY) Calculation
One of the module’s key functions is to compute a TMY, using statistical methods to select the most representative year from the historical data.
# Function to determine the TMY
def typical_year_daily(param_daily, ...):
# Statistical analysis for TMY calculation
return best_years, param_typical_daily
RES Calculation Module
The module calculates the potential energy supply from solar and wind resources. It includes specific algorithms to determine solar irradiation on tilted surfaces and to estimate wind turbine electricity production.
# Solar energy calculation function
def hourly_solar(H_day, lat, ...):
# Solar irradiation estimation logic
# Wind energy production function
def P_turb(power_curve, ...):
# Wind turbine energy calculation logic
Data Export
The final step involves aggregating the estimated data and exporting it to CSV format for further analysis and optimization within MicroGridsPy.
# Function for data export
def export(energy_PV, ...):
# Data aggregation and export logic
Insights
The RE_calculation.py module exemplifies the comprehensive approach of MicroGridsPy in modeling renewable energy systems. Its accurate data processing and analysis capabilities are pivotal in optimizing microgrid solutions.