Actual source code: taosolver_fg.c

petsc-3.7.7 2017-09-25
Report Typos and Errors
  1: #include <petsc/private/taoimpl.h> /*I "petsctao.h" I*/

  5: /*@
  6:   TaoSetInitialVector - Sets the initial guess for the solve

  8:   Logically collective on Tao

 10:   Input Parameters:
 11: + tao - the Tao context
 12: - x0  - the initial guess

 14:   Level: beginner
 15: .seealso: TaoCreate(), TaoSolve()
 16: @*/

 18: PetscErrorCode TaoSetInitialVector(Tao tao, Vec x0)
 19: {

 24:   if (x0) {
 26:     PetscObjectReference((PetscObject)x0);
 27:   }
 28:   VecDestroy(&tao->solution);
 29:   tao->solution = x0;
 30:   return(0);
 31: }

 35: /*@
 36:   TaoComputeGradient - Computes the gradient of the objective function

 38:   Collective on Tao

 40:   Input Parameters:
 41: + tao - the Tao context
 42: - X - input vector

 44:   Output Parameter:
 45: . G - gradient vector

 47:   Notes: TaoComputeGradient() is typically used within minimization implementations,
 48:   so most users would not generally call this routine themselves.

 50:   Level: advanced

 52: .seealso: TaoComputeObjective(), TaoComputeObjectiveAndGradient(), TaoSetGradientRoutine()
 53: @*/
 54: PetscErrorCode TaoComputeGradient(Tao tao, Vec X, Vec G)
 55: {
 57:   PetscReal      dummy;

 65:   if (tao->ops->computegradient) {
 66:     PetscLogEventBegin(Tao_GradientEval,tao,X,G,NULL);
 67:     PetscStackPush("Tao user gradient evaluation routine");
 68:     (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);
 69:     PetscStackPop;
 70:     PetscLogEventEnd(Tao_GradientEval,tao,X,G,NULL);
 71:     tao->ngrads++;
 72:   } else if (tao->ops->computeobjectiveandgradient) {
 73:     PetscLogEventBegin(Tao_ObjGradientEval,tao,X,G,NULL);
 74:     PetscStackPush("Tao user objective/gradient evaluation routine");
 75:     (*tao->ops->computeobjectiveandgradient)(tao,X,&dummy,G,tao->user_objgradP);
 76:     PetscStackPop;
 77:     PetscLogEventEnd(Tao_ObjGradientEval,tao,X,G,NULL);
 78:     tao->nfuncgrads++;
 79:   }  else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetGradientRoutine() has not been called");
 80:   return(0);
 81: }

 85: /*@
 86:   TaoComputeObjective - Computes the objective function value at a given point

 88:   Collective on Tao

 90:   Input Parameters:
 91: + tao - the Tao context
 92: - X - input vector

 94:   Output Parameter:
 95: . f - Objective value at X

 97:   Notes: TaoComputeObjective() is typically used within minimization implementations,
 98:   so most users would not generally call this routine themselves.

100:   Level: advanced

102: .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjectiveRoutine()
103: @*/
104: PetscErrorCode TaoComputeObjective(Tao tao, Vec X, PetscReal *f)
105: {
107:   Vec            temp;

113:   if (tao->ops->computeobjective) {
114:     PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);
115:     PetscStackPush("Tao user objective evaluation routine");
116:     (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);
117:     PetscStackPop;
118:     PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);
119:     tao->nfuncs++;
120:   } else if (tao->ops->computeobjectiveandgradient) {
121:     PetscInfo(tao,"Duplicating variable vector in order to call func/grad routine\n");
122:     VecDuplicate(X,&temp);
123:     PetscLogEventBegin(Tao_ObjGradientEval,tao,X,NULL,NULL);
124:     PetscStackPush("Tao user objective/gradient evaluation routine");
125:     (*tao->ops->computeobjectiveandgradient)(tao,X,f,temp,tao->user_objgradP);
126:     PetscStackPop;
127:     PetscLogEventEnd(Tao_ObjGradientEval,tao,X,NULL,NULL);
128:     VecDestroy(&temp);
129:     tao->nfuncgrads++;
130:   }  else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjectiveRoutine() has not been called");
131:   PetscInfo1(tao,"TAO Function evaluation: %14.12e\n",(double)(*f));
132:   return(0);
133: }

