-
Notifications
You must be signed in to change notification settings - Fork 849
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
Newton-Krylov primal iterations & Krylov discrete adjoint #1183
Conversation
Hi Pedro, seems like nice stuff is coming into being here.. 👍 just had a look at both papers, especially the second. From reading through the new integration class (and assuming you are working towards Newton-like iterations for FSI), could you point me to the coupled part? I'm expecting one has to assemble a "bigger" residual across the disciplines (or a routine that has the same functionality as a multiplication with it, like Algorithm 4 on page 943 in the paper from Kenway, Kennedy and Martins or what you are doing in |
Hi Ole, the first paper is actually closer to what I am aiming for with this implementation. |
This is a great new development! We would definitely need this for stiffer equations. At the moment most of our combustion models have 'OK' convergence, but this could really improve things! Is it functional for the incompressible flow testcases? |
In principle yes, but there are a few complications for coupling everything which made me take a step back:
The current implementation seems capable of pushing through some limit cycles that would otherwise just last forever. |
struct CSysMatrixComms { | ||
/*! | ||
* \brief Routine to load a vector quantity into the data structures for MPI point-to-point | ||
* communication and to launch non-blocking sends and recvs. |
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 also moved the MPI comms of CSysVectors out of the matrix, in time we can make this even more generic to communicate anything that "looks like" a CSysVector which would allow us to communicate solution variables without having to define enum types for them.
If there are no major comments I would add a testcase and merge this for the next release (and address any post mortem comments as they appear). |
AdjointProduct(CDiscAdjMultizoneDriver* d, unsigned short i) : driver(d), iZone(i) {} | ||
|
||
inline void operator()(const CSysVector<Scalar> & u, CSysVector<Scalar> & v) const override { | ||
driver->SetAllSolutions(iZone, true, u); | ||
driver->Iterate(iZone, iInnerIter, true); | ||
driver->GetAllSolutions(iZone, true, v); | ||
v -= u; |
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.
The "Krylov discrete adjoint" part is for the inner iterations of multizone problems.
It is based on manipulating the fixed point lambda = Ext + lambda (dx G)
into lambda (dx G - I) = -Ext
, and calling the LHS a "product" which is passed to GMRES.
This is not a strictly valid thing to do since there is a kind of flexible preconditioner in G, but it works better than the quasi-Newton thing (which is still available).
This manipulation is not possible for single zone because the RHS of the adjoint problem (i.e. the OF gradient) is not separate from the adjoints of the iteration (G).
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.
Please keep the quasi-Newton thing for a while, I'm still building the "real"-Newton thing (through a class inheriting from CQuasiNewtonInvLeastSquares
; one would have to figure out a common base class). Interestingly the real one requires the computation of Krylov subspaces, too, so there might be new or other overlaps..
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.
Of course, I'm a hoarder of features, I keep everything I can.
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.
Alright. From what I see, most of the implementation happens within the new integration class with little interference with the solver code. I'd have to read carefully through the first paper but I can also do it post mortem ;-)
I'll create a WIP for the Newton corrector in the next few days so that you can check what I'm up to there. I think it's quite different from what is done here though :-)
Proposed Changes
In a nutshell, we still solve a linear system to update the solution, but the approximate Jacobian is replaced by matrix-free products with the "real" Jacobian which are obtained by finite differences (each product requires the computation of the residual for a perturbed solution).
This linear system is much more ill-conditioned, and so in addition to the classical linear preconditioners, it is possible to use the traditional linear system as the preconditioner (you gotta love the kind of stuff SU2 lets you get away with sometimes).
This nesting makes each iteration potentially very expensive, it is crucial not to "over solve" the linear systems, and to use adaptive CFL to run always at the highest CFL possible.
Notwithstanding the preconditioner madness, this also works for explicit solvers, but that may only be good enough for dual time methods with relatively small time steps.
This seems to be good at converging problems that would otherwise not get past a limit cycle.
I do not expect it to be faster when that is not a problem.
Some references:
https://arc.aiaa.org/doi/abs/10.2514/6.2021-0857
https://arc.aiaa.org/doi/10.2514/1.J052255
Example config for the RANS ONERA M6 in the repo: turb_ONERAM6_nk.txt
It contains the explanation and recommendations for the different parameters.
The initial idea was to couple all solvers (flow, turbulence, etc.) but that makes the problem even more ill-conditioned and so I took a step back (as that also makes the implementation simpler...).
The skeleton of the coupled iteration exists in commit c97221b and it was functional... if anyone wants to take it further, it's there.
PR Checklist