Skip to content

implement multi-farm support in pywake_api#62

Open
kilojoules wants to merge 2 commits into
mainfrom
support-multiple-farms
Open

implement multi-farm support in pywake_api#62
kilojoules wants to merge 2 commits into
mainfrom
support-multiple-farms

Conversation

@kilojoules
Copy link
Copy Markdown
Member

No description provided.

@bjarketol
Copy link
Copy Markdown
Contributor

Hi @kilojoules,

I did a quick agent-based review. It found a few things.

High

  • Per-farm AEP normalization mismatchwifa/pywake_api.py:1040-1043, 1252-1254. For time-series cases, aep_per_turbine is computed with normalize_probabilities=True while total AEP uses normalize_probabilities=False. Multi-farm per-farm AEP is derived from aep_per_turbine, so it is on a different basis than total AEP. Fix: use the same normalization (False) for per-turbine AEP in time-series, then slice/sum per farm.

  • Turbine deduplication by name onlywifa/pywake_api.py:285-293 (_build_multifarm_turbines). Two farms whose turbine YAMLs share a name (e.g. IEA-15MW) but differ in power curve/geometry are silently merged into the first farm's spec — wrong physics, no warning. Fix: dedupe by structural fingerprint, or raise when distinct specs share a name. At minimum warn on reuse.

Medium

  • hub_heights collision across farmswifa/pywake_api.py:97-100, 294, 1234. Single-type farms always key hub_heights with local "0"; hub_heights.update(hh) overwrites prior farms. Distinct hub heights are lost, breaking height-dependent site interpolation / FUGA setup. Fix: key by global turbine-type index (or farm-scoped key) and derive first_hh from merged global turbine objects.

  • generate_outputs still receives a list in multi-farm pathwifa/pywake_api.py:~1249. generate_outputs(sim_results, system_dat, ...) was written for a single-farm dict; in the multi-farm branch system_dat["wind_farm"] is a list. Either crashes iterating farm_dat["layouts"] or silently writes only farm 0's artifacts. The new test only checks the return value. Fix: teach generate_outputs to handle a farm list (per-farm outputs), or branch/skip and document the gap. Extend the test to assert output-dir contents.

  • farm_dat = farms[0] as a single-farm stand-inwifa/pywake_api.py:~1218. Inline comment admits "assumes shared turbine spec across farms." Any downstream code reading farm_dat (e.g. rd lookup, layout-derived state) silently uses farm 0 only — defeating the point of multi-farm. Fix: refactor downstream usages to operate per-farm, or assert single-turbine-type in the multi-farm path. Don't paper over with a comment.

  • Flaky wall-clock assertiontests/test_pywake.py:~516 (test_pywake_multifarm_runs_fast). assert elapsed < 10.0 is flaky on shared CI and doesn't validate correctness. Fix: drop the timing assertion (or move to an opt-in benchmark) and rename the test to reflect what it verifies (per-farm AEP + wake interaction).

Low

  • Unused _type_nameswifa/pywake_api.py:~284. Unpacked from _build_farm_turbine_list but never used; the type-name → global-index map is rebuilt from wt.name(), inconsistent with the per-farm "0"-style keys. Fix: remove the unused return, or use _type_names consistently.

  • layouts shape assumptionwifa/pywake_api.py:~136 (_build_farm_turbine_list). The multi-type branch indexes farm_dat["layouts"][0]["turbine_types"] while the single-type branch handles both list and dict forms; a multi-type config with dict-form layouts crashes with an opaque error. Fix: normalize layouts to a list once at the top of the helper.

@SchmJo
Copy link
Copy Markdown
Contributor

SchmJo commented May 11, 2026

is this only for pywake? can we setup a new example case, such that I can also adopt foxes to read multiple farms from windio? Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants