Regression tests¶
GALE registers its CTest suite with -DERF_ENABLE_TESTS=ON (see Building).
The input decks are in Exec/CanonicalTests/MovingBodies, one directory per case with its
gold logs; the gold plotfiles are in Tests/ERFGoldFiles. Most tests run on the bundled
OpenFAST stub library (ERF_ENABLE_OPENFAST=ON, ERF_OPENFAST_USE_STUB=ON,
ERF_ENABLE_FFT=ON, MPI, not Windows). ERF’s own regression suite is not registered in a
GALE build.
Running¶
ctest --test-dir cmake-build/Tests -L moving-bodies # the canonical cases and the start-up aborts
ctest --test-dir cmake-build/Tests -L restart-parity -R "OpenFAST|MovingBodies"
ctest --test-dir cmake-build/Tests -L box-parity -R "OpenFAST|Actuator"
ctest --test-dir cmake-build/Tests -L openfast-real # real OpenFAST build only
ctest --test-dir cmake-build/Tests -L rosco # real OpenFAST build with ROSCO
.github/workflows/scripts/run_unit_tests.sh cmake-build/ERF/Tests/Unit/erf_unit_tests
ctest --test-dir cmake-build -L parallel -R "Actuator|BodyExchange" # on 1, 2 and 4 ranks
How the tests check results¶
The tables below name these checks instead of describing them again.
Gold: the plotfile matches its gold in
Tests/ERFGoldFiles; the named logs match the gold logs beside the deck to ten significant digits unless stated otherwise.Force identity: in every row, the integrated momentum source (
moving_bodies/momentum_source.csv) equals minus the bodies’ load: the thrust inT1_erf.csv, orload_xinmoving_bodies/total_load.csvfor towers, nacelles and farms. The spreading is normalised exactly, so this holds to roundoff.Box parity: the deck runs in one box and split unevenly in x and y; plotfiles and logs must agree.
Owner parity: the deck runs in one box (the body on rank 0, the I/O rank) and in three 20-cell boxes in x (
amr.max_grid_size_x = 24, the body on rank 1); the plotfiles and every file the owner writes must agree.Owners: a
MovingBodies_Owners_*test runs a deck for one step on two ranks and checks which rank owns each body.Restart parity: the deck runs straight to step 10, and again to a checkpoint at step 5 and on to step 10 (
Tests/RunRestartParity.cmake). The plotfiles must agree with zero tolerance and the logs to ten digits. The run that writes the checkpoint goes on to step 10 (OVERRUN), so the restart must drop the log rows past the checkpoint. A restart on another rank count compares the plotfile to the default tolerances and the logs to 8 digits, as the FFT solution differs at roundoff between rank counts.Abort: the run, or the restart (
Tests/RunRestartAbort.cmake), must stop with a message naming the input.
OpenFAST driver¶
One stub rotor of IEA 15 MW size (mode = none) is driven by a prescribed uniform velocity
for five steps of a uniform anelastic flow and adds no forcing.
Test |
Checks |
|---|---|
|
Plotfile equals the same deck run without |
Test location: OpenFAST_DriverOnly
Actuator velocity sampling¶
An anelastic box with the linear shear u = 5 + 0.05 z, v = 1 + 0.01 z is sampled at
the nodes of one stub rotor with its hub at 150 m. The sampler is exact for a linear field.
Test |
Checks |
|---|---|
|
Gold |
|
Box parity, flow files to eight digits. |
Test location: Actuator_Sampling
Actuator disk force spreading¶
A uniform 10 m/s anelastic flow runs for ten steps through a prescribed uniform-Ct disk
(radius 120 m, hub 150 m, Ct = 0.75, epsilon = 2 dx). It builds with
ERF_ENABLE_MOVING_BODIES=ON in place of OpenFAST. The disk’s owner rank alone samples the
flow for it and writes its log, statistics and wake lines.
Test |
Checks |
|---|---|
|
Gold plotfile and |
|
Box parity, plotfiles and disk logs. |
|
With wake lines 2 and 4 diameters behind: disk on rank 1, sampled points on rank 1 only, kernels on both ranks, wake lines on rank 0 only. |
|
Owner parity: plotfiles, disk log, statistics, both wake files and the momentum source. |
|
Restart parity on two ranks with the disk on rank 1; statistics and wake sums (three wake samples) come back from the checkpoint. |
|
The same checkpoint restarted on one rank, which reads rank 1’s files. |
Test location: Actuator_UniformCtDisk
Turbine table on a prescribed disk¶
Two disks side by side in a uniform 10.25 m/s flow for ten steps: T1 names the turbine table
NREL_5MW_126 and D1 keeps a constant Ct = 0.75, both of radius 63 m at hub 90 m.
Test |
Checks |
|---|---|
|
Both disk logs against their golds to ten significant digits, then |
Test location: Actuator_TurbineCtDisk
OpenFAST rotor as an actuator disk¶
A uniform 10 m/s flow runs for ten steps through one stub turbine in mode = adm; its loads
are spread as rings about the hub axis (num_points_t = 16, epsilon = 2 dx). Unless
stated otherwise each case checks Gold (plotfile, T1_flow.csv) and the force identity
(Tests/RunOpenFASTADM.cmake).
Test |
Checks |
|---|---|
|
|
|
|
|
Abort on an unknown |
|
|
|
Adds a nacelle drag point; the owner samples the hub as one more point. Gold plotfile and nacelle column of |
|
|
|
Restart parity with the turbine on rank 1; the recovered free stream is restored. |
|
|
|
100 m Witch-of-Agnesi ridge, turbine on top, |
|
Actuator line on the ridge with and without |
Test location: OpenFAST_ADM_Uniform, OpenFAST_ADM_Upstream, OpenFAST_ADM_UpstreamNacelle, OpenFAST_ADM_DiskCorrected, OpenFAST_ADM_Terrain
OpenFAST rotor as an actuator line¶
The disk deck runs with mode = alm and fllc = false: loads are spread from 20 nodes
per blade (epsilon = 2 dx) that turn through the 50 m cells at 0.9 cells per step, under
the one-cell limit erf.moving_bodies.alm_max_tip_cells. Unless stated otherwise each case
checks Gold and the force identity on the full force vector.
Test |
Checks |
|---|---|
|
Gold, force identity; box parity as blade points cross box faces. |
|
Tower (8 m, |
|
Widths per kind: |
|
|
|
Box parity with the tower axis on a box face; restart parity from step 5. |
|
Abort on a restart with another |
|
Filtered lifting-line correction (chord 6 m: optimal kernel 1.5 m vs the run’s 100 m). Gold plotfile and |
|
Restart parity with the turbine on rank 1, which writes and reads the correction and node-load checkpoint files. |
|
20 steps with |
|
Checkpoint at step 12 on two ranks (turbine on rank 1), restart to step 20: equals the straight run. |
|
Abort on a restart with the automatic values given by hand. |
|
Abort when |
Test location: OpenFAST_ALM_Uniform, OpenFAST_ALM_Tower, OpenFAST_ALM_ComponentWidths, OpenFAST_ALM_FLLC, OpenFAST_ALM_FLLC_Restart, OpenFAST_ALM_FLLC_Automatic
Anchor level on two levels¶
The disk deck adds a level 1 of 25 m cells around the rotor and its near wake. The turbine is sampled and forced on level 1; level 0 carries level 1’s source restricted onto its faces (ERF’s coarse-level source).
Test |
Checks |
|---|---|
|
Gold, force identity; box parity with the fine level split unevenly over two ranks. |
|
Restart parity; fine level and turbine restored exactly. |
|
Restart from a checkpoint rewritten by |
|
|
|
Abort when bodies live above level 0 and |
Test location: OpenFAST_ADM_TwoLevel, OpenFAST_ADM_TwoLevel_Restart
Force on the levels below the anchor¶
A prescribed-Ct disk (R = 120 m, Ct = 0.75, 10 m/s) runs on one level of 25 m cells and on a level 1 of 12.5 m cells whose box ends 0.8 R up and down stream; the kernel is 25 m wide in both.
Test |
Checks |
|---|---|
|
After 60 s, the deficits of the disk-averaged velocity and of the velocity a quarter diameter upstream are within 10 % of the one-level run. Without the coarse-level force they were 44 % and 81 % smaller and the thrust 12 % larger. |
Test location: Actuator_CtDisk_TwoLevel
Farms¶
Two stub turbines run as disks, the second two diameters behind the first, each with its own OpenFAST instance on its owner rank.
Test |
Checks |
|---|---|
|
Gold plotfile and |
|
One rank vs three 20-cell boxes on two ranks (T2 on rank 1): plotfiles, T2’s flow, turbine, statistics and correction logs, and |
|
Owners: with three 20-cell boxes, rank 1 owns the first turbine. |
|
Owners: rank 1 owns the second turbine with the box-parity split, and with two 30-cell boxes where both bases are on rank 0’s box. |
|
Third turbine; the second steps with |
|
Abort naming the two substep counts. |
|
|
|
|
|
Restart from step 5 with |
|
Restart from step 5 with no step left: statistics rewritten from the checkpoint. |
|
The same for the farm file with the turbine on rank 1 and rank 0 owning none: the collective rewrite holds the straight run’s bytes. |
|
One width per turbine (T1 2 cells, T2 1 cell); Gold, force identity and a box-parity twin. |
|
A prescribed-Ct disk (1 cell) where T2 stood: Gold plotfile and |
|
Disk upstream; owner parity with the disk on rank 1: plotfiles, disk log and statistics, turbine log and |
Test location: OpenFAST_ADM_TwoTurbines, OpenFAST_ADM_TwoWidths, OpenFAST_ADM_DiskAndTurbine
Real OpenFAST on terrain¶
These cases need -DERF_ENABLE_OPENFAST=ON -DERF_OPENFAST_USE_STUB=OFF with OpenFAST 5,
FFT and MPI (label openfast-real). The IEA 15 MW reference turbine
(Exec/CanonicalTests/MovingBodies/IEA15_land_model) stands 123 m up on the summit of the
Askervein hill, on a fitted mesh of 50 m cells with a uniform 10 m/s inflow, for ten steps of
0.4 s. The blades flap downwind once released (thrust drops by 60 %, torque by over 80 % in
the first step), so these are start-up regressions of the coupling, not validations.
Test |
Checks |
|---|---|
|
Gold plotfile to 1e-6 relative; |
|
The same golds; force identity on |
|
The checker on fixed logs: the disk case’s own must pass, one row off by 1e-6 must fail, a stub disk with loads along x must be refused. |
The golds are per platform: Tests/ERFGoldFiles/OpenFAST_{ADM,ALM}_Askervein_macOS and
..._Linux, and T1_erf.csv.macOS.gold and T1_erf.csv.Linux.gold (likewise
T1_flow.csv) beside the deck. macOS arm64 and the Linux GCC OpenFAST 5 CI job agree
exactly for four steps, then part: the feedback in both corrections amplifies a last-bit libm
difference to 4e-5 relative in the velocities, 1e-3 in the thrust and 4e-3 in the power by
step ten. One shared gold set would need tolerances coarser than the changes these cases
exist to catch. Within one platform the answers are reproducible; one and two ranks agree to
1e-15.
Test location: OpenFAST_ADM_Askervein, OpenFAST_ALM_Askervein
IEA 15 MW under ROSCO¶
These tests need a real OpenFAST build that knows a ROSCO library (ROSCO_DIR or
-DERF_BUILD_ROSCO=ON) and Python 3 (label rosco). The IEA 15 MW turbine runs under its
ROSCO controller on a flat domain at 9 m/s for ten steps.
Test |
Checks |
|---|---|
|
The disk on one and two levels, the line on two and three. Each makes its run folder with the case’s |
|
The ROSCO library loads and exports |
Test location: OpenFAST_IEA15_PowerCurve
Wake sampling lines¶
The disk case samples wake lines 2, 4 and 7 diameters behind the rotor (41 points over ±1.5 D, lateral and vertical) every two steps and averages them from 2 s on.
Test |
Checks |
|---|---|
|
Gold plotfile and |
Test location: OpenFAST_ADM_Wake
Turbulent inflow from a precursor¶
The stub disk runs for ten steps in a turbulent inflow.
Test |
Checks |
|---|---|
|
Inflow from the boundary planes of a 14-step periodic Smagorinsky precursor ( |
|
Steady 10 m/s inflow with |
Test location: OpenFAST_ADM_LES, OpenFAST_ADM_CPM
OpenFAST turbine restart¶
The disk case runs with two wake lines; the turbine restarts from its OpenFAST checkpoint
under chk00005/moving_bodies.
Test |
Checks |
|---|---|
|
Restart parity: wake average, correction, turbine, flow and statistics logs, momentum source and total load. |
|
Abort on, in order: a changed |
|
Turbine on rank 1; a malformed statistics or wake-average file stops every rank with that file’s message (a hang would hit the 180 s limit). |
|
Restart parity for the prescribed-Ct disk, with a later stop time on restart. |
|
Abort on a changed |
|
Restart parity on two ranks with the turbine and its wake lines on rank 1. |
|
The farm on two ranks; rank 1 writes and trims T1’s logs and checkpoint files. |
|
Checkpoint on two ranks, restart on one, which reads rank 1’s files. |
|
Per-rank logs on two ranks, restart on one with no step left: the I/O rank cuts rank 1’s files back to a 5-step run’s bytes ( |
|
One file per body on two ranks: each owner cuts its turbine’s files once (rank 1 for T1, rank 0 for T2); the I/O rank cuts the farm totals. |
|
The wake file of a turbine on rank 1 is cut by its owner. |
Test location: OpenFAST_ADM_Restart