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?

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
>>
>
>

Reply via email to