-
Notifications
You must be signed in to change notification settings - Fork 908
[WIP] Multizone adjoints for turbomachinery #2446
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
| AD::EndPreacc(); | ||
|
|
||
| /*--- Max is not differentiable, so we not register them for preacc. ---*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the difference between ending the preaccumulation before or after?
| } | ||
| } | ||
| } else if (Multizone_Problem && DiscreteAdjoint) { | ||
| SU2_MPI::Error(string("OUTPUT_WRT_FREQ cannot be specified for this solver " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| SU2_MPI::Error(string("OUTPUT_WRT_FREQ cannot be specified for this solver " | |
| SU2_MPI::Error("OUTPUT_WRT_FREQ cannot be specified for this solver " |
| "(writing of restart and sensitivity files not possible for multizone discrete adjoint during runtime yet).\n" | ||
| "Please remove this option from the config file, output files will be written when solver finalizes.\n"), CURRENT_FUNCTION); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm I'm pretty sure it is possible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is one for @oleburghardt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes and no, writing the files is fine, but the continuation of the multi-zone discrete adjoint solver is erratic. My guess is that some indices aren't cleared properly before re-recording the tape. (Writing adjoint solution variables to file only, without re-recording at all and without sensitivities, might give us some hints.)
The debug mode could eventually pin down where exactly things go wrong.
| BPressure = config->GetPressureOut_BC(); | ||
| Temperature = config->GetTotalTemperatureIn_BC(); | ||
|
|
||
| if (!reset){ | ||
| AD::RegisterInput(BPressure); | ||
| AD::RegisterInput(Temperature); | ||
| } | ||
|
|
||
| BPressure = config->GetPressureOut_BC(); | ||
| Temperature = config->GetTotalTemperatureIn_BC(); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are these wrong but not the others that follow the same pattern?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This threw a tagging error, and if I remember correctly it's because in the other sections the variables it accesses are directly used in the solver, whereas in the Giles implementation they are not, creating a mismatch in tags.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we fix it in a way that keeps a clear pattern for doing this type of thing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can give it a go
…ding of objective function calculation
… to run in quasi-MZ approach. (NEEDS CLEANING)
… MZ turbo testcase
…m/su2code/SU2 into feature_mz_turbomachinery_adjoint
| switch(donor_config->GetKind_MixingPlaneInterface()){ | ||
| case MATCHING: | ||
| targetSpan.donorSpan = iSpanTarget; | ||
| targetSpan.coefficient = 0.0; | ||
| break; | ||
|
|
||
| case NEAREST_SPAN: | ||
| // Find the nearest donor span | ||
| for (auto iSpanDonor = 0; iSpanDonor < nSpanDonor - 1; iSpanDonor++) { | ||
| const auto dist = abs(spanValuesTarget[iSpanTarget] - spanValuesDonor[iSpanDonor]); | ||
| if(dist < minDist){ | ||
| minDist = dist; | ||
| tSpan = iSpanDonor; | ||
| } | ||
| } | ||
| targetSpan.donorSpan = tSpan; | ||
| targetSpan.coefficient = 0.0; | ||
| break; | ||
|
|
||
| case LINEAR_INTERPOLATION: | ||
| { | ||
| bool printWarning = false; | ||
| // Check if target span is within donor bound | ||
| if (spanValuesTarget[iSpanTarget] <= spanValuesDonor[0]) { | ||
| // Below hub - use hub value | ||
| targetSpan.donorSpan = 0; | ||
| targetSpan.coefficient = 0.0; | ||
| printWarning = true; | ||
| } | ||
| else if (spanValuesTarget[iSpanTarget] >= spanValuesDonor[nSpanDonor - 1]) { | ||
| // Above shroud - use shroud value | ||
| targetSpan.donorSpan = nSpanDonor - 1; | ||
| targetSpan.coefficient = 0.0; | ||
| printWarning = true; | ||
| } | ||
| else { | ||
| // Find the donor span interval that brackets the target span | ||
| for (auto iSpanDonor = 0; iSpanDonor < nSpanDonor - 1; iSpanDonor++) { | ||
| const auto test = abs(spanValuesTarget[iSpanTarget] - spanValuesDonor[iSpanDonor]); | ||
| if(test < minDist && spanValuesTarget[iSpanTarget] > spanValuesDonor[iSpanDonor]){ | ||
| kSpan = iSpanDonor; | ||
| minDist = test; | ||
| } | ||
| } | ||
| // Calculate interpolation coefficient | ||
| coeff = (spanValuesTarget[iSpanTarget] - spanValuesDonor[kSpan]) / | ||
| (spanValuesDonor[kSpan + 1] - spanValuesDonor[kSpan]); | ||
| targetSpan.donorSpan = kSpan; | ||
| targetSpan.coefficient = coeff; | ||
| } | ||
| if (printWarning) { | ||
| if (rank == MASTER_NODE) { | ||
| cout << "Warning! Target spans exist outside the bounds of donor spans! Clamping interpolator..." << endl; | ||
| if (spanValuesTarget[iSpanTarget] <= spanValuesDonor[0]) cout << "This is an issue at the hub." << endl; | ||
| if (spanValuesTarget[iSpanTarget] >= spanValuesDonor[nSpanDonor - 1]) cout << "This is an issue at the shroud." << endl; | ||
| cout << "Setting coeff = 0.0 and transferring endwall value!" << endl; | ||
| } | ||
| } | ||
| break; | ||
| } | ||
| default: | ||
| SU2_MPI::Error("MixingPlane interface option not implemented yet", CURRENT_FUNCTION); | ||
| break; | ||
| } |
Check notice
Code scanning / CodeQL
Long switch case Note
LINEAR_INTERPOLATION (40 lines)
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 20 hours ago
To fix this issue, we should extract the lengthy content of the LINEAR_INTERPOLATION case into a dedicated method of CMixingPlane, such as HandleLinearInterpolation(...). This method should receive all the inputs needed (iSpanTarget, the spanValuesTarget/spanValuesDonor arrays, nSpanDonor, and so forth), and update the corresponding targetSpan for the current iteration. This reduces the switch case to a single function call for the LINEAR_INTERPOLATION case, improving readability and maintainability. Only code in the immediate code region related to the LINEAR_INTERPOLATION case and the class implementation may be changed; we must not touch files or lines not shown, nor alter unrelated imports or logic. The new function definition should be placed within the same file, as an appropriate member of CMixingPlane.
-
Copy modified lines R158-R165 -
Copy modified lines R174-R224
| @@ -155,46 +155,15 @@ | ||
| break; | ||
|
|
||
| case LINEAR_INTERPOLATION: | ||
| { | ||
| bool printWarning = false; | ||
| // Check if target span is within donor bound | ||
| if (spanValuesTarget[iSpanTarget] <= spanValuesDonor[0]) { | ||
| // Below hub - use hub value | ||
| targetSpan.donorSpan = 0; | ||
| targetSpan.coefficient = 0.0; | ||
| printWarning = true; | ||
| } | ||
| else if (spanValuesTarget[iSpanTarget] >= spanValuesDonor[nSpanDonor - 1]) { | ||
| // Above shroud - use shroud value | ||
| targetSpan.donorSpan = nSpanDonor - 1; | ||
| targetSpan.coefficient = 0.0; | ||
| printWarning = true; | ||
| } | ||
| else { | ||
| // Find the donor span interval that brackets the target span | ||
| for (auto iSpanDonor = 0; iSpanDonor < nSpanDonor - 1; iSpanDonor++) { | ||
| const auto test = abs(spanValuesTarget[iSpanTarget] - spanValuesDonor[iSpanDonor]); | ||
| if(test < minDist && spanValuesTarget[iSpanTarget] > spanValuesDonor[iSpanDonor]){ | ||
| kSpan = iSpanDonor; | ||
| minDist = test; | ||
| } | ||
| } | ||
| // Calculate interpolation coefficient | ||
| coeff = (spanValuesTarget[iSpanTarget] - spanValuesDonor[kSpan]) / | ||
| (spanValuesDonor[kSpan + 1] - spanValuesDonor[kSpan]); | ||
| targetSpan.donorSpan = kSpan; | ||
| targetSpan.coefficient = coeff; | ||
| } | ||
| if (printWarning) { | ||
| if (rank == MASTER_NODE) { | ||
| cout << "Warning! Target spans exist outside the bounds of donor spans! Clamping interpolator..." << endl; | ||
| if (spanValuesTarget[iSpanTarget] <= spanValuesDonor[0]) cout << "This is an issue at the hub." << endl; | ||
| if (spanValuesTarget[iSpanTarget] >= spanValuesDonor[nSpanDonor - 1]) cout << "This is an issue at the shroud." << endl; | ||
| cout << "Setting coeff = 0.0 and transferring endwall value!" << endl; | ||
| } | ||
| } | ||
| HandleLinearInterpolation( | ||
| targetSpan, | ||
| iSpanTarget, | ||
| spanValuesTarget, | ||
| spanValuesDonor, | ||
| nSpanDonor, | ||
| rank | ||
| ); | ||
| break; | ||
| } | ||
| default: | ||
| SU2_MPI::Error("MixingPlane interface option not implemented yet", CURRENT_FUNCTION); | ||
| break; | ||
| @@ -203,6 +171,57 @@ | ||
| } | ||
| } | ||
|
|
||
| // Helper method to handle LINEAR_INTERPOLATION logic for mixing planes | ||
| void CMixingPlane::HandleLinearInterpolation( | ||
| targetSpanData &targetSpan, | ||
| int iSpanTarget, | ||
| const std::vector<su2double> &spanValuesTarget, | ||
| const std::vector<su2double> &spanValuesDonor, | ||
| int nSpanDonor, | ||
| int rank | ||
| ) | ||
| { | ||
| bool printWarning = false; | ||
| int kSpan = 0; | ||
| su2double coeff = 0.0; | ||
| su2double minDist = 10E+06; | ||
| if (spanValuesTarget[iSpanTarget] <= spanValuesDonor[0]) { | ||
| // Below hub - use hub value | ||
| targetSpan.donorSpan = 0; | ||
| targetSpan.coefficient = 0.0; | ||
| printWarning = true; | ||
| } | ||
| else if (spanValuesTarget[iSpanTarget] >= spanValuesDonor[nSpanDonor - 1]) { | ||
| // Above shroud - use shroud value | ||
| targetSpan.donorSpan = nSpanDonor - 1; | ||
| targetSpan.coefficient = 0.0; | ||
| printWarning = true; | ||
| } | ||
| else { | ||
| // Find the donor span interval that brackets the target span | ||
| for (auto iSpanDonor = 0; iSpanDonor < nSpanDonor - 1; iSpanDonor++) { | ||
| const auto test = abs(spanValuesTarget[iSpanTarget] - spanValuesDonor[iSpanDonor]); | ||
| if(test < minDist && spanValuesTarget[iSpanTarget] > spanValuesDonor[iSpanDonor]){ | ||
| kSpan = iSpanDonor; | ||
| minDist = test; | ||
| } | ||
| } | ||
| // Calculate interpolation coefficient | ||
| coeff = (spanValuesTarget[iSpanTarget] - spanValuesDonor[kSpan]) / | ||
| (spanValuesDonor[kSpan + 1] - spanValuesDonor[kSpan]); | ||
| targetSpan.donorSpan = kSpan; | ||
| targetSpan.coefficient = coeff; | ||
| } | ||
| if (printWarning) { | ||
| if (rank == MASTER_NODE) { | ||
| cout << "Warning! Target spans exist outside the bounds of donor spans! Clamping interpolator..." << endl; | ||
| if (spanValuesTarget[iSpanTarget] <= spanValuesDonor[0]) cout << "This is an issue at the hub." << endl; | ||
| if (spanValuesTarget[iSpanTarget] >= spanValuesDonor[nSpanDonor - 1]) cout << "This is an issue at the shroud." << endl; | ||
| cout << "Setting coeff = 0.0 and transferring endwall value!" << endl; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void CMixingPlane::WriteInterpolationDetails(const std::string& filename, const CConfig* const* config) { | ||
| // Only write from master process in MPI | ||
| if (rank != MASTER_NODE) return; |

Proposed Changes
This is a cleaned up PR of the fixes needed for multizone adjoints for turbomachinery from the previous PR of @oleburghardt and I's work.
This hopefully is useable, so if you would like to test and report please feel free to contact me on Slack.
TODO:
Related Work
Now closed PR #2317
PR Checklist
Put an X by all that apply. You can fill this out after submitting the PR. If you have any questions, don't hesitate to ask! We want to help. These are a guide for you to know what the reviewers will be looking for in your contribution.
pre-commit run --allto format old commits.