On Fri, Jan 26, 2018 at 3:10 PM, Smith, Barry F. <bsm...@mcs.anl.gov> wrote:
> > > > On Jan 26, 2018, at 2:15 PM, Kong, Fande <fande.k...@inl.gov> wrote: > > > > > > > > On Mon, Jan 8, 2018 at 2:15 PM, Smith, Barry F. <bsm...@mcs.anl.gov> > wrote: > > > > > > > On Jan 8, 2018, at 2:59 PM, Alexander Lindsay < > alexlindsay...@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 > > > > > >