Skip to content

Navigation Menu

Sign in
Sign up

Repository files navigation

Probabilistic PV Hosting Capacity Assessment

Spatially and temporally correlated uncertainty, autonomous inverter control and active distribution network operation in a real SimBench low-voltage grid.

Python uv License


1 Motivation

The maximum photovoltaic (PV) capacity a low-voltage (LV) feeder can accommodate is classically determined deterministically: PV is scaled uniformly across all customers, one worst-case day is simulated, and the capacity at which the first limit is violated is declared the hosting capacity. That procedure answers a question nobody asks in practice. Real PV fleets grow where individual customers decide to invest, with heterogeneous system sizes, different orientations, single- or three-phase connections, and they operate under weather that is strongly correlated in space and time. A number that assumes all of this away cannot state how likely a violation is, how severe it would be, where and when it occurs, or which limit binds first.

This repository implements a probabilistic assessment that answers those questions on a real SimBench LV grid, and quantifies how much additional capacity autonomous inverter control and active network operation unlock — including their cost, their losses and whether the resulting curtailment is distributed fairly.

Origin

The study is a from-scratch reimplementation of the author's earlier work on probabilistic hosting capacity:

S. Kortmann, X. Han, M. Schwarz and G. Hug, "From a distributing to a generating network: Assessing PV hosting capacity under uncertainty in distribution grids", PESS 2021; Power and Energy Student Summit, 2021, pp. 1–6. IEEE Xplore 9735254

That paper motivated this repository. The reimplementation goes beyond it in four respects: uncertainty is spatially and temporally correlated through an explicit latent Gaussian model rather than sampled independently; phase imbalance is modelled physically with unbalanced three-phase power flow instead of a balanced approximation; curtailment fairness is quantified alongside efficiency; and every assumption, confidence interval and unsupported risk level is machine-recorded so a result can be traced back to what produced it.

2 Research questions

  1. How does deterministic PV hosting capacity differ from probabilistic hosting capacity?
  2. How strongly does uncertain spatial PV allocation affect hosting capacity?
  3. How strongly do temporal and spatial correlations affect the result compared with independent sampling?
  4. Which technical constraint is limiting — overvoltage, undervoltage, line loading, transformer loading, voltage unbalance, or non-convergence?
  5. How much can autonomous inverter control increase hosting capacity?
  6. How much additional capacity is enabled by OLTC operation and coordinated curtailment?
  7. What are the associated network losses, curtailed energy, reactive-power demand, tap operations, intervention costs and fairness impacts?
  8. Does a balanced power-flow analysis systematically over- or underestimate hosting capacity compared with an unbalanced three-phase analysis?
  9. Which buses have the greatest marginal impact on voltage and loading?
  10. How stable is the estimated hosting capacity with respect to Monte Carlo sample size?

Hypotheses

# Hypothesis
H1 Deterministic uniform PV scaling does not adequately represent hosting capacity under uncertain spatial PV allocation.
H2 Neglecting temporal and spatial correlation produces materially different risk estimates.
H3 Local Q(U) control increases hosting capacity but can increase reactive-power flows and losses.
H4 Coordinated operation of Q(U), OLTC and curtailment provides a larger increase than each individual measure.
H5 A small amount of targeted curtailment can generate a disproportionate capacity increase.
H6 Sensitivity-based curtailment minimises total curtailed energy but can distribute curtailment unfairly.
H7 A fairness-aware curtailment policy can reduce inequality with a limited efficiency penalty.
H8 Balanced analysis can conceal phase-specific voltage and loading violations.
H9 Electrical distance alone is not sufficient to explain the marginal network impact of PV at a bus.

Each hypothesis is evaluated against an explicit numerical criterion in reports/study_report.md and reported as supported, partially supported or not supported, together with the numbers that led to the verdict. Nothing is asserted that the generated tables do not support.

3 Mathematical definitions

Hosting capacity

definition formulation
deterministic $P^{\mathrm{det}}_{\mathrm{HC}} = \max\{P : \mathcal{V}(P) = 0\}$
joint chance constrained $P^{\epsilon}_{\mathrm{HC}} = \max\{P : \Pr[\mathcal{V}(P,\omega) > 0] \le \epsilon\}$
severity constrained $P^{R}{\mathrm{HC}} = \max\{P : \mathrm{CVaR}{\alpha}(S(P,\omega)) \le R_{\max}\}$
conservative as chance constrained, but the upper confidence bound of the estimated probability must satisfy the limit

