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; 1338*f73f8d2cSSatish 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() */ 15169d5b6da9SMark F. Adams ierr = PCSetFromOptions_MG(pc); CHKERRQ(ierr); 15175b89ad90SMark F. Adams { 15185b89ad90SMark F. Adams PetscBool galerkin; 15199d5b6da9SMark F. Adams ierr = PCMGGetGalerkin( pc, &galerkin); CHKERRQ(ierr); 15205b89ad90SMark F. Adams if(galerkin){ 15215b89ad90SMark F. Adams SETERRQ(wcomm,PETSC_ERR_ARG_WRONG, "GAMG does galerkin manually so it must not be used in PC_MG."); 15225b89ad90SMark F. Adams } 15235b89ad90SMark F. Adams } 15245745e0f5SMark F. Adams 152558471d46SMark F. Adams /* set interpolation between the levels, clean up */ 15269d5b6da9SMark F. Adams for (lidx=0,level=pc_gamg->Nlevels-1; 152758471d46SMark F. Adams lidx<fine_level; 152858471d46SMark F. Adams lidx++, level--){ 15299d5b6da9SMark F. Adams ierr = PCMGSetInterpolation( pc, lidx+1, Parr[level] );CHKERRQ(ierr); 1530587fa25dSMark F. Adams ierr = MatDestroy( &Parr[level] ); CHKERRQ(ierr); 1531587fa25dSMark F. Adams ierr = MatDestroy( &Aarr[level] ); CHKERRQ(ierr); 15325b89ad90SMark F. Adams } 15335745e0f5SMark F. Adams 15345b89ad90SMark F. Adams /* setupcalled is set to 0 so that MG is setup from scratch */ 15359d5b6da9SMark F. Adams pc->setupcalled = 0; 15369d5b6da9SMark F. Adams ierr = PCSetUp_MG( pc );CHKERRQ( ierr ); 15379d5b6da9SMark F. Adams pc->setupcalled = 1; /* use 1 as signal that this has not been re-setup */ 153858471d46SMark F. Adams 153958471d46SMark F. Adams { 154058471d46SMark F. Adams KSP smoother; /* PCSetUp_MG seems to insists on setting this to GMRES on coarse grid */ 15419d5b6da9SMark F. Adams ierr = PCMGGetSmoother( pc, 0, &smoother ); CHKERRQ(ierr); 154258471d46SMark F. Adams ierr = KSPSetType( smoother, KSPPREONLY ); CHKERRQ(ierr); 154358471d46SMark F. Adams ierr = KSPSetUp( smoother ); CHKERRQ(ierr); 154458471d46SMark F. Adams } 15455f8cf99dSMark F. Adams } 15465f8cf99dSMark F. Adams else { 15475f8cf99dSMark F. Adams KSP smoother; 15489d5b6da9SMark 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__); 15499d5b6da9SMark F. Adams ierr = PCMGGetSmoother( pc, 0, &smoother ); CHKERRQ(ierr); 15505f8cf99dSMark F. Adams ierr = KSPSetOperators( smoother, Aarr[0], Aarr[0], SAME_NONZERO_PATTERN ); CHKERRQ(ierr); 15515f8cf99dSMark F. Adams ierr = KSPSetType( smoother, KSPPREONLY ); CHKERRQ(ierr); 15525f8cf99dSMark F. Adams /* setupcalled is set to 0 so that MG is setup from scratch */ 15539d5b6da9SMark F. Adams pc->setupcalled = 0; 15549d5b6da9SMark F. Adams ierr = PCSetUp_MG( pc );CHKERRQ( ierr ); 15559d5b6da9SMark F. Adams pc->setupcalled = 1; /* use 1 as signal that this has not been re-setup */ 15565f8cf99dSMark F. Adams } 15575b89ad90SMark F. Adams PetscFunctionReturn(0); 15585b89ad90SMark F. Adams } 15595b89ad90SMark F. Adams 1560eb07cef2SMark F. Adams /* ------------------------------------------------------------------------- */ 15615b89ad90SMark F. Adams /* 15625b89ad90SMark F. Adams PCDestroy_GAMG - Destroys the private context for the GAMG preconditioner 15635b89ad90SMark F. Adams that was created with PCCreate_GAMG(). 15645b89ad90SMark F. Adams 15655b89ad90SMark F. Adams Input Parameter: 15665b89ad90SMark F. Adams . pc - the preconditioner context 15675b89ad90SMark F. Adams 15685b89ad90SMark F. Adams Application Interface Routine: PCDestroy() 15695b89ad90SMark F. Adams */ 15705b89ad90SMark F. Adams #undef __FUNCT__ 15715b89ad90SMark F. Adams #define __FUNCT__ "PCDestroy_GAMG" 15725b89ad90SMark F. Adams PetscErrorCode PCDestroy_GAMG(PC pc) 15735b89ad90SMark F. Adams { 15745b89ad90SMark F. Adams PetscErrorCode ierr; 15755b89ad90SMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 15765b89ad90SMark F. Adams PC_GAMG *pc_gamg= (PC_GAMG*)mg->innerctx; 15775b89ad90SMark F. Adams 15785b89ad90SMark F. Adams PetscFunctionBegin; 15795b89ad90SMark F. Adams ierr = PCReset_GAMG(pc);CHKERRQ(ierr); 15805b89ad90SMark F. Adams ierr = PetscFree(pc_gamg);CHKERRQ(ierr); 15815b89ad90SMark F. Adams ierr = PCDestroy_MG(pc);CHKERRQ(ierr); 15825b89ad90SMark F. Adams PetscFunctionReturn(0); 15835b89ad90SMark F. Adams } 15845b89ad90SMark F. Adams 1585676e1743SMark F. Adams 1586676e1743SMark F. Adams #undef __FUNCT__ 1587676e1743SMark F. Adams #define __FUNCT__ "PCGAMGSetProcEqLim" 1588676e1743SMark F. Adams /*@ 1589676e1743SMark F. Adams PCGAMGSetProcEqLim - Set number of equations to aim for on coarse grids via 1590676e1743SMark F. Adams processor reduction. 1591676e1743SMark F. Adams 1592676e1743SMark F. Adams Not Collective on PC 1593676e1743SMark F. Adams 1594676e1743SMark F. Adams Input Parameters: 1595676e1743SMark F. Adams . pc - the preconditioner context 1596676e1743SMark F. Adams 1597676e1743SMark F. Adams 1598676e1743SMark F. Adams Options Database Key: 1599676e1743SMark F. Adams . -pc_gamg_process_eq_limit 1600676e1743SMark F. Adams 1601676e1743SMark F. Adams Level: intermediate 1602676e1743SMark F. Adams 1603676e1743SMark F. Adams Concepts: Unstructured multrigrid preconditioner 1604676e1743SMark F. Adams 1605676e1743SMark F. Adams .seealso: () 1606676e1743SMark F. Adams @*/ 1607676e1743SMark F. Adams PetscErrorCode PCGAMGSetProcEqLim(PC pc, PetscInt n) 1608676e1743SMark F. Adams { 1609676e1743SMark F. Adams PetscErrorCode ierr; 1610676e1743SMark F. Adams 1611676e1743SMark F. Adams PetscFunctionBegin; 1612676e1743SMark F. Adams PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1613676e1743SMark F. Adams ierr = PetscTryMethod(pc,"PCGAMGSetProcEqLim_C",(PC,PetscInt),(pc,n));CHKERRQ(ierr); 1614676e1743SMark F. Adams PetscFunctionReturn(0); 1615676e1743SMark F. Adams } 1616676e1743SMark F. Adams 1617676e1743SMark F. Adams EXTERN_C_BEGIN 1618676e1743SMark F. Adams #undef __FUNCT__ 1619676e1743SMark F. Adams #define __FUNCT__ "PCGAMGSetProcEqLim_GAMG" 1620676e1743SMark F. Adams PetscErrorCode PCGAMGSetProcEqLim_GAMG(PC pc, PetscInt n) 1621676e1743SMark F. Adams { 1622c20e4228SMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 1623c20e4228SMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 1624676e1743SMark F. Adams 1625676e1743SMark F. Adams PetscFunctionBegin; 16269d5b6da9SMark F. Adams if(n>0) pc_gamg->min_eq_proc = n; 1627676e1743SMark F. Adams PetscFunctionReturn(0); 1628676e1743SMark F. Adams } 1629676e1743SMark F. Adams EXTERN_C_END 1630676e1743SMark F. Adams 1631676e1743SMark F. Adams #undef __FUNCT__ 1632389730f3SMark F. Adams #define __FUNCT__ "PCGAMGSetCoarseEqLim" 1633389730f3SMark F. Adams /*@ 1634389730f3SMark F. Adams PCGAMGSetCoarseEqLim - Set max number of equations on coarse grids. 1635389730f3SMark F. Adams 1636389730f3SMark F. Adams Collective on PC 1637389730f3SMark F. Adams 1638389730f3SMark F. Adams Input Parameters: 1639389730f3SMark F. Adams . pc - the preconditioner context 1640389730f3SMark F. Adams 1641389730f3SMark F. Adams 1642389730f3SMark F. Adams Options Database Key: 1643389730f3SMark F. Adams . -pc_gamg_coarse_eq_limit 1644389730f3SMark F. Adams 1645389730f3SMark F. Adams Level: intermediate 1646389730f3SMark F. Adams 1647389730f3SMark F. Adams Concepts: Unstructured multrigrid preconditioner 1648389730f3SMark F. Adams 1649389730f3SMark F. Adams .seealso: () 1650389730f3SMark F. Adams @*/ 1651389730f3SMark F. Adams PetscErrorCode PCGAMGSetCoarseEqLim(PC pc, PetscInt n) 1652389730f3SMark F. Adams { 1653389730f3SMark F. Adams PetscErrorCode ierr; 1654389730f3SMark F. Adams 1655389730f3SMark F. Adams PetscFunctionBegin; 1656389730f3SMark F. Adams PetscValidHeaderSpecific(pc,PC_CLASSID,1); 1657389730f3SMark F. Adams ierr = PetscTryMethod(pc,"PCGAMGSetCoarseEqLim_C",(PC,PetscInt),(pc,n));CHKERRQ(ierr); 1658389730f3SMark F. Adams PetscFunctionReturn(0); 1659389730f3SMark F. Adams } 1660389730f3SMark F. Adams 1661389730f3SMark F. Adams EXTERN_C_BEGIN 1662389730f3SMark F. Adams #undef __FUNCT__ 1663389730f3SMark F. Adams #define __FUNCT__ "PCGAMGSetCoarseEqLim_GAMG" 1664389730f3SMark F. Adams PetscErrorCode PCGAMGSetCoarseEqLim_GAMG(PC pc, PetscInt n) 1665389730f3SMark F. Adams { 1666389730f3SMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 1667389730f3SMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 1668389730f3SMark F. Adams 1669389730f3SMark F. Adams PetscFunctionBegin; 16709d5b6da9SMark F. Adams if(n>0) pc_gamg->coarse_eq_limit = n; 1671389730f3SMark F. Adams PetscFunctionReturn(0); 1672389730f3SMark F. Adams } 1673389730f3SMark F. Adams EXTERN_C_END 1674389730f3SMark F. Adams 1675389730f3SMark F. Adams #undef __FUNCT__ 16768263b398SMark F. Adams #define __FUNCT__ "PCGAMGSetRepartitioning" 1677676e1743SMark F. Adams /*@ 16788263b398SMark F. Adams PCGAMGSetRepartitioning - Repartition the coarse grids 1679676e1743SMark F. Adams 1680676e1743SMark F. Adams Collective on PC 1681676e1743SMark F. Adams 1682676e1743SMark F. Adams Input Parameters: 1683676e1743SMark F. Adams . pc - the preconditioner context 1684676e1743SMark F. Adams 1685676e1743SMark F. Adams 1686676e1743SMark F. Adams Options Database Key: 16878263b398SMark F. Adams . -pc_gamg_repartition 1688676e1743SMark F. Adams 1689676e1743SMark F. Adams Level: intermediate 1690676e1743SMark F. Adams 1691676e1743SMark F. Adams Concepts: Unstructured multrigrid preconditioner 1692676e1743SMark F. Adams 1693676e1743SMark F. Adams .seealso: () 1694676e1743SMark F. Adams @*/ 16958263b398SMark F. Adams PetscErrorCode PCGAMGSetRepartitioning(PC pc, PetscBool n) 1696676e1743SMark F. Adams { 1697676e1743SMark F. Adams PetscErrorCode ierr; 1698676e1743SMark F. Adams 1699676e1743SMark F. Adams PetscFunctionBegin; 1700676e1743SMark F. Adams PetscValidHeaderSpecific(pc,PC_CLASSID,1); 17018263b398SMark F. Adams ierr = PetscTryMethod(pc,"PCGAMGSetRepartitioning_C",(PC,PetscBool),(pc,n));CHKERRQ(ierr); 1702676e1743SMark F. Adams PetscFunctionReturn(0); 1703676e1743SMark F. Adams } 1704676e1743SMark F. Adams 1705676e1743SMark F. Adams EXTERN_C_BEGIN 1706676e1743SMark F. Adams #undef __FUNCT__ 17078263b398SMark F. Adams #define __FUNCT__ "PCGAMGSetRepartitioning_GAMG" 17088263b398SMark F. Adams PetscErrorCode PCGAMGSetRepartitioning_GAMG(PC pc, PetscBool n) 1709676e1743SMark F. Adams { 1710c20e4228SMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 1711c20e4228SMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 1712676e1743SMark F. Adams 1713676e1743SMark F. Adams PetscFunctionBegin; 17149d5b6da9SMark F. Adams pc_gamg->repart = n; 1715676e1743SMark F. Adams PetscFunctionReturn(0); 1716676e1743SMark F. Adams } 1717676e1743SMark F. Adams EXTERN_C_END 1718676e1743SMark F. Adams 1719676e1743SMark F. Adams #undef __FUNCT__ 17204ef23d27SMark F. Adams #define __FUNCT__ "PCGAMGSetNlevels" 17214ef23d27SMark F. Adams /*@ 17224ef23d27SMark F. Adams PCGAMGSetNlevels - 17234ef23d27SMark F. Adams 17244ef23d27SMark F. Adams Not collective on PC 17254ef23d27SMark F. Adams 17264ef23d27SMark F. Adams Input Parameters: 17274ef23d27SMark F. Adams . pc - the preconditioner context 17284ef23d27SMark F. Adams 17294ef23d27SMark F. Adams 17304ef23d27SMark F. Adams Options Database Key: 17314ef23d27SMark F. Adams . -pc_mg_levels 17324ef23d27SMark F. Adams 17334ef23d27SMark F. Adams Level: intermediate 17344ef23d27SMark F. Adams 17354ef23d27SMark F. Adams Concepts: Unstructured multrigrid preconditioner 17364ef23d27SMark F. Adams 17374ef23d27SMark F. Adams .seealso: () 17384ef23d27SMark F. Adams @*/ 17394ef23d27SMark F. Adams PetscErrorCode PCGAMGSetNlevels(PC pc, PetscInt n) 17404ef23d27SMark F. Adams { 17414ef23d27SMark F. Adams PetscErrorCode ierr; 17424ef23d27SMark F. Adams 17434ef23d27SMark F. Adams PetscFunctionBegin; 17444ef23d27SMark F. Adams PetscValidHeaderSpecific(pc,PC_CLASSID,1); 17454ef23d27SMark F. Adams ierr = PetscTryMethod(pc,"PCGAMGSetNlevels_C",(PC,PetscInt),(pc,n));CHKERRQ(ierr); 17464ef23d27SMark F. Adams PetscFunctionReturn(0); 17474ef23d27SMark F. Adams } 17484ef23d27SMark F. Adams 17494ef23d27SMark F. Adams EXTERN_C_BEGIN 17504ef23d27SMark F. Adams #undef __FUNCT__ 17514ef23d27SMark F. Adams #define __FUNCT__ "PCGAMGSetNlevels_GAMG" 17524ef23d27SMark F. Adams PetscErrorCode PCGAMGSetNlevels_GAMG(PC pc, PetscInt n) 17534ef23d27SMark F. Adams { 17544ef23d27SMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 17554ef23d27SMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 17564ef23d27SMark F. Adams 17574ef23d27SMark F. Adams PetscFunctionBegin; 17589d5b6da9SMark F. Adams pc_gamg->Nlevels = n; 17594ef23d27SMark F. Adams PetscFunctionReturn(0); 17604ef23d27SMark F. Adams } 17614ef23d27SMark F. Adams EXTERN_C_END 17624ef23d27SMark F. Adams 17634ef23d27SMark F. Adams #undef __FUNCT__ 17643542efc5SMark F. Adams #define __FUNCT__ "PCGAMGSetThreshold" 17653542efc5SMark F. Adams /*@ 17663542efc5SMark F. Adams PCGAMGSetThreshold - Relative threshold to use for dropping edges in aggregation graph 17673542efc5SMark F. Adams 17683542efc5SMark F. Adams Not collective on PC 17693542efc5SMark F. Adams 17703542efc5SMark F. Adams Input Parameters: 17713542efc5SMark F. Adams . pc - the preconditioner context 17723542efc5SMark F. Adams 17733542efc5SMark F. Adams 17743542efc5SMark F. Adams Options Database Key: 17753542efc5SMark F. Adams . -pc_gamg_threshold 17763542efc5SMark F. Adams 17773542efc5SMark F. Adams Level: intermediate 17783542efc5SMark F. Adams 17793542efc5SMark F. Adams Concepts: Unstructured multrigrid preconditioner 17803542efc5SMark F. Adams 17813542efc5SMark F. Adams .seealso: () 17823542efc5SMark F. Adams @*/ 17833542efc5SMark F. Adams PetscErrorCode PCGAMGSetThreshold(PC pc, PetscReal n) 17843542efc5SMark F. Adams { 17853542efc5SMark F. Adams PetscErrorCode ierr; 17863542efc5SMark F. Adams 17873542efc5SMark F. Adams PetscFunctionBegin; 17883542efc5SMark F. Adams PetscValidHeaderSpecific(pc,PC_CLASSID,1); 17893542efc5SMark F. Adams ierr = PetscTryMethod(pc,"PCGAMGSetThreshold_C",(PC,PetscReal),(pc,n));CHKERRQ(ierr); 17903542efc5SMark F. Adams PetscFunctionReturn(0); 17913542efc5SMark F. Adams } 17923542efc5SMark F. Adams 17933542efc5SMark F. Adams EXTERN_C_BEGIN 17943542efc5SMark F. Adams #undef __FUNCT__ 17953542efc5SMark F. Adams #define __FUNCT__ "PCGAMGSetThreshold_GAMG" 17963542efc5SMark F. Adams PetscErrorCode PCGAMGSetThreshold_GAMG(PC pc, PetscReal n) 17973542efc5SMark F. Adams { 1798c20e4228SMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 1799c20e4228SMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 18003542efc5SMark F. Adams 18013542efc5SMark F. Adams PetscFunctionBegin; 18029d5b6da9SMark F. Adams pc_gamg->threshold = n; 18033542efc5SMark F. Adams PetscFunctionReturn(0); 18043542efc5SMark F. Adams } 18053542efc5SMark F. Adams EXTERN_C_END 18063542efc5SMark F. Adams 18073542efc5SMark F. Adams #undef __FUNCT__ 18089d5b6da9SMark F. Adams #define __FUNCT__ "PCGAMGSetType" 1809676e1743SMark F. Adams /*@ 18109d5b6da9SMark F. Adams PCGAMGSetType - Set solution method - calls sub create method 1811676e1743SMark F. Adams 1812676e1743SMark F. Adams Collective on PC 1813676e1743SMark F. Adams 1814676e1743SMark F. Adams Input Parameters: 1815676e1743SMark F. Adams . pc - the preconditioner context 1816676e1743SMark F. Adams 1817676e1743SMark F. Adams 1818676e1743SMark F. Adams Options Database Key: 18193542efc5SMark F. Adams . -pc_gamg_type 1820676e1743SMark F. Adams 1821676e1743SMark F. Adams Level: intermediate 1822676e1743SMark F. Adams 1823676e1743SMark F. Adams Concepts: Unstructured multrigrid preconditioner 1824676e1743SMark F. Adams 1825676e1743SMark F. Adams .seealso: () 1826676e1743SMark F. Adams @*/ 18270202ef74SSatish Balay PetscErrorCode PCGAMGSetType( PC pc, const PCGAMGType type ) 1828676e1743SMark F. Adams { 1829676e1743SMark F. Adams PetscErrorCode ierr; 1830676e1743SMark F. Adams 1831676e1743SMark F. Adams PetscFunctionBegin; 1832676e1743SMark F. Adams PetscValidHeaderSpecific(pc,PC_CLASSID,1); 18330202ef74SSatish Balay ierr = PetscTryMethod(pc,"PCGAMGSetType_C",(PC,const PCGAMGType),(pc,type)); 1834676e1743SMark F. Adams CHKERRQ(ierr); 1835676e1743SMark F. Adams PetscFunctionReturn(0); 1836676e1743SMark F. Adams } 1837676e1743SMark F. Adams 1838676e1743SMark F. Adams EXTERN_C_BEGIN 1839676e1743SMark F. Adams #undef __FUNCT__ 18409d5b6da9SMark F. Adams #define __FUNCT__ "PCGAMGSetType_GAMG" 18410202ef74SSatish Balay PetscErrorCode PCGAMGSetType_GAMG( PC pc, const PCGAMGType type ) 1842676e1743SMark F. Adams { 18439d5b6da9SMark F. Adams PetscErrorCode ierr,(*r)(PC); 1844676e1743SMark F. Adams 1845676e1743SMark F. Adams PetscFunctionBegin; 18469d5b6da9SMark F. Adams ierr = PetscFListFind(GAMGList,((PetscObject)pc)->comm,type,PETSC_FALSE,(PetscVoidStarFunction)&r); 18479d5b6da9SMark F. Adams CHKERRQ(ierr); 18489d5b6da9SMark F. Adams 18499d5b6da9SMark F. Adams if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown GAMG type %s given",type); 18509d5b6da9SMark F. Adams 18519d5b6da9SMark F. Adams /* call sub create method */ 18529d5b6da9SMark F. Adams ierr = (*r)(pc); CHKERRQ(ierr); 18539d5b6da9SMark F. Adams 1854676e1743SMark F. Adams PetscFunctionReturn(0); 1855676e1743SMark F. Adams } 1856676e1743SMark F. Adams EXTERN_C_END 1857676e1743SMark F. Adams 18585b89ad90SMark F. Adams #undef __FUNCT__ 18595b89ad90SMark F. Adams #define __FUNCT__ "PCSetFromOptions_GAMG" 18605b89ad90SMark F. Adams PetscErrorCode PCSetFromOptions_GAMG( PC pc ) 18615b89ad90SMark F. Adams { 1862676e1743SMark F. Adams PetscErrorCode ierr; 1863676e1743SMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 1864676e1743SMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 1865676e1743SMark F. Adams PetscBool flag; 18665b89ad90SMark F. Adams 18675b89ad90SMark F. Adams PetscFunctionBegin; 1868676e1743SMark F. Adams ierr = PetscOptionsHead("GAMG options"); CHKERRQ(ierr); 1869676e1743SMark F. Adams { 187075b74bdaSMark F. Adams /* -pc_gamg_verbose */ 18719d5b6da9SMark F. Adams ierr = PetscOptionsInt("-pc_gamg_verbose","Verbose (debugging) output for PCGAMG", 18729d5b6da9SMark F. Adams "none", pc_gamg->verbose, 18739d5b6da9SMark F. Adams &pc_gamg->verbose, PETSC_NULL ); 18749d5b6da9SMark F. Adams CHKERRQ(ierr); 187575b74bdaSMark F. Adams 18768263b398SMark F. Adams /* -pc_gamg_repartition */ 18778263b398SMark F. Adams ierr = PetscOptionsBool("-pc_gamg_repartition", 18788263b398SMark F. Adams "Repartion coarse grids (false)", 18798263b398SMark F. Adams "PCGAMGRepartitioning", 18809d5b6da9SMark F. Adams pc_gamg->repart, 18819d5b6da9SMark F. Adams &pc_gamg->repart, 1882676e1743SMark F. Adams &flag); 1883676e1743SMark F. Adams CHKERRQ(ierr); 1884676e1743SMark F. Adams 1885c20e4228SMark F. Adams /* -pc_gamg_process_eq_limit */ 1886676e1743SMark F. Adams ierr = PetscOptionsInt("-pc_gamg_process_eq_limit", 1887676e1743SMark F. Adams "Limit (goal) on number of equations per process on coarse grids", 1888676e1743SMark F. Adams "PCGAMGSetProcEqLim", 18899d5b6da9SMark F. Adams pc_gamg->min_eq_proc, 18909d5b6da9SMark F. Adams &pc_gamg->min_eq_proc, 1891676e1743SMark F. Adams &flag ); 1892676e1743SMark F. Adams CHKERRQ(ierr); 18933542efc5SMark F. Adams 1894389730f3SMark F. Adams /* -pc_gamg_coarse_eq_limit */ 1895389730f3SMark F. Adams ierr = PetscOptionsInt("-pc_gamg_coarse_eq_limit", 1896389730f3SMark F. Adams "Limit on number of equations for the coarse grid", 1897389730f3SMark F. Adams "PCGAMGSetCoarseEqLim", 18989d5b6da9SMark F. Adams pc_gamg->coarse_eq_limit, 18999d5b6da9SMark F. Adams &pc_gamg->coarse_eq_limit, 1900389730f3SMark F. Adams &flag ); 1901389730f3SMark F. Adams CHKERRQ(ierr); 1902389730f3SMark F. Adams 1903c20e4228SMark F. Adams /* -pc_gamg_threshold */ 19043542efc5SMark F. Adams ierr = PetscOptionsReal("-pc_gamg_threshold", 19053542efc5SMark F. Adams "Relative threshold to use for dropping edges in aggregation graph", 19063542efc5SMark F. Adams "PCGAMGSetThreshold", 19079d5b6da9SMark F. Adams pc_gamg->threshold, 19089d5b6da9SMark F. Adams &pc_gamg->threshold, 19093542efc5SMark F. Adams &flag ); 19103542efc5SMark F. Adams CHKERRQ(ierr); 19114ef23d27SMark F. Adams 19124ef23d27SMark F. Adams ierr = PetscOptionsInt("-pc_mg_levels", 19134ef23d27SMark F. Adams "Set number of MG levels", 19144ef23d27SMark F. Adams "PCGAMGSetNlevels", 19159d5b6da9SMark F. Adams pc_gamg->Nlevels, 19169d5b6da9SMark F. Adams &pc_gamg->Nlevels, 19174ef23d27SMark F. Adams &flag ); 1918676e1743SMark F. Adams } 1919676e1743SMark F. Adams ierr = PetscOptionsTail();CHKERRQ(ierr); 1920676e1743SMark F. Adams 19215b89ad90SMark F. Adams PetscFunctionReturn(0); 19225b89ad90SMark F. Adams } 19235b89ad90SMark F. Adams 19245b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */ 19255b89ad90SMark F. Adams /*MC 19269d5b6da9SMark F. Adams PCCreate_GAMG - Geometric algebraic multigrid (AMG) preconditioning framework. 19279d5b6da9SMark F. Adams - This is the entry point to GAMG, registered in pcregis.c 19285b89ad90SMark F. Adams 1929280d9858SJed Brown Options Database Keys: 19305b89ad90SMark F. Adams Multigrid options(inherited) 1931280d9858SJed Brown + -pc_mg_cycles <1>: 1 for V cycle, 2 for W-cycle (PCMGSetCycleType) 1932280d9858SJed Brown . -pc_mg_smoothup <1>: Number of post-smoothing steps (PCMGSetNumberSmoothUp) 1933280d9858SJed Brown . -pc_mg_smoothdown <1>: Number of pre-smoothing steps (PCMGSetNumberSmoothDown) 1934280d9858SJed Brown - -pc_mg_type <multiplicative>: (one of) additive multiplicative full cascade kascade 19355b89ad90SMark F. Adams 19365b89ad90SMark F. Adams Level: intermediate 1937280d9858SJed Brown 19385b89ad90SMark F. Adams Concepts: multigrid 19395b89ad90SMark F. Adams 19405b89ad90SMark F. Adams .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, PCMGType, 1941280d9858SJed Brown PCMGSetLevels(), PCMGGetLevels(), PCMGSetType(), PCMGSetCycleType(), PCMGSetNumberSmoothDown(), 19425b89ad90SMark F. Adams PCMGSetNumberSmoothUp(), PCMGGetCoarseSolve(), PCMGSetResidual(), PCMGSetInterpolation(), 19435b89ad90SMark F. Adams PCMGSetRestriction(), PCMGGetSmoother(), PCMGGetSmootherUp(), PCMGGetSmootherDown(), 19445b89ad90SMark F. Adams PCMGSetCyclesOnLevel(), PCMGSetRhs(), PCMGSetX(), PCMGSetR() 19455b89ad90SMark F. Adams M*/ 19465b89ad90SMark F. Adams EXTERN_C_BEGIN 19475b89ad90SMark F. Adams #undef __FUNCT__ 19485b89ad90SMark F. Adams #define __FUNCT__ "PCCreate_GAMG" 19495b89ad90SMark F. Adams PetscErrorCode PCCreate_GAMG( PC pc ) 19505b89ad90SMark F. Adams { 19515b89ad90SMark F. Adams PetscErrorCode ierr; 19525b89ad90SMark F. Adams PC_GAMG *pc_gamg; 19535b89ad90SMark F. Adams PC_MG *mg; 19545ef31b24SMark F. Adams PetscClassId cookie; 19559d5b6da9SMark F. Adams 19565ee9c036SSatish Balay #if defined PETSC_USE_LOG 19579d5b6da9SMark F. Adams static long count = 0; 19585ee9c036SSatish Balay #endif 19595b89ad90SMark F. Adams 19605b89ad90SMark F. Adams PetscFunctionBegin; 19615b89ad90SMark F. Adams /* PCGAMG is an inherited class of PCMG. Initialize pc as PCMG */ 19625b89ad90SMark F. Adams ierr = PCSetType( pc, PCMG ); CHKERRQ(ierr); /* calls PCCreate_MG() and MGCreate_Private() */ 19635b89ad90SMark F. Adams ierr = PetscObjectChangeTypeName( (PetscObject)pc, PCGAMG ); CHKERRQ(ierr); 19645b89ad90SMark F. Adams 19655b89ad90SMark F. Adams /* create a supporting struct and attach it to pc */ 19665b89ad90SMark F. Adams ierr = PetscNewLog( pc, PC_GAMG, &pc_gamg ); CHKERRQ(ierr); 19675b89ad90SMark F. Adams mg = (PC_MG*)pc->data; 19685b89ad90SMark F. Adams mg->innerctx = pc_gamg; 19695b89ad90SMark F. Adams 19709d5b6da9SMark F. Adams pc_gamg->setup_count = 0; 19719d5b6da9SMark F. Adams /* these should be in subctx but repartitioning needs simple arrays */ 19729d5b6da9SMark F. Adams pc_gamg->data_sz = 0; 19739d5b6da9SMark F. Adams pc_gamg->data = 0; 19745b89ad90SMark F. Adams 19759d5b6da9SMark F. Adams /* register AMG type */ 19769d5b6da9SMark F. Adams if( !GAMGList ){ 19779d5b6da9SMark F. Adams ierr = PetscFListAdd(&GAMGList,GAMGGEO,"PCCreateGAMG_GEO",(void(*)(void))PCCreateGAMG_GEO);CHKERRQ(ierr); 19789d5b6da9SMark F. Adams ierr = PetscFListAdd(&GAMGList,GAMGAGG,"PCCreateGAMG_AGG",(void(*)(void))PCCreateGAMG_AGG);CHKERRQ(ierr); 19799d5b6da9SMark F. Adams } 19809d5b6da9SMark F. Adams 19819d5b6da9SMark F. Adams /* overwrite the pointers of PCMG by the functions of base class PCGAMG */ 19825b89ad90SMark F. Adams pc->ops->setfromoptions = PCSetFromOptions_GAMG; 19835b89ad90SMark F. Adams pc->ops->setup = PCSetUp_GAMG; 19845b89ad90SMark F. Adams pc->ops->reset = PCReset_GAMG; 19855b89ad90SMark F. Adams pc->ops->destroy = PCDestroy_GAMG; 19865b89ad90SMark F. Adams 19875b89ad90SMark F. Adams ierr = PetscObjectComposeFunctionDynamic( (PetscObject)pc, 1988676e1743SMark F. Adams "PCGAMGSetProcEqLim_C", 1989676e1743SMark F. Adams "PCGAMGSetProcEqLim_GAMG", 1990676e1743SMark F. Adams PCGAMGSetProcEqLim_GAMG); 1991676e1743SMark F. Adams CHKERRQ(ierr); 1992676e1743SMark F. Adams 1993676e1743SMark F. Adams ierr = PetscObjectComposeFunctionDynamic( (PetscObject)pc, 1994389730f3SMark F. Adams "PCGAMGSetCoarseEqLim_C", 1995389730f3SMark F. Adams "PCGAMGSetCoarseEqLim_GAMG", 1996389730f3SMark F. Adams PCGAMGSetCoarseEqLim_GAMG); 1997389730f3SMark F. Adams CHKERRQ(ierr); 1998389730f3SMark F. Adams 1999389730f3SMark F. Adams ierr = PetscObjectComposeFunctionDynamic( (PetscObject)pc, 20008263b398SMark F. Adams "PCGAMGSetRepartitioning_C", 20018263b398SMark F. Adams "PCGAMGSetRepartitioning_GAMG", 20028263b398SMark F. Adams PCGAMGSetRepartitioning_GAMG); 2003676e1743SMark F. Adams CHKERRQ(ierr); 2004676e1743SMark F. Adams 2005676e1743SMark F. Adams ierr = PetscObjectComposeFunctionDynamic( (PetscObject)pc, 20063542efc5SMark F. Adams "PCGAMGSetThreshold_C", 20073542efc5SMark F. Adams "PCGAMGSetThreshold_GAMG", 20083542efc5SMark F. Adams PCGAMGSetThreshold_GAMG); 20093542efc5SMark F. Adams CHKERRQ(ierr); 20103542efc5SMark F. Adams 20113542efc5SMark F. Adams ierr = PetscObjectComposeFunctionDynamic( (PetscObject)pc, 20129d5b6da9SMark F. Adams "PCGAMGSetType_C", 20139d5b6da9SMark F. Adams "PCGAMGSetType_GAMG", 20149d5b6da9SMark F. Adams PCGAMGSetType_GAMG); 2015676e1743SMark F. Adams CHKERRQ(ierr); 2016c97e1df0SMark F. Adams 20179d5b6da9SMark F. Adams pc_gamg->repart = PETSC_FALSE; 20189d5b6da9SMark F. Adams pc_gamg->min_eq_proc = 100; 20199d5b6da9SMark F. Adams pc_gamg->coarse_eq_limit = 1000; 20209d5b6da9SMark F. Adams pc_gamg->threshold = 0.05; 20219d5b6da9SMark F. Adams pc_gamg->Nlevels = GAMG_MAXLEVELS; 20229d5b6da9SMark F. Adams pc_gamg->verbose = 0; 20239d5b6da9SMark F. Adams pc_gamg->emax_id = -1; 20249d5b6da9SMark F. Adams pc_gamg->col_bs_id = -1; 20259d5b6da9SMark F. Adams 20269d5b6da9SMark F. Adams /* instantiate derived type */ 20279d5b6da9SMark F. Adams ierr = PetscOptionsHead("GAMG options"); CHKERRQ(ierr); 20289d5b6da9SMark F. Adams { 20299d5b6da9SMark F. Adams char tname[256] = GAMGAGG; 20309d5b6da9SMark F. Adams ierr = PetscOptionsList("-pc_gamg_type","Type of GAMG method","PCGAMGSetType", 20319d5b6da9SMark F. Adams GAMGList, tname, tname, sizeof(tname), PETSC_NULL ); 20329d5b6da9SMark F. Adams CHKERRQ(ierr); 20339d5b6da9SMark F. Adams ierr = PCGAMGSetType( pc, tname ); CHKERRQ(ierr); 20349d5b6da9SMark F. Adams } 20359d5b6da9SMark F. Adams ierr = PetscOptionsTail();CHKERRQ(ierr); 20369d5b6da9SMark F. Adams 2037b4fbaa2aSMark F. Adams #if defined PETSC_USE_LOG 2038785cba28SMark F. Adams if( count++ == 0 ) { 20395ef31b24SMark F. Adams PetscClassIdRegister("GAMG Setup",&cookie); 2040b4fbaa2aSMark F. Adams PetscLogEventRegister("GAMG: createProl", cookie, &gamg_setup_events[SET1]); 20412a44bfbaSMark F. Adams PetscLogEventRegister(" Graph", cookie, &gamg_setup_events[GRAPH]); 20422a44bfbaSMark F. Adams PetscLogEventRegister(" G.Mat", cookie, &gamg_setup_events[GRAPH_MAT]); 20432a44bfbaSMark F. Adams PetscLogEventRegister(" G.Filter", cookie, &gamg_setup_events[GRAPH_FILTER]); 20442a44bfbaSMark F. Adams PetscLogEventRegister(" G.Square", cookie, &gamg_setup_events[GRAPH_SQR]); 2045b4fbaa2aSMark F. Adams PetscLogEventRegister(" MIS/Agg", cookie, &gamg_setup_events[SET4]); 2046b4fbaa2aSMark F. Adams PetscLogEventRegister(" geo: growSupp", cookie, &gamg_setup_events[SET5]); 2047b4fbaa2aSMark F. Adams PetscLogEventRegister(" geo: triangle", cookie, &gamg_setup_events[SET6]); 2048b4fbaa2aSMark F. Adams PetscLogEventRegister(" search&set", cookie, &gamg_setup_events[FIND_V]); 2049b4fbaa2aSMark F. Adams PetscLogEventRegister(" SA: init", cookie, &gamg_setup_events[SET7]); 2050b4fbaa2aSMark F. Adams /* PetscLogEventRegister(" SA: frmProl0", cookie, &gamg_setup_events[SET8]); */ 2051b4fbaa2aSMark F. Adams PetscLogEventRegister(" SA: smooth", cookie, &gamg_setup_events[SET9]); 2052b4fbaa2aSMark F. Adams PetscLogEventRegister("GAMG: partLevel", cookie, &gamg_setup_events[SET2]); 2053ed3f9983SMark F. Adams PetscLogEventRegister(" repartition", cookie, &gamg_setup_events[SET12]); 2054ed3f9983SMark F. Adams PetscLogEventRegister(" Invert-Sort", cookie, &gamg_setup_events[SET13]); 2055ed3f9983SMark F. Adams PetscLogEventRegister(" Move A", cookie, &gamg_setup_events[SET14]); 2056ed3f9983SMark F. Adams PetscLogEventRegister(" Move P", cookie, &gamg_setup_events[SET15]); 2057f852f58cSMark F. Adams 2058b4fbaa2aSMark F. Adams /* PetscLogEventRegister(" PL move data", cookie, &gamg_setup_events[SET13]); */ 2059b4fbaa2aSMark F. Adams /* PetscLogEventRegister("GAMG: fix", cookie, &gamg_setup_events[SET10]); */ 2060b4fbaa2aSMark F. Adams /* PetscLogEventRegister("GAMG: set levels", cookie, &gamg_setup_events[SET11]); */ 20615ef31b24SMark F. Adams 2062b4fbaa2aSMark F. Adams /* create timer stages */ 2063b4fbaa2aSMark F. Adams #if defined GAMG_STAGES 2064b4fbaa2aSMark F. Adams { 2065b4fbaa2aSMark F. Adams char str[32]; 2066b4fbaa2aSMark F. Adams sprintf(str,"MG Level %d (finest)",0); 2067b4fbaa2aSMark F. Adams PetscLogStageRegister(str, &gamg_stages[0]); 2068b4fbaa2aSMark F. Adams PetscInt lidx; 2069b4fbaa2aSMark F. Adams for (lidx=1;lidx<9;lidx++){ 2070b4fbaa2aSMark F. Adams sprintf(str,"MG Level %d",lidx); 2071b4fbaa2aSMark F. Adams PetscLogStageRegister(str, &gamg_stages[lidx]); 2072b4fbaa2aSMark F. Adams } 2073b4fbaa2aSMark F. Adams } 2074b4fbaa2aSMark F. Adams #endif 2075b4fbaa2aSMark F. Adams } 2076b4fbaa2aSMark F. Adams #endif 20775b89ad90SMark F. Adams PetscFunctionReturn(0); 20785b89ad90SMark F. Adams } 20795b89ad90SMark F. Adams EXTERN_C_END 2080