<div dir="ltr">Hi Barry,<div><br></div><div>This seems to work for me.  I defined the following function in our code repository, and I call it every time I use KSPSetOperators to update the operator for my KSP object with PCMG:</div><div><br></div><div><div>PetscErrorCode PCMGSoftReset(PC pc)</div><div>{</div><div>  PC_MG          *mg        = (PC_MG*)pc->data;</div><div>  PC_MG_Levels   **mglevels = mg->levels;</div><div>  PetscErrorCode ierr;</div><div>  PetscInt       i,n;</div><div><br></div><div>  PetscFunctionBegin;</div><div>  if (mglevels) {</div><div>    n = mglevels[0]->levels;</div><div>    for (i=0; i<n; i++) {</div><div>      ierr = MatDestroy(&mglevels[i]->A);CHKERRQ(ierr);</div><div>      if (mglevels[i]->smoothd != mglevels[i]->smoothu) {</div><div>        ierr = KSPReset(mglevels[i]->smoothd);CHKERRQ(ierr);</div><div>      }</div><div>      ierr = KSPReset(mglevels[i]->smoothu);CHKERRQ(ierr);</div><div>    }     </div><div>  }</div><div>  pc->setupcalled = PETSC_FALSE;</div><div>  PetscFunctionReturn(0);</div><div>}</div></div><div><br>(Note that I had to add "pc->setupcalled = PETSC_FALSE".)  Thanks for the help!</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jan 24, 2018 at 12:19 PM, Smith, Barry F. <span dir="ltr"><<a href="mailto:bsmith@mcs.anl.gov" target="_blank">bsmith@mcs.anl.gov</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
   This is off the top of my head and my not be useful. Copy PCReset_MG() which is<br>
