Size and optimize
hybrid microgrids in Python
Py-Microgrid co-optimizes solar PV, wind, battery storage, and gensets against a real load profile. It returns the least-cost system that meets your demand, with full LCOE, net present cost, and CO₂ analysis.
PV · wind · battery · genset
LCOE · NPC · CO₂
predictive flexible dispatch
multi-location batching
Everything you need to design a microgrid
From resource data to a fully costed, dispatched system, all in one toolkit.
System optimization
Search component sizes against bounds and let the optimizer return the least-cost configuration that meets your load.
- Multi-objective sizing
- PV, wind, battery & genset
- Bounded search ranges
Predictive battery dispatch
Look-ahead dispatch with optional flexible load shifting that cuts peak demand by up to 20% where the schedule allows.
- Look-ahead scheduling
- Flexible-load shifting
- Grid-charging control
Economic analysis
Every run reports levelized cost of energy, net present cost, and CO₂ emissions over the full project lifetime.
- LCOE ($/kWh)
- Net present cost
- CO₂ emissions
Multi-location batching
Loop over any number of sites, pulling location-specific solar and wind resource data for side-by-side comparison.
- Batch optimization
- Per-site resource data
- Comparative results
HOPP integration
Built directly on NREL's HOPP framework, so simulations use the same validated performance and weather models.
- NREL resource data
- Validated weather models
- Hourly simulation
YAML configuration
Define sites, technologies, and dispatch options in one readable YAML file. Re-run a study without touching code.
- Single config file
- Readable & versionable
- Reproducible runs
A few lines to a costed system
The real package API. Copy, paste, and adapt.
from py_microgrid.utilities.keys import set_developer_nrel_gov_key
from py_microgrid.simulation.resource_files import ResourceDataManager
from py_microgrid.tools.optimization import SystemOptimizer
from py_microgrid.tools.analysis.bos import EconomicCalculator
# Set your free NREL API key (https://developer.nrel.gov/signup/)
set_developer_nrel_gov_key('your_api_key_here')
# Download solar and wind resource data for the site
resources = ResourceDataManager()
resources.download_solar_data(lat=-33.5265, lon=149.1588)
resources.download_wind_data(lat=-33.5265, lon=149.1588)
# Configure the economic model
economics = EconomicCalculator(discount_rate=0.0588, project_lifetime=25)
# Initialise the optimizer with predictive, flexible-load dispatch
optimizer = SystemOptimizer(
yaml_file_path='config/site_config.yaml',
economic_calculator=economics,
enable_flexible_load=True,
max_load_reduction_percentage=0.2,
)
# Search ranges per component
bounds = [
(5000, 50000), # PV capacity (kW)
(1, 50), # Number of wind turbines
(5000, 30000), # Battery energy (kWh)
(1000, 10000), # Battery power (kW)
(17000, 30000), # Genset capacity (kW)
]
initial = [[b[0] + (b[1] - b[0]) * 0.1 for b in bounds]]
# Run the optimization
result = optimizer.optimize_system(bounds, initial)
print(f"LCOE: ${result['System LCOE ($/kWh)']:.4f}/kWh")
print(f"System NPC: ${result['System NPC ($)']:,.2f}")
print(f"Demand met: {result['Demand Met Percentage']:.2f}%")
from py_microgrid.utilities import ConfigManager
from py_microgrid.simulation.resource_files import ResourceDataManager
from py_microgrid.tools.optimization import SystemOptimizer
from py_microgrid.tools.analysis.bos import EconomicCalculator
# Sites to evaluate
sites = [
{'name': 'Bathurst', 'lat': -33.5265, 'lon': 149.1588},
{'name': 'Broken Hill', 'lat': -31.9550, 'lon': 141.4540},
{'name': 'Darwin', 'lat': -12.4634, 'lon': 130.8456},
]
economics = EconomicCalculator(discount_rate=0.0588, project_lifetime=25)
bounds = [(5000, 50000), (1, 50), (5000, 30000), (1000, 10000), (17000, 30000)]
initial = [[b[0] + (b[1] - b[0]) * 0.1 for b in bounds]]
results = {}
for site in sites:
# Pull resource data for this location
resources = ResourceDataManager()
resources.download_solar_data(lat=site['lat'], lon=site['lon'])
resources.download_wind_data(lat=site['lat'], lon=site['lon'])
# Point the config at this location
config = ConfigManager('config/site_config.yaml')
data = config.load_yaml_safely()
data['site']['data']['lat'] = site['lat']
data['site']['data']['lon'] = site['lon']
config.save_yaml_safely(data)
optimizer = SystemOptimizer(
yaml_file_path='config/site_config.yaml',
economic_calculator=economics,
)
results[site['name']] = optimizer.optimize_system(bounds, initial)
# Compare LCOE across sites
for name, r in results.items():
print(f"{name:12s} LCOE=${r['System LCOE ($/kWh)']:.4f}/kWh "
f"demand met={r['Demand Met Percentage']:.1f}%")
# site_config.yaml
site:
data:
lat: -33.5265 # site latitude
lon: 149.1588 # site longitude
solar_resource_file: "" # auto-filled by ResourceDataManager
wind_resource_file: ""
grid_resource_file: ""
desired_schedule: "" # hourly load profile, kW
technologies:
pv:
system_capacity_kw: 10000
wind:
num_turbines: 5
battery:
system_capacity_kwh: 10000
system_capacity_kw: 2000
grid:
interconnect_kw: 20000
Install in three steps
Up and running on Python 3.10 or 3.11 in a few minutes.
Install dependencies
pip install HOPP
conda install -c conda-forge glpk coin-or-cbc -y
Clone the repository
git clone https://github.com/Hanrong-Huang/Py-Microgrid.git
cd Py-Microgrid
Add your NREL API key
# Get a free key: https://developer.nrel.gov/signup/
# Then in Python:
# from py_microgrid.utilities.keys import set_developer_nrel_gov_key
# set_developer_nrel_gov_key('your_api_key_here')