Skip to content

[BUGFIX] TurbOParkGauss mirror wakes geometry - #1206

Open
misi9170 wants to merge 3 commits into
NatLabRockies:developfrom
misi9170:bugfix/tp-mirror-wakes
Open

misi9170 wants to merge 3 commits into
NatLabRockies:developfrom
misi9170:bugfix/tp-mirror-wakes

Conversation

@misi9170

@misi9170 misi9170 commented Sep 9, 2026 •

Copy link
Copy Markdown
Collaborator

@MarkJamesSpring pointed out in #1205 that there is a bug in the implementation of the TurbOParkGauss model when the include_mirror_wakes flag is set to true. After digging into this a bit, it seems that there was a small geometry error in the original implementation #907 that we had overlooked until now.

In particular, the $z$ distance between an evaluation point z and the mirrored turbine was coded as z - 3*z_i, whereas I believe it should have been $z + z_i$ (see my sketch below, where the evaluation point location is denoted $(y_p, z_p)$ ).

PXL_20260909_160433443

This PR corrects the distance to z + z_i. The regression test values do change slightly with this change, but the differences are small.

Moreover, the resulting power difference is minimal. Running examples/example_turbopark/001_compare_turbopark_implementations.py prior to this change produces
f_orig

whereas with the change, the plots are
f_update

(that is, not visually different to my eye).

On the other hand, as discussed in #1205, examples/examples_visualization/002_visualize_cut_plane.py with "../inputs/gch.yaml" replaced by "../inputs/turboparkgauss.yaml" changes significantly, from the clearly erroneous
ff_orig

to a much better-looking

ff_change

In debugging, I also added a new test that checks that the front-row turbine in a shear layer is not affected by mirror wakes. As it turns out, this test would not have caught the bug anyway, but I figured I'd leave it in because it's a good test to have.

@misi9170 misi9170 added the bug Something isn't working label Sep 9, 2026
@misi9170
misi9170 requested review from rafmudaf and a lite review from Copilot September 9, 2026 16:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The regression test file enables DEBUG logging and the new unit test uses default allclose tolerances that may be flaky across environments.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Fixes the mirrored (image) turbine geometry used by the TurbOParkGauss velocity deficit model when mirror wakes are enabled, correcting the vertical distance calculation and updating tests accordingly.

Changes:

  • Correct mirrored-wake radial distance calculation in TurboparkgaussVelocityDeficit (z + z_i instead of z - 3*z_i).
  • Add a unit test ensuring front-row turbines are unaffected by enabling mirror wakes in a high-shear setup.
  • Update TurbOParkGauss regression baselines to reflect the corrected geometry.
File summaries
File Description
floris/core/wake_velocity/turboparkgauss.py Fixes mirror-wake geometry in radial distance calculation.
tests/turboparkgauss_unit_test.py Adds a mirror-wakes unit test for front-row invariance.
tests/reg_tests/turboparkgauss_regression_test.py Updates regression expected values (and currently enables DEBUG).
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread tests/turboparkgauss_unit_test.py
Comment thread tests/reg_tests/turboparkgauss_regression_test.py Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@misi9170

misi9170 commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator Author

@JasperShell Just tagging you here in case you think that the original implementation was actually correct---certainly no problem if it wasn't, I overlooked it in my review! As I mention above, power predictions only change very slightly as a result of the update.

Misha

@misi9170
misi9170 changed the base branch from main to develop September 9, 2026 16:42
@misi9170

misi9170 commented Sep 11, 2026 •

Copy link
Copy Markdown
Collaborator Author

Quick update here: I believe the reason that there is very minimal impact to the power of downstream turbines with this change is that the way the $z$-distance is used is in computing the height difference between the test point and the hub height of the turbine (or mirror turbine) producing the wake; this height distance is then squared in the process of computing the absolute distance to the test point from the hub location of the upstream turbine (using the Pythagorean theorem).

For downstream turbines (that are the same type as the upstream turbine), the test height $z$ is (roughly) equal to the hub height $z_i$. In this case, letting $z = z_i$, we have

$(z + z_i)^2 = (z_i + z_i)^2 = (2z_i)^2 = 4 z_i^2$.

If we instead use the form $z - 3z_i$, we have

$(z - 3z_i)^2 = (z_i - 3z_i)^2 = (-2z_i)^2 = 4 z_i^2$.

Taking this a little further, we'll find that small, symmetric perturbations to the evaluation points (because the flow is evaluated across the rotor, not just at the hub height) tend to (almost) cancel out when we average the rotor velocities to compute power.

If the evaluation point is $z = z_i + \delta z$, method 1 produces

$(z + z_i)^2 = (z_i + \delta_z + z_i)^2 = (2z_i + \delta z)^2 = 4z_i^2 + 2z_i\delta z_i + \delta z_i^2$

and if the evaluation point is $z = z_i + \delta z$, method 1 produces

$(z + z_i)^2 = (z_i - \delta_z + z_i)^2 = (2z_i - \delta z)^2 = 4z_i^2 - 2z_i\delta z_i + \delta z_i^2$

Now, using method 2, $z = z_i + \delta z$ produces

$(z + z_i)^2 = (z_i + \delta_z - 3z_i)^2 = (-2z_i + \delta z)^2 = 4z_i^2 - 2z_i\delta z_i + \delta z_i^2$

and $z = z_i - \delta z$ produces

$(z + z_i)^2 = (z_i - \delta_z - 3z_i)^2 = (-2z_i - \delta z)^2 = 4z_i^2 + 2z_i\delta z_i + \delta z_i^2$

These are the same solutions as method 1, but flipped, so as long as both $z = z_i + \delta z$ and $z = z_i - \delta z$ always contribute to power as pairs, the effects cancel out. However, when we evaluate points $z$ that are not near the hub height $z_i$ and are not used in pairs, as in the visualization solve, the "problem" becomes evident.

I think the reason that the pairs of points don't actually completely cancel when computing turbine power (so the reg tests had to be updated slightly) may be because of the shear layer, although I'm not 100% sure.

This branch has not been deployed

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

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants