[petsc-dev] SNESSetKSP and SNESDestroy

Pierre Jolivet pierre.jolivet at enseeiht.fr
Thu May 30 16:05:24 CDT 2019



> On 30 May 2019, at 10:51 PM, Stefano Zampini <stefano.zampini at gmail.com> wrote:
> 
> 
> 
>>> 
>>> 
>> 
>> Yeah… about that hack…
>> Before my first message, I tried something like:
>> 
>> 	SNESCreate(&snes);
>> 	KSP backup;
>> 	SNESGetKSP(snes, &backup);
>> 	SNESSetKSP(snes, &ksp);
>> 	SNESSolve(snes);
>> 	SNESSetKSP(snes, &backup);
>> 	SNESDestroy(&snes);
>> 
>> And this is bailing out ([1]PETSC ERROR: SNESSetKSP() Wrong type of object: Parameter # 2), which I find quite ironing since I’m getting the KSP from SNESGetKSP.
>> 
> 
> Pierre,
> 
> I assume you meant
> 
> SNESGetKSP(snes,&backup);
> SNESSetKSP(snes,ksp);
> SNESSolve(snes);
> SNESSetKSP(snes,backup);
> 
> The issue here is that the getter SNESGetKSP does not increase reference count on backup.
> So, when you do SNESSetKSP(snes,ksp) the object pointed to by backup is actually destroyed.
> This is why you got the error.
> 
> This is the correct code

Oops, didn’t check my inbox before sending the previous message.
This does get the job done in a much cleaner way.

Thanks!
Pierre

> SNESGetKSP(snes,&backup);
> PetscObjectReference((PetscObject)backup); // increase reference count
> SNESSetKSP(snes,ksp); // calls KSPdestroy on backup -> decrease reference count
> SNESSolve(snes);
> SNESSetKSP(snes,backup); // backup still points to a valid object
> KSPDestroy(&backup); // decrease reference count to backup (or destroy if it goes to zero)
> 
> 
>> SNESGetKSP(snes, &backup);
> 
>> 	KSP backup;
>> 	
>> 	SNESSetKSP(snes, &ksp);
>> SNESSolve(snes);
> 
>> SNESSetKSP(snes, &backup);
> 
>> As I’m typing this email I just tried something and the following fixes the hack: just add an extra KSPCreate on backup before the SNESDestroy.
>> 
>> Thanks,
>> Pierre
>> 
>>>>> 
>>>  KSP dummy;
>>>  KSPCreate(...,&dummy);
>>>>> KSP ksp;
>>>>> KSPSetUp(ksp);
>>>>> while(cond) {
>>>>>      SNES snes;
>>>>>      SNESCreate(&snes);
>>>>>      SNESSetKSP(snes, &ksp);
>>>>>      SNESSolve(snes);
>>>          SNESSetKSP(snes,dummy);
>>>>>      SNESDestroy(&snes);
>>>>> }
>>> It should work even if you don't setup dummy. But perhaps it is picky and you may need to add a matrix to dummy etc (don't worry it doesn't copy the matrix).
>>> 
>>> Barry
>>> 
>>> 
>>> 
>>> 
>>>> On May 30, 2019, at 9:51 AM, Stefano Zampini via petsc-dev <petsc-dev at mcs.anl.gov> wrote:
>>>> 
>>>> I meant SNESDestroy should call KSPDestroy
>>>> 
>>>> The reason for having the XXXReset methods called by the XXXDestroy is mostly code reuse, and it may lead to troubles.
>>>> The Reset concept is not uniform throughout the library.
>>>> 
>>>>> On May 30, 2019, at 3:59 PM, Stefano Zampini <stefano.zampini at gmail.com> wrote:
>>>>> 
>>>>> I think snes reset should call ksp destroy. I don't see the case for which this can lead to troubles 
>>>>> 
>>>>> Il Gio 30 Mag 2019, 15:43 Matthew Knepley via petsc-dev <petsc-dev at mcs.anl.gov> ha scritto:
>>>>> On Thu, May 30, 2019 at 6:08 AM Pierre Jolivet via petsc-dev <petsc-dev at mcs.anl.gov> wrote:
>>>>> Hello,
>>>>> I’m doing a continuation loop with something like:
>>>>> KSP ksp;
>>>>> KSPSetUp(ksp);
>>>>> while(cond) {
>>>>>      SNES snes;
>>>>>      SNESCreate(&snes);
>>>>>      SNESSetKSP(snes, &ksp);
>>>>>      SNESSolve(snes);
>>>>>      SNESDestroy(&snes);
>>>>> }
>>>>> 
>>>>> For the first iteration, everything is OK.
>>>>> After that, it looks like SNESDestroy is messing up with my outer-defined KSP(*), i.e., for the code to work I need to comment out the SNESDestroy.
>>>>> Is this the expected behavior? (if not, I’ll provide a MWE)
>>>>> How to fix this properly, without having leaks by not destroying the inner-defined SNESes?
>>>>> 
>>>>> Thanks in advance,
>>>>> Pierre
>>>>> 
>>>>> (*) to the outer-defined KSP is attached a PCFIELDSPLIT, first SNESSolve, everything OK:
>>>>> PC Object: 1 MPI processes
>>>>> type: fieldsplit
>>>>>  FieldSplit with MULTIPLICATIVE composition: total splits = 2
>>>>> 
>>>>> Second SNESSolve:
>>>>> [0]PETSC ERROR: PCFieldSplitSetDefaults() Unhandled case, must have at least two fields, not 1
>>>>> 
>>>>> I believe SNESDestroy() calls SNESReset(), which calls KSPReset(), which is wiping out your information.
>>>>> 
>>>>> This pattern is in a lot of places. Destroy calls Reset because it is natural to reuse the code which tears down
>>>>> the internal structures. Reset calls reset on subobjects because we also want to tear down their internal structures (usually).
>>>>> Reset wouldn't do what we want on resizing if we left subobjects unreset. However, this chain is causing subobjects to
>>>>> be wiped clean on Destroy, so that we cannot reuse subobjects.
>>>>> 
>>>>> It would not even work if you change the Destroy to Reset in the continuation loop. However, I think you can hoist all
>>>>> the SNES setup outside the loop. If you are changing sizes, then the KSP needs to be wiped out anyway. If not, then
>>>>> you do not need to wipe out the SNES.
>>>>> 
>>>>> Thanks,
>>>>> 
>>>>>   Matt
>>>>> 
>>>>> -- 
>>>>> What most experimenters take for granted before they begin their experiments is infinitely more interesting than any results to which their experiments lead.
>>>>> -- Norbert Wiener
>>>>> 
>>>>> https://www.cse.buffalo.edu/~knepley/

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mcs.anl.gov/pipermail/petsc-dev/attachments/20190530/56dd212e/attachment-0001.html>


More information about the petsc-dev mailing list