xref: /petsc/src/snes/impls/ms/ms.c (revision f73f8d2c34b175c91d916331f941e255591e9aaf)
137e1895aSJed Brown #include <private/snesimpl.h>   /*I "petscsnes.h" I*/
237e1895aSJed Brown 
337e1895aSJed Brown static const 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   }
6937e1895aSJed Brown   PetscFunctionReturn(0);
7037e1895aSJed Brown }
7137e1895aSJed Brown 
7237e1895aSJed Brown #undef __FUNCT__
7337e1895aSJed Brown #define __FUNCT__ "SNESMSRegisterDestroy"
7437e1895aSJed Brown /*@C
7537e1895aSJed Brown    SNESMSRegisterDestroy - Frees the list of schemes that were registered by TSRosWRegister().
7637e1895aSJed Brown 
7737e1895aSJed Brown    Not Collective
7837e1895aSJed Brown 
7937e1895aSJed Brown    Level: advanced
8037e1895aSJed Brown 
8137e1895aSJed Brown .keywords: TSRosW, register, destroy
8237e1895aSJed Brown .seealso: TSRosWRegister(), TSRosWRegisterAll(), TSRosWRegisterDynamic()
8337e1895aSJed Brown @*/
8437e1895aSJed Brown PetscErrorCode SNESMSRegisterDestroy(void)
8537e1895aSJed Brown {
8637e1895aSJed Brown   PetscErrorCode ierr;
8737e1895aSJed Brown   SNESMSTableauLink link;
8837e1895aSJed Brown 
8937e1895aSJed Brown   PetscFunctionBegin;
9037e1895aSJed Brown   while ((link = SNESMSTableauList)) {
9137e1895aSJed Brown     SNESMSTableau t = &link->tab;
9237e1895aSJed Brown     SNESMSTableauList = link->next;
9337e1895aSJed Brown     ierr = PetscFree3(t->gamma,t->delta,t->betasub);CHKERRQ(ierr);
9437e1895aSJed Brown     ierr = PetscFree(t->name);CHKERRQ(ierr);
9537e1895aSJed Brown     ierr = PetscFree(link);CHKERRQ(ierr);
9637e1895aSJed Brown   }
9737e1895aSJed Brown   SNESMSRegisterAllCalled = PETSC_FALSE;
9837e1895aSJed Brown   PetscFunctionReturn(0);
9937e1895aSJed Brown }
10037e1895aSJed Brown 
10137e1895aSJed Brown #undef __FUNCT__
10237e1895aSJed Brown #define __FUNCT__ "SNESMSInitializePackage"
10337e1895aSJed Brown /*@C
10437e1895aSJed Brown   SNESMSInitializePackage - This function initializes everything in the SNESMS package. It is called
10537e1895aSJed Brown   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to SNESCreate_MS()
10637e1895aSJed Brown   when using static libraries.
10737e1895aSJed Brown 
10837e1895aSJed Brown   Input Parameter:
10937e1895aSJed Brown   path - The dynamic library path, or PETSC_NULL
11037e1895aSJed Brown 
11137e1895aSJed Brown   Level: developer
11237e1895aSJed Brown 
11337e1895aSJed Brown .keywords: SNES, SNESMS, initialize, package
11437e1895aSJed Brown .seealso: PetscInitialize()
11537e1895aSJed Brown @*/
11637e1895aSJed Brown PetscErrorCode SNESMSInitializePackage(const char path[])
11737e1895aSJed Brown {
11837e1895aSJed Brown   PetscErrorCode ierr;
11937e1895aSJed Brown 
12037e1895aSJed Brown   PetscFunctionBegin;
12137e1895aSJed Brown   if (SNESMSPackageInitialized) PetscFunctionReturn(0);
12237e1895aSJed Brown   SNESMSPackageInitialized = PETSC_TRUE;
12337e1895aSJed Brown   ierr = SNESMSRegisterAll();CHKERRQ(ierr);
12437e1895aSJed Brown   ierr = PetscRegisterFinalize(SNESMSFinalizePackage);CHKERRQ(ierr);
12537e1895aSJed Brown   PetscFunctionReturn(0);
12637e1895aSJed Brown }
12737e1895aSJed Brown 
12837e1895aSJed Brown #undef __FUNCT__
12937e1895aSJed Brown #define __FUNCT__ "SNESMSFinalizePackage"
13037e1895aSJed Brown /*@C
13137e1895aSJed Brown   SNESMSFinalizePackage - This function destroys everything in the SNESMS package. It is
13237e1895aSJed Brown   called from PetscFinalize().
13337e1895aSJed Brown 
13437e1895aSJed Brown   Level: developer
13537e1895aSJed Brown 
13637e1895aSJed Brown .keywords: Petsc, destroy, package
13737e1895aSJed Brown .seealso: PetscFinalize()
13837e1895aSJed Brown @*/
13937e1895aSJed Brown PetscErrorCode SNESMSFinalizePackage(void)
14037e1895aSJed Brown {
14137e1895aSJed Brown   PetscErrorCode ierr;
14237e1895aSJed Brown 
14337e1895aSJed Brown   PetscFunctionBegin;
14437e1895aSJed Brown   SNESMSPackageInitialized = PETSC_FALSE;
14537e1895aSJed Brown   ierr = SNESMSRegisterDestroy();CHKERRQ(ierr);
14637e1895aSJed Brown   PetscFunctionReturn(0);
14737e1895aSJed Brown }
14837e1895aSJed Brown 
14937e1895aSJed Brown #undef __FUNCT__
15037e1895aSJed Brown #define __FUNCT__ "SNESMSRegister"
15137e1895aSJed Brown /*@C
15237e1895aSJed Brown    SNESMSRegister - register a multistage scheme
15337e1895aSJed Brown 
15437e1895aSJed Brown    Not Collective, but the same schemes should be registered on all processes on which they will be used
15537e1895aSJed Brown 
15637e1895aSJed Brown    Input Parameters:
15737e1895aSJed Brown +  name - identifier for method
15837e1895aSJed Brown .  nstages - number of stages
15937e1895aSJed Brown .  nregisters - number of registers used by low-storage implementation
16037e1895aSJed Brown .  gamma - coefficients, see Ketcheson's paper
16137e1895aSJed Brown .  delta - coefficients, see Ketcheson's paper
16237e1895aSJed Brown -  betasub - subdiagonal of Shu-Osher form
16337e1895aSJed Brown 
16437e1895aSJed Brown    Notes:
16537e1895aSJed Brown    The notation is described in Ketcheson (2010) Runge-Kutta methods with minimum storage implementations.
16637e1895aSJed Brown 
16737e1895aSJed Brown    Level: advanced
16837e1895aSJed Brown 
16937e1895aSJed Brown .keywords: SNES, register
17037e1895aSJed Brown 
17137e1895aSJed Brown .seealso: SNESMS
17237e1895aSJed Brown @*/
17337e1895aSJed Brown PetscErrorCode SNESMSRegister(const SNESMSType name,PetscInt nstages,PetscInt nregisters,PetscReal stability,const PetscReal gamma[],const PetscReal delta[],const PetscReal betasub[])
17437e1895aSJed Brown {
17537e1895aSJed Brown   PetscErrorCode ierr;
17637e1895aSJed Brown   SNESMSTableauLink link;
17737e1895aSJed Brown   SNESMSTableau t;
17837e1895aSJed Brown 
17937e1895aSJed Brown   PetscFunctionBegin;
18037e1895aSJed Brown   PetscValidCharPointer(name,1);
18137e1895aSJed Brown   if (nstages < 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have at least one stage");
18237e1895aSJed Brown   if (nregisters != 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only support for methods written in 3-register form");
18337e1895aSJed Brown   PetscValidPointer(gamma,4);
18437e1895aSJed Brown   PetscValidPointer(delta,5);
18537e1895aSJed Brown   PetscValidPointer(betasub,6);
18637e1895aSJed Brown 
18737e1895aSJed Brown   ierr = PetscMalloc(sizeof(*link),&link);CHKERRQ(ierr);
18837e1895aSJed Brown   ierr = PetscMemzero(link,sizeof(*link));CHKERRQ(ierr);
18937e1895aSJed Brown   t = &link->tab;
19037e1895aSJed Brown   ierr = PetscStrallocpy(name,&t->name);CHKERRQ(ierr);
19137e1895aSJed Brown   t->nstages    = nstages;
19237e1895aSJed Brown   t->nregisters = nregisters;
19337e1895aSJed Brown   t->stability  = stability;
19437e1895aSJed Brown   ierr = PetscMalloc3(nstages*nregisters,PetscReal,&t->gamma,nstages,PetscReal,&t->delta,nstages,PetscReal,&t->betasub);CHKERRQ(ierr);
19537e1895aSJed Brown   ierr = PetscMemcpy(t->gamma,gamma,nstages*nregisters*sizeof(PetscReal));CHKERRQ(ierr);
19637e1895aSJed Brown   ierr = PetscMemcpy(t->delta,delta,nstages*sizeof(PetscReal));CHKERRQ(ierr);
19737e1895aSJed Brown   ierr = PetscMemcpy(t->betasub,betasub,nstages*sizeof(PetscReal));CHKERRQ(ierr);
19837e1895aSJed Brown 
19937e1895aSJed Brown   link->next = SNESMSTableauList;
20037e1895aSJed Brown   SNESMSTableauList = link;
20137e1895aSJed Brown   PetscFunctionReturn(0);
20237e1895aSJed Brown }
20337e1895aSJed Brown 
20437e1895aSJed Brown #undef __FUNCT__
20537e1895aSJed Brown #define __FUNCT__ "SNESMSStep_3Sstar"
20637e1895aSJed Brown /*
20737e1895aSJed Brown   X - initial state, updated in-place.
20837e1895aSJed Brown   F - residual, computed at the initial X on input
20937e1895aSJed Brown */
21037e1895aSJed Brown static PetscErrorCode SNESMSStep_3Sstar(SNES snes,Vec X,Vec F)
21137e1895aSJed Brown {
21237e1895aSJed Brown   PetscErrorCode ierr;
21337e1895aSJed Brown   SNES_MS        *ms = (SNES_MS*)snes->data;
21437e1895aSJed Brown   SNESMSTableau  t = ms->tableau;
21537e1895aSJed Brown   const PetscReal *gamma = t->gamma,*delta = t->delta,*betasub = t->betasub;
21637e1895aSJed Brown   Vec            S1,S2,S3,Y;
21737e1895aSJed Brown   PetscInt       i,nstages = t->nstages;;
21837e1895aSJed Brown 
21937e1895aSJed Brown 
22037e1895aSJed Brown   PetscFunctionBegin;
22137e1895aSJed Brown   Y = snes->work[0];
22237e1895aSJed Brown   S1 = X;
22337e1895aSJed Brown   S2 = snes->work[1];
22437e1895aSJed Brown   S3 = snes->work[2];
22537e1895aSJed Brown   ierr = VecZeroEntries(S2);CHKERRQ(ierr);
22637e1895aSJed Brown   ierr = VecCopy(X,S3);CHKERRQ(ierr);
22737e1895aSJed Brown   for (i=0; i<nstages; i++) {
22837e1895aSJed Brown     Vec Ss[4] = {S1,S2,S3,Y};
229*f73f8d2cSSatish Balay     PetscScalar scoeff[4] = {gamma[0*nstages+i]-1.0,gamma[1*nstages+i],gamma[2*nstages+i],-betasub[i]*ms->damping};
23037e1895aSJed Brown     ierr = VecAXPY(S2,delta[i],S1);CHKERRQ(ierr);
23137e1895aSJed Brown     if (i>0) {
23237e1895aSJed Brown       ierr = SNESComputeFunction(snes,S1,F);CHKERRQ(ierr);
23337e1895aSJed Brown       if (snes->domainerror) {
23437e1895aSJed Brown         snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
23537e1895aSJed Brown         PetscFunctionReturn(0);
23637e1895aSJed Brown       }
23737e1895aSJed Brown     }
23837e1895aSJed Brown     ierr = SNES_KSPSolve(snes,snes->ksp,F,Y);CHKERRQ(ierr);
23937e1895aSJed Brown     ierr = VecMAXPY(S1,4,scoeff,Ss);CHKERRQ(ierr);
24037e1895aSJed Brown   }
24137e1895aSJed Brown   PetscFunctionReturn(0);
24237e1895aSJed Brown }
24337e1895aSJed Brown 
24437e1895aSJed Brown #undef __FUNCT__
24537e1895aSJed Brown #define __FUNCT__ "SNESSolve_MS"
24637e1895aSJed Brown static PetscErrorCode SNESSolve_MS(SNES snes)
24737e1895aSJed Brown {
24837e1895aSJed Brown   SNES_MS        *ms = (SNES_MS*)snes->data;
24937e1895aSJed Brown   Vec            X = snes->vec_sol,F = snes->vec_func;
25037e1895aSJed Brown   PetscReal      fnorm;
25137e1895aSJed Brown   MatStructure   mstruct;
25237e1895aSJed Brown   PetscInt       i;
25337e1895aSJed Brown   PetscErrorCode ierr;
25437e1895aSJed Brown 
25537e1895aSJed Brown   PetscFunctionBegin;
25637e1895aSJed Brown   snes->reason = SNES_CONVERGED_ITERATING;
25737e1895aSJed Brown   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
25837e1895aSJed Brown   snes->iter = 0;
25937e1895aSJed Brown   snes->norm = 0.;
26037e1895aSJed Brown   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
26137e1895aSJed Brown 
26237e1895aSJed Brown   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
26337e1895aSJed Brown   if (snes->domainerror) {
26437e1895aSJed Brown     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
26537e1895aSJed Brown     PetscFunctionReturn(0);
26637e1895aSJed Brown   }
26737e1895aSJed Brown   if (snes->jacobian) {         /* This method does not require a Jacobian, but it is usually preconditioned by PBJacobi */
26837e1895aSJed Brown     ierr = SNESComputeJacobian(snes,snes->vec_sol,&snes->jacobian,&snes->jacobian_pre,&mstruct);CHKERRQ(ierr);
26937e1895aSJed Brown     ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,mstruct);CHKERRQ(ierr);
27037e1895aSJed Brown   }
27137e1895aSJed Brown   if (ms->norms) {
27237e1895aSJed Brown     ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); /* fnorm <- ||F||  */
27337e1895aSJed Brown     if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
27437e1895aSJed Brown     /* Monitor convergence */
27537e1895aSJed Brown     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
27637e1895aSJed Brown     snes->iter = 0;
27737e1895aSJed Brown     snes->norm = fnorm;
27837e1895aSJed Brown     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
27937e1895aSJed Brown     SNESLogConvHistory(snes,snes->norm,0);
28037e1895aSJed Brown     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
28137e1895aSJed Brown 
28237e1895aSJed Brown     /* set parameter for default relative tolerance convergence test */
28337e1895aSJed Brown     snes->ttol = fnorm*snes->rtol;
28437e1895aSJed Brown     /* Test for convergence */
28537e1895aSJed Brown     ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
28637e1895aSJed Brown     if (snes->reason) PetscFunctionReturn(0);
28737e1895aSJed Brown   }
28837e1895aSJed Brown 
28937e1895aSJed Brown   /* Call general purpose update function */
29037e1895aSJed Brown   if (snes->ops->update) {
29137e1895aSJed Brown     ierr = (*snes->ops->update)(snes,snes->iter);CHKERRQ(ierr);
29237e1895aSJed Brown   }
29337e1895aSJed Brown   for (i = 0; i < snes->max_its; i++) {
29437e1895aSJed Brown     ierr = SNESMSStep_3Sstar(snes,X,F);CHKERRQ(ierr);
29537e1895aSJed Brown 
29637e1895aSJed Brown     if (i+1 < snes->max_its || ms->norms) {
29737e1895aSJed Brown       ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
29837e1895aSJed Brown       if (snes->domainerror) {
29937e1895aSJed Brown         snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
30037e1895aSJed Brown         PetscFunctionReturn(0);
30137e1895aSJed Brown       }
30237e1895aSJed Brown     }
30337e1895aSJed Brown 
30437e1895aSJed Brown     if (ms->norms) {
30537e1895aSJed Brown       ierr = VecNorm(F,NORM_2,&fnorm);CHKERRQ(ierr); /* fnorm <- ||F||  */
30637e1895aSJed Brown       if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
30737e1895aSJed Brown       /* Monitor convergence */
30837e1895aSJed Brown       ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
30937e1895aSJed Brown       snes->iter = i+1;
31037e1895aSJed Brown       snes->norm = fnorm;
31137e1895aSJed Brown       ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
31237e1895aSJed Brown       SNESLogConvHistory(snes,snes->norm,0);
31337e1895aSJed Brown       ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
31437e1895aSJed Brown 
31537e1895aSJed Brown       /* Test for convergence */
31637e1895aSJed Brown       ierr = (*snes->ops->converged)(snes,snes->iter,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
31737e1895aSJed Brown       if (snes->reason) PetscFunctionReturn(0);
31837e1895aSJed Brown     }
31937e1895aSJed Brown 
32037e1895aSJed Brown     /* Call general purpose update function */
32137e1895aSJed Brown     if (snes->ops->update) {
32237e1895aSJed Brown       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
32337e1895aSJed Brown     }
32437e1895aSJed Brown   }
32537e1895aSJed Brown   if (!snes->reason) snes->reason = SNES_CONVERGED_ITS;
32637e1895aSJed Brown   PetscFunctionReturn(0);
32737e1895aSJed Brown }
32837e1895aSJed Brown 
32937e1895aSJed Brown #undef __FUNCT__
33037e1895aSJed Brown #define __FUNCT__ "SNESSetUp_MS"
33137e1895aSJed Brown static PetscErrorCode SNESSetUp_MS(SNES snes)
33237e1895aSJed Brown {
33337e1895aSJed Brown   SNES_MS * ms = (SNES_MS *)snes->data;
33437e1895aSJed Brown   PetscErrorCode ierr;
33537e1895aSJed Brown 
33637e1895aSJed Brown   PetscFunctionBegin;
33737e1895aSJed Brown   if (!ms->tableau) {ierr = SNESMSSetType(snes,SNESMSDefault);CHKERRQ(ierr);}
33837e1895aSJed Brown   ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr);
33937e1895aSJed Brown   PetscFunctionReturn(0);
34037e1895aSJed Brown }
34137e1895aSJed Brown 
34237e1895aSJed Brown #undef __FUNCT__
34337e1895aSJed Brown #define __FUNCT__ "SNESReset_MS"
34437e1895aSJed Brown static PetscErrorCode SNESReset_MS(SNES snes)
34537e1895aSJed Brown {
34637e1895aSJed Brown 
34737e1895aSJed Brown   PetscFunctionBegin;
34837e1895aSJed Brown   PetscFunctionReturn(0);
34937e1895aSJed Brown }
35037e1895aSJed Brown 
35137e1895aSJed Brown #undef __FUNCT__
35237e1895aSJed Brown #define __FUNCT__ "SNESDestroy_MS"
35337e1895aSJed Brown static PetscErrorCode SNESDestroy_MS(SNES snes)
35437e1895aSJed Brown {
35537e1895aSJed Brown   PetscErrorCode ierr;
35637e1895aSJed Brown 
35737e1895aSJed Brown   PetscFunctionBegin;
35837e1895aSJed Brown   ierr = PetscFree(snes->data);CHKERRQ(ierr);
35937e1895aSJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"","",PETSC_NULL);CHKERRQ(ierr);
36037e1895aSJed Brown   PetscFunctionReturn(0);
36137e1895aSJed Brown }
36237e1895aSJed Brown 
36337e1895aSJed Brown #undef __FUNCT__
36437e1895aSJed Brown #define __FUNCT__ "SNESView_MS"
36537e1895aSJed Brown static PetscErrorCode SNESView_MS(SNES snes,PetscViewer viewer)
36637e1895aSJed Brown {
36737e1895aSJed Brown   PetscBool        iascii;
36837e1895aSJed Brown   PetscErrorCode   ierr;
36937e1895aSJed Brown   SNES_MS          *ms = (SNES_MS*)snes->data;
37037e1895aSJed Brown 
37137e1895aSJed Brown   PetscFunctionBegin;
37237e1895aSJed Brown   ierr = PetscTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
37337e1895aSJed Brown   if (iascii) {
37437e1895aSJed Brown     SNESMSTableau tab = ms->tableau;
37537e1895aSJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"  multi-stage method type: %s\n",tab?tab->name:"not yet set");CHKERRQ(ierr);
37637e1895aSJed Brown   }
37737e1895aSJed Brown   PetscFunctionReturn(0);
37837e1895aSJed Brown }
37937e1895aSJed Brown 
38037e1895aSJed Brown #undef __FUNCT__
38137e1895aSJed Brown #define __FUNCT__ "SNESSetFromOptions_MS"
38237e1895aSJed Brown static PetscErrorCode SNESSetFromOptions_MS(SNES snes)
38337e1895aSJed Brown {
38437e1895aSJed Brown   SNES_MS        *ms = (SNES_MS*)snes->data;;
38537e1895aSJed Brown   PetscErrorCode ierr;
38637e1895aSJed Brown 
38737e1895aSJed Brown   PetscFunctionBegin;
38837e1895aSJed Brown   ierr = PetscOptionsHead("SNES MS options");CHKERRQ(ierr);
38937e1895aSJed Brown   {
39037e1895aSJed Brown     SNESMSTableauLink link;
39137e1895aSJed Brown     PetscInt count,choice;
39237e1895aSJed Brown     PetscBool flg;
39337e1895aSJed Brown     const char **namelist;
39437e1895aSJed Brown     char mstype[256];
39537e1895aSJed Brown 
39637e1895aSJed Brown     ierr = PetscStrncpy(mstype,SNESMSDefault,sizeof mstype);CHKERRQ(ierr);
39737e1895aSJed Brown     for (link=SNESMSTableauList,count=0; link; link=link->next,count++) ;
39837e1895aSJed Brown     ierr = PetscMalloc(count*sizeof(char*),&namelist);CHKERRQ(ierr);
39937e1895aSJed Brown     for (link=SNESMSTableauList,count=0; link; link=link->next,count++) namelist[count] = link->tab.name;
40037e1895aSJed Brown     ierr = PetscOptionsEList("-snes_ms_type","Multistage smoother type","SNESMSSetType",(const char*const*)namelist,count,mstype,&choice,&flg);CHKERRQ(ierr);
40137e1895aSJed Brown     ierr = SNESMSSetType(snes,flg ? namelist[choice] : mstype);CHKERRQ(ierr);
40237e1895aSJed Brown     ierr = PetscFree(namelist);CHKERRQ(ierr);
40337e1895aSJed Brown     ierr = PetscOptionsReal("-snes_ms_damping","Damping for multistage method","SNESMSSetDamping",ms->damping,&ms->damping,PETSC_NULL);CHKERRQ(ierr);
40437e1895aSJed Brown     ierr = PetscOptionsBool("-snes_ms_norms","Compute norms for monitoring","none",ms->norms,&ms->norms,PETSC_NULL);CHKERRQ(ierr);
40537e1895aSJed Brown   }
40637e1895aSJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
40737e1895aSJed Brown   PetscFunctionReturn(0);
40837e1895aSJed Brown }
40937e1895aSJed Brown 
41037e1895aSJed Brown EXTERN_C_BEGIN
41137e1895aSJed Brown #undef __FUNCT__
41237e1895aSJed Brown #define __FUNCT__ "SNESMSSetType_MS"
41337e1895aSJed Brown PetscErrorCode  SNESMSSetType_MS(SNES snes,SNESMSType mstype)
41437e1895aSJed Brown {
41537e1895aSJed Brown   PetscErrorCode    ierr;
41637e1895aSJed Brown   SNES_MS           *ms = (SNES_MS*)snes->data;
41737e1895aSJed Brown   SNESMSTableauLink link;
41837e1895aSJed Brown   PetscBool         match;
41937e1895aSJed Brown 
42037e1895aSJed Brown   PetscFunctionBegin;
42137e1895aSJed Brown   if (ms->tableau) {
42237e1895aSJed Brown     ierr = PetscStrcmp(ms->tableau->name,mstype,&match);CHKERRQ(ierr);
42337e1895aSJed Brown     if (match) PetscFunctionReturn(0);
42437e1895aSJed Brown   }
42537e1895aSJed Brown   for (link = SNESMSTableauList; link; link=link->next) {
42637e1895aSJed Brown     ierr = PetscStrcmp(link->tab.name,mstype,&match);CHKERRQ(ierr);
42737e1895aSJed Brown     if (match) {
42837e1895aSJed Brown       ierr = SNESReset_MS(snes);CHKERRQ(ierr);
42937e1895aSJed Brown       ms->tableau = &link->tab;
43037e1895aSJed Brown       PetscFunctionReturn(0);
43137e1895aSJed Brown     }
43237e1895aSJed Brown   }
43337e1895aSJed Brown   SETERRQ1(((PetscObject)snes)->comm,PETSC_ERR_ARG_UNKNOWN_TYPE,"Could not find '%s'",mstype);
43437e1895aSJed Brown   PetscFunctionReturn(0);
43537e1895aSJed Brown }
43637e1895aSJed Brown EXTERN_C_END
43737e1895aSJed Brown 
43837e1895aSJed Brown 
43937e1895aSJed Brown #undef __FUNCT__
44037e1895aSJed Brown #define __FUNCT__ "SNESMSSetType"
44137e1895aSJed Brown /*@C
44237e1895aSJed Brown   SNESMSSetType - Set the type of multistage smoother
44337e1895aSJed Brown 
44437e1895aSJed Brown   Logically collective
44537e1895aSJed Brown 
44637e1895aSJed Brown   Input Parameter:
44737e1895aSJed Brown +  snes - nonlinear solver context
44837e1895aSJed Brown -  mstype - type of multistage method
44937e1895aSJed Brown 
45037e1895aSJed Brown   Level: beginner
45137e1895aSJed Brown 
45237e1895aSJed Brown .seealso: SNESMSGetType(), SNESMS
45337e1895aSJed Brown @*/
45437e1895aSJed Brown PetscErrorCode SNESMSSetType(SNES snes,const SNESMSType rostype)
45537e1895aSJed Brown {
45637e1895aSJed Brown   PetscErrorCode ierr;
45737e1895aSJed Brown 
45837e1895aSJed Brown   PetscFunctionBegin;
45937e1895aSJed Brown   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
46037e1895aSJed Brown   ierr = PetscTryMethod(snes,"SNESMSSetType_C",(SNES,const SNESMSType),(snes,rostype));CHKERRQ(ierr);
46137e1895aSJed Brown   PetscFunctionReturn(0);
46237e1895aSJed Brown }
46337e1895aSJed Brown 
46437e1895aSJed Brown /* -------------------------------------------------------------------------- */
46537e1895aSJed Brown /*MC
46637e1895aSJed Brown       SNESMS - multi-stage smoothers
46737e1895aSJed Brown 
46837e1895aSJed Brown       Options Database:
46937e1895aSJed Brown 
47037e1895aSJed Brown +     -snes_ms_type - type of multi-stage smoother
47137e1895aSJed Brown -     -snes_ms_damping - damping for multi-stage method
47237e1895aSJed Brown 
47337e1895aSJed Brown       Notes:
47437e1895aSJed Brown       These multistage methods are explicit Runge-Kutta methods that are often used as smoothers for
47537e1895aSJed Brown       FAS multigrid for transport problems. In the linear case, these are equivalent to polynomial smoothers (such as Chebychev).
47637e1895aSJed Brown 
47737e1895aSJed Brown       Multi-stage smoothers should usually be preconditioned by point-block Jacobi to ensure proper scaling and to normalize the wave speeds.
47837e1895aSJed Brown 
47937e1895aSJed Brown       The methods are specified in low storage form (Ketcheson 2010). New methods can be registered with SNESMSRegister().
48037e1895aSJed Brown 
48137e1895aSJed Brown       References:
48237e1895aSJed Brown 
48337e1895aSJed Brown       Ketcheson (2010) Runge-Kutta methods with minimum storage implementations.
48437e1895aSJed Brown 
48537e1895aSJed Brown       Jameson (1983) Solution of the Euler equations for two dimensional transonic flow by a multigrid method.
48637e1895aSJed Brown 
48737e1895aSJed Brown       Pierce and Giles (1997) Preconditioned multigrid methods for compressible flow calculations on stretched meshes.
48837e1895aSJed Brown 
48937e1895aSJed Brown       Level: beginner
49037e1895aSJed Brown 
49137e1895aSJed Brown .seealso:  SNESCreate(), SNES, SNESSetType(), SNESMS, SNESFAS, KSPCHEBYCHEV
49237e1895aSJed Brown 
49337e1895aSJed Brown M*/
49437e1895aSJed Brown EXTERN_C_BEGIN
49537e1895aSJed Brown #undef __FUNCT__
49637e1895aSJed Brown #define __FUNCT__ "SNESCreate_MS"
49737e1895aSJed Brown PetscErrorCode  SNESCreate_MS(SNES snes)
49837e1895aSJed Brown {
49937e1895aSJed Brown   PetscErrorCode ierr;
50037e1895aSJed Brown   SNES_MS        *ms;
50137e1895aSJed Brown 
50237e1895aSJed Brown   PetscFunctionBegin;
50337e1895aSJed Brown #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
50437e1895aSJed Brown   ierr = SNESMSInitializePackage(PETSC_NULL);CHKERRQ(ierr);
50537e1895aSJed Brown #endif
50637e1895aSJed Brown 
50737e1895aSJed Brown   snes->ops->setup          = SNESSetUp_MS;
50837e1895aSJed Brown   snes->ops->solve          = SNESSolve_MS;
50937e1895aSJed Brown   snes->ops->destroy        = SNESDestroy_MS;
51037e1895aSJed Brown   snes->ops->setfromoptions = SNESSetFromOptions_MS;
51137e1895aSJed Brown   snes->ops->view           = SNESView_MS;
51237e1895aSJed Brown   snes->ops->reset          = SNESReset_MS;
51337e1895aSJed Brown 
51437e1895aSJed Brown   snes->usespc  = PETSC_FALSE;
51537e1895aSJed Brown   snes->usesksp = PETSC_TRUE;
51637e1895aSJed Brown 
51737e1895aSJed Brown   ierr = PetscNewLog(snes,SNES_MS,&ms);CHKERRQ(ierr);
51837e1895aSJed Brown   snes->data = (void*)ms;
51937e1895aSJed Brown   ms->damping = 0.9;
52037e1895aSJed Brown   ms->norms   = PETSC_FALSE;
52137e1895aSJed Brown 
52237e1895aSJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESMSSetType_C","SNESMSSetType_MS",SNESMSSetType_MS);CHKERRQ(ierr);
52337e1895aSJed Brown   PetscFunctionReturn(0);
52437e1895aSJed Brown }
52537e1895aSJed Brown EXTERN_C_END
526