$\mathcal{V}$ is the system-level violation event over all buses, phases, branches and time steps. A capacity is never declared acceptable because a small sample happened to produce few violations; risk levels the sample cannot resolve ($n < 3/\epsilon$, rule of three) are flagged as unsupported rather than reported as results.

The violation event includes a curtailment budget. Under unrestricted curtailment the hosting capacity of any curtailment strategy is unbounded — arbitrarily much PV can be installed and then thrown away, which is mathematically true and practically meaningless. An operating point that curtails more than limits.max_curtailment_share of the available PV energy therefore counts as violated. The default of 3 % follows the share of annual generation that German feed-in management may curtail without compensation; it is a regulatory-practice assumption, is reported as its own violation type (curtailment_budget), and can be disabled — in which case the unboundedness is visible in the results rather than hidden.

Violation severity

$$\Delta V^{+}_{i,\phi,t} = \max(0, V_{i,\phi,t}-V_{\max}), \qquad \Delta V^{-}_{i,\phi,t} = \max(0, V_{\min}-V_{i,\phi,t}), \qquad \Delta L_{e,\phi,t} = \max(0, L_{e,\phi,t}-100,%)$$

integrated over time into p.u.-hours, percentage-point-hours and VUF-hours. Power-flow non-convergence is a separate outcome class, never silently converted into "feasible".

Uncertainty model

A latent Gaussian field with a grid-wide, a spatially correlated and an individual component, each stationary AR(1) in time:

$$\epsilon_{i,t} = a,G_t + b,S_{i,t} + c,I_{i,t}, \qquad x_t = \rho x_{t-1} + \sqrt{1-\rho^2},\eta_t, \qquad \Sigma_{ij} = \sigma^2 \exp!\left(-\frac{d_{ij}}{\ell}\right)$$

with $d_{ij}$ the length-weighted network distance between connection points. The field is mapped to a strictly positive load multiplier (lognormal, $\mathrm{E}[m]=1$) and a bounded PV availability factor. PV output is

$$P^{\mathrm{PV},s}_{i,t} = P^{s}_{i,\mathrm{nom}}; g_t^{\mathrm{base}}; f_i^{\mathrm{orientation}}; C^{s}_{i,t}, \qquad 0 \le P^{\mathrm{PV},s}_{i,t} \le P^{s}_{i,\mathrm{nom}}$$

Independent white noise exists only as an explicitly labelled reference ensemble used to quantify the effect of neglecting correlation (H2). The correlation structure is validated against its targets before any result is produced, on a dedicated long series — short study windows give strongly biased sample autocorrelations, which is a property of the estimator, not of the generator.

Uncertain PV allocation

Bernoulli adoption $z^s_i \sim \mathrm{Bernoulli}(p_i)$ (uniform or demand weighted), truncated-lognormal system sizes, sampled orientation/yield factors, and — in the default capacity-preserving mode — a rescaling that makes the installed total match the penetration level exactly:

$$\sum_i P^{s,\lambda}_{i,\mathrm{nom}} = \lambda, P_{\mathrm{PV,reference}}$$

so that a capacity sweep isolates the effect of where PV is connected from variation in how much is installed. An unconstrained-adoption mode exists but its results are never mixed with the capacity-preserving analysis.

Three-phase model

Phase imbalance is modelled physically, not by perturbing balanced results: loads and PV systems are assigned to phases and represented by pandapower asymmetric_load / asymmetric_sgen elements, conserving power exactly,

$$P_i = P_{i,a}+P_{i,b}+P_{i,c}, \qquad Q_i = Q_{i,a}+Q_{i,b}+Q_{i,c}$$

and the voltage unbalance factor is evaluated from the sequence voltages, $\mathrm{VUF}{i,t} = |V{2,i,t}|/|V_{1,i,t}| \cdot 100,%$.

SimBench does not ship the data an unbalanced power flow needs. The line standard types contain no zero-sequence parameters, the transformer standard types leave the vector group and the zero-sequence short-circuit data undefined, and pandapower 3.x's tap_changer_type discriminator is absent — which makes pandapower ignore the tap position entirely, so an OLTC controller would run without any effect. The code detects each gap programmatically (network.three_phase_readiness), fills it from explicit, configurable assumptions, records them in network_summary.json and in the report, and then verifies that the unbalanced model reproduces the balanced one for a deliberately symmetric operating point. It never falls back to a balanced solution while labelling the result three-phase.

