Skip to content

Repository files navigation

🌿 Green Hydrogen Plant Siting Optimization

Geospatial MCDA pipeline for identifying globally optimal green Hβ‚‚ production sites

CI Python 3.10+ License: MIT PRs Welcome


Overview

Green hydrogen (Hβ‚‚) produced via renewable-powered electrolysis is a cornerstone technology for decarbonizing hard-to-abate sectors β€” shipping, steel, ammonia, and long-haul transport. However, site selection is the most capital-sensitive decision in project development. An optimally sited plant can achieve a Levelized Cost of Hydrogen (LCOH) 30–50% lower than a poorly sited one, driven by differences in capacity factors, water availability, grid connection cost, and logistics.

This tool implements a Multi-Criteria Decision Analysis (MCDA) geospatial pipeline that:

  1. Ingests global renewable energy, water stress, and infrastructure datasets
  2. Scores every point on a configurable candidate grid using weighted multi-criteria analysis
  3. Ranks and spatially deduplicates the top-N sites globally or regionally
  4. Outputs an interactive HTML map with popup cards, heatmap overlay, and tier classification

Key output: A ranked GeoDataFrame + self-contained interactive HTML map deployable as a static website.


Architecture

Raw Data Sources
β”œβ”€β”€ Global Solar Atlas (GeoTIFF)    ─┐
β”œβ”€β”€ Global Wind Atlas (GeoTIFF)      β”œβ”€β–Ί RasterLoader ─► Solar/Wind CF scores
└── WRI Aqueduct (GeoTIFF)          β”€β”˜

β”œβ”€β”€ OpenStreetMap Ports (GeoJSON)   ─┐
└── OpenStreetMap Grid (GeoJSON)    ─┴─► VectorLoader ─► Proximity scores

All criteria ─► MCDAScorer (normalize + weight) ─► Composite scores [0, 1]
             ─► SiteRanker (spatial dedup)       ─► Top-N GeoDataFrame
             ─► H2SiteMapBuilder                 ─► Interactive HTML map

Module layout:

src/h2_siting/
β”œβ”€β”€ ingestion/
β”‚   β”œβ”€β”€ raster_loader.py   GeoTIFF sampling at candidate grid points
β”‚   └── vector_loader.py   Port/grid proximity via cKDTree
β”œβ”€β”€ scoring/
β”‚   β”œβ”€β”€ criteria.py        Min-max, z-score, rank normalization
β”‚   └── mcda.py            WSM, TOPSIS, VIKOR aggregation
β”œβ”€β”€ optimization/
β”‚   └── site_ranker.py     Candidate grid generation, greedy spatial dedup
β”œβ”€β”€ visualization/
β”‚   └── map_builder.py     Folium interactive HTML map
└── pipeline.py            Click CLI entry point

Criteria & Weights

Criterion Weight Direction Data Source Rationale
Solar Capacity Factor 0.25 Maximize Global Solar Atlas Primary renewable energy driver for LCOH
Wind Capacity Factor 0.20 Maximize Global Wind Atlas Complementary to solar; hybrid plants preferred
Water Stress 0.25 Minimize WRI Aqueduct Electrolysis requires ~9–15 L Hβ‚‚O per kg Hβ‚‚
Port Proximity 0.15 Maximize OpenStreetMap Export logistics for NH₃ / LOHC / liquid Hβ‚‚
Grid Proximity 0.15 Maximize OpenStreetMap HV grid connection cost (dominant CAPEX item)

Weights are fully configurable in config/default_weights.yaml. Total must sum to 1.0.


MCDA Methods

Three aggregation methods are available. Select via --method or edit config/default_weights.yaml.

Method Formula When to use
Weighted Sum (WSM) score = Ξ£(wα΅’ Γ— normα΅’) Default. Fast, interpretable, good for initial screening
TOPSIS Closeness to positive ideal / away from negative ideal Compensatory; balances across all criteria simultaneously
VIKOR Compromise ranking minimizing regret and utility gap When stakeholders disagree on weights; produces consensus ranking

For most Hβ‚‚ siting applications, WSM provides sufficient accuracy. Use TOPSIS when comparing finalists across a shortlist. Use VIKOR for multi-stakeholder decision processes.


