Actual source code: fdiff.c

  1: #include "taoapp.h"         /*I  "taoapp.h"  I*/
  2: #include "src/tao_impl.h"      /*I "src/tao_impl.h"  I*/
  3: #include "src/petsctao/include/taopetsc.h"          /*I "src/petsctao/include/taopetsc.h" I*/
  4: #include "petscsnes.h"



 12: static int Ftemp(SNES snes ,Vec X,Vec G,void*ctx){
 13:   int info;
 14:   TAO_APPLICATION taoapp = (TAO_APPLICATION)ctx;
 15:   TAO_SOLVER tao;
 18:   info = TaoAppGetTaoSolver(taoapp,&tao);
 19:   info=TaoAppComputeGradient(taoapp,X,G); CHKERRQ(info);
 20:   tao->ngrads++;
 21:   return(0);
 22: }

 27: /*@C
 28:   TaoAppDefaultComputeHessian - computes the gradient using finite differences.
 29:  
 30:   Collective on TAO_APPLICATION

 32:   Input Parameters:
 33: + taoapp - the TAO_APPLICATION context
 34: . X - compute gradient at this point
 35: - ctx - the TAO_APPLICATION structure, cast to (void*)

 37:   Output Parameters:
 38: . G - Gradient Vector

 40:    Options Database Key:
 41: +  -tao_fd_gradient - Activates TaoAppDefaultComputeGradient()
 42: -  -tao_fd_delta <delta> - change in x used to calculate finite differences




 47:    Level: intermediate

 49:    Note:
 50:    This routine is slow and expensive, and is not currently optimized
 51:    to take advantage of sparsity in the problem.  Although
 52:    TaoAppDefaultComputeGradient is not recommended for general use
 53:    in large-scale applications, It can be useful in checking the
 54:    correctness of a user-provided gradient.  Use the tao method "tao_fd_test"
 55:    to get an indication of whether your gradient is correct.


 58:    Note:
 59:    The gradient evaluation must be set using the routine TaoAppSetGradientRoutine().

 61: .keywords: TAO_APPLICATION, finite differences, Hessian

 63: .seealso: TaoAppDefaultComputeGradient(),  TaoAppSetGradientRoutine()

 65: @*/
 66: int TaoAppDefaultComputeGradient(TAO_APPLICATION taoapp,Vec X,Vec G,void*) 
 67: {
 68:   Vec TempX;
 69:   double *g;
 70:   double f, f2;
 71:   int i,low,high,N,info;
 72:   PetscTruth flg;
 73:   double h=1.0e-6;
 74:   TAO_SOLVER tao;
 76:   info = TaoAppGetTaoSolver(taoapp, &tao);
 77:   //PetscStackPush("TAO Finite Difference gradient");
 78:   //info = PetscLogEventBegin(Tao_FiniteDifferenceGradient,taoapp,X,0,0);
 79:   info = TaoAppComputeObjective(taoapp, X,&f); CHKERRQ(info);
 80:   tao->nfuncs++;
 81:   info = PetscOptionsGetReal(PETSC_NULL,"-tao_fd_delta",&h,&flg);
 82:   info = VecDuplicate(X,&TempX); CHKERRQ(info);
 83:   info = VecCopy(X,TempX); CHKERRQ(info);
 84:   info = VecGetSize(X,&N); CHKERRQ(info);
 85:   info = VecGetOwnershipRange(TempX,&low,&high); CHKERRQ(info);
 86:   info = VecGetArray(G,&g); CHKERRQ(info);
 87:   for (i=0;i<N;i++) {
 88:     info = VecSetValue(TempX,i,h,ADD_VALUES);
 89:     info = TaoAppComputeObjective(taoapp,TempX,&f2); CHKERRQ(info);
 90:     tao->nfuncs++;
 91:     info = VecSetValue(TempX,i,-h,ADD_VALUES);
 92:     if (i>=low && i<high) {
 93:       g[i-low]=(f2-f)/h;
 94:     }

 96:   }
 97:   info = VecRestoreArray(G,&g); CHKERRQ(info);
 98:   
 99:   //info = PetscLogEventEnd(Tao_FiniteDifferenceGradient, taoapp, X, 0,0); CHKERRQ(info);
100:   //PetscStackPop;
101:   
102:   return(0);
103: }

107: /*@C
108:    TaoAppDefaultComputeHessian - Computes the Hessian using finite differences. 

110:    Collective on TAO_APPLICATION

112:    Input Parameters:
113: +  taoapp - the TAO_APPLICATION context 
114: .  V - compute Hessian at this point
115: -  ctx - the TAO_APPLICATION structure, cast to (void*)

117:    Output Parameters:
118: +  H - Hessian matrix (not altered in this routine)
119: .  B - newly computed Hessian matrix to use with preconditioner (generally the same as H)
120: -  flag - flag indicating whether the matrix sparsity structure has changed

122:    Options Database Key:
123: +  -tao_fd - Activates TaoAppDefaultComputeHessian()
124: -  -tao_view_hessian - view the hessian after each evaluation using PETSC_VIEWER_STDOUT_WORLD

126:    Level: intermediate

128:    Notes:
129:    This routine is slow and expensive, and is not currently optimized
130:    to take advantage of sparsity in the problem.  Although
131:    TaoAppDefaultComputeHessian() is not recommended for general use
132:    in large-scale applications, It can be useful in checking the
133:    correctness of a user-provided Hessian.

135:    Note:
136:    The gradient evaluation must be set using the routine TaoAppSetGradientRoutine().

138: .keywords: TAO_APPLICATION, finite differences, Hessian

140: .seealso: TaoAppSetHessianRoutine(), TaoAppDefaultComputeHessianColor(), SNESDefaultComputeJacobian(),
141:           TaoAppSetGradientRoutine(), TaoAppDefaultComputeGradient()

143: @*/
144: int TaoAppDefaultComputeHessian(TAO_APPLICATION taoapp,Vec V,Mat *H,Mat *B,
145:                              MatStructure *flag,void *ctx){
146:   int                  info;
147:   MPI_Comm             comm;
148:   Vec                  G;
149:   SNES                 snes;
150:   TAO_SOLVER tao;


154:   info = TaoAppGetTaoSolver(taoapp, &tao);

157:   info = VecDuplicate(V,&G);CHKERRQ(info);

159:   info = PetscInfo(G,"TAO Using finite differences w/o coloring to compute matrix\n"); CHKERRQ(info);

161:   info = TaoAppComputeGradient(taoapp,V,G); CHKERRQ(info);
162:   tao->ngrads++;

164:   info = PetscObjectGetComm((PetscObject)(*H),&comm);CHKERRQ(info);
165:   info = SNESCreate(comm,&snes);CHKERRQ(info);

167:   info = SNESSetFunction(snes,G,Ftemp,taoapp);CHKERRQ(info);
168:   info = SNESDefaultComputeJacobian(snes,V,H,B,flag,taoapp);CHKERRQ(info);

170:   info = SNESDestroy(snes);CHKERRQ(info);
171:   
172:   info = VecDestroy(G);CHKERRQ(info);
173:   
174:   return(0);
175: }




184: /*@C
185:    TaoAppDefaultComputeHessianColor - Computes the Hessian using colored finite differences. 

187:    Collective on TAO_APPLICATION

189:    Input Parameters:
190: +  tao - the TAO_APPLICATION context
191: .  V - compute Hessian at this point
192: -  ctx - the TAO_APPLICATION structure, cast to (void*)

194:    Output Parameters:
195: +  H - Hessian matrix (not altered in this routine)
196: .  B - newly computed Hessian matrix to use with preconditioner (generally the same as H)
197: -  flag - flag indicating whether the matrix sparsity structure has changed

199:    Options Database Keys:
200: +  -mat_fd_coloring_freq <freq>
201: -  -tao_view_hessian - view the hessian after each evaluation using PETSC_VIEWER_STDOUT_WORLD

203:    Level: intermediate

205:    Note:
206:    The gradient evaluation must be set using the routine TaoSetPetscGradient().

208:  .keywords: TAO_APPLICATION, finite differences, Hessian, coloring, sparse

210: .seealso: TaoAppSetHessianRoutine(), TaoAppDefaultComputeHessian(),SNESDefaultComputeJacobianColor(), 
211:           TaoAppSetGradientRoutine(), TaoAppSetColoring()

213: @*/
214: int TaoAppDefaultComputeHessianColor(TAO_APPLICATION taoapp, Vec V, Mat *HH,Mat *BB,
215:                                   MatStructure *flag,void *ctx){
216:   int                 info;
217:   MPI_Comm            comm;
218:   Vec                 G=0;
219:   Mat                 H=*HH,B=*BB;
220:   SNES                snes;
221:   ISColoring          iscoloring;
222:   MatFDColoring       matfdcoloring;
223:   TAO_SOLVER          tao;


231:   info = TaoAppGetTaoSolver(taoapp,&tao); CHKERRQ(info);
232:   info = TaoAppGetColoring(taoapp,&iscoloring); CHKERRQ(info);
233:   if (!iscoloring){
234:     SETERRQ(1,"Must set coloring before using this routine.  Try Finite Differences without coloring\n");
235:   }
236:   info = VecDuplicate(V,&G);CHKERRQ(info);

238:   info=PetscInfo(G,"TAO computing matrix using finite differences and coloring\n"); CHKERRQ(info);

240:   info=TaoAppComputeGradient(taoapp,V,G); CHKERRQ(info);
241:   tao->ngrads++;

243:   info = PetscObjectGetComm((PetscObject)(H),&comm);CHKERRQ(info);
244:   info = SNESCreate(comm,&snes);CHKERRQ(info);

246:   info = MatFDColoringCreate(H,iscoloring,&matfdcoloring);CHKERRQ(info);
247:   info = MatFDColoringSetFunction(matfdcoloring,(int (*)(void)) Ftemp,taoapp);CHKERRQ(info);
248:   info = MatFDColoringSetFromOptions(matfdcoloring);CHKERRQ(info);

250:   info = SNESSetFunction(snes,G,Ftemp,taoapp);CHKERRQ(info);
251:   info = SNESSetJacobian(snes,H,B,SNESDefaultComputeJacobianColor,(void*)matfdcoloring);CHKERRQ(info);
252:   info = SNESDefaultComputeJacobianColor(snes,V,HH,BB,flag,matfdcoloring);CHKERRQ(info);

254:   info = MatFDColoringDestroy(matfdcoloring);CHKERRQ(info);
255:   info = SNESDestroy(snes);CHKERRQ(info);
256:   
257:   info = VecDestroy(G);CHKERRQ(info);
258:   return(0);
259: }

264: /* @
265:   TaoAppSetFiniteDifferencesOptions - Sets various TAO parameters from user options

267:    Collective on TAO_APPLICATION

269:    Input Parameters:
270: +  taoapp - the TAO Application (optional)

272:    Level: beginner

274: .keywords:  options, finite differences

276: .seealso: TaoSolveApplication();

278: @ */
279: int TaoAppSetFiniteDifferencesOptions(TAO_APPLICATION taoapp){
280:   int info;
281:   PetscTruth flg;



287:   flg=PETSC_FALSE;
288:   info = PetscOptionsName("-tao_fd","use finite differences for Hessian","TaoAppDefaultComputeHessian",&flg);CHKERRQ(info);
289:   if (flg) {
290:     info = TaoAppSetHessianRoutine(taoapp,TaoAppDefaultComputeHessian,(void*)taoapp);CHKERRQ(info);
291:     info = PetscInfo(taoapp,"Setting default finite difference Hessian matrix\n"); CHKERRQ(info);
292:   }

294:   flg=PETSC_FALSE;
295:   info = PetscOptionsName("-tao_fdgrad","use finite differences for gradient","TaoAppDefaultComputeGradient",&flg);CHKERRQ(info);
296:   if (flg) {
297:     info = TaoAppSetGradientRoutine(taoapp,TaoAppDefaultComputeGradient,(void*)taoapp);CHKERRQ(info);
298:     info = PetscInfo(taoapp,"Setting default finite difference gradient routine\n"); CHKERRQ(info);
299:   }


302:   flg=PETSC_FALSE;
303:   info = PetscOptionsName("-tao_fd_coloring","use finite differences with coloring to compute Hessian","TaoAppDefaultComputeHessianColor",&flg);CHKERRQ(info);
304:   if (flg) {
305:     info = TaoAppSetHessianRoutine(taoapp,TaoAppDefaultComputeHessianColor,(void*)taoapp);CHKERRQ(info);
306:     info = PetscInfo(taoapp,"Use finite differencing with coloring to compute Hessian \n"); CHKERRQ(info);
307:   }
308:     
309:   return(0);
310: }


