← All comparisons
Rotor velocity averaging
This comparison passes the same rotor-plane velocity fields to the installed FLORIS, FOXES, and PyWake packages and compares the outputs of their native rotor sampling and averaging implementations. It does not compare wake-model physics, turbine curves, superposition, or induction.
All sampling coordinates are normalized by rotor radius R.
Execution: Each common velocity field is passed to the installed framework's native rotor-grid and rotor-averaging implementation. No framework result is calculated by a wcomp replacement formula.
Methods used by each software
FLORIS
TurbineGrid (3 x 3)
- Samples
- 9
- Aggregation
- cubic mean of velocity
Nine equal-weight points on a square spanning -0.5R to 0.5R in the lateral and vertical directions.
Executed with FLORIS TurbineGrid(grid_resolution=3) and FLORIS average_velocity using the grid's native average_method.
FOXES
GridRotor (grid16)
- Samples
- 16
- Aggregation
- weighted arithmetic mean of velocity
Sixteen cell-center points on a 4 x 4 square spanning the rotor. Weights are evaluated by FOXES from each cell's overlap with the disk; the four corner cell centers lie outside the disk but retain partial-cell weight.
Executed with FOXES ModelBook grid16 and GridRotor.eval_rpoint_results, requesting FOXES' native REWS output.
PyWake
GridRotorAvg
- Samples
- 4
- Aggregation
- weighted arithmetic mean of velocity
Four equal-weight points at (+/-R/3, +/-R/3) in the rotor plane.
Executed with PyWake GridRotorAvg.__call__. PyWake averages the supplied deficit at its native rotor nodes; the comparison converts that result back to normalized velocity.
A ladder of test cases
Rather than jumping straight to a waked rotor, the comparison walks through four velocity fields of increasing difficulty. Each step adds exactly one new way for a coarse stencil to go wrong, so a deviation can be attributed to a specific cause instead of to the case as a whole.
- Uniform inflow —
U/U∞ = 1 - Linear vertical shear —
U/U∞ = 1 + 0.2 (z/R) - Quadratic radial deficit —
U/U∞ = 1 - 0.2 (r/R)² - Offset Gaussian velocity deficit —
U/U∞ = 1 - 0.35 exp(-((y/R - 0.35)² + (z/R)²) / (2 · 0.28²))
Reference: 128-point Gauss-Legendre radial integration with 720 azimuthal points. Each software result is compared with a dense-disk reference using the same aggregation semantics.
1. Uniform inflow
U/U∞ = 1
A constant field. Any quadrature whose weights sum to one is exact here, so this verifies the harness and the normalization of each stencil rather than discriminating between methods.
Exact area average: 1
| Software | Points | Rotor average | Dense reference | Absolute error | Relative error |
|---|
| FLORIS | 9 | 1.000000 | 1.000000 | 0.000000 | 0.00% |
| FOXES | 16 | 1.000000 | 1.000000 | 0.000000 | 0.00% |
| PyWake | 4 | 1.000000 | 1.000000 | 0.000000 | 0.00% |
2. Linear vertical shear
U/U∞ = 1 + 0.2 (z/R)
A linear profile. Because all three stencils are symmetric about the hub height, the positive and negative contributions cancel and the area average is still recovered exactly. Point placement starts to matter only once the aggregation is nonlinear.
Exact area average: 1
| Software | Points | Rotor average | Dense reference | Absolute error | Relative error |
|---|
| FLORIS | 9 | 1.006623 | 1.009902 | 0.003279 | 0.32% |
| FOXES | 16 | 1.000000 | 1.000000 | 0.000000 | 0.00% |
| PyWake | 4 | 1.000000 | 1.000000 | 0.000000 | 0.00% |
3. Quadratic radial deficit
U/U∞ = 1 - 0.2 (r/R)²
The first case with real curvature. The exact area average is 0.9. Stencils clustered near the hub under-resolve the slower flow near the blade tips and overpredict the rotor average, which exposes how far each sampling pattern reaches toward the rotor edge.
Exact area average: 0.9
| Software | Points | Rotor average | Dense reference | Absolute error | Relative error |
|---|
| FLORIS | 9 | 0.934529 | 0.903689 | 0.030841 | 3.41% |
| FOXES | 16 | 0.896800 | 0.900000 | 0.003200 | 0.36% |
| PyWake | 4 | 0.955556 | 0.900000 | 0.055556 | 6.17% |
4. Offset Gaussian velocity deficit
U/U∞ = 1 - 0.35 exp(-((y/R - 0.35)² + (z/R)²) / (2 · 0.28²))
A laterally offset deficit that approximates a partially waked rotor. It is neither symmetric nor smooth on the scale of the coarse stencils, so it is the most demanding case and the one most representative of wake-model use.
| Software | Points | Rotor average | Dense reference | Absolute error | Relative error |
|---|
| FLORIS | 9 | 0.935981 | 0.952786 | 0.016805 | 1.76% |
| FOXES | 16 | 0.947192 | 0.946132 | 0.001060 | 0.11% |
| PyWake | 4 | 0.909611 | 0.946132 | 0.036521 | 3.86% |
Errors across the ladder
Because FLORIS uses a cubic mean while FOXES and PyWake use arithmetic averaging in these configurations, each error is measured against a dense-disk reference with matching aggregation semantics rather than against a single shared number.
How to interpret this comparison
- Every case uses one identical velocity field; differences come only from sampling and averaging.
- Uniform inflow is exact for all three methods, which confirms that each set of weights is normalized.
- Linear shear is exact for FOXES and PyWake because their stencils are symmetric about hub height. FLORIS deviates here purely because a cubic mean is nonlinear, not because of where it samples.
- The quadratic case separates the methods by radial reach. PyWake samples only out to
r/R = 1/3 and FLORIS only to r/R = 0.5, so both miss the slower tip flow and read high. FOXES spans the full disk and lands slightly low because its corner cells carry weight just beyond the rim. - The offset Gaussian is the only case that is neither symmetric nor resolvable by a handful of points, which is why it is the most representative of partially waked operation.
- These results isolate quadrature error and are not a ranking of full wake-model accuracy.