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