<br>
PetscErrorCode PCReset_MG(PC pc)<br>
{<br>
  PC_MG          *mg        = (PC_MG*)pc->data;<br>
  PC_MG_Levels   **mglevels = mg->levels;<br>
  PetscErrorCode ierr;<br>
  PetscInt       i,n;<br>
<br>
  PetscFunctionBegin;<br>
  if (mglevels) {<br>
    n = mglevels[0]->levels;<br>
    for (i=0; i<n-1; i++) {<br>
      ierr = VecDestroy(&mglevels[i+1]->r);<wbr>CHKERRQ(ierr);<br>
      ierr = VecDestroy(&mglevels[i]->b);<wbr>CHKERRQ(ierr);<br>
      ierr = VecDestroy(&mglevels[i]->x);<wbr>CHKERRQ(ierr);<br>
      ierr = MatDestroy(&mglevels[i+1]-><wbr>restrct);CHKERRQ(ierr);<br>
      ierr = MatDestroy(&mglevels[i+1]-><wbr>interpolate);CHKERRQ(ierr);<br>
      ierr = VecDestroy(&mglevels[i+1]-><wbr>rscale);CHKERRQ(ierr);<br>
    }<br>
<br>
    for (i=0; i<n; i++) {<br>
      ierr = MatDestroy(&mglevels[i]->A);<wbr>CHKERRQ(ierr);<br>
      if (mglevels[i]->smoothd != mglevels[i]->smoothu) {<br>
        ierr = KSPReset(mglevels[i]->smoothd)<wbr>;CHKERRQ(ierr);<br>
      }<br>
      ierr = KSPReset(mglevels[i]->smoothu)<wbr>;CHKERRQ(ierr);<br>
    }<br>
  }<br>
  PetscFunctionReturn(0);<br>
}<br>
<br>
And change it to only destroy mats on each level ierr = MatDestroy(&mglevels[i]->A);<wbr>CHKERRQ(ierr); Keep everything else.<br>
<br>
Not that you will need to include #include <petsc/private/pcmgimpl.h>  in your code.<br>
<div class="HOEnZb"><div class="h5"><br>
> On Jan 24, 2018, at 9:53 AM, Ben Yee <<a href="mailto:bcyee@umich.edu">bcyee@umich.edu</a>> wrote:<br>
><br>
> Yes, the nonzero structure changes in a way that cannot easily be predicted.  I could overallocate, add some extra entries to the first matrix, and reuse that matrix, but I would have to roughly double the number of allocated entries, leading to an undesirable increase in memory.  I think that one alternative would be to just reset the KSP object when I change the operator, but, if I'm not mistaken, this would destroy all the interpolation operators and I'd have to redefine all of them.<br>
><br>
> On Wed, Jan 24, 2018 at 10:41 AM, Smith, Barry F. <<a href="mailto:bsmith@mcs.anl.gov">bsmith@mcs.anl.gov</a>> wrote:<br>
><br>
>   Ben<br>
><br>
>     This is a good question, I'll take a look at how difficult it would be to add this feature.<br>
><br>
>      I take it the nonzero structure of the outer matrix changes over time?<br>
><br>
><br>
>    Barry<br>
><br>
><br>
> > On Jan 24, 2018, at 9:12 AM, Ben Yee <<a href="mailto:bcyee@umich.edu">bcyee@umich.edu</a>> wrote:<br>
> ><br>
> > Hi,<br>
> ><br>
> > I have multiple matrices (with different nonzero structures) for which I would like to use the same KSP operator (KSPRICHARDSON with PCMG, Galerkin process for generating coarse grid operator).  I want to use the same PCMG structure for all the matrices (same interpolation, same restriction, same number of levels, same smoothing techniques, etc.), so I tried using KSPSetOperators to just change the operator.  My interpolation matrices are MPIAIJ matrices that I have defined myself and provided to PCMG.  My hope was that, with the new operator I provided, PETSc would recompute all of the coarse/intermediate grid operators using the Galerkin process with the old interpolation matrices and the new fine-grid operator.<br>
> ><br>
> > However, I get the wrong solution after changing the operator with KSPSetOperators.  After some extensive digging around the PETSc source code, it seems that the operators in mg.c are not updated by KSPSetOperators.  When I do a MatView on mglevels->A or the operator in mglevels->smoothu or mglevels->smoothd in PCMGMCycle_Private() of mg.c, it has the matrix values of the old matrix.  From what I understand, the only place where mglevels->A (used to compute the residual) is updated is in PCApplyRIchardson_MG() of mg.c, from the following lines of code:<br>
> >  74:   for<br>
> >  (i=0; i<levels; i++) {<br>
> ><br>
> >  75:     if<br>
> >  (!mglevels[i]->A) {<br>
> ><br>
> >  76:       KSPGetOperators<br>
> > (mglevels[i]->smoothu,&<wbr>mglevels[i]->A,NULL);<br>
> ><br>
> >  77:       PetscObjectReference((<wbr>PetscObject<br>
> > )mglevels[i]->A);<br>
> ><br>
> >  78:<br>
> >     }<br>
> ><br>
> >  79:   }<br>
> > It seems to me that the pointer mglevels[i]->A is only set once, when it is undefined at the beginning of the iteration scheme.  I think there are more issues as well, but this is the easiest one to point out.  (For example, it doesn't seem like it is possible to update the operator for mglevels[i]->smoothd from KSPSetOperators on the outermost KSP object, and, if I try to set it manually via PCMGGetSmoother, I get errors if the nonzero structures of the coarse-grid operators have changed, which tends to be the case when the fine-grid operator's nonzero structure changes).<br>
> ><br>
> > Is there something I'm doing wrong?  Is there a way to do this so that I can reuse PCMG with a new operator?<br>
> ><br>
> > Thanks!<br>
> ><br>
> > --<br>
> > Ben Yee<br>
> ><br>
> > NERS PhD Candidate, University of Michigan<br>
> > B.S. Mech. & Nuclear Eng., U.C. Berkeley<br>
><br>
><br>
><br>
><br>
> --<br>
> Ben Yee<br>
><br>
> NERS PhD Candidate, University of Michigan<br>
> B.S. Mech. & Nuclear Eng., U.C. Berkeley<br>
<br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr">Ben Yee<div><font size="1"><br></font><div><font size="1">NERS PhD Candidate, University of Michigan</font></div><div><font size="1">B.S. Mech. & Nuclear Eng., U.C. Berkeley</font></div></div></div></div></div></div>
</div>