1 #include <private/linesearchimpl.h> /*I "petsclinesearch.h" I*/ 2 3 PetscBool LineSearchRegisterAllCalled = PETSC_FALSE; 4 PetscFList LineSearchList = PETSC_NULL; 5 6 PetscClassId LineSearch_CLASSID; 7 PetscLogEvent LineSearch_Apply; 8 9 #undef __FUNCT__ 10 #define __FUNCT__ "LineSearchCreate" 11 PetscErrorCode LineSearchCreate(MPI_Comm comm, LineSearch * outlinesearch) { 12 PetscErrorCode ierr; 13 LineSearch linesearch; 14 PetscFunctionBegin; 15 ierr = PetscHeaderCreate(linesearch, _p_LineSearch,struct _LineSearchOps,LineSearch_CLASSID, 0, 16 "LineSearch","Line-search method","LineSearch",comm,LineSearchDestroy,LineSearchView);CHKERRQ(ierr); 17 18 linesearch->ops->precheckstep = PETSC_NULL; 19 linesearch->ops->postcheckstep = PETSC_NULL; 20 21 linesearch->lambda = 1.0; 22 linesearch->fnorm = 1.0; 23 linesearch->ynorm = 1.0; 24 linesearch->xnorm = 1.0; 25 linesearch->success = PETSC_TRUE; 26 linesearch->norms = PETSC_TRUE; 27 linesearch->keeplambda = PETSC_FALSE; 28 linesearch->damping = 1.0; 29 linesearch->maxstep = 1e8; 30 linesearch->steptol = 1e-12; 31 linesearch->precheckctx = PETSC_NULL; 32 linesearch->postcheckctx = PETSC_NULL; 33 linesearch->max_its = 1; 34 linesearch->setupcalled = PETSC_FALSE; 35 *outlinesearch = linesearch; 36 PetscFunctionReturn(0); 37 } 38 39 #undef __FUNCT__ 40 #define __FUNCT__ "LineSearchSetUp" 41 PetscErrorCode LineSearchSetUp(LineSearch linesearch) { 42 PetscErrorCode ierr; 43 PetscFunctionBegin; 44 45 if (!((PetscObject)linesearch)->type_name) { 46 ierr = LineSearchSetType(linesearch,LINESEARCHBASIC);CHKERRQ(ierr); 47 } 48 49 if (!linesearch->setupcalled) { 50 ierr = VecDuplicate(linesearch->vec_sol, &linesearch->vec_sol_new);CHKERRQ(ierr); 51 ierr = VecDuplicate(linesearch->vec_func, &linesearch->vec_func_new);CHKERRQ(ierr); 52 if (linesearch->ops->setup) { 53 ierr = (*linesearch->ops->setup)(linesearch);CHKERRQ(ierr); 54 } 55 linesearch->lambda = linesearch->damping; 56 linesearch->setupcalled = PETSC_TRUE; 57 } 58 PetscFunctionReturn(0); 59 } 60 61 #undef __FUNCT__ 62 #define __FUNCT__ "LineSearchReset" 63 PetscErrorCode LineSearchReset(LineSearch linesearch) { 64 PetscErrorCode ierr; 65 PetscFunctionBegin; 66 if (linesearch->ops->reset) { 67 (*linesearch->ops->reset)(linesearch); 68 } 69 ierr = VecDestroy(&linesearch->vec_sol_new);CHKERRQ(ierr); 70 ierr = VecDestroy(&linesearch->vec_func_new);CHKERRQ(ierr); 71 72 ierr = VecDestroyVecs(linesearch->nwork, &linesearch->work);CHKERRQ(ierr); 73 linesearch->nwork = 0; 74 linesearch->setupcalled = PETSC_FALSE; 75 PetscFunctionReturn(0); 76 } 77 78 #undef __FUNCT__ 79 #define __FUNCT__ "LineSearchPreCheck" 80 PetscErrorCode LineSearchPreCheck(LineSearch linesearch, PetscBool * changed) 81 { 82 PetscErrorCode ierr; 83 PetscFunctionBegin; 84 *changed = PETSC_FALSE; 85 if (linesearch->ops->precheckstep) { 86 ierr = (*linesearch->ops->precheckstep)(linesearch, linesearch->vec_sol, linesearch->vec_update, changed);CHKERRQ(ierr); 87 } 88 PetscFunctionReturn(0); 89 } 90 91 #undef __FUNCT__ 92 #define __FUNCT__ "LineSearchPostCheck" 93 PetscErrorCode LineSearchPostCheck(LineSearch linesearch, PetscBool * changed_W, PetscBool * changed_Y) 94 { 95 PetscErrorCode ierr; 96 PetscFunctionBegin; 97 *changed_Y = PETSC_FALSE; 98 *changed_W = PETSC_FALSE; 99 if (linesearch->ops->postcheckstep) { 100 ierr = (*linesearch->ops->postcheckstep)(linesearch, linesearch->vec_sol, linesearch->vec_sol_new, linesearch->vec_update, changed_W, changed_Y);CHKERRQ(ierr); 101 } 102 PetscFunctionReturn(0); 103 } 104 105 #undef __FUNCT__ 106 #define __FUNCT__ "LineSearchApply" 107 PetscErrorCode LineSearchApply(LineSearch linesearch, Vec X, Vec F, PetscReal * fnorm, Vec Y) { 108 PetscErrorCode ierr; 109 PetscFunctionBegin; 110 111 /* check the pointers */ 112 PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1); 113 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 114 PetscValidHeaderSpecific(F,VEC_CLASSID,3); 115 PetscValidHeaderSpecific(Y,VEC_CLASSID,4); 116 117 linesearch->success = PETSC_TRUE; 118 119 linesearch->vec_sol = X; 120 linesearch->vec_update = Y; 121 linesearch->vec_func = F; 122 123 ierr = LineSearchSetUp(linesearch);CHKERRQ(ierr); 124 125 if (!linesearch->keeplambda) 126 linesearch->lambda = linesearch->damping; /* set the initial guess to lambda */ 127 128 if (fnorm) { 129 linesearch->fnorm = *fnorm; 130 } else { 131 ierr = VecNorm(F, NORM_2, &linesearch->fnorm);CHKERRQ(ierr); 132 } 133 134 ierr = PetscLogEventBegin(LineSearch_Apply,linesearch,X,F,Y);CHKERRQ(ierr); 135 136 ierr = (*linesearch->ops->apply)(linesearch);CHKERRQ(ierr); 137 138 ierr = PetscLogEventEnd(LineSearch_Apply,linesearch,X,F,Y);CHKERRQ(ierr); 139 140 if (fnorm) 141 *fnorm = linesearch->fnorm; 142 PetscFunctionReturn(0); 143 } 144 145 #undef __FUNCT__ 146 #define __FUNCT__ "LineSearchDestroy" 147 PetscErrorCode LineSearchDestroy(LineSearch * linesearch) { 148 PetscErrorCode ierr; 149 PetscFunctionBegin; 150 if (!*linesearch) PetscFunctionReturn(0); 151 PetscValidHeaderSpecific((*linesearch),LineSearch_CLASSID,1); 152 if (--((PetscObject)(*linesearch))->refct > 0) {*linesearch = 0; PetscFunctionReturn(0);} 153 ierr = PetscObjectDepublish((*linesearch));CHKERRQ(ierr); 154 ierr = LineSearchReset(*linesearch); 155 if ((*linesearch)->ops->destroy) { 156 (*linesearch)->ops->destroy(*linesearch); 157 } 158 ierr = PetscViewerDestroy(&(*linesearch)->monitor);CHKERRQ(ierr); 159 ierr = PetscHeaderDestroy(linesearch);CHKERRQ(ierr); 160 PetscFunctionReturn(0); 161 } 162 163 #undef __FUNCT__ 164 #define __FUNCT__ "LineSearchSetMonitor" 165 /*@C 166 SNESLineSearchSetMonitor - Prints information about the progress or lack of progress of the line search 167 168 Input Parameters: 169 + snes - nonlinear context obtained from SNESCreate() 170 - flg - PETSC_TRUE to monitor the line search 171 172 Logically Collective on SNES 173 174 Options Database: 175 . -snes_ls_monitor 176 177 Level: intermediate 178 179 180 .seealso: SNESLineSearchSet(), SNESLineSearchSetPostCheck(), SNESSetUpdate() 181 @*/ 182 PetscErrorCode LineSearchSetMonitor(LineSearch linesearch,PetscBool flg) 183 { 184 185 PetscErrorCode ierr; 186 PetscFunctionBegin; 187 if (flg && !linesearch->monitor) { 188 ierr = PetscViewerASCIIOpen(((PetscObject)linesearch)->comm,"stdout",&linesearch->monitor);CHKERRQ(ierr); 189 } else if (!flg && linesearch->monitor) { 190 ierr = PetscViewerDestroy(&linesearch->monitor);CHKERRQ(ierr); 191 } 192 PetscFunctionReturn(0); 193 } 194 195 #undef __FUNCT__ 196 #define __FUNCT__ "LineSearchSetFromOptions" 197 PetscErrorCode LineSearchSetFromOptions(LineSearch linesearch) { 198 PetscErrorCode ierr; 199 const char *deft = LINESEARCHBASIC; 200 char type[256]; 201 PetscBool flg, set; 202 PetscFunctionBegin; 203 if (!LineSearchRegisterAllCalled) {ierr = LineSearchRegisterAll(PETSC_NULL);CHKERRQ(ierr);} 204 205 ierr = PetscObjectOptionsBegin((PetscObject)linesearch);CHKERRQ(ierr); 206 if (((PetscObject)linesearch)->type_name) { 207 deft = ((PetscObject)linesearch)->type_name; 208 } 209 ierr = PetscOptionsList("-linesearch_type","Line-search method","LineSearchSetType",LineSearchList,deft,type,256,&flg);CHKERRQ(ierr); 210 if (flg) { 211 ierr = LineSearchSetType(linesearch,type);CHKERRQ(ierr); 212 } else if (!((PetscObject)linesearch)->type_name) { 213 ierr = LineSearchSetType(linesearch,deft);CHKERRQ(ierr); 214 } 215 if (linesearch->ops->setfromoptions) { 216 (*linesearch->ops->setfromoptions)(linesearch);CHKERRQ(ierr); 217 } 218 219 ierr = PetscOptionsBool("-linesearch_monitor","Print progress of line searches","SNESLineSearchSetMonitor", 220 linesearch->monitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr); 221 if (set) {ierr = LineSearchSetMonitor(linesearch,flg);CHKERRQ(ierr);} 222 223 ierr = PetscOptionsReal("-linesearch_damping","Line search damping and initial step guess","LineSearchSetDamping",linesearch->damping,&linesearch->damping,0);CHKERRQ(ierr); 224 ierr = PetscOptionsBool("-linesearch_norms","Compute final norms in line search","LineSearchSetDamping",linesearch->norms,&linesearch->norms,0);CHKERRQ(ierr); 225 ierr = PetscOptionsBool("-linesearch_keeplambda","Use previous lambda as damping","LineSearchSetDamping",linesearch->keeplambda,&linesearch->keeplambda,0);CHKERRQ(ierr); 226 ierr = PetscOptionsInt("-linesearch_max_it","Maximum iterations for iterative line searches","",linesearch->max_its,&linesearch->max_its,0);CHKERRQ(ierr); 227 ierr = PetscObjectProcessOptionsHandlers((PetscObject)linesearch);CHKERRQ(ierr); 228 ierr = PetscOptionsEnd();CHKERRQ(ierr); 229 PetscFunctionReturn(0); 230 } 231 232 #undef __FUNCT__ 233 #define __FUNCT__ "LineSearchView" 234 PetscErrorCode LineSearchView(LineSearch linesearch) { 235 PetscFunctionBegin; 236 PetscFunctionReturn(0); 237 } 238 239 #undef __FUNCT__ 240 #define __FUNCT__ "LineSearchSetType" 241 PetscErrorCode LineSearchSetType(LineSearch linesearch, const LineSearchType type) 242 { 243 244 PetscErrorCode ierr,(*r)(LineSearch); 245 PetscBool match; 246 247 PetscFunctionBegin; 248 PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1); 249 PetscValidCharPointer(type,2); 250 251 ierr = PetscTypeCompare((PetscObject)linesearch,type,&match);CHKERRQ(ierr); 252 if (match) PetscFunctionReturn(0); 253 254 ierr = PetscFListFind(LineSearchList,((PetscObject)linesearch)->comm,type,PETSC_TRUE,(void (**)(void)) &r);CHKERRQ(ierr); 255 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested Line Search type %s",type); 256 /* Destroy the previous private linesearch context */ 257 if (linesearch->ops->destroy) { 258 ierr = (*(linesearch)->ops->destroy)(linesearch);CHKERRQ(ierr); 259 linesearch->ops->destroy = PETSC_NULL; 260 } 261 /* Reinitialize function pointers in LineSearchOps structure */ 262 linesearch->ops->apply = 0; 263 linesearch->ops->view = 0; 264 linesearch->ops->setfromoptions = 0; 265 linesearch->ops->destroy = 0; 266 267 ierr = PetscObjectChangeTypeName((PetscObject)linesearch,type);CHKERRQ(ierr); 268 ierr = (*r)(linesearch);CHKERRQ(ierr); 269 #if defined(PETSC_HAVE_AMS) 270 if (PetscAMSPublishAll) { 271 ierr = PetscObjectAMSPublish((PetscObject)linesearch);CHKERRQ(ierr); 272 } 273 #endif 274 PetscFunctionReturn(0); 275 } 276 277 #undef __FUNCT__ 278 #define __FUNCT__ "LineSearchSetSNES" 279 PetscErrorCode LineSearchSetSNES(LineSearch linesearch, SNES snes){ 280 PetscFunctionBegin; 281 PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1); 282 PetscValidHeaderSpecific(snes,SNES_CLASSID,2); 283 linesearch->snes = snes; 284 PetscFunctionReturn(0); 285 } 286 287 #undef __FUNCT__ 288 #define __FUNCT__ "LineSearchGetSNES" 289 PetscErrorCode LineSearchGetSNES(LineSearch linesearch, SNES *snes){ 290 PetscFunctionBegin; 291 *snes = linesearch->snes; 292 PetscFunctionReturn(0); 293 } 294 295 296 #undef __FUNCT__ 297 #define __FUNCT__ "LineSearchGetNorms" 298 PetscErrorCode LineSearchGetNorms(LineSearch linesearch, PetscReal * xnorm, PetscReal * fnorm, PetscReal * ynorm) 299 { 300 PetscFunctionBegin; 301 if (xnorm) { 302 *xnorm = linesearch->xnorm; 303 } 304 if (fnorm) { 305 *fnorm = linesearch->fnorm; 306 } 307 if (ynorm) { 308 *ynorm = linesearch->ynorm; 309 } 310 PetscFunctionReturn(0); 311 } 312 313 #undef __FUNCT__ 314 #define __FUNCT__ "LineSearchAppendOptionsPrefix" 315 /*@C 316 LineSearchAppendOptionsPrefix - Appends to the prefix used for searching for all 317 SNES options in the database. 318 319 Logically Collective on SNES 320 321 Input Parameters: 322 + snes - the SNES context 323 - prefix - the prefix to prepend to all option names 324 325 Notes: 326 A hyphen (-) must NOT be given at the beginning of the prefix name. 327 The first character of all runtime options is AUTOMATICALLY the hyphen. 328 329 Level: advanced 330 331 .keywords: SNES, append, options, prefix, database 332 333 .seealso: SNESGetOptionsPrefix() 334 @*/ 335 PetscErrorCode LineSearchAppendOptionsPrefix(LineSearch linesearch,const char prefix[]) 336 { 337 PetscErrorCode ierr; 338 339 PetscFunctionBegin; 340 PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1); 341 ierr = PetscObjectAppendOptionsPrefix((PetscObject)linesearch,prefix);CHKERRQ(ierr); 342 PetscFunctionReturn(0); 343 } 344 345 #undef __FUNCT__ 346 #define __FUNCT__ "LineSearchGetOptionsPrefix" 347 /*@C 348 LineSearchGetOptionsPrefix - Sets the prefix used for searching for all 349 SNES options in the database. 350 351 Not Collective 352 353 Input Parameter: 354 . snes - the SNES context 355 356 Output Parameter: 357 . prefix - pointer to the prefix string used 358 359 Notes: On the fortran side, the user should pass in a string 'prefix' of 360 sufficient length to hold the prefix. 361 362 Level: advanced 363 364 .keywords: SNES, get, options, prefix, database 365 366 .seealso: SNESAppendOptionsPrefix() 367 @*/ 368 PetscErrorCode LineSearchGetOptionsPrefix(LineSearch linesearch,const char *prefix[]) 369 { 370 PetscErrorCode ierr; 371 372 PetscFunctionBegin; 373 PetscValidHeaderSpecific(linesearch,LineSearch_CLASSID,1); 374 ierr = PetscObjectGetOptionsPrefix((PetscObject)linesearch,prefix);CHKERRQ(ierr); 375 PetscFunctionReturn(0); 376 } 377 378 #undef __FUNCT__ 379 #define __FUNCT__ "LineSearchGetWork" 380 PetscErrorCode LineSearchGetWork(LineSearch linesearch, PetscInt nwork) 381 { 382 PetscErrorCode ierr; 383 PetscFunctionBegin; 384 if (linesearch->vec_sol) { 385 ierr = VecDuplicateVecs(linesearch->vec_sol, nwork, &linesearch->work);CHKERRQ(ierr); 386 } else { 387 SETERRQ(((PetscObject)linesearch)->comm, PETSC_ERR_USER, "Cannot get linesearch work-vectors without setting a solution vec!"); 388 } 389 PetscFunctionReturn(0); 390 } 391 392 #undef __FUNCT__ 393 #define __FUNCT__ "LineSearchGetSuccess" 394 PetscErrorCode LineSearchGetSuccess(LineSearch linesearch, PetscBool *success) 395 { 396 PetscFunctionBegin; 397 if (success) { 398 *success = linesearch->success; 399 } 400 PetscFunctionReturn(0); 401 } 402 403 #undef __FUNCT__ 404 #define __FUNCT__ "LineSearchRegister" 405 /*@C 406 LineSearchRegister - See LineSearchRegisterDynamic() 407 408 Level: advanced 409 @*/ 410 PetscErrorCode LineSearchRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(LineSearch)) 411 { 412 char fullname[PETSC_MAX_PATH_LEN]; 413 PetscErrorCode ierr; 414 415 PetscFunctionBegin; 416 ierr = PetscFListConcat(path,name,fullname);CHKERRQ(ierr); 417 ierr = PetscFListAdd(&LineSearchList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr); 418 PetscFunctionReturn(0); 419 } 420