4 Control strategies

key strategy cos φ(P) Q(U) OLTC curtailment
no_control A: unity power factor, static tap
cosphi_p B: cos φ(P) characteristic
qu C: Q(U) droop with deadband
oltc D: OLTC voltage-band control
fixed_curtailment E: fixed local feed-in cap fixed
prop_curtailment F: proportional coordinated proportional
sens_curtailment G: sensitivity-based (LP) sensitivity
fair_curtailment H: fairness-aware (LP) fairness
coordinated I: Q(U) + OLTC + sensitivity LP sensitivity

Every strategy runs the same deterministic controller sequence — update uncertain load and available PV, autonomous inverter control, OLTC, evaluate remaining violations, coordinated curtailment, re-run the nonlinear AC power flow, evaluate final metrics — so a comparison is never confounded by controller ordering. Inverter capability ($|Q| \le \sqrt{S_r^2-P^2}$ and $\cos\varphi \ge \cos\varphi_{\min}$) is enforced after every control action. Q(U) is iterated with relaxation, and non-convergence or detected oscillation is reported rather than accepted. The coordinated LP solutions are always validated with a nonlinear power flow and re-linearised at the new operating point; infeasibility is reported, not hidden behind a soft penalty.

5 Repository structure

probabilistic-pv-hosting-capacity/
├── configs/
│ ├── demo.yaml # reduced sample counts, short live run
│ ├── research.yaml # larger sample counts, three critical days
│ └── sensitivity.yaml # alternative assumptions (never merged with the above)
├── src/probabilistic_pv_hosting_capacity/
│ ├── config.py # every scientific assumption, validated with pydantic
│ ├── network.py # SimBench selection, sequence-data gaps, distances
│ ├── profiles.py # profile inspection, critical-day selection, reduction
│ ├── uncertainty.py # correlated latent field + uncertain PV fleets
│ ├── phase_allocation.py # phase assignment, asymmetric conversion
│ ├── power_flow.py # templates, unified result, solver backends, benchmarks
│ ├── controls/ # base, no_control, cosphi_p, qu_control, oltc, curtailment
│ ├── violations.py # exceedances, severity, limiting-constraint classification
│ ├── risk.py # probabilities, confidence intervals, CVaR, bootstrap
│ ├── hosting_capacity.py # four definitions, adaptive search, isotonic curve
│ ├── sensitivity.py # finite differences, linear-model validation
│ ├── fairness.py # Jain, Gini, Lorenz, distributional metrics
│ ├── economics.py # illustrative cost model, Pareto frontier
│ ├── simulation.py # Monte Carlo engine, parallelism, caching
│ ├── study.py # campaign orchestration and output writing
│ ├── results.py # run directories and provenance metadata
│ ├── plotting.py # 18 publication figures (RWTH corporate design)
│ ├── reporting.py # study report + figure catalogue, generated from data
│ └── cli.py # `pv-hc` command-line interface
├── tests/ # focused unit tests + an end-to-end campaign test
├── outputs/<run_id>/ # all machine-readable results of a run
└── reports/ # study_report.md, figure_catalog.md

6 Installation

Requires uv and Python ≥ 3.12. No proprietary data and no commercial solver is used; every dependency is open source.

git clone https://github.com/skortmann/probabilistic-pv-hosting-capacity.git
cd probabilistic-pv-hosting-capacity
uv sync

uv.lock pins the exact resolved versions. Do not install packages outside uv.

Optional but recommended. The figures use the rwth-latex style of rwthplots, which typesets all labels with a real LaTeX installation. On Debian/Ubuntu:

sudo apt install texlive-latex-extra texlive-fonts-recommended dvipng cm-super

Without LaTeX the same style is applied with matplotlib's mathtext instead, and the substitution is recorded in figure_style.json and in the figure catalogue rather than silently ignored.

7 Usage

