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.
Methods used by each software
FLORIS
TurbineGrid (3 x 3)
Samples
9
Aggregation
cubic mean of velocity
9 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 power_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
4 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.
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.
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 reads 1.006623 against an exact area average of 1, because its cubic mean of a varying field is above the arithmetic mean no matter where it samples. Its dense-disk cubic reference is already 1.009902. The remaining 0.32% error against that reference is a sampling effect: FLORIS only samples out to ±R/2 on each axis, so it sees less of the shear than the full disk.
The quadratic case separates the methods by radial reach. PyWake samples at(±R/3, ±R/3), no farther than r/R = 0.47 from the hub, and FLORIS reachesr/R = 0.71 at the corners of its ±R/2 square. Both miss the slower tip flow and read high. FOXES spans the full disk and lands slightly low (0.36%) because its four corner points sit at r/R = 1.06, beyond the rim, where the velocity is lowest, yet carry partial-cell weight.
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. Both PyWake (3.86%) and FLORIS (1.76%) read too much deficit, while FOXES is within 0.11%. PyWake places two of its four points near the deficit core at y/R = 0.35 and none beyond R/3, so the core is over-weighted.
These results isolate quadrature error and are not a ranking of full wake-model accuracy.