• Energy

Vattenfall: Quantum Optimisation for Offshore Wind Farm Layout

Vattenfall

Vattenfall applied quantum optimisation to offshore wind turbine placement, formulating the layout problem as a QUBO to maximise energy yield while minimising wake interference across its North Sea portfolio.

Key Outcome
QAOA solutions for 24-turbine layout problems matched classical MILP solvers with 35% fewer solver iterations, demonstrating viable near-term quantum application for renewable energy infrastructure planning.

The Challenge

Offshore wind farm layout optimisation is one of the most computationally demanding problems in renewable energy project development. Vattenfall, a major operator across the North Sea, faces this challenge at scale: each new offshore wind project requires selecting turbine positions from a discretised grid of candidate locations while managing wake interactions, seabed constraints, environmental exclusion zones, and grid connection costs.

The wake interference problem is particularly acute. A turbine positioned in the wind shadow of an upstream turbine can experience power losses of 10 to 40% depending on wind direction and turbine spacing. Across an offshore array of dozens of turbines, cumulative wake losses directly reduce the project’s annual energy production and therefore its financial return. Classical solvers including mixed-integer linear programming and evolutionary algorithms can find good layouts for small farms, but solution quality degrades as problem size grows because the combinatorial search space grows factorially.

Vattenfall’s digital innovation team partnered with quantum computing researchers to test QAOA as an alternative optimisation approach, initially targeting 24-turbine subproblems drawn from real project geometries in the Vattenfall Hollandse Kust Noord portfolio.

The Quantum Approach

The turbine placement problem was encoded as a quadratic unconstrained binary optimisation. For a grid of MM candidate positions, binary variable xi{0,1}x_i \in \{0, 1\} indicates whether a turbine is placed at position ii. The objective combined a wake penalty matrix (computed using the Park/Jensen wake model) with a cardinality constraint enforcing exactly NN turbines placed.

QAOA circuits were constructed using Qiskit with p=3p = 3 layers (three alternating cost and mixer unitaries), optimised using COBYLA on a classical co-processor. The 24-variable QUBO mapped to 24 qubits, within the range of IBM Quantum’s 27-qubit Falcon processors with sufficient connectivity.

import numpy as np
from qiskit_optimization import QuadraticProgram
from qiskit_optimization.converters import QuadraticProgramToQubo
from qiskit_algorithms import QAOA
from qiskit_algorithms.optimizers import COBYLA
from qiskit.primitives import Sampler

# Wake penalty matrix: entry [i,j] is the fractional power loss at turbine j
# when turbine i is upwind, averaged over the wind rose.
# Shape: (24, 24), precomputed with Jensen wake model.
wake_penalty = np.load("wake_penalty_24.npy")

N_POSITIONS = 24
N_TURBINES = 12  # place 12 turbines from 24 candidate positions

qp = QuadraticProgram("vattenfall_layout")

for i in range(N_POSITIONS):
    qp.binary_var(name=f"x_{i}")

# Objective: minimise total wake loss across all turbine pairs
linear_terms = {}
quadratic_terms = {}

for i in range(N_POSITIONS):
    for j in range(N_POSITIONS):
        if i != j and wake_penalty[i, j] > 0.01:
            key = (f"x_{i}", f"x_{j}")
            quadratic_terms[key] = quadratic_terms.get(key, 0) + wake_penalty[i, j]

qp.minimize(linear=linear_terms, quadratic=quadratic_terms)

# Cardinality constraint: exactly N_TURBINES turbines
qp.linear_constraint(
    linear={f"x_{i}": 1 for i in range(N_POSITIONS)},
    sense="==",
    rhs=N_TURBINES,
    name="cardinality",
)

# Convert to QUBO for QAOA
converter = QuadraticProgramToQubo()
qubo = converter.convert(qp)

# Run QAOA with p=3 layers
sampler = Sampler()
optimizer = COBYLA(maxiter=300)
qaoa = QAOA(sampler=sampler, optimizer=optimizer, reps=3)

from qiskit_optimization.algorithms import MinimumEigenOptimizer
solver = MinimumEigenOptimizer(qaoa)
result = solver.solve(qubo)

placement = [i for i, val in enumerate(result.x) if val > 0.5]
print(f"Turbines placed at: {placement}")
print(f"Objective (wake loss): {result.fval:.4f}")

QAOA iteration counts were compared against a commercial MILP solver (Gurobi) running on the same QUBO formulation, with both solvers run until they reached the same objective value tolerance.

Results and Implications

For 24-turbine layout problems, QAOA matched the solution quality of the classical MILP solver while requiring 35% fewer solver iterations to converge to within 2% of the optimal objective value. The advantage was attributed to QAOA’s ability to explore multiple candidate solutions simultaneously through quantum superposition, allowing it to escape local optima that trapped the classical branch-and-bound search.

Annual energy production estimates for the quantum-optimised layouts were on average 1.8% higher than layouts produced by the classical solver within the same iteration budget, corresponding to meaningful additional revenue across a 25-year project lifetime. For a 400 MW offshore wind farm, a 1.8% AEP improvement represents several million euros of additional lifetime revenue.

Vattenfall identified 24-turbine subproblems as within current quantum hardware capability, but noted that full commercial farms (80 to 150 turbines) require decomposition into overlapping subproblems with coordination between subproblem solutions. The team is developing a divide-and-coordinate framework where QAOA solves local layout subproblems and classical post-processing stitches them together, targeting deployment readiness when fault-tolerant hardware supporting 100+ logical qubits becomes available.