Hi, actually, I have a follow up on this topic. I noticed that when I call SNESSetFunctionDomainError(), it exits the solve as expected, but it leads to a converged reason "DIVERGED_LINE_SEARCH" instead of "DIVERGED_FUNCTION_DOMAIN". If I also set SNESSetConvergedReason(snes, SNES_DIVERGED_FUNCTION_DOMAIN) in the callback, then I get the expected SNES_DIVERGED_FUNCTION_DOMAIN converged reason, so that's what I'm doing now. I was surprised by this behavior, though, since I expected that calling SNESSetFunctionDomainError woudld lead to the DIVERGED_FUNCTION_DOMAIN converged reason, so I just wanted to check on what could be causing this.
FYI, I'm using PETSc 3.23.4 Thanks, David On Thu, Dec 18, 2025 at 8:10 AM David Knezevic <[email protected]> wrote: > Thank you very much for this guidance. I switched to use > SNES_DIVERGED_FUNCTION_DOMAIN, and I don't get any errors now. > > Thanks! > David > > > On Wed, Dec 17, 2025 at 3:43 PM Barry Smith <[email protected]> wrote: > >> >> >> On Dec 17, 2025, at 2:47 PM, David Knezevic <[email protected]> >> wrote: >> >> Stefano and Barry: Thank you, this is very helpful. >> >> I'll give some more info here which may help to clarify further. Normally >> we do just get a negative "converged reason", as you described. But in this >> specific case where I'm having issues the solve is a numerically sensitive >> creep solve, which has exponential terms in the residual and jacobian >> callback that can "blow up" and give NaN values. In this case, the root >> cause is that we hit a NaN value during a callback, and then we throw an >> exception (in libMesh C++ code) which I gather leads to the SNES solve >> exiting with this error code. >> >> Is there a way to tell the SNES to terminate with a negative "converged >> reason" because we've encountered some issue during the callback? >> >> >> In your callback you should call SNESSetFunctionDomainError() and make >> sure the function value has an infinity or NaN in it (you can call >> VecFlag() for this purpose)). >> >> Now SNESConvergedReason will be a completely >> reasonable SNES_DIVERGED_FUNCTION_DOMAIN >> >> Barry >> >> If you are using an ancient version of PETSc (I hope you are using the >> latest since that always has more bug fixes and features) that does not >> have SNESSetFunctionDomainError then just make sure the function vector >> result has an infinity or NaN in it and then SNESConvergedReason will be >> SNES_DIVERGED_FNORM_NAN >> >> >> >> >> Thanks, >> David >> >> >> On Wed, Dec 17, 2025 at 2:25 PM Barry Smith <[email protected]> wrote: >> >>> >>> >>> On Dec 17, 2025, at 2:08 PM, David Knezevic via petsc-users < >>> [email protected]> wrote: >>> >>> Hi, >>> >>> I'm using PETSc via the libMesh framework, so creating a MWE is >>> complicated by that, unfortunately. >>> >>> The situation is that I am not modifying the solution vector in a >>> callback. The SNES solve has terminated, with PetscErrorCode 82, and I then >>> want to update the solution vector (reset it to the "previously converged >>> value") and then try to solve again with a smaller load increment. This is >>> a typical "auto load stepping" strategy in FE. >>> >>> >>> Once a PetscError is generated you CANNOT continue the PETSc program, >>> it is not designed to allow this and trying to continue will lead to >>> further problems. >>> >>> So what you need to do is prevent PETSc from getting to the point >>> where an actual PetscErrorCode of 82 is generated. Normally SNESSolve() >>> returns without generating an error even if the nonlinear solver failed >>> (for example did not converge). One then uses SNESGetConvergedReason to >>> check if it converged or not. Normally when SNESSolve() returns, regardless >>> of whether the converged reason is negative or positive, there will be no >>> locked vectors and one can modify the SNES object and call SNESSolve again. >>> >>> So my guess is that an actual PETSc error is being generated >>> because SNESSetErrorIfNotConverged(snes,PETSC_TRUE) is being called by >>> either your code or libMesh or the option -snes_error_if_not_converged is >>> being used. In your case when you wish the code to work after a >>> non-converged SNESSolve() these options should never be set instead you >>> should check the result of SNESGetConvergedReason() to check if SNESSolve >>> has failed. If SNESSetErrorIfNotConverged() is never being set that may >>> indicate you are using an old version of PETSc or have it a bug inside >>> PETSc's SNES that does not handle errors correctly and we can help fix the >>> problem if you can provide a full debug output version of when the error >>> occurs. >>> >>> Barry >>> >>> >>> >>> >>> >>> >>> >>> >>> I think the key piece of info I'd like to know is, at what point is the >>> solution vector "unlocked" by the SNES object? Should it be unlocked as >>> soon as the SNES solve has terminated with PetscErrorCode 82? Since it >>> seems to me that it hasn't been unlocked yet (maybe just on a subset of the >>> processes). Should I manually "unlock" the solution vector by >>> calling VecLockWriteSet? >>> >>> Thanks, >>> David >>> >>> >>> >>> On Wed, Dec 17, 2025 at 2:02 PM Stefano Zampini < >>> [email protected]> wrote: >>> >>>> You are not allowed to call VecGetArray on the solution vector of an >>>> SNES object within a user callback, nor to modify its values in any other >>>> way. >>>> Put in C++ lingo, the solution vector is a "const" argument >>>> It would be great if you could provide an MWE to help us understand >>>> your problem >>>> >>>> >>>> Il giorno mer 17 dic 2025 alle ore 20:51 David Knezevic via petsc-users >>>> <[email protected]> ha scritto: >>>> >>>>> Hi all, >>>>> >>>>> I have a question about this error: >>>>> >>>>>> Vector 'Vec_0x84000005_0' (argument #2) was locked for read-only >>>>>> access in unknown_function() at unknown file:0 (line numbers only >>>>>> accurate >>>>>> to function begin) >>>>> >>>>> >>>>> I'm encountering this error in an FE solve where there is an error >>>>> encountered during the residual/jacobian assembly, and what we normally do >>>>> in that situation is shrink the load step and continue, starting from the >>>>> "last converged solution". However, in this case I'm running on 32 >>>>> processes, and 5 of the processes report the error above about a "locked >>>>> vector". >>>>> >>>>> We clear the SNES object (via SNESDestroy) before we reset the >>>>> solution to the "last converged solution", and then we make a new SNES >>>>> object subsequently. But it seems to me that somehow the solution vector >>>>> is >>>>> still marked as "locked" on 5 of the processes when we modify the solution >>>>> vector, which leads to the error above. >>>>> >>>>> I was wondering if someone could advise on what the best way to handle >>>>> this would be? I thought one option could be to add an MPI barrier call >>>>> prior to updating the solution vector to "last converged solution", to >>>>> make >>>>> sure that the SNES object is destroyed on all procs (and hence the locks >>>>> cleared) before editing the solution vector, but I'm unsure if that would >>>>> make a difference. Any help would be most appreciated! >>>>> >>>>> Thanks, >>>>> David >>>>> >>>> >>>> >>>> -- >>>> Stefano >>>> >>> >>> >>
