Long-Term Correction (LTC)#
Long-term correction extends a short on-site measurement campaign to represent the long-term wind climate at a site. WindKit provides Measure-Correlate-Predict (MCP) methods that learn the relationship between a short-term target and a long-term reference, then apply it to the full reference record.
MCP Workflow#
A long-term reference station provides many years of wind data.
Short-term target measurements at the project site overlap the reference (the concurrent period).
An MCP model is fitted on the concurrent period, learning a per-sector mapping from reference to target wind speeds.
The fitted model is applied to the full reference record to produce a long-term corrected wind climate at the site.
Data Requirements#
Both reference and target datasets must be time series wind climates (TSWC) containing wind_speed and wind_direction
over a time dimension.
Single-point datasets only (one spatial location per dataset).
The reference and target must share the same time coordinates during the concurrent period.
For testing, windkit.create_tswc_pair() generates a correlated
synthetic pair:
out_locs = create_point(500000, 6200000, 80, 32632)
period_lt = pd.date_range("2004-01-01", "2009-01-01", freq="1h", inclusive="left")
period_st = pd.date_range("2008-01-01", "2009-01-01", freq="1h", inclusive="left")
tgt_lt, ref_lt = wk.create_tswc_pair(
out_locs,
date_range=period_lt,
weibull_A=(6.0, 8.0),
weibull_k=(1.6, 2.2),
target_r2=0.8,
speed_tau=14400.0,
)
ref_st = ref_lt.sel(time=period_st)
tgt_st = tgt_lt.sel(time=period_st)
Available Methods#
WindKit provides two sectorwise MCP regression methods:
Method |
Regression |
Variance |
Noise option |
|---|---|---|---|
Ordinary least squares |
Compresses variance |
||
Variance ratio (σy / σx) |
Preserves variance ratio |
– |
Both methods fit one independent linear model per wind direction sector (default 12 sectors of 30°).
Fitting and Predicting#
The API follows the scikit-learn fit / predict pattern:
model = LinRegMCP(n_sectors=12)
model.fit(ref_st, tgt_st)
# Deterministic prediction (conditional mean)
pred_lt = model.predict(ref_lt)
# Prediction with noise (recovers variance)
pred_lt_noisy = model.predict_with_noise(ref_lt, seed=42)
Recovering Variance with Noise#
Deterministic MCP predictions lie on the regression line — every predicted wind speed is the conditional mean for its sector. This compresses the variance of the predicted distribution, clipping the high-wind tail where most energy is produced.
predict_with_noise() adds Gaussian noise
sampled from the per-sector residual standard deviation, N(0, residual_std),
re-inflating the distribution to its proper width. Negative wind speeds are
clipped to zero.
pred_lt_det = model.predict(ref_lt)
pred_lt_noisy = model.predict_with_noise(ref_lt, seed=42)
ws_true = tgt_lt.wind_speed.values.flatten()
print(f"Site true std: {np.std(ws_true):.3f} m/s")
print(f"LinReg (deterministic): {np.std(pred_lt_det.wind_speed.values):.3f} m/s")
print(f"LinReg (with noise): {np.std(pred_lt_noisy.wind_speed.values):.3f} m/s")
Site true std: 3.447 m/s
LinReg (deterministic): 3.040 m/s
LinReg (with noise): 3.340 m/s
When to use which:
Energy yield estimation — use
predict_with_noiseto preserve the distribution shape, especially the high-wind tail.Regression diagnostics — use
predictfor clean deterministic output when evaluating model fit quality.
Model Evaluation#
calc_scores() computes four metrics comparing predicted
and observed wind speeds:
Metric |
Interpretation |
|---|---|
R² |
Coefficient of determination — 1.0 is perfect. |
RMSE |
Root mean squared error (m/s) — lower is better. |
Mean bias |
Systematic over/under-prediction (m/s) — 0 is unbiased. |
EMD |
Earth mover’s distance — distribution shape similarity. |
pred_st = model.predict(ref_st)
scores = calc_scores(tgt_st, pred_st, name="LinReg", period="Concurrent")
print(scores.to_string(index=False))
Name Period Metric Score
LinReg Concurrent R^2 0.796049
LinReg Concurrent RMSE 1.570163
LinReg Concurrent Mean bias 0.000000
LinReg Concurrent EMD 0.386572
Configuration Options#
All MCP classes accept these parameters at construction:
n_sectors(int, default 12)Number of wind direction sectors. Each sector gets an independent regression model.
quantiles(bool, default False)If
True, sectors are defined by equal-probability quantiles of the wind direction distribution rather than constant widths.ws_cutoff(float, default 0.0)Wind speed threshold — observations below this value are excluded from fitting.
VarRatMCP additionally accepts:
fit_intercept(bool, default True)Whether to fit an intercept term. Set to
Falseto force the regression through the origin.