Quick Start

# 1. Clone the repository
git clone https://github.com/IsaH93/green-h2-siting.git
cd green-h2-siting

# 2. Install dependencies
pip install -e "."
pip install -r requirements-dev.txt

# 3. Generate synthetic sample data
make sample
# or: python scripts/generate_sample_data.py

# 4. Run the full pipeline on sample data
make run
# or: h2-siting run --config config/default_weights.yaml --output outputs/h2_sites_map.html

# 5. Open the interactive map
open outputs/h2_sites_map.html   # macOS
xdg-open outputs/h2_sites_map.html   # Linux

To run over Europe only:

h2-siting run --bbox "-10,35,40,70" --resolution 0.5 --method topsis --output outputs/europe.html

Data Sources

Download real data and place in data/raw/:

Dataset Format Resolution Download URL
Global Solar Atlas (capacity factor) GeoTIFF 250m https://globalsolaratlas.info/download
Global Wind Atlas (capacity factor) GeoTIFF 250m https://globalwindatlas.info/downloads/gis-files
WRI Aqueduct Baseline Water Stress GeoTIFF 500m https://www.wri.org/data/aqueduct-global-maps-30-data
World Port Index (ports) CSV/GeoJSON Point https://msi.nga.mil/Publications/WPI
OSM High-Voltage Grid (lines) GeoJSON Line https://osmdata.openstreetmap.de/

For quick testing without downloading, use make sample to generate synthetic proxy data.


Configuration

All pipeline parameters are controlled by config/default_weights.yaml:

criteria:
  solar_capacity_factor:
    weight: 0.25          # contribution to composite score (all weights must sum to 1.0)
    direction: maximize   # 'maximize' = higher raw value β†’ higher score
                          # 'minimize' = lower raw value β†’ higher score (e.g., water stress)

scoring:
  normalization: min_max  # 'min_max' | 'z_score' | 'rank'
  aggregation: weighted_sum  # 'weighted_sum' | 'topsis' | 'vikor'

output:
  top_n_sites: 50                      # number of candidate sites in output
  map_zoom_start: 3                    # initial Folium map zoom level
  candidate_grid_resolution_deg: 0.5  # grid spacing (~55km at equator)

Normalization methods:

  • min_max β€” scales each criterion to [0, 1] range. Best for bounded inputs (capacity factors).
  • z_score β€” standardizes to mean=0, std=1, clips at Β±3Οƒ, then rescales. Better for skewed distributions.
  • rank β€” converts to percentile ranks. Robust to outliers; good for water stress data.

CLI Reference

h2-siting [OPTIONS] COMMAND [ARGS]

Options:
  -v, --verbose   Enable debug logging

Commands:
  run    Run the full siting optimization pipeline
  info   Display configuration summary

h2-siting run [OPTIONS]

  --config, -c  PATH    YAML config file [default: config/default_weights.yaml]
  --data-dir, -d PATH   Directory with input rasters and vectors [default: data/sample]
  --output, -o PATH     Output HTML map path [default: outputs/h2_sites_map.html]
  --bbox TEXT           Bounding box: min_lon,min_lat,max_lon,max_lat [default: global]
  --resolution FLOAT    Grid resolution in degrees (overrides config)
  --top-n INT           Number of top sites (overrides config)
  --method CHOICE       weighted_sum | topsis | vikor (overrides config)

Examples:

# Global run (slow β€” ~500k points at 0.5Β°)
h2-siting run --output outputs/global_map.html

# Europe at 1Β° resolution
h2-siting run --bbox "-15,30,45,72" --resolution 1.0 --output outputs/europe_1deg.html

# MENA region with TOPSIS
h2-siting run --bbox "-20,10,65,40" --method topsis --top-n 30 --output outputs/mena.html

# Azerbaijan / Caspian region (SOCAR focus area)
h2-siting run --bbox "40,35,55,45" --resolution 0.25 --output outputs/caspian.html

Project Structure

