1 #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 2 3 static SNESMSType SNESMSDefault = SNESMSM62; 4 static PetscBool SNESMSRegisterAllCalled; 5 static PetscBool SNESMSPackageInitialized; 6 7 typedef struct _SNESMSTableau *SNESMSTableau; 8 struct _SNESMSTableau { 9 char *name; 10 PetscInt nstages; /* Number of stages */ 11 PetscInt nregisters; /* Number of registers */ 12 PetscReal stability; /* Scaled stability region */ 13 PetscReal *gamma; /* Coefficients of 3S* method */ 14 PetscReal *delta; /* Coefficients of 3S* method */ 15 PetscReal *betasub; /* Subdiagonal of beta in Shu-Osher form */ 16 }; 17 18 typedef struct _SNESMSTableauLink *SNESMSTableauLink; 19 struct _SNESMSTableauLink { 20 struct _SNESMSTableau tab; 21 SNESMSTableauLink next; 22 }; 23 static SNESMSTableauLink SNESMSTableauList; 24 25 typedef struct { 26 SNESMSTableau tableau; /* Tableau in low-storage form */ 27 PetscReal damping; /* Damping parameter, like length of (pseudo) time step */ 28 PetscBool norms; /* Compute norms, usually only for monitoring purposes */ 29 } SNES_MS; 30 31 #undef __FUNCT__ 32 #define __FUNCT__ "SNESMSRegisterAll" 33 /*@C 34 SNESMSRegisterAll - Registers all of the multi-stage methods in SNESMS 35 36 Not Collective, but should be called by all processes which will need the schemes to be registered 37 38 Level: advanced 39 40 .keywords: SNES, SNESMS, register, all 41 42 .seealso: SNESMSRegisterDestroy() 43 @*/ 44 PetscErrorCode SNESMSRegisterAll(void) 45 { 46 PetscErrorCode ierr; 47 48 PetscFunctionBegin; 49 if (SNESMSRegisterAllCalled) PetscFunctionReturn(0); 50 SNESMSRegisterAllCalled = PETSC_TRUE; 51 52 { 53 PetscReal gamma[3][1] = {{1.0},{0.0},{0.0}}; 54 PetscReal delta[1] = {0.0}; 55 PetscReal betasub[1] = {1.0}; 56 ierr = SNESMSRegister(SNESMSEULER,1,3,1.0,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 57 } 58 59 { 60 PetscReal gamma[3][6] = { 61 {0.0000000000000000E+00, -7.0304722367110606E-01, -1.9836719667506464E-01, -1.6023843981863788E+00, 9.4483822882855284E-02, -1.4204296130641869E-01}, 62 {1.0000000000000000E+00, 1.1111025767083920E+00, 5.6150921583923230E-01, 7.4151723494934041E-01, 3.1714538168600587E-01, 4.6479276238548706E-01}, 63 {0.0000000000000000E+00, 0.0000000000000000E+00, 0.0000000000000000E+00, 6.7968174970583317E-01, -4.1755042846051737E-03, -1.9115668129923846E-01} 64 }; 65 PetscReal delta[6] = {1.0000000000000000E+00, 5.3275427433201750E-01, 6.0143544663985238E-01, 4.5874077053842177E-01, 2.7544386906104651E-01, 0.0000000000000000E+00}; 66 PetscReal betasub[6] = {8.4753115429481929E-01, 7.4018896368655618E-01, 6.5963574086583309E-03, 4.6747795645517759E-01, 1.3314545813643919E-01, 5.3260800028018784E-01}; 67 ierr = SNESMSRegister(SNESMSM62,6,3,1.0,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 68 } 69 { 70 PetscReal gamma[3][4] = {{0,0,0,0},{0,0,0,0},{1,1,1,1}}; 71 PetscReal delta[4] = {0,0,0,0}; 72 PetscReal betasub[4] = {0.25, 0.5, 0.55, 1.0}; 73 ierr = SNESMSRegister(SNESMSJAMESON83,4,3,1.0,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 74 } 75 { /* Van Leer, Tai, and Powell (1989) 2 stage, order 1 */ 76 PetscReal gamma[3][2] = {{0,0},{0,0},{1,1}}; 77 PetscReal delta[2] = {0,0}; 78 PetscReal betasub[2] = {0.3333,1.0}; 79 ierr = SNESMSRegister(SNESMSVLTP21,2,3,1.0,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 80 } 81 { /* Van Leer, Tai, and Powell (1989) 3 stage, order 1 */ 82 PetscReal gamma[3][3] = {{0,0,0},{0,0,0},{1,1,1}}; 83 PetscReal delta[3] = {0,0,0}; 84 PetscReal betasub[3] = {0.1481,0.4000,1.0}; 85 ierr = SNESMSRegister(SNESMSVLTP31,3,3,1.5,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 86 } 87 { /* Van Leer, Tai, and Powell (1989) 4 stage, order 1 */ 88 PetscReal gamma[3][4] = {{0,0,0,0},{0,0,0,0},{1,1,1,1}}; 89 PetscReal delta[4] = {0,0,0,0}; 90 PetscReal betasub[4] = {0.0833,0.2069,0.4265,1.0}; 91 ierr = SNESMSRegister(SNESMSVLTP41,4,3,2.0,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 92 } 93 { /* Van Leer, Tai, and Powell (1989) 5 stage, order 1 */ 94 PetscReal gamma[3][5] = {{0,0,0,0,0},{0,0,0,0,0},{1,1,1,1,1}}; 95 PetscReal delta[5] = {0,0,0,0,0}; 96 PetscReal betasub[5] = {0.0533,0.1263,0.2375,0.4414,1.0}; 97 ierr = SNESMSRegister(SNESMSVLTP51,5,3,2.5,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 98 } 99 { /* Van Leer, Tai, and Powell (1989) 6 stage, order 1 */ 100 PetscReal gamma[3][6] = {{0,0,0,0,0,0},{0,0,0,0,0,0},{1,1,1,1,1,1}}; 101 PetscReal delta[6] = {0,0,0,0,0,0}; 102 PetscReal betasub[6] = {0.0370,0.0851,0.1521,0.2562,0.4512,1.0}; 103 ierr = SNESMSRegister(SNESMSVLTP61,6,3,3.0,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 104 } 105 PetscFunctionReturn(0); 106 } 107 108 #undef __FUNCT__ 109 #define __FUNCT__ "SNESMSRegisterDestroy" 110 /*@C 111 SNESMSRegisterDestroy - Frees the list of schemes that were registered by TSRosWRegister(). 112 113 Not Collective 114 115 Level: advanced 116 117 .keywords: TSRosW, register, destroy 118 .seealso: TSRosWRegister(), TSRosWRegisterAll(), TSRosWRegister() 119 @*/ 120 PetscErrorCode SNESMSRegisterDestroy(void) 121 { 122 PetscErrorCode ierr; 123 SNESMSTableauLink link; 124 125 PetscFunctionBegin; 126 while ((link = SNESMSTableauList)) { 127 SNESMSTableau t = &link->tab; 128 SNESMSTableauList = link->next; 129 130 ierr = PetscFree3(t->gamma,t->delta,t->betasub);CHKERRQ(ierr); 131 ierr = PetscFree(t->name);CHKERRQ(ierr); 132 ierr = PetscFree(link);CHKERRQ(ierr); 133 } 134 SNESMSRegisterAllCalled = PETSC_FALSE; 135 PetscFunctionReturn(0); 136 } 137 138 #undef __FUNCT__ 139 #define __FUNCT__ "SNESMSInitializePackage" 140 /*@C 141 SNESMSInitializePackage - This function initializes everything in the SNESMS package. It is called 142 from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to SNESCreate_MS() 143 when using static libraries. 144 145 Level: developer 146 147 .keywords: SNES, SNESMS, initialize, package 148 .seealso: PetscInitialize() 149 @*/ 150 PetscErrorCode SNESMSInitializePackage(void) 151 { 152 PetscErrorCode ierr; 153 154 PetscFunctionBegin; 155 if (SNESMSPackageInitialized) PetscFunctionReturn(0); 156 SNESMSPackageInitialized = PETSC_TRUE; 157 158 ierr = SNESMSRegisterAll();CHKERRQ(ierr); 159 ierr = PetscRegisterFinalize(SNESMSFinalizePackage);CHKERRQ(ierr); 160 PetscFunctionReturn(0); 161 } 162 163 #undef __FUNCT__ 164 #define __FUNCT__ "SNESMSFinalizePackage" 165 /*@C 166 SNESMSFinalizePackage - This function destroys everything in the SNESMS package. It is 167 called from PetscFinalize(). 168 169 Level: developer 170 171 .keywords: Petsc, destroy, package 172 .seealso: PetscFinalize() 173 @*/ 174 PetscErrorCode SNESMSFinalizePackage(void) 175 { 176 PetscErrorCode ierr; 177 178 PetscFunctionBegin; 179 SNESMSPackageInitialized = PETSC_FALSE; 180 181 ierr = SNESMSRegisterDestroy();CHKERRQ(ierr); 182 PetscFunctionReturn(0); 183 } 184 185 #undef __FUNCT__ 186 #define __FUNCT__ "SNESMSRegister" 187 /*@C 188 SNESMSRegister - register a multistage scheme 189 190 Not Collective, but the same schemes should be registered on all processes on which they will be used 191 192 Input Parameters: 193 + name - identifier for method 194 . nstages - number of stages 195 . nregisters - number of registers used by low-storage implementation 196 . gamma - coefficients, see Ketcheson's paper 197 . delta - coefficients, see Ketcheson's paper 198 - betasub - subdiagonal of Shu-Osher form 199 200 Notes: 201 The notation is described in Ketcheson (2010) Runge-Kutta methods with minimum storage implementations. 202 203 Level: advanced 204 205 .keywords: SNES, register 206 207 .seealso: SNESMS 208 @*/ 209 PetscErrorCode SNESMSRegister(SNESMSType name,PetscInt nstages,PetscInt nregisters,PetscReal stability,const PetscReal gamma[],const PetscReal delta[],const PetscReal betasub[]) 210 { 211 PetscErrorCode ierr; 212 SNESMSTableauLink link; 213 SNESMSTableau t; 214 215 PetscFunctionBegin; 216 PetscValidCharPointer(name,1); 217 if (nstages < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have at least one stage"); 218 if (nregisters != 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only support for methods written in 3-register form"); 219 PetscValidPointer(gamma,4); 220 PetscValidPointer(delta,5); 221 PetscValidPointer(betasub,6); 222 223 ierr = PetscNew(&link);CHKERRQ(ierr); 224 t = &link->tab; 225 ierr = PetscStrallocpy(name,&t->name);CHKERRQ(ierr); 226 t->nstages = nstages; 227 t->nregisters = nregisters; 228 t->stability = stability; 229 230 ierr = PetscMalloc3(nstages*nregisters,&t->gamma,nstages,&t->delta,nstages,&t->betasub);CHKERRQ(ierr); 231 ierr = PetscMemcpy(t->gamma,gamma,nstages*nregisters*sizeof(PetscReal));CHKERRQ(ierr); 232 ierr = PetscMemcpy(t->delta,delta,nstages*sizeof(PetscReal));CHKERRQ(ierr); 233 ierr = PetscMemcpy(t->betasub,betasub,nstages*sizeof(PetscReal));CHKERRQ(ierr); 234 235 link->next = SNESMSTableauList; 236 SNESMSTableauList = link; 237 PetscFunctionReturn(0); 238 } 239 240 #undef __FUNCT__ 241 #define __FUNCT__ "SNESMSStep_3Sstar" 242 /* 243 X - initial state, updated in-place. 244 F - residual, computed at the initial X on input 245 */ 246 static PetscErrorCode SNESMSStep_3Sstar(SNES snes,Vec X,Vec F) 247 { 248 PetscErrorCode ierr; 249 SNES_MS *ms = (SNES_MS*)snes->data; 250 SNESMSTableau t = ms->tableau; 251 const PetscReal *gamma = t->gamma,*delta = t->delta,*betasub = t->betasub; 252 Vec S1,S2,S3,Y; 253 PetscInt i,nstages = t->nstages;; 254 255 256 PetscFunctionBegin; 257 Y = snes->work[0]; 258 S1 = X; 259 S2 = snes->work[1]; 260 S3 = snes->work[2]; 261 ierr = VecZeroEntries(S2);CHKERRQ(ierr); 262 ierr = VecCopy(X,S3);CHKERRQ(ierr); 263 for (i=0; i<nstages; i++) { 264 Vec Ss[4]; 265 PetscScalar scoeff[4]; 266 267 Ss[0] = S1; Ss[1] = S2; Ss[2] = S3; Ss[3] = Y; 268 269 scoeff[0] = gamma[0*nstages+i]-(PetscReal)1.0; 270 scoeff[1] = gamma[1*nstages+i]; 271 scoeff[2] = gamma[2*nstages+i]; 272 scoeff[3] = -betasub[i]*ms->damping; 273 274 ierr = VecAXPY(S2,delta[i],S1);CHKERRQ(ierr); 275 if (i>0) { 276 ierr = SNESComputeFunction(snes,S1,F);CHKERRQ(ierr); 277 } 278 ierr = KSPSolve(snes->ksp,F,Y);CHKERRQ(ierr); 279 ierr = VecMAXPY(S1,4,scoeff,Ss);CHKERRQ(ierr); 280 } 281 PetscFunctionReturn(0); 282 } 283 284 #undef __FUNCT__ 285 #define __FUNCT__ "SNESSolve_MS" 286 static PetscErrorCode SNESSolve_MS(SNES snes) 287 { 288 SNES_MS *ms = (SNES_MS*)snes->data; 289 Vec X = snes->vec_sol,F = snes->vec_func; 290 PetscReal fnorm; 291 PetscInt i; 292 PetscErrorCode ierr; 293 294 PetscFunctionBegin; 295 296 if (snes->xl || snes->xu || snes->ops->computevariablebounds) { 297 SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE, "SNES solver %s does not support bounds", ((PetscObject)snes)->type_name); 298 } 299 300 ierr = PetscCitationsRegister(SNESCitation,&SNEScite);CHKERRQ(ierr); 301 snes->reason = SNES_CONVERGED_ITERATING; 302 ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 303 snes->iter = 0; 304 snes->norm = 0.; 305 ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 306 if (!snes->vec_func_init_set) { 307 ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 308 } else snes->vec_func_init_set = PETSC_FALSE; 309 310 if (snes->jacobian) { /* This method does not require a Jacobian, but it is usually preconditioned by PBJacobi */ 311 ierr = SNESComputeJacobian(snes,snes->vec_sol,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr); 312 } 313 if (ms->norms) { 314 ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 315 SNESCheckFunctionNorm(snes,fnorm); 316 /* Monitor convergence */ 317 ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 318 snes->iter = 0; 319 snes->norm = fnorm; 320 ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 321 ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); 322 ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 323 324 /* Test for convergence */ 325 ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 326 if (snes->reason) PetscFunctionReturn(0); 327 } 328 329 /* Call general purpose update function */ 330 if (snes->ops->update) { 331 ierr = (*snes->ops->update)(snes,snes->iter);CHKERRQ(ierr); 332 } 333 for (i = 0; i < snes->max_its; i++) { 334 ierr = SNESMSStep_3Sstar(snes,X,F);CHKERRQ(ierr); 335 336 if (i+1 < snes->max_its || ms->norms) { 337 ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 338 } 339 340 if (ms->norms) { 341 ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 342 SNESCheckFunctionNorm(snes,fnorm); 343 344 /* Monitor convergence */ 345 ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 346 snes->iter = i+1; 347 snes->norm = fnorm; 348 ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 349 ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); 350 ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 351 352 /* Test for convergence */ 353 ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 354 if (snes->reason) PetscFunctionReturn(0); 355 } 356 357 /* Call general purpose update function */ 358 if (snes->ops->update) { 359 ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 360 } 361 } 362 if (!snes->reason) snes->reason = SNES_CONVERGED_ITS; 363 PetscFunctionReturn(0); 364 } 365 366 #undef __FUNCT__ 367 #define __FUNCT__ "SNESSetUp_MS" 368 static PetscErrorCode SNESSetUp_MS(SNES snes) 369 { 370 SNES_MS *ms = (SNES_MS*)snes->data; 371 PetscErrorCode ierr; 372 373 PetscFunctionBegin; 374 if (!ms->tableau) {ierr = SNESMSSetType(snes,SNESMSDefault);CHKERRQ(ierr);} 375 ierr = SNESSetWorkVecs(snes,3);CHKERRQ(ierr); 376 ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); 377 PetscFunctionReturn(0); 378 } 379 380 #undef __FUNCT__ 381 #define __FUNCT__ "SNESReset_MS" 382 static PetscErrorCode SNESReset_MS(SNES snes) 383 { 384 385 PetscFunctionBegin; 386 PetscFunctionReturn(0); 387 } 388 389 #undef __FUNCT__ 390 #define __FUNCT__ "SNESDestroy_MS" 391 static PetscErrorCode SNESDestroy_MS(SNES snes) 392 { 393 PetscErrorCode ierr; 394 395 PetscFunctionBegin; 396 ierr = PetscFree(snes->data);CHKERRQ(ierr); 397 ierr = PetscObjectComposeFunction((PetscObject)snes,"",NULL);CHKERRQ(ierr); 398 PetscFunctionReturn(0); 399 } 400 401 #undef __FUNCT__ 402 #define __FUNCT__ "SNESView_MS" 403 static PetscErrorCode SNESView_MS(SNES snes,PetscViewer viewer) 404 { 405 PetscBool iascii; 406 PetscErrorCode ierr; 407 SNES_MS *ms = (SNES_MS*)snes->data; 408 409 PetscFunctionBegin; 410 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 411 if (iascii) { 412 SNESMSTableau tab = ms->tableau; 413 ierr = PetscViewerASCIIPrintf(viewer," multi-stage method type: %s\n",tab ? tab->name : "not yet set");CHKERRQ(ierr); 414 } 415 PetscFunctionReturn(0); 416 } 417 418 #undef __FUNCT__ 419 #define __FUNCT__ "SNESSetFromOptions_MS" 420 static PetscErrorCode SNESSetFromOptions_MS(PetscOptions *PetscOptionsObject,SNES snes) 421 { 422 SNES_MS *ms = (SNES_MS*)snes->data; 423 PetscErrorCode ierr; 424 425 PetscFunctionBegin; 426 ierr = PetscOptionsHead(PetscOptionsObject,"SNES MS options");CHKERRQ(ierr); 427 { 428 SNESMSTableauLink link; 429 PetscInt count,choice; 430 PetscBool flg; 431 const char **namelist; 432 char mstype[256]; 433 434 ierr = PetscStrncpy(mstype,SNESMSDefault,sizeof(mstype));CHKERRQ(ierr); 435 for (link=SNESMSTableauList,count=0; link; link=link->next,count++) ; 436 ierr = PetscMalloc1(count,&namelist);CHKERRQ(ierr); 437 for (link=SNESMSTableauList,count=0; link; link=link->next,count++) namelist[count] = link->tab.name; 438 ierr = PetscOptionsEList("-snes_ms_type","Multistage smoother type","SNESMSSetType",(const char*const*)namelist,count,mstype,&choice,&flg);CHKERRQ(ierr); 439 ierr = SNESMSSetType(snes,flg ? namelist[choice] : mstype);CHKERRQ(ierr); 440 ierr = PetscFree(namelist);CHKERRQ(ierr); 441 ierr = PetscOptionsReal("-snes_ms_damping","Damping for multistage method","SNESMSSetDamping",ms->damping,&ms->damping,NULL);CHKERRQ(ierr); 442 ierr = PetscOptionsBool("-snes_ms_norms","Compute norms for monitoring","none",ms->norms,&ms->norms,NULL);CHKERRQ(ierr); 443 } 444 ierr = PetscOptionsTail();CHKERRQ(ierr); 445 PetscFunctionReturn(0); 446 } 447 448 #undef __FUNCT__ 449 #define __FUNCT__ "SNESMSSetType_MS" 450 PetscErrorCode SNESMSSetType_MS(SNES snes,SNESMSType mstype) 451 { 452 PetscErrorCode ierr; 453 SNES_MS *ms = (SNES_MS*)snes->data; 454 SNESMSTableauLink link; 455 PetscBool match; 456 457 PetscFunctionBegin; 458 if (ms->tableau) { 459 ierr = PetscStrcmp(ms->tableau->name,mstype,&match);CHKERRQ(ierr); 460 if (match) PetscFunctionReturn(0); 461 } 462 for (link = SNESMSTableauList; link; link=link->next) { 463 ierr = PetscStrcmp(link->tab.name,mstype,&match);CHKERRQ(ierr); 464 if (match) { 465 ierr = SNESReset_MS(snes);CHKERRQ(ierr); 466 ms->tableau = &link->tab; 467 PetscFunctionReturn(0); 468 } 469 } 470 SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",mstype); 471 PetscFunctionReturn(0); 472 } 473 474 #undef __FUNCT__ 475 #define __FUNCT__ "SNESMSSetType" 476 /*@C 477 SNESMSSetType - Set the type of multistage smoother 478 479 Logically collective 480 481 Input Parameter: 482 + snes - nonlinear solver context 483 - mstype - type of multistage method 484 485 Level: beginner 486 487 .seealso: SNESMSGetType(), SNESMS 488 @*/ 489 PetscErrorCode SNESMSSetType(SNES snes,SNESMSType rostype) 490 { 491 PetscErrorCode ierr; 492 493 PetscFunctionBegin; 494 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 495 ierr = PetscTryMethod(snes,"SNESMSSetType_C",(SNES,SNESMSType),(snes,rostype));CHKERRQ(ierr); 496 PetscFunctionReturn(0); 497 } 498 499 /* -------------------------------------------------------------------------- */ 500 /*MC 501 SNESMS - multi-stage smoothers 502 503 Options Database: 504 505 + -snes_ms_type - type of multi-stage smoother 506 - -snes_ms_damping - damping for multi-stage method 507 508 Notes: 509 These multistage methods are explicit Runge-Kutta methods that are often used as smoothers for 510 FAS multigrid for transport problems. In the linear case, these are equivalent to polynomial smoothers (such as Chebyshev). 511 512 Multi-stage smoothers should usually be preconditioned by point-block Jacobi to ensure proper scaling and to normalize the wave speeds. 513 514 The methods are specified in low storage form (Ketcheson 2010). New methods can be registered with SNESMSRegister(). 515 516 References: 517 518 Ketcheson (2010) Runge-Kutta methods with minimum storage implementations. 519 520 Jameson (1983) Solution of the Euler equations for two dimensional transonic flow by a multigrid method. 521 522 Pierce and Giles (1997) Preconditioned multigrid methods for compressible flow calculations on stretched meshes. 523 524 Level: beginner 525 526 .seealso: SNESCreate(), SNES, SNESSetType(), SNESMS, SNESFAS, KSPCHEBYSHEV 527 528 M*/ 529 #undef __FUNCT__ 530 #define __FUNCT__ "SNESCreate_MS" 531 PETSC_EXTERN PetscErrorCode SNESCreate_MS(SNES snes) 532 { 533 PetscErrorCode ierr; 534 SNES_MS *ms; 535 536 PetscFunctionBegin; 537 ierr = SNESMSInitializePackage();CHKERRQ(ierr); 538 539 snes->ops->setup = SNESSetUp_MS; 540 snes->ops->solve = SNESSolve_MS; 541 snes->ops->destroy = SNESDestroy_MS; 542 snes->ops->setfromoptions = SNESSetFromOptions_MS; 543 snes->ops->view = SNESView_MS; 544 snes->ops->reset = SNESReset_MS; 545 546 snes->usespc = PETSC_FALSE; 547 snes->usesksp = PETSC_TRUE; 548 549 ierr = PetscNewLog(snes,&ms);CHKERRQ(ierr); 550 snes->data = (void*)ms; 551 ms->damping = 0.9; 552 ms->norms = PETSC_FALSE; 553 554 ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESMSSetType_C",SNESMSSetType_MS);CHKERRQ(ierr); 555 PetscFunctionReturn(0); 556 } 557 558