137: /*@
138:   TaoComputeObjectiveAndGradient - Computes the objective function value at a given point

140:   Collective on Tao

142:   Input Parameters:
143: + tao - the Tao context
144: - X - input vector

146:   Output Parameter:
147: + f - Objective value at X
148: - g - Gradient vector at X

150:   Notes: TaoComputeObjectiveAndGradient() is typically used within minimization implementations,
151:   so most users would not generally call this routine themselves.

153:   Level: advanced

155: .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjectiveRoutine()
156: @*/
157: PetscErrorCode TaoComputeObjectiveAndGradient(Tao tao, Vec X, PetscReal *f, Vec G)
158: {

167:   if (tao->ops->computeobjectiveandgradient) {
168:     PetscLogEventBegin(Tao_ObjGradientEval,tao,X,G,NULL);
169:     PetscStackPush("Tao user objective/gradient evaluation routine");
170:     (*tao->ops->computeobjectiveandgradient)(tao,X,f,G,tao->user_objgradP);
171:     PetscStackPop;
172:     if (tao->ops->computegradient == TaoDefaultComputeGradient) {
173:       /* Overwrite gradient with finite difference gradient */
174:       TaoDefaultComputeGradient(tao,X,G,tao->user_objgradP);
175:     }
176:     PetscLogEventEnd(Tao_ObjGradientEval,tao,X,G,NULL);
177:     tao->nfuncgrads++;
178:   } else if (tao->ops->computeobjective && tao->ops->computegradient) {
179:     PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);
180:     PetscStackPush("Tao user objective evaluation routine");
181:     (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);
182:     PetscStackPop;
183:     PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);
184:     tao->nfuncs++;
185:     PetscLogEventBegin(Tao_GradientEval,tao,X,G,NULL);
186:     PetscStackPush("Tao user gradient evaluation routine");
187:     (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);
188:     PetscStackPop;
189:     PetscLogEventEnd(Tao_GradientEval,tao,X,G,NULL);
190:     tao->ngrads++;
191:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjectiveRoutine() or TaoSetGradientRoutine() not set");
192:   PetscInfo1(tao,"TAO Function evaluation: %14.12e\n",(double)(*f));
193:   return(0);
194: }

198: /*@C
199:   TaoSetObjectiveRoutine - Sets the function evaluation routine for minimization

201:   Logically collective on Tao

203:   Input Parameter:
204: + tao - the Tao context
205: . func - the objective function
206: - ctx - [optional] user-defined context for private data for the function evaluation
207:         routine (may be NULL)

209:   Calling sequence of func:
210: $      func (Tao tao, Vec x, PetscReal *f, void *ctx);

212: + x - input vector
213: . f - function value
214: - ctx - [optional] user-defined function context

216:   Level: beginner

218: .seealso: TaoSetGradientRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine()
219: @*/
220: PetscErrorCode TaoSetObjectiveRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal*,void*),void *ctx)
221: {
224:   tao->user_objP = ctx;
225:   tao->ops->computeobjective = func;
226:   return(0);
227: }

231: /*@C
232:   TaoSetSeparableObjectiveRoutine - Sets the function evaluation routine for least-square applications

234:   Logically collective on Tao

236:   Input Parameter:
237: + tao - the Tao context
238: . func - the objective function evaluation routine
239: - ctx - [optional] user-defined context for private data for the function evaluation
240:         routine (may be NULL)

242:   Calling sequence of func:
243: $      func (Tao tao, Vec x, Vec f, void *ctx);

245: + x - input vector
246: . f - function value vector
247: - ctx - [optional] user-defined function context

249:   Level: beginner

251: .seealso: TaoSetObjectiveRoutine(), TaoSetJacobianRoutine()
252: @*/
253: PetscErrorCode TaoSetSeparableObjectiveRoutine(Tao tao, Vec sepobj, PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx)
254: {
258:   tao->user_sepobjP = ctx;
259:   tao->sep_objective = sepobj;
260:   tao->ops->computeseparableobjective = func;
261:   return(0);
262: }