# complete demonstration workflow (campaign + figures + reports)
uv run pv-hc
# inspect the candidate SimBench grids, the selected grid and its data gaps
uv run pv-hc inspect-network --config configs/demo.yaml
# validate the correlated uncertainty model against its configured targets
uv run pv-hc validate-uncertainty --config configs/demo.yaml
# run a campaign
uv run pv-hc run --config configs/demo.yaml
uv run pv-hc run --config configs/research.yaml
uv run pv-hc run --config configs/sensitivity.yaml
# override individual settings without editing the YAML
uv run pv-hc run --config configs/demo.yaml --scenarios 100 --mode three_phase --workers 16
# re-analyse, re-plot or re-report an existing run without recomputing
uv run pv-hc analyze --run-id <run_id>
uv run pv-hc plot --run-id <run_id>
uv run pv-hc report --run-id <run_id>

Demo versus research mode

demo.yaml research.yaml
critical days 1 3
time resolution 45 min (stride 3) 30 min (stride 2)
Monte Carlo scenarios 40 300
statistically supported risk levels 10 % 10 %, 5 %, 1 %
capacity grid / bisection steps 6 / 4 10 / 6
power-flow mode hybrid hybrid
indicative runtime (32 workers) a few minutes roughly an hour

The demo is sized so that the 10 % risk level is genuinely supported ($n \ge 3/\epsilon = 30$); the research configuration additionally supports 1 %.

8 Outputs

Each run writes everything needed to reproduce and re-analyse it:

outputs/<run_id>/
├── config_resolved.yaml # fully resolved configuration (all defaults expanded)
├── metadata.json # versions, git commit, seeds, hashes, timings, failures
├── network_summary.json # grid, distances, sequence-data assumptions
├── profile_inspection.json # resolution, units, naming, element assignment
├── uncertainty_validation.json # target vs empirical correlation structure
├── mode_consistency.json # balanced vs three-phase verification
├── scenario_parameters.parquet # sampled PV fleet per scenario (full traceability)
├── scenario_results.parquet # every scenario evaluation, all metrics
├── risk_curve.parquet # risk and severity per capacity and strategy
├── hosting_capacity_summary.csv # every definition, with support flags
├── strategy_summary.csv # technical, economic and fairness key figures
├── sensitivity_results.parquet # per-bus sensitivities and distances
├── fairness_results.csv # Jain, Gini, distributional metrics
├── limiting_constraints.csv # share of failures per constraint
├── hybrid_comparison.csv # matched balanced vs three-phase scenarios
├── voltage_quantiles.csv # per-step ensemble quantiles
├── convergence.csv # sample-size study
├── benchmark.csv # measured per-solve cost of the solver options
├── failures.csv # every failed operating point with its inputs
├── figures/ # 18 figures as PNG (300 dpi) and PDF
├── figure_data/ # the plotted data of every figure as CSV
└── trajectories/ # detailed time series of representative scenarios

9 Generated figures

# figure question it answers
1 Network topology and uncertain PV allocation Why can equal aggregate capacity have different impact?
2 Example correlated uncertainty scenarios Is the stochastic model coherent rather than noise?
3 Correlation-model validation Does the generator reproduce the intended correlations?
4 Risk curve Main result: violation probability vs installed capacity
5 Violation-severity curves Do equal probabilities hide different consequences?
6 Limiting-constraint decomposition What physically limits the hosting capacity?
7 Voltage quantile fan chart When is the voltage risk greatest?
8 Three-phase voltage and VUF heatmap Which phase-specific effects does balancing hide?
9 Balanced versus three-phase comparison How large is the balanced-screening error?
10 Control-strategy comparison What does each strategy cost technically?
11 Hosting capacity versus curtailment Is a little curtailment disproportionately effective?
12 Techno-economic Pareto frontier Which strategies are non-dominated?
13 Curtailment fairness Are the same prosumers repeatedly disadvantaged?
14 Spatial sensitivity map Why are certain buses prioritised?
15 Electrical distance versus sensitivity Is distance a sufficient proxy?
16 Monte Carlo convergence Is the estimate stable in the sample size?
17 Representative critical scenario How do the controls act over the day?
18 Graphical abstract Overview of the whole workflow

reports/figure_catalog.md documents each figure's file name, scientific question, variables, caveats and a data-derived interpretation. The plotted data of every figure is stored as CSV next to it.

10 Main findings

The findings of a specific run are written to reports/study_report.md — the executive summary, the hypothesis verdicts with their criteria, and the limiting-constraint decomposition. They are deliberately not duplicated here, because they depend on the configuration, the selected grid and the sample size, and a README cannot be regenerated from a run.

Structural results that hold across the configurations shipped here:

  • The selected rural SimBench LV feeder is transformer-thermally limited before the EN 50160 voltage band binds, so voltage-only measures (Q(U), OLTC) cannot raise its hosting capacity much, while curtailment can. Under the stricter 3 % voltage-rise planning criterion — evaluated in parallel and reported separately — voltage becomes co-limiting. The limiting constraint is a property of the grid, not a general result.
  • The OLTC lowers voltages and therefore raises currents: on a thermally limited feeder it can reduce rather than increase the hosting capacity.
  • Sensitivity-based and proportional curtailment need almost the same total energy on this feeder but distribute it very differently (Gini coefficients differ by an order of magnitude), and the fairness-aware policy restores near-equality at a small efficiency penalty.
  • The unbalanced solution gives systematically higher maximum voltages and transformer loadings than the balanced screening, i.e. balanced screening is optimistic here.

11 Limitations

Stated in full in reports/study_report.md, section 16. In brief: synthetic uncertainty distributions; no measured household-level data; dependence on the selected SimBench grid and time periods; assumed PV orientation and phase-connection rules; assumed zero-sequence parameters (SimBench provides none); quasi-static controllers without dynamics; finite Monte Carlo sample error; linearisation error of the coordinated curtailment; illustrative economic coefficients; no protection, harmonic or electromagnetic analysis; and a material difference between planning and operational voltage limits.

12 Reproducibility

  • All randomness derives from one configurable seed through named, collision-free streams; common random numbers are used across strategies and capacity levels, so strategy comparisons are paired.
  • Results are independent of the number of workers (verified by a test).
  • Every run stores its resolved configuration, its configuration hash, the git commit, the Python and dependency versions, the seeds, the sample counts, the failure counts and the stage timings.
  • Failed operating points are retained with their inputs in failures.csv and are never dropped from the probability denominator; the conservative handling (non-convergence = violation) is the primary metric and the optimistic alternative is reported alongside it.
  • recycle — reuse of pandapower's internal branch model, the dominant speed-up for long time series — is verified against freshly built solutions at run start and disabled automatically if it disagrees.

Performance

Measured per balanced solve on the default 97-bus feeder (written to benchmark.csv on every run, so the numbers can be checked on any machine):

configuration per solve
pandapower solver, no branch-model reuse 20–33 ms
lightsim2grid solver, no branch-model reuse 20–32 ms
lightsim2grid + recycle 6–9 ms (×ばつ faster)
runpp_3ph (unbalanced) ≈ 33 ms

pandapower 3.5.4 accepts lightsim2grid (default "auto", so it is active once the package is installed) and its solution agrees with pandapower's own Newton–Raphson to about 10ドル^{-13}$ p.u. For grids of this size the Newton solve is not the bottleneck — pandapower's per-call model build and result extraction is — so the C++ solver alone gives little gain, while branch-model reuse gives ×ばつ. Both are configurable, and numba is enabled by default (its benefit grows with network size).

Quality gates

uv run ruff format .
uv run ruff check .
uv run mypy src
uv run pytest --cov # add -m "not slow" to skip the end-to-end campaign

13 Citation

See CITATION.cff for this software. If you use the results, please also cite the paper this work builds on:

@inproceedings{kortmann2021hosting,
 author = {Kortmann, Steffen and Han, Xuejiao and Schwarz, Marius and Hug, Gabriela},
 title = {From a distributing to a generating network: Assessing PV hosting capacity
 under uncertainty in distribution grids},
 booktitle = {PESS 2021; Power and Energy Student Summit},
 year = {2021},
 pages = {1--6},
 url = {https://ieeexplore.ieee.org/document/9735254},
}

14 Acknowledgements

Built on pandapower and SimBench — the SimBench benchmark grids and profiles are the open data basis of this study. The balanced power flow is accelerated with lightsim2grid; the figures use the RWTH Aachen corporate-design style sheets from rwthplots (RWTH-IAEW).

15 License

MIT — see LICENSE.

About

Probabilistic PV hosting-capacity assessment of a SimBench LV grid under spatially and temporally correlated uncertainty, with autonomous inverter control and active distribution network operation

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

AltStyle によって変換されたページ (->オリジナル) /