1*5b89ad90SMark F. Adams /* 2*5b89ad90SMark F. Adams GAMG geometric-algebric multiogrid PC - Mark Adams 2011 3*5b89ad90SMark F. Adams */ 4*5b89ad90SMark F. Adams #include <private/pcimpl.h> /*I "petscpc.h" I*/ 5*5b89ad90SMark F. Adams #include <../src/ksp/pc/impls/mg/mgimpl.h> /*I "petscpcmg.h" I*/ 6*5b89ad90SMark F. Adams #include <../src/mat/impls/aij/seq/aij.h> 7*5b89ad90SMark F. Adams #include <../src/mat/impls/aij/mpi/mpiaij.h> 8*5b89ad90SMark F. Adams 9*5b89ad90SMark F. Adams /* Private context for the GAMG preconditioner */ 10*5b89ad90SMark F. Adams typedef struct gamg_TAG { 11*5b89ad90SMark F. Adams gamg_TAG() : m_dim(0), m_Nlevels(-1), m_data(0) 12*5b89ad90SMark F. Adams {} 13*5b89ad90SMark F. Adams PetscInt m_dim; 14*5b89ad90SMark F. Adams PetscInt m_Nlevels; 15*5b89ad90SMark F. Adams PetscInt m_data_sz; 16*5b89ad90SMark F. Adams PetscReal *m_data; /* blocked vector of vertex data on fine grid (coordinates) */ 17*5b89ad90SMark F. Adams } PC_GAMG; 18*5b89ad90SMark F. Adams 19*5b89ad90SMark F. Adams /* -----------------------------------------------------------------------------*/ 20*5b89ad90SMark F. Adams #undef __FUNCT__ 21*5b89ad90SMark F. Adams #define __FUNCT__ "PCReset_GAMG" 22*5b89ad90SMark F. Adams PetscErrorCode PCReset_GAMG(PC pc) 23*5b89ad90SMark F. Adams { 24*5b89ad90SMark F. Adams PetscErrorCode ierr; 25*5b89ad90SMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 26*5b89ad90SMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 27*5b89ad90SMark F. Adams 28*5b89ad90SMark F. Adams PetscFunctionBegin; 29*5b89ad90SMark F. Adams if (pc_gamg->m_data) { 30*5b89ad90SMark F. Adams ierr = PetscFree(pc_gamg->m_data);CHKERRQ(ierr); 31*5b89ad90SMark F. Adams pc_gamg->m_data = 0; 32*5b89ad90SMark F. Adams } 33*5b89ad90SMark F. Adams PetscFunctionReturn(0); 34*5b89ad90SMark F. Adams } 35*5b89ad90SMark F. Adams 36*5b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */ 37*5b89ad90SMark F. Adams /* 38*5b89ad90SMark F. Adams PCSetCoordinates_GAMG 39*5b89ad90SMark F. Adams 40*5b89ad90SMark F. Adams Input Parameter: 41*5b89ad90SMark F. Adams . pc - the preconditioner context 42*5b89ad90SMark F. Adams */ 43*5b89ad90SMark F. Adams #undef __FUNCT__ 44*5b89ad90SMark F. Adams #define __FUNCT__ "PCSetCoordinates_GAMG" 45*5b89ad90SMark F. Adams PetscErrorCode PCSetCoordinates_GAMG( PC pc, const int ndm, 46*5b89ad90SMark F. Adams PetscReal *coords ) 47*5b89ad90SMark F. Adams { 48*5b89ad90SMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 49*5b89ad90SMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 50*5b89ad90SMark F. Adams PetscErrorCode ierr; PetscInt bs, my0, tt; 51*5b89ad90SMark F. Adams 52*5b89ad90SMark F. Adams PetscFunctionBegin; 53*5b89ad90SMark F. Adams Mat mat = pc->pmat; 54*5b89ad90SMark F. Adams ierr = MatGetBlockSize( mat, &bs ); CHKERRQ( ierr ); 55*5b89ad90SMark F. Adams ierr = MatGetOwnershipRange( mat, &my0, &tt ); CHKERRQ(ierr); 56*5b89ad90SMark F. Adams const PetscInt arrsz = (tt-my0)/bs*ndm; 57*5b89ad90SMark F. Adams 58*5b89ad90SMark F. Adams // put coordinates 59*5b89ad90SMark F. Adams if ( pc_gamg->m_data==0 || pc_gamg->m_data_sz != arrsz ) { 60*5b89ad90SMark F. Adams if( pc_gamg->m_data != 0 ) { 61*5b89ad90SMark F. Adams ierr = PetscFree( pc_gamg->m_data ); CHKERRQ(ierr); 62*5b89ad90SMark F. Adams } 63*5b89ad90SMark F. Adams ierr = PetscMalloc( (arrsz+1)*sizeof(double), &pc_gamg->m_data ); CHKERRQ(ierr); 64*5b89ad90SMark F. Adams } 65*5b89ad90SMark F. Adams 66*5b89ad90SMark F. Adams /* copy data in */ 67*5b89ad90SMark F. Adams for(tt=0;tt<arrsz;tt++){ 68*5b89ad90SMark F. Adams pc_gamg->m_data[tt] = coords[tt]; 69*5b89ad90SMark F. Adams } 70*5b89ad90SMark F. Adams pc_gamg->m_data_sz = arrsz; 71*5b89ad90SMark F. Adams pc_gamg->m_dim = ndm; 72*5b89ad90SMark F. Adams 73*5b89ad90SMark F. Adams PetscFunctionReturn(0); 74*5b89ad90SMark F. Adams } 75*5b89ad90SMark F. Adams 76*5b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */ 77*5b89ad90SMark F. Adams /* 78*5b89ad90SMark F. Adams createCrsOp 79*5b89ad90SMark F. Adams 80*5b89ad90SMark F. Adams Input Parameter: 81*5b89ad90SMark F. Adams . Amat - matrix on this fine level 82*5b89ad90SMark F. Adams . P_out - prolongation operator to the next level 83*5b89ad90SMark F. Adams . Acrs - coarse matrix that is created 84*5b89ad90SMark F. Adams */ 85*5b89ad90SMark F. Adams #undef __FUNCT__ 86*5b89ad90SMark F. Adams #define __FUNCT__ "createCrsOp" 87*5b89ad90SMark F. Adams PetscErrorCode createCrsOp( Mat Amat, Mat P_inout, Mat *Acrs ) 88*5b89ad90SMark F. Adams { 89*5b89ad90SMark F. Adams PetscErrorCode ierr; 90*5b89ad90SMark F. Adams 91*5b89ad90SMark F. Adams PetscFunctionBegin; 92*5b89ad90SMark F. Adams Mat H; 93*5b89ad90SMark F. Adams ierr = MatPtAP( Amat, P_inout, MAT_INITIAL_MATRIX, 2.0, &H); CHKERRQ(ierr); 94*5b89ad90SMark F. Adams *Acrs = H; 95*5b89ad90SMark F. Adams 96*5b89ad90SMark F. Adams PetscFunctionReturn(0); 97*5b89ad90SMark F. Adams } 98*5b89ad90SMark F. Adams 99*5b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */ 100*5b89ad90SMark F. Adams /* 101*5b89ad90SMark F. Adams PCSetUp_GAMG - Prepares for the use of the GAMG preconditioner 102*5b89ad90SMark F. Adams by setting data structures and options. 103*5b89ad90SMark F. Adams 104*5b89ad90SMark F. Adams Input Parameter: 105*5b89ad90SMark F. Adams . pc - the preconditioner context 106*5b89ad90SMark F. Adams 107*5b89ad90SMark F. Adams Application Interface Routine: PCSetUp() 108*5b89ad90SMark F. Adams 109*5b89ad90SMark F. Adams Notes: 110*5b89ad90SMark F. Adams The interface routine PCSetUp() is not usually called directly by 111*5b89ad90SMark F. Adams the user, but instead is called by PCApply() if necessary. 112*5b89ad90SMark F. Adams */ 113*5b89ad90SMark F. Adams extern PetscErrorCode PCSetFromOptions_MG(PC); 114*5b89ad90SMark F. Adams extern PetscErrorCode PCReset_MG(PC); 115*5b89ad90SMark F. Adams extern PetscErrorCode createProlongation( Mat, Mat *, PetscReal [], PetscReal **, const PetscInt); 116*5b89ad90SMark F. Adams #undef __FUNCT__ 117*5b89ad90SMark F. Adams #define __FUNCT__ "PCSetUp_GAMG" 118*5b89ad90SMark F. Adams PetscErrorCode PCSetUp_GAMG( PC pc ) 119*5b89ad90SMark F. Adams { 120*5b89ad90SMark F. Adams PetscErrorCode ierr; 121*5b89ad90SMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 122*5b89ad90SMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 123*5b89ad90SMark F. Adams Mat Amat = pc->mat, Pmat = pc->pmat; 124*5b89ad90SMark F. Adams PetscBool isSeq, isMPI; 125*5b89ad90SMark F. Adams PetscInt fine_level, level, level1, M, N, bs, lidx; 126*5b89ad90SMark F. Adams MPI_Comm wcomm = ((PetscObject)pc)->comm; 127*5b89ad90SMark F. Adams 128*5b89ad90SMark F. Adams PetscFunctionBegin; 129*5b89ad90SMark F. Adams if (pc->setupcalled){ 130*5b89ad90SMark F. Adams /* no state data in GAMG to destroy (now) */ 131*5b89ad90SMark F. Adams ierr = PCReset_MG(pc);CHKERRQ(ierr); 132*5b89ad90SMark F. Adams } 133*5b89ad90SMark F. Adams if ( pc_gamg->m_data==0 ) { 134*5b89ad90SMark F. Adams SETERRQ(wcomm,PETSC_ERR_SUP,"PCSetUp_GAMG called before PCSetCoordinates"); 135*5b89ad90SMark F. Adams } 136*5b89ad90SMark F. Adams /* setup special features of PCGAMG */ 137*5b89ad90SMark F. Adams ierr = PetscTypeCompare((PetscObject) Amat, MATSEQAIJ, &isSeq);CHKERRQ(ierr); 138*5b89ad90SMark F. Adams ierr = PetscTypeCompare((PetscObject) Amat, MATMPIAIJ, &isMPI);CHKERRQ(ierr); 139*5b89ad90SMark F. Adams if (isMPI) { 140*5b89ad90SMark F. Adams } else if (isSeq) { 141*5b89ad90SMark F. Adams } else SETERRQ1(wcomm,PETSC_ERR_ARG_WRONG, "Matrix type '%s' cannot be used with GAMG. GAMG can only handle AIJ matrices.",((PetscObject)Amat)->type_name); 142*5b89ad90SMark F. Adams 143*5b89ad90SMark F. Adams /* GAMG requires input of fine-grid matrix. It determines nlevels. */ 144*5b89ad90SMark F. Adams ierr = MatGetSize( Amat, &M, &N );CHKERRQ(ierr); 145*5b89ad90SMark F. Adams ierr = MatGetBlockSize( Amat, &bs ); CHKERRQ(ierr); 146*5b89ad90SMark F. Adams if(bs!=1) SETERRQ1(wcomm,PETSC_ERR_ARG_WRONG, "GAMG only supports scalar prblems bs = '%d'.",bs); 147*5b89ad90SMark F. Adams 148*5b89ad90SMark F. Adams /* Get A_i and R_i */ 149*5b89ad90SMark F. Adams #define GAMG_MAXLEVELS 10 150*5b89ad90SMark F. Adams Mat Aarr[GAMG_MAXLEVELS], Rarr[GAMG_MAXLEVELS]; PetscReal *coarse_crds = 0, *crds = pc_gamg->m_data; 151*5b89ad90SMark F. Adams for (level=0, Aarr[0] = Pmat; level < GAMG_MAXLEVELS-1; level++ ){ 152*5b89ad90SMark F. Adams ierr = MatGetSize( Aarr[level], &M, &N );CHKERRQ(ierr); 153*5b89ad90SMark F. Adams if( M < 100 ) { /* hard wire this for now */ 154*5b89ad90SMark F. Adams break; 155*5b89ad90SMark F. Adams } 156*5b89ad90SMark F. Adams level1 = level + 1; 157*5b89ad90SMark F. Adams ierr = createProlongation( Aarr[level], &Rarr[level1], crds, &coarse_crds, pc_gamg->m_dim ); 158*5b89ad90SMark F. Adams CHKERRQ(ierr); 159*5b89ad90SMark F. Adams if(level==0) Aarr[0] = Amat; /* use Pmat for finest level setup, but use mat for solver */ 160*5b89ad90SMark F. Adams ierr = createCrsOp( Aarr[level], Rarr[level1], &Aarr[level1] ); CHKERRQ(ierr); 161*5b89ad90SMark F. Adams ierr = PetscFree( crds ); CHKERRQ( ierr ); 162*5b89ad90SMark F. Adams crds = coarse_crds; 163*5b89ad90SMark F. Adams } 164*5b89ad90SMark F. Adams if( coarse_crds != 0 ) { 165*5b89ad90SMark F. Adams ierr = PetscFree( coarse_crds ); CHKERRQ( ierr ); 166*5b89ad90SMark F. Adams } 167*5b89ad90SMark F. Adams pc_gamg->m_data = 0; /* destroyed coordinate data */ 168*5b89ad90SMark F. Adams pc_gamg->m_Nlevels = level + 1; 169*5b89ad90SMark F. Adams fine_level = level; 170*5b89ad90SMark F. Adams ierr = PCMGSetLevels(pc,pc_gamg->m_Nlevels,PETSC_NULL);CHKERRQ(ierr); 171*5b89ad90SMark F. Adams 172*5b89ad90SMark F. Adams /* set default smoothers */ 173*5b89ad90SMark F. Adams PetscReal emax = 2.0, emin; 174*5b89ad90SMark F. Adams for (level=1; level<=fine_level; level++){ 175*5b89ad90SMark F. Adams KSP smoother; PC subpc; 176*5b89ad90SMark F. Adams ierr = PCMGGetSmoother(pc,level,&smoother);CHKERRQ(ierr); 177*5b89ad90SMark F. Adams ierr = KSPSetType(smoother,KSPCHEBYCHEV);CHKERRQ(ierr); 178*5b89ad90SMark F. Adams emin = emax/5.0; 179*5b89ad90SMark F. Adams ierr = KSPGetPC(smoother,&subpc);CHKERRQ(ierr); 180*5b89ad90SMark F. Adams ierr = PCSetType(subpc,PCJACOBI);CHKERRQ(ierr); 181*5b89ad90SMark F. Adams ierr = KSPChebychevSetEigenvalues(smoother, emax, emin);CHKERRQ(ierr); /* need auto !!!!*/ 182*5b89ad90SMark F. Adams } 183*5b89ad90SMark F. Adams ierr = PCSetFromOptions_MG(pc); CHKERRQ(ierr); /* should be called in PCSetFromOptions_GAMG(), but cannot be called prior to PCMGSetLevels() */ 184*5b89ad90SMark F. Adams { 185*5b89ad90SMark F. Adams PetscBool galerkin; 186*5b89ad90SMark F. Adams ierr = PCMGGetGalerkin( pc, &galerkin); CHKERRQ(ierr); 187*5b89ad90SMark F. Adams if(galerkin){ 188*5b89ad90SMark F. Adams SETERRQ(wcomm,PETSC_ERR_ARG_WRONG, "GAMG does galerkin manually so it must not be used in PC_MG."); 189*5b89ad90SMark F. Adams } 190*5b89ad90SMark F. Adams } 191*5b89ad90SMark F. Adams /* create coarse level and the interpolation between the levels */ 192*5b89ad90SMark F. Adams for (level=0,lidx=pc_gamg->m_Nlevels-1; level<fine_level; level++,lidx--){ 193*5b89ad90SMark F. Adams level1 = level + 1; 194*5b89ad90SMark F. Adams /* PetscInt MM,NN; */ 195*5b89ad90SMark F. Adams /* ierr = MatGetSize( Rarr[lidx], &MM, &NN );CHKERRQ(ierr); */ 196*5b89ad90SMark F. Adams /* PetscPrintf(PETSC_COMM_WORLD,"%s Set P(%d,%d) on level %d (%d)\n",__FUNCT__,MM,NN,level1,lidx); */ 197*5b89ad90SMark F. Adams ierr = PCMGSetInterpolation(pc,level1,Rarr[lidx]);CHKERRQ(ierr); 198*5b89ad90SMark F. Adams if(!true) { 199*5b89ad90SMark F. Adams PetscViewer viewer; 200*5b89ad90SMark F. Adams ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF, "Rmat.m", &viewer); CHKERRQ(ierr); 201*5b89ad90SMark F. Adams ierr = PetscViewerSetFormat( viewer, PETSC_VIEWER_ASCII_MATLAB); CHKERRQ(ierr); 202*5b89ad90SMark F. Adams ierr = MatView(Rarr[level1],viewer);CHKERRQ(ierr); 203*5b89ad90SMark F. Adams ierr = PetscViewerDestroy( &viewer ); 204*5b89ad90SMark F. Adams } 205*5b89ad90SMark F. Adams KSP smoother; 206*5b89ad90SMark F. Adams ierr = PCMGGetSmoother(pc,level,&smoother); CHKERRQ(ierr); 207*5b89ad90SMark F. Adams ierr = KSPSetOperators( smoother, Aarr[lidx], Aarr[lidx], DIFFERENT_NONZERO_PATTERN ); 208*5b89ad90SMark F. Adams CHKERRQ(ierr); 209*5b89ad90SMark F. Adams /* ierr = MatGetSize( Aarr[lidx], &MM, &NN ); CHKERRQ(ierr); */ 210*5b89ad90SMark F. Adams /* PetscPrintf(PETSC_COMM_WORLD,"%s Set A(%d,%d) on level %d (%d)\n",__FUNCT__,MM,NN,level,lidx); */ 211*5b89ad90SMark F. Adams } 212*5b89ad90SMark F. Adams { /* fine level (no P) */ 213*5b89ad90SMark F. Adams KSP smoother; 214*5b89ad90SMark F. Adams ierr = PCMGGetSmoother(pc,fine_level,&smoother); CHKERRQ(ierr); 215*5b89ad90SMark F. Adams ierr = KSPSetOperators( smoother, Aarr[0], Aarr[0], DIFFERENT_NONZERO_PATTERN ); 216*5b89ad90SMark F. Adams CHKERRQ(ierr); 217*5b89ad90SMark F. Adams /* PetscInt MM,NN; */ 218*5b89ad90SMark F. Adams /* ierr = MatGetSize( Aarr[0], &MM, &NN );CHKERRQ(ierr); */ 219*5b89ad90SMark F. Adams /* PetscPrintf(PETSC_COMM_WORLD,"%s Set A(%d,%d) on level %d (%d)\n",__FUNCT__,MM,NN,fine_level,0); */ 220*5b89ad90SMark F. Adams } 221*5b89ad90SMark F. Adams 222*5b89ad90SMark F. Adams /* setupcalled is set to 0 so that MG is setup from scratch */ 223*5b89ad90SMark F. Adams pc->setupcalled = 0; 224*5b89ad90SMark F. Adams ierr = PCSetUp_MG(pc);CHKERRQ(ierr); 225*5b89ad90SMark F. Adams PetscFunctionReturn(0); 226*5b89ad90SMark F. Adams } 227*5b89ad90SMark F. Adams 228*5b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */ 229*5b89ad90SMark F. Adams /* 230*5b89ad90SMark F. Adams PCDestroy_GAMG - Destroys the private context for the GAMG preconditioner 231*5b89ad90SMark F. Adams that was created with PCCreate_GAMG(). 232*5b89ad90SMark F. Adams 233*5b89ad90SMark F. Adams Input Parameter: 234*5b89ad90SMark F. Adams . pc - the preconditioner context 235*5b89ad90SMark F. Adams 236*5b89ad90SMark F. Adams Application Interface Routine: PCDestroy() 237*5b89ad90SMark F. Adams */ 238*5b89ad90SMark F. Adams #undef __FUNCT__ 239*5b89ad90SMark F. Adams #define __FUNCT__ "PCDestroy_GAMG" 240*5b89ad90SMark F. Adams PetscErrorCode PCDestroy_GAMG(PC pc) 241*5b89ad90SMark F. Adams { 242*5b89ad90SMark F. Adams PetscErrorCode ierr; 243*5b89ad90SMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 244*5b89ad90SMark F. Adams PC_GAMG *pc_gamg= (PC_GAMG*)mg->innerctx; 245*5b89ad90SMark F. Adams 246*5b89ad90SMark F. Adams PetscFunctionBegin; 247*5b89ad90SMark F. Adams ierr = PCReset_GAMG(pc);CHKERRQ(ierr); 248*5b89ad90SMark F. Adams if (pc_gamg->m_data) { 249*5b89ad90SMark F. Adams ierr = PetscFree(pc_gamg->m_data);CHKERRQ(ierr); 250*5b89ad90SMark F. Adams } 251*5b89ad90SMark F. Adams ierr = PetscFree(pc_gamg);CHKERRQ(ierr); 252*5b89ad90SMark F. Adams ierr = PCDestroy_MG(pc);CHKERRQ(ierr); 253*5b89ad90SMark F. Adams PetscFunctionReturn(0); 254*5b89ad90SMark F. Adams } 255*5b89ad90SMark F. Adams 256*5b89ad90SMark F. Adams #undef __FUNCT__ 257*5b89ad90SMark F. Adams #define __FUNCT__ "PCSetFromOptions_GAMG" 258*5b89ad90SMark F. Adams PetscErrorCode PCSetFromOptions_GAMG(PC pc) 259*5b89ad90SMark F. Adams { 260*5b89ad90SMark F. Adams /* PetscErrorCode ierr; */ 261*5b89ad90SMark F. Adams /* PC_MG *mg = (PC_MG*)pc->data; */ 262*5b89ad90SMark F. Adams /* PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; */ 263*5b89ad90SMark F. Adams /* MPI_Comm comm = ((PetscObject)pc)->comm; */ 264*5b89ad90SMark F. Adams 265*5b89ad90SMark F. Adams PetscFunctionBegin; 266*5b89ad90SMark F. Adams PetscFunctionReturn(0); 267*5b89ad90SMark F. Adams } 268*5b89ad90SMark F. Adams 269*5b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */ 270*5b89ad90SMark F. Adams /* 271*5b89ad90SMark F. Adams PCCreate_GAMG - Creates a GAMG preconditioner context, PC_GAMG 272*5b89ad90SMark F. Adams 273*5b89ad90SMark F. Adams Input Parameter: 274*5b89ad90SMark F. Adams . pc - the preconditioner context 275*5b89ad90SMark F. Adams 276*5b89ad90SMark F. Adams Application Interface Routine: PCCreate() 277*5b89ad90SMark F. Adams 278*5b89ad90SMark F. Adams */ 279*5b89ad90SMark F. Adams /* MC 280*5b89ad90SMark F. Adams PCGAMG - Use algebraic multigrid preconditioning. This preconditioner requires you provide 281*5b89ad90SMark F. Adams fine grid discretization matrix and coordinates on the fine grid. 282*5b89ad90SMark F. Adams 283*5b89ad90SMark F. Adams Options Database Key: 284*5b89ad90SMark F. Adams Multigrid options(inherited) 285*5b89ad90SMark F. Adams + -pc_mg_cycles <1>: 1 for V cycle, 2 for W-cycle (MGSetCycles) 286*5b89ad90SMark F. Adams . -pc_mg_smoothup <1>: Number of post-smoothing steps (MGSetNumberSmoothUp) 287*5b89ad90SMark F. Adams . -pc_mg_smoothdown <1>: Number of pre-smoothing steps (MGSetNumberSmoothDown) 288*5b89ad90SMark F. Adams -pc_mg_type <multiplicative>: (one of) additive multiplicative full cascade kascade 289*5b89ad90SMark F. Adams GAMG options: 290*5b89ad90SMark F. Adams 291*5b89ad90SMark F. Adams Level: intermediate 292*5b89ad90SMark F. Adams Concepts: multigrid 293*5b89ad90SMark F. Adams 294*5b89ad90SMark F. Adams .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, PCMGType, 295*5b89ad90SMark F. Adams PCMGSetLevels(), PCMGGetLevels(), PCMGSetType(), MPSetCycles(), PCMGSetNumberSmoothDown(), 296*5b89ad90SMark F. Adams PCMGSetNumberSmoothUp(), PCMGGetCoarseSolve(), PCMGSetResidual(), PCMGSetInterpolation(), 297*5b89ad90SMark F. Adams PCMGSetRestriction(), PCMGGetSmoother(), PCMGGetSmootherUp(), PCMGGetSmootherDown(), 298*5b89ad90SMark F. Adams PCMGSetCyclesOnLevel(), PCMGSetRhs(), PCMGSetX(), PCMGSetR() 299*5b89ad90SMark F. Adams M */ 300*5b89ad90SMark F. Adams 301*5b89ad90SMark F. Adams EXTERN_C_BEGIN 302*5b89ad90SMark F. Adams #undef __FUNCT__ 303*5b89ad90SMark F. Adams #define __FUNCT__ "PCCreate_GAMG" 304*5b89ad90SMark F. Adams PetscErrorCode PCCreate_GAMG(PC pc) 305*5b89ad90SMark F. Adams { 306*5b89ad90SMark F. Adams PetscErrorCode ierr; 307*5b89ad90SMark F. Adams PC_GAMG *pc_gamg; 308*5b89ad90SMark F. Adams PC_MG *mg; 309*5b89ad90SMark F. Adams 310*5b89ad90SMark F. Adams PetscFunctionBegin; 311*5b89ad90SMark F. Adams /* PCGAMG is an inherited class of PCMG. Initialize pc as PCMG */ 312*5b89ad90SMark F. Adams ierr = PCSetType(pc,PCMG);CHKERRQ(ierr); /* calls PCCreate_MG() and MGCreate_Private() */ 313*5b89ad90SMark F. Adams ierr = PetscObjectChangeTypeName((PetscObject)pc,PCGAMG);CHKERRQ(ierr); 314*5b89ad90SMark F. Adams 315*5b89ad90SMark F. Adams /* create a supporting struct and attach it to pc */ 316*5b89ad90SMark F. Adams ierr = PetscNewLog(pc,PC_GAMG,&pc_gamg);CHKERRQ(ierr); 317*5b89ad90SMark F. Adams mg = (PC_MG*)pc->data; 318*5b89ad90SMark F. Adams mg->innerctx = pc_gamg; 319*5b89ad90SMark F. Adams 320*5b89ad90SMark F. Adams pc_gamg->m_data = 0; 321*5b89ad90SMark F. Adams pc_gamg->m_Nlevels = -1; 322*5b89ad90SMark F. Adams 323*5b89ad90SMark F. Adams /* overwrite the pointers of PCMG by the functions of PCGAMG */ 324*5b89ad90SMark F. Adams pc->ops->setfromoptions = PCSetFromOptions_GAMG; 325*5b89ad90SMark F. Adams pc->ops->setup = PCSetUp_GAMG; 326*5b89ad90SMark F. Adams pc->ops->reset = PCReset_GAMG; 327*5b89ad90SMark F. Adams pc->ops->destroy = PCDestroy_GAMG; 328*5b89ad90SMark F. Adams 329*5b89ad90SMark F. Adams ierr = PetscObjectComposeFunctionDynamic( (PetscObject)pc, 330*5b89ad90SMark F. Adams "PCSetCoordinates_C", 331*5b89ad90SMark F. Adams "PCSetCoordinates_GAMG", 332*5b89ad90SMark F. Adams PCSetCoordinates_GAMG);CHKERRQ(ierr); 333*5b89ad90SMark F. Adams PetscFunctionReturn(0); 334*5b89ad90SMark F. Adams } 335*5b89ad90SMark F. Adams EXTERN_C_END 336