266: /*@
267:   TaoSetSeparableObjectiveWeights - Give weights for the separable objective values. A vector can be used if only diagonal terms are used, otherwise a matrix can be give. If this function is not used, or if sigma_v and sigma_w are both NULL, then the default identity matrix will be used for weights.

269:   Collective on Tao

271:   Input Parameters:
272: + tao - the Tao context
273: . sigma_v - vector of weights (diagonal terms only)
274: . n       - the number of weights (if using off-diagonal)
275: . rows    - index list of rows for sigma_w
276: . cols    - index list of columns for sigma_w
277: - vals - array of weights



281:   Note: Either sigma_v or sigma_w (or both) should be NULL

283:   Level: intermediate

285: .seealso: TaoSetSeparableObjectiveRoutine()
286: @*/
287: PetscErrorCode TaoSetSeparableObjectiveWeights(Tao tao, Vec sigma_v, PetscInt n, PetscInt *rows, PetscInt *cols, PetscReal *vals)
288: {
290:   PetscInt       i;
293:   VecDestroy(&tao->sep_weights_v);
294:   tao->sep_weights_v=sigma_v;
295:   if (sigma_v) {
296:     PetscObjectReference((PetscObject)sigma_v);
297:   }
298:   if (vals) {
299:     if (tao->sep_weights_n) {
300:       PetscFree(tao->sep_weights_rows);
301:       PetscFree(tao->sep_weights_cols);
302:       PetscFree(tao->sep_weights_w);
303:     }
304:     PetscMalloc1(n,&tao->sep_weights_rows);
305:     PetscMalloc1(n,&tao->sep_weights_cols);
306:     PetscMalloc1(n,&tao->sep_weights_w);
307:     tao->sep_weights_n=n;
308:     for (i=0;i<n;i++) {
309:       tao->sep_weights_rows[i]=rows[i];
310:       tao->sep_weights_cols[i]=cols[i];
311:       tao->sep_weights_w[i]=vals[i];
312:     }
313:   } else {
314:     tao->sep_weights_n=0;
315:     tao->sep_weights_rows=0;
316:     tao->sep_weights_cols=0;
317:   }
318:   return(0);
319: }
322: /*@
323:   TaoComputeSeparableObjective - Computes a separable objective function vector at a given point (for least-square applications)

325:   Collective on Tao

327:   Input Parameters:
328: + tao - the Tao context
329: - X - input vector

331:   Output Parameter:
332: . f - Objective vector at X

334:   Notes: TaoComputeSeparableObjective() is typically used within minimization implementations,
335:   so most users would not generally call this routine themselves.

337:   Level: advanced

339: .seealso: TaoSetSeparableObjectiveRoutine()
340: @*/
341: PetscErrorCode TaoComputeSeparableObjective(Tao tao, Vec X, Vec F)
342: {

351:   if (tao->ops->computeseparableobjective) {
352:     PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);
353:     PetscStackPush("Tao user separable objective evaluation routine");
354:     (*tao->ops->computeseparableobjective)(tao,X,F,tao->user_sepobjP);
355:     PetscStackPop;
356:     PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);
357:     tao->nfuncs++;
358:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetSeparableObjectiveRoutine() has not been called");
359:   PetscInfo(tao,"TAO separable function evaluation.\n");
360:   return(0);
361: }

365: /*@C
366:   TaoSetGradientRoutine - Sets the gradient evaluation routine for minimization

368:   Logically collective on Tao

370:   Input Parameter:
371: + tao - the Tao context
372: . func - the gradient function
373: - ctx - [optional] user-defined context for private data for the gradient evaluation
374:         routine (may be NULL)

376:   Calling sequence of func:
377: $      func (Tao tao, Vec x, Vec g, void *ctx);

379: + x - input vector
380: . g - gradient value (output)
381: - ctx - [optional] user-defined function context

383:   Level: beginner

385: .seealso: TaoSetObjectiveRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine()
386: @*/
387: PetscErrorCode TaoSetGradientRoutine(Tao tao,  PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx)
388: {
391:   tao->user_gradP = ctx;
392:   tao->ops->computegradient = func;
393:   return(0);
394: }


