Actual source code: fdiff.c

petsc-3.8.4 2018-03-24
Report Typos and Errors
  1:  #include <petsctao.h>
  2:  #include <petsc/private/taoimpl.h>
  3:  #include <petscsnes.h>

  5: /*
  6:    For finited difference computations of the Hessian, we use PETSc's SNESComputeJacobianDefault
  7: */

  9: static PetscErrorCode Fsnes(SNES snes ,Vec X,Vec G,void*ctx)
 10: {
 12:   Tao            tao = (Tao)ctx;

 16:   ierr=TaoComputeGradient(tao,X,G);
 17:   return(0);
 18: }

 20: /*@C
 21:   TaoDefaultComputeGradient - computes the gradient using finite differences.

 23:   Collective on Tao

 25:   Input Parameters:
 26: + tao - the Tao context
 27: . X - compute gradient at this point
 28: - dummy - not used

 30:   Output Parameters:
 31: . G - Gradient Vector

 33:    Options Database Key:
 34: +  -tao_fd_gradient - Activates TaoDefaultComputeGradient()
 35: -  -tao_fd_delta <delta> - change in x used to calculate finite differences

 37:    Level: advanced

 39:    Note:
 40:    This routine is slow and expensive, and is not currently optimized
 41:    to take advantage of sparsity in the problem.  Although
 42:    TaoAppDefaultComputeGradient is not recommended for general use
 43:    in large-scale applications, It can be useful in checking the
 44:    correctness of a user-provided gradient.  Use the tao method TAOTEST
 45:    to get an indication of whether your gradient is correct.


 48:    Note:
 49:    This finite difference gradient evaluation can be set using the routine TaoSetGradientRoutine() or by using the command line option -tao_fd_gradient

 51: .seealso: TaoSetGradientRoutine()

 53: @*/
 54: PetscErrorCode TaoDefaultComputeGradient(Tao tao,Vec X,Vec G,void *dummy)
 55: {
 56:   PetscScalar    *x,*g;
 57:   PetscReal      f, f2;
 59:   PetscInt       low,high,N,i;
 60:   PetscBool      flg;
 61:   PetscReal      h=.5*PETSC_SQRT_MACHINE_EPSILON;

 64:   PetscOptionsGetReal(((PetscObject)tao)->options,((PetscObject)tao)->prefix,"-tao_fd_delta",&h,&flg);
 65:   VecGetSize(X,&N);
 66:   VecGetOwnershipRange(X,&low,&high);
 67:   VecGetArray(G,&g);
 68:   for (i=0;i<N;i++) {
 69:     if (i>=low && i<high) {
 70:       VecGetArray(X,&x);
 71:       x[i-low] -= h;
 72:       VecRestoreArray(X,&x);
 73:     }

 75:     TaoComputeObjective(tao, X,&f);

 77:     if (i>=low && i<high) {
 78:       VecGetArray(X,&x);
 79:       x[i-low] += 2*h;
 80:       VecRestoreArray(X,&x);
 81:     }

 83:     TaoComputeObjective(tao,X,&f2);

 85:     if (i>=low && i<high) {
 86:       VecGetArray(X,&x);
 87:       x[i-low] -= h;
 88:       VecRestoreArray(X,&x);
 89:     }
 90:     if (i>=low && i<high) {
 91:       g[i-low]=(f2-f)/(2.0*h);
 92:     }
 93:   }
 94:   VecRestoreArray(G,&g);
 95:   return(0);
 96: }

 98: /*@C
 99:    TaoDefaultComputeHessian - Computes the Hessian using finite differences.

101:    Collective on Tao

103:    Input Parameters:
104: +  tao - the Tao context
105: .  V - compute Hessian at this point
106: -  dummy - not used

108:    Output Parameters:
109: +  H - Hessian matrix (not altered in this routine)
110: -  B - newly computed Hessian matrix to use with preconditioner (generally the same as H)

112:    Options Database Key:
113: +  -tao_fd - Activates TaoDefaultComputeHessian()
114: -  -tao_view_hessian - view the hessian after each evaluation using PETSC_VIEWER_STDOUT_WORLD

116:    Level: advanced

118:    Notes:
119:    This routine is slow and expensive, and is not currently optimized
120:    to take advantage of sparsity in the problem.  Although
121:    TaoDefaultComputeHessian() is not recommended for general use
122:    in large-scale applications, It can be useful in checking the
123:    correctness of a user-provided Hessian.

125: .seealso: TaoSetHessianRoutine(), TaoDefaultComputeHessianColor(), SNESComputeJacobianDefault(), TaoSetGradientRoutine(), TaoDefaultComputeGradient()

127: @*/
128: PetscErrorCode TaoDefaultComputeHessian(Tao tao,Vec V,Mat H,Mat B,void *dummy)
129: {
130:   PetscErrorCode       ierr;
131:   MPI_Comm             comm;
132:   Vec                  G;
133:   SNES                 snes;

137:   VecDuplicate(V,&G);

139:   PetscInfo(tao,"TAO Using finite differences w/o coloring to compute Hessian matrix\n");

141:   TaoComputeGradient(tao,V,G);

143:   PetscObjectGetComm((PetscObject)H,&comm);
144:   SNESCreate(comm,&snes);

146:   SNESSetFunction(snes,G,Fsnes,tao);
147:   SNESComputeJacobianDefault(snes,V,H,B,tao);
148:   SNESDestroy(&snes);
149:   VecDestroy(&G);
150:   return(0);
151: }

153: /*@C
154:    TaoDefaultComputeHessianColor - Computes the Hessian using colored finite differences.

156:    Collective on Tao

158:    Input Parameters:
159: +  tao - the Tao context
160: .  V - compute Hessian at this point
161: -  ctx - the PetscColoring object (must be of type MatFDColoring)

163:    Output Parameters:
164: +  H - Hessian matrix (not altered in this routine)
165: -  B - newly computed Hessian matrix to use with preconditioner (generally the same as H)

167:    Level: advanced


170: .seealso: TaoSetHessianRoutine(), TaoDefaultComputeHessian(),SNESComputeJacobianDefaultColor(), TaoSetGradientRoutine()

172: @*/
173: PetscErrorCode TaoDefaultComputeHessianColor(Tao tao, Vec V, Mat H,Mat B,void *ctx)
174: {
175:   PetscErrorCode      ierr;
176:   MatFDColoring       coloring = (MatFDColoring)ctx;

180:   ierr=PetscInfo(tao,"TAO computing matrix using finite differences Hessian and coloring\n");
181:   MatFDColoringApply(B,coloring,V,ctx);
182:   if (H != B) {
183:     MatAssemblyBegin(H, MAT_FINAL_ASSEMBLY);
184:     MatAssemblyEnd(H, MAT_FINAL_ASSEMBLY);
185:   }
186:   return(0);
187: }