Commits

Peter Brune committed 5e806d2

Added residual and restart tolerances to SNESComposite.

User can now specify parameters for when to choose a solver solution
or the combination candidate solution based upon stagnation and
progress with -snes_composite_stol and -snes_composite_rtol.

Comments (0)

Files changed (1)

src/snes/impls/composite/snescomposite.c

   PetscBLASInt       lwork;          /* the size of the work vector */
   PetscBLASInt       info;           /* the output condition */
 
+  PetscReal          rtol;           /* restart tolerance for accepting the combination */
+  PetscReal          stol;           /* restart tolerance for the combination */
 } SNES_Composite;
 
 #undef __FUNCT__
   SNES_CompositeLink next = jac->head;
   Vec                *Xes = jac->Xes,*Fes = jac->Fes;
   PetscInt           i,j;
-  PetscScalar        tot,ftf;
+  PetscScalar        tot,total,ftf;
+  PetscReal          min_fnorm;
+  PetscInt           min_i;
 
   PetscFunctionBegin;
   if (!next) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONGSTATE,"No composite SNESes supplied via SNESCompositeAddSNES() or -snes_composite_sneses");
     }
     ierr = VecDotBegin(Fes[i],F,&jac->g[i]);CHKERRQ(ierr);
   }
+
   for (i=0;i<jac->n;i++) {
     for (j=0;j<i+1;j++) {
       ierr = VecDotEnd(Fes[i],Fes[j],&jac->h[i + j*jac->n]);CHKERRQ(ierr);
   if (jac->info > 0) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_LIB,"SVD failed to converge");
 #endif
   tot = 0.;
+  total = 0.;
   for (i=0; i<jac->n; i++) {
     if (PetscIsInfOrNanScalar(jac->beta[i])) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_LIB,"SVD generated inconsistent output");
     ierr = PetscInfo2(snes,"%d: %f\n",i,PetscRealPart(jac->beta[i]));CHKERRQ(ierr);
     tot += jac->beta[i];
+    total += PetscAbsScalar(jac->beta[i]);
   }
   ierr = VecScale(X,(1. - tot));CHKERRQ(ierr);
   ierr = VecMAXPY(X,jac->n,jac->beta,Xes);CHKERRQ(ierr);
   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
   ierr = VecNorm(F,NORM_2,fnorm);CHKERRQ(ierr);
 
-  /* take the minimum-normed candidate if it beats the combination */
+  /* take the minimum-normed candidate if it beats the combination by a factor of rtol or the combination has stagnated */
+  min_fnorm = jac->fnorms[0];
+  min_i     = 0;
   for (i=0; i<jac->n; i++) {
-    if (jac->fnorms[i] < *fnorm) {
-      ierr = VecCopy(Xes[i],X);CHKERRQ(ierr);
-      ierr = VecCopy(Fes[i],F);CHKERRQ(ierr);
-      *fnorm = jac->fnorms[i];
+    if (jac->fnorms[i] < min_fnorm) {
+      min_fnorm = jac->fnorms[i];
+      min_i     = i;
     }
   }
+
+  /* stagnation or divergence restart to the solution of the solver that failed the least */
+  if (PetscRealPart(total) < jac->stol || min_fnorm*jac->rtol < *fnorm) {
+    ierr = VecCopy(X,jac->Xes[min_i]);CHKERRQ(ierr);
+    ierr = VecCopy(F,jac->Fes[min_i]);CHKERRQ(ierr);
+    *fnorm = min_fnorm;
+  }
   PetscFunctionReturn(0);
 }
 
       ierr = SNESCompositeSetDamping(snes,i,dmps[i]);CHKERRQ(ierr);
     }
   }
+  ierr = PetscOptionsReal("-snes_composite_stol","Step tolerance for restart on the additive composite solvers","",jac->stol,&jac->stol,NULL);CHKERRQ(ierr);
+  ierr = PetscOptionsReal("-snes_composite_rtol","Residual tolerance for the additive composite solvers","",jac->rtol,&jac->rtol,NULL);CHKERRQ(ierr);
   ierr = PetscOptionsTail();CHKERRQ(ierr);
 
   next = jac->head;
   jac->fnorms = NULL;
   jac->nsnes = 0;
   jac->head  = 0;
+  jac->stol  = 0.1;
+  jac->rtol  = 1.1;
 
   jac->h     = NULL;
   jac->s     = NULL;
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.