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 <[email protected]> wrote:
> 
> 
> 
> On Fri, Jan 26, 2018 at 3:10 PM, Smith, Barry F. <[email protected]> wrote:
> 
> 
> > On Jan 26, 2018, at 2:15 PM, Kong, Fande <[email protected]> wrote:
> >
> >
> >
> > On Mon, Jan 8, 2018 at 2:15 PM, Smith, Barry F. <[email protected]> wrote:
> >
> >
> > > On Jan 8, 2018, at 2:59 PM, Alexander Lindsay <[email protected]> 
> > > 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
> >
> >

Reply via email to