1 #include <../src/snes/impls/ngmres/snesngmres.h> /*I "petscsnes.h" I*/ 2 #include <petscblaslapack.h> 3 4 const char *const SNESNGMRESRestartTypes[] = {"NONE","PERIODIC","DIFFERENCE","SNESNGMRESRestartType","SNES_NGMRES_RESTART_",0}; 5 const char *const SNESNGMRESSelectTypes[] = {"NONE","DIFFERENCE","LINESEARCH","SNESNGMRESSelectType","SNES_NGMRES_SELECT_",0}; 6 7 #undef __FUNCT__ 8 #define __FUNCT__ "SNESReset_NGMRES" 9 PetscErrorCode SNESReset_NGMRES(SNES snes) 10 { 11 SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 12 PetscErrorCode ierr; 13 14 PetscFunctionBegin; 15 ierr = VecDestroyVecs(ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr); 16 ierr = VecDestroyVecs(ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr); 17 ierr = SNESLineSearchDestroy(&ngmres->additive_linesearch);CHKERRQ(ierr); 18 PetscFunctionReturn(0); 19 } 20 21 #undef __FUNCT__ 22 #define __FUNCT__ "SNESDestroy_NGMRES" 23 PetscErrorCode SNESDestroy_NGMRES(SNES snes) 24 { 25 PetscErrorCode ierr; 26 SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 27 28 PetscFunctionBegin; 29 ierr = SNESReset_NGMRES(snes);CHKERRQ(ierr); 30 ierr = PetscFree5(ngmres->h,ngmres->beta,ngmres->xi,ngmres->fnorms,ngmres->q);CHKERRQ(ierr); 31 ierr = PetscFree(ngmres->s);CHKERRQ(ierr); 32 ierr = PetscFree(ngmres->xnorms);CHKERRQ(ierr); 33 #if PETSC_USE_COMPLEX 34 ierr = PetscFree(ngmres->rwork);CHKERRQ(ierr); 35 #endif 36 ierr = PetscFree(ngmres->work);CHKERRQ(ierr); 37 ierr = PetscFree(snes->data);CHKERRQ(ierr); 38 PetscFunctionReturn(0); 39 } 40 41 #undef __FUNCT__ 42 #define __FUNCT__ "SNESSetUp_NGMRES" 43 PetscErrorCode SNESSetUp_NGMRES(SNES snes) 44 { 45 SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 46 const char *optionsprefix; 47 PetscInt msize,hsize; 48 PetscErrorCode ierr; 49 50 PetscFunctionBegin; 51 if (snes->pc && snes->pcside == PC_LEFT && snes->functype == SNES_FUNCTION_UNPRECONDITIONED) { 52 SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"SNESNGMRES does not support left preconditioning with unpreconditioned function"); 53 } 54 if (snes->pcside == PC_LEFT && snes->functype == SNES_FUNCTION_DEFAULT) snes->functype = SNES_FUNCTION_PRECONDITIONED; 55 ierr = SNESSetWorkVecs(snes,5);CHKERRQ(ierr); 56 if (!ngmres->Xdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Xdot);CHKERRQ(ierr);} 57 if (!ngmres->Fdot) {ierr = VecDuplicateVecs(snes->vec_sol,ngmres->msize,&ngmres->Fdot);CHKERRQ(ierr);} 58 if (!ngmres->setup_called) { 59 msize = ngmres->msize; /* restart size */ 60 hsize = msize * msize; 61 62 /* explicit least squares minimization solve */ 63 ierr = PetscMalloc5(hsize,&ngmres->h, msize,&ngmres->beta, msize,&ngmres->xi, msize,&ngmres->fnorms, hsize,&ngmres->q);CHKERRQ(ierr); 64 ierr = PetscMalloc1(msize,&ngmres->xnorms);CHKERRQ(ierr); 65 ngmres->nrhs = 1; 66 ngmres->lda = msize; 67 ngmres->ldb = msize; 68 ierr = PetscMalloc1(msize,&ngmres->s);CHKERRQ(ierr); 69 ierr = PetscMemzero(ngmres->h, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 70 ierr = PetscMemzero(ngmres->q, hsize*sizeof(PetscScalar));CHKERRQ(ierr); 71 ierr = PetscMemzero(ngmres->xi, msize*sizeof(PetscScalar));CHKERRQ(ierr); 72 ierr = PetscMemzero(ngmres->beta,msize*sizeof(PetscScalar));CHKERRQ(ierr); 73 ngmres->lwork = 12*msize; 74 #if PETSC_USE_COMPLEX 75 ierr = PetscMalloc1(ngmres->lwork,&ngmres->rwork);CHKERRQ(ierr); 76 #endif 77 ierr = PetscMalloc1(ngmres->lwork,&ngmres->work);CHKERRQ(ierr); 78 } 79 80 /* linesearch setup */ 81 ierr = SNESGetOptionsPrefix(snes,&optionsprefix);CHKERRQ(ierr); 82 83 if (ngmres->select_type == SNES_NGMRES_SELECT_LINESEARCH) { 84 ierr = SNESLineSearchCreate(PetscObjectComm((PetscObject)snes),&ngmres->additive_linesearch);CHKERRQ(ierr); 85 ierr = SNESLineSearchSetSNES(ngmres->additive_linesearch,snes);CHKERRQ(ierr); 86 ierr = SNESLineSearchSetType(ngmres->additive_linesearch,SNESLINESEARCHL2);CHKERRQ(ierr); 87 ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,"additive_");CHKERRQ(ierr); 88 ierr = SNESLineSearchAppendOptionsPrefix(ngmres->additive_linesearch,optionsprefix);CHKERRQ(ierr); 89 ierr = SNESLineSearchSetFromOptions(ngmres->additive_linesearch);CHKERRQ(ierr); 90 } 91 92 ngmres->setup_called = PETSC_TRUE; 93 PetscFunctionReturn(0); 94 } 95 96 #undef __FUNCT__ 97 #define __FUNCT__ "SNESSetFromOptions_NGMRES" 98 PetscErrorCode SNESSetFromOptions_NGMRES(PetscOptions *PetscOptionsObject,SNES snes) 99 { 100 SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 101 PetscErrorCode ierr; 102 PetscBool debug = PETSC_FALSE; 103 SNESLineSearch linesearch; 104 105 PetscFunctionBegin; 106 ierr = PetscOptionsHead(PetscOptionsObject,"SNES NGMRES options");CHKERRQ(ierr); 107 ierr = PetscOptionsEnum("-snes_ngmres_select_type","Select type","SNESNGMRESSetSelectType",SNESNGMRESSelectTypes, 108 (PetscEnum)ngmres->select_type,(PetscEnum*)&ngmres->select_type,NULL);CHKERRQ(ierr); 109 ierr = PetscOptionsEnum("-snes_ngmres_restart_type","Restart type","SNESNGMRESSetRestartType",SNESNGMRESRestartTypes, 110 (PetscEnum)ngmres->restart_type,(PetscEnum*)&ngmres->restart_type,NULL);CHKERRQ(ierr); 111 ierr = PetscOptionsBool("-snes_ngmres_candidate", "Use candidate storage", "SNES",ngmres->candidate,&ngmres->candidate,NULL);CHKERRQ(ierr); 112 ierr = PetscOptionsBool("-snes_ngmres_approxfunc","Linearly approximate the function", "SNES",ngmres->approxfunc,&ngmres->approxfunc,NULL);CHKERRQ(ierr); 113 ierr = PetscOptionsInt("-snes_ngmres_m", "Number of directions", "SNES",ngmres->msize,&ngmres->msize,NULL);CHKERRQ(ierr); 114 ierr = PetscOptionsInt("-snes_ngmres_restart", "Iterations before forced restart", "SNES",ngmres->restart_periodic,&ngmres->restart_periodic,NULL);CHKERRQ(ierr); 115 ierr = PetscOptionsInt("-snes_ngmres_restart_it", "Tolerance iterations before restart","SNES",ngmres->restart_it,&ngmres->restart_it,NULL);CHKERRQ(ierr); 116 ierr = PetscOptionsBool("-snes_ngmres_monitor", "Monitor actions of NGMRES", "SNES",ngmres->monitor ? PETSC_TRUE : PETSC_FALSE,&debug,NULL);CHKERRQ(ierr); 117 if (debug) { 118 ngmres->monitor = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 119 } 120 ierr = PetscOptionsReal("-snes_ngmres_gammaA", "Residual selection constant", "SNES",ngmres->gammaA,&ngmres->gammaA,NULL);CHKERRQ(ierr); 121 ierr = PetscOptionsReal("-snes_ngmres_gammaC", "Residual restart constant", "SNES",ngmres->gammaC,&ngmres->gammaC,NULL);CHKERRQ(ierr); 122 ierr = PetscOptionsReal("-snes_ngmres_epsilonB", "Difference selection constant", "SNES",ngmres->epsilonB,&ngmres->epsilonB,NULL);CHKERRQ(ierr); 123 ierr = PetscOptionsReal("-snes_ngmres_deltaB", "Difference residual selection constant", "SNES",ngmres->deltaB,&ngmres->deltaB,NULL);CHKERRQ(ierr); 124 ierr = PetscOptionsBool("-snes_ngmres_single_reduction", "Aggregate reductions", "SNES",ngmres->singlereduction,&ngmres->singlereduction,NULL);CHKERRQ(ierr); 125 ierr = PetscOptionsTail();CHKERRQ(ierr); 126 if ((ngmres->gammaA > ngmres->gammaC) && (ngmres->gammaC > 2.)) ngmres->gammaC = ngmres->gammaA; 127 128 /* set the default type of the line search if the user hasn't already. */ 129 if (!snes->linesearch) { 130 ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 131 ierr = SNESLineSearchSetType(linesearch,SNESLINESEARCHBASIC);CHKERRQ(ierr); 132 } 133 PetscFunctionReturn(0); 134 } 135 136 #undef __FUNCT__ 137 #define __FUNCT__ "SNESView_NGMRES" 138 PetscErrorCode SNESView_NGMRES(SNES snes,PetscViewer viewer) 139 { 140 SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 141 PetscBool iascii; 142 PetscErrorCode ierr; 143 144 PetscFunctionBegin; 145 ierr = PetscObjectTypeCompare((PetscObject) viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 146 if (iascii) { 147 ierr = PetscViewerASCIIPrintf(viewer," Number of stored past updates: %d\n", ngmres->msize);CHKERRQ(ierr); 148 ierr = PetscViewerASCIIPrintf(viewer," Residual selection: gammaA=%1.0e, gammaC=%1.0e\n",ngmres->gammaA,ngmres->gammaC);CHKERRQ(ierr); 149 ierr = PetscViewerASCIIPrintf(viewer," Difference restart: epsilonB=%1.0e, deltaB=%1.0e\n",ngmres->epsilonB,ngmres->deltaB);CHKERRQ(ierr); 150 } 151 PetscFunctionReturn(0); 152 } 153 154 #undef __FUNCT__ 155 #define __FUNCT__ "SNESSolve_NGMRES" 156 PetscErrorCode SNESSolve_NGMRES(SNES snes) 157 { 158 SNES_NGMRES *ngmres = (SNES_NGMRES*) snes->data; 159 /* present solution, residual, and preconditioned residual */ 160 Vec X,F,B,D,Y; 161 162 /* candidate linear combination answers */ 163 Vec XA,FA,XM,FM; 164 165 /* coefficients and RHS to the minimization problem */ 166 PetscReal fnorm,fMnorm,fAnorm; 167 PetscReal xnorm,xMnorm,xAnorm; 168 PetscReal ynorm,yMnorm,yAnorm; 169 PetscInt k,k_restart,l,ivec,restart_count = 0; 170 171 /* solution selection data */ 172 PetscBool selectRestart; 173 PetscReal dnorm,dminnorm = 0.0; 174 PetscReal fminnorm; 175 176 SNESConvergedReason reason; 177 SNESLineSearchReason lssucceed; 178 PetscErrorCode ierr; 179 180 PetscFunctionBegin; 181 182 if (snes->xl || snes->xu || snes->ops->computevariablebounds) { 183 SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name); 184 } 185 186 ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr); 187 /* variable initialization */ 188 snes->reason = SNES_CONVERGED_ITERATING; 189 X = snes->vec_sol; 190 F = snes->vec_func; 191 B = snes->vec_rhs; 192 XA = snes->vec_sol_update; 193 FA = snes->work[0]; 194 D = snes->work[1]; 195 196 /* work for the line search */ 197 Y = snes->work[2]; 198 XM = snes->work[3]; 199 FM = snes->work[4]; 200 201 ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 202 snes->iter = 0; 203 snes->norm = 0.; 204 ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 205 206 /* initialization */ 207 208 if (snes->pc && snes->pcside == PC_LEFT) { 209 ierr = SNESApplyNPC(snes,X,NULL,F);CHKERRQ(ierr); 210 ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 211 if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 212 snes->reason = SNES_DIVERGED_INNER; 213 PetscFunctionReturn(0); 214 } 215 ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); 216 } else { 217 if (!snes->vec_func_init_set) { 218 ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 219 } else snes->vec_func_init_set = PETSC_FALSE; 220 221 ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); 222 SNESCheckFunctionNorm(snes,fnorm); 223 } 224 fminnorm = fnorm; 225 226 ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 227 snes->norm = fnorm; 228 ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 229 ierr = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr); 230 ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr); 231 ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 232 if (snes->reason) PetscFunctionReturn(0); 233 SNESNGMRESUpdateSubspace_Private(snes,0,0,F,fnorm,X); 234 235 k_restart = 1; 236 l = 1; 237 ivec = 0; 238 for (k=1; k < snes->max_its+1; k++) { 239 /* Computation of x^M */ 240 if (snes->pc && snes->pcside == PC_RIGHT) { 241 ierr = VecCopy(X,XM);CHKERRQ(ierr); 242 ierr = SNESSetInitialFunction(snes->pc,F);CHKERRQ(ierr); 243 244 ierr = PetscLogEventBegin(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr); 245 ierr = SNESSolve(snes->pc,B,XM);CHKERRQ(ierr); 246 ierr = PetscLogEventEnd(SNES_NPCSolve,snes->pc,XM,B,0);CHKERRQ(ierr); 247 248 ierr = SNESGetConvergedReason(snes->pc,&reason);CHKERRQ(ierr); 249 if (reason < 0 && reason != SNES_DIVERGED_MAX_IT) { 250 snes->reason = SNES_DIVERGED_INNER; 251 PetscFunctionReturn(0); 252 } 253 ierr = SNESGetNPCFunction(snes,FM,&fMnorm);CHKERRQ(ierr); 254 } else { 255 /* no preconditioner -- just take gradient descent with line search */ 256 ierr = VecCopy(F,Y);CHKERRQ(ierr); 257 ierr = VecCopy(F,FM);CHKERRQ(ierr); 258 ierr = VecCopy(X,XM);CHKERRQ(ierr); 259 260 fMnorm = fnorm; 261 262 ierr = SNESLineSearchApply(snes->linesearch,XM,FM,&fMnorm,Y);CHKERRQ(ierr); 263 ierr = SNESLineSearchGetReason(snes->linesearch,&lssucceed);CHKERRQ(ierr); 264 if (lssucceed) { 265 if (++snes->numFailures >= snes->maxFailures) { 266 snes->reason = SNES_DIVERGED_LINE_SEARCH; 267 PetscFunctionReturn(0); 268 } 269 } 270 } 271 ierr = SNESNGMRESFormCombinedSolution_Private(snes,ivec,l,XM,FM,fMnorm,X,XA,FA);CHKERRQ(ierr); 272 /* r = F(x) */ 273 if (fminnorm > fMnorm) fminnorm = fMnorm; /* the minimum norm is now of F^M */ 274 275 /* differences for selection and restart */ 276 if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE || ngmres->select_type == SNES_NGMRES_SELECT_DIFFERENCE) { 277 ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,&dnorm,&dminnorm,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr); 278 } else { 279 ierr = SNESNGMRESNorms_Private(snes,l,X,F,XM,FM,XA,FA,D,NULL,NULL,&xMnorm,NULL,&yMnorm,&xAnorm,&fAnorm,&yAnorm);CHKERRQ(ierr); 280 } 281 SNESCheckFunctionNorm(snes,fnorm); 282 283 /* combination (additive) or selection (multiplicative) of the N-GMRES solution */ 284 ierr = SNESNGMRESSelect_Private(snes,k_restart,XM,FM,xMnorm,fMnorm,yMnorm,XA,FA,xAnorm,fAnorm,yAnorm,dnorm,fminnorm,dminnorm,X,F,Y,&xnorm,&fnorm,&ynorm);CHKERRQ(ierr); 285 selectRestart = PETSC_FALSE; 286 if (ngmres->restart_type == SNES_NGMRES_RESTART_DIFFERENCE) { 287 ierr = SNESNGMRESSelectRestart_Private(snes,l,fAnorm,dnorm,fminnorm,dminnorm,&selectRestart);CHKERRQ(ierr); 288 /* if the restart conditions persist for more than restart_it iterations, restart. */ 289 if (selectRestart) restart_count++; 290 else restart_count = 0; 291 } else if (ngmres->restart_type == SNES_NGMRES_RESTART_PERIODIC) { 292 if (k_restart > ngmres->restart_periodic) { 293 if (ngmres->monitor) ierr = PetscViewerASCIIPrintf(ngmres->monitor,"periodic restart after %D iterations\n",k_restart);CHKERRQ(ierr); 294 restart_count = ngmres->restart_it; 295 } 296 } 297 ivec = k_restart % ngmres->msize; /* replace the last used part of the subspace */ 298 /* restart after restart conditions have persisted for a fixed number of iterations */ 299 if (restart_count >= ngmres->restart_it) { 300 if (ngmres->monitor) { 301 ierr = PetscViewerASCIIPrintf(ngmres->monitor,"Restarted at iteration %d\n",k_restart);CHKERRQ(ierr); 302 } 303 restart_count = 0; 304 k_restart = 1; 305 l = 1; 306 ivec = 0; 307 /* q_{00} = nu */ 308 ierr = SNESNGMRESUpdateSubspace_Private(snes,0,0,FM,fMnorm,XM);CHKERRQ(ierr); 309 } else { 310 /* select the current size of the subspace */ 311 if (l < ngmres->msize) l++; 312 k_restart++; 313 /* place the current entry in the list of previous entries */ 314 if (ngmres->candidate) { 315 if (fminnorm > fMnorm) fminnorm = fMnorm; 316 ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,FM,fMnorm,XM);CHKERRQ(ierr); 317 } else { 318 if (fminnorm > fnorm) fminnorm = fnorm; 319 ierr = SNESNGMRESUpdateSubspace_Private(snes,ivec,l,F,fnorm,X);CHKERRQ(ierr); 320 } 321 } 322 323 ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 324 snes->iter = k; 325 snes->norm = fnorm; 326 ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 327 ierr = SNESLogConvergenceHistory(snes,snes->norm,snes->iter);CHKERRQ(ierr); 328 ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 329 ierr = (*snes->ops->converged)(snes,snes->iter,0,0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 330 if (snes->reason) PetscFunctionReturn(0); 331 } 332 snes->reason = SNES_DIVERGED_MAX_IT; 333 PetscFunctionReturn(0); 334 } 335 336 #undef __FUNCT__ 337 #define __FUNCT__ "SNESNGMRESSetRestartType" 338 /*@ 339 SNESNGMRESSetRestartType - Sets the restart type for SNESNGMRES. 340 341 Logically Collective on SNES 342 343 Input Parameters: 344 + snes - the iterative context 345 - rtype - restart type 346 347 Options Database: 348 + -snes_ngmres_restart_type<difference,periodic,none> - set the restart type 349 - -snes_ngmres_restart[30] - sets the number of iterations before restart for periodic 350 351 Level: intermediate 352 353 SNESNGMRESRestartTypes: 354 + SNES_NGMRES_RESTART_NONE - never restart 355 . SNES_NGMRES_RESTART_DIFFERENCE - restart based upon difference criteria 356 - SNES_NGMRES_RESTART_PERIODIC - restart after a fixed number of iterations 357 358 Notes: 359 The default line search used is the L2 line search and it requires two additional function evaluations. 360 361 .keywords: SNES, SNESNGMRES, restart, type, set SNESLineSearch 362 @*/ 363 PetscErrorCode SNESNGMRESSetRestartType(SNES snes,SNESNGMRESRestartType rtype) 364 { 365 PetscErrorCode ierr; 366 367 PetscFunctionBegin; 368 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 369 ierr = PetscTryMethod(snes,"SNESNGMRESSetRestartType_C",(SNES,SNESNGMRESRestartType),(snes,rtype));CHKERRQ(ierr); 370 PetscFunctionReturn(0); 371 } 372 373 #undef __FUNCT__ 374 #define __FUNCT__ "SNESNGMRESSetSelectType" 375 /*@ 376 SNESNGMRESSetSelectType - Sets the selection type for SNESNGMRES. This determines how the candidate solution and 377 combined solution are used to create the next iterate. 378 379 Logically Collective on SNES 380 381 Input Parameters: 382 + snes - the iterative context 383 - stype - selection type 384 385 Options Database: 386 . -snes_ngmres_select_type<difference,none,linesearch> 387 388 Level: intermediate 389 390 SNESNGMRESSelectTypes: 391 + SNES_NGMRES_SELECT_NONE - choose the combined solution all the time 392 . SNES_NGMRES_SELECT_DIFFERENCE - choose based upon the selection criteria 393 - SNES_NGMRES_SELECT_LINESEARCH - choose based upon line search combination 394 395 Notes: 396 The default line search used is the L2 line search and it requires two additional function evaluations. 397 398 .keywords: SNES, SNESNGMRES, selection, type, set SNESLineSearch 399 @*/ 400 PetscErrorCode SNESNGMRESSetSelectType(SNES snes,SNESNGMRESSelectType stype) 401 { 402 PetscErrorCode ierr; 403 404 PetscFunctionBegin; 405 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 406 ierr = PetscTryMethod(snes,"SNESNGMRESSetSelectType_C",(SNES,SNESNGMRESSelectType),(snes,stype));CHKERRQ(ierr); 407 PetscFunctionReturn(0); 408 } 409 410 #undef __FUNCT__ 411 #define __FUNCT__ "SNESNGMRESSetSelectType_NGMRES" 412 PetscErrorCode SNESNGMRESSetSelectType_NGMRES(SNES snes,SNESNGMRESSelectType stype) 413 { 414 SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 415 416 PetscFunctionBegin; 417 ngmres->select_type = stype; 418 PetscFunctionReturn(0); 419 } 420 421 #undef __FUNCT__ 422 #define __FUNCT__ "SNESNGMRESSetRestartType_NGMRES" 423 PetscErrorCode SNESNGMRESSetRestartType_NGMRES(SNES snes,SNESNGMRESRestartType rtype) 424 { 425 SNES_NGMRES *ngmres = (SNES_NGMRES*)snes->data; 426 427 PetscFunctionBegin; 428 ngmres->restart_type = rtype; 429 PetscFunctionReturn(0); 430 } 431 432 /*MC 433 SNESNGMRES - The Nonlinear Generalized Minimum Residual method. 434 435 Level: beginner 436 437 Options Database: 438 + -snes_ngmres_select_type<difference,none,linesearch> - choose the select between candidate and combined solution 439 . -snes_ngmres_restart_type<difference,none,periodic> - choose the restart conditions 440 . -snes_ngmres_candidate - Use NGMRES variant which combines candidate solutions instead of actual solutions 441 . -snes_ngmres_m - Number of stored previous solutions and residuals 442 . -snes_ngmres_restart_it - Number of iterations the restart conditions hold before restart 443 . -snes_ngmres_gammaA - Residual tolerance for solution select between the candidate and combination 444 . -snes_ngmres_gammaC - Residual tolerance for restart 445 . -snes_ngmres_epsilonB - Difference tolerance between subsequent solutions triggering restart 446 . -snes_ngmres_deltaB - Difference tolerance between residuals triggering restart 447 . -snes_ngmres_monitor - Prints relevant information about the ngmres iteration 448 . -snes_linesearch_type <basic,l2,cp> - Line search type used for the default smoother 449 - -additive_snes_linesearch_type - linesearch type used to select between the candidate and combined solution with additive select type 450 451 Notes: 452 453 The N-GMRES method combines m previous solutions into a minimum-residual solution by solving a small linearized 454 optimization problem at each iteration. 455 456 References: 457 458 "Krylov Subspace Acceleration of Nonlinear Multigrid with Application to Recirculating Flows", C. W. Oosterlee and T. Washio, 459 SIAM Journal on Scientific Computing, 21(5), 2000. 460 461 .seealso: SNESCreate(), SNES, SNESSetType(), SNESType (for list of available types) 462 M*/ 463 464 #undef __FUNCT__ 465 #define __FUNCT__ "SNESCreate_NGMRES" 466 PETSC_EXTERN PetscErrorCode SNESCreate_NGMRES(SNES snes) 467 { 468 SNES_NGMRES *ngmres; 469 PetscErrorCode ierr; 470 471 PetscFunctionBegin; 472 snes->ops->destroy = SNESDestroy_NGMRES; 473 snes->ops->setup = SNESSetUp_NGMRES; 474 snes->ops->setfromoptions = SNESSetFromOptions_NGMRES; 475 snes->ops->view = SNESView_NGMRES; 476 snes->ops->solve = SNESSolve_NGMRES; 477 snes->ops->reset = SNESReset_NGMRES; 478 479 snes->usespc = PETSC_TRUE; 480 snes->usesksp = PETSC_FALSE; 481 snes->pcside = PC_RIGHT; 482 483 ierr = PetscNewLog(snes,&ngmres);CHKERRQ(ierr); 484 snes->data = (void*) ngmres; 485 ngmres->msize = 30; 486 487 if (!snes->tolerancesset) { 488 snes->max_funcs = 30000; 489 snes->max_its = 10000; 490 } 491 492 ngmres->candidate = PETSC_FALSE; 493 494 ngmres->additive_linesearch = NULL; 495 ngmres->approxfunc = PETSC_FALSE; 496 ngmres->restart_it = 2; 497 ngmres->restart_periodic = 30; 498 ngmres->gammaA = 2.0; 499 ngmres->gammaC = 2.0; 500 ngmres->deltaB = 0.9; 501 ngmres->epsilonB = 0.1; 502 503 ngmres->restart_type = SNES_NGMRES_RESTART_DIFFERENCE; 504 ngmres->select_type = SNES_NGMRES_SELECT_DIFFERENCE; 505 506 ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetSelectType_C",SNESNGMRESSetSelectType_NGMRES);CHKERRQ(ierr); 507 ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESNGMRESSetRestartType_C",SNESNGMRESSetRestartType_NGMRES);CHKERRQ(ierr); 508 PetscFunctionReturn(0); 509 } 510 511