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 /*@ 32 TaoComputeGradient - Computes the gradient of the objective function 33 34 Collective on Tao 35 36 Input Parameters: 37 + tao - the Tao context 38 - X - input vector 39 40 Output Parameter: 41 . G - gradient vector 42 43 Notes: TaoComputeGradient() is typically used within minimization implementations, 44 so most users would not generally call this routine themselves. 45 46 Level: advanced 47 48 .seealso: TaoComputeObjective(), TaoComputeObjectiveAndGradient(), TaoSetGradientRoutine() 49 @*/ 50 PetscErrorCode TaoComputeGradient(Tao tao, Vec X, Vec G) 51 { 52 PetscErrorCode ierr; 53 PetscReal dummy; 54 55 PetscFunctionBegin; 56 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 57 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 58 PetscValidHeaderSpecific(G,VEC_CLASSID,2); 59 PetscCheckSameComm(tao,1,X,2); 60 PetscCheckSameComm(tao,1,G,3); 61 ierr = VecLockPush(X);CHKERRQ(ierr); 62 if (tao->ops->computegradient) { 63 ierr = PetscLogEventBegin(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr); 64 PetscStackPush("Tao user gradient evaluation routine"); 65 ierr = (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);CHKERRQ(ierr); 66 PetscStackPop; 67 ierr = PetscLogEventEnd(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr); 68 tao->ngrads++; 69 } else if (tao->ops->computeobjectiveandgradient) { 70 ierr = PetscLogEventBegin(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr); 71 PetscStackPush("Tao user objective/gradient evaluation routine"); 72 ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,&dummy,G,tao->user_objgradP);CHKERRQ(ierr); 73 PetscStackPop; 74 ierr = PetscLogEventEnd(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr); 75 tao->nfuncgrads++; 76 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetGradientRoutine() has not been called"); 77 ierr = VecLockPop(X);CHKERRQ(ierr); 78 PetscFunctionReturn(0); 79 } 80 81 /*@ 82 TaoComputeObjective - Computes the objective function value at a given point 83 84 Collective on Tao 85 86 Input Parameters: 87 + tao - the Tao context 88 - X - input vector 89 90 Output Parameter: 91 . f - Objective value at X 92 93 Notes: TaoComputeObjective() is typically used within minimization implementations, 94 so most users would not generally call this routine themselves. 95 96 Level: advanced 97 98 .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjectiveRoutine() 99 @*/ 100 PetscErrorCode TaoComputeObjective(Tao tao, Vec X, PetscReal *f) 101 { 102 PetscErrorCode ierr; 103 Vec temp; 104 105 PetscFunctionBegin; 106 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 107 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 108 PetscCheckSameComm(tao,1,X,2); 109 ierr = VecLockPush(X);CHKERRQ(ierr); 110 if (tao->ops->computeobjective) { 111 ierr = PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 112 PetscStackPush("Tao user objective evaluation routine"); 113 ierr = (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);CHKERRQ(ierr); 114 PetscStackPop; 115 ierr = PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 116 tao->nfuncs++; 117 } else if (tao->ops->computeobjectiveandgradient) { 118 ierr = PetscInfo(tao,"Duplicating variable vector in order to call func/grad routine\n");CHKERRQ(ierr); 119 ierr = VecDuplicate(X,&temp);CHKERRQ(ierr); 120 ierr = PetscLogEventBegin(Tao_ObjGradientEval,tao,X,NULL,NULL);CHKERRQ(ierr); 121 PetscStackPush("Tao user objective/gradient evaluation routine"); 122 ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,f,temp,tao->user_objgradP);CHKERRQ(ierr); 123 PetscStackPop; 124 ierr = PetscLogEventEnd(Tao_ObjGradientEval,tao,X,NULL,NULL);CHKERRQ(ierr); 125 ierr = VecDestroy(&temp);CHKERRQ(ierr); 126 tao->nfuncgrads++; 127 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjectiveRoutine() has not been called"); 128 ierr = PetscInfo1(tao,"TAO Function evaluation: %14.12e\n",(double)(*f));CHKERRQ(ierr); 129 ierr = VecLockPop(X);CHKERRQ(ierr); 130 PetscFunctionReturn(0); 131 } 132 133 /*@ 134 TaoComputeObjectiveAndGradient - Computes the objective function value at a given point 135 136 Collective on Tao 137 138 Input Parameters: 139 + tao - the Tao context 140 - X - input vector 141 142 Output Parameter: 143 + f - Objective value at X 144 - g - Gradient vector at X 145 146 Notes: TaoComputeObjectiveAndGradient() is typically used within minimization implementations, 147 so most users would not generally call this routine themselves. 148 149 Level: advanced 150 151 .seealso: TaoComputeGradient(), TaoComputeObjectiveAndGradient(), TaoSetObjectiveRoutine() 152 @*/ 153 PetscErrorCode TaoComputeObjectiveAndGradient(Tao tao, Vec X, PetscReal *f, Vec G) 154 { 155 PetscErrorCode ierr; 156 157 PetscFunctionBegin; 158 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 159 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 160 PetscValidHeaderSpecific(G,VEC_CLASSID,4); 161 PetscCheckSameComm(tao,1,X,2); 162 PetscCheckSameComm(tao,1,G,4); 163 ierr = VecLockPush(X);CHKERRQ(ierr); 164 if (tao->ops->computeobjectiveandgradient) { 165 ierr = PetscLogEventBegin(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr); 166 if (tao->ops->computegradient == TaoDefaultComputeGradient) { 167 ierr = TaoComputeObjective(tao,X,f);CHKERRQ(ierr); 168 ierr = TaoDefaultComputeGradient(tao,X,G,NULL);CHKERRQ(ierr); 169 } else { 170 PetscStackPush("Tao user objective/gradient evaluation routine"); 171 ierr = (*tao->ops->computeobjectiveandgradient)(tao,X,f,G,tao->user_objgradP);CHKERRQ(ierr); 172 PetscStackPop; 173 } 174 ierr = PetscLogEventEnd(Tao_ObjGradientEval,tao,X,G,NULL);CHKERRQ(ierr); 175 tao->nfuncgrads++; 176 } else if (tao->ops->computeobjective && tao->ops->computegradient) { 177 ierr = PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 178 PetscStackPush("Tao user objective evaluation routine"); 179 ierr = (*tao->ops->computeobjective)(tao,X,f,tao->user_objP);CHKERRQ(ierr); 180 PetscStackPop; 181 ierr = PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 182 tao->nfuncs++; 183 ierr = PetscLogEventBegin(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr); 184 PetscStackPush("Tao user gradient evaluation routine"); 185 ierr = (*tao->ops->computegradient)(tao,X,G,tao->user_gradP);CHKERRQ(ierr); 186 PetscStackPop; 187 ierr = PetscLogEventEnd(Tao_GradientEval,tao,X,G,NULL);CHKERRQ(ierr); 188 tao->ngrads++; 189 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetObjectiveRoutine() or TaoSetGradientRoutine() not set"); 190 ierr = PetscInfo1(tao,"TAO Function evaluation: %14.12e\n",(double)(*f));CHKERRQ(ierr); 191 ierr = VecLockPop(X);CHKERRQ(ierr); 192 PetscFunctionReturn(0); 193 } 194 195 /*@C 196 TaoSetObjectiveRoutine - Sets the function evaluation routine for minimization 197 198 Logically collective on Tao 199 200 Input Parameter: 201 + tao - the Tao context 202 . func - the objective function 203 - ctx - [optional] user-defined context for private data for the function evaluation 204 routine (may be NULL) 205 206 Calling sequence of func: 207 $ func (Tao tao, Vec x, PetscReal *f, void *ctx); 208 209 + x - input vector 210 . f - function value 211 - ctx - [optional] user-defined function context 212 213 Level: beginner 214 215 .seealso: TaoSetGradientRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine() 216 @*/ 217 PetscErrorCode TaoSetObjectiveRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal*,void*),void *ctx) 218 { 219 PetscFunctionBegin; 220 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 221 tao->user_objP = ctx; 222 tao->ops->computeobjective = func; 223 PetscFunctionReturn(0); 224 } 225 226 /*@C 227 TaoSetSeparableObjectiveRoutine - Sets the function evaluation routine for least-square applications 228 229 Logically collective on Tao 230 231 Input Parameter: 232 + tao - the Tao context 233 . func - the objective function evaluation routine 234 - ctx - [optional] user-defined context for private data for the function evaluation 235 routine (may be NULL) 236 237 Calling sequence of func: 238 $ func (Tao tao, Vec x, Vec f, void *ctx); 239 240 + x - input vector 241 . f - function value vector 242 - ctx - [optional] user-defined function context 243 244 Level: beginner 245 246 .seealso: TaoSetObjectiveRoutine(), TaoSetJacobianRoutine() 247 @*/ 248 PetscErrorCode TaoSetSeparableObjectiveRoutine(Tao tao, Vec sepobj, PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx) 249 { 250 PetscFunctionBegin; 251 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 252 PetscValidHeaderSpecific(sepobj, VEC_CLASSID,2); 253 tao->user_sepobjP = ctx; 254 tao->sep_objective = sepobj; 255 tao->ops->computeseparableobjective = func; 256 PetscFunctionReturn(0); 257 } 258 259 /*@ 260 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. 261 262 Collective on Tao 263 264 Input Parameters: 265 + tao - the Tao context 266 . sigma_v - vector of weights (diagonal terms only) 267 . n - the number of weights (if using off-diagonal) 268 . rows - index list of rows for sigma_w 269 . cols - index list of columns for sigma_w 270 - vals - array of weights 271 272 273 274 Note: Either sigma_v or sigma_w (or both) should be NULL 275 276 Level: intermediate 277 278 .seealso: TaoSetSeparableObjectiveRoutine() 279 @*/ 280 PetscErrorCode TaoSetSeparableObjectiveWeights(Tao tao, Vec sigma_v, PetscInt n, PetscInt *rows, PetscInt *cols, PetscReal *vals) 281 { 282 PetscErrorCode ierr; 283 PetscInt i; 284 PetscFunctionBegin; 285 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 286 ierr = VecDestroy(&tao->sep_weights_v);CHKERRQ(ierr); 287 tao->sep_weights_v=sigma_v; 288 if (sigma_v) { 289 ierr = PetscObjectReference((PetscObject)sigma_v);CHKERRQ(ierr); 290 } 291 if (vals) { 292 if (tao->sep_weights_n) { 293 ierr = PetscFree(tao->sep_weights_rows);CHKERRQ(ierr); 294 ierr = PetscFree(tao->sep_weights_cols);CHKERRQ(ierr); 295 ierr = PetscFree(tao->sep_weights_w);CHKERRQ(ierr); 296 } 297 ierr = PetscMalloc1(n,&tao->sep_weights_rows);CHKERRQ(ierr); 298 ierr = PetscMalloc1(n,&tao->sep_weights_cols);CHKERRQ(ierr); 299 ierr = PetscMalloc1(n,&tao->sep_weights_w);CHKERRQ(ierr); 300 tao->sep_weights_n=n; 301 for (i=0;i<n;i++) { 302 tao->sep_weights_rows[i]=rows[i]; 303 tao->sep_weights_cols[i]=cols[i]; 304 tao->sep_weights_w[i]=vals[i]; 305 } 306 } else { 307 tao->sep_weights_n=0; 308 tao->sep_weights_rows=0; 309 tao->sep_weights_cols=0; 310 } 311 PetscFunctionReturn(0); 312 } 313 /*@ 314 TaoComputeSeparableObjective - Computes a separable objective function vector at a given point (for least-square applications) 315 316 Collective on Tao 317 318 Input Parameters: 319 + tao - the Tao context 320 - X - input vector 321 322 Output Parameter: 323 . f - Objective vector at X 324 325 Notes: TaoComputeSeparableObjective() is typically used within minimization implementations, 326 so most users would not generally call this routine themselves. 327 328 Level: advanced 329 330 .seealso: TaoSetSeparableObjectiveRoutine() 331 @*/ 332 PetscErrorCode TaoComputeSeparableObjective(Tao tao, Vec X, Vec F) 333 { 334 PetscErrorCode ierr; 335 336 PetscFunctionBegin; 337 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 338 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 339 PetscValidHeaderSpecific(F,VEC_CLASSID,3); 340 PetscCheckSameComm(tao,1,X,2); 341 PetscCheckSameComm(tao,1,F,3); 342 if (tao->ops->computeseparableobjective) { 343 ierr = PetscLogEventBegin(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 344 PetscStackPush("Tao user separable objective evaluation routine"); 345 ierr = (*tao->ops->computeseparableobjective)(tao,X,F,tao->user_sepobjP);CHKERRQ(ierr); 346 PetscStackPop; 347 ierr = PetscLogEventEnd(Tao_ObjectiveEval,tao,X,NULL,NULL);CHKERRQ(ierr); 348 tao->nfuncs++; 349 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"TaoSetSeparableObjectiveRoutine() has not been called"); 350 ierr = PetscInfo(tao,"TAO separable function evaluation.\n");CHKERRQ(ierr); 351 PetscFunctionReturn(0); 352 } 353 354 /*@C 355 TaoSetGradientRoutine - Sets the gradient evaluation routine for minimization 356 357 Logically collective on Tao 358 359 Input Parameter: 360 + tao - the Tao context 361 . func - the gradient function 362 - ctx - [optional] user-defined context for private data for the gradient evaluation 363 routine (may be NULL) 364 365 Calling sequence of func: 366 $ func (Tao tao, Vec x, Vec g, void *ctx); 367 368 + x - input vector 369 . g - gradient value (output) 370 - ctx - [optional] user-defined function context 371 372 Level: beginner 373 374 .seealso: TaoSetObjectiveRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine() 375 @*/ 376 PetscErrorCode TaoSetGradientRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, Vec, void*),void *ctx) 377 { 378 PetscFunctionBegin; 379 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 380 tao->user_gradP = ctx; 381 tao->ops->computegradient = func; 382 PetscFunctionReturn(0); 383 } 384 385 /*@C 386 TaoSetObjectiveAndGradientRoutine - Sets a combined objective function and gradient evaluation routine for minimization 387 388 Logically collective on Tao 389 390 Input Parameter: 391 + tao - the Tao context 392 . func - the gradient function 393 - ctx - [optional] user-defined context for private data for the gradient evaluation 394 routine (may be NULL) 395 396 Calling sequence of func: 397 $ func (Tao tao, Vec x, PetscReal *f, Vec g, void *ctx); 398 399 + x - input vector 400 . f - objective value (output) 401 . g - gradient value (output) 402 - ctx - [optional] user-defined function context 403 404 Level: beginner 405 406 .seealso: TaoSetObjectiveRoutine(), TaoSetHessianRoutine() TaoSetObjectiveAndGradientRoutine() 407 @*/ 408 PetscErrorCode TaoSetObjectiveAndGradientRoutine(Tao tao, PetscErrorCode (*func)(Tao, Vec, PetscReal *, Vec, void*), void *ctx) 409 { 410 PetscFunctionBegin; 411 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 412 tao->user_objgradP = ctx; 413 tao->ops->computeobjectiveandgradient = func; 414 PetscFunctionReturn(0); 415 } 416 417 /*@ 418 TaoIsObjectiveDefined -- Checks to see if the user has 419 declared an objective-only routine. Useful for determining when 420 it is appropriate to call TaoComputeObjective() or 421 TaoComputeObjectiveAndGradient() 422 423 Collective on Tao 424 425 Input Parameter: 426 + tao - the Tao context 427 - ctx - PETSC_TRUE if objective function routine is set by user, 428 PETSC_FALSE otherwise 429 Level: developer 430 431 .seealso: TaoSetObjectiveRoutine(), TaoIsGradientDefined(), TaoIsObjectiveAndGradientDefined() 432 @*/ 433 PetscErrorCode TaoIsObjectiveDefined(Tao tao, PetscBool *flg) 434 { 435 PetscFunctionBegin; 436 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 437 if (tao->ops->computeobjective == 0) *flg = PETSC_FALSE; 438 else *flg = PETSC_TRUE; 439 PetscFunctionReturn(0); 440 } 441 442 /*@ 443 TaoIsGradientDefined -- Checks to see if the user has 444 declared an objective-only routine. Useful for determining when 445 it is appropriate to call TaoComputeGradient() or 446 TaoComputeGradientAndGradient() 447 448 Not Collective 449 450 Input Parameter: 451 + tao - the Tao context 452 - ctx - PETSC_TRUE if gradient routine is set by user, PETSC_FALSE otherwise 453 Level: developer 454 455 .seealso: TaoSetGradientRoutine(), TaoIsObjectiveDefined(), TaoIsObjectiveAndGradientDefined() 456 @*/ 457 PetscErrorCode TaoIsGradientDefined(Tao tao, PetscBool *flg) 458 { 459 PetscFunctionBegin; 460 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 461 if (tao->ops->computegradient == 0) *flg = PETSC_FALSE; 462 else *flg = PETSC_TRUE; 463 PetscFunctionReturn(0); 464 } 465 466 /*@ 467 TaoIsObjectiveAndGradientDefined -- Checks to see if the user has 468 declared a joint objective/gradient routine. Useful for determining when 469 it is appropriate to call TaoComputeObjective() or 470 TaoComputeObjectiveAndGradient() 471 472 Not Collective 473 474 Input Parameter: 475 + tao - the Tao context 476 - ctx - PETSC_TRUE if objective/gradient routine is set by user, PETSC_FALSE otherwise 477 Level: developer 478 479 .seealso: TaoSetObjectiveAndGradientRoutine(), TaoIsObjectiveDefined(), TaoIsGradientDefined() 480 @*/ 481 PetscErrorCode TaoIsObjectiveAndGradientDefined(Tao tao, PetscBool *flg) 482 { 483 PetscFunctionBegin; 484 PetscValidHeaderSpecific(tao,TAO_CLASSID,1); 485 if (tao->ops->computeobjectiveandgradient == 0) *flg = PETSC_FALSE; 486 else *flg = PETSC_TRUE; 487 PetscFunctionReturn(0); 488 } 489