Skip to content

Conversation

@bmunguia
Copy link
Member

@bmunguia bmunguia commented Nov 3, 2025

Proposed Changes

This PR is part of a joint effort with Alberto Perlini (@xla27) and Andrea Rausa (@rois1995) to implement anisotropic mesh adaptation in SU2. In our SU2 conference talks this year, I presented updates to the metric tensor computation in my fork for unsteady adaptation, and Alberto presented updates to the Python adaptation loop to use the open-source MMG remesher, as well as results for incompressible Euler/NS and NEMO.

Part 1 will focus on my contributions in SU2's post-processing/output to calculate metric tensor fields for feature-based adaptation. Part 2 will focus on the implementation of the adaptation loop in Python, including conversion between SU2 restarts/meshes and the .meshb format.

For the metric tensor field computation, I have implemented:

  • CVariable containers to store adaptation sensor variable/gradient/Hessian/metric tensor
    • We only store the lower-triangular elements of the Hessian/metric, so the size of the array at each point is $nSymMat = 3*(nDim-1)$
  • CSolver function SetPrimitive_Adapt() to store the chosen adaptation sensor
  • Green-Gauss Hessian calculation in computeGradientsGreenGauss.hpp which calculates the Hessian field for the chosen sensor and stores the lower triangle
  • Integration of the Hessian (symmetric positive definite by construction) determinant and Lp-norm normalization (see references) in computeMetrics.hpp
  • Integration of the Hessian field in time for unsteady adaptation
  • Output of metric tensor for different flow solvers, and updates to Paraview XML filewriter to allow for proper parsing of symmetric tensors

The following relevant config options have been added:

  • COMPUTE_METRIC (bool) - whether to calculate the sizing metric in post-processing (default False)
  • NORMALIZE_METRIC (bool) - whether to perform the Lp-norm normalization of Hessians (default True)
  • NUM_METHOD_HESS (str) - gradient method for Hessian calculation (only GG for now)
  • METRIC_SENSOR (str) - field to use for sizing metric
  • METRIC_NORM (unsigned short) - choice of norm for Lp-norm normalization
  • METRIC_COMPLEXITY (unsigned long) - target mesh size
  • METRIC_HMAX (float) - maximum cell size (constraint on minimum metric tensor eigenvalue)
  • METRIC_HMIN (float) - minimum cell size (constraint on maximum metric tensor eigenvalue)
  • METRIC_ARMAX (float) - maximum cell aspect ratio (constraint on ratio of hmax to hmin)

PR Checklist

  • 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.

References

  1. Loseille and Alauzet. “Continuous mesh framework part I: well-posed continuous interpolation error,” 2011.
  2. Alauzet and Loseille. “A decade of progress on anisotropic mesh adaptation for computational fluid dynamics,” 2016.
  3. Perlini. "Mesh adaptation in SU2: current status and perspectives," 2025.
  4. Munguía. "Towards a deep learning framework for time-accurate anisotropic mesh adaptation," 2025.

@pcarruscag
Copy link
Member

Is the mesh adaptation code itself open source?

@bmunguia
Copy link
Member Author

bmunguia commented Nov 3, 2025

If you mean MMG, it's on Github https://github.com/MmgTools/mmg

If you mean the SU2-MMG interface, it's in Alberto's fork https://github.com/xla27/SU2/tree/feat_adap_mmg

Copy link
Member

@pcarruscag pcarruscag left a comment

Choose a reason for hiding this comment

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

Excellent. Next question, what do you need from the python wrapper to do all of this outside of the SU2 core?

@bmunguia
Copy link
Member Author

bmunguia commented Nov 3, 2025

The python script basically just coordinates calls to SU2 and MMG in 2 nested loops, the inner loop being a series of adaptations at a given target mesh size and the outer loop being over a list of sizes. It also handles file conversions since MMG uses libmeshb for both the mesh and metric field.

For the file conversion, Alberto has a straight python implementation that I think only handles tris/tets, and I have a separate repo with a C++ implementation/python API that I used for my results that I presented in Varenna https://github.com/bmunguia/limon

@pcarruscag
Copy link
Member

Cool, the functionality would be more flexible if the sensor was also configurable via python, what you have here has a list of hardcoded possible variables, in python it would be very easy to target other solvers, create custom mixes of variables etc.
So maybe a helper to compute a generic gradient/hessian in c++?

void CSolver::CompleteComms(CGeometry *geometry,
const CConfig *config,
MPI_QUANTITIES commType) {

Check failure

Code scanning / CodeQL

Comparison of narrow type with wide type in loop condition High

Comparison between
iVar
of type unsigned short and
nVarHess
of wider type int.
MPI_QUANTITIES commType) {

/*--- Local variables ---*/

Check failure

Code scanning / CodeQL

Multiplication result converted to larger type High

Multiplication result may overflow 'int' before it is converted to 'unsigned long'.
auto& gradient = base_nodes->GetGradient_Adapt();
auto nHess = config->GetGoal_Oriented_Metric()? nVar : config->GetnMetric_Sensor();

computeGradientsGreenGauss(this, MPI_QUANTITIES::GRADIENT_ADAPT, PERIODIC_GRAD_ADAPT,

Check failure

Code scanning / CodeQL

Comparison of narrow type with wide type in loop condition High

Comparison between
iVar
of type unsigned short and
nVarHess
of wider type int.

computeGradientsGreenGauss(this, MPI_QUANTITIES::GRADIENT_ADAPT, PERIODIC_GRAD_ADAPT,
*geometry, *config, solution, 0, nHess, idxVel, gradient);

Check failure

Code scanning / CodeQL

Multiplication result converted to larger type High

Multiplication result may overflow 'int' before it is converted to 'unsigned long'.
Comment on lines +8019 to +8021
switch (Kind_Hessian_Method) {
case GREEN_GAUSS: cout << "Hessian for adaptive metric: Green-Gauss." << endl; break;
}

Check notice

Code scanning / CodeQL

No trivial switch statements Note

This switch statement should either handle more cases, or be rewritten as an if statement.
@bigfooted
Copy link
Contributor

Hi Brian, what's the status?

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.

3 participants