Skip to content

Two aligned wind turbine example case - #313

Open
ia267 wants to merge 21 commits into
xcompact3d:mainfrom
ia267:309_two_aligned_wind_turbines_examples
Open

Two aligned wind turbine example case#313
ia267 wants to merge 21 commits into
xcompact3d:mainfrom
ia267:309_two_aligned_wind_turbines_examples

Conversation

@ia267

@ia267 ia267 commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

Created the flow case for the wind turbine example, including an interface for the turbine models (currently only the Actuator Disc Model)

changes

  • turbine_model_t - abstract interface for turbine forcing models, with methods init, update, project_forces, write_output. Ships with a no-op dummy (turbine_dummy_t, also the iturbine=0 model) so the case runs before any real model exists.
  • wind_turbine case - uniform inflow / convective outflow in x, using a polymorphic turbine_model_t. The case owns the turbine object and is the only place the iturbine switch appears (at allocation time); after that it calls the polymorphic turbine with no branching.
  • iSVV / hyperviscous dissipation - added c_nu and nu0_nu for the compact6-hyperviscous scheme. This is the implicit LES the two_turbines case uses ( Incompact3d jles=4) - implicit numerical dissipation, not an explicit SGS model (the explicit Smagorinsky LES issue is Add Smagorinsky LES with wall damping #321). These params are optional.
  • Boundary conditions - Dirichlet / periodic / periodic (matches the cylinder case). In Incompact3d the example uses free-slip walls in y and z, but the FFT Poisson solver currently requires z periodic and supports only a single MPI rank in non-periodic directions.
  • Actuator Disc Model (ADM) (src/turbine/adm.f90) - super-Gaussian force smearing (King et al. 2017), local (Calaf) thrust coefficient C_T' = C_T/(1-a)^2, optional T_relax velocity filter, per-disc disc<N>.adm diagnostics, and restart-safe checkpoint state. This is a close representation of Incompact3d's ADM. The projected force divided by rho_air so it's a true acceleration (identical to Incompact3d when rho_air=1). Read from a .ad disc-coordinates file

Other changes

Not part of the disc model, but needed for the case.

  • Cylinder case - MPI correctness fix. cylinder.f90 averaged the inflow/outflow mass flux over the local ny*nz (with a NOTE admitting this was wrong under y/z decomposition). Now uses the global plane size via get_global_dims. Unchanged on a single-rank, only fixes decomposed runs
  • Q-criterion formula fix. compute_qcriterion (CUDA + OMP) now uses the full second invariant; the previous form dropped the 0.5*(div u)^2 term. Zero for divergence-free flow, but more accurate on the discerete field
  • Backend x-face primitive + slice_max_sum min. The outflow BC reproduces Incompact3d's outflow + pre_correc, which needs two new backend capabilities. slice_max_sum gains an optional signed min_val (for the convective speed cx = 0.5*(uxmax + uxmin) * gdt/dx), and a new field_add_const_x_face (abstract + CUDA + OMP) for the exact outlet mass correction (bxxn = bxxn - ut + ut1). Without the mass correction, an under-resolved wake reaching the outflow injects boundary divergence; with it the example holds machine-precision divergence at the outlet. This is used for the wind turbine case's boundary treatment

Supporting cases

  • inlet-noise BC: field based Dirichlet inlet refreshed per subsetp only when inlet_noise /= 0; RNG seeded deterministically (rank-offset) for reproducible runs at a fixed decomposition.
  • base_case: finalise_case_specific hook, append -on-restart for monitoring.csv and central release of the persistent inflow-BC planes
  • config: new wind_turbine_ml params (inlet_noise, adm_coords, rho_air, T_relax)
  • docs: input_file.rst documents wind_turbine_nml, the ADM, the .ad format and the corrected Q-criterion

The example uses a dimensional (effective LES Re = 450) setup rather than Incompact3d's non-dimensional Re=45000, which is under-resolved at affordable cost and blows up; the dimensional formulation resolves the wake and runs cleanly to t=800.

Closes #309
Closes #311

Example case visualisations:
https://github.com/user-attachments/assets/f7b88c46-9b2a-43b8-9cc1-8921e9595fe2

turbine_performance mean_wake_deficit

@ia267 ia267 added this to the Wind Turbine Example milestone Jun 9, 2026
@ia267 ia267 self-assigned this Jun 9, 2026
@ia267 ia267 added the examples Example simulation case label Jun 9, 2026
@ia267
ia267 force-pushed the 309_two_aligned_wind_turbines_examples branch from 7933e0b to 0b7249a Compare June 9, 2026 08:28
@ia267
ia267 force-pushed the 309_two_aligned_wind_turbines_examples branch 2 times, most recently from d2d578a to fb3db44 Compare June 23, 2026 14:32
@ia267
ia267 force-pushed the 309_two_aligned_wind_turbines_examples branch from fb3db44 to c29a3b2 Compare July 7, 2026 20:07
@ia267
ia267 force-pushed the 309_two_aligned_wind_turbines_examples branch from c29a3b2 to dc072f2 Compare August 12, 2026 14:17
@ia267
ia267 requested a review from kaanolgu August 12, 2026 14:18
@ia267
ia267 marked this pull request as ready for review August 13, 2026 14:17
ia267 and others added 18 commits August 27, 2026 12:58
Add turbine model lifecycle hooks for scalar output, checkpoint state, and
finalisation. Register the wind-turbine model with the I/O manager, persist ADM
restart-critical state, and write per-disc ADM diagnostic series.

Also extend the ADM unit test to cover running means and scalar-output columns.
- add inlet_noise to wind_turbine namelist/config
- generate noisy inlet fields once per substep in define_BC
- apply inlet BC via field_set_face_from_field for u/v/w
- remove old scalar outflow BC path to avoid inconsistent BC updates
Previously U_disc was only evaluated when recompute_forces is true (first substage), leaving substages 2 and 3 applying thrust based on stale velocity. Move the disc-averaging outside the recompute_forces guard so the force remains consistent with each RK substage velocity. On the first substage the time filter is advanced and U_disc_filt is used for thrust; on subsequent substages the instantaneous U_disc is used directly.
…ise reproducible

- Release persistent inflow-BC planes in base_case%case_finalise so cylinder,
  wind_turbine and future cases are cleaned up in one place.
- Rebuild the wind_turbine inlet plane only when inlet_noise is non-zero; a
  noise-free inlet is built once and reused.
- Seed the RNG deterministically, offset by rank, so inlet-noise runs are
  reproducible for a fixed decomposition.
The sponge was only needed as a crutch for the under-resolved high-Re runs.
The dimensional (effective LES Re) case holds machine-precision divergence
without it, and no shipped example or test exercised it. Removing the
sponge_* config params and the init_sponge/apply_sponge machinery keeps the
ADM case focused on the disc model.
The shipped example was the non-dimensional Re=45000 AB3 config, which is
under-resolved and blows up (NaN ~t=2). Replace it with the dimensional
effective-LES-Re setup (Re=450, RK3, dt=0.2, D=126m discs) that runs cleanly
to t=800 with machine-precision divergence and a developing turbulent wake.
Also updates discs.ad to the matching dimensional disc geometry.
- Add a Wind Turbine Parameters section covering the wind_turbine_nml block
  (init_noise, inlet_noise, bc_start_*, iturbine, iturboutput, adm_coords,
  rho_air, T_relax), the ADM thrust/power model, the .ad file format, and the
  disc<N>.adm diagnostics.
- Update the Q-criterion formula to the general second-invariant form now
  used in the code.
- Reword the iturbine=1 description in plain terms (not yet implemented).
- Refer to Incompact3d by name instead of 'legacy' in code comments.
Fix line-length and indentation to satisfy fprettify: split the long
wind_turbine_nml namelist and the ADM stats_start/stats_freq assignments,
reformat the compute_qcriterion continuation, and lay out the ADM output
column names one per line.
ia267 added 2 commits August 27, 2026 13:00
…ehavior

Commit fcfe416 made project_forces recompute U_disc (and the thrust) from
each RK substage velocity, but test_adm was written for the earlier
freeze-and-reuse behavior and was never updated, so it asserted U_disc = 10
after the velocity changed to 20 at a repeated substage. Update the block to
expect the recomputed U_disc = 20 and the corresponding thrust, and fix the
stale 'reuse the resulting thrust' comment in update_adm.
Drop the unverified NREL-5MW label, make the Reynolds-number comment
self-contained instead of referencing the non-dimensional case, and reword
the init_noise and iSVV comments for clarity.
@ia267
ia267 force-pushed the 309_two_aligned_wind_turbines_examples branch from e254fc6 to ec7c800 Compare August 27, 2026 12:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

examples Example simulation case

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Actuator Disc Model Add two aligned wind turbines example case

1 participant