#include /*I "petsctao.h" I*/ #include #include #include /* For finited difference computations of the Hessian, we use PETSc's SNESComputeJacobianDefault */ static PetscErrorCode Fsnes(SNES snes,Vec X,Vec G,void* ctx) { Tao tao = (Tao)ctx; PetscFunctionBegin; PetscValidHeaderSpecific(tao,TAO_CLASSID,4); PetscCall(TaoComputeGradient(tao,X,G)); PetscFunctionReturn(0); } /*@C TaoDefaultComputeGradient - computes the gradient using finite differences. Collective on tao Input Parameters: + tao - the Tao context . X - compute gradient at this point - dummy - not used Output Parameter: . G - Gradient Vector Options Database Key: + -tao_fd_gradient - activates TaoDefaultComputeGradient() - -tao_fd_delta - change in X used to calculate finite differences Level: advanced Notes: This routine is slow and expensive, and is not optimized to take advantage of sparsity in the problem. Although not recommended for general use in large-scale applications, it can be useful in checking the correctness of a user-provided gradient. Use the tao method TAOTEST to get an indication of whether your gradient is correct. This finite difference gradient evaluation can be set using the routine `TaoSetGradient()` or by using the command line option -tao_fd_gradient .seealso: `Tao`, `TaoSetGradient()` @*/ PetscErrorCode TaoDefaultComputeGradient(Tao tao,Vec Xin,Vec G,void *dummy) { Vec X; PetscScalar *g; PetscReal f, f2; PetscInt low,high,N,i; PetscBool flg; PetscReal h=.5*PETSC_SQRT_MACHINE_EPSILON; PetscFunctionBegin; PetscCall(PetscOptionsGetReal(((PetscObject)tao)->options,((PetscObject)tao)->prefix,"-tao_fd_delta",&h,&flg)); PetscCall(VecDuplicate(Xin,&X)); PetscCall(VecCopy(Xin,X)); PetscCall(VecGetSize(X,&N)); PetscCall(VecGetOwnershipRange(X,&low,&high)); PetscCall(VecSetOption(X,VEC_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE)); PetscCall(VecGetArray(G,&g)); for (i=0;i=low && i