1 #include <petsc/private/taoimpl.h> /*I "petsctao.h" I*/ 2 3 /*@ 4 TaoSetInitialVector - Sets the initial guess for the solve 5 6 Logically collective on Tao 7 8 Input Parameters: 9 + tao - the Tao context 10 - x0 - the initial guess 11 12 Level: beginner 13 .seealso: TaoCreate(), TaoSolve() 14 @*/ 15 16 PetscErrorCode TaoSetInitialVector(Tao tao, Vec x0) 17 { 18 PetscErrorCode ierr; 19 20 PetscFunctionBegin; 21 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 22 if (x0) { 23 PetscValidHeaderSpecific(x0,VEC_CLASSID,2); 24 PetscObjectReference((PetscObject)x0); 25 } 26 ierr = VecDestroy(&tao->solution);CHKERRQ(ierr); 27 tao->solution = x0; 28 PetscFunctionReturn(0); 29 } 30 31 PetscErrorCode TaoTestGradient(Tao tao,Vec g1) 32 { 33 Vec x = tao->solution,g2,g3; 34 PetscBool complete_print = PETSC_FALSE,test = PETSC_FALSE; 35 PetscReal hcnorm,fdnorm,hcmax,fdmax,diffmax,diffnorm; 36 PetscScalar dot; 37 MPI_Comm comm; 38 PetscViewer viewer; 39 PetscInt tabs; 40 static PetscBool directionsprinted = PETSC_FALSE; 41 PetscErrorCode ierr; 42 43 PetscFunctionBegin; 44 ierr = PetscObjectOptionsBegin((PetscObject)tao);CHKERRQ(ierr); 45 ierr = PetscOptionsName("-tao_test_gradient","Compare hand-coded and finite difference Gradients","None",&test);CHKERRQ(ierr); 46 ierr = PetscOptionsBool("-tao_test_gradient_view","View difference between hand-coded and finite difference Gradients element entries","None",complete_print,&complete_print,NULL);CHKERRQ(ierr); 47 ierr = PetscOptionsEnd();CHKERRQ(ierr); 48 if (!test) PetscFunctionReturn(0); 49 50 ierr = PetscObjectGetComm((PetscObject)tao,&comm);CHKERRQ(ierr); 51 ierr = PetscViewerASCIIGetStdout(comm,&viewer);CHKERRQ(ierr); 52 ierr = PetscViewerASCIIGetTab(viewer, &tabs);CHKERRQ(ierr); 53 ierr = PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel);CHKERRQ(ierr); 54 ierr = PetscViewerASCIIPrintf(viewer," ---------- Testing Gradient -------------\n");CHKERRQ(ierr); 55 if (!complete_print && !directionsprinted) { 56 ierr = PetscViewerASCIIPrintf(viewer," Run with -tao_test_gradient_view and optionally -tao_test_gradient <threshold> to show difference\n");CHKERRQ(ierr); 57 ierr = PetscViewerASCIIPrintf(viewer," of hand-coded and finite difference gradient entries greater than <threshold>.\n");CHKERRQ(ierr); 58 } 59 if (!directionsprinted) { 60 ierr = PetscViewerASCIIPrintf(viewer," Testing hand-coded Gradient, if (for double precision runs) ||G - Gfd||_F/||G||_F is\n");CHKERRQ(ierr); 61 ierr = PetscViewerASCIIPrintf(viewer," O(1.e-8), the hand-coded Hessian is probably correct.\n");CHKERRQ(ierr); 62 directionsprinted = PETSC_TRUE; 63 } 64 65 ierr = VecDuplicate(x,&g2);CHKERRQ(ierr); 66 ierr = VecDuplicate(x,&g3);CHKERRQ(ierr); 67 68 /* Compute finite difference gradient, assume the gradient is already computed by TaoComputeGradient() and put into g1 */ 69 ierr = TaoDefaultComputeGradient(tao,x,g2,NULL);CHKERRQ(ierr); 70 71 ierr = VecNorm(g2,NORM_2,&fdnorm);CHKERRQ(ierr); 72 ierr = VecNorm(g1,NORM_2,&hcnorm);CHKERRQ(ierr); 73 ierr = VecNorm(g2,NORM_INFINITY,&fdmax);CHKERRQ(ierr); 74 ierr = VecNorm(g1,NORM_INFINITY,&hcmax);CHKERRQ(ierr); 75 ierr = VecDot(g1,g2,&dot);CHKERRQ(ierr); 76 ierr = VecCopy(g1,g3);CHKERRQ(ierr); 77 ierr = VecAXPY(g3,-1.0,g2);CHKERRQ(ierr); 78 ierr = VecNorm(g3,NORM_2,&diffnorm);CHKERRQ(ierr); 79 ierr = VecNorm(g3,NORM_INFINITY,&diffmax);CHKERRQ(ierr); 80 ierr = PetscViewerASCIIPrintf(viewer," ||Gfd|| %g, ||G|| = %g, angle cosine = (Gfd'G)/||Gfd||||G|| = %g\n", (double)fdnorm, (double)hcnorm, (double)(PetscRealPart(dot)/(fdnorm*hcnorm)));CHKERRQ(ierr); 81 ierr = PetscViewerASCIIPrintf(viewer," 2-norm ||G - Gfd||/||G|| = %g, ||G - Gfd|| = %g\n",(double)(diffnorm/PetscMax(hcnorm,fdnorm)),(double)diffnorm);CHKERRQ(ierr); 82 ierr = PetscViewerASCIIPrintf(viewer," max-norm ||G - Gfd||/||G|| = %g, ||G - Gfd|| = %g\n",(double)(diffmax/PetscMax(hcmax,fdmax)),(double)diffmax);CHKERRQ(ierr); 83 84 if (complete_print) { 85 ierr = PetscViewerASCIIPrintf(viewer," Hand-coded gradient ----------\n");CHKERRQ(ierr); 86 ierr = VecView(g1,viewer);CHKERRQ(ierr); 87 ierr = PetscViewerASCIIPrintf(viewer," Finite difference gradient ----------\n");CHKERRQ(ierr); 88 ierr = VecView(g2,viewer);CHKERRQ(ierr); 89 ierr = PetscViewerASCIIPrintf(viewer," Hand-coded minus finite-difference gradient ----------\n");CHKERRQ(ierr); 90 ierr = VecView(g3,viewer);CHKERRQ(ierr); 91 } 92 ierr = VecDestroy(&g2);CHKERRQ(ierr); 93 ierr = VecDestroy(&g3);CHKERRQ(ierr); 94 PetscFunctionReturn(0); 95 } 96 97 /*@ 98 TaoComputeGradient - Computes the gradient of the objective function 99 100 Collective on Tao 101 102 Input Parameters: 103 + tao - the Tao context 104 - X - input vector 105 106 Output Parameter: 107 . G - gradient vector 108 109 Options Database Keys: 110 + -tao_test_gradient - compare the user provided gradient with one compute via finite differences to check for errors 111 - -tao_test_gradient_view - display the user provided gradient, the finite difference gradient and the difference between them to help users detect the location of errors in the user provided gradient 112 113 Notes: 114 TaoComputeGradient() is typically used within minimization implementations, 115 so most users would not generally call this routine themselves. 116 117 Level: advanced 118 119 .seealso: TaoComputeObjective(), TaoComputeObjectiveAndGradient(), TaoSetGradientRoutine() 120 @*/ 121 PetscErrorCode TaoComputeGradient(Tao tao, Vec X, Vec G) 122 { 123 PetscErrorCode ierr; 124 PetscReal dummy; 125 126 PetscFunctionBegin; 127 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 128 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 129 PetscValidHeaderSpecific(G,VEC_CLASSID,2); 130 PetscCheckSameComm(tao,1,X,2); 131 PetscCheckSameComm(tao,1,G,3); 132 ierr = VecLockPush(X);CHKERRQ(ierr); 133 if (tao->ops->computegradient) { 134 ierr = PetscLogEventBegin(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr); 135 PetscStackPush("Tao user gradient evaluation routine"); 136 ierr = (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);CHKERRQ(ierr); 137 PetscStackPop; 138 ierr = PetscLogEventEnd(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr); 139 tao->ngrads++; 140 } else if (tao->ops->computeobjectiveandgradient) { 141 ierr = PetscLogEventBegin(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr); 142 PetscStackPush("Tao user objective/gradient evaluation routine"); 143 ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,&dummy,G,tao->user_objgradP);CHKERRQ(ierr); 144 PetscStackPop; 145 ierr = PetscLogEventEnd(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr); 146 tao->nfuncgrads++; 147 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetGradientRoutine() has not been called"); 148 ierr = VecLockPop(X);CHKERRQ(ierr); 149 150 ierr = TaoTestGradient(tao,G);CHKERRQ(ierr); 151 PetscFunctionReturn(0); 152 } 153 154 /*@ 155 TaoComputeObjective - Computes the objective function value at a given point 156 157 Collective on Tao 158 159 Input Parameters: 160 + tao - the Tao context 161 - X - input vector 162 163 Output Parameter: 164 . f - Objective value at X 165 166 Notes: 167 TaoComputeObjective() is typically used within minimization implementations, 168 so most users would not generally call this routine themselves. 169 170 Level: advanced 171 172 .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjectiveRoutine() 173 @*/ 174 PetscErrorCode TaoComputeObjective(Tao tao, Vec X, PetscReal *f) 175 { 176 PetscErrorCode ierr; 177 Vec temp; 178 179 PetscFunctionBegin; 180 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 181 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 182 PetscCheckSameComm(tao,1,X,2); 183 ierr = VecLockPush(X);CHKERRQ(ierr); 184 if (tao->ops->computeobjective) { 185 ierr = PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 186 PetscStackPush("Tao user objective evaluation routine"); 187 ierr = (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);CHKERRQ(ierr); 188 PetscStackPop; 189 ierr = PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 190 tao->nfuncs++; 191 } else if (tao->ops->computeobjectiveandgradient) { 192 ierr = PetscInfo(tao,"Duplicating variable vector in order to call func/grad routine\n");CHKERRQ(ierr); 193 ierr = VecDuplicate(X,&temp);CHKERRQ(ierr); 194 ierr = PetscLogEventBegin(Tao_ObjGradientEval,tao,X,NULL,NULL);CHKERRQ(ierr); 195 PetscStackPush("Tao user objective/gradient evaluation routine"); 196 ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,f,temp,tao->user_objgradP);CHKERRQ(ierr); 197 PetscStackPop; 198 ierr = PetscLogEventEnd(Tao_ObjGradientEval,tao,X,NULL,NULL);CHKERRQ(ierr); 199 ierr = VecDestroy(&temp);CHKERRQ(ierr); 200 tao->nfuncgrads++; 201 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjectiveRoutine() has not been called"); 202 ierr = PetscInfo1(tao,"TAO Function evaluation: %20.19e\n",(double)(*f));CHKERRQ(ierr); 203 ierr = VecLockPop(X);CHKERRQ(ierr); 204 PetscFunctionReturn(0); 205 } 206 207 /*@ 208 TaoComputeObjectiveAndGradient - Computes the objective function value at a given point 209 210 Collective on Tao 211 212 Input Parameters: 213 + tao - the Tao context 214 - X - input vector 215 216 Output Parameter: 217 + f - Objective value at X 218 - g - Gradient vector at X 219 220 Notes: 221 TaoComputeObjectiveAndGradient() is typically used within minimization implementations, 222 so most users would not generally call this routine themselves. 223 224 Level: advanced 225 226 .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjectiveRoutine() 227 @*/ 228 PetscErrorCode TaoComputeObjectiveAndGradient(Tao tao, Vec X, PetscReal *f, Vec G) 229 { 230 PetscErrorCode ierr; 231 232 PetscFunctionBegin; 233 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 234 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 235 PetscValidHeaderSpecific(G,VEC_CLASSID,4); 236 PetscCheckSameComm(tao,1,X,2); 237 PetscCheckSameComm(tao,1,G,4); 238 ierr = VecLockPush(X);CHKERRQ(ierr); 239 if (tao->ops->computeobjectiveandgradient) { 240 ierr = PetscLogEventBegin(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr); 241 if (tao->ops->computegradient == TaoDefaultComputeGradient) { 242 ierr = TaoComputeObjective(tao,X,f);CHKERRQ(ierr); 243 ierr = TaoDefaultComputeGradient(tao,X,G,NULL);CHKERRQ(ierr); 244 } else { 245 PetscStackPush("Tao user objective/gradient evaluation routine"); 246 ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,f,G,tao->user_objgradP);CHKERRQ(ierr); 247 PetscStackPop; 248 } 249 ierr = PetscLogEventEnd(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr); 250 tao->nfuncgrads++; 251 } else if (tao->ops->computeobjective && tao->ops->computegradient) { 252 ierr = PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 253 PetscStackPush("Tao user objective evaluation routine"); 254 ierr = (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);CHKERRQ(ierr); 255 PetscStackPop; 256 ierr = PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 257 tao->nfuncs++; 258 ierr = PetscLogEventBegin(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr); 259 PetscStackPush("Tao user gradient evaluation routine"); 260 ierr = (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);CHKERRQ(ierr); 261 PetscStackPop; 262 ierr = PetscLogEventEnd(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr); 263 tao->ngrads++; 264 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjectiveRoutine() or TaoSetGradientRoutine() not set"); 265 ierr = PetscInfo1(tao,"TAO Function evaluation: %20.19e\n",(double)(*f));CHKERRQ(ierr); 266 ierr = VecLockPop(X);CHKERRQ(ierr); 267 268 ierr = TaoTestGradient(tao,G);CHKERRQ(ierr); 269 PetscFunctionReturn(0); 270 } 271 272 /*@C 273 TaoSetObjectiveRoutine - Sets the function evaluation routine for minimization 274 275 Logically collective on Tao 276 277 Input Parameter: 278 + tao - the Tao context 279 . func - the objective function 280 - ctx - [optional] user-defined context for private data for the function evaluation 281 routine (may be NULL) 282 283 Calling sequence of func: 284 $ func (Tao tao, Vec x, PetscReal *f, void *ctx); 285 286 + x - input vector 287 . f - function value 288 - ctx - [optional] user-defined function context 289 290 Level: beginner 291 292 .seealso: TaoSetGradientRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine() 293 @*/ 294 PetscErrorCode TaoSetObjectiveRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal*,void*),void *ctx) 295 { 296 PetscFunctionBegin; 297 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 298 tao->user_objP = ctx; 299 tao->ops->computeobjective = func; 300 PetscFunctionReturn(0); 301 } 302 303 /*@C 304 TaoSetSeparableObjectiveRoutine - Sets the function evaluation routine for least-square applications 305 306 Logically collective on Tao 307 308 Input Parameter: 309 + tao - the Tao context 310 . func - the objective function evaluation routine 311 - ctx - [optional] user-defined context for private data for the function evaluation 312 routine (may be NULL) 313 314 Calling sequence of func: 315 $ func (Tao tao, Vec x, Vec f, void *ctx); 316 317 + x - input vector 318 . f - function value vector 319 - ctx - [optional] user-defined function context 320 321 Level: beginner 322 323 .seealso: TaoSetObjectiveRoutine(), TaoSetJacobianRoutine() 324 @*/ 325 PetscErrorCode TaoSetSeparableObjectiveRoutine(Tao tao, Vec sepobj, PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx) 326 { 327 PetscFunctionBegin; 328 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 329 PetscValidHeaderSpecific(sepobj, VEC_CLASSID,2); 330 tao->user_sepobjP = ctx; 331 tao->sep_objective = sepobj; 332 tao->ops->computeseparableobjective = func; 333 PetscFunctionReturn(0); 334 } 335 336 /*@ 337 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. 338 339 Collective on Tao 340 341 Input Parameters: 342 + tao - the Tao context 343 . sigma_v - vector of weights (diagonal terms only) 344 . n - the number of weights (if using off-diagonal) 345 . rows - index list of rows for sigma_w 346 . cols - index list of columns for sigma_w 347 - vals - array of weights 348 349 350 351 Note: Either sigma_v or sigma_w (or both) should be NULL 352 353 Level: intermediate 354 355 .seealso: TaoSetSeparableObjectiveRoutine() 356 @*/ 357 PetscErrorCode TaoSetSeparableObjectiveWeights(Tao tao, Vec sigma_v, PetscInt n, PetscInt *rows, PetscInt *cols, PetscReal *vals) 358 { 359 PetscErrorCode ierr; 360 PetscInt i; 361 PetscFunctionBegin; 362 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 363 ierr = VecDestroy(&tao->sep_weights_v);CHKERRQ(ierr); 364 tao->sep_weights_v=sigma_v; 365 if (sigma_v) { 366 ierr = PetscObjectReference((PetscObject)sigma_v);CHKERRQ(ierr); 367 } 368 if (vals) { 369 if (tao->sep_weights_n) { 370 ierr = PetscFree(tao->sep_weights_rows);CHKERRQ(ierr); 371 ierr = PetscFree(tao->sep_weights_cols);CHKERRQ(ierr); 372 ierr = PetscFree(tao->sep_weights_w);CHKERRQ(ierr); 373 } 374 ierr = PetscMalloc1(n,&tao->sep_weights_rows);CHKERRQ(ierr); 375 ierr = PetscMalloc1(n,&tao->sep_weights_cols);CHKERRQ(ierr); 376 ierr = PetscMalloc1(n,&tao->sep_weights_w);CHKERRQ(ierr); 377 tao->sep_weights_n=n; 378 for (i=0;i<n;i++) { 379 tao->sep_weights_rows[i]=rows[i]; 380 tao->sep_weights_cols[i]=cols[i]; 381 tao->sep_weights_w[i]=vals[i]; 382 } 383 } else { 384 tao->sep_weights_n=0; 385 tao->sep_weights_rows=0; 386 tao->sep_weights_cols=0; 387 } 388 PetscFunctionReturn(0); 389 } 390 /*@ 391 TaoComputeSeparableObjective - Computes a separable objective function vector at a given point (for least-square applications) 392 393 Collective on Tao 394 395 Input Parameters: 396 + tao - the Tao context 397 - X - input vector 398 399 Output Parameter: 400 . f - Objective vector at X 401 402 Notes: 403 TaoComputeSeparableObjective() is typically used within minimization implementations, 404 so most users would not generally call this routine themselves. 405 406 Level: advanced 407 408 .seealso: TaoSetSeparableObjectiveRoutine() 409 @*/ 410 PetscErrorCode TaoComputeSeparableObjective(Tao tao, Vec X, Vec F) 411 { 412 PetscErrorCode ierr; 413 414 PetscFunctionBegin; 415 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 416 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 417 PetscValidHeaderSpecific(F,VEC_CLASSID,3); 418 PetscCheckSameComm(tao,1,X,2); 419 PetscCheckSameComm(tao,1,F,3); 420 if (tao->ops->computeseparableobjective) { 421 ierr = PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 422 PetscStackPush("Tao user separable objective evaluation routine"); 423 ierr = (*tao->ops->computeseparableobjective)(tao,X,F,tao->user_sepobjP);CHKERRQ(ierr); 424 PetscStackPop; 425 ierr = PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 426 tao->nfuncs++; 427 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetSeparableObjectiveRoutine() has not been called"); 428 ierr = PetscInfo(tao,"TAO separable function evaluation.\n");CHKERRQ(ierr); 429 PetscFunctionReturn(0); 430 } 431 432 /*@C 433 TaoSetGradientRoutine - Sets the gradient evaluation routine for minimization 434 435 Logically collective on Tao 436 437 Input Parameter: 438 + tao - the Tao context 439 . func - the gradient function 440 - ctx - [optional] user-defined context for private data for the gradient evaluation 441 routine (may be NULL) 442 443 Calling sequence of func: 444 $ func (Tao tao, Vec x, Vec g, void *ctx); 445 446 + x - input vector 447 . g - gradient value (output) 448 - ctx - [optional] user-defined function context 449 450 Level: beginner 451 452 .seealso: TaoSetObjectiveRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine() 453 @*/ 454 PetscErrorCode TaoSetGradientRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx) 455 { 456 PetscFunctionBegin; 457 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 458 tao->user_gradP = ctx; 459 tao->ops->computegradient = func; 460 PetscFunctionReturn(0); 461 } 462 463 /*@C 464 TaoSetObjectiveAndGradientRoutine - Sets a combined objective function and gradient evaluation routine for minimization 465 466 Logically collective on Tao 467 468 Input Parameter: 469 + tao - the Tao context 470 . func - the gradient function 471 - ctx - [optional] user-defined context for private data for the gradient evaluation 472 routine (may be NULL) 473 474 Calling sequence of func: 475 $ func (Tao tao, Vec x, PetscReal *f, Vec g, void *ctx); 476 477 + x - input vector 478 . f - objective value (output) 479 . g - gradient value (output) 480 - ctx - [optional] user-defined function context 481 482 Level: beginner 483 484 .seealso: TaoSetObjectiveRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine() 485 @*/ 486 PetscErrorCode TaoSetObjectiveAndGradientRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal *, Vec, void*), void *ctx) 487 { 488 PetscFunctionBegin; 489 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 490 tao->user_objgradP = ctx; 491 tao->ops->computeobjectiveandgradient = func; 492 PetscFunctionReturn(0); 493 } 494 495 /*@ 496 TaoIsObjectiveDefined -- Checks to see if the user has 497 declared an objective-only routine. Useful for determining when 498 it is appropriate to call TaoComputeObjective() or 499 TaoComputeObjectiveAndGradient() 500 501 Collective on Tao 502 503 Input Parameter: 504 + tao - the Tao context 505 - ctx - PETSC_TRUE if objective function routine is set by user, 506 PETSC_FALSE otherwise 507 Level: developer 508 509 .seealso: TaoSetObjectiveRoutine(), TaoIsGradientDefined(), TaoIsObjectiveAndGradientDefined() 510 @*/ 511 PetscErrorCode TaoIsObjectiveDefined(Tao tao, PetscBool *flg) 512 { 513 PetscFunctionBegin; 514 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 515 if (tao->ops->computeobjective == 0) *flg = PETSC_FALSE; 516 else *flg = PETSC_TRUE; 517 PetscFunctionReturn(0); 518 } 519 520 /*@ 521 TaoIsGradientDefined -- Checks to see if the user has 522 declared an objective-only routine. Useful for determining when 523 it is appropriate to call TaoComputeGradient() or 524 TaoComputeGradientAndGradient() 525 526 Not Collective 527 528 Input Parameter: 529 + tao - the Tao context 530 - ctx - PETSC_TRUE if gradient routine is set by user, PETSC_FALSE otherwise 531 Level: developer 532 533 .seealso: TaoSetGradientRoutine(), TaoIsObjectiveDefined(), TaoIsObjectiveAndGradientDefined() 534 @*/ 535 PetscErrorCode TaoIsGradientDefined(Tao tao, PetscBool *flg) 536 { 537 PetscFunctionBegin; 538 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 539 if (tao->ops->computegradient == 0) *flg = PETSC_FALSE; 540 else *flg = PETSC_TRUE; 541 PetscFunctionReturn(0); 542 } 543 544 /*@ 545 TaoIsObjectiveAndGradientDefined -- Checks to see if the user has 546 declared a joint objective/gradient routine. Useful for determining when 547 it is appropriate to call TaoComputeObjective() or 548 TaoComputeObjectiveAndGradient() 549 550 Not Collective 551 552 Input Parameter: 553 + tao - the Tao context 554 - ctx - PETSC_TRUE if objective/gradient routine is set by user, PETSC_FALSE otherwise 555 Level: developer 556 557 .seealso: TaoSetObjectiveAndGradientRoutine(), TaoIsObjectiveDefined(), TaoIsGradientDefined() 558 @*/ 559 PetscErrorCode TaoIsObjectiveAndGradientDefined(Tao tao, PetscBool *flg) 560 { 561 PetscFunctionBegin; 562 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 563 if (tao->ops->computeobjectiveandgradient == 0) *flg = PETSC_FALSE; 564 else *flg = PETSC_TRUE; 565 PetscFunctionReturn(0); 566 } 567