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