Skip to content

Conversation

@bigfooted
Copy link
Contributor

@bigfooted bigfooted commented Jan 18, 2026

Proposed Changes

Give a brief overview of your contribution here in a few sentences.

Implement multigrid agglomeration according to Nishikawa and Diskin.

  • euler walls are working correctly.

  • mpi still needs to be checked.

  • I am submitting my contribution to the develop branch.

  • My contribution generates no new compiler warnings (try with --warnlevel=3 when using meson).

  • My contribution is commented and consistent with SU2 style (https://su2code.github.io/docs_v7/Style-Guide/).

  • I used the pre-commit hook to prevent dirty commits and used pre-commit run --all to format old commits.

  • I have added a test case that demonstrates my contribution, if necessary.

  • I have updated appropriate documentation (Tutorials, Docs Page, config_template.cpp), if necessary.

Comment on lines +60 to +64
MG_PRE_SMOOTH= ( 4, 4, 4, 4 )
MG_POST_SMOOTH= ( 4, 4, 4, 4 )
MG_CORRECTION_SMOOTH= ( 4, 4, 4, 4 )
MG_DAMP_RESTRICTION= 0.5
MG_DAMP_PROLONGATION= 0.5
Copy link
Contributor Author

Choose a reason for hiding this comment

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

When MG is finalized, these will be initial values and will be adaptively changed.

bigfooted and others added 5 commits January 26, 2026 14:02
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Comment on lines 179 to 183
if (nDim == 2) {
//agglomerate_seed = ((config->GetMarker_All_KindBC(copy_marker[0]) == SEND_RECEIVE) ||
// (config->GetMarker_All_KindBC(copy_marker[1]) == SEND_RECEIVE));

/* --- Euler walls can also not be agglomerated when the point has 2 markers ---*/
if ((config->GetMarker_All_KindBC(copy_marker[0]) == EULER_WALL) ||
(config->GetMarker_All_KindBC(copy_marker[1]) == EULER_WALL)) {
agglomerate_seed = false;
}

Check notice

Code scanning / CodeQL

Futile conditional Note

If-statement with an empty then-branch and no else-branch.

Copilot Autofix

AI about 23 hours ago

In general, to fix a futile conditional with an empty then-branch and no else-branch, either remove the conditional entirely if it serves no purpose, or implement the intended logic in the branch. Here, the if (nDim == 2) block is empty by design (its original body is commented out), and the 2D behavior is already described in the preceding comments, so the best minimal fix is to remove the empty if statement and keep behavior unchanged.

Concretely, in Common/src/geometry/CMultiGridGeometry.cpp, within the if (counter == 2) block around line 176–184, delete the if (nDim == 2) { ... } statement (including its now-comment-only body and braces), leaving the existing comments intact and retaining the if (nDim == 3) line. No new methods, imports, or definitions are required, and no other parts of the file need to change.

Suggested changeset 1
Common/src/geometry/CMultiGridGeometry.cpp

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/Common/src/geometry/CMultiGridGeometry.cpp b/Common/src/geometry/CMultiGridGeometry.cpp
--- a/Common/src/geometry/CMultiGridGeometry.cpp
+++ b/Common/src/geometry/CMultiGridGeometry.cpp
@@ -175,10 +175,7 @@
         /*--- In 3D, we agglomerate if the 2 markers are the same. ---*/
         if (counter == 2) {
           /*--- agglomerate if one of the 2 markers are MPI markers. ---*/
-          if (nDim == 2) {
-            // agglomerate_seed = ((config->GetMarker_All_KindBC(copy_marker[0]) == SEND_RECEIVE) ||
-            //                     (config->GetMarker_All_KindBC(copy_marker[1]) == SEND_RECEIVE));
-          }
+          // In 2D, agglomeration for this case is intentionally disabled; see comments above.
           /*--- agglomerate if both markers are the same. ---*/
           if (nDim == 3) agglomerate_seed = (copy_marker[0] == copy_marker[1]);
 
EOF
@@ -175,10 +175,7 @@
/*--- In 3D, we agglomerate if the 2 markers are the same. ---*/
if (counter == 2) {
/*--- agglomerate if one of the 2 markers are MPI markers. ---*/
if (nDim == 2) {
// agglomerate_seed = ((config->GetMarker_All_KindBC(copy_marker[0]) == SEND_RECEIVE) ||
// (config->GetMarker_All_KindBC(copy_marker[1]) == SEND_RECEIVE));
}
// In 2D, agglomeration for this case is intentionally disabled; see comments above.
/*--- agglomerate if both markers are the same. ---*/
if (nDim == 3) agglomerate_seed = (copy_marker[0] == copy_marker[1]);

Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +848 to +858
// /*--- If seed has 2 markers and one is SEND_RECEIVE, do not agglomerate with physical boundary ---*/
// if ((marker_seed.size() == 2) && (config->GetMarker_All_KindBC(marker_seed[0]) == SEND_RECEIVE)) {
// if (copy_marker[0] == marker_seed[1]) {
// agglomerate_CV = false;
// }
// }
// if ((marker_seed.size() == 2) && (config->GetMarker_All_KindBC(marker_seed[1]) == SEND_RECEIVE)) {
// if (copy_marker[0] == marker_seed[0]) {
// agglomerate_CV = false;
// }
// }

Check notice

Code scanning / CodeQL

Commented-out code Note

This comment appears to contain commented-out code.

Copilot Autofix

AI about 23 hours ago

To fix the problem in general, remove or properly document any commented-out executable code. If the logic is needed, it should be reinstated as normal code and covered by tests; if it is not needed, it should be deleted. Comments should be reserved for explanations, high-level descriptions, or true examples clearly marked as such, not as a storage place for disabled logic.

In this specific case, the single best way to fix the issue without changing existing functionality is to delete the commented-out if blocks on lines 846–856 that implement the SEND_RECEIVE special case. The surrounding active logic (for counter == 1) already sets agglomerate_CV under its own conditions; removing the dead code leaves behavior unchanged while eliminating the static-analysis warning and improving readability. No new methods, imports, or definitions are needed; we just edit Common/src/geometry/CMultiGridGeometry.cpp to remove those commented if statements, keeping the rest of the comment block intact and preserving indentation.

Suggested changeset 1
Common/src/geometry/CMultiGridGeometry.cpp

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/Common/src/geometry/CMultiGridGeometry.cpp b/Common/src/geometry/CMultiGridGeometry.cpp
--- a/Common/src/geometry/CMultiGridGeometry.cpp
+++ b/Common/src/geometry/CMultiGridGeometry.cpp
@@ -843,18 +843,6 @@
         // note that this should be the same marker id, not just the same marker type.
         if ((marker_seed.size() == 1) && (copy_marker[0] == marker_seed[0])) agglomerate_CV = true;
 
-        // /*--- If seed has 2 markers and one is SEND_RECEIVE, do not agglomerate with physical boundary ---*/
-        // if ((marker_seed.size() == 2) && (config->GetMarker_All_KindBC(marker_seed[0]) == SEND_RECEIVE)) {
-        //   if (copy_marker[0] == marker_seed[1]) {
-        //     agglomerate_CV = false;
-        //   }
-        // }
-        // if ((marker_seed.size() == 2) && (config->GetMarker_All_KindBC(marker_seed[1]) == SEND_RECEIVE)) {
-        //   if (copy_marker[0] == marker_seed[0]) {
-        //     agglomerate_CV = false;
-        //   }
-        // }
-
         /*--- Note: If there is only one marker, but the marker is the SEND_RECEIVE, then the point is actually an
               interior point and we do not agglomerate.  ---*/
       }
EOF
@@ -843,18 +843,6 @@
// note that this should be the same marker id, not just the same marker type.
if ((marker_seed.size() == 1) && (copy_marker[0] == marker_seed[0])) agglomerate_CV = true;

// /*--- If seed has 2 markers and one is SEND_RECEIVE, do not agglomerate with physical boundary ---*/
// if ((marker_seed.size() == 2) && (config->GetMarker_All_KindBC(marker_seed[0]) == SEND_RECEIVE)) {
// if (copy_marker[0] == marker_seed[1]) {
// agglomerate_CV = false;
// }
// }
// if ((marker_seed.size() == 2) && (config->GetMarker_All_KindBC(marker_seed[1]) == SEND_RECEIVE)) {
// if (copy_marker[0] == marker_seed[0]) {
// agglomerate_CV = false;
// }
// }

/*--- Note: If there is only one marker, but the marker is the SEND_RECEIVE, then the point is actually an
interior point and we do not agglomerate. ---*/
}
Copilot is powered by AI and may make mistakes. Always verify output.
bigfooted and others added 4 commits January 28, 2026 17:06
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
@bigfooted bigfooted changed the title [WIP] Fix multigrid agglomeration Fix multigrid agglomeration Jan 28, 2026
Comment on lines 344 to 352
/*--- Force sequential execution of recursive calls for determinism ---*/
SU2_OMP_BARRIER
SU2_OMP_MASTER
{
// Empty - just ensures only one thread enters the recursion at a time
}
END_SU2_OMP_MASTER
SU2_OMP_BARRIER

Copy link
Contributor

Choose a reason for hiding this comment

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

What's the intent here? Right now, it seems equivalent to a plain SU2_OMP_BARRIER.

Copy link
Contributor Author

@bigfooted bigfooted Feb 2, 2026

Choose a reason for hiding this comment

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

Thanks Johannes, for looking into this. I was testing some OMP stuff because it was giving me non-deterministic results (different convergence nr of iterations per run). I will clean this up as well.

*/
void SetRestricted_Solution(unsigned short RunTime_EqSystem, CSolver *sol_fine, CSolver *sol_coarse,
CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config);
CGeometry *geo_fine, CGeometry *geo_coarse, CConfig *config, unsigned short iMesh = 999);
Copy link
Member

Choose a reason for hiding this comment

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

why the magic 999?

Comment on lines +179 to +180
// agglomerate_seed = ((config->GetMarker_All_KindBC(copy_marker[0]) == SEND_RECEIVE) ||
// (config->GetMarker_All_KindBC(copy_marker[1]) == SEND_RECEIVE));
Copy link
Member

Choose a reason for hiding this comment

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

wip? or the comment above if counter == 2 needs to be updated?


/*--- Reset state at the beginning of a new solve (iter 0 or 1) ---*/
/*--- This ensures deterministic behavior across multiple runs ---*/
static unsigned long last_reset_iter = ULONG_MAX;
Copy link
Member

Choose a reason for hiding this comment

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

yeah this gets a bit out of hand xD

/*--- Update LocalCFL at each coarse grid point ---*/
SU2_OMP_FOR_STAT(roundUpDiv(geometry_coarse->GetnPoint(), omp_get_num_threads()))
for (auto iPoint = 0ul; iPoint < geometry_coarse->GetnPoint(); iPoint++) {
solver_coarse->GetNodes()->SetLocalCFL(iPoint, CFL_coarse_new);
Copy link
Member

Choose a reason for hiding this comment

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

Make a function for the adaptation, please.


}

/*--- MPI sync after RK stage to ensure halos have updated solution for next smoothing iteration ---*/
Copy link
Member

Choose a reason for hiding this comment

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

I don't see why this would be necessary, in the whole code we always communicate everything after it is computed, so this is either missing somewhere else, or masking another issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ok, I'll check if this can now be removed, it seemed to be useful before.


delete [] Solution;

/*--- Ensure all threads complete before MPI communication ---*/
Copy link
Member

Choose a reason for hiding this comment

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

Not needed, for loops have an implied barrier at the end.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ah ok, I guess this shows my lack of knowledge regarding OMP implementation.

Copy link
Member

Choose a reason for hiding this comment

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

That's what the standard says, it's not our implementation doing funny bussiness.
If you want a loop that doesn't sync, you need to explicitly use the "no wait" directive.

Comment on lines +664 to +665
/*--- Ensure MPI completion visible to all threads ---*/
SU2_OMP_BARRIER
Copy link
Member

Choose a reason for hiding this comment

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

Same comment about CompleteComms.
We use funneled communications, so I'm pretty sure we have a barrier somewhere in the comms.

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.

4 participants