Commits

Jed Brown committed 3630d66 Merge

Merge branch 'madams/gamg-aggoptions'

More delegation and less method-overriding.

* madams/gamg-aggoptions:
PCGAMG: call subtype destroy from PCDestroy_GAMG
PCGAMG: move subtype pointers to _PCGAMGOps.
PCGAMG: set subtype in PCSetFromOptions_GAMG instead of PCCreate_GAMG

Comments (0)

Files changed (4)

src/ksp/pc/impls/gamg/agg.c

   PetscBool      flag;
 
   PetscFunctionBegin;
-  /* call base class */
-  ierr = PCSetFromOptions_GAMG(pc);CHKERRQ(ierr);
 
   ierr = PetscOptionsHead("GAMG-AGG options");CHKERRQ(ierr);
   {
    . pc -
 */
 #undef __FUNCT__
-#define __FUNCT__ "PCDestroy_AGG"
-PetscErrorCode PCDestroy_AGG(PC pc)
+#define __FUNCT__ "PCDestroy_GAMG_AGG"
+PetscErrorCode PCDestroy_GAMG_AGG(PC pc)
 {
   PetscErrorCode ierr;
   PC_MG          *mg          = (PC_MG*)pc->data;
   PC_GAMG        *pc_gamg     = (PC_GAMG*)mg->innerctx;
-  PC_GAMG_AGG    *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx;
 
   PetscFunctionBegin;
-  if (pc_gamg_agg) {
-    ierr        = PetscFree(pc_gamg_agg);CHKERRQ(ierr);
-    pc_gamg_agg = 0;
-  }
-
-  /* call base class */
-  ierr = PCDestroy_GAMG(pc);CHKERRQ(ierr);
+  ierr = PetscFree(pc_gamg->subctx);CHKERRQ(ierr);
   PetscFunctionReturn(0);
 }
 
   PC_GAMG_AGG    *pc_gamg_agg;
 
   PetscFunctionBegin;
-  if (pc_gamg->subctx) {
-    /* call base class */
-    ierr = PCDestroy_GAMG(pc);CHKERRQ(ierr);
-  }
-
   /* create sub context for SA */
   ierr            = PetscNewLog(pc, PC_GAMG_AGG, &pc_gamg_agg);CHKERRQ(ierr);
   pc_gamg->subctx = pc_gamg_agg;
 
-  pc->ops->setfromoptions = PCSetFromOptions_GAMG_AGG;
-  pc->ops->destroy        = PCDestroy_AGG;
+  pc_gamg->ops->setfromoptions = PCSetFromOptions_GAMG_AGG;
+  pc_gamg->ops->destroy        = PCDestroy_GAMG_AGG;
   /* reset does not do anything; setup not virtual */
 
   /* set internal function pointers */
-  pc_gamg->graph       = PCGAMGgraph_AGG;
-  pc_gamg->coarsen     = PCGAMGCoarsen_AGG;
-  pc_gamg->prolongator = PCGAMGProlongator_AGG;
-  pc_gamg->optprol     = PCGAMGOptprol_AGG;
-  pc_gamg->formkktprol = PCGAMGKKTProl_AGG;
+  pc_gamg->ops->graph       = PCGAMGgraph_AGG;
+  pc_gamg->ops->coarsen     = PCGAMGCoarsen_AGG;
+  pc_gamg->ops->prolongator = PCGAMGProlongator_AGG;
+  pc_gamg->ops->optprol     = PCGAMGOptprol_AGG;
+  pc_gamg->ops->formkktprol = PCGAMGKKTProl_AGG;
 
-  pc_gamg->createdefaultdata = PCSetData_AGG;
+  pc_gamg->ops->createdefaultdata = PCSetData_AGG;
 
   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_AGG);CHKERRQ(ierr);
   PetscFunctionReturn(0);

