Genetic Algorithm for Wind Farm Layout Optimization
Overview
The genetic algorithm is designed to optimize wind farms of any shape. Each layout is encoded as n unique grid-cell identifiers. It requires a predefined amount of turbines, a unified rotor radius and an average wind speed value for each incoming wind direction. A terrain effect model can be included that downloads an 'SRTM' elevation model and loads a Corine Land Cover raster to approximate surface roughness.
Breaking release: layouts are n unique grid-cell IDs, not a 0/1 string.
Breaking
- Genome is
ncell IDs. The loop isselection→set_crossover→swap_mutation→get_grids→fitness.trimtonis not in the loop.selection()returns an ID matrix; pipe it intoset_crossover(), not the old binarycrossover(). - Public API is snake_case:
area,wind,rotor,mutation_rate,selection_mode,crs.plotitis nowplot. Unused loop argscrossPart1andtrimForceare gone. Invalidselection_modeerrors (no interactive prompt). - Defaults that change a run:
selection_mode = "VAR", mutation2/n(was often0.8),n_elite = 3. Session options (inject, immigrants, seasons, local search) also change search behaviour.
Show all changes in 5.0.0Hide the rest of the changes in 5.0.0
- Legacy
crossover(),mutation()andtrimton()still accept 0/1 chromosomes. New exports:set_crossover(),swap_mutation(). plot_fitness_evolution()is gone (it only calledplot_parkfitness()).
New
- Results have class
windfarmGA(print/plot).ga_options()lists or setsoptions(windfarmGA.*). explore_result(): Shiny map of a generation, wind rose, downwind wake cones, optional terrain layers + turbine popups. Click a new fitness max to jump the slider.- Fitness is \(E \times (\eta/100)^w\) (
windfarmGA.fitness_efficiency_weight, default 1). Log hub-height profile (power law viawindfarmGA.wind_profile = "power"). Optional manufacturer curve (ga_options(power_curve = …),read_power_curve(),plot_power_curve()).Cpdefault 0.45; optional cut-in / rated / cut-out. - Elitism archives the best layout (no fitness × 10). Elite children, neighbour local search, fitness cache, immigrants, spatial crossover. Early stop only after
stall_generationsidle gens (no new layout, cell, or best). - Terrain: pass a DEM (
terrain = dem) to skip the download. Per-cell height / \(z_0\) / \(k\) / air density are computed once and stored asterrainModelforplot_resultandrandom_search. random_search()jitters turbines inside their cells (runs). Terrain is reused fromresult; passweibull_srcagain (not stored).plot_random_search()draws both panels on the same grid.- Wake search and circle overlap run in C++. Turbines exactly upwind (
alpha = 0) are kept (old triangle test dropped them). - Wind helpers:
wind_from_uv(),wind_from_series(). GitHub-only extras inexperimental/(ERA5/GWA, noise, rayshader, mapgl) are not in the CRAN tarball.plot_mapgl_from_result()reusesterrain_tiles//terrain.mbtiles, draws wake cones colored byAbschGesamt(0% green → max red) and the rayshader OBJ (wind_turbine_v1.obj). Three.js is r149 UMD from localhost. TileJSON Terrarium encoding;maxzoomis the highest tile folder. Basemaps:satellite,topo, Carto. Port 8000 leftover servers are freed (rebuild = TRUEremakes the tiles). - Plots wait for Enter between pages when interactive.
plot_generation()shows every layout in a generation.plot_viewshed()projects lon/lat DEMs first. genetic_algorithm(on_generation = ...)callsfunction(generation, iteration, energy, efficiency, fitness)after each generation so a Shiny app can show progress without forking the GA.wake_cones()is the public name for the downwind search-cone polygons (plot_leaflet, MapGL). Internal geometry iswake_cone_polys().
Fixes
- Weibull speed no longer becomes all-NA after masking (fitness crash).
- Power-curve energy is the park sum, not the first turbine.
clc_legend.csvis in the tarball again (.Rbuildignorehad dropped every CSV).crossoverparent fitness is(a + b) / 2.isSpatialuses the given CRS, not hardcoded 3035.plot_windrose()works with ggplot2 4.x (S7). If ggplot2 4 meets an oldsystemfonts, updatesystemfonts.- Parallel clusters always stop via
on.exit. plot_result(terrain = dem)no longer errors on a SpatRaster. Weibull file paths get a CRS before crop. PROJ < 6 branches are gone.with_mocked_bindings()intest_coverage_branches.Rwraps the ggplot2-missing checks incode = { … }(testthat requires named bindings).random_search()test usesruns, not the removedn.resultrectis the first 50 generations of the old 200-iteration run, saved withxz(~90 KB). A new 50-gen GA is larger becauseallCoordsnow stores a bigger population.plot_cell_heatmap()/ga_result_grid()no longer assume a missing CRS is lon/lat. Meter coordinates get the result projection (same asplot_leaflet()). The 4326 round-trip broke the grid on macOS.- Roxygen: unused
@inheritParamsontrimton()andturbine_influences()removed (params were already documented). - Rd help is ASCII-only (
≈,×, em-dash broke the CRAN PDF manual). README no longer links to the archived check-results page (404). - Parallel:
n_clusteris capped at 2 under_R_CHECK_LIMIT_CORES_(R errors onmakeCluster(detectCores() - 1)). Terrain tests no longer need a localg100_06.tif. random_search_single(turbine = …)skips the interactive prompt. User-input tests no longer write to a fakestdin.stopCluster()is wrapped intry()so a dead worker does not fail the run. Live parallel GA tests skip undercovr. Time sequential vs PSOCK locally withsource("experimental/bench_parallel.R"); bench_parallel(). Windows starts PSOCK workers sequentially;fitness()loads windfarmGA/terra/sf on the workers. The bench catches dropped connections (often at 6–8 workers on this small site). README notes ~4 workers as the useful default on the demo site.calculate_energy()uses its public arguments (layout,area,wind, …) instead of internal aliases. Unusedmaxt0in the GA first-generation fuzzy block is gone.windata_format()column matching used a brokensapply(grepl, …)(--run-donttestexample). Frames that already havews/wdskip the matcher (soprobabno longer triggers it).
From NEWS.md in the release
Install
Health
- OK13 OKNow
- OK5 OK2026-09-14
Documentation
- Help pages
- 55includes a package overview page
- Examples that run
- 37%15 run in a plain check · 20 only when donttest examples are enabled (R CMD check --as-cran) · 6 never run
- Exported functions with examples
- 87%
- Documented parameters
- 100%
- Return-value docs
- 100%
- Help pages citing references
- 2%
Downloads
Repository
- PRs merged (all time)
- 100%
- Median days to close, 50 most recently updated closed issues
- 40
- Median days to close, 50 most recently updated closed PRs
- 0
Stars over time
Releases over time
10 development-tooling and community-health practices detected across 7 families in the upstream repository
Checks run against github.com/ysosirius/windfarmga on 2026-10-21.
The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel
GitHub Pages site last deployed 2026-09-14 · The repository has a site deploy workflow
pkgdown site last built 2026-09-14
Show all practicesHide 3 practices
Dependencies
Code & Tests
Datasets
People & History
Pick two releases to compare their code metrics.
- unarchivedReturned to CRAN2026-09-14
- 5.0.0Latest2026-09-14 · current release · diff ↗ ·
removed 1 export
plot_fitness_evolutionadded 17 exports
as_windfarmGA, explore_result, ga_options, generation_layouts, is_plotly_installed, is_shiny_installed, plot_cell_heatmap, plot_generation, plot_population, plot_power_curve, population_census, read_power_curve, set_crossover, swap_mutation, wake_cones, wind_from_series, wind_from_uv - RR 4.6.0 released · 2026-04-24
- archivedRemoved from CRAN2025-11-07issues were not corrected despite reminders
- RR 4.5.0 released · 2025-04-11
- unarchivedReturned to CRAN2025-01-18
- 4.0.02025-01-18 · diff ↗ ·
removed 10 exports
cansee, dup_coords, getDEM, getISO3, interpol_view, plot_heatmap, rasterprofile, viewTo, viewshed, windfarmGAadded 8 exports
circle_intersection, is_doparallel_installed, is_elevatr_installed, is_foreach_installed, is_ggplot2_installed, is_leaflet_installed, is_parallel_installed, terrain_model - RR 4.4.0 released · 2024-04-24
- RR 4.3.0 released · 2023-04-21
- RR 4.2.0 released · 2022-04-22
- archivedRemoved from CRAN2021-06-28check problems were not corrected in time
- RR 4.1.0 released · 2021-05-18
- unarchivedReturned to CRAN2021-05-05
- 3.0.02021-05-05 · diff ↗ ·
removed 25 exports
BaroHoehe, GridFilter, HexaTex, InfluPoints, PlotWindfarmGA, RandomSearch, RandomSearchPlot, RandomSearchTurb, StartGA, VekWinkelCalc, calculateEn, crossover1, genAlgo, getRects, heatmapGA, leafPlot, plotCloud, plotEvolution, plotResult, plotWindrose, plotbeorwor, plotfitnessevolution, plotparkfitness, selection1, tess2SPdf - archivedRemoved from CRAN2021-03-28issues were not corrected in time
- 2.3.02020-10-20 · diff ↗
Show 12 earlier eventsHide 12 earlier events
- RR 4.0.0 released · 2020-04-24
- 2.2.32019-12-16 · diff ↗
- 2.2.22019-08-27 · diff ↗ ·
removed 1 export
plot_farm_3dadded 25 exports
barometric_height, calculate_energy, crossover, genetic_algorithm, get_dist_angles, get_grids, grid_area, hexa_area, init_population, plot_cloud, plot_development, plot_evolution, plot_fitness_evolution, plot_heatmap, plot_leaflet, plot_parkfitness, plot_random_search, plot_result, plot_windfarmGA, plot_windrose, random_search, random_search_single, selection, turbine_influences, windata_format - RR 3.6.0 released · 2019-04-26
- 2.2.12019-02-18 · diff ↗ ·
removed 7 exports
GoogleChromePlot, GooglePlot, PointToLine2, WinkelCalc, euc.dist, readinteger, readintegerSeladded 14 exports
RandomSearch, RandomSearchPlot, RandomSearchTurb, cansee, dup_coords, getDEM, getISO3, interpol_view, isSpatial, plot_farm_3d, plot_viewshed, rasterprofile, viewTo, viewshed - RR 3.5.0 released · 2018-04-23
- 1.2.12018-03-25 · diff ↗
- 1.22018-03-11 · diff ↗
- 1.1.12017-07-27 · diff ↗
- 1.1
- 1.02017-06-24
- RR 3.4.0 released · 2017-04-21
Package metadata
- First published
- 2017-06-24
- Total releases
- 12 / 9 yrs
- License
- MIT + file LICENSE OSI
- Minimum R
- ≥ 4.1.0
- Bundled data
- 133 KB / 6 files
- Download size
- 2.8 MB
Cite
Cite this package
Run in R for the authors' preferred citation:
citation("windfarmGA")This package has no citation file, so citation() returns this entry built from DESCRIPTION.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-25, which the citation names so these numbers can be found later. More on citing and the projects behind them.