1b45d2f2cSJed Brown #include <petsc-private/snesimpl.h> /*I "petscsnes.h" I*/ 237e1895aSJed Brown 319fd82e9SBarry Smith static SNESMSType SNESMSDefault = SNESMSM62; 437e1895aSJed Brown static PetscBool SNESMSRegisterAllCalled; 537e1895aSJed Brown static PetscBool SNESMSPackageInitialized; 637e1895aSJed Brown 737e1895aSJed Brown typedef struct _SNESMSTableau *SNESMSTableau; 837e1895aSJed Brown struct _SNESMSTableau { 937e1895aSJed Brown char *name; 1037e1895aSJed Brown PetscInt nstages; /* Number of stages */ 1137e1895aSJed Brown PetscInt nregisters; /* Number of registers */ 1237e1895aSJed Brown PetscReal stability; /* Scaled stability region */ 1337e1895aSJed Brown PetscReal *gamma; /* Coefficients of 3S* method */ 1437e1895aSJed Brown PetscReal *delta; /* Coefficients of 3S* method */ 1537e1895aSJed Brown PetscReal *betasub; /* Subdiagonal of beta in Shu-Osher form */ 1637e1895aSJed Brown }; 1737e1895aSJed Brown 1837e1895aSJed Brown typedef struct _SNESMSTableauLink *SNESMSTableauLink; 1937e1895aSJed Brown struct _SNESMSTableauLink { 2037e1895aSJed Brown struct _SNESMSTableau tab; 2137e1895aSJed Brown SNESMSTableauLink next; 2237e1895aSJed Brown }; 2337e1895aSJed Brown static SNESMSTableauLink SNESMSTableauList; 2437e1895aSJed Brown 2537e1895aSJed Brown typedef struct { 2637e1895aSJed Brown SNESMSTableau tableau; /* Tableau in low-storage form */ 2737e1895aSJed Brown PetscReal damping; /* Damping parameter, like length of (pseudo) time step */ 2837e1895aSJed Brown PetscBool norms; /* Compute norms, usually only for monitoring purposes */ 2937e1895aSJed Brown } SNES_MS; 3037e1895aSJed Brown 3137e1895aSJed Brown #undef __FUNCT__ 3237e1895aSJed Brown #define __FUNCT__ "SNESMSRegisterAll" 3337e1895aSJed Brown /*@C 3437e1895aSJed Brown SNESMSRegisterAll - Registers all of the multi-stage methods in SNESMS 3537e1895aSJed Brown 3637e1895aSJed Brown Not Collective, but should be called by all processes which will need the schemes to be registered 3737e1895aSJed Brown 3837e1895aSJed Brown Level: advanced 3937e1895aSJed Brown 4037e1895aSJed Brown .keywords: SNES, SNESMS, register, all 4137e1895aSJed Brown 4237e1895aSJed Brown .seealso: SNESMSRegisterDestroy() 4337e1895aSJed Brown @*/ 4437e1895aSJed Brown PetscErrorCode SNESMSRegisterAll(void) 4537e1895aSJed Brown { 4637e1895aSJed Brown PetscErrorCode ierr; 4737e1895aSJed Brown 4837e1895aSJed Brown PetscFunctionBegin; 4937e1895aSJed Brown if (SNESMSRegisterAllCalled) PetscFunctionReturn(0); 5037e1895aSJed Brown SNESMSRegisterAllCalled = PETSC_TRUE; 5137e1895aSJed Brown 5237e1895aSJed Brown { 5337e1895aSJed Brown PetscReal gamma[3][1] = {{1.0},{0.0},{0.0}}; 5437e1895aSJed Brown PetscReal delta[1] = {0.0}; 5537e1895aSJed Brown PetscReal betasub[1] = {1.0}; 5637e1895aSJed Brown ierr = SNESMSRegister(SNESMSEULER,1,3,1.0,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 5737e1895aSJed Brown } 5837e1895aSJed Brown 5937e1895aSJed Brown { 6037e1895aSJed Brown PetscReal gamma[3][6] = { 6137e1895aSJed Brown {0.0000000000000000E+00, -7.0304722367110606E-01, -1.9836719667506464E-01, -1.6023843981863788E+00, 9.4483822882855284E-02, -1.4204296130641869E-01}, 6237e1895aSJed Brown {1.0000000000000000E+00, 1.1111025767083920E+00, 5.6150921583923230E-01, 7.4151723494934041E-01, 3.1714538168600587E-01, 4.6479276238548706E-01}, 6337e1895aSJed Brown {0.0000000000000000E+00, 0.0000000000000000E+00, 0.0000000000000000E+00, 6.7968174970583317E-01, -4.1755042846051737E-03, -1.9115668129923846E-01} 6437e1895aSJed Brown }; 6537e1895aSJed Brown PetscReal delta[6] = {1.0000000000000000E+00, 5.3275427433201750E-01, 6.0143544663985238E-01, 4.5874077053842177E-01, 2.7544386906104651E-01, 0.0000000000000000E+00}; 6637e1895aSJed Brown PetscReal betasub[6] = {8.4753115429481929E-01, 7.4018896368655618E-01, 6.5963574086583309E-03, 4.6747795645517759E-01, 1.3314545813643919E-01, 5.3260800028018784E-01}; 6737e1895aSJed Brown ierr = SNESMSRegister(SNESMSM62,6,3,1.0,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 6837e1895aSJed Brown } 69a97cb6bcSJed Brown { 70a97cb6bcSJed Brown PetscReal gamma[3][4] = {{0,0,0,0},{0,0,0,0},{1,1,1,1}}; 71a97cb6bcSJed Brown PetscReal delta[4] = {0,0,0,0}; 72a97cb6bcSJed Brown PetscReal betasub[4] = {0.25, 0.5, 0.55, 1.0}; 73a97cb6bcSJed Brown ierr = SNESMSRegister(SNESMSJAMESON83,4,3,1.0,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 74a97cb6bcSJed Brown } 75a97cb6bcSJed Brown { /* Van Leer, Tai, and Powell (1989) 2 stage, order 1 */ 76a97cb6bcSJed Brown PetscReal gamma[3][2] = {{0,0},{0,0},{1,1}}; 77a97cb6bcSJed Brown PetscReal delta[2] = {0,0}; 78a97cb6bcSJed Brown PetscReal betasub[2] = {0.3333,1.0}; 79a97cb6bcSJed Brown ierr = SNESMSRegister(SNESMSVLTP21,2,3,1.0,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 80a97cb6bcSJed Brown } 81a97cb6bcSJed Brown { /* Van Leer, Tai, and Powell (1989) 3 stage, order 1 */ 82a97cb6bcSJed Brown PetscReal gamma[3][3] = {{0,0,0},{0,0,0},{1,1,1}}; 83a97cb6bcSJed Brown PetscReal delta[3] = {0,0,0}; 84a97cb6bcSJed Brown PetscReal betasub[3] = {0.1481,0.4000,1.0}; 85a97cb6bcSJed Brown ierr = SNESMSRegister(SNESMSVLTP31,3,3,1.5,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 86a97cb6bcSJed Brown } 87a97cb6bcSJed Brown { /* Van Leer, Tai, and Powell (1989) 4 stage, order 1 */ 88a97cb6bcSJed Brown PetscReal gamma[3][4] = {{0,0,0,0},{0,0,0,0},{1,1,1,1}}; 89a97cb6bcSJed Brown PetscReal delta[4] = {0,0,0,0}; 90a97cb6bcSJed Brown PetscReal betasub[4] = {0.0833,0.2069,0.4265,1.0}; 91a97cb6bcSJed Brown ierr = SNESMSRegister(SNESMSVLTP41,4,3,2.0,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 92a97cb6bcSJed Brown } 93a97cb6bcSJed Brown { /* Van Leer, Tai, and Powell (1989) 5 stage, order 1 */ 94a97cb6bcSJed Brown PetscReal gamma[3][5] = {{0,0,0,0,0},{0,0,0,0,0},{1,1,1,1,1}}; 95a97cb6bcSJed Brown PetscReal delta[5] = {0,0,0,0,0}; 96a97cb6bcSJed Brown PetscReal betasub[5] = {0.0533,0.1263,0.2375,0.4414,1.0}; 97a97cb6bcSJed Brown ierr = SNESMSRegister(SNESMSVLTP51,5,3,2.5,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 98a97cb6bcSJed Brown } 99a97cb6bcSJed Brown { /* Van Leer, Tai, and Powell (1989) 6 stage, order 1 */ 100a97cb6bcSJed Brown PetscReal gamma[3][6] = {{0,0,0,0,0,0},{0,0,0,0,0,0},{1,1,1,1,1,1}}; 101a97cb6bcSJed Brown PetscReal delta[6] = {0,0,0,0,0,0}; 102a97cb6bcSJed Brown PetscReal betasub[6] = {0.0370,0.0851,0.1521,0.2562,0.4512,1.0}; 103a97cb6bcSJed Brown ierr = SNESMSRegister(SNESMSVLTP61,6,3,3.0,&gamma[0][0],delta,betasub);CHKERRQ(ierr); 104a97cb6bcSJed Brown } 10537e1895aSJed Brown PetscFunctionReturn(0); 10637e1895aSJed Brown } 10737e1895aSJed Brown 10837e1895aSJed Brown #undef __FUNCT__ 10937e1895aSJed Brown #define __FUNCT__ "SNESMSRegisterDestroy" 11037e1895aSJed Brown /*@C 11137e1895aSJed Brown SNESMSRegisterDestroy - Frees the list of schemes that were registered by TSRosWRegister(). 11237e1895aSJed Brown 11337e1895aSJed Brown Not Collective 11437e1895aSJed Brown 11537e1895aSJed Brown Level: advanced 11637e1895aSJed Brown 11737e1895aSJed Brown .keywords: TSRosW, register, destroy 11837e1895aSJed Brown .seealso: TSRosWRegister(), TSRosWRegisterAll(), TSRosWRegisterDynamic() 11937e1895aSJed Brown @*/ 12037e1895aSJed Brown PetscErrorCode SNESMSRegisterDestroy(void) 12137e1895aSJed Brown { 12237e1895aSJed Brown PetscErrorCode ierr; 12337e1895aSJed Brown SNESMSTableauLink link; 12437e1895aSJed Brown 12537e1895aSJed Brown PetscFunctionBegin; 12637e1895aSJed Brown while ((link = SNESMSTableauList)) { 12737e1895aSJed Brown SNESMSTableau t = &link->tab; 12837e1895aSJed Brown SNESMSTableauList = link->next; 1291aa26658SKarl Rupp 13037e1895aSJed Brown ierr = PetscFree3(t->gamma,t->delta,t->betasub);CHKERRQ(ierr); 13137e1895aSJed Brown ierr = PetscFree(t->name);CHKERRQ(ierr); 13237e1895aSJed Brown ierr = PetscFree(link);CHKERRQ(ierr); 13337e1895aSJed Brown } 13437e1895aSJed Brown SNESMSRegisterAllCalled = PETSC_FALSE; 13537e1895aSJed Brown PetscFunctionReturn(0); 13637e1895aSJed Brown } 13737e1895aSJed Brown 13837e1895aSJed Brown #undef __FUNCT__ 13937e1895aSJed Brown #define __FUNCT__ "SNESMSInitializePackage" 14037e1895aSJed Brown /*@C 14137e1895aSJed Brown SNESMSInitializePackage - This function initializes everything in the SNESMS package. It is called 14237e1895aSJed Brown from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to SNESCreate_MS() 14337e1895aSJed Brown when using static libraries. 14437e1895aSJed Brown 14537e1895aSJed Brown Input Parameter: 1460298fd71SBarry Smith path - The dynamic library path, or NULL 14737e1895aSJed Brown 14837e1895aSJed Brown Level: developer 14937e1895aSJed Brown 15037e1895aSJed Brown .keywords: SNES, SNESMS, initialize, package 15137e1895aSJed Brown .seealso: PetscInitialize() 15237e1895aSJed Brown @*/ 15337e1895aSJed Brown PetscErrorCode SNESMSInitializePackage(const char path[]) 15437e1895aSJed Brown { 15537e1895aSJed Brown PetscErrorCode ierr; 15637e1895aSJed Brown 15737e1895aSJed Brown PetscFunctionBegin; 15837e1895aSJed Brown if (SNESMSPackageInitialized) PetscFunctionReturn(0); 15937e1895aSJed Brown SNESMSPackageInitialized = PETSC_TRUE; 1601aa26658SKarl Rupp 16137e1895aSJed Brown ierr = SNESMSRegisterAll();CHKERRQ(ierr); 16237e1895aSJed Brown ierr = PetscRegisterFinalize(SNESMSFinalizePackage);CHKERRQ(ierr); 16337e1895aSJed Brown PetscFunctionReturn(0); 16437e1895aSJed Brown } 16537e1895aSJed Brown 16637e1895aSJed Brown #undef __FUNCT__ 16737e1895aSJed Brown #define __FUNCT__ "SNESMSFinalizePackage" 16837e1895aSJed Brown /*@C 16937e1895aSJed Brown SNESMSFinalizePackage - This function destroys everything in the SNESMS package. It is 17037e1895aSJed Brown called from PetscFinalize(). 17137e1895aSJed Brown 17237e1895aSJed Brown Level: developer 17337e1895aSJed Brown 17437e1895aSJed Brown .keywords: Petsc, destroy, package 17537e1895aSJed Brown .seealso: PetscFinalize() 17637e1895aSJed Brown @*/ 17737e1895aSJed Brown PetscErrorCode SNESMSFinalizePackage(void) 17837e1895aSJed Brown { 17937e1895aSJed Brown PetscErrorCode ierr; 18037e1895aSJed Brown 18137e1895aSJed Brown PetscFunctionBegin; 18237e1895aSJed Brown SNESMSPackageInitialized = PETSC_FALSE; 1831aa26658SKarl Rupp 18437e1895aSJed Brown ierr = SNESMSRegisterDestroy();CHKERRQ(ierr); 18537e1895aSJed Brown PetscFunctionReturn(0); 18637e1895aSJed Brown } 18737e1895aSJed Brown 18837e1895aSJed Brown #undef __FUNCT__ 18937e1895aSJed Brown #define __FUNCT__ "SNESMSRegister" 19037e1895aSJed Brown /*@C 19137e1895aSJed Brown SNESMSRegister - register a multistage scheme 19237e1895aSJed Brown 19337e1895aSJed Brown Not Collective, but the same schemes should be registered on all processes on which they will be used 19437e1895aSJed Brown 19537e1895aSJed Brown Input Parameters: 19637e1895aSJed Brown + name - identifier for method 19737e1895aSJed Brown . nstages - number of stages 19837e1895aSJed Brown . nregisters - number of registers used by low-storage implementation 19937e1895aSJed Brown . gamma - coefficients, see Ketcheson's paper 20037e1895aSJed Brown . delta - coefficients, see Ketcheson's paper 20137e1895aSJed Brown - betasub - subdiagonal of Shu-Osher form 20237e1895aSJed Brown 20337e1895aSJed Brown Notes: 20437e1895aSJed Brown The notation is described in Ketcheson (2010) Runge-Kutta methods with minimum storage implementations. 20537e1895aSJed Brown 20637e1895aSJed Brown Level: advanced 20737e1895aSJed Brown 20837e1895aSJed Brown .keywords: SNES, register 20937e1895aSJed Brown 21037e1895aSJed Brown .seealso: SNESMS 21137e1895aSJed Brown @*/ 21219fd82e9SBarry Smith PetscErrorCode SNESMSRegister(SNESMSType name,PetscInt nstages,PetscInt nregisters,PetscReal stability,const PetscReal gamma[],const PetscReal delta[],const PetscReal betasub[]) 21337e1895aSJed Brown { 21437e1895aSJed Brown PetscErrorCode ierr; 21537e1895aSJed Brown SNESMSTableauLink link; 21637e1895aSJed Brown SNESMSTableau t; 21737e1895aSJed Brown 21837e1895aSJed Brown PetscFunctionBegin; 21937e1895aSJed Brown PetscValidCharPointer(name,1); 22037e1895aSJed Brown if (nstages < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have at least one stage"); 22137e1895aSJed Brown if (nregisters != 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only support for methods written in 3-register form"); 22237e1895aSJed Brown PetscValidPointer(gamma,4); 22337e1895aSJed Brown PetscValidPointer(delta,5); 22437e1895aSJed Brown PetscValidPointer(betasub,6); 22537e1895aSJed Brown 22637e1895aSJed Brown ierr = PetscMalloc(sizeof(*link),&link);CHKERRQ(ierr); 22737e1895aSJed Brown ierr = PetscMemzero(link,sizeof(*link));CHKERRQ(ierr); 22837e1895aSJed Brown t = &link->tab; 22937e1895aSJed Brown ierr = PetscStrallocpy(name,&t->name);CHKERRQ(ierr); 23037e1895aSJed Brown t->nstages = nstages; 23137e1895aSJed Brown t->nregisters = nregisters; 23237e1895aSJed Brown t->stability = stability; 2331aa26658SKarl Rupp 23437e1895aSJed Brown ierr = PetscMalloc3(nstages*nregisters,PetscReal,&t->gamma,nstages,PetscReal,&t->delta,nstages,PetscReal,&t->betasub);CHKERRQ(ierr); 23537e1895aSJed Brown ierr = PetscMemcpy(t->gamma,gamma,nstages*nregisters*sizeof(PetscReal));CHKERRQ(ierr); 23637e1895aSJed Brown ierr = PetscMemcpy(t->delta,delta,nstages*sizeof(PetscReal));CHKERRQ(ierr); 23737e1895aSJed Brown ierr = PetscMemcpy(t->betasub,betasub,nstages*sizeof(PetscReal));CHKERRQ(ierr); 23837e1895aSJed Brown 23937e1895aSJed Brown link->next = SNESMSTableauList; 24037e1895aSJed Brown SNESMSTableauList = link; 24137e1895aSJed Brown PetscFunctionReturn(0); 24237e1895aSJed Brown } 24337e1895aSJed Brown 24437e1895aSJed Brown #undef __FUNCT__ 24537e1895aSJed Brown #define __FUNCT__ "SNESMSStep_3Sstar" 24637e1895aSJed Brown /* 24737e1895aSJed Brown X - initial state, updated in-place. 24837e1895aSJed Brown F - residual, computed at the initial X on input 24937e1895aSJed Brown */ 25037e1895aSJed Brown static PetscErrorCode SNESMSStep_3Sstar(SNES snes,Vec X,Vec F) 25137e1895aSJed Brown { 25237e1895aSJed Brown PetscErrorCode ierr; 25337e1895aSJed Brown SNES_MS *ms = (SNES_MS*)snes->data; 25437e1895aSJed Brown SNESMSTableau t = ms->tableau; 25537e1895aSJed Brown const PetscReal *gamma = t->gamma,*delta = t->delta,*betasub = t->betasub; 25637e1895aSJed Brown Vec S1,S2,S3,Y; 25737e1895aSJed Brown PetscInt i,nstages = t->nstages;; 25837e1895aSJed Brown 25937e1895aSJed Brown 26037e1895aSJed Brown PetscFunctionBegin; 26137e1895aSJed Brown Y = snes->work[0]; 26237e1895aSJed Brown S1 = X; 26337e1895aSJed Brown S2 = snes->work[1]; 26437e1895aSJed Brown S3 = snes->work[2]; 26537e1895aSJed Brown ierr = VecZeroEntries(S2);CHKERRQ(ierr); 26637e1895aSJed Brown ierr = VecCopy(X,S3);CHKERRQ(ierr); 26737e1895aSJed Brown for (i=0; i<nstages; i++) { 268da80777bSKarl Rupp Vec Ss[4]; 269da80777bSKarl Rupp PetscScalar scoeff[4]; 270da80777bSKarl Rupp 271da80777bSKarl Rupp Ss[0] = S1; Ss[1] = S2; Ss[2] = S3; Ss[3] = Y; 2721aa26658SKarl Rupp 273da80777bSKarl Rupp scoeff[0] = gamma[0*nstages+i]-(PetscReal)1.0; 274da80777bSKarl Rupp scoeff[1] = gamma[1*nstages+i]; 275da80777bSKarl Rupp scoeff[2] = gamma[2*nstages+i]; 276da80777bSKarl Rupp scoeff[3] = -betasub[i]*ms->damping; 2771aa26658SKarl Rupp 27837e1895aSJed Brown ierr = VecAXPY(S2,delta[i],S1);CHKERRQ(ierr); 27937e1895aSJed Brown if (i>0) { 28037e1895aSJed Brown ierr = SNESComputeFunction(snes,S1,F);CHKERRQ(ierr); 28137e1895aSJed Brown if (snes->domainerror) { 28237e1895aSJed Brown snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 28337e1895aSJed Brown PetscFunctionReturn(0); 28437e1895aSJed Brown } 28537e1895aSJed Brown } 28637e1895aSJed Brown ierr = SNES_KSPSolve(snes,snes->ksp,F,Y);CHKERRQ(ierr); 28737e1895aSJed Brown ierr = VecMAXPY(S1,4,scoeff,Ss);CHKERRQ(ierr); 28837e1895aSJed Brown } 28937e1895aSJed Brown PetscFunctionReturn(0); 29037e1895aSJed Brown } 29137e1895aSJed Brown 29237e1895aSJed Brown #undef __FUNCT__ 29337e1895aSJed Brown #define __FUNCT__ "SNESSolve_MS" 29437e1895aSJed Brown static PetscErrorCode SNESSolve_MS(SNES snes) 29537e1895aSJed Brown { 29637e1895aSJed Brown SNES_MS *ms = (SNES_MS*)snes->data; 29737e1895aSJed Brown Vec X = snes->vec_sol,F = snes->vec_func; 29837e1895aSJed Brown PetscReal fnorm; 29937e1895aSJed Brown MatStructure mstruct; 30037e1895aSJed Brown PetscInt i; 30137e1895aSJed Brown PetscErrorCode ierr; 30237e1895aSJed Brown 30337e1895aSJed Brown PetscFunctionBegin; 30437e1895aSJed Brown snes->reason = SNES_CONVERGED_ITERATING; 30537e1895aSJed Brown ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 30637e1895aSJed Brown snes->iter = 0; 30737e1895aSJed Brown snes->norm = 0.; 30837e1895aSJed Brown ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 309e4ed7901SPeter Brune if (!snes->vec_func_init_set) { 31037e1895aSJed Brown ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 31137e1895aSJed Brown if (snes->domainerror) { 31237e1895aSJed Brown snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 31337e1895aSJed Brown PetscFunctionReturn(0); 31437e1895aSJed Brown } 3151aa26658SKarl Rupp } else snes->vec_func_init_set = PETSC_FALSE; 3161aa26658SKarl Rupp 31737e1895aSJed Brown if (snes->jacobian) { /* This method does not require a Jacobian, but it is usually preconditioned by PBJacobi */ 31837e1895aSJed Brown ierr = SNESComputeJacobian(snes,snes->vec_sol,&snes->jacobian,&snes->jacobian_pre,&mstruct);CHKERRQ(ierr); 31937e1895aSJed Brown ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,mstruct);CHKERRQ(ierr); 32037e1895aSJed Brown } 32137e1895aSJed Brown if (ms->norms) { 322e4ed7901SPeter Brune if (!snes->norm_init_set) { 32337e1895aSJed Brown ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 324189a9710SBarry Smith if (PetscIsInfOrNanReal(fnorm)) { 325189a9710SBarry Smith snes->reason = SNES_DIVERGED_FNORM_NAN; 326189a9710SBarry Smith PetscFunctionReturn(0); 327189a9710SBarry Smith } 328e4ed7901SPeter Brune } else { 329e4ed7901SPeter Brune fnorm = snes->norm_init; 330e4ed7901SPeter Brune snes->norm_init_set = PETSC_FALSE; 331e4ed7901SPeter Brune } 33237e1895aSJed Brown /* Monitor convergence */ 33337e1895aSJed Brown ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 33437e1895aSJed Brown snes->iter = 0; 33537e1895aSJed Brown snes->norm = fnorm; 33637e1895aSJed Brown ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 337a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); 33837e1895aSJed Brown ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 33937e1895aSJed Brown 34037e1895aSJed Brown /* set parameter for default relative tolerance convergence test */ 34137e1895aSJed Brown snes->ttol = fnorm*snes->rtol; 34237e1895aSJed Brown /* Test for convergence */ 34337e1895aSJed Brown ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 34437e1895aSJed Brown if (snes->reason) PetscFunctionReturn(0); 34537e1895aSJed Brown } 34637e1895aSJed Brown 34737e1895aSJed Brown /* Call general purpose update function */ 34837e1895aSJed Brown if (snes->ops->update) { 34937e1895aSJed Brown ierr = (*snes->ops->update)(snes,snes->iter);CHKERRQ(ierr); 35037e1895aSJed Brown } 35137e1895aSJed Brown for (i = 0; i < snes->max_its; i++) { 35237e1895aSJed Brown ierr = SNESMSStep_3Sstar(snes,X,F);CHKERRQ(ierr); 35337e1895aSJed Brown 35437e1895aSJed Brown if (i+1 < snes->max_its || ms->norms) { 35537e1895aSJed Brown ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr); 35637e1895aSJed Brown if (snes->domainerror) { 35737e1895aSJed Brown snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; 35837e1895aSJed Brown PetscFunctionReturn(0); 35937e1895aSJed Brown } 36037e1895aSJed Brown } 36137e1895aSJed Brown 36237e1895aSJed Brown if (ms->norms) { 36337e1895aSJed Brown ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); /* fnorm <- ||F|| */ 364189a9710SBarry Smith if (PetscIsInfOrNanReal(fnorm)) { 365189a9710SBarry Smith snes->reason = SNES_DIVERGED_FNORM_NAN; 366189a9710SBarry Smith PetscFunctionReturn(0); 367189a9710SBarry Smith } 368189a9710SBarry Smith 36937e1895aSJed Brown /* Monitor convergence */ 37037e1895aSJed Brown ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr); 37137e1895aSJed Brown snes->iter = i+1; 37237e1895aSJed Brown snes->norm = fnorm; 37337e1895aSJed Brown ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr); 374a71f0d7dSBarry Smith ierr = SNESLogConvergenceHistory(snes,snes->norm,0);CHKERRQ(ierr); 37537e1895aSJed Brown ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr); 37637e1895aSJed Brown 37737e1895aSJed Brown /* Test for convergence */ 37837e1895aSJed Brown ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr); 37937e1895aSJed Brown if (snes->reason) PetscFunctionReturn(0); 38037e1895aSJed Brown } 38137e1895aSJed Brown 38237e1895aSJed Brown /* Call general purpose update function */ 38337e1895aSJed Brown if (snes->ops->update) { 38437e1895aSJed Brown ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr); 38537e1895aSJed Brown } 38637e1895aSJed Brown } 38737e1895aSJed Brown if (!snes->reason) snes->reason = SNES_CONVERGED_ITS; 38837e1895aSJed Brown PetscFunctionReturn(0); 38937e1895aSJed Brown } 39037e1895aSJed Brown 39137e1895aSJed Brown #undef __FUNCT__ 39237e1895aSJed Brown #define __FUNCT__ "SNESSetUp_MS" 39337e1895aSJed Brown static PetscErrorCode SNESSetUp_MS(SNES snes) 39437e1895aSJed Brown { 39537e1895aSJed Brown SNES_MS *ms = (SNES_MS*)snes->data; 39637e1895aSJed Brown PetscErrorCode ierr; 39737e1895aSJed Brown 39837e1895aSJed Brown PetscFunctionBegin; 39937e1895aSJed Brown if (!ms->tableau) {ierr = SNESMSSetType(snes,SNESMSDefault);CHKERRQ(ierr);} 40037e1895aSJed Brown ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr); 4016cab3a1bSJed Brown ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); 40237e1895aSJed Brown PetscFunctionReturn(0); 40337e1895aSJed Brown } 40437e1895aSJed Brown 40537e1895aSJed Brown #undef __FUNCT__ 40637e1895aSJed Brown #define __FUNCT__ "SNESReset_MS" 40737e1895aSJed Brown static PetscErrorCode SNESReset_MS(SNES snes) 40837e1895aSJed Brown { 40937e1895aSJed Brown 41037e1895aSJed Brown PetscFunctionBegin; 41137e1895aSJed Brown PetscFunctionReturn(0); 41237e1895aSJed Brown } 41337e1895aSJed Brown 41437e1895aSJed Brown #undef __FUNCT__ 41537e1895aSJed Brown #define __FUNCT__ "SNESDestroy_MS" 41637e1895aSJed Brown static PetscErrorCode SNESDestroy_MS(SNES snes) 41737e1895aSJed Brown { 41837e1895aSJed Brown PetscErrorCode ierr; 41937e1895aSJed Brown 42037e1895aSJed Brown PetscFunctionBegin; 42137e1895aSJed Brown ierr = PetscFree(snes->data);CHKERRQ(ierr); 42200de8ff0SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"","",NULL);CHKERRQ(ierr); 42337e1895aSJed Brown PetscFunctionReturn(0); 42437e1895aSJed Brown } 42537e1895aSJed Brown 42637e1895aSJed Brown #undef __FUNCT__ 42737e1895aSJed Brown #define __FUNCT__ "SNESView_MS" 42837e1895aSJed Brown static PetscErrorCode SNESView_MS(SNES snes,PetscViewer viewer) 42937e1895aSJed Brown { 43037e1895aSJed Brown PetscBool iascii; 43137e1895aSJed Brown PetscErrorCode ierr; 43237e1895aSJed Brown SNES_MS *ms = (SNES_MS*)snes->data; 43337e1895aSJed Brown 43437e1895aSJed Brown PetscFunctionBegin; 435251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 43637e1895aSJed Brown if (iascii) { 43737e1895aSJed Brown SNESMSTableau tab = ms->tableau; 43837e1895aSJed Brown ierr = PetscViewerASCIIPrintf(viewer," multi-stage method type: %s\n",tab ? tab->name : "not yet set");CHKERRQ(ierr); 43937e1895aSJed Brown } 44037e1895aSJed Brown PetscFunctionReturn(0); 44137e1895aSJed Brown } 44237e1895aSJed Brown 44337e1895aSJed Brown #undef __FUNCT__ 44437e1895aSJed Brown #define __FUNCT__ "SNESSetFromOptions_MS" 44537e1895aSJed Brown static PetscErrorCode SNESSetFromOptions_MS(SNES snes) 44637e1895aSJed Brown { 447725b86d8SJed Brown SNES_MS *ms = (SNES_MS*)snes->data; 44837e1895aSJed Brown PetscErrorCode ierr; 44937e1895aSJed Brown 45037e1895aSJed Brown PetscFunctionBegin; 45137e1895aSJed Brown ierr = PetscOptionsHead("SNES MS options");CHKERRQ(ierr); 45237e1895aSJed Brown { 45337e1895aSJed Brown SNESMSTableauLink link; 45437e1895aSJed Brown PetscInt count,choice; 45537e1895aSJed Brown PetscBool flg; 45637e1895aSJed Brown const char **namelist; 45737e1895aSJed Brown char mstype[256]; 45837e1895aSJed Brown 4598caf3d72SBarry Smith ierr = PetscStrncpy(mstype,SNESMSDefault,sizeof(mstype));CHKERRQ(ierr); 46037e1895aSJed Brown for (link=SNESMSTableauList,count=0; link; link=link->next,count++) ; 46137e1895aSJed Brown ierr = PetscMalloc(count*sizeof(char*),&namelist);CHKERRQ(ierr); 46237e1895aSJed Brown for (link=SNESMSTableauList,count=0; link; link=link->next,count++) namelist[count] = link->tab.name; 46337e1895aSJed Brown ierr = PetscOptionsEList("-snes_ms_type","Multistage smoother type","SNESMSSetType",(const char*const*)namelist,count,mstype,&choice,&flg);CHKERRQ(ierr); 46437e1895aSJed Brown ierr = SNESMSSetType(snes,flg ? namelist[choice] : mstype);CHKERRQ(ierr); 46537e1895aSJed Brown ierr = PetscFree(namelist);CHKERRQ(ierr); 4660298fd71SBarry Smith ierr = PetscOptionsReal("-snes_ms_damping","Damping for multistage method","SNESMSSetDamping",ms->damping,&ms->damping,NULL);CHKERRQ(ierr); 4670298fd71SBarry Smith ierr = PetscOptionsBool("-snes_ms_norms","Compute norms for monitoring","none",ms->norms,&ms->norms,NULL);CHKERRQ(ierr); 46837e1895aSJed Brown } 46937e1895aSJed Brown ierr = PetscOptionsTail();CHKERRQ(ierr); 47037e1895aSJed Brown PetscFunctionReturn(0); 47137e1895aSJed Brown } 47237e1895aSJed Brown 47337e1895aSJed Brown #undef __FUNCT__ 47437e1895aSJed Brown #define __FUNCT__ "SNESMSSetType_MS" 47537e1895aSJed Brown PetscErrorCode SNESMSSetType_MS(SNES snes,SNESMSType mstype) 47637e1895aSJed Brown { 47737e1895aSJed Brown PetscErrorCode ierr; 47837e1895aSJed Brown SNES_MS *ms = (SNES_MS*)snes->data; 47937e1895aSJed Brown SNESMSTableauLink link; 48037e1895aSJed Brown PetscBool match; 48137e1895aSJed Brown 48237e1895aSJed Brown PetscFunctionBegin; 48337e1895aSJed Brown if (ms->tableau) { 48437e1895aSJed Brown ierr = PetscStrcmp(ms->tableau->name,mstype,&match);CHKERRQ(ierr); 48537e1895aSJed Brown if (match) PetscFunctionReturn(0); 48637e1895aSJed Brown } 48737e1895aSJed Brown for (link = SNESMSTableauList; link; link=link->next) { 48837e1895aSJed Brown ierr = PetscStrcmp(link->tab.name,mstype,&match);CHKERRQ(ierr); 48937e1895aSJed Brown if (match) { 49037e1895aSJed Brown ierr = SNESReset_MS(snes);CHKERRQ(ierr); 49137e1895aSJed Brown ms->tableau = &link->tab; 49237e1895aSJed Brown PetscFunctionReturn(0); 49337e1895aSJed Brown } 49437e1895aSJed Brown } 495ce94432eSBarry Smith SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",mstype); 49637e1895aSJed Brown PetscFunctionReturn(0); 49737e1895aSJed Brown } 49837e1895aSJed Brown 49937e1895aSJed Brown #undef __FUNCT__ 50037e1895aSJed Brown #define __FUNCT__ "SNESMSSetType" 50137e1895aSJed Brown /*@C 50237e1895aSJed Brown SNESMSSetType - Set the type of multistage smoother 50337e1895aSJed Brown 50437e1895aSJed Brown Logically collective 50537e1895aSJed Brown 50637e1895aSJed Brown Input Parameter: 50737e1895aSJed Brown + snes - nonlinear solver context 50837e1895aSJed Brown - mstype - type of multistage method 50937e1895aSJed Brown 51037e1895aSJed Brown Level: beginner 51137e1895aSJed Brown 51237e1895aSJed Brown .seealso: SNESMSGetType(), SNESMS 51337e1895aSJed Brown @*/ 51419fd82e9SBarry Smith PetscErrorCode SNESMSSetType(SNES snes,SNESMSType rostype) 51537e1895aSJed Brown { 51637e1895aSJed Brown PetscErrorCode ierr; 51737e1895aSJed Brown 51837e1895aSJed Brown PetscFunctionBegin; 51937e1895aSJed Brown PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 52019fd82e9SBarry Smith ierr = PetscTryMethod(snes,"SNESMSSetType_C",(SNES,SNESMSType),(snes,rostype));CHKERRQ(ierr); 52137e1895aSJed Brown PetscFunctionReturn(0); 52237e1895aSJed Brown } 52337e1895aSJed Brown 52437e1895aSJed Brown /* -------------------------------------------------------------------------- */ 52537e1895aSJed Brown /*MC 52637e1895aSJed Brown SNESMS - multi-stage smoothers 52737e1895aSJed Brown 52837e1895aSJed Brown Options Database: 52937e1895aSJed Brown 53037e1895aSJed Brown + -snes_ms_type - type of multi-stage smoother 53137e1895aSJed Brown - -snes_ms_damping - damping for multi-stage method 53237e1895aSJed Brown 53337e1895aSJed Brown Notes: 53437e1895aSJed Brown These multistage methods are explicit Runge-Kutta methods that are often used as smoothers for 5356c9de887SHong Zhang FAS multigrid for transport problems. In the linear case, these are equivalent to polynomial smoothers (such as Chebyshev). 53637e1895aSJed Brown 53737e1895aSJed Brown Multi-stage smoothers should usually be preconditioned by point-block Jacobi to ensure proper scaling and to normalize the wave speeds. 53837e1895aSJed Brown 53937e1895aSJed Brown The methods are specified in low storage form (Ketcheson 2010). New methods can be registered with SNESMSRegister(). 54037e1895aSJed Brown 54137e1895aSJed Brown References: 54237e1895aSJed Brown 54337e1895aSJed Brown Ketcheson (2010) Runge-Kutta methods with minimum storage implementations. 54437e1895aSJed Brown 54537e1895aSJed Brown Jameson (1983) Solution of the Euler equations for two dimensional transonic flow by a multigrid method. 54637e1895aSJed Brown 54737e1895aSJed Brown Pierce and Giles (1997) Preconditioned multigrid methods for compressible flow calculations on stretched meshes. 54837e1895aSJed Brown 54937e1895aSJed Brown Level: beginner 55037e1895aSJed Brown 5516c9de887SHong Zhang .seealso: SNESCreate(), SNES, SNESSetType(), SNESMS, SNESFAS, KSPCHEBYSHEV 55237e1895aSJed Brown 55337e1895aSJed Brown M*/ 55437e1895aSJed Brown #undef __FUNCT__ 55537e1895aSJed Brown #define __FUNCT__ "SNESCreate_MS" 556*8cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_MS(SNES snes) 55737e1895aSJed Brown { 55837e1895aSJed Brown PetscErrorCode ierr; 55937e1895aSJed Brown SNES_MS *ms; 56037e1895aSJed Brown 56137e1895aSJed Brown PetscFunctionBegin; 56237e1895aSJed Brown #if !defined(PETSC_USE_DYNAMIC_LIBRARIES) 5630298fd71SBarry Smith ierr = SNESMSInitializePackage(NULL);CHKERRQ(ierr); 56437e1895aSJed Brown #endif 56537e1895aSJed Brown 56637e1895aSJed Brown snes->ops->setup = SNESSetUp_MS; 56737e1895aSJed Brown snes->ops->solve = SNESSolve_MS; 56837e1895aSJed Brown snes->ops->destroy = SNESDestroy_MS; 56937e1895aSJed Brown snes->ops->setfromoptions = SNESSetFromOptions_MS; 57037e1895aSJed Brown snes->ops->view = SNESView_MS; 57137e1895aSJed Brown snes->ops->reset = SNESReset_MS; 57237e1895aSJed Brown 57337e1895aSJed Brown snes->usespc = PETSC_FALSE; 57437e1895aSJed Brown snes->usesksp = PETSC_TRUE; 57537e1895aSJed Brown 57637e1895aSJed Brown ierr = PetscNewLog(snes,SNES_MS,&ms);CHKERRQ(ierr); 57737e1895aSJed Brown snes->data = (void*)ms; 57837e1895aSJed Brown ms->damping = 0.9; 57937e1895aSJed Brown ms->norms = PETSC_FALSE; 58037e1895aSJed Brown 58100de8ff0SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESMSSetType_C","SNESMSSetType_MS",SNESMSSetType_MS);CHKERRQ(ierr); 58237e1895aSJed Brown PetscFunctionReturn(0); 58337e1895aSJed Brown } 58499e0435eSBarry Smith 585