green-h2-siting/
β”œβ”€β”€ .github/workflows/ci.yml     GitHub Actions: test + Docker build
β”œβ”€β”€ config/default_weights.yaml  MCDA criteria weights and scoring config
β”œβ”€β”€ data/
β”‚   β”œβ”€β”€ raw/                     Real datasets (gitignored β€” user provides)
β”‚   β”œβ”€β”€ processed/               Intermediate outputs (gitignored)
β”‚   └── sample/                  Synthetic test data (committed)
β”œβ”€β”€ notebooks/
β”‚   β”œβ”€β”€ 01_data_exploration.ipynb    Raster/vector EDA and QA
β”‚   β”œβ”€β”€ 02_scoring_analysis.ipynb   MCDA run, method comparison, correlation
β”‚   └── 03_results_visualization.ipynb  Map, bar chart, radar, sensitivity
β”œβ”€β”€ outputs/                     Generated maps and figures (gitignored)
β”œβ”€β”€ scripts/
β”‚   └── generate_sample_data.py  Generates synthetic data/sample/ files
β”œβ”€β”€ src/h2_siting/
β”‚   β”œβ”€β”€ ingestion/               Raster + vector data loading
β”‚   β”œβ”€β”€ scoring/                 Normalization + MCDA engines
β”‚   β”œβ”€β”€ optimization/            Candidate grid + site ranking
β”‚   β”œβ”€β”€ visualization/           Folium map builder
β”‚   └── pipeline.py              CLI entry point
β”œβ”€β”€ tests/                       pytest test suite
β”œβ”€β”€ Dockerfile                   Production container
β”œβ”€β”€ docker-compose.yml           One-command Docker run
β”œβ”€β”€ Makefile                     Development shortcuts
β”œβ”€β”€ pyproject.toml               Package metadata + tool config
└── requirements.txt / requirements-dev.txt

Development

# Install dev dependencies
make install-dev

# Run tests
make test

# Run tests with HTML coverage report
make test-cov

# Lint (flake8 + mypy)
make lint

# Auto-format (black)
make format

Docker:

# Build and run via Docker Compose
docker compose up --build

# Or manually
docker build -t h2-siting:latest .
docker run -v $(pwd)/data:/app/data -v $(pwd)/outputs:/app/outputs \
  h2-siting:latest run --config config/default_weights.yaml

Results Interpretation

The output HTML map contains:

  • Heatmap layer: background color gradient showing composite suitability across all candidate points
  • Marker cluster layer: top-N sites as interactive circles; zoom in to expand clusters
  • Popup cards: click any marker for rank, score, lat/lon, and per-criterion breakdown
  • Legend: score tier classification in bottom-left corner

Score Tiers:

Tier Score Range Color Interpretation
1 β€” Excellent β‰₯ 0.80 Green Proceed to prefeasibility study
2 β€” Good 0.65–0.80 Light green Strong candidate; validate water access
3 β€” Moderate 0.50–0.65 Yellow Viable with mitigation measures
4 β€” Marginal 0.35–0.50 Orange High risk; single-criterion bottleneck likely
5 β€” Poor < 0.35 Red Not recommended

Important: Scores are relative rankings within the input dataset, not absolute suitability scores. Always validate top-ranked sites with local data (land use, social license, permitting constraints).


Roadmap

  • Land use mask: Exclude protected areas (WDPA), urban zones, and water bodies using OSM/WDPA polygons
  • Country attribution: Auto-assign ISO 3166 country codes to all ranked sites using Natural Earth
  • LCOH overlay: Integrate simplified LCOH model (electrolyzer CAPEX Γ— CF + OPEX) per site
  • Demand proximity: Add nearest industrial cluster / demand center as a criterion
  • Desalination bonus: Flag coastal sites where seawater desalination can offset freshwater stress
  • REST API endpoint: FastAPI wrapper for programmatic scoring of arbitrary coordinates
  • Export formats: GeoPackage, Shapefile, KML output options
  • Multi-scenario comparison: Side-by-side map view for different weight configurations

License

MIT License β€” Copyright (c) 2026 Isa Hasanov

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.


Built by Isa Hasanov β€” Innovation Manager, SOCAR

About

Geospatial MCDA pipeline (WSM/TOPSIS/VIKOR) for siting green hydrogen plants

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages