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: }