Skip to content

AD: fix OLAF treecode near-core regularization floor and TwrInfl OpenMP data race - #3430

Open
luwang00 wants to merge 2 commits into
OpenFAST:rc-5.0.1from
luwang00:b/OLAF
Open

AD: fix OLAF treecode near-core regularization floor and TwrInfl OpenMP data race#3430
luwang00 wants to merge 2 commits into
OpenFAST:rc-5.0.1from
luwang00:b/OLAF

Conversation

@luwang00

@luwang00 luwang00 commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Feature or improvement description
FVW treecode: the wake path used Tree%DistanceDirect = 2*mean(RegParam), averaged over an over-allocated array whose sentinel tail drove it negative during wake buildup, disabling the near-core direct-evaluation fallback. Replace it with a per-node maxRegParam (max eps over the cell's particles); each branch now uses distDirect = BranchFactor*radius + 2*maxRegParam so control points inside a regularization core fall back to direct evaluation. Applied to both the particle and segment trees.

TwrInflArray: make FirstWarn_TowerStrike firstprivate and ErrStat2/ErrMsg2 private in the OpenMP loop to avoid a data race.

In ui_part_nograd_11, the idRegExp mollifier (1-exp(-(r/rc)^3))/r^3 differs from 1/r^3 by <exp(-8)~3.4e-4 once r>2*rc, which is exactly the accuracy the far-field multipole already accepts at its BranchFactor*radius+2*maxRegParam floor. Treat the mollifier as 1 beyond that boundary (new PART_REG_NRAD/PART_REG_CUT3 params) so the near-field direct kernel and the far-field multipole share the same 2*rc cutoff. Since most near-field tree pairs have r>>rc, this skips exp() for the majority of evaluations, giving ~25-32 percent serial speedup on the treecode path with the output unchanged to ~1.8e-5 relative. Also caches r^2/r^3/rc^3 to drop redundant calculations; the compact-support branch is refactored identically (bit-for-bit).

Related issue, if one exists
There are several reported issues with OLAF. Unclear if this fix addresses any of them.

Impacted areas of the software
OLAF

Generative AI usage
Co-authored-by: Microsoft Copilot copilot@microsoft.com
Co-authored-by: Anthropic Claude claude@anthropic.com

Test results, if applicable
One r-test needs rebasing: ad_BAR_OLAF. Very small differences.

  • r-test branch merging required

…MP data race

FVW treecode: the wake path used Tree%DistanceDirect = 2*mean(RegParam), averaged over an over-allocated array whose sentinel tail drove it negative during wake buildup, disabling the near-core direct-evaluation fallback. Replace it with a per-node maxRegParam (max eps over the cell's particles); each branch now uses distDirect = BranchFactor*radius + 2*maxRegParam so control points inside a regularization core fall back to direct evaluation. Applied to both the particle and segment trees.

TwrInflArray: make FirstWarn_TowerStrike firstprivate and ErrStat2/ErrMsg2 private in the OpenMP loop to avoid a data race.

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus <noreply@anthropic.com>
In ui_part_nograd_11 the idRegExp mollifier (1-exp(-(r/rc)^3))/r^3 differs from 1/r^3 by <exp(-8)~3.4e-4 once r>2*rc, which is exactly the accuracy the far-field multipole already accepts at its BranchFactor*radius+2*maxRegParam floor. Treat the mollifier as 1 beyond that boundary (new PART_REG_NRAD/PART_REG_CUT3 params) so the near-field direct kernel and the far-field multipole share the same 2*rc cutoff. Since most near-field tree pairs have r>>rc, this skips exp() for the majority of evaluations, giving ~25-32 percent serial speedup on the treecode path with the output unchanged to ~1.8e-5 relative. Also caches r^2/r^3/rc^3 to drop redundant ** intrinsics; the compact-support branch is refactored identically (bit-for-bit).

FVW_Subs: scope the DEV_VERSION NaN/sentinel checks in SegmentsToPartWrap to the active particles (1:nPart); the preallocated tail intentionally keeps its sentinel and must not trip the check.

Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>

Co-authored-by: Claude Opus <noreply@anthropic.com>

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.

Pull request overview

This PR adjusts OLAF/FVW induced-velocity computation to make near-core/direct-evaluation behavior robust during wake buildup, removes an OpenMP data race in tower-influence calculations, and optimizes the particle exponential-regularization kernel to reduce expensive exp() calls while keeping results within the stated tolerance.

Changes:

  • Replace the global tree “direct-eval distance” floor (based on a mean regularization parameter) with a per-node maxRegParam floor used during traversal for both particle and segment trees.
  • Fix an OpenMP data race in TwrInflArray by making loop-local state (FirstWarn_TowerStrike, ErrStat2/ErrMsg2) thread-safe.
  • Optimize ui_part_nograd_11 by reusing r^2/r^3/rc^3 and skipping the exponential mollifier computation for r > 2*rc.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
modules/aerodyn/src/FVW_VortexTools.f90 Adds per-node maxRegParam and applies it in tree traversal to enforce a near-core direct-evaluation floor.
modules/aerodyn/src/FVW_Subs.f90 Restricts DEV NaN/sentinel checks to active particle ranges to avoid false negatives from preallocated tails.
modules/aerodyn/src/FVW_BiotSavart.f90 Speeds up particle exponential regularization by sharing the same 2*rc cutoff as the far-field floor and caching powers of r/rc.
modules/aerodyn/src/AeroDyn.f90 Removes an OpenMP data race in TwrInflArray via firstprivate/private scoping.

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

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants