System Preprocessors
pc.c
Go to the documentation of this file.
00001 /*! \page pc The preconditioner
00002 
00003   Choosing a preconditioner changes a linear system into a preconditioned
00004   system. However, this is not a transformation of any coefficient matrix,
00005   so this preprocessor is handled a bit differently from the previous ones.
00006  */
00007 
00008 #include <stdlib.h>
00009 #include <stdio.h>
00010 #include "syspro.h"
00011 #include "syspro_impl.h"
00012 #include "sysprolinear.h"
00013 #include "sysprotransform.h"
00014 #include "linear_impl.h"
00015 #include "linpc.h"
00016 #include "linksp.h"
00017 #include "petsc.h"
00018 #include "petscmat.h"
00019 #include "petscpc.h"
00020 #include "petscksp.h"
00021 #include "anamod.h"
00022 
00023 #define PetscObjectStateDecrease(obj) ((obj)->state--,0)
00024 
00025 #define PREPROCESSOR "pc"
00026 
00027 #undef __FUNCT__
00028 #define __FUNCT__ "setup_pc_choices"
00029 static PetscErrorCode setup_pc_choices()
00030 {
00031   SalsaTransform pc; SalsaTransformObject cur;
00032   PetscErrorCode ierr;
00033 
00034   PetscFunctionBegin;
00035 
00036   ierr = TransformGetByName(PREPROCESSOR,&pc); CHKERRQ(ierr);
00037 
00038   /*
00039    * Set up various properties of PCs; these can be used
00040    * later to disable KSP choices
00041    */
00042   /* symmetric substitutions */
00043   ierr = SysProDefineIntAnnotation(PREPROCESSOR,"notrans"); CHKERRQ(ierr);
00044   /* requires transpose */
00045   ierr = SysProDefineIntAnnotation(PREPROCESSOR,"noparallel"); CHKERRQ(ierr);
00046   /* is direct solve */
00047   ierr = SysProDefineIntAnnotation(PREPROCESSOR,"directsolve"); CHKERRQ(ierr);
00048   /* marked as breaking down */
00049   ierr = SysProDefineIntAnnotation(PREPROCESSOR,"marked"); CHKERRQ(ierr);
00050   
00051 #if defined(PETSC_HAVE_BLOCKSOLVE)
00052   /*
00053    * BlockSolve 95
00054    */
00055   ierr = NewTransformObject(PREPROCESSOR,PCBS95,&cur); CHKERRQ(ierr);
00056   ierr = TransformObjectSetExplanation(cur,"BlockSolve 95"); CHKERRQ(ierr);
00057   ierr = TransformObjectIntAnnotate(cur,"notrans",1); CHKERRQ(ierr);
00058 #endif
00059   
00060 #if defined(PETSC_HAVE_HYPRE)
00061   /*
00062    * Hypre methods: boomeramg and pilut
00063    */
00064   ierr = NewTransformObject(PREPROCESSOR,PCBOOMERAMG,&cur); CHKERRQ(ierr);
00065   ierr = TransformObjectSetExplanation(cur,"Hypre BoomerAMG"); CHKERRQ(ierr);
00066   ierr = TransformObjectIntAnnotate(cur,"notrans",1); CHKERRQ(ierr);
00067 
00068   ierr = NewTransformObject(PREPROCESSOR,PCPILUT,&cur); CHKERRQ(ierr);
00069   ierr = TransformObjectSetExplanation(cur,"Hypre pILUt"); CHKERRQ(ierr);
00070   ierr = TransformObjectIntAnnotate(cur,"notrans",1); CHKERRQ(ierr);
00071 
00072   ierr = NewTransformObject(PREPROCESSOR,PCEUCLID,&cur); CHKERRQ(ierr);
00073   ierr = TransformObjectSetExplanation(cur,"Hypre Euclid"); CHKERRQ(ierr);
00074   ierr = TransformObjectIntAnnotate(cur,"notrans",1); CHKERRQ(ierr);
00075   ierr = TransformObjectDefineOption(cur,"fill"); CHKERRQ(ierr);
00076   ierr = TransformObjectAddOption(cur,1); CHKERRQ(ierr);
00077 
00078   ierr = NewTransformObject(PREPROCESSOR,PCPARASAILS,&cur); CHKERRQ(ierr);
00079   ierr = TransformObjectSetExplanation(cur,"Hypre ParaSails"); CHKERRQ(ierr);
00080   ierr = TransformObjectIntAnnotate(cur,"notrans",1); CHKERRQ(ierr);
00081   ierr = TransformObjectDefineOption(cur,"fill"); CHKERRQ(ierr);
00082   ierr = TransformObjectAddOption(cur,1); CHKERRQ(ierr);
00083   ierr = TransformObjectAddOption(cur,2); CHKERRQ(ierr);
00084   ierr = TransformObjectAddOption(cur,3); CHKERRQ(ierr);
00085 #endif
00086 
00087   /*
00088    * ILU sequential
00089    */
00090   ierr = NewTransformObject(PREPROCESSOR,PCILU,&cur); CHKERRQ(ierr);
00091   ierr = TransformObjectSetExplanation(cur,"Incomplete LU"); CHKERRQ(ierr);
00092   ierr = TransformObjectIntAnnotate(cur,"noparallel",1); CHKERRQ(ierr);
00093   ierr = TransformObjectDefineOption(cur,"fill"); CHKERRQ(ierr);
00094   ierr = TransformObjectAddOption(cur,1); CHKERRQ(ierr);
00095   ierr = TransformObjectAddOption(cur,2); CHKERRQ(ierr);
00096   ierr = TransformObjectAddOption(cur,3); CHKERRQ(ierr);
00097   /* shifted version */
00098   ierr = NewTransformObject(PREPROCESSOR,PCSILU,&cur); CHKERRQ(ierr);
00099   ierr = TransformObjectSetExplanation(cur,"shifted Incomplete LU"); CHKERRQ(ierr);
00100   ierr = TransformObjectIntAnnotate(cur,"noparallel",1); CHKERRQ(ierr);
00101   ierr = TransformObjectDefineOption(cur,"fill"); CHKERRQ(ierr);
00102   ierr = TransformObjectAddOption(cur,1); CHKERRQ(ierr);
00103   ierr = TransformObjectAddOption(cur,2); CHKERRQ(ierr);
00104   ierr = TransformObjectAddOption(cur,3); CHKERRQ(ierr);
00105   
00106 #if 0
00107 #if defined(PETSC_HAVE_SPAI)
00108   /*
00109    * SPAI
00110    */
00111   ierr = NewTransformObject(PREPROCESSOR,PCSPAI,&cur); CHKERRQ(ierr);
00112   ierr = TransformObjectSetExplanation(cur,"Sparse Approximate Inverse"); CHKERRQ(ierr);
00113   ierr = TransformObjectIntAnnotate(cur,"notrans",1); CHKERRQ(ierr);
00114   ierr = TransformObjectIntAnnotate(cur,"noparallel",1); CHKERRQ(ierr);
00115   ierr = TransformObjectDefineOption(cur,"blocksize"); CHKERRQ(ierr);
00116   ierr = TransformObjectAddOption(cur,1); CHKERRQ(ierr);
00117   ierr = TransformObjectAddOption(cur,2); CHKERRQ(ierr);
00118   ierr = TransformObjectAddOption(cur,3); CHKERRQ(ierr);
00119 #endif
00120 #endif
00121 
00122   /*
00123    * Additive Schwarz
00124    */
00125   ierr = NewTransformObject
00126     (PREPROCESSOR,PCASM,&cur); CHKERRQ(ierr);
00127   ierr = TransformObjectSetExplanation(cur,"Additive Schwarz method"); CHKERRQ(ierr);
00128   ierr = TransformObjectDefineOption(cur,"local-method"); CHKERRQ(ierr);
00129   /*
00130   ierr = TransformCurrentItemDefineOption(cur,"local method: -1: LU; $\\geq1$ fill levels$+1$; $\\leq-1$: negative of local CG iterations$+1$","local method"); CHKERRQ(ierr);
00131   */
00132   ierr = TransformObjectAddOption(cur,1); CHKERRQ(ierr);
00133   ierr = TransformObjectAddOptionExplanation(cur,1,"ILU(0)"); CHKERRQ(ierr); 
00134   ierr = TransformObjectAddOption(cur,2); CHKERRQ(ierr);
00135   ierr = TransformObjectAddOptionExplanation(cur,2,"ILU(1)"); CHKERRQ(ierr); 
00136   ierr = TransformObjectAddOption(cur,3); CHKERRQ(ierr);
00137   ierr = TransformObjectAddOptionExplanation(cur,3,"ILU(2)"); CHKERRQ(ierr); 
00138   ierr = TransformObjectAddOption(cur,-1); CHKERRQ(ierr);
00139   ierr = TransformObjectAddOptionExplanation(cur,-1,"LU"); CHKERRQ(ierr); 
00140   /*
00141   ierr = TransformObjectAddOption(cur,-7); CHKERRQ(ierr);
00142   ierr = TransformObjectAddOptionExplanation
00143     (cur,"6 iterations GMRES"); CHKERRQ(ierr); 
00144   */
00145 
00146   /*
00147    * Restricted Additive Schwarz
00148    */
00149   ierr = NewTransformObject(PREPROCESSOR,PCRASM,&cur); CHKERRQ(ierr);
00150   ierr = TransformObjectSetExplanation(cur,"Restrictied Additive Schwarz method"); CHKERRQ(ierr);
00151   ierr = TransformObjectDefineOption(cur,"local-method"); CHKERRQ(ierr);
00152   ierr = TransformObjectAddOption(cur,1); CHKERRQ(ierr);
00153   ierr = TransformObjectAddOptionExplanation(cur,1,"ILU(0)"); CHKERRQ(ierr); 
00154   ierr = TransformObjectAddOption(cur,2); CHKERRQ(ierr);
00155   ierr = TransformObjectAddOptionExplanation(cur,2,"ILU(1)"); CHKERRQ(ierr); 
00156   ierr = TransformObjectAddOption(cur,3); CHKERRQ(ierr);
00157   ierr = TransformObjectAddOptionExplanation(cur,3,"ILU(2)"); CHKERRQ(ierr); 
00158   ierr = TransformObjectAddOption(cur,-1); CHKERRQ(ierr);
00159   ierr = TransformObjectAddOptionExplanation(cur,-1,"LU"); CHKERRQ(ierr); 
00160   /*
00161   ierr = TransformObjectAddOption(cur,-7); CHKERRQ(ierr);
00162   ierr = TransformObjectAddOptionExplanation
00163     (cur,"6 iterations GMRES"); CHKERRQ(ierr); 
00164   */
00165 
00166   /*
00167    * Block Jacobi
00168    */
00169   ierr = NewTransformObject(PREPROCESSOR,PCBJACOBI,&cur); CHKERRQ(ierr);
00170   ierr = TransformObjectSetExplanation(cur,"Block Jacobi"); CHKERRQ(ierr);
00171   ierr = TransformObjectDefineOption(cur,"local-method"); CHKERRQ(ierr);
00172   ierr = TransformObjectIntAnnotate(cur,"notrans",1); CHKERRQ(ierr);
00173   ierr = TransformObjectAddOption(cur,1); CHKERRQ(ierr);
00174   ierr = TransformObjectAddOption(cur,2); CHKERRQ(ierr);
00175   ierr = TransformObjectAddOption(cur,3); CHKERRQ(ierr);
00176   ierr = TransformObjectAddOption(cur,-1); CHKERRQ(ierr);
00177   /*
00178   ierr = TransformObjectAddOption(cur,-7); CHKERRQ(ierr);
00179   */
00180 
00181   ierr = NewTransformObject(PREPROCESSOR,PCJACOBI,&cur); CHKERRQ(ierr);
00182   ierr = TransformObjectSetExplanation(cur,"Point Jacobi"); CHKERRQ(ierr);
00183   ierr = NewTransformObject(PREPROCESSOR,PCNONE,&cur); CHKERRQ(ierr);
00184   ierr = TransformObjectSetExplanation(cur,"None"); CHKERRQ(ierr);
00185   
00186   /*
00187    * Direct methods
00188    */
00189   ierr = NewTransformObject(PREPROCESSOR,PCLU,&cur); CHKERRQ(ierr);
00190   ierr = TransformObjectSetExplanation(cur,"Petsc LU"); CHKERRQ(ierr);
00191   ierr = TransformObjectIntAnnotate(cur,"directsolve",1); CHKERRQ(ierr);
00192 #if defined(PETSC_HAVE_MUMPS)
00193   ierr = NewTransformObject(PREPROCESSOR,PCMUMPS,&cur); CHKERRQ(ierr);
00194   ierr = TransformObjectSetExplanation(cur,"Mumps LU"); CHKERRQ(ierr);
00195   ierr = TransformObjectIntAnnotate(cur,"directsolve",1); CHKERRQ(ierr);
00196 #endif
00197 #if defined(PETSC_HAVE_SPOOLES)
00198   ierr = NewTransformObject(PREPROCESSOR,PCSPOOLES,&cur); CHKERRQ(ierr);
00199   ierr = TransformObjectSetExplanation(cur,"Spooles LU"); CHKERRQ(ierr);
00200   ierr = TransformObjectIntAnnotate(cur,"directsolve",1); CHKERRQ(ierr);
00201 #endif
00202 #if defined(PETSC_HAVE_SUPERLU_DIST)
00203   ierr = NewTransformObject(PREPROCESSOR,PCSUPERLU,&cur); CHKERRQ(ierr);
00204   ierr = TransformObjectSetExplanation(cur,"SuperLU LU"); CHKERRQ(ierr);
00205   ierr = TransformObjectIntAnnotate(cur,"directsolve",1); CHKERRQ(ierr);
00206 #endif
00207 #if defined(PETSC_HAVE_UMFPACK)
00208   ierr = NewTransformObject(PREPROCESSOR,PCUMFPACK,&cur); CHKERRQ(ierr);
00209   ierr = TransformObjectSetExplanation(cur,"Umfpack LU"); CHKERRQ(ierr);
00210   ierr = TransformObjectIntAnnotate(cur,"directsolve",1); CHKERRQ(ierr);
00211 #endif
00212 
00213   PetscFunctionReturn(0);
00214 }
00215 
00216 #undef __FUNCT__
00217 #define __FUNCT__ "disable_pcs"
00218 static PetscErrorCode disable_pcs
00219 (NumericalProblem theproblem,SalsaTransform pc)
00220 {
00221   SalsaTransformObject curpc; int ds;
00222   PetscBool flg; PetscErrorCode ierr;
00223   PetscFunctionBegin;
00224 
00225   ierr = SysProRetrieveQuantity
00226     (theproblem,"variance","diagonal-sign",(void*)&ds,PETSC_NULL,
00227      &flg); CHKERRQ(ierr);
00228   ierr = TransformObjectGetByName("pc","euclid",&curpc); CHKERRQ(ierr);
00229   if (0) {
00230     ierr = TransformObjectMark(curpc);  CHKERRQ(ierr);}
00231 
00232   PetscFunctionReturn(0);
00233 }
00234 
00235 #undef __FUNCT__
00236 #define __FUNCT__ "pcoptionshandling"
00237 /*! Disable certain preconditioners based on commandline options.
00238   
00239   At the moment this is only disabling of direct solvers if the 
00240   user asks for iterative only.
00241 */
00242 static PetscErrorCode pcoptionshandling()
00243 {
00244   char **names; int nnames,iname; PetscBool onlyiterative,onlydirect;
00245   PetscErrorCode ierr;
00246   PetscFunctionBegin;
00247   ierr = PetscOptionsHasName
00248     (PETSC_NULL,"-syspro_pc_iterative",&onlyiterative); CHKERRQ(ierr);
00249   ierr = PetscOptionsHasName
00250     (PETSC_NULL,"-syspro_pc_direct",&onlydirect); CHKERRQ(ierr);
00251   if (onlyiterative || onlydirect) { 
00252     ierr = RetrieveAllPreprocessorValues
00253       (PREPROCESSOR,(const char***)&names,&nnames); CHKERRQ(ierr);
00254     for (iname=0; iname<nnames; iname++) {
00255       SalsaTransformObject to; int isdirect; PetscBool flg;
00256       ierr = TransformObjectGetByName
00257         (PREPROCESSOR,names[iname],&to); CHKERRQ(ierr);
00258       ierr = TransformObjectGetIntAnnotation
00259         (to,"directsolve",&isdirect,&flg); CHKERRQ(ierr);
00260       if ( (flg && isdirect && onlyiterative) ||
00261            ( onlydirect && ( !flg || !isdirect) ) 
00262            ){
00263         ierr = TransformObjectMark(to); CHKERRQ(ierr);
00264       }
00265     }
00266   }
00267   PetscFunctionReturn(0);
00268 }
00269 
00270 #undef __FUNCT__
00271 #define __FUNCT__ "create_solver"
00272 /*! Create a solver and 
00273   install a monitor that dynamically increases the maximum
00274   number of iterations.
00275 */
00276 static PetscErrorCode create_solver(NumericalProblem prob,void **ctx)
00277 {
00278   KSP solver; PetscErrorCode ierr;
00279   PetscFunctionBegin;
00280 
00281   ierr = KSPCreate(prob->comm,&solver); CHKERRQ(ierr);
00282   /*ierr = SysProLinearInstallCustomKSPMonitor(solver); CHKERRQ(ierr);*/
00283   *(KSP*)ctx = solver;
00284 #if 0
00285   { 
00286     PC pc;
00287     ierr = PCCreate(prob->comm,&pc); CHKERRQ(ierr);
00288     *(PC*)ctx = pc;
00289   }
00290 #endif
00291   PetscFunctionReturn(0);
00292 }
00293 
00294 #undef __FUNCT__
00295 #define __FUNCT__ "destroy_solver"
00296 static PetscErrorCode destroy_solver(void *ctx)
00297 {
00298   KSP solver; PetscErrorCode ierr;
00299   PetscFunctionBegin;
00300 
00301   solver = (KSP)ctx;
00302   ierr = KSPDestroy(&solver); CHKERRQ(ierr);
00303 #if 0
00304   {
00305     PC pc;
00306     pc = (PC)ctx;
00307     ierr = PCDestroy(pc); CHKERRQ(ierr);
00308   }
00309 #endif
00310   PetscFunctionReturn(0);
00311 }
00312 
00313 #undef __FUNCT__
00314 #define __FUNCT__ "setup_pc"
00315 static PetscErrorCode setup_pc
00316 (const char *type,int pcv,PetscBool overwrite,
00317  NumericalProblem inproblem,NumericalProblem *outproblem,
00318  void *gctx,void **ctx,PetscBool *success)
00319 {
00320   LinearSystem newproblem,problem = (LinearSystem)inproblem;
00321   KSP solver; PC pc;  Mat A,B,Buse;
00322   PetscErrorCode ierr;
00323 
00324   PetscFunctionBegin;
00325   /*
00326    * handling the problem data is trivial
00327    */
00328   ierr = LinearSystemDuplicatePointers(problem,&newproblem); CHKERRQ(ierr);
00329 
00330   ierr = LinearSystemGetParts
00331     (problem,&A,&B,PETSC_NULL,PETSC_NULL,PETSC_NULL); CHKERRQ(ierr);
00332   ierr = set_preconditioner_base_matrix((PCType)type,B,&Buse); CHKERRQ(ierr);
00333   ierr = LinearSystemSetParts
00334     (newproblem,PETSC_NULL,Buse,PETSC_NULL,PETSC_NULL,PETSC_NULL); CHKERRQ(ierr);
00335   /*  ierr = PurgeAttachedArrays(A); CHKERRQ(ierr);*/
00336   ierr = PetscObjectStateIncrease((PetscObject)A); CHKERRQ(ierr);
00337 
00338   *outproblem = (NumericalProblem)newproblem;
00339   
00340   /*
00341    * the fun part is setting up the Petsc PC
00342    */
00343   solver = (KSP)gctx;
00344   ierr = KSPSetOperators(solver,A,Buse); CHKERRQ(ierr);
00345   ierr = KSPGetPC(solver,&pc); CHKERRQ(ierr);
00346 #if 0
00347   pc = (PC)gctx;
00348   ierr = PCSetOperators(pc,A,Buse,SAME_NONZERO_PATTERN); CHKERRQ(ierr);
00349 #endif
00350   ierr = SetPetscOptionsForPC(pc,(PCType)type,pcv,6); CHKERRQ(ierr);
00351   {
00352     PetscLogDouble t1,t2,*tstore; PetscErrorCode ierr_save1,ierr_save2;
00353     ierr = PetscTime(&t1); CHKERRQ(ierr);
00354     ierr = PCSetFromOptions(pc); CHKERRQ(ierr);
00355     ierr = PetscPushErrorHandler(&PetscReturnErrorHandler,NULL); CHKERRQ(ierr);
00356     ierr = PCSetUp(pc); ierr_save1 = ierr;
00357     ierr = PCSetUpOnBlocks(pc); ierr_save2 = ierr;
00358     ierr = PetscTime(&t2); CHKERRQ(ierr);
00359     ierr = PetscPopErrorHandler(); CHKERRQ(ierr);
00360     *success = TRUTH(!ierr_save1 && !ierr_save2);
00361     ierr = PreprocessorGetContext("solution",(void**)&tstore); CHKERRQ(ierr);
00362     *tstore = t2-t1;
00363   }
00364   
00365   PetscFunctionReturn(0);
00366 }
00367 
00368 #undef __FUNCT__
00369 #define __FUNCT__ "unset_pc"
00370 static PetscErrorCode unset_pc
00371 (const char *type,PetscBool overwrite,void *gctx,void *ctx,
00372  NumericalProblem thisproblem,NumericalProblem upproblem,
00373  NumericalSolution old,NumericalSolution nnew)
00374 {
00375   LinearSystem problem = (LinearSystem)thisproblem;
00376   Mat A;
00377   PetscErrorCode ierr;
00378 
00379   PetscFunctionBegin;
00380   ierr = LinearSystemGetParts
00381     (problem,&A,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL); CHKERRQ(ierr);
00382   /*  ierr = PurgeAttachedArrays(A); CHKERRQ(ierr);*/
00383   ierr = PetscObjectStateDecrease((PetscObject)A); CHKERRQ(ierr);
00384 
00385   ierr = LinearSolutionCopy
00386     ((LinearSolution)old,(LinearSolution)nnew); CHKERRQ(ierr);
00387   /*ierr = LinearSolutionDelete((LinearSolution)old); CHKERRQ(ierr);*/
00388   //ierr = DeleteLinearSystem((LinearSystem)thisproblem); CHKERRQ(ierr);
00389   PetscFunctionReturn(0);
00390 }
00391 
00392 #undef __FUNCT__
00393 #define __FUNCT__ "DeclarePCPreprocessor"
00394 PetscErrorCode DeclarePCPreprocessor(void)
00395 {
00396   SystemPreprocessor pp; PetscErrorCode ierr;
00397   PetscFunctionBegin;
00398   ierr = DeclarePreprocessor
00399     (PREPROCESSOR,
00400      &setup_pc_choices,&disable_pcs,0,0,
00401      &create_solver,&destroy_solver,
00402      &setup_pc,&unset_pc); CHKERRQ(ierr);
00403   ierr = PreprocessorSetPreservedCategories
00404     (PREPROCESSOR,"laplace"); CHKERRQ(ierr);
00405   ierr = SystemPreprocessorGetByName(PREPROCESSOR,&pp); CHKERRQ(ierr);
00406   pp->optionshandling = &pcoptionshandling;
00407   PetscFunctionReturn(0);
00408 }