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

Reply via email to