src/ksp/pc/impls/gamg/gamg.c

       ierr = PetscMalloc(pc_gamg->data_sz*sizeof(PetscReal), &pc_gamg->data);CHKERRQ(ierr);
       for (qq=0; qq<pc_gamg->data_sz; qq++) pc_gamg->data[qq] = pc_gamg->orig_data[qq];
     } else {
-      if (!pc_gamg->createdefaultdata) SETERRQ(comm,PETSC_ERR_PLIB,"'createdefaultdata' not set(?) need to support NULL data");
+      if (!pc_gamg->ops->createdefaultdata) SETERRQ(comm,PETSC_ERR_PLIB,"'createdefaultdata' not set(?) need to support NULL data");
       if (stokes) SETERRQ(comm,PETSC_ERR_PLIB,"Need data (eg, PCSetCoordinates) for Stokes problems");
-      ierr = pc_gamg->createdefaultdata(pc, kktMatsArr[0].A11);CHKERRQ(ierr);
+      ierr = pc_gamg->ops->createdefaultdata(pc, kktMatsArr[0].A11);CHKERRQ(ierr);
     }
   }
 
       PetscCoarsenData *agg_lists;
       Mat              Prol11,Prol22;
 
-      ierr = pc_gamg->graph(pc,kktMatsArr[level].A11, &Gmat);CHKERRQ(ierr);
-      ierr = pc_gamg->coarsen(pc, &Gmat, &agg_lists);CHKERRQ(ierr);
-      ierr = pc_gamg->prolongator(pc, kktMatsArr[level].A11, Gmat, agg_lists, &Prol11);CHKERRQ(ierr);
+      ierr = pc_gamg->ops->graph(pc,kktMatsArr[level].A11, &Gmat);CHKERRQ(ierr);
+      ierr = pc_gamg->ops->coarsen(pc, &Gmat, &agg_lists);CHKERRQ(ierr);
+      ierr = pc_gamg->ops->prolongator(pc, kktMatsArr[level].A11, Gmat, agg_lists, &Prol11);CHKERRQ(ierr);
 
       /* could have failed to create new level */
       if (Prol11) {
         ierr = MatGetBlockSizes(Prol11, NULL, &bs);CHKERRQ(ierr);
 
         if (stokes) {
-          if (!pc_gamg->formkktprol) SETERRQ(comm,PETSC_ERR_USER,"Stokes not supportd by AMG method.");
+          if (!pc_gamg->ops->formkktprol) SETERRQ(comm,PETSC_ERR_USER,"Stokes not supportd by AMG method.");
           /* R A12 == (T = A21 P)';  G = T' T; coarsen G; form plain agg with G */
-          ierr = pc_gamg->formkktprol(pc, Prol11, kktMatsArr[level].A21, &Prol22);CHKERRQ(ierr);
+          ierr = pc_gamg->ops->formkktprol(pc, Prol11, kktMatsArr[level].A21, &Prol22);CHKERRQ(ierr);
         }
 
-        if (pc_gamg->optprol) {
+        if (pc_gamg->ops->optprol) {
           /* smooth */
-          ierr = pc_gamg->optprol(pc, kktMatsArr[level].A11, &Prol11);CHKERRQ(ierr);
+          ierr = pc_gamg->ops->optprol(pc, kktMatsArr[level].A11, &Prol11);CHKERRQ(ierr);
         }
 
         if (stokes) {
 
   PetscFunctionBegin;
   ierr = PCReset_GAMG(pc);CHKERRQ(ierr);
+  if (pc_gamg->ops->destroy) {
+    ierr = (*pc_gamg->ops->destroy)(pc);CHKERRQ(ierr);
+  }
+  ierr = PetscFree(pc_gamg->ops);CHKERRQ(ierr);
+  ierr = PetscFree(pc_gamg->gamg_type_name);CHKERRQ(ierr);
   ierr = PetscFree(pc_gamg);CHKERRQ(ierr);
   ierr = PCDestroy_MG(pc);CHKERRQ(ierr);
   PetscFunctionReturn(0);
 static PetscErrorCode PCGAMGSetType_GAMG(PC pc, PCGAMGType type)
 {
   PetscErrorCode ierr,(*r)(PC);
+  PC_MG          *mg      = (PC_MG*)pc->data;
+  PC_GAMG        *pc_gamg = (PC_GAMG*)mg->innerctx;
 
   PetscFunctionBegin;
   ierr = PetscFunctionListFind(GAMGList,type,&r);CHKERRQ(ierr);
   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown GAMG type %s given",type);
+  if (pc_gamg->ops->destroy) {
+    ierr = (*pc_gamg->ops->destroy)(pc);CHKERRQ(ierr);
+    ierr = PetscMemzero(pc_gamg->ops,sizeof(struct _PCGAMGOps));CHKERRQ(ierr);
+  }
+  ierr = PetscFree(pc_gamg->gamg_type_name);CHKERRQ(ierr);
+  ierr = PetscStrallocpy(type,&pc_gamg->gamg_type_name);CHKERRQ(ierr);
   ierr = (*r)(pc);CHKERRQ(ierr);
   PetscFunctionReturn(0);
 }
   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
   ierr = PetscOptionsHead("GAMG options");CHKERRQ(ierr);
   {
+    /* -pc_gamg_type */
+    {
+      char tname[256] = PCGAMGAGG;
+      const char *deftype = pc_gamg->gamg_type_name ? pc_gamg->gamg_type_name : tname;
+      ierr = PetscOptionsList("-pc_gamg_type","Type of AMG method","PCGAMGSetType",GAMGList, tname, tname, sizeof(tname), &flag);CHKERRQ(ierr);
+      /* call PCCreateGAMG_XYZ */
+      if (flag || !pc_gamg->gamg_type_name) {
+        ierr = PCGAMGSetType(pc, flag ? tname : deftype);CHKERRQ(ierr);
+      }
+    }
     /* -pc_gamg_verbose */
     ierr = PetscOptionsInt("-pc_gamg_verbose","Verbose (debugging) output for PCGAMG",
                            "none", pc_gamg->verbose,
     if (flag && pc_gamg->verbose) {
       ierr = PetscPrintf(comm,"\t[%d]%s threshold set %e\n",0,__FUNCT__,pc_gamg->threshold);CHKERRQ(ierr);
     }
-
+    /* -pc_gamg_eigtarget */
     ierr = PetscOptionsRealArray("-pc_gamg_eigtarget","Target eigenvalue range as fraction of estimated maximum eigenvalue","PCGAMGSetEigTarget",pc_gamg->eigtarget,&two,NULL);CHKERRQ(ierr);
     ierr = PetscOptionsInt("-pc_mg_levels",
                            "Set number of MG levels",
                            pc_gamg->Nlevels,
                            &pc_gamg->Nlevels,
                            &flag);CHKERRQ(ierr);
+
+    /* set options for subtype */
+    if (pc_gamg->ops->setfromoptions) {ierr = (*pc_gamg->ops->setfromoptions)(pc);CHKERRQ(ierr);}
   }
   ierr = PetscOptionsTail();CHKERRQ(ierr);
   PetscFunctionReturn(0);
   mg->galerkin = 2;             /* Use Galerkin, but it is computed externally */
   mg->innerctx = pc_gamg;
 
+  ierr = PetscNewLog(pc,struct _PCGAMGOps,&pc_gamg->ops);CHKERRQ(ierr);
+
   pc_gamg->setup_count = 0;
   /* these should be in subctx but repartitioning needs simple arrays */
   pc_gamg->data_sz = 0;
   ierr = PetscLogEventRegister("GAMGKKTProl_AGG", PC_CLASSID, &PC_GAMGKKTProl_AGG);CHKERRQ(ierr);
 #endif
 
-  /* instantiate derived type */
-  ierr = PetscOptionsHead("GAMG options");CHKERRQ(ierr);
-  {
-    char tname[256] = PCGAMGAGG;
-    ierr = PetscOptionsList("-pc_gamg_type","Type of GAMG method","PCGAMGSetType",GAMGList, tname, tname, sizeof(tname), NULL);CHKERRQ(ierr);
-    ierr = PCGAMGSetType(pc, tname);CHKERRQ(ierr);
-  }
-  ierr = PetscOptionsTail();CHKERRQ(ierr);
   PetscFunctionReturn(0);
 }
 

src/ksp/pc/impls/gamg/gamg.h

 #include <../src/mat/impls/aij/seq/aij.h>
 #include <../src/mat/impls/aij/mpi/mpiaij.h>
 
+struct _PCGAMGOps {
+  PetscErrorCode (*graph)(PC, const Mat, Mat*);
+  PetscErrorCode (*coarsen)(PC, Mat*, PetscCoarsenData**);
+  PetscErrorCode (*prolongator)(PC, const Mat, const Mat, PetscCoarsenData*, Mat*);
+  PetscErrorCode (*optprol)(PC, const Mat, Mat*);
+  PetscErrorCode (*formkktprol)(PC, const Mat, const Mat, Mat*);
+  PetscErrorCode (*createdefaultdata)(PC, Mat); /* for data methods that have a default (SA) */
+  PetscErrorCode (*setfromoptions)(PC);
+  PetscErrorCode (*destroy)(PC);
+};
+
 /* Private context for the GAMG preconditioner */
 typedef struct gamg_TAG {
   PetscInt  Nlevels;
   PetscReal *data;          /* [data_sz] blocked vector of vertex data on fine grid (coordinates/nullspace) */
   PetscReal *orig_data;          /* cache data */
 
-  PetscErrorCode (*graph)(PC, const Mat, Mat*);
-  PetscErrorCode (*coarsen)(PC, Mat*, PetscCoarsenData**);
-  PetscErrorCode (*prolongator)(PC, const Mat, const Mat, PetscCoarsenData*, Mat*);
-  PetscErrorCode (*optprol)(PC, const Mat, Mat*);
-  PetscErrorCode (*formkktprol)(PC, const Mat, const Mat, Mat*);
-  PetscErrorCode (*createdefaultdata)(PC, Mat); /* for data methods that have a default (SA) */
+  struct _PCGAMGOps *ops;
+  char *gamg_type_name;
 
   void *subctx;
 } PC_GAMG;

src/ksp/pc/impls/gamg/geo.c

   }
   ierr = PetscOptionsTail();CHKERRQ(ierr);
 
-  /* call base class */
-  ierr = PCSetFromOptions_GAMG(pc);CHKERRQ(ierr);
-
   if (pc_gamg->verbose) {
     PetscPrintf(PetscObjectComm((PetscObject)pc),"[%d]%s done\n",0,__FUNCT__);
   }
   PetscFunctionReturn(0);
 }
 
+#undef __FUNCT__
+#define __FUNCT__ "PCDestroy_GAMG_GEO"
+static PetscErrorCode PCDestroy_GAMG_GEO(PC pc)
+{
+  PetscErrorCode ierr;
+
+  PetscFunctionBegin;
+  ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL);CHKERRQ(ierr);
+  PetscFunctionReturn(0);
+}
+
 /* -------------------------------------------------------------------------- */
 /*
  PCCreateGAMG_GEO
   PC_GAMG        *pc_gamg = (PC_GAMG*)mg->innerctx;
 
   PetscFunctionBegin;
-  pc->ops->setfromoptions = PCSetFromOptions_GEO;
-  /* pc->ops->destroy        = PCDestroy_GEO; */
+  pc_gamg->ops->setfromoptions = PCSetFromOptions_GEO;
+  pc_gamg->ops->destroy        = PCDestroy_GAMG_GEO;
   /* reset does not do anything; setup not virtual */
 
   /* set internal function pointers */
-  pc_gamg->graph       = PCGAMGgraph_GEO;
-  pc_gamg->coarsen     = PCGAMGcoarsen_GEO;
-  pc_gamg->prolongator = PCGAMGProlongator_GEO;
-  pc_gamg->optprol     = 0;
-  pc_gamg->formkktprol = 0;
-
-  pc_gamg->createdefaultdata = PCSetData_GEO;
+  pc_gamg->ops->graph       = PCGAMGgraph_GEO;
+  pc_gamg->ops->coarsen     = PCGAMGcoarsen_GEO;
+  pc_gamg->ops->prolongator = PCGAMGProlongator_GEO;
+  pc_gamg->ops->optprol     = 0;
+  pc_gamg->ops->formkktprol = 0;
+  pc_gamg->ops->createdefaultdata = PCSetData_GEO;
 
   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_GEO);CHKERRQ(ierr);
   PetscFunctionReturn(0);