399: /*@C
400:   TaoSetObjectiveAndGradientRoutine - Sets a combined objective function and gradient evaluation routine for minimization

402:   Logically collective on Tao

404:   Input Parameter:
405: + tao - the Tao context
406: . func - the gradient function
407: - ctx - [optional] user-defined context for private data for the gradient evaluation
408:         routine (may be NULL)

410:   Calling sequence of func:
411: $      func (Tao tao, Vec x, PetscReal *f, Vec g, void *ctx);

413: + x - input vector
414: . f - objective value (output)
415: . g - gradient value (output)
416: - ctx - [optional] user-defined function context

418:   Level: beginner

420: .seealso: TaoSetObjectiveRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine()
421: @*/
422: PetscErrorCode TaoSetObjectiveAndGradientRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal *, Vec, void*), void *ctx)
423: {
426:   tao->user_objgradP = ctx;
427:   tao->ops->computeobjectiveandgradient = func;
428:   return(0);
429: }

433: /*@
434:   TaoIsObjectiveDefined -- Checks to see if the user has
435:   declared an objective-only routine.  Useful for determining when
436:   it is appropriate to call TaoComputeObjective() or
437:   TaoComputeObjectiveAndGradient()

439:   Collective on Tao

441:   Input Parameter:
442: + tao - the Tao context
443: - ctx - PETSC_TRUE if objective function routine is set by user,
444:         PETSC_FALSE otherwise
445:   Level: developer

447: .seealso: TaoSetObjectiveRoutine(), TaoIsGradientDefined(), TaoIsObjectiveAndGradientDefined()
448: @*/
449: PetscErrorCode TaoIsObjectiveDefined(Tao tao, PetscBool *flg)
450: {
453:   if (tao->ops->computeobjective == 0) *flg = PETSC_FALSE;
454:   else *flg = PETSC_TRUE;
455:   return(0);
456: }

460: /*@
461:   TaoIsGradientDefined -- Checks to see if the user has
462:   declared an objective-only routine.  Useful for determining when
463:   it is appropriate to call TaoComputeGradient() or
464:   TaoComputeGradientAndGradient()

466:   Not Collective

468:   Input Parameter:
469: + tao - the Tao context
470: - ctx - PETSC_TRUE if gradient routine is set by user, PETSC_FALSE otherwise
471:   Level: developer

473: .seealso: TaoSetGradientRoutine(), TaoIsObjectiveDefined(), TaoIsObjectiveAndGradientDefined()
474: @*/
475: PetscErrorCode TaoIsGradientDefined(Tao tao, PetscBool *flg)
476: {
479:   if (tao->ops->computegradient == 0) *flg = PETSC_FALSE;
480:   else *flg = PETSC_TRUE;
481:   return(0);
482: }


487: /*@
488:   TaoIsObjectiveAndGradientDefined -- Checks to see if the user has
489:   declared a joint objective/gradient routine.  Useful for determining when
490:   it is appropriate to call TaoComputeObjective() or
491:   TaoComputeObjectiveAndGradient()

493:   Not Collective

495:   Input Parameter:
496: + tao - the Tao context
497: - ctx - PETSC_TRUE if objective/gradient routine is set by user, PETSC_FALSE otherwise
498:   Level: developer

500: .seealso: TaoSetObjectiveAndGradientRoutine(), TaoIsObjectiveDefined(), TaoIsGradientDefined()
501: @*/
502: PetscErrorCode TaoIsObjectiveAndGradientDefined(Tao tao, PetscBool *flg)
503: {
506:   if (tao->ops->computeobjectiveandgradient == 0) *flg = PETSC_FALSE;
507:   else *flg = PETSC_TRUE;
508:   return(0);
509: }