xref: /petsc/src/ksp/pc/impls/gamg/gamg.c (revision ce4cda84c3c744293c810bc1e3aed5a19ef6187b)
15b89ad90SMark F. Adams /*
20cd22d39SHong Zhang  GAMG geometric-algebric multigrid PC - Mark Adams 2011
35b89ad90SMark F. Adams  */
4313a3e24SSatish Balay #include "private/matimpl.h"
5389730f3SMark F. Adams #include <../src/ksp/pc/impls/gamg/gamg.h>           /*I "petscpc.h" I*/
65a9b9e01SMark F. Adams #include <private/kspimpl.h>
7f96513f1SMatthew G Knepley 
8b4fbaa2aSMark F. Adams #if defined PETSC_USE_LOG
9b4fbaa2aSMark F. Adams PetscLogEvent gamg_setup_events[NUM_SET];
10b4fbaa2aSMark F. Adams #endif
11b4fbaa2aSMark F. Adams #define GAMG_MAXLEVELS 30
12b4fbaa2aSMark F. Adams 
13b8fd24d8SMark F. Adams /*#define GAMG_STAGES*/
14b4fbaa2aSMark F. Adams #if (defined PETSC_USE_LOG && defined GAMG_STAGES)
15b4fbaa2aSMark F. Adams static PetscLogStage gamg_stages[GAMG_MAXLEVELS];
16b4fbaa2aSMark F. Adams #endif
17f96513f1SMatthew G Knepley 
189d5b6da9SMark F. Adams /* typedef enum { NOT_DONE=-2, DELETED=-1, REMOVED=-3 } NState; */
199d5b6da9SMark F. Adams /* use int instead of enum to facilitate passing them via Scatters */
209d5b6da9SMark F. Adams typedef int NState;
219d5b6da9SMark F. Adams static const NState NOT_DONE=-2;
229d5b6da9SMark F. Adams static const NState DELETED=-1;
239d5b6da9SMark F. Adams static const NState REMOVED=-3;
249d5b6da9SMark F. Adams 
259d5b6da9SMark F. Adams #define  IS_SELECTED(s) (s!=DELETED && s!=NOT_DONE && s!=REMOVED)
269d5b6da9SMark F. Adams 
279d5b6da9SMark F. Adams int compare (const void *a, const void *b)
289d5b6da9SMark F. Adams {
299d5b6da9SMark F. Adams   return (((GAMGNode*)a)->degree - ((GAMGNode*)b)->degree);
309d5b6da9SMark F. Adams }
319d5b6da9SMark F. Adams 
329d5b6da9SMark F. Adams static PetscFList GAMGList = 0;
339d5b6da9SMark F. Adams 
345b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */
355b89ad90SMark F. Adams /*
369d5b6da9SMark F. Adams    createGraph
375b89ad90SMark F. Adams 
385b89ad90SMark F. Adams  Input Parameter:
399d5b6da9SMark F. Adams  . pc - this
409d5b6da9SMark F. Adams  . Amat - original graph
419d5b6da9SMark F. Adams  Output Parameter:
429d5b6da9SMark F. Adams  . Gmat - output, filter Graph
439d5b6da9SMark F. Adams  . AuxMat - filter matrix for when 'square'
449d5b6da9SMark F. Adams  . permIS - perumutation IS (this should not be here)
455b89ad90SMark F. Adams  */
465b89ad90SMark F. Adams #undef __FUNCT__
479d5b6da9SMark F. Adams #define __FUNCT__ "createGraph"
489d5b6da9SMark F. Adams PetscErrorCode createGraph(PC pc, const Mat Amat, Mat *a_Gmat, Mat *a_AuxMat, IS *a_permIS )
495b89ad90SMark F. Adams {
509d5b6da9SMark F. Adams   PC_MG          *mg = (PC_MG*)pc->data;
515b89ad90SMark F. Adams   PC_GAMG        *pc_gamg = (PC_GAMG*)mg->innerctx;
529d5b6da9SMark F. Adams   const PetscInt verbose = pc_gamg->verbose;
539d5b6da9SMark F. Adams   const PetscReal vfilter = pc_gamg->threshold;
546c237d78SBarry Smith   PetscErrorCode ierr;
559d5b6da9SMark F. Adams   PetscInt       Istart,Iend,Ii,jj,ncols,nloc,kk,nnz0,nnz1,NN,MM,bs;
569d5b6da9SMark F. Adams   PetscMPIInt    mype, npe;
579d5b6da9SMark F. Adams   MPI_Comm       wcomm = ((PetscObject)Amat)->comm;
589d5b6da9SMark F. Adams   PetscInt       *d_nnz, *o_nnz;
599d5b6da9SMark F. Adams   Mat            Gmat;
609d5b6da9SMark F. Adams   const PetscScalar    *vals;
619d5b6da9SMark F. Adams   const PetscInt *idx;
625b89ad90SMark F. Adams 
635b89ad90SMark F. Adams   PetscFunctionBegin;
649d5b6da9SMark F. Adams   ierr = MPI_Comm_rank(wcomm,&mype);CHKERRQ(ierr);
659d5b6da9SMark F. Adams   ierr = MPI_Comm_size(wcomm,&npe);CHKERRQ(ierr);
669d5b6da9SMark F. Adams   ierr = MatGetOwnershipRange( Amat, &Istart, &Iend ); CHKERRQ(ierr);
679d5b6da9SMark F. Adams   ierr = MatGetSize( Amat, &MM, &NN ); CHKERRQ(ierr);
68038e3b61SMark F. Adams   ierr = MatGetBlockSize( Amat, &bs ); CHKERRQ(ierr);
699d5b6da9SMark F. Adams   nloc = (Iend-Istart)/bs;
70038e3b61SMark F. Adams 
719d5b6da9SMark F. Adams #if defined PETSC_USE_LOG
729d5b6da9SMark F. Adams   ierr = PetscLogEventBegin(gamg_setup_events[GRAPH],0,0,0,0);CHKERRQ(ierr);
739d5b6da9SMark F. Adams   ierr = PetscLogEventBegin(gamg_setup_events[GRAPH_MAT],0,0,0,0);CHKERRQ(ierr);
749d5b6da9SMark F. Adams #endif
759d5b6da9SMark F. Adams   /* count nnz, there is sparcity in here so this might not be enough */
769d5b6da9SMark F. Adams   ierr = PetscMalloc( nloc*sizeof(PetscInt), &d_nnz ); CHKERRQ(ierr);
779d5b6da9SMark F. Adams   ierr = PetscMalloc( nloc*sizeof(PetscInt), &o_nnz ); CHKERRQ(ierr);
789d5b6da9SMark F. Adams   for ( Ii = Istart, nnz0 = jj = 0 ; Ii < Iend ; Ii += bs, jj++ ) {
799d5b6da9SMark F. Adams     ierr = MatGetRow(Amat,Ii,&ncols,0,0); CHKERRQ(ierr);
809d5b6da9SMark F. Adams     d_nnz[jj] = ncols; /* very pessimistic */
819d5b6da9SMark F. Adams     o_nnz[jj] = ncols;
829d5b6da9SMark F. Adams     if( d_nnz[jj] > nloc ) d_nnz[jj] = nloc;
839d5b6da9SMark F. Adams     if( o_nnz[jj] > (NN/bs-nloc) ) o_nnz[jj] = NN/bs-nloc;
849d5b6da9SMark F. Adams     nnz0 += ncols;
859d5b6da9SMark F. Adams     ierr = MatRestoreRow(Amat,Ii,&ncols,0,0); CHKERRQ(ierr);
86f6536408SMark F. Adams   }
879d5b6da9SMark F. Adams   nnz0 /= (nloc+1);
885b89ad90SMark F. Adams 
899d5b6da9SMark F. Adams   /* get scalar copy (norms) of matrix */
909d5b6da9SMark F. Adams   ierr = MatCreateMPIAIJ( wcomm, nloc, nloc,
919d5b6da9SMark F. Adams                           PETSC_DETERMINE, PETSC_DETERMINE,
929d5b6da9SMark F. Adams                           0, d_nnz, 0, o_nnz, &Gmat );
93038e3b61SMark F. Adams 
949d5b6da9SMark F. Adams   for( Ii = Istart; Ii < Iend ; Ii++ ) {
959d5b6da9SMark F. Adams     PetscInt dest_row = Ii/bs;
969d5b6da9SMark F. Adams     ierr = MatGetRow(Amat,Ii,&ncols,&idx,&vals); CHKERRQ(ierr);
979d5b6da9SMark F. Adams     for(jj=0;jj<ncols;jj++){
989d5b6da9SMark F. Adams       PetscInt dest_col = idx[jj]/bs;
999d5b6da9SMark F. Adams       PetscScalar sv = PetscAbs(PetscRealPart(vals[jj]));
1009d5b6da9SMark F. Adams       ierr = MatSetValues(Gmat,1,&dest_row,1,&dest_col,&sv,ADD_VALUES);  CHKERRQ(ierr);
1019d5b6da9SMark F. Adams     }
1029d5b6da9SMark F. Adams     ierr = MatRestoreRow(Amat,Ii,&ncols,&idx,&vals); CHKERRQ(ierr);
1039d5b6da9SMark F. Adams   }
1049d5b6da9SMark F. Adams   ierr = MatAssemblyBegin(Gmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1059d5b6da9SMark F. Adams   ierr = MatAssemblyEnd(Gmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1069d5b6da9SMark F. Adams   /* scale Gmat so filter works */
1079d5b6da9SMark F. Adams   {
1089d5b6da9SMark F. Adams     Vec diag;
1099d5b6da9SMark F. Adams     ierr = MatGetVecs( Gmat, &diag, 0 );    CHKERRQ(ierr);
1109d5b6da9SMark F. Adams     ierr = MatGetDiagonal( Gmat, diag );    CHKERRQ(ierr);
1119d5b6da9SMark F. Adams     ierr = VecReciprocal( diag );           CHKERRQ(ierr);
1129d5b6da9SMark F. Adams     ierr = VecSqrtAbs( diag );              CHKERRQ(ierr);
1139d5b6da9SMark F. Adams     ierr = MatDiagonalScale( Gmat, diag, diag );CHKERRQ(ierr);
1149d5b6da9SMark F. Adams     ierr = VecDestroy( &diag );           CHKERRQ(ierr);
1159d5b6da9SMark F. Adams   }
1169d5b6da9SMark F. Adams #if defined PETSC_USE_LOG
1179d5b6da9SMark F. Adams   ierr = PetscLogEventEnd(gamg_setup_events[GRAPH_MAT],0,0,0,0);   CHKERRQ(ierr);
1189d5b6da9SMark F. Adams   ierr = PetscLogEventBegin(gamg_setup_events[GRAPH_FILTER],0,0,0,0);CHKERRQ(ierr);
1199d5b6da9SMark F. Adams #endif
1209d5b6da9SMark F. Adams 
1219d5b6da9SMark F. Adams   ierr = MatGetOwnershipRange(Gmat,&Istart,&Iend);CHKERRQ(ierr); /* use AIJ from here */
1229d5b6da9SMark F. Adams   {
1239d5b6da9SMark F. Adams     Mat Gmat2;
1249d5b6da9SMark F. Adams     ierr = MatCreateMPIAIJ(wcomm,nloc,nloc,PETSC_DECIDE,PETSC_DECIDE,0,d_nnz,0,o_nnz,&Gmat2);
1259d5b6da9SMark F. Adams     CHKERRQ(ierr);
1269d5b6da9SMark F. Adams     for( Ii = Istart, nnz1 = 0 ; Ii < Iend; Ii++ ){
1279d5b6da9SMark F. Adams       ierr = MatGetRow(Gmat,Ii,&ncols,&idx,&vals); CHKERRQ(ierr);
1289d5b6da9SMark F. Adams       for(jj=0;jj<ncols;jj++){
1299d5b6da9SMark F. Adams         PetscScalar sv = PetscAbs(PetscRealPart(vals[jj]));
1309d5b6da9SMark F. Adams         if( PetscRealPart(sv) > vfilter ) {
1319d5b6da9SMark F. Adams           ierr = MatSetValues(Gmat2,1,&Ii,1,&idx[jj],&sv,INSERT_VALUES); CHKERRQ(ierr);
1329d5b6da9SMark F. Adams 	  nnz1++;
1339d5b6da9SMark F. Adams         }
1349d5b6da9SMark F. Adams       }
1359d5b6da9SMark F. Adams       ierr = MatRestoreRow(Gmat,Ii,&ncols,&idx,&vals); CHKERRQ(ierr);
1369d5b6da9SMark F. Adams     }
1379d5b6da9SMark F. Adams     nnz1 /= (nloc+1);
1389d5b6da9SMark F. Adams     ierr = MatAssemblyBegin(Gmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1399d5b6da9SMark F. Adams     ierr = MatAssemblyEnd(Gmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1409d5b6da9SMark F. Adams     ierr = MatDestroy( &Gmat );  CHKERRQ(ierr);
1419d5b6da9SMark F. Adams     Gmat = Gmat2;
1429d5b6da9SMark F. Adams     if( verbose ) {
1439d5b6da9SMark F. Adams       PetscPrintf(PETSC_COMM_WORLD,"\t%s ave nnz/row %d --> %d\n",__FUNCT__,nnz0,nnz1);
1449d5b6da9SMark F. Adams     }
1459d5b6da9SMark F. Adams   }
1469d5b6da9SMark F. Adams   ierr = PetscFree( d_nnz ); CHKERRQ(ierr);
1479d5b6da9SMark F. Adams   ierr = PetscFree( o_nnz ); CHKERRQ(ierr);
1489d5b6da9SMark F. Adams 
1499d5b6da9SMark F. Adams #if defined PETSC_USE_LOG
1509d5b6da9SMark F. Adams   ierr = PetscLogEventEnd(gamg_setup_events[GRAPH_FILTER],0,0,0,0);   CHKERRQ(ierr);
1519d5b6da9SMark F. Adams   ierr = PetscLogEventBegin(gamg_setup_events[GRAPH_SQR],0,0,0,0);CHKERRQ(ierr);
1529d5b6da9SMark F. Adams #endif
1539d5b6da9SMark F. Adams   /* square matrix - SA */
1549d5b6da9SMark F. Adams   if( a_AuxMat ){
1559d5b6da9SMark F. Adams     Mat Gmat2;
1569d5b6da9SMark F. Adams     ierr = MatTransposeMatMult( Gmat, Gmat, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &Gmat2 );
1579d5b6da9SMark F. Adams     CHKERRQ(ierr);
1589d5b6da9SMark F. Adams     *a_AuxMat = Gmat;
1599d5b6da9SMark F. Adams     /* force compressed row storage for B matrix in AuxMat */
1609d5b6da9SMark F. Adams     if (npe > 1) {
1619d5b6da9SMark F. Adams       Mat_MPIAIJ *mpimat = (Mat_MPIAIJ*)Gmat->data;
1629d5b6da9SMark F. Adams       Mat_SeqAIJ *Bmat = (Mat_SeqAIJ*) mpimat->B->data;
1639d5b6da9SMark F. Adams       Bmat->compressedrow.check = PETSC_TRUE;
1649d5b6da9SMark F. Adams       ierr = MatCheckCompressedRow(mpimat->B,&Bmat->compressedrow,Bmat->i,Gmat->rmap->n,-1.0);
1659d5b6da9SMark F. Adams       CHKERRQ(ierr);
1669d5b6da9SMark F. Adams       assert( Bmat->compressedrow.use );
1679d5b6da9SMark F. Adams     }
1689d5b6da9SMark F. Adams     Gmat = Gmat2; /* now work with the squared matrix (get forced soon) */
1699d5b6da9SMark F. Adams   }
1709d5b6da9SMark F. Adams 
1719d5b6da9SMark F. Adams #if defined PETSC_USE_LOG
1729d5b6da9SMark F. Adams   ierr = PetscLogEventEnd(gamg_setup_events[GRAPH_SQR],0,0,0,0);   CHKERRQ(ierr);
1739d5b6da9SMark F. Adams #endif
1749d5b6da9SMark F. Adams   if (npe > 1) {
1759d5b6da9SMark F. Adams     /* force compressed row storage for B matrix */
1769d5b6da9SMark F. Adams     Mat_MPIAIJ *mpimat = (Mat_MPIAIJ*)Gmat->data;
1779d5b6da9SMark F. Adams     Mat_SeqAIJ *Bmat = (Mat_SeqAIJ*) mpimat->B->data;
1789d5b6da9SMark F. Adams     Bmat->compressedrow.check = PETSC_TRUE;
1799d5b6da9SMark F. Adams     ierr = MatCheckCompressedRow(mpimat->B,&Bmat->compressedrow,Bmat->i,Gmat->rmap->n,-1.0);
1809d5b6da9SMark F. Adams     CHKERRQ(ierr);
1819d5b6da9SMark F. Adams     assert( Bmat->compressedrow.use );
1829d5b6da9SMark F. Adams   }
1839d5b6da9SMark F. Adams 
1849d5b6da9SMark F. Adams   /* create random permutation with sort for geo-mg -- this should be refactored, its sort of geo-mg specific */
1859d5b6da9SMark F. Adams   {
1869d5b6da9SMark F. Adams     GAMGNode *gnodes;
1879d5b6da9SMark F. Adams     PetscInt *permute;
1889d5b6da9SMark F. Adams 
1899d5b6da9SMark F. Adams     ierr = PetscMalloc( nloc*sizeof(GAMGNode), &gnodes ); CHKERRQ(ierr);
1909d5b6da9SMark F. Adams     ierr = PetscMalloc( nloc*sizeof(PetscInt), &permute ); CHKERRQ(ierr);
1919d5b6da9SMark F. Adams 
1929d5b6da9SMark F. Adams     for (Ii=Istart; Ii<Iend; Ii++) { /* locals only? */
1939d5b6da9SMark F. Adams       ierr = MatGetRow(Gmat,Ii,&ncols,0,0); CHKERRQ(ierr);
1949d5b6da9SMark F. Adams       {
1959d5b6da9SMark F. Adams         PetscInt lid = Ii - Istart;
1969d5b6da9SMark F. Adams         gnodes[lid].lid = lid;
1979d5b6da9SMark F. Adams         gnodes[lid].degree = ncols;
1989d5b6da9SMark F. Adams       }
1999d5b6da9SMark F. Adams       ierr = MatRestoreRow(Gmat,Ii,&ncols,0,0); CHKERRQ(ierr);
2009d5b6da9SMark F. Adams     }
2019d5b6da9SMark F. Adams     /* randomize */
2029d5b6da9SMark F. Adams     srand(1); /* make deterministic */
2039d5b6da9SMark F. Adams     if( PETSC_TRUE ) {
2049d5b6da9SMark F. Adams       PetscBool *bIndexSet;
2059d5b6da9SMark F. Adams       ierr = PetscMalloc( nloc*sizeof(PetscBool), &bIndexSet ); CHKERRQ(ierr);
2069d5b6da9SMark F. Adams       for ( Ii = 0; Ii < nloc ; Ii++) bIndexSet[Ii] = PETSC_FALSE;
2079d5b6da9SMark F. Adams       for ( Ii = 0; Ii < nloc ; Ii++)
2089d5b6da9SMark F. Adams       {
2099d5b6da9SMark F. Adams         PetscInt iSwapIndex = rand()%nloc;
2109d5b6da9SMark F. Adams         if (!bIndexSet[iSwapIndex] && iSwapIndex != Ii)
2119d5b6da9SMark F. Adams         {
2129d5b6da9SMark F. Adams           GAMGNode iTemp = gnodes[iSwapIndex];
2139d5b6da9SMark F. Adams           gnodes[iSwapIndex] = gnodes[Ii];
2149d5b6da9SMark F. Adams           gnodes[Ii] = iTemp;
2159d5b6da9SMark F. Adams           bIndexSet[Ii] = PETSC_TRUE;
2169d5b6da9SMark F. Adams           bIndexSet[iSwapIndex] = PETSC_TRUE;
2179d5b6da9SMark F. Adams         }
2189d5b6da9SMark F. Adams       }
2199d5b6da9SMark F. Adams       ierr = PetscFree( bIndexSet );  CHKERRQ(ierr);
2209d5b6da9SMark F. Adams     }
2219d5b6da9SMark F. Adams     /* only sort locals */
2229d5b6da9SMark F. Adams     qsort( gnodes, nloc, sizeof(GAMGNode), compare );
2239d5b6da9SMark F. Adams     /* create IS of permutation */
2249d5b6da9SMark F. Adams     for(kk=0;kk<nloc;kk++) { /* locals only */
2259d5b6da9SMark F. Adams       permute[kk] = gnodes[kk].lid;
2269d5b6da9SMark F. Adams     }
2279d5b6da9SMark F. Adams     ierr = ISCreateGeneral( PETSC_COMM_SELF, (Iend-Istart), permute, PETSC_COPY_VALUES, a_permIS );
2289d5b6da9SMark F. Adams     CHKERRQ(ierr);
2299d5b6da9SMark F. Adams 
2309d5b6da9SMark F. Adams     ierr = PetscFree( gnodes );  CHKERRQ(ierr);
2319d5b6da9SMark F. Adams     ierr = PetscFree( permute );  CHKERRQ(ierr);
2329d5b6da9SMark F. Adams   }
2339d5b6da9SMark F. Adams #if defined PETSC_USE_LOG
2349d5b6da9SMark F. Adams   ierr = PetscLogEventEnd(gamg_setup_events[GRAPH],0,0,0,0);   CHKERRQ(ierr);
2359d5b6da9SMark F. Adams #endif
2369d5b6da9SMark F. Adams   *a_Gmat = Gmat;
2375b89ad90SMark F. Adams 
2385b89ad90SMark F. Adams   PetscFunctionReturn(0);
2395b89ad90SMark F. Adams }
2405b89ad90SMark F. Adams 
2419d5b6da9SMark F. Adams /* -------------------------------------------------------------------------- */
2429d5b6da9SMark F. Adams /*
2439d5b6da9SMark F. Adams    getDataWithGhosts - hacks into Mat MPIAIJ so this must have > 1 pe
2449d5b6da9SMark F. Adams 
2459d5b6da9SMark F. Adams    Input Parameter:
2469d5b6da9SMark F. Adams    . Gmat - MPIAIJ matrix for scattters
2479d5b6da9SMark F. Adams    . data_sz - number of data terms per node (# cols in output)
2489d5b6da9SMark F. Adams    . data_in[nloc*data_sz] - column oriented data
2499d5b6da9SMark F. Adams    Output Parameter:
2509d5b6da9SMark F. Adams    . stride - numbrt of rows of output
2519d5b6da9SMark F. Adams    . data_out[stride*data_sz] - output data with ghosts
2529d5b6da9SMark F. Adams */
2539d5b6da9SMark F. Adams #undef __FUNCT__
2549d5b6da9SMark F. Adams #define __FUNCT__ "getDataWithGhosts"
2559d5b6da9SMark F. Adams PetscErrorCode getDataWithGhosts( const Mat Gmat,
2569d5b6da9SMark F. Adams                                   const PetscInt data_sz,
2579d5b6da9SMark F. Adams                                   const PetscReal data_in[],
2589d5b6da9SMark F. Adams                                   PetscInt *a_stride,
2599d5b6da9SMark F. Adams                                   PetscReal **a_data_out
2609d5b6da9SMark F. Adams                                   )
2619d5b6da9SMark F. Adams {
2629d5b6da9SMark F. Adams   PetscErrorCode ierr;
2639d5b6da9SMark F. Adams   PetscMPIInt    mype,npe;
2649d5b6da9SMark F. Adams   MPI_Comm       wcomm = ((PetscObject)Gmat)->comm;
2659d5b6da9SMark F. Adams   Vec            tmp_crds;
2669d5b6da9SMark F. Adams   Mat_MPIAIJ    *mpimat = (Mat_MPIAIJ*)Gmat->data;
2679d5b6da9SMark F. Adams   PetscInt       nnodes,num_ghosts,dir,kk,jj,my0,Iend,nloc;
2689d5b6da9SMark F. Adams   PetscScalar   *data_arr;
2699d5b6da9SMark F. Adams   PetscReal     *datas;
2709d5b6da9SMark F. Adams   PetscBool      isMPIAIJ;
2719d5b6da9SMark F. Adams 
2729d5b6da9SMark F. Adams   PetscFunctionBegin;
2739d5b6da9SMark F. Adams   ierr = PetscTypeCompare( (PetscObject)Gmat, MATMPIAIJ, &isMPIAIJ ); CHKERRQ(ierr);
2749d5b6da9SMark F. Adams   assert(isMPIAIJ);
2759d5b6da9SMark F. Adams   ierr = MPI_Comm_rank(wcomm,&mype);CHKERRQ(ierr);
2769d5b6da9SMark F. Adams   ierr = MPI_Comm_size(wcomm,&npe);CHKERRQ(ierr);                      assert(npe>1);
2779d5b6da9SMark F. Adams   ierr = MatGetOwnershipRange( Gmat, &my0, &Iend );    CHKERRQ(ierr);
2789d5b6da9SMark F. Adams   nloc = Iend - my0;
2799d5b6da9SMark F. Adams   ierr = VecGetLocalSize( mpimat->lvec, &num_ghosts );   CHKERRQ(ierr);
2809d5b6da9SMark F. Adams   nnodes = num_ghosts + nloc;
2819d5b6da9SMark F. Adams   *a_stride = nnodes;
2829d5b6da9SMark F. Adams   ierr = MatGetVecs( Gmat, &tmp_crds, 0 );    CHKERRQ(ierr);
2839d5b6da9SMark F. Adams 
2849d5b6da9SMark F. Adams   ierr = PetscMalloc( data_sz*nnodes*sizeof(PetscReal), &datas); CHKERRQ(ierr);
2859d5b6da9SMark F. Adams   for(dir=0; dir<data_sz; dir++) {
2869d5b6da9SMark F. Adams     /* set local, and global */
2879d5b6da9SMark F. Adams     for(kk=0; kk<nloc; kk++) {
2889d5b6da9SMark F. Adams       PetscInt gid = my0 + kk;
2899d5b6da9SMark F. Adams       PetscScalar crd = (PetscScalar)data_in[dir*nloc + kk]; /* col oriented */
2909d5b6da9SMark F. Adams       datas[dir*nnodes + kk] = PetscRealPart(crd);
2919d5b6da9SMark F. Adams       ierr = VecSetValues(tmp_crds, 1, &gid, &crd, INSERT_VALUES ); CHKERRQ(ierr);
2929d5b6da9SMark F. Adams     }
2939d5b6da9SMark F. Adams     ierr = VecAssemblyBegin( tmp_crds ); CHKERRQ(ierr);
2949d5b6da9SMark F. Adams     ierr = VecAssemblyEnd( tmp_crds ); CHKERRQ(ierr);
2959d5b6da9SMark F. Adams     /* get ghost datas */
2969d5b6da9SMark F. Adams     ierr = VecScatterBegin(mpimat->Mvctx,tmp_crds,mpimat->lvec,INSERT_VALUES,SCATTER_FORWARD);
2979d5b6da9SMark F. Adams     CHKERRQ(ierr);
2989d5b6da9SMark F. Adams     ierr = VecScatterEnd(mpimat->Mvctx,tmp_crds,mpimat->lvec,INSERT_VALUES,SCATTER_FORWARD);
2999d5b6da9SMark F. Adams     CHKERRQ(ierr);
3009d5b6da9SMark F. Adams     ierr = VecGetArray( mpimat->lvec, &data_arr );   CHKERRQ(ierr);
3019d5b6da9SMark F. Adams     for(kk=nloc,jj=0;jj<num_ghosts;kk++,jj++){
3029d5b6da9SMark F. Adams       datas[dir*nnodes + kk] = PetscRealPart(data_arr[jj]);
3039d5b6da9SMark F. Adams     }
3049d5b6da9SMark F. Adams     ierr = VecRestoreArray( mpimat->lvec, &data_arr ); CHKERRQ(ierr);
3059d5b6da9SMark F. Adams   }
3069d5b6da9SMark F. Adams   ierr = VecDestroy(&tmp_crds); CHKERRQ(ierr);
3079d5b6da9SMark F. Adams 
3089d5b6da9SMark F. Adams   *a_data_out = datas;
3099d5b6da9SMark F. Adams 
3109d5b6da9SMark F. Adams   PetscFunctionReturn(0);
3119d5b6da9SMark F. Adams }
3129d5b6da9SMark F. Adams 
3139d5b6da9SMark F. Adams /* -------------------------------------------------------------------------- */
3149d5b6da9SMark F. Adams /*
3159d5b6da9SMark F. Adams    smoothAggs -
3169d5b6da9SMark F. Adams 
3179d5b6da9SMark F. Adams    Input Parameter:
3189d5b6da9SMark F. Adams    . Gmat_2 - glabal matrix of graph (data not defined)
3199d5b6da9SMark F. Adams    . Gmat_1
3209d5b6da9SMark F. Adams    . lid_state
3219d5b6da9SMark F. Adams    Input/Output Parameter:
3229d5b6da9SMark F. Adams    . id_llist - linked list rooted at selected node (size is nloc + nghosts_2)
3239d5b6da9SMark F. Adams    . deleted_parent_gid
3249d5b6da9SMark F. Adams */
3259d5b6da9SMark F. Adams #undef __FUNCT__
3269d5b6da9SMark F. Adams #define __FUNCT__ "smoothAggs"
3279d5b6da9SMark F. Adams PetscErrorCode smoothAggs( const Mat Gmat_2, /* base (squared) graph */
3289d5b6da9SMark F. Adams                            const Mat Gmat_1, /* base graph, could be unsymmetic */
3299d5b6da9SMark F. Adams                            const PetscScalar lid_state[], /* [nloc], states */
3309d5b6da9SMark F. Adams                            PetscInt id_llist[], /* [nloc+nghost_2], aggragate list */
3319d5b6da9SMark F. Adams                            PetscScalar deleted_parent_gid[] /* [nloc], which pe owns my deleted */
3329d5b6da9SMark F. Adams 
3339d5b6da9SMark F. Adams                            )
3349d5b6da9SMark F. Adams {
3359d5b6da9SMark F. Adams   PetscErrorCode ierr;
3369d5b6da9SMark F. Adams   PetscBool      isMPI;
3379d5b6da9SMark F. Adams   Mat_SeqAIJ    *matA_1, *matB_1=0;
3389d5b6da9SMark F. Adams   MPI_Comm       wcomm = ((PetscObject)Gmat_2)->comm;
3399d5b6da9SMark F. Adams   PetscMPIInt    mype;
3409d5b6da9SMark F. Adams   PetscInt       nghosts_2,nghosts_1,lid,*ii,n,*idx,j,ix,Iend,my0;
3419d5b6da9SMark F. Adams   Mat_MPIAIJ    *mpimat_2 = 0, *mpimat_1=0;
3429d5b6da9SMark F. Adams   const PetscInt nloc = Gmat_2->rmap->n;
3439d5b6da9SMark F. Adams   PetscScalar   *cpcol_1_state;
3449d5b6da9SMark F. Adams 
3459d5b6da9SMark F. Adams   PetscFunctionBegin;
3469d5b6da9SMark F. Adams   ierr = MPI_Comm_rank( wcomm, &mype );   CHKERRQ(ierr);
3479d5b6da9SMark F. Adams   ierr = MatGetOwnershipRange(Gmat_1,&my0,&Iend);  CHKERRQ(ierr);
3489d5b6da9SMark F. Adams 
3499d5b6da9SMark F. Adams   if( !PETSC_TRUE ) {
3509d5b6da9SMark F. Adams     PetscViewer viewer; char fname[32]; static int llev=0;
3519d5b6da9SMark F. Adams     sprintf(fname,"Gmat1_%d.mat",llev++);
3529d5b6da9SMark F. Adams     PetscViewerASCIIOpen(wcomm,fname,&viewer);
3539d5b6da9SMark F. Adams     ierr = PetscViewerSetFormat( viewer, PETSC_VIEWER_ASCII_MATLAB);  CHKERRQ(ierr);
3549d5b6da9SMark F. Adams     ierr = MatView(Gmat_1, viewer ); CHKERRQ(ierr);
3559d5b6da9SMark F. Adams     ierr = PetscViewerDestroy( &viewer );
3569d5b6da9SMark F. Adams   }
3579d5b6da9SMark F. Adams 
3589d5b6da9SMark F. Adams   /* get submatrices */
3599d5b6da9SMark F. Adams   ierr = PetscTypeCompare( (PetscObject)Gmat_1, MATMPIAIJ, &isMPI ); CHKERRQ(ierr);
3609d5b6da9SMark F. Adams 
3619d5b6da9SMark F. Adams   if (isMPI) {
3629d5b6da9SMark F. Adams     PetscInt    *gids, gid;
3639d5b6da9SMark F. Adams     PetscScalar *real_gids;
3649d5b6da9SMark F. Adams     Vec          tempVec;
3659d5b6da9SMark F. Adams 
3669d5b6da9SMark F. Adams     ierr = PetscMalloc( nloc*sizeof(PetscInt), &gids ); CHKERRQ(ierr);
3679d5b6da9SMark F. Adams     ierr = PetscMalloc( nloc*sizeof(PetscScalar), &real_gids ); CHKERRQ(ierr);
3689d5b6da9SMark F. Adams 
3699d5b6da9SMark F. Adams     for(lid=0,gid=my0;lid<nloc;lid++,gid++){
3709d5b6da9SMark F. Adams       gids[lid] = gid;
3719d5b6da9SMark F. Adams       real_gids[lid] = (PetscScalar)gid;
3729d5b6da9SMark F. Adams     }
3739d5b6da9SMark F. Adams     /* grab matrix objects */
3749d5b6da9SMark F. Adams     mpimat_2 = (Mat_MPIAIJ*)Gmat_2->data;
3759d5b6da9SMark F. Adams     mpimat_1 = (Mat_MPIAIJ*)Gmat_1->data;
3769d5b6da9SMark F. Adams     matA_1 = (Mat_SeqAIJ*)mpimat_1->A->data;
3779d5b6da9SMark F. Adams     matB_1 = (Mat_SeqAIJ*)mpimat_1->B->data;
3789d5b6da9SMark F. Adams     /* get ghost sizes */
3799d5b6da9SMark F. Adams     ierr = VecGetLocalSize( mpimat_1->lvec, &nghosts_1 ); CHKERRQ(ierr);
3809d5b6da9SMark F. Adams     ierr = VecGetLocalSize( mpimat_2->lvec, &nghosts_2 ); CHKERRQ(ierr);
3819d5b6da9SMark F. Adams     /* get 'cpcol_1_state' */
3829d5b6da9SMark F. Adams     ierr = MatGetVecs( Gmat_1, &tempVec, 0 );         CHKERRQ(ierr);
3839d5b6da9SMark F. Adams     if(nloc>0){
3849d5b6da9SMark F. Adams       ierr = VecSetValues( tempVec, nloc, gids, lid_state, INSERT_VALUES );  CHKERRQ(ierr);
3859d5b6da9SMark F. Adams     }
3869d5b6da9SMark F. Adams     ierr = VecAssemblyBegin( tempVec ); CHKERRQ(ierr);
3879d5b6da9SMark F. Adams     ierr = VecAssemblyEnd( tempVec ); CHKERRQ(ierr);
3889d5b6da9SMark F. Adams     ierr = VecScatterBegin(mpimat_1->Mvctx,tempVec, mpimat_1->lvec,INSERT_VALUES,SCATTER_FORWARD);
3899d5b6da9SMark F. Adams     CHKERRQ(ierr);
3909d5b6da9SMark F. Adams     ierr =   VecScatterEnd(mpimat_1->Mvctx,tempVec, mpimat_1->lvec,INSERT_VALUES,SCATTER_FORWARD);
3919d5b6da9SMark F. Adams     CHKERRQ(ierr);
3929d5b6da9SMark F. Adams     ierr = VecGetArray( mpimat_1->lvec, &cpcol_1_state ); CHKERRQ(ierr);
3939d5b6da9SMark F. Adams     ierr = VecDestroy( &tempVec ); CHKERRQ(ierr);
3949d5b6da9SMark F. Adams 
3959d5b6da9SMark F. Adams     ierr = PetscFree( gids );  CHKERRQ(ierr);
3969d5b6da9SMark F. Adams     ierr = PetscFree( real_gids );  CHKERRQ(ierr);
3979d5b6da9SMark F. Adams   } else {
3989d5b6da9SMark F. Adams     PetscBool      isAIJ;
3999d5b6da9SMark F. Adams     ierr = PetscTypeCompare( (PetscObject)Gmat_2, MATSEQAIJ, &isAIJ ); CHKERRQ(ierr);
4009d5b6da9SMark F. Adams     assert(isAIJ);
4019d5b6da9SMark F. Adams     matA_1 = (Mat_SeqAIJ*)Gmat_1->data;
4029d5b6da9SMark F. Adams     nghosts_2 = nghosts_1 = 0;
4039d5b6da9SMark F. Adams   }
4049d5b6da9SMark F. Adams   assert( matA_1 && !matA_1->compressedrow.use );
4059d5b6da9SMark F. Adams   assert( matB_1==0 || matB_1->compressedrow.use );
4069d5b6da9SMark F. Adams 
4079d5b6da9SMark F. Adams   {
4089d5b6da9SMark F. Adams     PetscInt *lid_cprowID_1;
4099d5b6da9SMark F. Adams     PetscInt *lid_sel_lid;
4109d5b6da9SMark F. Adams 
4119d5b6da9SMark F. Adams     ierr = PetscMalloc( nloc*sizeof(PetscInt), &lid_cprowID_1 ); CHKERRQ(ierr);
4129d5b6da9SMark F. Adams     ierr = PetscMalloc( nloc*sizeof(PetscInt), &lid_sel_lid ); CHKERRQ(ierr);
4139d5b6da9SMark F. Adams 
4149d5b6da9SMark F. Adams     /*reverse map to selelected node */
4159d5b6da9SMark F. Adams     for(lid=0;lid<nloc;lid++) lid_cprowID_1[lid] = lid_sel_lid[lid] = -1;
4169d5b6da9SMark F. Adams     for(lid=0;lid<nloc;lid++){
4179d5b6da9SMark F. Adams       NState state = (NState)PetscRealPart(lid_state[lid]);
4189d5b6da9SMark F. Adams       if( IS_SELECTED(state) ){
4199d5b6da9SMark F. Adams         PetscInt flid = lid;
4209d5b6da9SMark F. Adams         do{
4219d5b6da9SMark F. Adams           lid_sel_lid[flid] = lid; assert(flid<nloc);
4229d5b6da9SMark F. Adams         } while( (flid=id_llist[flid]) != -1 );
4239d5b6da9SMark F. Adams       }
4249d5b6da9SMark F. Adams     }
4259d5b6da9SMark F. Adams 
4269d5b6da9SMark F. Adams     /* set index into compressed row 'lid_cprowID' */
4279d5b6da9SMark F. Adams     if( matB_1 ) {
4289d5b6da9SMark F. Adams       ii = matB_1->compressedrow.i;
4299d5b6da9SMark F. Adams       for (ix=0; ix<matB_1->compressedrow.nrows; ix++) {
4309d5b6da9SMark F. Adams         PetscInt lid = matB_1->compressedrow.rindex[ix];
4319d5b6da9SMark F. Adams         lid_cprowID_1[lid] = ix;
4329d5b6da9SMark F. Adams       }
4339d5b6da9SMark F. Adams     }
4349d5b6da9SMark F. Adams 
4359d5b6da9SMark F. Adams     for(lid=0;lid<nloc;lid++){
4369d5b6da9SMark F. Adams       NState state = (NState)PetscRealPart(lid_state[lid]);
4379d5b6da9SMark F. Adams       if( IS_SELECTED(state) ) {
4389d5b6da9SMark F. Adams         /* steal locals */
4399d5b6da9SMark F. Adams         ii = matA_1->i; n = ii[lid+1] - ii[lid];
4409d5b6da9SMark F. Adams         idx = matA_1->j + ii[lid];
4419d5b6da9SMark F. Adams         for (j=0; j<n; j++) {
4429d5b6da9SMark F. Adams           PetscInt flid, lidj = idx[j];
4439d5b6da9SMark F. Adams           NState statej = (NState)PetscRealPart(lid_state[lidj]);
4449d5b6da9SMark F. Adams           if( statej==DELETED && lid_sel_lid[lidj] != lid ){ /* steal it */
4459d5b6da9SMark F. Adams 	    if( lid_sel_lid[lidj] != -1 ){
4469d5b6da9SMark F. Adams 	      /* I'm stealing this local */
4479d5b6da9SMark F. Adams 	      PetscInt hav=0, flid2 = lid_sel_lid[lidj], lastid; assert(flid2!=-1);
4489d5b6da9SMark F. Adams 	      for( lastid=flid2, flid=id_llist[flid2] ; flid!=-1 ; flid=id_llist[flid] ) {
4499d5b6da9SMark F. Adams 		if( flid == lidj ) {
4509d5b6da9SMark F. Adams 		  id_llist[lastid] = id_llist[lidj];                    /* remove lidj from list */
4519d5b6da9SMark F. Adams 		  id_llist[lidj] = id_llist[lid]; id_llist[lid] = lidj; /* insert 'lidj' into head of llist */
4529d5b6da9SMark F. Adams 		  hav++;
4539d5b6da9SMark F. Adams 		  /* break; */
4549d5b6da9SMark F. Adams 		}
4559d5b6da9SMark F. Adams 		lastid = flid;
4569d5b6da9SMark F. Adams 	      }
4579d5b6da9SMark F. Adams 	      if(hav!=1){
4589d5b6da9SMark F. Adams                 flid2 = lid_sel_lid[lidj];
4599d5b6da9SMark F. Adams 		if(hav!=0){
4609d5b6da9SMark F. Adams 		  SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,
4619d5b6da9SMark F. Adams 			   "found %d vertices.  (if %d==0) failed to find self in 'selected' lists.  probably structurally unsymmetric matrix",
4629d5b6da9SMark F. Adams 			   hav,hav);
4639d5b6da9SMark F. Adams 		}
4649d5b6da9SMark F. Adams 	      }
4659d5b6da9SMark F. Adams 	    }
4669d5b6da9SMark F. Adams 	    else{
4679d5b6da9SMark F. Adams 	      /* I'm stealing this local, owned by a ghost */
4689d5b6da9SMark F. Adams 	      deleted_parent_gid[lidj] = (PetscScalar)(lid+my0); /* this makes it a no-op later */
4699d5b6da9SMark F. Adams 	      lid_sel_lid[lidj] = lid; /* not needed */
4709d5b6da9SMark F. Adams 	      id_llist[lidj] = id_llist[lid]; id_llist[lid] = lidj; /* insert 'lidj' into head of llist */
4719d5b6da9SMark F. Adams 	    }
4729d5b6da9SMark F. Adams 	  }
4739d5b6da9SMark F. Adams         }
4749d5b6da9SMark F. Adams         /* ghosts are done by 'DELETED' branch */
4759d5b6da9SMark F. Adams       }
4769d5b6da9SMark F. Adams       else if( state == DELETED ) {
4779d5b6da9SMark F. Adams         /* see if I have a selected ghost neighbors */
4789d5b6da9SMark F. Adams         if( (ix=lid_cprowID_1[lid]) != -1 ) {
4799d5b6da9SMark F. Adams           PetscInt hav = 0, old_sel_lid = lid_sel_lid[lid], lastid; assert(old_sel_lid<nloc);
4809d5b6da9SMark F. Adams           ii = matB_1->compressedrow.i; n = ii[ix+1] - ii[ix];
4819d5b6da9SMark F. Adams           idx = matB_1->j + ii[ix];
4829d5b6da9SMark F. Adams           for( j=0 ; j<n ; j++ ) {
4839d5b6da9SMark F. Adams             PetscInt cpid = idx[j];
4849d5b6da9SMark F. Adams             NState statej = (NState)PetscRealPart(cpcol_1_state[cpid]);
4859d5b6da9SMark F. Adams             if( IS_SELECTED(statej) ) {
4869d5b6da9SMark F. Adams               PetscInt new_sel_gid = (PetscInt)statej, hv=0, flid;
4879d5b6da9SMark F. Adams               hav++;
4889d5b6da9SMark F. Adams               /* remove from list */
4899d5b6da9SMark F. Adams 	      if( old_sel_lid != -1 ) {
4909d5b6da9SMark F. Adams 		/* assert(deleted_parent_gid[lid]==-1.0 ); */
4919d5b6da9SMark F. Adams 		for( lastid=old_sel_lid, flid=id_llist[old_sel_lid] ; flid != -1 ; flid=id_llist[flid] ) {
4929d5b6da9SMark F. Adams 		  if( flid == lid ) {
4939d5b6da9SMark F. Adams 		    id_llist[lastid] = id_llist[lid];   /* remove lid from 'old_sel_lid' list */
4949d5b6da9SMark F. Adams 		    hv++;
4959d5b6da9SMark F. Adams 		    break;
4969d5b6da9SMark F. Adams 		  }
4979d5b6da9SMark F. Adams 		  lastid = flid;
4989d5b6da9SMark F. Adams 		}
4999d5b6da9SMark F. Adams 		/* assert(hv==1); */
5009d5b6da9SMark F. Adams 	      }
5019d5b6da9SMark F. Adams 	      else {
5029d5b6da9SMark F. Adams 		assert(deleted_parent_gid[lid] != -1.0); /* stealing from one ghost, giving to another */
5039d5b6da9SMark F. Adams 	      }
5049d5b6da9SMark F. Adams 
5059d5b6da9SMark F. Adams 	      /* this will get other proc to add this */
5069d5b6da9SMark F. Adams               deleted_parent_gid[lid] = (PetscScalar)new_sel_gid;
5079d5b6da9SMark F. Adams 	    }
5089d5b6da9SMark F. Adams           }
5099d5b6da9SMark F. Adams           assert(hav <= 1);
5109d5b6da9SMark F. Adams         }
5119d5b6da9SMark F. Adams       }
5129d5b6da9SMark F. Adams     }
5139d5b6da9SMark F. Adams 
5149d5b6da9SMark F. Adams     ierr = PetscFree( lid_cprowID_1 );  CHKERRQ(ierr);
5159d5b6da9SMark F. Adams     ierr = PetscFree( lid_sel_lid );  CHKERRQ(ierr);
5169d5b6da9SMark F. Adams   }
5179d5b6da9SMark F. Adams 
5189d5b6da9SMark F. Adams   if(isMPI) {
5199d5b6da9SMark F. Adams     ierr = VecRestoreArray( mpimat_1->lvec, &cpcol_1_state ); CHKERRQ(ierr);
5209d5b6da9SMark F. Adams   }
5219d5b6da9SMark F. Adams 
5229d5b6da9SMark F. Adams   PetscFunctionReturn(0);
5239d5b6da9SMark F. Adams }
5249d5b6da9SMark F. Adams 
5259d5b6da9SMark F. Adams /* -------------------------------------------------------------------------- */
5269d5b6da9SMark F. Adams /*
5279d5b6da9SMark F. Adams    maxIndSetAgg - parallel maximal independent set (MIS) with data locality info.
5289d5b6da9SMark F. Adams 
5299d5b6da9SMark F. Adams    Input Parameter:
5309d5b6da9SMark F. Adams    . perm - serial permutation of rows of local to process in MIS
5319d5b6da9SMark F. Adams    . Gmat - glabal matrix of graph (data not defined)
5329d5b6da9SMark F. Adams    . Auxmat - non-squared matrix
5339d5b6da9SMark F. Adams    . strict_aggs - flag for whether to keep strict (non overlapping) aggregates in 'llist';
5349d5b6da9SMark F. Adams    Output Parameter:
5359d5b6da9SMark F. Adams    . a_selected - IS of selected vertices, includes 'ghost' nodes at end with natural local indices
5369d5b6da9SMark F. Adams    . a_locals_llist - linked list of local nodes rooted at selected node (size is nloc + nghosts)
5379d5b6da9SMark F. Adams */
5389d5b6da9SMark F. Adams #undef __FUNCT__
5399d5b6da9SMark F. Adams #define __FUNCT__ "maxIndSetAgg"
5409d5b6da9SMark F. Adams PetscErrorCode maxIndSetAgg( const IS perm,
5419d5b6da9SMark F. Adams                              const Mat Gmat,
5429d5b6da9SMark F. Adams                              const Mat Auxmat,
5439d5b6da9SMark F. Adams 			     const PetscBool strict_aggs,
5449d5b6da9SMark F. Adams                              IS *a_selected,
5459d5b6da9SMark F. Adams                              IS *a_locals_llist
5469d5b6da9SMark F. Adams                              )
5479d5b6da9SMark F. Adams {
5489d5b6da9SMark F. Adams   PetscErrorCode ierr;
5499d5b6da9SMark F. Adams   PetscBool      isMPI;
5509d5b6da9SMark F. Adams   Mat_SeqAIJ    *matA, *matB = 0;
5519d5b6da9SMark F. Adams   MPI_Comm       wcomm = ((PetscObject)Gmat)->comm;
5529d5b6da9SMark F. Adams   Vec            locState, ghostState;
5539d5b6da9SMark F. Adams   PetscInt       num_fine_ghosts,kk,n,ix,j,*idx,*ii,iter,Iend,my0;
5549d5b6da9SMark F. Adams   Mat_MPIAIJ    *mpimat = 0;
5559d5b6da9SMark F. Adams   PetscScalar   *cpcol_gid,*cpcol_state;
5569d5b6da9SMark F. Adams   PetscMPIInt    mype;
5579d5b6da9SMark F. Adams   const PetscInt *perm_ix;
5589d5b6da9SMark F. Adams   PetscInt nDone = 0, nselected = 0;
5599d5b6da9SMark F. Adams   const PetscInt nloc = Gmat->rmap->n;
5609d5b6da9SMark F. Adams 
5619d5b6da9SMark F. Adams   PetscFunctionBegin;
5629d5b6da9SMark F. Adams   ierr = MPI_Comm_rank( wcomm, &mype );   CHKERRQ(ierr);
5639d5b6da9SMark F. Adams   /* get submatrices */
5649d5b6da9SMark F. Adams   ierr = PetscTypeCompare( (PetscObject)Gmat, MATMPIAIJ, &isMPI ); CHKERRQ(ierr);
5659d5b6da9SMark F. Adams   if (isMPI) {
5669d5b6da9SMark F. Adams     mpimat = (Mat_MPIAIJ*)Gmat->data;
5679d5b6da9SMark F. Adams     matA = (Mat_SeqAIJ*)mpimat->A->data;
5689d5b6da9SMark F. Adams     matB = (Mat_SeqAIJ*)mpimat->B->data;
5699d5b6da9SMark F. Adams   } else {
5709d5b6da9SMark F. Adams     PetscBool      isAIJ;
5719d5b6da9SMark F. Adams     ierr = PetscTypeCompare( (PetscObject)Gmat, MATSEQAIJ, &isAIJ ); CHKERRQ(ierr);
5729d5b6da9SMark F. Adams     assert(isAIJ);
5739d5b6da9SMark F. Adams     matA = (Mat_SeqAIJ*)Gmat->data;
5749d5b6da9SMark F. Adams   }
5759d5b6da9SMark F. Adams   assert( matA && !matA->compressedrow.use );
5769d5b6da9SMark F. Adams   assert( matB==0 || matB->compressedrow.use );
5779d5b6da9SMark F. Adams   /* get vector */
5789d5b6da9SMark F. Adams   ierr = MatGetVecs( Gmat, &locState, 0 );         CHKERRQ(ierr);
5799d5b6da9SMark F. Adams 
5809d5b6da9SMark F. Adams   ierr = MatGetOwnershipRange(Gmat,&my0,&Iend);  CHKERRQ(ierr);
5819d5b6da9SMark F. Adams 
5829d5b6da9SMark F. Adams   if( mpimat ) {
5839d5b6da9SMark F. Adams     PetscInt gid;
5849d5b6da9SMark F. Adams     for(kk=0,gid=my0;kk<nloc;kk++,gid++) {
5859d5b6da9SMark F. Adams       PetscScalar v = (PetscScalar)(gid);
5869d5b6da9SMark F. Adams       ierr = VecSetValues( locState, 1, &gid, &v, INSERT_VALUES );  CHKERRQ(ierr); /* set with GID */
5879d5b6da9SMark F. Adams     }
5889d5b6da9SMark F. Adams     ierr = VecAssemblyBegin( locState ); CHKERRQ(ierr);
5899d5b6da9SMark F. Adams     ierr = VecAssemblyEnd( locState ); CHKERRQ(ierr);
5909d5b6da9SMark F. Adams     ierr = VecScatterBegin(mpimat->Mvctx,locState,mpimat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5919d5b6da9SMark F. Adams     ierr =   VecScatterEnd(mpimat->Mvctx,locState,mpimat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5929d5b6da9SMark F. Adams     ierr = VecGetArray( mpimat->lvec, &cpcol_gid ); CHKERRQ(ierr); /* get proc ID in 'cpcol_gid' */
5939d5b6da9SMark F. Adams     ierr = VecDuplicate( mpimat->lvec, &ghostState ); CHKERRQ(ierr); /* need 2nd compressed col. of off proc data */
5949d5b6da9SMark F. Adams     ierr = VecGetLocalSize( mpimat->lvec, &num_fine_ghosts ); CHKERRQ(ierr);
5959d5b6da9SMark F. Adams     ierr = VecSet( ghostState, (PetscScalar)((PetscReal)NOT_DONE) );  CHKERRQ(ierr); /* set with UNKNOWN state */
5969d5b6da9SMark F. Adams   }
5979d5b6da9SMark F. Adams   else num_fine_ghosts = 0;
5989d5b6da9SMark F. Adams 
5999d5b6da9SMark F. Adams   {  /* need an inverse map - locals */
6009d5b6da9SMark F. Adams     PetscInt *lid_cprowID, *lid_gid;
6019d5b6da9SMark F. Adams     PetscScalar *deleted_parent_gid; /* only used for strict aggs */
6029d5b6da9SMark F. Adams     PetscInt *id_llist; /* linked list with locality info - output */
6039d5b6da9SMark F. Adams     PetscScalar *lid_state;
6049d5b6da9SMark F. Adams 
6059d5b6da9SMark F. Adams     ierr = PetscMalloc( nloc*sizeof(PetscInt), &lid_cprowID ); CHKERRQ(ierr);
6069d5b6da9SMark F. Adams     ierr = PetscMalloc( (nloc+1)*sizeof(PetscInt), &lid_gid ); CHKERRQ(ierr);
6079d5b6da9SMark F. Adams     ierr = PetscMalloc( (nloc+1)*sizeof(PetscScalar), &deleted_parent_gid ); CHKERRQ(ierr);
6089d5b6da9SMark F. Adams     ierr = PetscMalloc( (nloc+num_fine_ghosts)*sizeof(PetscInt), &id_llist ); CHKERRQ(ierr);
6099d5b6da9SMark F. Adams     ierr = PetscMalloc( (nloc+1)*sizeof(PetscScalar), &lid_state ); CHKERRQ(ierr);
6109d5b6da9SMark F. Adams 
6119d5b6da9SMark F. Adams     for(kk=0;kk<nloc;kk++) {
6129d5b6da9SMark F. Adams       id_llist[kk] = -1; /* terminates linked lists */
6139d5b6da9SMark F. Adams       lid_cprowID[kk] = -1;
6149d5b6da9SMark F. Adams       deleted_parent_gid[kk] = -1.0;
6159d5b6da9SMark F. Adams       lid_gid[kk] = kk + my0;
6169d5b6da9SMark F. Adams       lid_state[kk] =  (PetscScalar)((PetscReal)NOT_DONE);
6179d5b6da9SMark F. Adams     }
6189d5b6da9SMark F. Adams     for(ix=0;kk<nloc+num_fine_ghosts;kk++,ix++) {
6199d5b6da9SMark F. Adams       id_llist[kk] = -1; /* terminates linked lists */
6209d5b6da9SMark F. Adams     }
6219d5b6da9SMark F. Adams     /* set index into cmpressed row 'lid_cprowID' */
6229d5b6da9SMark F. Adams     if( matB ) {
6239d5b6da9SMark F. Adams       ii = matB->compressedrow.i;
6249d5b6da9SMark F. Adams       for (ix=0; ix<matB->compressedrow.nrows; ix++) {
6259d5b6da9SMark F. Adams         PetscInt lid = matB->compressedrow.rindex[ix];
6269d5b6da9SMark F. Adams         lid_cprowID[lid] = ix;
6279d5b6da9SMark F. Adams       }
6289d5b6da9SMark F. Adams     }
6299d5b6da9SMark F. Adams     /* MIS */
6309d5b6da9SMark F. Adams     ierr = ISGetIndices( perm, &perm_ix );     CHKERRQ(ierr);
6319d5b6da9SMark F. Adams     iter = 0;
6329d5b6da9SMark F. Adams     while ( nDone < nloc || PETSC_TRUE ) { /* asyncronous not implemented */
6339d5b6da9SMark F. Adams       iter++;
6349d5b6da9SMark F. Adams       if( mpimat ) {
6359d5b6da9SMark F. Adams         ierr = VecGetArray( ghostState, &cpcol_state ); CHKERRQ(ierr);
6369d5b6da9SMark F. Adams       }
6379d5b6da9SMark F. Adams       /* check all vertices */
6389d5b6da9SMark F. Adams       for(kk=0;kk<nloc;kk++){
6399d5b6da9SMark F. Adams         PetscInt lid = perm_ix[kk];
6409d5b6da9SMark F. Adams         NState state = (NState)PetscRealPart(lid_state[lid]);
6419d5b6da9SMark F. Adams         if( state == NOT_DONE ) {
6429d5b6da9SMark F. Adams           /* parallel test, delete if selected ghost */
6439d5b6da9SMark F. Adams           PetscBool isOK = PETSC_TRUE;
6449d5b6da9SMark F. Adams           if( (ix=lid_cprowID[lid]) != -1 ) { /* if I have any ghost neighbors */
6459d5b6da9SMark F. Adams             ii = matB->compressedrow.i; n = ii[ix+1] - ii[ix];
6469d5b6da9SMark F. Adams             idx = matB->j + ii[ix];
6479d5b6da9SMark F. Adams             for( j=0 ; j<n ; j++ ) {
6489d5b6da9SMark F. Adams               PetscInt cpid = idx[j]; /* compressed row ID in B mat */
6499d5b6da9SMark F. Adams               PetscInt gid = (PetscInt)PetscRealPart(cpcol_gid[cpid]);
6509d5b6da9SMark F. Adams               NState statej = (NState)PetscRealPart(cpcol_state[cpid]);
6519d5b6da9SMark F. Adams               if( statej == NOT_DONE && gid >= Iend ) { /* should be (pe>mype), use gid as pe proxy */
6529d5b6da9SMark F. Adams                 isOK = PETSC_FALSE; /* can not delete */
6539d5b6da9SMark F. Adams               }
6549d5b6da9SMark F. Adams               else if( IS_SELECTED(statej) ) { /* lid is now deleted, do it */
6559d5b6da9SMark F. Adams 		assert(0);
6569d5b6da9SMark F. Adams               }
6579d5b6da9SMark F. Adams             }
6589d5b6da9SMark F. Adams           } /* parallel test */
6599d5b6da9SMark F. Adams           if( isOK ){ /* select or remove this vertex */
6609d5b6da9SMark F. Adams             nDone++;
6619d5b6da9SMark F. Adams             /* check for singleton */
6629d5b6da9SMark F. Adams             ii = matA->i; n = ii[lid+1] - ii[lid];
6639d5b6da9SMark F. Adams             if( n < 2 ) {
6649d5b6da9SMark F. Adams               /* if I have any ghost adj then not a sing */
6659d5b6da9SMark F. Adams               ix = lid_cprowID[lid];
6669d5b6da9SMark F. Adams               if( ix==-1 || (matB->compressedrow.i[ix+1]-matB->compressedrow.i[ix])==0 ){
6679d5b6da9SMark F. Adams                 lid_state[lid] =  (PetscScalar)((PetscReal)REMOVED);
6689d5b6da9SMark F. Adams                 continue; /* one local adj (me) and no ghost - singleton - flag and continue */
6699d5b6da9SMark F. Adams               }
6709d5b6da9SMark F. Adams             }
6719d5b6da9SMark F. Adams             /* SELECTED state encoded with global index */
6729d5b6da9SMark F. Adams             lid_state[lid] =  (PetscScalar)(lid+my0);
6739d5b6da9SMark F. Adams             nselected++;
6749d5b6da9SMark F. Adams 	    /* delete local adj */
6759d5b6da9SMark F. Adams 	    idx = matA->j + ii[lid];
6769d5b6da9SMark F. Adams 	    for (j=0; j<n; j++) {
6779d5b6da9SMark F. Adams               PetscInt lidj = idx[j];
6789d5b6da9SMark F. Adams               NState statej = (NState)PetscRealPart(lid_state[lidj]);
6799d5b6da9SMark F. Adams               if( statej == NOT_DONE ){
6809d5b6da9SMark F. Adams                 nDone++;
6819d5b6da9SMark F. Adams                 id_llist[lidj] = id_llist[lid]; id_llist[lid] = lidj; /* insert 'lidj' into head of llist */
6829d5b6da9SMark F. Adams                 lid_state[lidj] = (PetscScalar)(PetscReal)DELETED;  /* delete this */
6839d5b6da9SMark F. Adams               }
6849d5b6da9SMark F. Adams             }
6859d5b6da9SMark F. Adams 
6869d5b6da9SMark F. Adams             /* delete ghost adj - deleted ghost done later for aggregation */
6879d5b6da9SMark F. Adams             if( !strict_aggs ) {
6889d5b6da9SMark F. Adams               if( (ix=lid_cprowID[lid]) != -1 ) { /* if I have any ghost neighbors */
6899d5b6da9SMark F. Adams                 ii = matB->compressedrow.i; n = ii[ix+1] - ii[ix];
6909d5b6da9SMark F. Adams                 idx = matB->j + ii[ix];
6919d5b6da9SMark F. Adams                 for( j=0 ; j<n ; j++ ) {
6929d5b6da9SMark F. Adams                   PetscInt cpid = idx[j]; /* compressed row ID in B mat */
6939d5b6da9SMark F. Adams                   NState statej = (NState)PetscRealPart(cpcol_state[cpid]);
6949d5b6da9SMark F. Adams                   assert( !IS_SELECTED(statej) );
6959d5b6da9SMark F. Adams 
6969d5b6da9SMark F. Adams 		  if( statej == NOT_DONE ) {
6979d5b6da9SMark F. Adams 		    PetscInt lidj = nloc + cpid;
6989d5b6da9SMark F. Adams 		    /* cpcol_state[cpid] = (PetscScalar)DELETED; this should happen later ... */
6999d5b6da9SMark F. Adams 		    id_llist[lidj] = id_llist[lid]; id_llist[lid] = lidj; /* insert 'lidj' into head of llist */
7009d5b6da9SMark F. Adams 		  }
7019d5b6da9SMark F. Adams 		}
7029d5b6da9SMark F. Adams 	      }
7039d5b6da9SMark F. Adams 	    }
7049d5b6da9SMark F. Adams 
7059d5b6da9SMark F. Adams           } /* selected */
7069d5b6da9SMark F. Adams         } /* not done vertex */
7079d5b6da9SMark F. Adams       } /* vertex loop */
7089d5b6da9SMark F. Adams 
7099d5b6da9SMark F. Adams       /* update ghost states and count todos */
7109d5b6da9SMark F. Adams       if( mpimat ) {
7119d5b6da9SMark F. Adams         PetscInt t1, t2;
7129d5b6da9SMark F. Adams         ierr = VecRestoreArray( ghostState, &cpcol_state ); CHKERRQ(ierr);
7139d5b6da9SMark F. Adams         /* put lid state in 'locState' */
7149d5b6da9SMark F. Adams         ierr = VecSetValues( locState, nloc, lid_gid, lid_state, INSERT_VALUES ); CHKERRQ(ierr);
7159d5b6da9SMark F. Adams         ierr = VecAssemblyBegin( locState ); CHKERRQ(ierr);
7169d5b6da9SMark F. Adams         ierr = VecAssemblyEnd( locState ); CHKERRQ(ierr);
7179d5b6da9SMark F. Adams         /* scatter states, check for done */
7189d5b6da9SMark F. Adams         ierr = VecScatterBegin(mpimat->Mvctx,locState,ghostState,INSERT_VALUES,SCATTER_FORWARD);
7199d5b6da9SMark F. Adams         CHKERRQ(ierr);
7209d5b6da9SMark F. Adams         ierr =   VecScatterEnd(mpimat->Mvctx,locState,ghostState,INSERT_VALUES,SCATTER_FORWARD);
7219d5b6da9SMark F. Adams         CHKERRQ(ierr);
7229d5b6da9SMark F. Adams 	/* delete locals from selected ghosts */
7239d5b6da9SMark F. Adams         ierr = VecGetArray( ghostState, &cpcol_state ); CHKERRQ(ierr);
7249d5b6da9SMark F. Adams 	ii = matB->compressedrow.i;
7259d5b6da9SMark F. Adams 	for (ix=0; ix<matB->compressedrow.nrows; ix++) {
7269d5b6da9SMark F. Adams 	  PetscInt lid = matB->compressedrow.rindex[ix];
7279d5b6da9SMark F. Adams 	  NState state = (NState)PetscRealPart(lid_state[lid]);
7289d5b6da9SMark F. Adams 	  if( state == NOT_DONE ) {
7299d5b6da9SMark F. Adams 	    /* look at ghosts */
7309d5b6da9SMark F. Adams 	    n = ii[ix+1] - ii[ix];
7319d5b6da9SMark F. Adams 	    idx = matB->j + ii[ix];
7329d5b6da9SMark F. Adams             for( j=0 ; j<n ; j++ ) {
7339d5b6da9SMark F. Adams               PetscInt cpid = idx[j]; /* compressed row ID in B mat */
7349d5b6da9SMark F. Adams               NState statej = (NState)PetscRealPart(cpcol_state[cpid]);
7359d5b6da9SMark F. Adams               if( IS_SELECTED(statej) ) { /* lid is now deleted, do it */
7369d5b6da9SMark F. Adams                 PetscInt lidj = nloc + cpid;
7379d5b6da9SMark F. Adams                 nDone++;
7389d5b6da9SMark F. Adams 		lid_state[lid] = (PetscScalar)(PetscReal)DELETED; /* delete this */
7399d5b6da9SMark F. Adams 		if( !strict_aggs ) {
7409d5b6da9SMark F. Adams 		  id_llist[lid] = id_llist[lidj]; id_llist[lidj] = lid; /* insert 'lid' into head of ghost llist */
7419d5b6da9SMark F. Adams 		}
7429d5b6da9SMark F. Adams 		else {
7439d5b6da9SMark F. Adams                   PetscInt gid = (PetscInt)PetscRealPart(cpcol_gid[cpid]);
7449d5b6da9SMark F. Adams 		  deleted_parent_gid[lid] = (PetscScalar)gid; /* keep track of proc that I belong to */
7459d5b6da9SMark F. Adams 		}
7469d5b6da9SMark F. Adams 		break;
7479d5b6da9SMark F. Adams 	      }
7489d5b6da9SMark F. Adams 	    }
7499d5b6da9SMark F. Adams 	  }
7509d5b6da9SMark F. Adams 	}
7519d5b6da9SMark F. Adams         ierr = VecRestoreArray( ghostState, &cpcol_state ); CHKERRQ(ierr);
7529d5b6da9SMark F. Adams 
7539d5b6da9SMark F. Adams 	/* all done? */
7549d5b6da9SMark F. Adams         t1 = nloc - nDone; assert(t1>=0);
7559d5b6da9SMark F. Adams         ierr = MPI_Allreduce ( &t1, &t2, 1, MPIU_INT, MPIU_SUM, wcomm ); /* synchronous version */
7569d5b6da9SMark F. Adams         if( t2 == 0 ) break;
7579d5b6da9SMark F. Adams       }
7589d5b6da9SMark F. Adams       else break; /* all done */
7599d5b6da9SMark F. Adams     } /* outer parallel MIS loop */
7609d5b6da9SMark F. Adams     ierr = ISRestoreIndices(perm,&perm_ix);     CHKERRQ(ierr);
7619d5b6da9SMark F. Adams 
7629d5b6da9SMark F. Adams     if( mpimat ){ /* free this buffer up (not really needed here) */
7639d5b6da9SMark F. Adams       ierr = VecRestoreArray( mpimat->lvec, &cpcol_gid ); CHKERRQ(ierr);
7649d5b6da9SMark F. Adams     }
7659d5b6da9SMark F. Adams 
7669d5b6da9SMark F. Adams     /* adjust aggregates */
7679d5b6da9SMark F. Adams     if( strict_aggs ) {
7689d5b6da9SMark F. Adams       ierr = smoothAggs(Gmat, Auxmat, lid_state, id_llist, deleted_parent_gid);
7699d5b6da9SMark F. Adams       CHKERRQ(ierr);
7709d5b6da9SMark F. Adams     }
7719d5b6da9SMark F. Adams 
7729d5b6da9SMark F. Adams     /* tell adj who my deleted vertices belong to */
7739d5b6da9SMark F. Adams     if( strict_aggs && matB ) {
7749d5b6da9SMark F. Adams       PetscScalar *cpcol_sel_gid;
7759d5b6da9SMark F. Adams       PetscInt cpid;
7769d5b6da9SMark F. Adams       /* get proc of deleted ghost */
7779d5b6da9SMark F. Adams       ierr = VecSetValues(locState, nloc, lid_gid, deleted_parent_gid, INSERT_VALUES); CHKERRQ(ierr);
7789d5b6da9SMark F. Adams       ierr = VecAssemblyBegin(locState); CHKERRQ(ierr);
7799d5b6da9SMark F. Adams       ierr = VecAssemblyEnd(locState); CHKERRQ(ierr);
7809d5b6da9SMark F. Adams       ierr = VecScatterBegin(mpimat->Mvctx,locState,mpimat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7819d5b6da9SMark F. Adams       ierr =   VecScatterEnd(mpimat->Mvctx,locState,mpimat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7829d5b6da9SMark F. Adams       ierr = VecGetArray( mpimat->lvec, &cpcol_sel_gid ); CHKERRQ(ierr); /* has pe that owns ghost */
7839d5b6da9SMark F. Adams       for(cpid=0; cpid<num_fine_ghosts; cpid++) {
7849d5b6da9SMark F. Adams         PetscInt gid = (PetscInt)PetscRealPart(cpcol_sel_gid[cpid]);
7859d5b6da9SMark F. Adams 	if( gid >= my0 && gid < Iend ) { /* I own this deleted */
7869d5b6da9SMark F. Adams 	  PetscInt lidj = nloc + cpid;
7879d5b6da9SMark F. Adams 	  PetscInt lid = gid - my0;
7889d5b6da9SMark F. Adams 	  id_llist[lidj] = id_llist[lid]; id_llist[lid] = lidj; /* insert 'lidj' into head of llist */
7899d5b6da9SMark F. Adams 	  assert(IS_SELECTED( (NState)PetscRealPart(lid_state[lid]) ));
7909d5b6da9SMark F. Adams 	}
7919d5b6da9SMark F. Adams       }
7929d5b6da9SMark F. Adams       ierr = VecRestoreArray( mpimat->lvec, &cpcol_sel_gid ); CHKERRQ(ierr);
7939d5b6da9SMark F. Adams     }
7949d5b6da9SMark F. Adams 
7959d5b6da9SMark F. Adams     /* create output IS of aggregates in linked list */
7969d5b6da9SMark F. Adams     ierr = ISCreateGeneral(PETSC_COMM_SELF,nloc+num_fine_ghosts,id_llist,PETSC_COPY_VALUES,a_locals_llist);
7979d5b6da9SMark F. Adams     CHKERRQ(ierr);
7989d5b6da9SMark F. Adams 
7999d5b6da9SMark F. Adams     /* make 'a_selected' - output */
8009d5b6da9SMark F. Adams     if( mpimat ) {
8019d5b6da9SMark F. Adams       ierr = VecGetArray( ghostState, &cpcol_state ); CHKERRQ(ierr);
8029d5b6da9SMark F. Adams     }
8039d5b6da9SMark F. Adams     for (j=0; j<num_fine_ghosts; j++) {
8049d5b6da9SMark F. Adams       if( IS_SELECTED( (NState)PetscRealPart(cpcol_state[j]) ) ) nselected++;
8059d5b6da9SMark F. Adams     }
8069d5b6da9SMark F. Adams     {
8079d5b6da9SMark F. Adams       PetscInt *selected_set;
8089d5b6da9SMark F. Adams       ierr = PetscMalloc( nselected*sizeof(PetscInt), &selected_set ); CHKERRQ(ierr);
8099d5b6da9SMark F. Adams       for(kk=0,j=0;kk<nloc;kk++){
8109d5b6da9SMark F. Adams         NState state = (NState)PetscRealPart(lid_state[kk]);
8119d5b6da9SMark F. Adams         if( IS_SELECTED(state) ) {
8129d5b6da9SMark F. Adams           selected_set[j++] = kk;
8139d5b6da9SMark F. Adams         }
8149d5b6da9SMark F. Adams       }
8159d5b6da9SMark F. Adams       for (kk=0; kk<num_fine_ghosts; kk++) {
8169d5b6da9SMark F. Adams         if( IS_SELECTED( (NState)PetscRealPart(cpcol_state[kk]) ) ) {
8179d5b6da9SMark F. Adams           selected_set[j++] = nloc + kk;
8189d5b6da9SMark F. Adams         }
8199d5b6da9SMark F. Adams       }
8209d5b6da9SMark F. Adams       assert(j==nselected);
8219d5b6da9SMark F. Adams       ierr = ISCreateGeneral(PETSC_COMM_SELF, nselected, selected_set, PETSC_COPY_VALUES, a_selected );
8229d5b6da9SMark F. Adams       CHKERRQ(ierr);
8239d5b6da9SMark F. Adams       ierr = PetscFree( selected_set );  CHKERRQ(ierr);
8249d5b6da9SMark F. Adams     }
8259d5b6da9SMark F. Adams     if( mpimat ) {
8269d5b6da9SMark F. Adams       ierr = VecRestoreArray( ghostState, &cpcol_state ); CHKERRQ(ierr);
8279d5b6da9SMark F. Adams     }
8289d5b6da9SMark F. Adams 
8299d5b6da9SMark F. Adams     ierr = PetscFree( lid_cprowID );  CHKERRQ(ierr);
8309d5b6da9SMark F. Adams     ierr = PetscFree( lid_gid );  CHKERRQ(ierr);
8319d5b6da9SMark F. Adams     ierr = PetscFree( deleted_parent_gid );  CHKERRQ(ierr);
8329d5b6da9SMark F. Adams     ierr = PetscFree( id_llist );  CHKERRQ(ierr);
8339d5b6da9SMark F. Adams     ierr = PetscFree( lid_state );  CHKERRQ(ierr);
8349d5b6da9SMark F. Adams   } /* scoping */
8359d5b6da9SMark F. Adams 
8369d5b6da9SMark F. Adams   if(mpimat){
8379d5b6da9SMark F. Adams     ierr = VecDestroy( &ghostState ); CHKERRQ(ierr);
8389d5b6da9SMark F. Adams   }
8399d5b6da9SMark F. Adams 
8409d5b6da9SMark F. Adams   ierr = VecDestroy( &locState );                    CHKERRQ(ierr);
8419d5b6da9SMark F. Adams 
8429d5b6da9SMark F. Adams   PetscFunctionReturn(0);
8439d5b6da9SMark F. Adams }
844d3d6bff4SMark F. Adams 
845d3d6bff4SMark F. Adams /* ----------------------------------------------------------------------------- */
846d3d6bff4SMark F. Adams #undef __FUNCT__
847d3d6bff4SMark F. Adams #define __FUNCT__ "PCReset_GAMG"
848d3d6bff4SMark F. Adams PetscErrorCode PCReset_GAMG(PC pc)
849d3d6bff4SMark F. Adams {
850d3d6bff4SMark F. Adams   PetscErrorCode  ierr;
851d3d6bff4SMark F. Adams   PC_MG           *mg = (PC_MG*)pc->data;
852d3d6bff4SMark F. Adams   PC_GAMG         *pc_gamg = (PC_GAMG*)mg->innerctx;
853d3d6bff4SMark F. Adams 
854d3d6bff4SMark F. Adams   PetscFunctionBegin;
8559d5b6da9SMark F. Adams   if( pc_gamg->data != 0 ) { /* this should not happen, cleaned up in SetUp */
8569d5b6da9SMark F. Adams     ierr = PetscFree(pc_gamg->data); CHKERRQ(ierr);
85758471d46SMark F. Adams   }
8589d5b6da9SMark F. Adams   pc_gamg->data = 0; pc_gamg->data_sz = 0;
859d3d6bff4SMark F. Adams   PetscFunctionReturn(0);
860d3d6bff4SMark F. Adams }
861d3d6bff4SMark F. Adams 
8625b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */
8635b89ad90SMark F. Adams /*
864a147abb0SMark F. Adams    createLevel: create coarse op with RAP.  repartition and/or reduce number
865a147abb0SMark F. Adams      of active processors.
8665b89ad90SMark F. Adams 
8675b89ad90SMark F. Adams    Input Parameter:
8689d5b6da9SMark F. Adams    . pc - parameters
8699d5b6da9SMark F. Adams    . Amat_fine - matrix on this fine (k) level
8709d5b6da9SMark F. Adams    . ndata_rows - size of data to move (coarse grid)
8719d5b6da9SMark F. Adams    . ndata_cols - size of data to move (coarse grid)
8729d5b6da9SMark F. Adams    . cbs - coarse block size
8739d5b6da9SMark F. Adams    . isLast -
8743530afc2SMark F. Adams    In/Output Parameter:
8753530afc2SMark F. Adams    . a_P_inout - prolongation operator to the next level (k-1)
876eb07cef2SMark F. Adams    . a_coarse_data - data that need to be moved
877afc97cdcSMark F. Adams    . a_nactive_proc - number of active procs
87811e60469SMark F. Adams    Output Parameter:
8793530afc2SMark F. Adams    . a_Amat_crs - coarse matrix that is created (k-1)
8805b89ad90SMark F. Adams */
8815cb416c2SMark F. Adams 
8825b89ad90SMark F. Adams #undef __FUNCT__
8838263b398SMark F. Adams #define __FUNCT__ "createLevel"
8849d5b6da9SMark F. Adams PetscErrorCode createLevel( const PC pc,
8859d5b6da9SMark F. Adams                             const Mat Amat_fine,
8869d5b6da9SMark F. Adams                             const PetscInt ndata_rows,
8879d5b6da9SMark F. Adams                             const PetscInt ndata_cols,
8889d5b6da9SMark F. Adams                             const PetscInt cbs,
8899d5b6da9SMark F. Adams                             const PetscBool isLast,
8903530afc2SMark F. Adams                             Mat *a_P_inout,
891eb07cef2SMark F. Adams                             PetscReal **a_coarse_data,
892afc97cdcSMark F. Adams                             PetscMPIInt *a_nactive_proc,
893389730f3SMark F. Adams                             Mat *a_Amat_crs
89411e60469SMark F. Adams                             )
8955b89ad90SMark F. Adams {
8969d5b6da9SMark F. Adams   PC_MG           *mg = (PC_MG*)pc->data;
897486a8d0bSJed Brown   PC_GAMG         *pc_gamg = (PC_GAMG*)mg->innerctx;
8989d5b6da9SMark F. Adams   const PetscBool  repart = pc_gamg->repart;
8999d5b6da9SMark F. Adams   const PetscInt   min_eq_proc = pc_gamg->min_eq_proc, coarse_max = pc_gamg->coarse_eq_limit;
9005b89ad90SMark F. Adams   PetscErrorCode   ierr;
901038e3b61SMark F. Adams   Mat              Cmat,Pnew,Pold=*a_P_inout;
90211e60469SMark F. Adams   IS               new_indices,isnum;
9039d5b6da9SMark F. Adams   MPI_Comm         wcomm = ((PetscObject)Amat_fine)->comm;
9045a9b9e01SMark F. Adams   PetscMPIInt      mype,npe,new_npe,nactive = *a_nactive_proc;
9055a9b9e01SMark F. Adams   PetscInt         neq,NN,Istart,Iend,Istart0,Iend0,ncrs_new,ncrs0,rfactor;
9065b89ad90SMark F. Adams 
9075b89ad90SMark F. Adams   PetscFunctionBegin;
90811e60469SMark F. Adams   ierr = MPI_Comm_rank( wcomm, &mype ); CHKERRQ(ierr);
90911e60469SMark F. Adams   ierr = MPI_Comm_size( wcomm, &npe );  CHKERRQ(ierr);
910f6536408SMark F. Adams 
91111e60469SMark F. Adams   /* RAP */
91296434bc1SMark F. Adams #ifdef USE_R
91396434bc1SMark F. Adams   /* make R wih brute force for now */
91496434bc1SMark F. Adams   ierr = MatTranspose( Pold, Pnew );
91596434bc1SMark F. Adams   ierr = MatDestroy( &Pold );  CHKERRQ(ierr);
9169d5b6da9SMark F. Adams   ierr = MatRARt( Amat_fine, Pnew, MAT_INITIAL_MATRIX, 2.0, &Cmat ); CHKERRQ(ierr);
91796434bc1SMark F. Adams   Pold = Pnew;
91896434bc1SMark F. Adams #else
9199d5b6da9SMark F. Adams   ierr = MatPtAP( Amat_fine, Pold, MAT_INITIAL_MATRIX, 2.0, &Cmat ); CHKERRQ(ierr);
92096434bc1SMark F. Adams #endif
9219d5b6da9SMark F. Adams   ierr = MatSetBlockSize( Cmat, cbs );      CHKERRQ(ierr);
922038e3b61SMark F. Adams   ierr = MatGetOwnershipRange( Cmat, &Istart0, &Iend0 ); CHKERRQ(ierr);
9239d5b6da9SMark F. Adams   ncrs0 = (Iend0-Istart0)/cbs; assert((Iend0-Istart0)%cbs == 0);
924038e3b61SMark F. Adams 
925f852f58cSMark F. Adams   /* get number of PEs to make active, reduce */
926f852f58cSMark F. Adams   ierr = MatGetSize( Cmat, &neq, &NN );  CHKERRQ(ierr);
92781708dccSMark F. Adams   new_npe = (PetscMPIInt)((float)neq/(float)min_eq_proc + 0.5); /* hardwire min. number of eq/proc */
928f852f58cSMark F. Adams   if( new_npe == 0 || neq < coarse_max ) new_npe = 1;
9295a9b9e01SMark F. Adams   else if (new_npe >= nactive ) new_npe = nactive; /* no change, rare */
9309d5b6da9SMark F. Adams   if( isLast ) new_npe = 1;
931f852f58cSMark F. Adams 
9325a9b9e01SMark F. Adams   if( !repart && new_npe==nactive ) {
933a147abb0SMark F. Adams     *a_Amat_crs = Cmat; /* output - no repartitioning or reduction */
93422063be5SMark F. Adams   }
93522063be5SMark F. Adams   else {
93622063be5SMark F. Adams     /* Repartition Cmat_{k} and move colums of P^{k}_{k-1} and coordinates accordingly */
9379d5b6da9SMark F. Adams     const PetscInt *idx,data_sz=ndata_rows*ndata_cols;
9389d5b6da9SMark F. Adams     const PetscInt  stride0=ncrs0*ndata_rows;
9395a9b9e01SMark F. Adams     PetscInt        *counts,is_sz,*newproc_idx,ii,jj,kk,strideNew,*tidx,inpe,targetPE;
9405a9b9e01SMark F. Adams     IS              isnewproc;
9415a9b9e01SMark F. Adams     VecScatter      vecscat;
94222063be5SMark F. Adams     PetscScalar    *array;
94322063be5SMark F. Adams     Vec             src_crd, dest_crd;
94422063be5SMark F. Adams     PetscReal      *data = *a_coarse_data;
9455a9b9e01SMark F. Adams     IS              isscat;
946e33ef3b1SMark F. Adams 
947fd3c6afaSMark F. Adams     ierr = PetscMalloc( npe*sizeof(PetscInt), &counts ); CHKERRQ(ierr);
94892a756f0SMark F. Adams 
949b4fbaa2aSMark F. Adams #if defined PETSC_USE_LOG
950b4fbaa2aSMark F. Adams       ierr = PetscLogEventBegin(gamg_setup_events[SET12],0,0,0,0);CHKERRQ(ierr);
951b4fbaa2aSMark F. Adams #endif
9525a9b9e01SMark F. Adams     if( repart ) {
9535a9b9e01SMark F. Adams       /* create sub communicator  */
9545a9b9e01SMark F. Adams       Mat             adj;
9555a9b9e01SMark F. Adams 
9569d5b6da9SMark F. Adams       if (pc_gamg->verbose) PetscPrintf(PETSC_COMM_WORLD,"\t[%d]%s repartition: npe (active): %d --> %d, neq = %d\n",mype,__FUNCT__,*a_nactive_proc,new_npe,neq);
9575a9b9e01SMark F. Adams 
9585a9b9e01SMark F. Adams       /* MatPartitioningApply call MatConvert, which is collective */
9599d5b6da9SMark F. Adams       if( cbs == 1 ) {
960038e3b61SMark F. Adams 	ierr = MatConvert( Cmat, MATMPIADJ, MAT_INITIAL_MATRIX, &adj );   CHKERRQ(ierr);
961eb07cef2SMark F. Adams       }
962eb07cef2SMark F. Adams       else{
963038e3b61SMark F. Adams 	/* make a scalar matrix to partition */
964eb07cef2SMark F. Adams 	Mat tMat;
96558471d46SMark F. Adams 	PetscInt ncols,jj,Ii;
966b4fbaa2aSMark F. Adams 	const PetscScalar *vals;
967b4fbaa2aSMark F. Adams 	const PetscInt *idx;
9685f8cf99dSMark F. Adams 	PetscInt *d_nnz, *o_nnz;
9695ee9c036SSatish Balay 	static int llev = 0;
970b4fbaa2aSMark F. Adams 
97158471d46SMark F. Adams 	ierr = PetscMalloc( ncrs0*sizeof(PetscInt), &d_nnz ); CHKERRQ(ierr);
9725f8cf99dSMark F. Adams 	ierr = PetscMalloc( ncrs0*sizeof(PetscInt), &o_nnz ); CHKERRQ(ierr);
9739d5b6da9SMark F. Adams 	for ( Ii = Istart0, jj = 0 ; Ii < Iend0 ; Ii += cbs, jj++ ) {
97458471d46SMark F. Adams 	  ierr = MatGetRow(Cmat,Ii,&ncols,0,0); CHKERRQ(ierr);
9759d5b6da9SMark F. Adams 	  d_nnz[jj] = ncols/cbs;
9769d5b6da9SMark F. Adams 	  o_nnz[jj] = ncols/cbs;
97758471d46SMark F. Adams 	  ierr = MatRestoreRow(Cmat,Ii,&ncols,0,0); CHKERRQ(ierr);
9785f8cf99dSMark F. Adams 	  if( d_nnz[jj] > ncrs0 ) d_nnz[jj] = ncrs0;
9799d5b6da9SMark F. Adams 	  if( o_nnz[jj] > (neq/cbs-ncrs0) ) o_nnz[jj] = neq/cbs-ncrs0;
98058471d46SMark F. Adams 	}
9816876a03eSMark F. Adams 
982eb07cef2SMark F. Adams 	ierr = MatCreateMPIAIJ( wcomm, ncrs0, ncrs0,
983eb07cef2SMark F. Adams 				PETSC_DETERMINE, PETSC_DETERMINE,
9845f8cf99dSMark F. Adams 				0, d_nnz, 0, o_nnz,
985eb07cef2SMark F. Adams 				&tMat );
9866876a03eSMark F. Adams 	CHKERRQ(ierr);
98758471d46SMark F. Adams 	ierr = PetscFree( d_nnz ); CHKERRQ(ierr);
9885f8cf99dSMark F. Adams 	ierr = PetscFree( o_nnz ); CHKERRQ(ierr);
989eb07cef2SMark F. Adams 
99022063be5SMark F. Adams 	for ( ii = Istart0; ii < Iend0; ii++ ) {
9919d5b6da9SMark F. Adams 	  PetscInt dest_row = ii/cbs;
99222063be5SMark F. Adams 	  ierr = MatGetRow(Cmat,ii,&ncols,&idx,&vals); CHKERRQ(ierr);
993eb07cef2SMark F. Adams 	  for( jj = 0 ; jj < ncols ; jj++ ){
9949d5b6da9SMark F. Adams 	    PetscInt dest_col = idx[jj]/cbs;
995eb07cef2SMark F. Adams 	    PetscScalar v = 1.0;
996eb07cef2SMark F. Adams 	    ierr = MatSetValues(tMat,1,&dest_row,1,&dest_col,&v,ADD_VALUES); CHKERRQ(ierr);
997eb07cef2SMark F. Adams 	  }
99822063be5SMark F. Adams 	  ierr = MatRestoreRow(Cmat,ii,&ncols,&idx,&vals); CHKERRQ(ierr);
999eb07cef2SMark F. Adams 	}
1000eb07cef2SMark F. Adams 	ierr = MatAssemblyBegin(tMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1001eb07cef2SMark F. Adams 	ierr = MatAssemblyEnd(tMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1002eb07cef2SMark F. Adams 
1003b4fbaa2aSMark F. Adams 	if( llev++ == -1 ) {
1004b4fbaa2aSMark F. Adams 	  PetscViewer viewer; char fname[32];
1005b4fbaa2aSMark F. Adams 	  sprintf(fname,"part_mat_%d.mat",llev);
1006b4fbaa2aSMark F. Adams 	  PetscViewerBinaryOpen(wcomm,fname,FILE_MODE_WRITE,&viewer);
1007b4fbaa2aSMark F. Adams 	  ierr = MatView( tMat, viewer ); CHKERRQ(ierr);
1008b4fbaa2aSMark F. Adams 	  ierr = PetscViewerDestroy( &viewer );
1009b4fbaa2aSMark F. Adams 	}
1010b4fbaa2aSMark F. Adams 
1011eb07cef2SMark F. Adams 	ierr = MatConvert( tMat, MATMPIADJ, MAT_INITIAL_MATRIX, &adj );   CHKERRQ(ierr);
1012eb07cef2SMark F. Adams 
1013eb07cef2SMark F. Adams 	ierr = MatDestroy( &tMat );  CHKERRQ(ierr);
1014eb07cef2SMark F. Adams       }
1015f150b916SMark F. Adams 
10165a9b9e01SMark F. Adams       { /* partition: get newproc_idx, set is_sz */
10175a9b9e01SMark F. Adams 	char prefix[256];
10185a9b9e01SMark F. Adams 	const char *pcpre;
1019b4fbaa2aSMark F. Adams 	const PetscInt *is_idx;
1020b4fbaa2aSMark F. Adams 	MatPartitioning  mpart;
1021a4b7d37bSMark F. Adams 	IS proc_is;
10222f03bc48SMark F. Adams 
10235a9b9e01SMark F. Adams 	ierr = MatPartitioningCreate( wcomm, &mpart ); CHKERRQ(ierr);
10245ef31b24SMark F. Adams 	ierr = MatPartitioningSetAdjacency( mpart, adj ); CHKERRQ(ierr);
10259d5b6da9SMark F. Adams 	ierr = PCGetOptionsPrefix(pc,&pcpre);CHKERRQ(ierr);
102659a0be82SJed Brown 	ierr = PetscSNPrintf(prefix,sizeof prefix,"%spc_gamg_",pcpre?pcpre:"");CHKERRQ(ierr);
102759a0be82SJed Brown 	ierr = PetscObjectSetOptionsPrefix((PetscObject)mpart,prefix);CHKERRQ(ierr);
102811e60469SMark F. Adams 	ierr = MatPartitioningSetFromOptions( mpart );    CHKERRQ(ierr);
10295ef31b24SMark F. Adams 	ierr = MatPartitioningSetNParts( mpart, new_npe );CHKERRQ(ierr);
1030a4b7d37bSMark F. Adams 	ierr = MatPartitioningApply( mpart, &proc_is ); CHKERRQ(ierr);
103111e60469SMark F. Adams 	ierr = MatPartitioningDestroy( &mpart );          CHKERRQ(ierr);
10325a9b9e01SMark F. Adams 
10335ef31b24SMark F. Adams 	/* collect IS info */
1034a4b7d37bSMark F. Adams 	ierr = ISGetLocalSize( proc_is, &is_sz );       CHKERRQ(ierr);
10359d5b6da9SMark F. Adams 	ierr = PetscMalloc( cbs*is_sz*sizeof(PetscInt), &newproc_idx ); CHKERRQ(ierr);
1036a4b7d37bSMark F. Adams 	ierr = ISGetIndices( proc_is, &is_idx );        CHKERRQ(ierr);
1037a147abb0SMark F. Adams 	NN = 1; /* bring to "front" of machine */
1038a147abb0SMark F. Adams 	/*NN = npe/new_npe;*/ /* spread partitioning across machine */
1039b4fbaa2aSMark F. Adams 	for( kk = jj = 0 ; kk < is_sz ; kk++ ){
10409d5b6da9SMark F. Adams 	  for( ii = 0 ; ii < cbs ; ii++, jj++ ){
10418263b398SMark F. Adams 	    newproc_idx[jj] = is_idx[kk] * NN; /* distribution */
1042eb07cef2SMark F. Adams 	  }
10435ef31b24SMark F. Adams 	}
1044a4b7d37bSMark F. Adams 	ierr = ISRestoreIndices( proc_is, &is_idx );     CHKERRQ(ierr);
1045a4b7d37bSMark F. Adams 	ierr = ISDestroy( &proc_is );                    CHKERRQ(ierr);
1046b4fbaa2aSMark F. Adams 
10479d5b6da9SMark F. Adams 	is_sz *= cbs;
10485ef31b24SMark F. Adams       }
10495ef31b24SMark F. Adams       ierr = MatDestroy( &adj );                       CHKERRQ(ierr);
10505a9b9e01SMark F. Adams 
10518263b398SMark F. Adams       ierr = ISCreateGeneral( wcomm, is_sz, newproc_idx, PETSC_COPY_VALUES, &isnewproc );
10525a9b9e01SMark F. Adams       CHKERRQ(ierr);
10538263b398SMark F. Adams       if( newproc_idx != 0 ) {
10548263b398SMark F. Adams 	ierr = PetscFree( newproc_idx );  CHKERRQ(ierr);
10555ef31b24SMark F. Adams       }
10565a9b9e01SMark F. Adams     }
10575a9b9e01SMark F. Adams     else { /* simple aggreagtion of parts */
10585a9b9e01SMark F. Adams       /* find factor */
10595a9b9e01SMark F. Adams       if( new_npe == 1 ) rfactor = npe; /* easy */
10605a9b9e01SMark F. Adams       else {
10615a9b9e01SMark F. Adams 	PetscReal best_fact = 0.;
10625a9b9e01SMark F. Adams 	jj = -1;
10635a9b9e01SMark F. Adams 	for( kk = 1 ; kk <= npe ; kk++ ){
10645a9b9e01SMark F. Adams 	  if( npe%kk==0 ) { /* a candidate */
10655a9b9e01SMark F. Adams 	    PetscReal nactpe = (PetscReal)npe/(PetscReal)kk, fact = nactpe/(PetscReal)new_npe;
10665a9b9e01SMark F. Adams 	    if(fact > 1.0) fact = 1./fact; /* keep fact < 1 */
10675a9b9e01SMark F. Adams 	    if( fact > best_fact ) {
10685a9b9e01SMark F. Adams 	      best_fact = fact; jj = kk;
10695a9b9e01SMark F. Adams 	    }
10705a9b9e01SMark F. Adams 	  }
10715a9b9e01SMark F. Adams 	}
10725a9b9e01SMark F. Adams 	if(jj!=-1) rfactor = jj;
10735a9b9e01SMark F. Adams 	else rfactor = 1; /* prime? */
10745a9b9e01SMark F. Adams       }
10755a9b9e01SMark F. Adams       new_npe = npe/rfactor;
10765a9b9e01SMark F. Adams 
10775a9b9e01SMark F. Adams       if( new_npe==nactive ) {
10785a9b9e01SMark F. Adams 	*a_Amat_crs = Cmat; /* output - no repartitioning or reduction */
10795a9b9e01SMark F. Adams 	ierr = PetscFree( counts );  CHKERRQ(ierr);
10805a9b9e01SMark F. Adams 	*a_nactive_proc = new_npe; /* output */
10819d5b6da9SMark F. Adams 	if (pc_gamg->verbose) PetscPrintf(PETSC_COMM_WORLD,"\t[%d]%s aggregate processors noop: new_npe=%d, neq=%d\n",mype,__FUNCT__,new_npe,neq);
10825a9b9e01SMark F. Adams 	PetscFunctionReturn(0);
10835a9b9e01SMark F. Adams       }
10845a9b9e01SMark F. Adams 
10855a9b9e01SMark F. Adams       /* reduce - isnewproc */
10865a9b9e01SMark F. Adams       targetPE = mype/rfactor;
10875a9b9e01SMark F. Adams 
10889d5b6da9SMark F. Adams       if (pc_gamg->verbose) PetscPrintf(PETSC_COMM_WORLD,"\t[%d]%s aggregate processors: npe: %d --> %d, neq=%d\n",mype,__FUNCT__,*a_nactive_proc,new_npe,neq);
10899d5b6da9SMark F. Adams       is_sz = ncrs0*cbs;
10905a9b9e01SMark F. Adams       ierr = ISCreateStride( wcomm, is_sz, targetPE, 0, &isnewproc );
10915a9b9e01SMark F. Adams       CHKERRQ(ierr);
10925a9b9e01SMark F. Adams     }
1093e33ef3b1SMark F. Adams 
109411e60469SMark F. Adams     /*
109511e60469SMark F. Adams       Create an index set from the isnewproc index set to indicate the mapping TO
109611e60469SMark F. Adams     */
109711e60469SMark F. Adams     ierr = ISPartitioningToNumbering( isnewproc, &isnum ); CHKERRQ(ierr);
109811e60469SMark F. Adams     /*
109911e60469SMark F. Adams       Determine how many elements are assigned to each processor
110011e60469SMark F. Adams     */
1101fd3c6afaSMark F. Adams     inpe = npe;
1102fd3c6afaSMark F. Adams     ierr = ISPartitioningCount( isnewproc, inpe, counts ); CHKERRQ(ierr);
110311e60469SMark F. Adams     ierr = ISDestroy( &isnewproc );                       CHKERRQ(ierr);
11049d5b6da9SMark F. Adams     ncrs_new = counts[mype]/cbs;
11059d5b6da9SMark F. Adams     strideNew = ncrs_new*ndata_rows;
1106b4fbaa2aSMark F. Adams #if defined PETSC_USE_LOG
1107b4fbaa2aSMark F. Adams       ierr = PetscLogEventEnd(gamg_setup_events[SET12],0,0,0,0);   CHKERRQ(ierr);
1108b4fbaa2aSMark F. Adams #endif
110922063be5SMark F. Adams     /* Create a vector to contain the newly ordered element information */
111011e60469SMark F. Adams     ierr = VecCreate( wcomm, &dest_crd );
1111d3d6bff4SMark F. Adams     ierr = VecSetSizes( dest_crd, data_sz*ncrs_new, PETSC_DECIDE ); CHKERRQ(ierr);
1112470e26f8SMark F. Adams     ierr = VecSetFromOptions( dest_crd ); CHKERRQ(ierr); /* this is needed! */
111311e60469SMark F. Adams     /*
11149d5b6da9SMark F. Adams      There are 'ndata_rows*ndata_cols' data items per node, (one can think of the vectors of having
11159d5b6da9SMark F. Adams      a block size of ...).  Note, ISs are expanded into equation space by 'cbs'.
111611e60469SMark F. Adams      */
111792a756f0SMark F. Adams     ierr = PetscMalloc( (ncrs0*data_sz)*sizeof(PetscInt), &tidx ); CHKERRQ(ierr);
111811e60469SMark F. Adams     ierr = ISGetIndices( isnum, &idx ); CHKERRQ(ierr);
1119038e3b61SMark F. Adams     for(ii=0,jj=0; ii<ncrs0 ; ii++) {
11209d5b6da9SMark F. Adams       PetscInt id = idx[ii*cbs]/cbs; /* get node back */
1121d3d6bff4SMark F. Adams       for( kk=0; kk<data_sz ; kk++, jj++) tidx[jj] = id*data_sz + kk;
112211e60469SMark F. Adams     }
1123038e3b61SMark F. Adams     ierr = ISRestoreIndices( isnum, &idx ); CHKERRQ(ierr);
1124d3d6bff4SMark F. Adams     ierr = ISCreateGeneral( wcomm, data_sz*ncrs0, tidx, PETSC_COPY_VALUES, &isscat );
112511e60469SMark F. Adams     CHKERRQ(ierr);
112692a756f0SMark F. Adams     ierr = PetscFree( tidx );  CHKERRQ(ierr);
112711e60469SMark F. Adams     /*
112811e60469SMark F. Adams      Create a vector to contain the original vertex information for each element
112911e60469SMark F. Adams      */
1130d3d6bff4SMark F. Adams     ierr = VecCreateSeq( PETSC_COMM_SELF, data_sz*ncrs0, &src_crd ); CHKERRQ(ierr);
11319d5b6da9SMark F. Adams     for( jj=0; jj<ndata_cols ; jj++ ) {
1132d3d6bff4SMark F. Adams       for( ii=0 ; ii<ncrs0 ; ii++) {
11339d5b6da9SMark F. Adams 	for( kk=0; kk<ndata_rows ; kk++ ) {
11349d5b6da9SMark F. Adams 	  PetscInt ix = ii*ndata_rows + kk + jj*stride0, jx = ii*data_sz + kk*ndata_cols + jj;
1135676e1743SMark F. Adams           PetscScalar tt = (PetscScalar)data[ix];
1136676e1743SMark F. Adams 	  ierr = VecSetValues( src_crd, 1, &jx, &tt, INSERT_VALUES );  CHKERRQ(ierr);
1137d3d6bff4SMark F. Adams 	}
1138038e3b61SMark F. Adams       }
1139eb07cef2SMark F. Adams     }
1140eb07cef2SMark F. Adams     ierr = VecAssemblyBegin(src_crd); CHKERRQ(ierr);
1141eb07cef2SMark F. Adams     ierr = VecAssemblyEnd(src_crd); CHKERRQ(ierr);
114211e60469SMark F. Adams     /*
114311e60469SMark F. Adams       Scatter the element vertex information (still in the original vertex ordering)
114411e60469SMark F. Adams       to the correct processor
114511e60469SMark F. Adams     */
114611e60469SMark F. Adams     ierr = VecScatterCreate( src_crd, PETSC_NULL, dest_crd, isscat, &vecscat);
114711e60469SMark F. Adams     CHKERRQ(ierr);
114811e60469SMark F. Adams     ierr = ISDestroy( &isscat );       CHKERRQ(ierr);
114911e60469SMark F. Adams     ierr = VecScatterBegin(vecscat,src_crd,dest_crd,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
115011e60469SMark F. Adams     ierr = VecScatterEnd(vecscat,src_crd,dest_crd,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
115111e60469SMark F. Adams     ierr = VecScatterDestroy( &vecscat );       CHKERRQ(ierr);
115211e60469SMark F. Adams     ierr = VecDestroy( &src_crd );       CHKERRQ(ierr);
115311e60469SMark F. Adams     /*
115411e60469SMark F. Adams       Put the element vertex data into a new allocation of the gdata->ele
115511e60469SMark F. Adams     */
1156eb07cef2SMark F. Adams     ierr = PetscFree( *a_coarse_data );    CHKERRQ(ierr);
1157d3d6bff4SMark F. Adams     ierr = PetscMalloc( data_sz*ncrs_new*sizeof(PetscReal), a_coarse_data );    CHKERRQ(ierr);
1158eb07cef2SMark F. Adams 
115911e60469SMark F. Adams     ierr = VecGetArray( dest_crd, &array );    CHKERRQ(ierr);
1160eb07cef2SMark F. Adams     data = *a_coarse_data;
11619d5b6da9SMark F. Adams     for( jj=0; jj<ndata_cols ; jj++ ) {
1162d3d6bff4SMark F. Adams       for( ii=0 ; ii<ncrs_new ; ii++) {
11639d5b6da9SMark F. Adams 	for( kk=0; kk<ndata_rows ; kk++ ) {
11649d5b6da9SMark F. Adams 	  PetscInt ix = ii*ndata_rows + kk + jj*strideNew, jx = ii*data_sz + kk*ndata_cols + jj;
1165d3d6bff4SMark F. Adams 	  data[ix] = PetscRealPart(array[jx]);
1166d3d6bff4SMark F. Adams 	  array[jx] = 1.e300;
1167d3d6bff4SMark F. Adams 	}
1168038e3b61SMark F. Adams       }
1169038e3b61SMark F. Adams     }
117011e60469SMark F. Adams     ierr = VecRestoreArray( dest_crd, &array );    CHKERRQ(ierr);
117111e60469SMark F. Adams     ierr = VecDestroy( &dest_crd );    CHKERRQ(ierr);
1172ed3f9983SMark F. Adams #if defined PETSC_USE_LOG
1173ed3f9983SMark F. Adams     ierr = PetscLogEventBegin(gamg_setup_events[SET13],0,0,0,0);CHKERRQ(ierr);
1174ed3f9983SMark F. Adams #endif
117511e60469SMark F. Adams     /*
117611e60469SMark F. Adams       Invert for MatGetSubMatrix
117711e60469SMark F. Adams     */
11789d5b6da9SMark F. Adams     ierr = ISInvertPermutation( isnum, ncrs_new*cbs, &new_indices ); CHKERRQ(ierr);
117911e60469SMark F. Adams     ierr = ISSort( new_indices ); CHKERRQ(ierr); /* is this needed? */
118011e60469SMark F. Adams     ierr = ISDestroy( &isnum ); CHKERRQ(ierr);
1181ed3f9983SMark F. Adams #if defined PETSC_USE_LOG
1182ed3f9983SMark F. Adams     ierr = PetscLogEventEnd(gamg_setup_events[SET13],0,0,0,0);CHKERRQ(ierr);
1183ed3f9983SMark F. Adams     ierr = PetscLogEventBegin(gamg_setup_events[SET14],0,0,0,0);CHKERRQ(ierr);
1184ed3f9983SMark F. Adams #endif
118511e60469SMark F. Adams     /* A_crs output */
1186038e3b61SMark F. Adams     ierr = MatGetSubMatrix( Cmat, new_indices, new_indices, MAT_INITIAL_MATRIX, a_Amat_crs );
118711e60469SMark F. Adams     CHKERRQ(ierr);
1188eb07cef2SMark F. Adams 
1189038e3b61SMark F. Adams     ierr = MatDestroy( &Cmat ); CHKERRQ(ierr);
1190e33ef3b1SMark F. Adams     Cmat = *a_Amat_crs; /* output */
11919d5b6da9SMark F. Adams     ierr = MatSetBlockSize( Cmat, cbs );      CHKERRQ(ierr);
1192ed3f9983SMark F. Adams #if defined PETSC_USE_LOG
1193ed3f9983SMark F. Adams     ierr = PetscLogEventEnd(gamg_setup_events[SET14],0,0,0,0);CHKERRQ(ierr);
1194ed3f9983SMark F. Adams #endif
119511e60469SMark F. Adams     /* prolongator */
119611e60469SMark F. Adams     ierr = MatGetOwnershipRange( Pold, &Istart, &Iend );    CHKERRQ(ierr);
119711e60469SMark F. Adams     {
119811e60469SMark F. Adams       IS findices;
1199ed3f9983SMark F. Adams #if defined PETSC_USE_LOG
1200ed3f9983SMark F. Adams       ierr = PetscLogEventBegin(gamg_setup_events[SET15],0,0,0,0);CHKERRQ(ierr);
1201ed3f9983SMark F. Adams #endif
120211e60469SMark F. Adams       ierr = ISCreateStride(wcomm,Iend-Istart,Istart,1,&findices);   CHKERRQ(ierr);
120396434bc1SMark F. Adams #ifdef USE_R
120496434bc1SMark F. Adams       ierr = MatGetSubMatrix( Pold, new_indices, findices, MAT_INITIAL_MATRIX, &Pnew );
120596434bc1SMark F. Adams #else
120611e60469SMark F. Adams       ierr = MatGetSubMatrix( Pold, findices, new_indices, MAT_INITIAL_MATRIX, &Pnew );
120796434bc1SMark F. Adams #endif
120811e60469SMark F. Adams       CHKERRQ(ierr);
120911e60469SMark F. Adams       ierr = ISDestroy( &findices ); CHKERRQ(ierr);
1210ed3f9983SMark F. Adams #if defined PETSC_USE_LOG
1211ed3f9983SMark F. Adams       ierr = PetscLogEventEnd(gamg_setup_events[SET15],0,0,0,0);CHKERRQ(ierr);
1212ed3f9983SMark F. Adams #endif
121311e60469SMark F. Adams     }
12143530afc2SMark F. Adams     ierr = MatDestroy( a_P_inout ); CHKERRQ(ierr);
1215a147abb0SMark F. Adams     *a_P_inout = Pnew; /* output - repartitioned */
121611e60469SMark F. Adams     ierr = ISDestroy( &new_indices ); CHKERRQ(ierr);
121792a756f0SMark F. Adams     ierr = PetscFree( counts );  CHKERRQ(ierr);
1218e33ef3b1SMark F. Adams   }
12195b89ad90SMark F. Adams 
12205a9b9e01SMark F. Adams   *a_nactive_proc = new_npe; /* output */
12215a9b9e01SMark F. Adams 
12225b89ad90SMark F. Adams   PetscFunctionReturn(0);
12235b89ad90SMark F. Adams }
12245b89ad90SMark F. Adams 
12255b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */
12265b89ad90SMark F. Adams /*
12275b89ad90SMark F. Adams    PCSetUp_GAMG - Prepares for the use of the GAMG preconditioner
12285b89ad90SMark F. Adams                     by setting data structures and options.
12295b89ad90SMark F. Adams 
12305b89ad90SMark F. Adams    Input Parameter:
12315b89ad90SMark F. Adams .  pc - the preconditioner context
12325b89ad90SMark F. Adams 
12335b89ad90SMark F. Adams    Application Interface Routine: PCSetUp()
12345b89ad90SMark F. Adams 
12355b89ad90SMark F. Adams    Notes:
12365b89ad90SMark F. Adams    The interface routine PCSetUp() is not usually called directly by
12375b89ad90SMark F. Adams    the user, but instead is called by PCApply() if necessary.
12385b89ad90SMark F. Adams */
12395b89ad90SMark F. Adams #undef __FUNCT__
12405b89ad90SMark F. Adams #define __FUNCT__ "PCSetUp_GAMG"
12419d5b6da9SMark F. Adams PetscErrorCode PCSetUp_GAMG( PC pc )
12425b89ad90SMark F. Adams {
12435b89ad90SMark F. Adams   PetscErrorCode  ierr;
12449d5b6da9SMark F. Adams   PC_MG           *mg = (PC_MG*)pc->data;
12455b89ad90SMark F. Adams   PC_GAMG         *pc_gamg = (PC_GAMG*)mg->innerctx;
124658471d46SMark F. Adams   PC_MG_Levels   **mglevels = mg->levels;
12479d5b6da9SMark F. Adams   Mat              Amat = pc->mat, Pmat = pc->pmat;
1248d3d6bff4SMark F. Adams   PetscInt         fine_level, level, level1, M, N, bs, nloc, lidx, Istart, Iend;
12499d5b6da9SMark F. Adams   MPI_Comm         wcomm = ((PetscObject)pc)->comm;
12503530afc2SMark F. Adams   PetscMPIInt      mype,npe,nactivepe;
1251587fa25dSMark F. Adams   Mat              Aarr[GAMG_MAXLEVELS], Parr[GAMG_MAXLEVELS];
1252587fa25dSMark F. Adams   PetscReal       *coarse_data = 0, *data, emaxs[GAMG_MAXLEVELS];
1253737a81a9SMark F. Adams   MatInfo          info;
12545ef31b24SMark F. Adams 
12555b89ad90SMark F. Adams   PetscFunctionBegin;
12569d5b6da9SMark F. Adams   pc_gamg->setup_count++;
12579d5b6da9SMark F. Adams   assert(pc_gamg->createprolongator);
1258fca9ed99SMark F. Adams 
12599d5b6da9SMark F. Adams   if( pc->setupcalled > 0 ) {
126003a628feSMark F. Adams     /* just do Galerkin grids */
126158471d46SMark F. Adams     Mat B,dA,dB;
126258471d46SMark F. Adams 
126358471d46SMark F. Adams     /* PCSetUp_MG seems to insists on setting this to GMRES */
126458471d46SMark F. Adams     ierr = KSPSetType( mglevels[0]->smoothd, KSPPREONLY ); CHKERRQ(ierr);
126558471d46SMark F. Adams 
12669d5b6da9SMark F. Adams     if( pc_gamg->Nlevels > 1 ) {
126758471d46SMark F. Adams       /* currently only handle case where mat and pmat are the same on coarser levels */
12689d5b6da9SMark F. Adams       ierr = KSPGetOperators(mglevels[pc_gamg->Nlevels-1]->smoothd,&dA,&dB,PETSC_NULL);CHKERRQ(ierr);
126958471d46SMark F. Adams       /* (re)set to get dirty flag */
12709d5b6da9SMark F. Adams       ierr = KSPSetOperators(mglevels[pc_gamg->Nlevels-1]->smoothd,dA,dB,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
12719d5b6da9SMark F. Adams       ierr = KSPSetUp( mglevels[pc_gamg->Nlevels-1]->smoothd ); CHKERRQ(ierr);
127258471d46SMark F. Adams 
12739d5b6da9SMark F. Adams       for (level=pc_gamg->Nlevels-2; level>-1; level--) {
127458471d46SMark F. Adams         ierr = KSPGetOperators(mglevels[level]->smoothd,PETSC_NULL,&B,PETSC_NULL);CHKERRQ(ierr);
127503a628feSMark F. Adams         /* the first time through the matrix structure has changed from repartitioning */
12769d5b6da9SMark F. Adams         if( pc_gamg->setup_count == 2 ) {
127703a628feSMark F. Adams           ierr = MatDestroy( &B );  CHKERRQ(ierr);
127803a628feSMark F. Adams           ierr = MatPtAP(dB,mglevels[level+1]->interpolate,MAT_INITIAL_MATRIX,1.0,&B);CHKERRQ(ierr);
127903a628feSMark F. Adams           mglevels[level]->A = B;
128003a628feSMark F. Adams         }
128103a628feSMark F. Adams         else {
128258471d46SMark F. Adams           ierr = MatPtAP(dB,mglevels[level+1]->interpolate,MAT_REUSE_MATRIX,1.0,&B);CHKERRQ(ierr);
128303a628feSMark F. Adams         }
128458471d46SMark F. Adams         ierr = KSPSetOperators(mglevels[level]->smoothd,B,B,SAME_NONZERO_PATTERN); CHKERRQ(ierr);
128558471d46SMark F. Adams         dB = B;
128658471d46SMark F. Adams         /* setup KSP/PC */
128758471d46SMark F. Adams         ierr = KSPSetUp( mglevels[level]->smoothd ); CHKERRQ(ierr);
128858471d46SMark F. Adams       }
12895f8cf99dSMark F. Adams     }
129058471d46SMark F. Adams 
12919d5b6da9SMark F. Adams     pc->setupcalled = 2;
129203a628feSMark F. Adams 
129358471d46SMark F. Adams     PetscFunctionReturn(0);
1294eb07cef2SMark F. Adams   }
1295f6536408SMark F. Adams 
1296baa4e9faSMark F. Adams   ierr = MPI_Comm_rank(wcomm,&mype);CHKERRQ(ierr);
1297baa4e9faSMark F. Adams   ierr = MPI_Comm_size(wcomm,&npe);CHKERRQ(ierr);
12985b89ad90SMark F. Adams   /* GAMG requires input of fine-grid matrix. It determines nlevels. */
12995b89ad90SMark F. Adams   ierr = MatGetBlockSize( Amat, &bs ); CHKERRQ(ierr);
13003530afc2SMark F. Adams   ierr = MatGetSize( Amat, &M, &N );CHKERRQ(ierr);
1301eb07cef2SMark F. Adams   ierr = MatGetOwnershipRange( Amat, &Istart, &Iend ); CHKERRQ(ierr);
1302eb07cef2SMark F. Adams   nloc = (Iend-Istart)/bs; assert((Iend-Istart)%bs == 0);
1303eb07cef2SMark F. Adams 
13049d5b6da9SMark F. Adams   if( pc_gamg->data == 0 && nloc > 0 ) {
13059d5b6da9SMark F. Adams     if(!pc_gamg->createdefaultdata){
13069d5b6da9SMark F. Adams       SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_LIB,"GEO MG needs coordinates");
1307eb07cef2SMark F. Adams     }
13089d5b6da9SMark F. Adams     ierr = pc_gamg->createdefaultdata( pc ); CHKERRQ(ierr);
13099d5b6da9SMark F. Adams   }
13109d5b6da9SMark F. Adams   data = pc_gamg->data;
1311038e3b61SMark F. Adams 
1312eb07cef2SMark F. Adams   /* Get A_i and R_i */
1313737a81a9SMark F. Adams   ierr = MatGetInfo(Amat,MAT_GLOBAL_SUM,&info); CHKERRQ(ierr);
13149d5b6da9SMark F. Adams   if (pc_gamg->verbose) PetscPrintf(PETSC_COMM_WORLD,"\t[%d]%s level %d N=%d, n data rows=%d, n data cols=%d, nnz/row (ave)=%d, np=%d\n",
13159d5b6da9SMark F. Adams 	      mype,__FUNCT__,0,N,pc_gamg->data_rows,pc_gamg->data_cols,
13162c047e2dSMark F. Adams 	      (int)(info.nz_used/(PetscReal)N),npe);
13178f4b7eb5SMark F. Adams   for ( level=0, Aarr[0] = Pmat, nactivepe = npe; /* hard wired stopping logic */
13189d5b6da9SMark F. Adams         level < (pc_gamg->Nlevels-1) && (level==0 || M>pc_gamg->coarse_eq_limit); /* && (npe==1 || nactivepe>1); */
13190205a208SMark F. Adams         level++ ){
13205b89ad90SMark F. Adams     level1 = level + 1;
1321b4fbaa2aSMark F. Adams #if (defined PETSC_USE_LOG && defined GAMG_STAGES)
1322b4fbaa2aSMark F. Adams     ierr = PetscLogStagePush(gamg_stages[level]); CHKERRQ( ierr );
1323b4fbaa2aSMark F. Adams #endif
1324b4fbaa2aSMark F. Adams #if defined PETSC_USE_LOG
1325b4fbaa2aSMark F. Adams     ierr = PetscLogEventBegin(gamg_setup_events[SET1],0,0,0,0);CHKERRQ(ierr);
1326b4fbaa2aSMark F. Adams #endif
13279d5b6da9SMark F. Adams     ierr = pc_gamg->createprolongator( pc, Aarr[level], data, &Parr[level1], &coarse_data );
13285b89ad90SMark F. Adams     CHKERRQ(ierr);
13299d5b6da9SMark F. Adams     /* get new block size of coarse matrices */
13309d5b6da9SMark F. Adams     if( pc_gamg->col_bs_id != -1 && Parr[level1] ){
13319d5b6da9SMark F. Adams       PetscBool flag;
13329d5b6da9SMark F. Adams       ierr = PetscObjectComposedDataGetInt( (PetscObject)Parr[level1], pc_gamg->col_bs_id, bs, flag );
13339d5b6da9SMark F. Adams       CHKERRQ( ierr );
13349d5b6da9SMark F. Adams     }
13359d5b6da9SMark F. Adams     /* cache eigen estimate */
13369d5b6da9SMark F. Adams     if( pc_gamg->emax_id != -1 ){
13379d5b6da9SMark F. Adams       PetscBool flag;
1338f73f8d2cSSatish Balay       ierr = PetscObjectComposedDataGetReal( (PetscObject)Aarr[level], pc_gamg->emax_id, emaxs[level], flag );
13399d5b6da9SMark F. Adams       CHKERRQ( ierr );
13409d5b6da9SMark F. Adams       if( !flag ) emaxs[level] = -1.;
13419d5b6da9SMark F. Adams     }
13429d5b6da9SMark F. Adams     else emaxs[level] = -1.;
13439d5b6da9SMark F. Adams 
1344d3d6bff4SMark F. Adams     ierr = PetscFree( data ); CHKERRQ( ierr );
1345b4fbaa2aSMark F. Adams #if defined PETSC_USE_LOG
1346b4fbaa2aSMark F. Adams     ierr = PetscLogEventEnd(gamg_setup_events[SET1],0,0,0,0);CHKERRQ(ierr);
1347b4fbaa2aSMark F. Adams #endif
1348baa4e9faSMark F. Adams     if(level==0) Aarr[0] = Amat; /* use Pmat for finest level setup, but use mat for solver */
13499d5b6da9SMark F. Adams     if( Parr[level1] ) {
1350b4fbaa2aSMark F. Adams #if defined PETSC_USE_LOG
1351b4fbaa2aSMark F. Adams       ierr = PetscLogEventBegin(gamg_setup_events[SET2],0,0,0,0);CHKERRQ(ierr);
1352b4fbaa2aSMark F. Adams #endif
13539d5b6da9SMark F. Adams       ierr = createLevel( pc, Aarr[level],
13549d5b6da9SMark F. Adams                           pc_gamg->data_rows,
13559d5b6da9SMark F. Adams                           pc_gamg->data_cols, bs,
13569d5b6da9SMark F. Adams                           (PetscBool)(level==pc_gamg->Nlevels-2),
1357389730f3SMark F. Adams                           &Parr[level1], &coarse_data, &nactivepe, &Aarr[level1] );
13583530afc2SMark F. Adams       CHKERRQ(ierr);
1359b4fbaa2aSMark F. Adams #if defined PETSC_USE_LOG
1360b4fbaa2aSMark F. Adams       ierr = PetscLogEventEnd(gamg_setup_events[SET2],0,0,0,0);CHKERRQ(ierr);
1361b4fbaa2aSMark F. Adams #endif
13623530afc2SMark F. Adams       ierr = MatGetSize( Aarr[level1], &M, &N );CHKERRQ(ierr);
1363737a81a9SMark F. Adams       ierr = MatGetInfo( Aarr[level1], MAT_GLOBAL_SUM, &info ); CHKERRQ(ierr);
13649d5b6da9SMark F. Adams       if (pc_gamg->verbose) PetscPrintf(PETSC_COMM_WORLD,"\t\t[%d]%s %d) N=%d, n data cols=%d, nnz/row (ave)=%d, %d active pes\n",
13659d5b6da9SMark F. Adams 		  mype,__FUNCT__,(int)level1,N,pc_gamg->data_cols,
13662c047e2dSMark F. Adams 		  (int)(info.nz_used/(PetscReal)N),nactivepe);
1367e33ef3b1SMark F. Adams       /* coarse grids with SA can have zero row/cols from singleton aggregates */
1368737a81a9SMark F. Adams 
136981708dccSMark F. Adams       /* stop if one node */
13709d5b6da9SMark F. Adams       if( M/pc_gamg->data_cols < 2 ) {
137181708dccSMark F. Adams         level++;
137281708dccSMark F. Adams         break;
137381708dccSMark F. Adams       }
137481708dccSMark F. Adams 
137581708dccSMark F. Adams       if (PETSC_FALSE) {
1376785cba28SMark F. Adams         Vec diag; PetscScalar *data_arr,v; PetscInt Istart,Iend,kk,nloceq,id;
1377785cba28SMark F. Adams         v = 1.e-10; /* LU factor has hard wired numbers for small diags so this needs to match (yuk) */
1378e33ef3b1SMark F. Adams         ierr = MatGetOwnershipRange(Aarr[level1], &Istart, &Iend); CHKERRQ(ierr);
1379785cba28SMark F. Adams         nloceq = Iend-Istart;
1380e33ef3b1SMark F. Adams         ierr = MatGetVecs( Aarr[level1], &diag, 0 );    CHKERRQ(ierr);
1381e33ef3b1SMark F. Adams         ierr = MatGetDiagonal( Aarr[level1], diag );    CHKERRQ(ierr);
1382e33ef3b1SMark F. Adams         ierr = VecGetArray( diag, &data_arr );   CHKERRQ(ierr);
1383785cba28SMark F. Adams         for(kk=0;kk<nloceq;kk++){
1384e33ef3b1SMark F. Adams           if(data_arr[kk]==0.0) {
1385785cba28SMark F. Adams             id = kk + Istart;
1386e33ef3b1SMark F. Adams             ierr = MatSetValues(Aarr[level1],1,&id,1,&id,&v,INSERT_VALUES);
1387e33ef3b1SMark F. Adams             CHKERRQ(ierr);
1388ecd57171SMark F. Adams             PetscPrintf(PETSC_COMM_SELF,"\t[%d]%s warning: added zero to diag (%d) on level %d \n",mype,__FUNCT__,id,level1);
1389e33ef3b1SMark F. Adams           }
1390e33ef3b1SMark F. Adams         }
1391e33ef3b1SMark F. Adams         ierr = VecRestoreArray( diag, &data_arr ); CHKERRQ(ierr);
1392e33ef3b1SMark F. Adams         ierr = VecDestroy( &diag );                CHKERRQ(ierr);
1393e33ef3b1SMark F. Adams         ierr = MatAssemblyBegin(Aarr[level1],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1394e33ef3b1SMark F. Adams         ierr = MatAssemblyEnd(Aarr[level1],MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1395e33ef3b1SMark F. Adams       }
1396486a8d0bSJed Brown     } else {
1397be544d3cSMark F. Adams       coarse_data = 0;
1398baa4e9faSMark F. Adams       break;
1399baa4e9faSMark F. Adams     }
1400eb07cef2SMark F. Adams     data = coarse_data;
1401b4fbaa2aSMark F. Adams 
1402b4fbaa2aSMark F. Adams #if (defined PETSC_USE_LOG && defined GAMG_STAGES)
1403b4fbaa2aSMark F. Adams     ierr = PetscLogStagePop(); CHKERRQ( ierr );
1404b4fbaa2aSMark F. Adams #endif
14055b89ad90SMark F. Adams   }
1406be544d3cSMark F. Adams   if( coarse_data ) {
1407eb07cef2SMark F. Adams     ierr = PetscFree( coarse_data ); CHKERRQ( ierr );
1408be544d3cSMark F. Adams   }
14099d5b6da9SMark F. Adams   if (pc_gamg->verbose) PetscPrintf(PETSC_COMM_WORLD,"\t[%d]%s %d levels\n",0,__FUNCT__,level + 1);
14109d5b6da9SMark F. Adams   pc_gamg->data = 0; /* destroyed coordinate data */
14119d5b6da9SMark F. Adams   pc_gamg->Nlevels = level + 1;
14125b89ad90SMark F. Adams   fine_level = level;
14139d5b6da9SMark F. Adams   ierr = PCMGSetLevels(pc,pc_gamg->Nlevels,PETSC_NULL);CHKERRQ(ierr);
14145b89ad90SMark F. Adams 
14159d5b6da9SMark F. Adams   if( pc_gamg->Nlevels > 1 ) { /* don't setup MG if  */
1416fc4362bfSMark F. Adams   /* set default smoothers */
14179d5b6da9SMark F. Adams   for ( lidx = 1, level = pc_gamg->Nlevels-2;
1418587fa25dSMark F. Adams         lidx <= fine_level;
1419587fa25dSMark F. Adams         lidx++, level--) {
14205745e0f5SMark F. Adams     PetscReal emax, emin;
14215b89ad90SMark F. Adams     KSP smoother; PC subpc;
1422f6536408SMark F. Adams     PetscBool isCheb;
1423f6536408SMark F. Adams     /* set defaults */
14249d5b6da9SMark F. Adams     ierr = PCMGGetSmoother( pc, lidx, &smoother ); CHKERRQ(ierr);
14255b89ad90SMark F. Adams     ierr = KSPSetType( smoother, KSPCHEBYCHEV );CHKERRQ(ierr);
1426f6536408SMark F. Adams     ierr = KSPGetPC( smoother, &subpc ); CHKERRQ(ierr);
1427f6536408SMark F. Adams     /* ierr = KSPSetTolerances(smoother,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,2); CHKERRQ(ierr); */
14289d5b6da9SMark F. Adams     ierr = PCSetType( subpc, PCJACOBI ); CHKERRQ(ierr);
1429f6536408SMark F. Adams     ierr = KSPSetNormType( smoother, KSP_NORM_NONE ); CHKERRQ(ierr);
1430f6536408SMark F. Adams     /* overide defaults with input parameters */
1431f6536408SMark F. Adams     ierr = KSPSetFromOptions( smoother ); CHKERRQ(ierr);
1432f6536408SMark F. Adams 
1433f6536408SMark F. Adams     ierr = KSPSetOperators( smoother, Aarr[level], Aarr[level], SAME_NONZERO_PATTERN );   CHKERRQ(ierr);
1434f6536408SMark F. Adams     /* do my own cheby */
1435f6536408SMark F. Adams     ierr = PetscTypeCompare( (PetscObject)smoother, KSPCHEBYCHEV, &isCheb ); CHKERRQ(ierr);
143641139db5SMark F. Adams 
1437f6536408SMark F. Adams     if( isCheb ) {
14389d5b6da9SMark F. Adams       ierr = PetscTypeCompare( (PetscObject)subpc, PCJACOBI, &isCheb ); CHKERRQ(ierr);
1439f6536408SMark F. Adams       if( isCheb && emaxs[level] > 0.0 ) emax=emaxs[level]; /* eigen estimate only for diagnal PC */
1440587fa25dSMark F. Adams       else{ /* eigen estimate 'emax' */
1441587fa25dSMark F. Adams         KSP eksp; Mat Lmat = Aarr[level];
1442fc4362bfSMark F. Adams         Vec bb, xx; PC pc;
1443f6536408SMark F. Adams         const PCType type;
1444038e3b61SMark F. Adams 
1445f6536408SMark F. Adams         ierr = PCGetType( subpc, &type );   CHKERRQ(ierr);
14465745e0f5SMark F. Adams         ierr = MatGetVecs( Lmat, &bb, 0 );         CHKERRQ(ierr);
14475745e0f5SMark F. Adams         ierr = MatGetVecs( Lmat, &xx, 0 );         CHKERRQ(ierr);
1448fc4362bfSMark F. Adams         {
1449fc4362bfSMark F. Adams           PetscRandom    rctx;
1450fc4362bfSMark F. Adams           ierr = PetscRandomCreate(wcomm,&rctx);CHKERRQ(ierr);
1451fc4362bfSMark F. Adams           ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr);
1452fc4362bfSMark F. Adams           ierr = VecSetRandom(bb,rctx);CHKERRQ(ierr);
1453fc4362bfSMark F. Adams           ierr = PetscRandomDestroy( &rctx ); CHKERRQ(ierr);
14545b89ad90SMark F. Adams         }
1455fc4362bfSMark F. Adams         ierr = KSPCreate(wcomm,&eksp);CHKERRQ(ierr);
1456038e3b61SMark F. Adams         ierr = KSPSetTolerances( eksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, 10 );
1457fc4362bfSMark F. Adams         CHKERRQ(ierr);
1458fc4362bfSMark F. Adams         ierr = KSPSetNormType( eksp, KSP_NORM_NONE );                 CHKERRQ(ierr);
1459fc4362bfSMark F. Adams 
1460f6536408SMark F. Adams         ierr = KSPAppendOptionsPrefix( eksp, "est_");         CHKERRQ(ierr);
1461f6536408SMark F. Adams         ierr = KSPSetFromOptions( eksp );    CHKERRQ(ierr);
1462f6536408SMark F. Adams 
1463f6536408SMark F. Adams         ierr = KSPSetInitialGuessNonzero( eksp, PETSC_FALSE ); CHKERRQ(ierr);
1464f6536408SMark F. Adams         ierr = KSPSetOperators( eksp, Lmat, Lmat, SAME_NONZERO_PATTERN ); CHKERRQ( ierr );
1465f6536408SMark F. Adams         ierr = KSPGetPC( eksp, &pc );CHKERRQ( ierr );
1466f6536408SMark F. Adams         ierr = PCSetType( pc, type ); CHKERRQ(ierr); /* should be same as eigen estimates op. */
1467f6536408SMark F. Adams 
1468fc4362bfSMark F. Adams         ierr = KSPSetComputeSingularValues( eksp,PETSC_TRUE ); CHKERRQ(ierr);
14695a9b9e01SMark F. Adams 
14705a9b9e01SMark F. Adams 	/* solve - keep stuff out of logging */
14715a9b9e01SMark F. Adams 	ierr = PetscLogEventDeactivate(KSP_Solve);CHKERRQ(ierr);
14725a9b9e01SMark F. Adams 	ierr = PetscLogEventDeactivate(PC_Apply);CHKERRQ(ierr);
1473fc4362bfSMark F. Adams         ierr = KSPSolve( eksp, bb, xx ); CHKERRQ(ierr);
14745a9b9e01SMark F. Adams 	ierr = PetscLogEventActivate(KSP_Solve);CHKERRQ(ierr);
14755a9b9e01SMark F. Adams 	ierr = PetscLogEventActivate(PC_Apply);CHKERRQ(ierr);
14765a9b9e01SMark F. Adams 
1477fc4362bfSMark F. Adams         ierr = KSPComputeExtremeSingularValues( eksp, &emax, &emin ); CHKERRQ(ierr);
14785a9b9e01SMark F. Adams 
1479fc4362bfSMark F. Adams         ierr = VecDestroy( &xx );       CHKERRQ(ierr);
1480fc4362bfSMark F. Adams         ierr = VecDestroy( &bb );       CHKERRQ(ierr);
1481fc4362bfSMark F. Adams         ierr = KSPDestroy( &eksp );       CHKERRQ(ierr);
1482f6536408SMark F. Adams 
14839d5b6da9SMark F. Adams         if (pc_gamg->verbose) {
148441139db5SMark F. Adams           PetscPrintf(PETSC_COMM_WORLD,"\t\t\t%s PC setup max eigen=%e min=%e\n",
148541139db5SMark F. Adams                       __FUNCT__,emax,emin);
1486f6536408SMark F. Adams         }
1487fc4362bfSMark F. Adams       }
1488038e3b61SMark F. Adams       {
1489038e3b61SMark F. Adams         PetscInt N1, N0, tt;
1490038e3b61SMark F. Adams         ierr = MatGetSize( Aarr[level], &N1, &tt );         CHKERRQ(ierr);
1491038e3b61SMark F. Adams         ierr = MatGetSize( Aarr[level+1], &N0, &tt );       CHKERRQ(ierr);
1492f6536408SMark F. Adams         /* heuristic - is this crap? */
1493f6536408SMark F. Adams         emin = 1.*emax/((PetscReal)N1/(PetscReal)N0);
1494038e3b61SMark F. Adams         emax *= 1.05;
1495038e3b61SMark F. Adams       }
1496fc4362bfSMark F. Adams       ierr = KSPChebychevSetEigenvalues( smoother, emax, emin );CHKERRQ(ierr);
1497f6536408SMark F. Adams     }
14985745e0f5SMark F. Adams   }
14995745e0f5SMark F. Adams   {
1500ecd57171SMark F. Adams     /* coarse grid */
1501ecd57171SMark F. Adams     KSP smoother,*k2; PC subpc,pc2; PetscInt ii,first;
15029d5b6da9SMark F. Adams     Mat Lmat = Aarr[pc_gamg->Nlevels-1];
15039d5b6da9SMark F. Adams     ierr = PCMGGetSmoother( pc, 0, &smoother ); CHKERRQ(ierr);
150458471d46SMark F. Adams     ierr = KSPSetOperators( smoother, Lmat, Lmat, SAME_NONZERO_PATTERN ); CHKERRQ(ierr);
15055745e0f5SMark F. Adams     ierr = KSPSetNormType( smoother, KSP_NORM_NONE ); CHKERRQ(ierr);
1506ecd57171SMark F. Adams     ierr = KSPGetPC( smoother, &subpc ); CHKERRQ(ierr);
1507ecd57171SMark F. Adams     ierr = PCSetType( subpc, PCBJACOBI ); CHKERRQ(ierr);
1508ecd57171SMark F. Adams     ierr = PCSetUp( subpc ); CHKERRQ(ierr);
1509ecd57171SMark F. Adams     ierr = PCBJacobiGetSubKSP(subpc,&ii,&first,&k2);CHKERRQ(ierr);
1510ecd57171SMark F. Adams     assert(ii==1);
1511ecd57171SMark F. Adams     ierr = KSPGetPC(k2[0],&pc2);CHKERRQ(ierr);
1512ecd57171SMark F. Adams     ierr = PCSetType( pc2, PCLU ); CHKERRQ(ierr);
1513fc4362bfSMark F. Adams   }
1514737a81a9SMark F. Adams 
1515fc4362bfSMark F. Adams   /* should be called in PCSetFromOptions_GAMG(), but cannot be called prior to PCMGSetLevels() */
1516*ce4cda84SJed Brown   ierr = PetscObjectOptionsBegin((PetscObject)pc);CHKERRQ(ierr);
15179d5b6da9SMark F. Adams   ierr = PCSetFromOptions_MG(pc); CHKERRQ(ierr);
1518*ce4cda84SJed Brown   ierr = PetscOptionsEnd();CHKERRQ(ierr);
1519*ce4cda84SJed Brown   if (mg->galerkin != 2) SETERRQ(wcomm,PETSC_ERR_USER,"GAMG does Galerkin manually so the -pc_mg_galerkin option must not be used.");
15205745e0f5SMark F. Adams 
152158471d46SMark F. Adams   /* set interpolation between the levels, clean up */
15229d5b6da9SMark F. Adams   for (lidx=0,level=pc_gamg->Nlevels-1;
152358471d46SMark F. Adams        lidx<fine_level;
152458471d46SMark F. Adams        lidx++, level--){
15259d5b6da9SMark F. Adams     ierr = PCMGSetInterpolation( pc, lidx+1, Parr[level] );CHKERRQ(ierr);
1526587fa25dSMark F. Adams     ierr = MatDestroy( &Parr[level] );  CHKERRQ(ierr);
1527587fa25dSMark F. Adams     ierr = MatDestroy( &Aarr[level] );  CHKERRQ(ierr);
15285b89ad90SMark F. Adams   }
15295745e0f5SMark F. Adams 
15305b89ad90SMark F. Adams   /* setupcalled is set to 0 so that MG is setup from scratch */
15319d5b6da9SMark F. Adams   pc->setupcalled = 0;
15329d5b6da9SMark F. Adams   ierr = PCSetUp_MG( pc );CHKERRQ( ierr );
15339d5b6da9SMark F. Adams   pc->setupcalled = 1; /* use 1 as signal that this has not been re-setup */
153458471d46SMark F. Adams 
153558471d46SMark F. Adams   {
153658471d46SMark F. Adams     KSP smoother;  /* PCSetUp_MG seems to insists on setting this to GMRES on coarse grid */
15379d5b6da9SMark F. Adams     ierr = PCMGGetSmoother( pc, 0, &smoother ); CHKERRQ(ierr);
153858471d46SMark F. Adams     ierr = KSPSetType( smoother, KSPPREONLY ); CHKERRQ(ierr);
153958471d46SMark F. Adams     ierr = KSPSetUp( smoother ); CHKERRQ(ierr);
154058471d46SMark F. Adams   }
15415f8cf99dSMark F. Adams   }
15425f8cf99dSMark F. Adams   else {
15435f8cf99dSMark F. Adams     KSP smoother;
15449d5b6da9SMark F. Adams     if (pc_gamg->verbose) PetscPrintf(PETSC_COMM_WORLD,"\t[%d]%s one level solver used (system is seen as DD). Using default solver.\n",mype,__FUNCT__);
15459d5b6da9SMark F. Adams     ierr = PCMGGetSmoother( pc, 0, &smoother ); CHKERRQ(ierr);
15465f8cf99dSMark F. Adams     ierr = KSPSetOperators( smoother, Aarr[0], Aarr[0], SAME_NONZERO_PATTERN );   CHKERRQ(ierr);
15475f8cf99dSMark F. Adams     ierr = KSPSetType( smoother, KSPPREONLY ); CHKERRQ(ierr);
15485f8cf99dSMark F. Adams     /* setupcalled is set to 0 so that MG is setup from scratch */
15499d5b6da9SMark F. Adams     pc->setupcalled = 0;
15509d5b6da9SMark F. Adams     ierr = PCSetUp_MG( pc );CHKERRQ( ierr );
15519d5b6da9SMark F. Adams     pc->setupcalled = 1; /* use 1 as signal that this has not been re-setup */
15525f8cf99dSMark F. Adams   }
15535b89ad90SMark F. Adams   PetscFunctionReturn(0);
15545b89ad90SMark F. Adams }
15555b89ad90SMark F. Adams 
1556eb07cef2SMark F. Adams /* ------------------------------------------------------------------------- */
15575b89ad90SMark F. Adams /*
15585b89ad90SMark F. Adams    PCDestroy_GAMG - Destroys the private context for the GAMG preconditioner
15595b89ad90SMark F. Adams    that was created with PCCreate_GAMG().
15605b89ad90SMark F. Adams 
15615b89ad90SMark F. Adams    Input Parameter:
15625b89ad90SMark F. Adams .  pc - the preconditioner context
15635b89ad90SMark F. Adams 
15645b89ad90SMark F. Adams    Application Interface Routine: PCDestroy()
15655b89ad90SMark F. Adams */
15665b89ad90SMark F. Adams #undef __FUNCT__
15675b89ad90SMark F. Adams #define __FUNCT__ "PCDestroy_GAMG"
15685b89ad90SMark F. Adams PetscErrorCode PCDestroy_GAMG(PC pc)
15695b89ad90SMark F. Adams {
15705b89ad90SMark F. Adams   PetscErrorCode  ierr;
15715b89ad90SMark F. Adams   PC_MG           *mg = (PC_MG*)pc->data;
15725b89ad90SMark F. Adams   PC_GAMG         *pc_gamg= (PC_GAMG*)mg->innerctx;
15735b89ad90SMark F. Adams 
15745b89ad90SMark F. Adams   PetscFunctionBegin;
15755b89ad90SMark F. Adams   ierr = PCReset_GAMG(pc);CHKERRQ(ierr);
15765b89ad90SMark F. Adams   ierr = PetscFree(pc_gamg);CHKERRQ(ierr);
15775b89ad90SMark F. Adams   ierr = PCDestroy_MG(pc);CHKERRQ(ierr);
15785b89ad90SMark F. Adams   PetscFunctionReturn(0);
15795b89ad90SMark F. Adams }
15805b89ad90SMark F. Adams 
1581676e1743SMark F. Adams 
1582676e1743SMark F. Adams #undef __FUNCT__
1583676e1743SMark F. Adams #define __FUNCT__ "PCGAMGSetProcEqLim"
1584676e1743SMark F. Adams /*@
1585676e1743SMark F. Adams    PCGAMGSetProcEqLim - Set number of equations to aim for on coarse grids via
1586676e1743SMark F. Adams    processor reduction.
1587676e1743SMark F. Adams 
1588676e1743SMark F. Adams    Not Collective on PC
1589676e1743SMark F. Adams 
1590676e1743SMark F. Adams    Input Parameters:
1591676e1743SMark F. Adams .  pc - the preconditioner context
1592676e1743SMark F. Adams 
1593676e1743SMark F. Adams 
1594676e1743SMark F. Adams    Options Database Key:
1595676e1743SMark F. Adams .  -pc_gamg_process_eq_limit
1596676e1743SMark F. Adams 
1597676e1743SMark F. Adams    Level: intermediate
1598676e1743SMark F. Adams 
1599676e1743SMark F. Adams    Concepts: Unstructured multrigrid preconditioner
1600676e1743SMark F. Adams 
1601676e1743SMark F. Adams .seealso: ()
1602676e1743SMark F. Adams @*/
1603676e1743SMark F. Adams PetscErrorCode  PCGAMGSetProcEqLim(PC pc, PetscInt n)
1604676e1743SMark F. Adams {
1605676e1743SMark F. Adams   PetscErrorCode ierr;
1606676e1743SMark F. Adams 
1607676e1743SMark F. Adams   PetscFunctionBegin;
1608676e1743SMark F. Adams   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1609676e1743SMark F. Adams   ierr = PetscTryMethod(pc,"PCGAMGSetProcEqLim_C",(PC,PetscInt),(pc,n));CHKERRQ(ierr);
1610676e1743SMark F. Adams   PetscFunctionReturn(0);
1611676e1743SMark F. Adams }
1612676e1743SMark F. Adams 
1613676e1743SMark F. Adams EXTERN_C_BEGIN
1614676e1743SMark F. Adams #undef __FUNCT__
1615676e1743SMark F. Adams #define __FUNCT__ "PCGAMGSetProcEqLim_GAMG"
1616676e1743SMark F. Adams PetscErrorCode PCGAMGSetProcEqLim_GAMG(PC pc, PetscInt n)
1617676e1743SMark F. Adams {
1618c20e4228SMark F. Adams   PC_MG           *mg = (PC_MG*)pc->data;
1619c20e4228SMark F. Adams   PC_GAMG         *pc_gamg = (PC_GAMG*)mg->innerctx;
1620676e1743SMark F. Adams 
1621676e1743SMark F. Adams   PetscFunctionBegin;
16229d5b6da9SMark F. Adams   if(n>0) pc_gamg->min_eq_proc = n;
1623676e1743SMark F. Adams   PetscFunctionReturn(0);
1624676e1743SMark F. Adams }
1625676e1743SMark F. Adams EXTERN_C_END
1626676e1743SMark F. Adams 
1627676e1743SMark F. Adams #undef __FUNCT__
1628389730f3SMark F. Adams #define __FUNCT__ "PCGAMGSetCoarseEqLim"
1629389730f3SMark F. Adams /*@
1630389730f3SMark F. Adams    PCGAMGSetCoarseEqLim - Set max number of equations on coarse grids.
1631389730f3SMark F. Adams 
1632389730f3SMark F. Adams  Collective on PC
1633389730f3SMark F. Adams 
1634389730f3SMark F. Adams    Input Parameters:
1635389730f3SMark F. Adams .  pc - the preconditioner context
1636389730f3SMark F. Adams 
1637389730f3SMark F. Adams 
1638389730f3SMark F. Adams    Options Database Key:
1639389730f3SMark F. Adams .  -pc_gamg_coarse_eq_limit
1640389730f3SMark F. Adams 
1641389730f3SMark F. Adams    Level: intermediate
1642389730f3SMark F. Adams 
1643389730f3SMark F. Adams    Concepts: Unstructured multrigrid preconditioner
1644389730f3SMark F. Adams 
1645389730f3SMark F. Adams .seealso: ()
1646389730f3SMark F. Adams  @*/
1647389730f3SMark F. Adams PetscErrorCode PCGAMGSetCoarseEqLim(PC pc, PetscInt n)
1648389730f3SMark F. Adams {
1649389730f3SMark F. Adams   PetscErrorCode ierr;
1650389730f3SMark F. Adams 
1651389730f3SMark F. Adams   PetscFunctionBegin;
1652389730f3SMark F. Adams   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1653389730f3SMark F. Adams   ierr = PetscTryMethod(pc,"PCGAMGSetCoarseEqLim_C",(PC,PetscInt),(pc,n));CHKERRQ(ierr);
1654389730f3SMark F. Adams   PetscFunctionReturn(0);
1655389730f3SMark F. Adams }
1656389730f3SMark F. Adams 
1657389730f3SMark F. Adams EXTERN_C_BEGIN
1658389730f3SMark F. Adams #undef __FUNCT__
1659389730f3SMark F. Adams #define __FUNCT__ "PCGAMGSetCoarseEqLim_GAMG"
1660389730f3SMark F. Adams PetscErrorCode PCGAMGSetCoarseEqLim_GAMG(PC pc, PetscInt n)
1661389730f3SMark F. Adams {
1662389730f3SMark F. Adams   PC_MG           *mg = (PC_MG*)pc->data;
1663389730f3SMark F. Adams   PC_GAMG         *pc_gamg = (PC_GAMG*)mg->innerctx;
1664389730f3SMark F. Adams 
1665389730f3SMark F. Adams   PetscFunctionBegin;
16669d5b6da9SMark F. Adams   if(n>0) pc_gamg->coarse_eq_limit = n;
1667389730f3SMark F. Adams   PetscFunctionReturn(0);
1668389730f3SMark F. Adams }
1669389730f3SMark F. Adams EXTERN_C_END
1670389730f3SMark F. Adams 
1671389730f3SMark F. Adams #undef __FUNCT__
16728263b398SMark F. Adams #define __FUNCT__ "PCGAMGSetRepartitioning"
1673676e1743SMark F. Adams /*@
16748263b398SMark F. Adams    PCGAMGSetRepartitioning - Repartition the coarse grids
1675676e1743SMark F. Adams 
1676676e1743SMark F. Adams    Collective on PC
1677676e1743SMark F. Adams 
1678676e1743SMark F. Adams    Input Parameters:
1679676e1743SMark F. Adams .  pc - the preconditioner context
1680676e1743SMark F. Adams 
1681676e1743SMark F. Adams 
1682676e1743SMark F. Adams    Options Database Key:
16838263b398SMark F. Adams .  -pc_gamg_repartition
1684676e1743SMark F. Adams 
1685676e1743SMark F. Adams    Level: intermediate
1686676e1743SMark F. Adams 
1687676e1743SMark F. Adams    Concepts: Unstructured multrigrid preconditioner
1688676e1743SMark F. Adams 
1689676e1743SMark F. Adams .seealso: ()
1690676e1743SMark F. Adams @*/
16918263b398SMark F. Adams PetscErrorCode PCGAMGSetRepartitioning(PC pc, PetscBool n)
1692676e1743SMark F. Adams {
1693676e1743SMark F. Adams   PetscErrorCode ierr;
1694676e1743SMark F. Adams 
1695676e1743SMark F. Adams   PetscFunctionBegin;
1696676e1743SMark F. Adams   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
16978263b398SMark F. Adams   ierr = PetscTryMethod(pc,"PCGAMGSetRepartitioning_C",(PC,PetscBool),(pc,n));CHKERRQ(ierr);
1698676e1743SMark F. Adams   PetscFunctionReturn(0);
1699676e1743SMark F. Adams }
1700676e1743SMark F. Adams 
1701676e1743SMark F. Adams EXTERN_C_BEGIN
1702676e1743SMark F. Adams #undef __FUNCT__
17038263b398SMark F. Adams #define __FUNCT__ "PCGAMGSetRepartitioning_GAMG"
17048263b398SMark F. Adams PetscErrorCode PCGAMGSetRepartitioning_GAMG(PC pc, PetscBool n)
1705676e1743SMark F. Adams {
1706c20e4228SMark F. Adams   PC_MG           *mg = (PC_MG*)pc->data;
1707c20e4228SMark F. Adams   PC_GAMG         *pc_gamg = (PC_GAMG*)mg->innerctx;
1708676e1743SMark F. Adams 
1709676e1743SMark F. Adams   PetscFunctionBegin;
17109d5b6da9SMark F. Adams   pc_gamg->repart = n;
1711676e1743SMark F. Adams   PetscFunctionReturn(0);
1712676e1743SMark F. Adams }
1713676e1743SMark F. Adams EXTERN_C_END
1714676e1743SMark F. Adams 
1715676e1743SMark F. Adams #undef __FUNCT__
17164ef23d27SMark F. Adams #define __FUNCT__ "PCGAMGSetNlevels"
17174ef23d27SMark F. Adams /*@
17184ef23d27SMark F. Adams    PCGAMGSetNlevels -
17194ef23d27SMark F. Adams 
17204ef23d27SMark F. Adams    Not collective on PC
17214ef23d27SMark F. Adams 
17224ef23d27SMark F. Adams    Input Parameters:
17234ef23d27SMark F. Adams .  pc - the preconditioner context
17244ef23d27SMark F. Adams 
17254ef23d27SMark F. Adams 
17264ef23d27SMark F. Adams    Options Database Key:
17274ef23d27SMark F. Adams .  -pc_mg_levels
17284ef23d27SMark F. Adams 
17294ef23d27SMark F. Adams    Level: intermediate
17304ef23d27SMark F. Adams 
17314ef23d27SMark F. Adams    Concepts: Unstructured multrigrid preconditioner
17324ef23d27SMark F. Adams 
17334ef23d27SMark F. Adams .seealso: ()
17344ef23d27SMark F. Adams @*/
17354ef23d27SMark F. Adams PetscErrorCode PCGAMGSetNlevels(PC pc, PetscInt n)
17364ef23d27SMark F. Adams {
17374ef23d27SMark F. Adams   PetscErrorCode ierr;
17384ef23d27SMark F. Adams 
17394ef23d27SMark F. Adams   PetscFunctionBegin;
17404ef23d27SMark F. Adams   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
17414ef23d27SMark F. Adams   ierr = PetscTryMethod(pc,"PCGAMGSetNlevels_C",(PC,PetscInt),(pc,n));CHKERRQ(ierr);
17424ef23d27SMark F. Adams   PetscFunctionReturn(0);
17434ef23d27SMark F. Adams }
17444ef23d27SMark F. Adams 
17454ef23d27SMark F. Adams EXTERN_C_BEGIN
17464ef23d27SMark F. Adams #undef __FUNCT__
17474ef23d27SMark F. Adams #define __FUNCT__ "PCGAMGSetNlevels_GAMG"
17484ef23d27SMark F. Adams PetscErrorCode PCGAMGSetNlevels_GAMG(PC pc, PetscInt n)
17494ef23d27SMark F. Adams {
17504ef23d27SMark F. Adams   PC_MG           *mg = (PC_MG*)pc->data;
17514ef23d27SMark F. Adams   PC_GAMG         *pc_gamg = (PC_GAMG*)mg->innerctx;
17524ef23d27SMark F. Adams 
17534ef23d27SMark F. Adams   PetscFunctionBegin;
17549d5b6da9SMark F. Adams   pc_gamg->Nlevels = n;
17554ef23d27SMark F. Adams   PetscFunctionReturn(0);
17564ef23d27SMark F. Adams }
17574ef23d27SMark F. Adams EXTERN_C_END
17584ef23d27SMark F. Adams 
17594ef23d27SMark F. Adams #undef __FUNCT__
17603542efc5SMark F. Adams #define __FUNCT__ "PCGAMGSetThreshold"
17613542efc5SMark F. Adams /*@
17623542efc5SMark F. Adams    PCGAMGSetThreshold - Relative threshold to use for dropping edges in aggregation graph
17633542efc5SMark F. Adams 
17643542efc5SMark F. Adams    Not collective on PC
17653542efc5SMark F. Adams 
17663542efc5SMark F. Adams    Input Parameters:
17673542efc5SMark F. Adams .  pc - the preconditioner context
17683542efc5SMark F. Adams 
17693542efc5SMark F. Adams 
17703542efc5SMark F. Adams    Options Database Key:
17713542efc5SMark F. Adams .  -pc_gamg_threshold
17723542efc5SMark F. Adams 
17733542efc5SMark F. Adams    Level: intermediate
17743542efc5SMark F. Adams 
17753542efc5SMark F. Adams    Concepts: Unstructured multrigrid preconditioner
17763542efc5SMark F. Adams 
17773542efc5SMark F. Adams .seealso: ()
17783542efc5SMark F. Adams @*/
17793542efc5SMark F. Adams PetscErrorCode PCGAMGSetThreshold(PC pc, PetscReal n)
17803542efc5SMark F. Adams {
17813542efc5SMark F. Adams   PetscErrorCode ierr;
17823542efc5SMark F. Adams 
17833542efc5SMark F. Adams   PetscFunctionBegin;
17843542efc5SMark F. Adams   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
17853542efc5SMark F. Adams   ierr = PetscTryMethod(pc,"PCGAMGSetThreshold_C",(PC,PetscReal),(pc,n));CHKERRQ(ierr);
17863542efc5SMark F. Adams   PetscFunctionReturn(0);
17873542efc5SMark F. Adams }
17883542efc5SMark F. Adams 
17893542efc5SMark F. Adams EXTERN_C_BEGIN
17903542efc5SMark F. Adams #undef __FUNCT__
17913542efc5SMark F. Adams #define __FUNCT__ "PCGAMGSetThreshold_GAMG"
17923542efc5SMark F. Adams PetscErrorCode PCGAMGSetThreshold_GAMG(PC pc, PetscReal n)
17933542efc5SMark F. Adams {
1794c20e4228SMark F. Adams   PC_MG           *mg = (PC_MG*)pc->data;
1795c20e4228SMark F. Adams   PC_GAMG         *pc_gamg = (PC_GAMG*)mg->innerctx;
17963542efc5SMark F. Adams 
17973542efc5SMark F. Adams   PetscFunctionBegin;
17989d5b6da9SMark F. Adams   pc_gamg->threshold = n;
17993542efc5SMark F. Adams   PetscFunctionReturn(0);
18003542efc5SMark F. Adams }
18013542efc5SMark F. Adams EXTERN_C_END
18023542efc5SMark F. Adams 
18033542efc5SMark F. Adams #undef __FUNCT__
18049d5b6da9SMark F. Adams #define __FUNCT__ "PCGAMGSetType"
1805676e1743SMark F. Adams /*@
18069d5b6da9SMark F. Adams    PCGAMGSetType - Set solution method - calls sub create method
1807676e1743SMark F. Adams 
1808676e1743SMark F. Adams    Collective on PC
1809676e1743SMark F. Adams 
1810676e1743SMark F. Adams    Input Parameters:
1811676e1743SMark F. Adams .  pc - the preconditioner context
1812676e1743SMark F. Adams 
1813676e1743SMark F. Adams 
1814676e1743SMark F. Adams    Options Database Key:
18153542efc5SMark F. Adams .  -pc_gamg_type
1816676e1743SMark F. Adams 
1817676e1743SMark F. Adams    Level: intermediate
1818676e1743SMark F. Adams 
1819676e1743SMark F. Adams    Concepts: Unstructured multrigrid preconditioner
1820676e1743SMark F. Adams 
1821676e1743SMark F. Adams .seealso: ()
1822676e1743SMark F. Adams @*/
18230202ef74SSatish Balay PetscErrorCode PCGAMGSetType( PC pc, const PCGAMGType type )
1824676e1743SMark F. Adams {
1825676e1743SMark F. Adams   PetscErrorCode ierr;
1826676e1743SMark F. Adams 
1827676e1743SMark F. Adams   PetscFunctionBegin;
1828676e1743SMark F. Adams   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
18290202ef74SSatish Balay   ierr = PetscTryMethod(pc,"PCGAMGSetType_C",(PC,const PCGAMGType),(pc,type));
1830676e1743SMark F. Adams   CHKERRQ(ierr);
1831676e1743SMark F. Adams   PetscFunctionReturn(0);
1832676e1743SMark F. Adams }
1833676e1743SMark F. Adams 
1834676e1743SMark F. Adams EXTERN_C_BEGIN
1835676e1743SMark F. Adams #undef __FUNCT__
18369d5b6da9SMark F. Adams #define __FUNCT__ "PCGAMGSetType_GAMG"
18370202ef74SSatish Balay PetscErrorCode PCGAMGSetType_GAMG( PC pc, const PCGAMGType type )
1838676e1743SMark F. Adams {
18399d5b6da9SMark F. Adams   PetscErrorCode ierr,(*r)(PC);
1840676e1743SMark F. Adams 
1841676e1743SMark F. Adams   PetscFunctionBegin;
18429d5b6da9SMark F. Adams   ierr = PetscFListFind(GAMGList,((PetscObject)pc)->comm,type,PETSC_FALSE,(PetscVoidStarFunction)&r);
18439d5b6da9SMark F. Adams   CHKERRQ(ierr);
18449d5b6da9SMark F. Adams 
18459d5b6da9SMark F. Adams   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown GAMG type %s given",type);
18469d5b6da9SMark F. Adams 
18479d5b6da9SMark F. Adams   /* call sub create method */
18489d5b6da9SMark F. Adams   ierr = (*r)(pc); CHKERRQ(ierr);
18499d5b6da9SMark F. Adams 
1850676e1743SMark F. Adams   PetscFunctionReturn(0);
1851676e1743SMark F. Adams }
1852676e1743SMark F. Adams EXTERN_C_END
1853676e1743SMark F. Adams 
18545b89ad90SMark F. Adams #undef __FUNCT__
18555b89ad90SMark F. Adams #define __FUNCT__ "PCSetFromOptions_GAMG"
18565b89ad90SMark F. Adams PetscErrorCode PCSetFromOptions_GAMG( PC pc )
18575b89ad90SMark F. Adams {
1858676e1743SMark F. Adams   PetscErrorCode  ierr;
1859676e1743SMark F. Adams   PC_MG           *mg = (PC_MG*)pc->data;
1860676e1743SMark F. Adams   PC_GAMG         *pc_gamg = (PC_GAMG*)mg->innerctx;
1861676e1743SMark F. Adams   PetscBool        flag;
18625b89ad90SMark F. Adams 
18635b89ad90SMark F. Adams   PetscFunctionBegin;
1864676e1743SMark F. Adams   ierr = PetscOptionsHead("GAMG options"); CHKERRQ(ierr);
1865676e1743SMark F. Adams   {
186675b74bdaSMark F. Adams     /* -pc_gamg_verbose */
18679d5b6da9SMark F. Adams     ierr = PetscOptionsInt("-pc_gamg_verbose","Verbose (debugging) output for PCGAMG",
18689d5b6da9SMark F. Adams                            "none", pc_gamg->verbose,
18699d5b6da9SMark F. Adams                            &pc_gamg->verbose, PETSC_NULL );
18709d5b6da9SMark F. Adams     CHKERRQ(ierr);
187175b74bdaSMark F. Adams 
18728263b398SMark F. Adams     /* -pc_gamg_repartition */
18738263b398SMark F. Adams     ierr = PetscOptionsBool("-pc_gamg_repartition",
18748263b398SMark F. Adams                             "Repartion coarse grids (false)",
18758263b398SMark F. Adams                             "PCGAMGRepartitioning",
18769d5b6da9SMark F. Adams                             pc_gamg->repart,
18779d5b6da9SMark F. Adams                             &pc_gamg->repart,
1878676e1743SMark F. Adams                             &flag);
1879676e1743SMark F. Adams     CHKERRQ(ierr);
1880676e1743SMark F. Adams 
1881c20e4228SMark F. Adams     /* -pc_gamg_process_eq_limit */
1882676e1743SMark F. Adams     ierr = PetscOptionsInt("-pc_gamg_process_eq_limit",
1883676e1743SMark F. Adams                            "Limit (goal) on number of equations per process on coarse grids",
1884676e1743SMark F. Adams                            "PCGAMGSetProcEqLim",
18859d5b6da9SMark F. Adams                            pc_gamg->min_eq_proc,
18869d5b6da9SMark F. Adams                            &pc_gamg->min_eq_proc,
1887676e1743SMark F. Adams                            &flag );
1888676e1743SMark F. Adams     CHKERRQ(ierr);
18893542efc5SMark F. Adams 
1890389730f3SMark F. Adams     /* -pc_gamg_coarse_eq_limit */
1891389730f3SMark F. Adams     ierr = PetscOptionsInt("-pc_gamg_coarse_eq_limit",
1892389730f3SMark F. Adams                            "Limit on number of equations for the coarse grid",
1893389730f3SMark F. Adams                            "PCGAMGSetCoarseEqLim",
18949d5b6da9SMark F. Adams                            pc_gamg->coarse_eq_limit,
18959d5b6da9SMark F. Adams                            &pc_gamg->coarse_eq_limit,
1896389730f3SMark F. Adams                            &flag );
1897389730f3SMark F. Adams     CHKERRQ(ierr);
1898389730f3SMark F. Adams 
1899c20e4228SMark F. Adams     /* -pc_gamg_threshold */
19003542efc5SMark F. Adams     ierr = PetscOptionsReal("-pc_gamg_threshold",
19013542efc5SMark F. Adams                             "Relative threshold to use for dropping edges in aggregation graph",
19023542efc5SMark F. Adams                             "PCGAMGSetThreshold",
19039d5b6da9SMark F. Adams                             pc_gamg->threshold,
19049d5b6da9SMark F. Adams                             &pc_gamg->threshold,
19053542efc5SMark F. Adams                             &flag );
19063542efc5SMark F. Adams     CHKERRQ(ierr);
19074ef23d27SMark F. Adams 
19084ef23d27SMark F. Adams     ierr = PetscOptionsInt("-pc_mg_levels",
19094ef23d27SMark F. Adams                            "Set number of MG levels",
19104ef23d27SMark F. Adams                            "PCGAMGSetNlevels",
19119d5b6da9SMark F. Adams                            pc_gamg->Nlevels,
19129d5b6da9SMark F. Adams                            &pc_gamg->Nlevels,
19134ef23d27SMark F. Adams                            &flag );
1914676e1743SMark F. Adams   }
1915676e1743SMark F. Adams   ierr = PetscOptionsTail();CHKERRQ(ierr);
1916676e1743SMark F. Adams 
19175b89ad90SMark F. Adams   PetscFunctionReturn(0);
19185b89ad90SMark F. Adams }
19195b89ad90SMark F. Adams 
19205b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */
19215b89ad90SMark F. Adams /*MC
19229d5b6da9SMark F. Adams      PCCreate_GAMG - Geometric algebraic multigrid (AMG) preconditioning framework.
19239d5b6da9SMark F. Adams        - This is the entry point to GAMG, registered in pcregis.c
19245b89ad90SMark F. Adams 
1925280d9858SJed Brown    Options Database Keys:
19265b89ad90SMark F. Adams    Multigrid options(inherited)
1927280d9858SJed Brown +  -pc_mg_cycles <1>: 1 for V cycle, 2 for W-cycle (PCMGSetCycleType)
1928280d9858SJed Brown .  -pc_mg_smoothup <1>: Number of post-smoothing steps (PCMGSetNumberSmoothUp)
1929280d9858SJed Brown .  -pc_mg_smoothdown <1>: Number of pre-smoothing steps (PCMGSetNumberSmoothDown)
1930280d9858SJed Brown -  -pc_mg_type <multiplicative>: (one of) additive multiplicative full cascade kascade
19315b89ad90SMark F. Adams 
19325b89ad90SMark F. Adams   Level: intermediate
1933280d9858SJed Brown 
19345b89ad90SMark F. Adams   Concepts: multigrid
19355b89ad90SMark F. Adams 
19365b89ad90SMark F. Adams .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC, PCMGType,
1937280d9858SJed Brown            PCMGSetLevels(), PCMGGetLevels(), PCMGSetType(), PCMGSetCycleType(), PCMGSetNumberSmoothDown(),
19385b89ad90SMark F. Adams            PCMGSetNumberSmoothUp(), PCMGGetCoarseSolve(), PCMGSetResidual(), PCMGSetInterpolation(),
19395b89ad90SMark F. Adams            PCMGSetRestriction(), PCMGGetSmoother(), PCMGGetSmootherUp(), PCMGGetSmootherDown(),
19405b89ad90SMark F. Adams            PCMGSetCyclesOnLevel(), PCMGSetRhs(), PCMGSetX(), PCMGSetR()
19415b89ad90SMark F. Adams M*/
19425b89ad90SMark F. Adams EXTERN_C_BEGIN
19435b89ad90SMark F. Adams #undef __FUNCT__
19445b89ad90SMark F. Adams #define __FUNCT__ "PCCreate_GAMG"
19455b89ad90SMark F. Adams PetscErrorCode  PCCreate_GAMG( PC pc )
19465b89ad90SMark F. Adams {
19475b89ad90SMark F. Adams   PetscErrorCode  ierr;
19485b89ad90SMark F. Adams   PC_GAMG         *pc_gamg;
19495b89ad90SMark F. Adams   PC_MG           *mg;
19505ef31b24SMark F. Adams   PetscClassId     cookie;
19519d5b6da9SMark F. Adams 
19525ee9c036SSatish Balay #if defined PETSC_USE_LOG
19539d5b6da9SMark F. Adams   static long count = 0;
19545ee9c036SSatish Balay #endif
19555b89ad90SMark F. Adams 
19565b89ad90SMark F. Adams   PetscFunctionBegin;
19575b89ad90SMark F. Adams   /* PCGAMG is an inherited class of PCMG. Initialize pc as PCMG */
19585b89ad90SMark F. Adams   ierr = PCSetType( pc, PCMG );  CHKERRQ(ierr); /* calls PCCreate_MG() and MGCreate_Private() */
19595b89ad90SMark F. Adams   ierr = PetscObjectChangeTypeName( (PetscObject)pc, PCGAMG ); CHKERRQ(ierr);
19605b89ad90SMark F. Adams 
19615b89ad90SMark F. Adams   /* create a supporting struct and attach it to pc */
19625b89ad90SMark F. Adams   ierr = PetscNewLog( pc, PC_GAMG, &pc_gamg ); CHKERRQ(ierr);
19635b89ad90SMark F. Adams   mg = (PC_MG*)pc->data;
1964*ce4cda84SJed Brown   mg->galerkin = 2;             /* Use Galerkin, but it is computed externally */
19655b89ad90SMark F. Adams   mg->innerctx = pc_gamg;
19665b89ad90SMark F. Adams 
19679d5b6da9SMark F. Adams   pc_gamg->setup_count = 0;
19689d5b6da9SMark F. Adams   /* these should be in subctx but repartitioning needs simple arrays */
19699d5b6da9SMark F. Adams   pc_gamg->data_sz = 0;
19709d5b6da9SMark F. Adams   pc_gamg->data = 0;
19715b89ad90SMark F. Adams 
19729d5b6da9SMark F. Adams   /* register AMG type */
19739d5b6da9SMark F. Adams   if( !GAMGList ){
19749d5b6da9SMark F. Adams     ierr = PetscFListAdd(&GAMGList,GAMGGEO,"PCCreateGAMG_GEO",(void(*)(void))PCCreateGAMG_GEO);CHKERRQ(ierr);
19759d5b6da9SMark F. Adams     ierr = PetscFListAdd(&GAMGList,GAMGAGG,"PCCreateGAMG_AGG",(void(*)(void))PCCreateGAMG_AGG);CHKERRQ(ierr);
19769d5b6da9SMark F. Adams   }
19779d5b6da9SMark F. Adams 
19789d5b6da9SMark F. Adams   /* overwrite the pointers of PCMG by the functions of base class PCGAMG */
19795b89ad90SMark F. Adams   pc->ops->setfromoptions = PCSetFromOptions_GAMG;
19805b89ad90SMark F. Adams   pc->ops->setup          = PCSetUp_GAMG;
19815b89ad90SMark F. Adams   pc->ops->reset          = PCReset_GAMG;
19825b89ad90SMark F. Adams   pc->ops->destroy        = PCDestroy_GAMG;
19835b89ad90SMark F. Adams 
19845b89ad90SMark F. Adams   ierr = PetscObjectComposeFunctionDynamic( (PetscObject)pc,
1985676e1743SMark F. Adams 					    "PCGAMGSetProcEqLim_C",
1986676e1743SMark F. Adams 					    "PCGAMGSetProcEqLim_GAMG",
1987676e1743SMark F. Adams 					    PCGAMGSetProcEqLim_GAMG);
1988676e1743SMark F. Adams   CHKERRQ(ierr);
1989676e1743SMark F. Adams 
1990676e1743SMark F. Adams   ierr = PetscObjectComposeFunctionDynamic( (PetscObject)pc,
1991389730f3SMark F. Adams 					    "PCGAMGSetCoarseEqLim_C",
1992389730f3SMark F. Adams 					    "PCGAMGSetCoarseEqLim_GAMG",
1993389730f3SMark F. Adams 					    PCGAMGSetCoarseEqLim_GAMG);
1994389730f3SMark F. Adams   CHKERRQ(ierr);
1995389730f3SMark F. Adams 
1996389730f3SMark F. Adams   ierr = PetscObjectComposeFunctionDynamic( (PetscObject)pc,
19978263b398SMark F. Adams 					    "PCGAMGSetRepartitioning_C",
19988263b398SMark F. Adams 					    "PCGAMGSetRepartitioning_GAMG",
19998263b398SMark F. Adams 					    PCGAMGSetRepartitioning_GAMG);
2000676e1743SMark F. Adams   CHKERRQ(ierr);
2001676e1743SMark F. Adams 
2002676e1743SMark F. Adams   ierr = PetscObjectComposeFunctionDynamic( (PetscObject)pc,
20033542efc5SMark F. Adams 					    "PCGAMGSetThreshold_C",
20043542efc5SMark F. Adams 					    "PCGAMGSetThreshold_GAMG",
20053542efc5SMark F. Adams 					    PCGAMGSetThreshold_GAMG);
20063542efc5SMark F. Adams   CHKERRQ(ierr);
20073542efc5SMark F. Adams 
20083542efc5SMark F. Adams   ierr = PetscObjectComposeFunctionDynamic( (PetscObject)pc,
20099d5b6da9SMark F. Adams 					    "PCGAMGSetType_C",
20109d5b6da9SMark F. Adams 					    "PCGAMGSetType_GAMG",
20119d5b6da9SMark F. Adams 					    PCGAMGSetType_GAMG);
2012676e1743SMark F. Adams   CHKERRQ(ierr);
2013c97e1df0SMark F. Adams 
20149d5b6da9SMark F. Adams   pc_gamg->repart = PETSC_FALSE;
20159d5b6da9SMark F. Adams   pc_gamg->min_eq_proc = 100;
20169d5b6da9SMark F. Adams   pc_gamg->coarse_eq_limit = 1000;
20179d5b6da9SMark F. Adams   pc_gamg->threshold = 0.05;
20189d5b6da9SMark F. Adams   pc_gamg->Nlevels = GAMG_MAXLEVELS;
20199d5b6da9SMark F. Adams   pc_gamg->verbose = 0;
20209d5b6da9SMark F. Adams   pc_gamg->emax_id = -1;
20219d5b6da9SMark F. Adams   pc_gamg->col_bs_id = -1;
20229d5b6da9SMark F. Adams 
20239d5b6da9SMark F. Adams   /* instantiate derived type */
20249d5b6da9SMark F. Adams   ierr = PetscOptionsHead("GAMG options"); CHKERRQ(ierr);
20259d5b6da9SMark F. Adams   {
20269d5b6da9SMark F. Adams     char tname[256] = GAMGAGG;
20279d5b6da9SMark F. Adams     ierr = PetscOptionsList("-pc_gamg_type","Type of GAMG method","PCGAMGSetType",
20289d5b6da9SMark F. Adams                             GAMGList, tname, tname, sizeof(tname), PETSC_NULL );
20299d5b6da9SMark F. Adams     CHKERRQ(ierr);
20309d5b6da9SMark F. Adams     ierr = PCGAMGSetType( pc, tname ); CHKERRQ(ierr);
20319d5b6da9SMark F. Adams   }
20329d5b6da9SMark F. Adams   ierr = PetscOptionsTail();CHKERRQ(ierr);
20339d5b6da9SMark F. Adams 
2034b4fbaa2aSMark F. Adams #if defined PETSC_USE_LOG
2035785cba28SMark F. Adams   if( count++ == 0 ) {
20365ef31b24SMark F. Adams     PetscClassIdRegister("GAMG Setup",&cookie);
2037b4fbaa2aSMark F. Adams     PetscLogEventRegister("GAMG: createProl", cookie, &gamg_setup_events[SET1]);
20382a44bfbaSMark F. Adams     PetscLogEventRegister("  Graph", cookie, &gamg_setup_events[GRAPH]);
20392a44bfbaSMark F. Adams     PetscLogEventRegister("    G.Mat", cookie, &gamg_setup_events[GRAPH_MAT]);
20402a44bfbaSMark F. Adams     PetscLogEventRegister("    G.Filter", cookie, &gamg_setup_events[GRAPH_FILTER]);
20412a44bfbaSMark F. Adams     PetscLogEventRegister("    G.Square", cookie, &gamg_setup_events[GRAPH_SQR]);
2042b4fbaa2aSMark F. Adams     PetscLogEventRegister("  MIS/Agg", cookie, &gamg_setup_events[SET4]);
2043b4fbaa2aSMark F. Adams     PetscLogEventRegister("  geo: growSupp", cookie, &gamg_setup_events[SET5]);
2044b4fbaa2aSMark F. Adams     PetscLogEventRegister("  geo: triangle", cookie, &gamg_setup_events[SET6]);
2045b4fbaa2aSMark F. Adams     PetscLogEventRegister("    search&set", cookie, &gamg_setup_events[FIND_V]);
2046b4fbaa2aSMark F. Adams     PetscLogEventRegister("  SA: init", cookie, &gamg_setup_events[SET7]);
2047b4fbaa2aSMark F. Adams     /* PetscLogEventRegister("  SA: frmProl0", cookie, &gamg_setup_events[SET8]); */
2048b4fbaa2aSMark F. Adams     PetscLogEventRegister("  SA: smooth", cookie, &gamg_setup_events[SET9]);
2049b4fbaa2aSMark F. Adams     PetscLogEventRegister("GAMG: partLevel", cookie, &gamg_setup_events[SET2]);
2050ed3f9983SMark F. Adams     PetscLogEventRegister("  repartition", cookie, &gamg_setup_events[SET12]);
2051ed3f9983SMark F. Adams     PetscLogEventRegister("  Invert-Sort", cookie, &gamg_setup_events[SET13]);
2052ed3f9983SMark F. Adams     PetscLogEventRegister("  Move A", cookie, &gamg_setup_events[SET14]);
2053ed3f9983SMark F. Adams     PetscLogEventRegister("  Move P", cookie, &gamg_setup_events[SET15]);
2054f852f58cSMark F. Adams 
2055b4fbaa2aSMark F. Adams     /* PetscLogEventRegister(" PL move data", cookie, &gamg_setup_events[SET13]); */
2056b4fbaa2aSMark F. Adams     /* PetscLogEventRegister("GAMG: fix", cookie, &gamg_setup_events[SET10]); */
2057b4fbaa2aSMark F. Adams     /* PetscLogEventRegister("GAMG: set levels", cookie, &gamg_setup_events[SET11]); */
20585ef31b24SMark F. Adams 
2059b4fbaa2aSMark F. Adams     /* create timer stages */
2060b4fbaa2aSMark F. Adams #if defined GAMG_STAGES
2061b4fbaa2aSMark F. Adams     {
2062b4fbaa2aSMark F. Adams       char str[32];
2063b4fbaa2aSMark F. Adams       sprintf(str,"MG Level %d (finest)",0);
2064b4fbaa2aSMark F. Adams       PetscLogStageRegister(str, &gamg_stages[0]);
2065b4fbaa2aSMark F. Adams       PetscInt lidx;
2066b4fbaa2aSMark F. Adams       for (lidx=1;lidx<9;lidx++){
2067b4fbaa2aSMark F. Adams 	sprintf(str,"MG Level %d",lidx);
2068b4fbaa2aSMark F. Adams 	PetscLogStageRegister(str, &gamg_stages[lidx]);
2069b4fbaa2aSMark F. Adams       }
2070b4fbaa2aSMark F. Adams     }
2071b4fbaa2aSMark F. Adams #endif
2072b4fbaa2aSMark F. Adams   }
2073b4fbaa2aSMark F. Adams #endif
20745b89ad90SMark F. Adams   PetscFunctionReturn(0);
20755b89ad90SMark F. Adams }
20765b89ad90SMark F. Adams EXTERN_C_END
2077