313: static char TaoAppColoringXXX[] = "TaoColoring";

315: typedef struct {
316:   ISColoring coloring;
317: } TaoAppColorit;

321: static int TaoAppDestroyColoringXXX(void*ctx){
322:   int info;
323:   TaoAppColorit *mctx=(TaoAppColorit*)ctx;
325:   if (mctx){
326:     /*
327:     if (mctx->coloring){  
328:       info = ISColoringDestroy(mctx->coloring);CHKERRQ(info);
329:     }
330:     */
331:     info = PetscFree(mctx); CHKERRQ(info);
332:   }
333:   return(0);
334: }

338: /*@
339:    TaoAppSetColoring - Set the matrix coloring to be used when computing the
340:    Hessian by finite differences.

342:    Collective on TAO_APPLICATION

344:    Input Parameters:
345: +  app - the TAO_APPLICATION context
346: -  coloring - the coloring to be used

348:    Level: intermediate

350:    Note:
351:    The gradient evaluation must be set using the routine TaoSetPetscGradient().

353:  .keywords: TAO_APPLICATION, finite differences, Hessian, coloring, sparse

355: .seealso: TaoAppSetHessianRoutine(), TaoAppDefaultComputeHessianColor(),
356:           TaoAppSetGradientRoutine()

358: @*/
359: int TaoAppSetColoring(TAO_APPLICATION taoapp, ISColoring coloring){
360:   int ii,info;
361:   TaoAppColorit *mctx;
364:   
365:   info = TaoAppQueryForObject(taoapp,TaoAppColoringXXX,(void**)&mctx); CHKERRQ(info);
366:   if (mctx==0){
367:     info=PetscNew(TaoAppColorit,(void**)&mctx); CHKERRQ(info);
368:     info=TaoAppAddObject(taoapp,TaoAppColoringXXX,(void*)mctx,&ii); CHKERRQ(info);
369:     info=TaoAppSetDestroyRoutine(taoapp,TaoAppDestroyColoringXXX, (void*)mctx); CHKERRQ(info);
370:   }
371:   /*
372:   if (coloring){
373:   info=PetscObjectReference((PetscObject)coloring); CHKERRQ(info);
374:   }
375:   if (mctx->coloring){
376:        info=ISColoringDestroy(mctx->coloring); CHKERRQ(info);
377:   }
378:   */
379:   mctx->coloring=coloring;  
380:   return(0);
381: }

385: /*@C
386:    TaoAppGetColoring - Set the matrix coloring to be used when computing the
387:    Hessian by finite differences.

389:    Collective on TAO_APPLICATION

391:    Input Parameters:
392: +  app - the TAO_APPLICATION context
393: -  coloring - the coloring to be used

395:    Level: advanced

397:    Note:
398:    The gradient evaluation must be set using the routine TaoAppSetGradientRoutine().

400:  .keywords: TAO_APPLICATION, finite differences, Hessian, coloring, sparse

402: .seealso: TaoAppSetHessianRoutine(), TaoAppDefaultComputeHessianColor(),
403:           TaoAppSetGradientRoutine()

405: @*/
406: int TaoAppGetColoring(TAO_APPLICATION taoapp, ISColoring *coloring){
407:   int info;
408:   TaoAppColorit *mctx;
411:   if (coloring){
412:     info = TaoAppQueryForObject(taoapp,TaoAppColoringXXX,(void**)&mctx); CHKERRQ(info);
413:     if (mctx){
414:       *coloring=mctx->coloring;
415:     } else {
416:       *coloring=0;
417:     }
418:   }
419:   return(0);
420: }


425: int TaoAppAddFiniteDifferences(TAO_APPLICATION taoapp){
426:   int info;
428:   info = TaoAppSetOptionsRoutine(taoapp,TaoAppSetFiniteDifferencesOptions); CHKERRQ(info);
429:   return(0);
430: }

432: int MatTAOMFSetGradient(Mat mat,Vec v,int (*func)(TAO_APPLICATION,Vec,Vec,void *),void *funcctx){
434:   return(0);
435: }