SU2
SU2 copied to clipboard
[WIP] Aero-Structural Discrete Adjoint Sensitivities and Python Wrapper Developments
Motivation
Fundamental bottlenecks exist for industrial adoption of high-fidelity physics codes with fully coupled discrete adjoint sensitivity analysis. These bottlenecks include a lack of flexibility, modularity, and robustness of the computational tools, as well as the potential startup development costs needed to implement and verify the MDAO features. The purpose of this work is to facilitate the coupling of SU2 with external structural codes (e.g. NASTRAN, TACS, Airbus structural suite Lagrange) for gradient-based aerodynamic shape and structural sizing optimization using dedicated frameworks (e.g. OpenMDAO).
Startup development costs include the creation of modular tools that are designed to be driven by another framework like OpenMDAO, rather than to drive execution themselves. However, leveraging those MDAO frameworks assumes that software codes and modules to be coupled exist, have appropriate data structures, execution and query APIs, and are wrapped in Python for flexibility and ease of use. The proposed changes were motivated with the goal of making SU2 more modular and flexible, particularly to facilitate its integration into large-scale MDAO frameworks. For more details on the motivation, methodology, and verification & validation results, please refer to our paper from AIAA Aviation 2022.
Proposed Changes
@aa-g and I propose the following code updates:
-
Implementation of residual-based discrete adjoint solver as
CDiscAdjResidualSolver
a. New config option:KIND_DISC_ADJ
-
Enhancements and standardization of SU2 Python API a. Add pysu2/pysu2ad methods b. Standardize Python API and function names c. Overloaded getter/setter methods to make data handling more flexible
Related Work
These efforts are related to Issue #1262, Pull Request #1300, and Discussion #1325.
PR Checklist
- [X] I am submitting my contribution to the develop branch.
- [ ] My contribution generates no new compiler warnings (try with --warnlevel=3 when using meson).
- [X] My contribution is commented and consistent with SU2 style (https://su2code.github.io/docs_v7/Style-Guide/).
- [X] 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.
This is not the preferred way to contribute to open source, especially considering that the refactoring PR already had comments.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If this is still a relevant issue please comment on it to restart the discussion. Thank you for your contributions.
Okay @pcarruscag I believe I reverted all the annoying format changes. Can you please review the code when you get the chance?
BTW I am aware about the boilerplate code in python_wrapper_structure.cpp
and I plan to adapt CPyWrapperMatrixView
. Would appreciate some feedback anyways
Can you describe how the functions and modes you are adding are used? Maybe a python example would help. It seems a lot of this exists in the disc adj multizone driver, for example the derivative of the objective function is stored by that driver.
Can you describe how the functions and modes you are adding are used? Maybe a python example would help. It seems a lot of this exists in the disc adj multizone driver, for example the derivative of the objective function is stored by that driver.
Yes, I will definitely add a Python example and supporting documentation.
Essentially we modified the recording, seeding, and extracting of the AD tape in CDiscAdjResidualSolver
to provide partial derivatives of objective, residuals, and forces with respect to conservative variables, coordinates, displacements, and farfield variables. We need the partials to form and solve the adjoint system, which is handled by external MDO framework
Sounds good, with that it will be easier to reason about when the recording types are created and used, right now someone would have to sit down and reverse-engineer the process. My intuition is that we can use some of the machinery introduced for multizone (partial tape evaluation) to simplify the recording management. And just to be clear I am very interested in having this feature in the code for comparison with the FP approach.
Sounds good, with that it will be easier to reason about when the recording types are created and used, right now someone would have to sit down and reverse-engineer the process. My intuition is that we can use some of the machinery introduced for multizone (partial tape evaluation) to simplify the recording management. And just to be clear I am very interested in having this feature in the code for comparison with the FP approach.
That's exactly right. We started investigating the multizone driver a while back but we didn't get very far... It's been a while so i will need a refresher.
Sure, there's broader interest in comparison with FP. Ole, Nico, and I talked about doing a detailed characterization last summer and we briefly brought it up in Varenna last week
All the regression and unit tests are passing now!
The following functions in python_wrapper_structure.cpp
could be implemented as CPyWrapperMatrixView
:
Adjoints
- GetMarkerAdjointForces()
Sensitivities
- GetCoordinatesCoordinatesSensitivities()
- GetMarkerCoordinatesDisplacementsSensitivities()
- GetObjectiveFarfieldVariablesSensitivities()
- GetResidualsFarfieldVariablesSensitivities()
- GetObjectiveStatesSensitivities()
- GetResidualsStatesSensitivities()
- GetForcesStatesSensitivities()
- GetObjectiveCoordinatesSensitivities()
- GetResidualsCoordinatesSensitivities()
- GetForcesCoordinatesSensitivities()
- GetMarkerObjectiveDisplacementsSensitivities()
- GetMarkerResidualsDisplacementsSensitivities()
- GetMarkerForcesDisplacementsSensitivities()
- GetMarkerForceSensitivities()
Flow solution
- GetHeatFluxes()
- GetMarkerHeatFluxes()
- GetNonequilibriumMassFractions()
- GetVibrationalTemperatures()