[petsc-users] Context behind SNESComputeFunction call

Fande Kong fdkong.jd at gmail.com
Sat Jan 27 11:18:02 CST 2018


Hi Barry,

Thanks so much!

Does this requires us to attach a shell function "MatAssemblyEnd_SNESMF"?
We need to maintain "MatAssemblyEnd_SNESMF" in the moose side?



Could we just add a flag into the original routine "MatAssemblyEnd_SNESMF"
in PETSc?


*static PetscErrorCode MatAssemblyEnd_SNESMF(Mat J,MatAssemblyType mt)*
*{*
*  PetscErrorCode ierr;*
*  MatMFFD        j    = (MatMFFD)J->data;*
*  SNES           snes = (SNES)j->ctx;*
*  PetscBool    refuse;*
*  Vec            u,f;*

*  PetscFunctionBegin;*
*  ierr = MatAssemblyEnd_MFFD(J,mt);CHKERRQ(ierr);*

*  ierr = SNESGetReuseBaseMFFD(SNES snes, & refuse);CHKERRQ(ierr);*

*  ierr = SNESGetSolution(snes,&u);CHKERRQ(ierr);*
*  if (j->func == (PetscErrorCode (*)(void*,Vec,Vec))SNESComputeFunction ||
reuse) {*
*    ierr = SNESGetFunction(snes,&f,NULL,NULL);CHKERRQ(ierr);*
*    ierr = MatMFFDSetBase_MFFD(J,u,f);CHKERRQ(ierr);*
*  } else {*
*    /* f value known by SNES is not correct for other differencing
function */*
*    ierr = MatMFFDSetBase_MFFD(J,u,NULL);CHKERRQ(ierr);*
*  }*
*  PetscFunctionReturn(0);*
*}*



We may need new  APIs SNESGetReuseBaseMFFD and SNESSetReuseBaseMFFD, and
a command line option "-snes_reuse_base_mffd".  "reuse" is
false by default, and it is consistent with current setting.


Please let me know what do you think. If you agree, I can make a PR on this.

Fande,


On Fri, Jan 26, 2018 at 10:47 PM, Smith, Barry F. <bsmith at mcs.anl.gov>
wrote:

>
>   Thanks, I now understand the situation.
>
>   I have a tentative solution for you that does not require complex new
> APIs. I have added one function to the master branch MatSNESMFGetSNES() and
> attach a modified example that utilizes this to avoid the extra function
> evaluations.
>
>
>
>    Please let me know if it works for you and what you think,
>
>    Barry
>
>
>
> > On Jan 26, 2018, at 5:54 PM, Alexander Lindsay <alexlindsay239 at gmail.com>
> wrote:
> >
> > We are doing something non-standard. We set different functions for snes
> and mffd. When a function is called through snes, we know we are doing a
> non-linear residual evaluation and we allow an update of our mechanical
> contact nodes. When a function is called through mffd, we know we are
> within the linear solve, and we do not allow our contact state to change.
> If after a contact update our non-linear residual is not deemed to be
> converged, then we would hope to be able to re-use it for the zeroth-linear
> residual.
> >
> > I know that you don't like this way of handling contact, but it
> integrates well for us into our multiphysics framework and works well in
> many cases.
> >
> > On Jan 26, 2018, at 5:34 PM, Kong, Fande <fande.kong at inl.gov> wrote:
> >
> >> Hi Barry,
> >>
> >> I made minor changes on src/snes/examples/tutorials/ex2.c to
> demonstrate this issue.  Please see the attachment.
> >>
> >> ./ex2 -snes_monitor -ksp_monitor -snes_mf_operator 1
> >>
> >>
> >> atol=1e-50, rtol=1e-08, stol=1e-08, maxit=50, maxf=10000
> >>  FormFunction is called
> >>   0 SNES Function norm 5.414682427127e+00
> >>     0 KSP Residual norm 9.559082033938e-01
> >>  FormFunction is called
> >>  FormFunction is called
> >>     1 KSP Residual norm 1.703870633386e-09
> >>  FormFunction is called
> >>  FormFunction is called
> >>   1 SNES Function norm 2.952582481151e-01
> >>     0 KSP Residual norm 2.672054855433e-02
> >>  FormFunction is called
> >>  FormFunction is called
> >>     1 KSP Residual norm 1.519298012177e-10
> >>  FormFunction is called
> >>  FormFunction is called
> >>   2 SNES Function norm 4.502289047587e-04
> >>     0 KSP Residual norm 4.722075651268e-05
> >>  FormFunction is called
> >>  FormFunction is called
> >>     1 KSP Residual norm 3.834927363659e-14
> >>  FormFunction is called
> >>  FormFunction is called
> >>   3 SNES Function norm 1.390073376131e-09
> >> number of SNES iterations = 3
> >>
> >> Norm of error 1.49795e-10, Iterations 3
> >>
> >> "FormFunction" is called TWICE at "0 KSP".
> >>
> >> If we comment out MatMFFDSetFunction:
> >>
> >> /* ierr = MatMFFDSetFunction(Jacobian,FormFunction_MFFD,(void*)snes);CHKERRQ(ierr);
> */
> >>
> >>
> >> ./ex2 -snes_monitor -ksp_monitor -snes_mf_operator 1
> >>
> >> atol=1e-50, rtol=1e-08, stol=1e-08, maxit=50, maxf=10000
> >>  FormFunction is called
> >>   0 SNES Function norm 5.414682427127e+00
> >>     0 KSP Residual norm 9.559082033938e-01
> >>  FormFunction is called
> >>     1 KSP Residual norm 1.703870633386e-09
> >>  FormFunction is called
> >>  FormFunction is called
> >>   1 SNES Function norm 2.952582481151e-01
> >>     0 KSP Residual norm 2.672054855433e-02
> >>  FormFunction is called
> >>     1 KSP Residual norm 1.519298012177e-10
> >>  FormFunction is called
> >>  FormFunction is called
> >>   2 SNES Function norm 4.502289047587e-04
> >>     0 KSP Residual norm 4.722075651268e-05
> >>  FormFunction is called
> >>     1 KSP Residual norm 3.834927363659e-14
> >>  FormFunction is called
> >>  FormFunction is called
> >>   3 SNES Function norm 1.390073376131e-09
> >> number of SNES iterations = 3
> >>
> >> Norm of error 1.49795e-10, Iterations 3
> >>
> >> "FormFunction" is called ONCE at "0 KSP".
> >>
> >> Hopefully, this example makes the point clear.
> >>
> >>
> >> Fande,
> >>
> >> On Fri, Jan 26, 2018 at 3:50 PM, Smith, Barry F. <bsmith at mcs.anl.gov>
> wrote:
> >>
> >>
> >>   So you are doing something non-standard? Are you not just using
> -snes_mf or -snes_mf_operator? Can you send me a sample code that has the
> extra function evaluations? Because if you run through regular usage with
> the debugger you will see there is no extra evaluation.
> >>
> >>    Barry
> >>
> >>
> >> > On Jan 26, 2018, at 4:32 PM, Kong, Fande <fande.kong at inl.gov> wrote:
> >> >
> >> >
> >> >
> >> > On Fri, Jan 26, 2018 at 3:10 PM, Smith, Barry F. <bsmith at mcs.anl.gov>
> wrote:
> >> >
> >> >
> >> > > On Jan 26, 2018, at 2:15 PM, Kong, Fande <fande.kong at inl.gov>
> wrote:
> >> > >
> >> > >
> >> > >
> >> > > On Mon, Jan 8, 2018 at 2:15 PM, Smith, Barry F. <bsmith at mcs.anl.gov>
> wrote:
> >> > >
> >> > >
> >> > > > On Jan 8, 2018, at 2:59 PM, Alexander Lindsay <
> alexlindsay239 at gmail.com> wrote:
> >> > > >
> >> > > > Is there any elegant way to tell whether SNESComputeFunction is
> being called under different conceptual contexts?
> >> > > >
> >> > > > E.g. non-linear residual evaluation vs. Jacobian formation from
> finite differencing vs. Jacobian-vector products from finite differencing?
> >> > >
> >> > >   Under normal usage with the options database no.
> >> > >
> >> > > Hi Barry,
> >> > >
> >> > > How difficult to provide an API? Is it possible?
> >> > >
> >> > >
> >> > >
> >> > >   If you have some reason to know you could write three functions
> and provide them to SNESSetFunction(), MatMFFDSetFunction(), and
> MatFDColoringSetFunction(). Note that these functions have slightly
> different calling sequences but you can have all of them call the same
> underlying common function if you are only interested in, for example, how
> many times the function is used for each purpose.
> >> > >
> >> > > If we use this way for the Jacobian-free Newton, the function
> evaluation will be called twice at the first linear iteration because the
> computed residual vector at the nonlinear step  is not reused. Any way to
> reuse the function residual of the Newton step instead of recomputing a new
> residual at the first linear iteration?
> >> >
> >> >    It does reuse the function evaluation. Why do you think it does
> not? If you look at MatMult_MFFD() you will see the lines of code
> >> >
> >> >   /* compute func(U) as base for differencing; only needed first time
> in and not when provided by user */
> >> >   if (ctx->ncurrenth == 1 && ctx->current_f_allocated) {
> >> >     ierr = (*ctx->func)(ctx->funcctx,U,F);CHKERRQ(ierr);
> >> >   }
> >> >
> >> > since the if is satisfied it does not compute the function at the
> base location.  To double check I ran src/snes/examples/tutorials/ex19
> with -snes_mf in the debugger and verified that the "extra" function
> evaluations are not done.
> >> >
> >> > In MatAssemblyEnd_SNESMF,
> >> >
> >> >   if (j->func == (PetscErrorCode (*)(void*,Vec,Vec))SNESComputeFunction)
> {
> >> >     ierr = SNESGetFunction(snes,&f,NULL,NULL);CHKERRQ(ierr);
> >> >     ierr = MatMFFDSetBase_MFFD(J,u,f);CHKERRQ(ierr);
> >> >   } else {
> >> >     /* f value known by SNES is not correct for other differencing
> function */
> >> >     ierr = MatMFFDSetBase_MFFD(J,u,NULL);CHKERRQ(ierr);
> >> >   }
> >> >
> >> >
> >> > Will hit ierr = MatMFFDSetBase_MFFD(J,u,NULL);CHKERRQ(ierr), because
> SNES and MAT have different function pointers.
> >> >
> >> > In MatMFFDSetBase_MFFD(Mat J,Vec U,Vec F),
> >> >
> >> >   if (F) {
> >> >     if (ctx->current_f_allocated) {ierr = VecDestroy(&ctx->current_f);
> CHKERRQ(ierr);}
> >> >     ctx->current_f           = F;
> >> >     ctx->current_f_allocated = PETSC_FALSE;
> >> >   } else if (!ctx->current_f_allocated) {
> >> >     ierr = MatCreateVecs(J,NULL,&ctx->current_f);CHKERRQ(ierr);
> >> >
> >> >     ctx->current_f_allocated = PETSC_TRUE;
> >> >   }
> >> >
> >> > Because F=NULL, we then have ctx->current_f_allocated = PETSC_TRUE.
> >> >
> >> > Then, the following if statement is true:
> >> >
> >> >   if (ctx->ncurrenth == 1 && ctx->current_f_allocated) {
> >> >     ierr = (*ctx->func)(ctx->funcctx,U,F);CHKERRQ(ierr);
> >> >   }
> >> >
> >> >
> >> > Fande,
> >> >
> >> >
> >> >
> >> >   Barry
> >> >
> >> >
> >> > >
> >> > > Fande,
> >> > >
> >> > >
> >> > >
> >> > >    Barry
> >> > >
> >> > >
> >> > >
> >> > > >
> >> > > > Alex
> >> > >
> >> > >
> >>
> >>
> >> <ex2.c>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mcs.anl.gov/pipermail/petsc-users/attachments/20180127/c71a8196/attachment.html>


More information about the petsc-users mailing list