-
Notifications
You must be signed in to change notification settings - Fork 35
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
structure quasi-static solver try/catch too general #658
Comments
I think I do not have a clear answer to this right now. Let me start with general considerations: A main problem that I see is that it is generally difficult to identify the precise reason for convergence failure of a linear/nonlinear solver. Many users have probably experienced that too large a time step for incompressible flows causes convergence failure of the pressure Poisson solver, and that it needs some experience to link this convergence failure to a violation of the CFL condition. For this example, I currently consider it difficult to considerably improve the situation from a user perspective by doing more refined throw/catch techniques for the linear solver, apart from listing/printing many possible reasons for convergence failure (collected over time from user experience) in case the problem fails to converge. So I have some concerns that we can come up with kind of an automatic solution to this type of problems, but I am very happy if you see possibilities for improvements in this direction. I could imagine it can also happen that the same problem might cause failure of the Newton solver or failure of the linear solver (depending on some other parameters), making it hard to draw conclusions from try/catch techniques. Regarding e.g. the (other) problem with invalid deformation states (Jacobian) for structural problems with large deformation, in my experience it helped more to explicitly do such checks (is the Jacobian valid?) than trying to react to non-convergence of a solver. This would imply we need to understand the problem that causes convergence failure and then integrate this knowledge into the code. In the beginning, you write "bugs", where I am not sure what you mean exactly, mistakes in implementation? Currently, I consider bugs a different topic than try/catch of run time errors.
I am not sure if I understood this correctly. Wouldn't this mean the simulation terminates in case the linear solver fails / throws an error (in case the outer try/catch block is removed)? However, from a user perspective there might still be the motivation to repeat the load step with a reduced load factor for example. Another disadvantage of removing Asserts from the Newton solver is that one would then have to implement corresponding messages at many places in the code that make use of the Newton solver. So I currently think additional parameters for the convergence state in the Newton solver (which might principally be helpful) do not allow to remove outer try/catch blocks. |
I think one of the intents of this issue is to discuss if we would like to try to separate convergence issues of any kind from other assertions we might throw, assertions that check missing parameters or missing cases. So in a sense, I believe that exadg/include/exadg/structure/time_integration/driver_quasi_static_problems.cpp Lines 171 to 175 in b9bc9fe
should not just pick any exception ... , but only a specific type of exceptions, e.g. those where the linear solver or nonlinear solver fail to converge, with infinite norms and other behavior. Unfortunately, deal.II is not really stringent in throwing useful exceptions for NaN or similar conditions (so I think we would need to do it in ExaDG, but I admit I have not looked closely), many of those actually use Assert instead of AssertThrow .
To give an example, if one of the ingredients inside the solver would throw an exception that a particular feature is not implemented inside the Newton solver, then this |
Thank you for your detailed answers and taking the time to type them down here!
I fully agree, I suggested to preserve the functionality, but using a different implementation (flags instead of exceptions). That was maybe a bit unclear, but I think passing around the flags is tedious anyways and custom exceptions might do the trick in a more elegant fashion.
|
My current solution goes along the lines of what @kronbichler suggested: introduce custom exceptions and catch them: |
The current behavior of this example code in debug mode is: |
The current behavior of this example code in release mode is: |
I think this is actually already quite close to what we want as a first step? |
Thank you for the experiment. I think case 2 and case 3 perform as expected (apart from the error message possibly, but that is a minor issue). For case 1, the difference in behavior for debug and release mode is a bit annoying, so here we should think about a better approach. I think that the case when we have This means that I agree with the points @nfehn made about the difficulty for automatically detecting non-convergence and the usefulness of repeating steps. Of course we should also work on other mechanisms to detect failure where they fit, because they might be more informative than the linear/nonlinear solver no-convergence. Regarding your code @richardschu I believe we need to be more restrictive, because if we use something like |
I think the try/catch block in the structure's quasi-static solver is too generous and can make finding bugs in any called linear solver quite hard. If you had any assertion thrown within the block, the solver would just state something like:
The only assertion we would like to catch is Newton solver divergence, which expresses itself in overflow/underflow some NaN possibly and linear solver nonconvergence ... maybe more? So identifying all these expections to catch would be one way.
Another way would be to pass in a boolean flag
newton_converged
, whichs state isfalse
originally and set to true only if everything went as expected. Then, we would remove theAssertThrow
s here and here in the Newton solver and simply rely on the returned flag (+return
statements). Then we could get rid of the try/catch block.Yet another option would be to define custom exceptions we can then throw and catch outside - maybe the cleanest option, were we do not rely on a flag passed around several software layers!
What are your opinions?
Once we converge at something, I volunteer to make a draft 🚀
The text was updated successfully, but these errors were encountered: