15b89ad90SMark F. Adams /* 25b89ad90SMark F. Adams GAMG geometric-algebric multiogrid PC - Mark Adams 2011 35b89ad90SMark F. Adams */ 45ef31b24SMark F. Adams #include <../src/ksp/pc/impls/gamg/gamg.h> 5f96513f1SMatthew G Knepley 6f96513f1SMatthew G Knepley PetscLogEvent gamg_setup_stages[NUM_SET]; 7f96513f1SMatthew G Knepley 85b89ad90SMark F. Adams /* Private context for the GAMG preconditioner */ 95b89ad90SMark F. Adams typedef struct gamg_TAG { 105b89ad90SMark F. Adams PetscInt m_dim; 115b89ad90SMark F. Adams PetscInt m_Nlevels; 125b89ad90SMark F. Adams PetscInt m_data_sz; 135b89ad90SMark F. Adams PetscReal *m_data; /* blocked vector of vertex data on fine grid (coordinates) */ 145b89ad90SMark F. Adams } PC_GAMG; 155b89ad90SMark F. Adams 16fc4362bfSMark F. Adams #define TOP_GRID_LIM 100 175ef31b24SMark F. Adams 185b89ad90SMark F. Adams /* -----------------------------------------------------------------------------*/ 195b89ad90SMark F. Adams #undef __FUNCT__ 205b89ad90SMark F. Adams #define __FUNCT__ "PCReset_GAMG" 215b89ad90SMark F. Adams PetscErrorCode PCReset_GAMG(PC pc) 225b89ad90SMark F. Adams { 235b89ad90SMark F. Adams PetscErrorCode ierr; 245b89ad90SMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 255b89ad90SMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 265b89ad90SMark F. Adams 275b89ad90SMark F. Adams PetscFunctionBegin; 285b89ad90SMark F. Adams ierr = PetscFree(pc_gamg->m_data);CHKERRQ(ierr); 29eb07cef2SMark F. Adams pc_gamg->m_data = 0; pc_gamg->m_data_sz = 0; 305b89ad90SMark F. Adams PetscFunctionReturn(0); 315b89ad90SMark F. Adams } 325b89ad90SMark F. Adams 335b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */ 345b89ad90SMark F. Adams /* 355b89ad90SMark F. Adams PCSetCoordinates_GAMG 365b89ad90SMark F. Adams 375b89ad90SMark F. Adams Input Parameter: 385b89ad90SMark F. Adams . pc - the preconditioner context 395b89ad90SMark F. Adams */ 40a92563c5SMark F. Adams EXTERN_C_BEGIN 415b89ad90SMark F. Adams #undef __FUNCT__ 425b89ad90SMark F. Adams #define __FUNCT__ "PCSetCoordinates_GAMG" 43eb07cef2SMark F. Adams PetscErrorCode PCSetCoordinates_GAMG( PC a_pc, PetscInt a_ndm, PetscReal *a_coords ) 445b89ad90SMark F. Adams { 45eb07cef2SMark F. Adams PC_MG *mg = (PC_MG*)a_pc->data; 465b89ad90SMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 476c237d78SBarry Smith PetscErrorCode ierr; 48eb07cef2SMark F. Adams PetscInt arrsz, bs, my0, tt, ii, nloc, sz, kk; 49eb07cef2SMark F. Adams Mat mat = a_pc->pmat; 50eb07cef2SMark F. Adams PetscBool useSA = PETSC_FALSE, flag; 51eb07cef2SMark F. Adams char str[16]; 525b89ad90SMark F. Adams 535b89ad90SMark F. Adams PetscFunctionBegin; 54eb07cef2SMark F. Adams ierr = PetscOptionsGetString(PETSC_NULL,"-pc_gamg_type",str,16,&flag); CHKERRQ( ierr ); 55eb07cef2SMark F. Adams useSA = (PetscBool)(flag && strcmp(str,"sa") == 0); 565b89ad90SMark F. Adams ierr = MatGetBlockSize( mat, &bs ); CHKERRQ( ierr ); 575b89ad90SMark F. Adams ierr = MatGetOwnershipRange( mat, &my0, &tt ); CHKERRQ(ierr); 58eb07cef2SMark F. Adams nloc = (tt-my0)/bs; sz = (useSA ? (a_coords==0 ? a_ndm*a_ndm: (a_ndm==2 ? 3*a_ndm : 6*a_ndm)) : a_ndm ); 59eb07cef2SMark F. Adams arrsz = nloc*sz; 605b89ad90SMark F. Adams 615b89ad90SMark F. Adams // put coordinates 626c237d78SBarry Smith if (!pc_gamg->m_data || (pc_gamg->m_data_sz != arrsz)) { 635b89ad90SMark F. Adams ierr = PetscFree( pc_gamg->m_data ); CHKERRQ(ierr); 64eb07cef2SMark F. Adams ierr = PetscMalloc((arrsz+1)*sizeof(double), &pc_gamg->m_data ); CHKERRQ(ierr); 655b89ad90SMark F. Adams } 66eb07cef2SMark F. Adams for(tt=0;tt<arrsz;tt++)pc_gamg->m_data[tt] = 0.; 67eb07cef2SMark F. Adams pc_gamg->m_data[arrsz] = -99.; 685b89ad90SMark F. Adams /* copy data in */ 69eb07cef2SMark F. Adams if( useSA ) { 70eb07cef2SMark F. Adams for(tt=0,kk=0;tt<nloc;tt++){ 71eb07cef2SMark F. Adams PetscReal *data = &pc_gamg->m_data[tt*sz]; 72eb07cef2SMark F. Adams for(ii=0;ii<a_ndm;ii++) data[a_ndm*ii + ii] = 1.0; /* translational mode */ 73eb07cef2SMark F. Adams if( a_coords != 0 ) { 74eb07cef2SMark F. Adams if( a_ndm == 2 ){ 75eb07cef2SMark F. Adams data[4] = a_coords[2*tt+1]; data[5] = -a_coords[2*tt]; 765b89ad90SMark F. Adams } 77eb07cef2SMark F. Adams else { 78eb07cef2SMark F. Adams data[10] = -a_coords[2*tt+2]; data[12] = a_coords[2*tt+2]; data[15] = a_coords[2*tt+1]; 79eb07cef2SMark F. Adams data[11] = -a_coords[2*tt+1]; data[14] = -a_coords[2*tt]; data[16] = a_coords[2*tt]; 80eb07cef2SMark F. Adams } 81eb07cef2SMark F. Adams } 82eb07cef2SMark F. Adams } 83eb07cef2SMark F. Adams } 84eb07cef2SMark F. Adams else { 85eb07cef2SMark F. Adams for(tt=0;tt<arrsz;tt++){ 86eb07cef2SMark F. Adams pc_gamg->m_data[tt] = a_coords[tt]; 87eb07cef2SMark F. Adams } 88eb07cef2SMark F. Adams } 89eb07cef2SMark F. Adams assert(pc_gamg->m_data[arrsz] == -99.); 905b89ad90SMark F. Adams pc_gamg->m_data_sz = arrsz; 91eb07cef2SMark F. Adams pc_gamg->m_dim = a_ndm; 925b89ad90SMark F. Adams 935b89ad90SMark F. Adams PetscFunctionReturn(0); 945b89ad90SMark F. Adams } 95a92563c5SMark F. Adams EXTERN_C_END 965b89ad90SMark F. Adams 975b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */ 985b89ad90SMark F. Adams /* 9911e60469SMark F. Adams partitionLevel 1005b89ad90SMark F. Adams 1015b89ad90SMark F. Adams Input Parameter: 1023530afc2SMark F. Adams . a_Amat_fine - matrix on this fine (k) level 103eb07cef2SMark F. Adams . a_data_sz - size of data to move 1043530afc2SMark F. Adams In/Output Parameter: 1053530afc2SMark F. Adams . a_P_inout - prolongation operator to the next level (k-1) 106eb07cef2SMark F. Adams . a_coarse_data - data that need to be moved 1073530afc2SMark F. Adams . a_active_proc - number of active procs 10811e60469SMark F. Adams Output Parameter: 1093530afc2SMark F. Adams . a_Amat_crs - coarse matrix that is created (k-1) 1105b89ad90SMark F. Adams */ 1115cb416c2SMark F. Adams 1125b89ad90SMark F. Adams #undef __FUNCT__ 11311e60469SMark F. Adams #define __FUNCT__ "partitionLevel" 1143530afc2SMark F. Adams PetscErrorCode partitionLevel( Mat a_Amat_fine, 115eb07cef2SMark F. Adams PetscInt a_data_sz, 1163530afc2SMark F. Adams Mat *a_P_inout, 117eb07cef2SMark F. Adams PetscReal **a_coarse_data, 1183530afc2SMark F. Adams PetscMPIInt *a_active_proc, 1193530afc2SMark F. Adams Mat *a_Amat_crs 12011e60469SMark F. Adams ) 1215b89ad90SMark F. Adams { 1225b89ad90SMark F. Adams PetscErrorCode ierr; 1233530afc2SMark F. Adams Mat Amat, Pnew, Pold = *a_P_inout; 12411e60469SMark F. Adams IS new_indices,isnum; 1253530afc2SMark F. Adams MPI_Comm wcomm = ((PetscObject)a_Amat_fine)->comm; 1265ef31b24SMark F. Adams PetscMPIInt nactive_procs,mype,npe; 127eb07cef2SMark F. Adams PetscInt Istart,Iend,Istart0,Iend0,ncrs0,ncrs_new,bs,bs2; 1285b89ad90SMark F. Adams 1295b89ad90SMark F. Adams PetscFunctionBegin; 13011e60469SMark F. Adams ierr = MPI_Comm_rank(wcomm,&mype);CHKERRQ(ierr); 13111e60469SMark F. Adams ierr = MPI_Comm_size(wcomm,&npe);CHKERRQ(ierr); 132eb07cef2SMark F. Adams ierr = MatGetBlockSize( a_Amat_fine, &bs ); CHKERRQ(ierr); 13311e60469SMark F. Adams /* RAP */ 1343530afc2SMark F. Adams ierr = MatPtAP( a_Amat_fine, Pold, MAT_INITIAL_MATRIX, 2.0, &Amat ); CHKERRQ(ierr); 135eb07cef2SMark F. Adams ierr = MatSetBlockSize( Amat, bs ); CHKERRQ(ierr); 136eb07cef2SMark F. Adams ierr = MatGetOwnershipRange( Amat, &Istart0, &Iend0 ); CHKERRQ(ierr); 137eb07cef2SMark F. Adams ncrs0 = (Iend0-Istart0)/bs; assert( (Iend0-Istart0)%bs == 0 ); 138acadaa72SMark F. Adams 13911e60469SMark F. Adams /* Repartition Amat_{k} and move colums of P^{k}_{k-1} and coordinates accordingly */ 14011e60469SMark F. Adams { 1413530afc2SMark F. Adams PetscInt neq,N,counts[npe]; 14211e60469SMark F. Adams IS isnewproc; 1435ef31b24SMark F. Adams PetscMPIInt new_npe,targ_npe; 1443530afc2SMark F. Adams 1453530afc2SMark F. Adams ierr = MatGetSize( Amat, &neq, &N );CHKERRQ(ierr); 1463530afc2SMark F. Adams #define MIN_EQ_PROC 100 1475ef31b24SMark F. Adams nactive_procs = *a_active_proc; 1483530afc2SMark F. Adams targ_npe = neq/MIN_EQ_PROC; /* hardwire min. number of eq/proc */ 1495ef31b24SMark F. Adams if( targ_npe == 0 || neq < TOP_GRID_LIM ) new_npe = 1; /* chop coarsest grid */ 1505ef31b24SMark F. Adams else if (targ_npe >= nactive_procs ) new_npe = nactive_procs; /* no change */ 1513530afc2SMark F. Adams else { 1525ef31b24SMark F. Adams PetscMPIInt factstart,fact; 1533530afc2SMark F. Adams new_npe = -9999; 1545ef31b24SMark F. Adams factstart = nactive_procs; 1553530afc2SMark F. Adams for(fact=factstart;fact>0;fact--){ /* try to find a better number of procs */ 1565ef31b24SMark F. Adams if( nactive_procs%fact==0 && neq/(nactive_procs/fact) > MIN_EQ_PROC ) { 1575ef31b24SMark F. Adams new_npe = nactive_procs/fact; 1583530afc2SMark F. Adams } 1593530afc2SMark F. Adams } 1603530afc2SMark F. Adams assert(new_npe != -9999); 1613530afc2SMark F. Adams } 1623530afc2SMark F. Adams *a_active_proc = new_npe; /* output for next time */ 16311e60469SMark F. Adams { /* partition: get 'isnewproc' */ 16411e60469SMark F. Adams MatPartitioning mpart; 1655ef31b24SMark F. Adams Mat adj; 1665ef31b24SMark F. Adams const PetscInt *is_idx; 167eb07cef2SMark F. Adams PetscInt is_sz,kk,jj,ii,old_fact=(npe/nactive_procs),new_fact=(npe/new_npe),*isnewproc_idx; 168c9a0b8beSMark F. Adams /* create sub communicator */ 169c9a0b8beSMark F. Adams MPI_Comm cm,new_comm; 1705ef31b24SMark F. Adams int membershipKey = mype % old_fact; 171c9a0b8beSMark F. Adams ierr = MPI_Comm_split(wcomm, membershipKey, mype, &cm); CHKERRQ(ierr); 172c9a0b8beSMark F. Adams ierr = PetscCommDuplicate( cm, &new_comm, PETSC_NULL ); CHKERRQ(ierr); 173c9a0b8beSMark F. Adams ierr = MPI_Comm_free( &cm ); CHKERRQ(ierr); 174c9a0b8beSMark F. Adams 1755ef31b24SMark F. Adams /* MatPartitioningApply call MatConvert, which is collective */ 176eb07cef2SMark F. Adams if( bs==1) { 1775ef31b24SMark F. Adams ierr = MatConvert( Amat, MATMPIADJ, MAT_INITIAL_MATRIX, &adj ); CHKERRQ(ierr); 178eb07cef2SMark F. Adams } 179eb07cef2SMark F. Adams else { 180eb07cef2SMark F. Adams Mat tMat; 181eb07cef2SMark F. Adams PetscInt Ii,ncols; const PetscScalar *vals; const PetscInt *idx; 182eb07cef2SMark F. Adams ierr = MatCreateMPIAIJ( wcomm, ncrs0, ncrs0, 183eb07cef2SMark F. Adams PETSC_DETERMINE, PETSC_DETERMINE, 184eb07cef2SMark F. Adams 25, PETSC_NULL, 10, PETSC_NULL, 185eb07cef2SMark F. Adams &tMat ); 186eb07cef2SMark F. Adams 187eb07cef2SMark F. Adams for ( Ii = Istart0; Ii < Iend0; Ii++ ) { 188eb07cef2SMark F. Adams PetscInt dest_row = Ii/bs; 189eb07cef2SMark F. Adams ierr = MatGetRow(Amat,Ii,&ncols,&idx,&vals); CHKERRQ(ierr); 190eb07cef2SMark F. Adams for( jj = 0 ; jj < ncols ; jj++ ){ 191eb07cef2SMark F. Adams PetscInt dest_col = idx[jj]/bs; 192eb07cef2SMark F. Adams PetscScalar v = 1.0; 193eb07cef2SMark F. Adams ierr = MatSetValues(tMat,1,&dest_row,1,&dest_col,&v,ADD_VALUES); CHKERRQ(ierr); 194eb07cef2SMark F. Adams } 195eb07cef2SMark F. Adams ierr = MatRestoreRow(Amat,Ii,&ncols,&idx,&vals); CHKERRQ(ierr); 196eb07cef2SMark F. Adams } 197eb07cef2SMark F. Adams ierr = MatAssemblyBegin(tMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 198eb07cef2SMark F. Adams ierr = MatAssemblyEnd(tMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 199eb07cef2SMark F. Adams 200eb07cef2SMark F. Adams ierr = MatConvert( tMat, MATMPIADJ, MAT_INITIAL_MATRIX, &adj ); CHKERRQ(ierr); 201eb07cef2SMark F. Adams 202eb07cef2SMark F. Adams ierr = MatDestroy( &tMat ); CHKERRQ(ierr); 203eb07cef2SMark F. Adams } 2045ef31b24SMark F. Adams if( membershipKey == 0 ) { 2055ef31b24SMark F. Adams /* hack to fix global data that pmetis.c uses in 'adj' */ 2065ef31b24SMark F. Adams for( kk=0 , jj=0 ; kk<=npe ; jj++, kk += old_fact ) { 2075ef31b24SMark F. Adams adj->rmap->range[jj] = adj->rmap->range[kk]; 2085ef31b24SMark F. Adams } 2095ef31b24SMark F. Adams ierr = MatPartitioningCreate( new_comm, &mpart ); CHKERRQ(ierr); 2105ef31b24SMark F. Adams ierr = MatPartitioningSetAdjacency( mpart, adj ); CHKERRQ(ierr); 21111e60469SMark F. Adams ierr = MatPartitioningSetFromOptions( mpart ); CHKERRQ(ierr); 2125ef31b24SMark F. Adams ierr = MatPartitioningSetNParts( mpart, new_npe ); CHKERRQ(ierr); 21311e60469SMark F. Adams ierr = MatPartitioningApply( mpart, &isnewproc ); CHKERRQ(ierr); 21411e60469SMark F. Adams ierr = MatPartitioningDestroy( &mpart ); CHKERRQ(ierr); 2155ef31b24SMark F. Adams /* collect IS info */ 2165ef31b24SMark F. Adams ierr = ISGetLocalSize( isnewproc, &is_sz ); CHKERRQ(ierr); 217eb07cef2SMark F. Adams ierr = PetscMalloc( bs*is_sz*sizeof(PetscInt), &isnewproc_idx ); CHKERRQ(ierr); 2185ef31b24SMark F. Adams ierr = ISGetIndices( isnewproc, &is_idx ); CHKERRQ(ierr); 219eb07cef2SMark F. Adams /* spread partitioning across machine - probably the right thing to do but machine spec. */ 220eb07cef2SMark F. Adams for(kk=0,jj=0;kk<is_sz;kk++){ 221eb07cef2SMark F. Adams for(ii=0 ; ii<bs ; ii++, jj++ ) { /* expand for equation level by 'bs' */ 222eb07cef2SMark F. Adams isnewproc_idx[jj] = is_idx[kk] * new_fact; 223eb07cef2SMark F. Adams } 2245ef31b24SMark F. Adams } 2255ef31b24SMark F. Adams ierr = ISRestoreIndices( isnewproc, &is_idx ); CHKERRQ(ierr); 2265ef31b24SMark F. Adams ierr = ISDestroy( &isnewproc ); CHKERRQ(ierr); 227eb07cef2SMark F. Adams is_sz *= bs; 2285ef31b24SMark F. Adams } 2295ef31b24SMark F. Adams else { 2305ef31b24SMark F. Adams isnewproc_idx = 0; 2315ef31b24SMark F. Adams is_sz = 0; 2325ef31b24SMark F. Adams } 2335ef31b24SMark F. Adams ierr = MatDestroy( &adj ); CHKERRQ(ierr); 2345ef31b24SMark F. Adams ierr = MPI_Comm_free( &new_comm ); CHKERRQ(ierr); 2355ef31b24SMark F. Adams ierr = ISCreateGeneral( wcomm, is_sz, isnewproc_idx, PETSC_COPY_VALUES, &isnewproc ); 2365ef31b24SMark F. Adams if( membershipKey == 0 ) { 2375ef31b24SMark F. Adams ierr = PetscFree( isnewproc_idx ); CHKERRQ(ierr); 2385ef31b24SMark F. Adams } 23911e60469SMark F. Adams } 24011e60469SMark F. Adams /* 24111e60469SMark F. Adams Create an index set from the isnewproc index set to indicate the mapping TO 24211e60469SMark F. Adams */ 24311e60469SMark F. Adams ierr = ISPartitioningToNumbering( isnewproc, &isnum ); CHKERRQ(ierr); 24411e60469SMark F. Adams /* 24511e60469SMark F. Adams Determine how many elements are assigned to each processor 24611e60469SMark F. Adams */ 24711e60469SMark F. Adams ierr = ISPartitioningCount( isnewproc, npe, counts ); CHKERRQ(ierr); 24811e60469SMark F. Adams ierr = ISDestroy( &isnewproc ); CHKERRQ(ierr); 249eb07cef2SMark F. Adams ncrs_new = counts[mype]/bs; 25011e60469SMark F. Adams } 2515ef31b24SMark F. Adams 25211e60469SMark F. Adams { /* Create a vector to contain the newly ordered element information */ 25311e60469SMark F. Adams const PetscInt *idx; 25411e60469SMark F. Adams PetscInt i,j,k; 25511e60469SMark F. Adams IS isscat; 25611e60469SMark F. Adams PetscScalar *array; 25711e60469SMark F. Adams Vec src_crd, dest_crd; 258eb07cef2SMark F. Adams PetscReal *data = *a_coarse_data; 25911e60469SMark F. Adams VecScatter vecscat; 260eb07cef2SMark F. Adams PetscInt tidx[ncrs0*a_data_sz]; 261acadaa72SMark F. Adams 26211e60469SMark F. Adams ierr = VecCreate( wcomm, &dest_crd ); 263eb07cef2SMark F. Adams ierr = VecSetSizes( dest_crd, a_data_sz*ncrs_new, PETSC_DECIDE ); CHKERRQ(ierr); 26411e60469SMark F. Adams ierr = VecSetFromOptions( dest_crd ); CHKERRQ(ierr); /*funny vector-get global options?*/ 26511e60469SMark F. Adams /* 266eb07cef2SMark F. Adams There are 'a_data_sz' data items per node, (one can think of the vectors of having a 267eb07cef2SMark F. Adams block size of 'a_data_sz'). Note, ISs are expanded into equation space by 'bs'. 26811e60469SMark F. Adams */ 26911e60469SMark F. Adams ierr = ISGetIndices( isnum, &idx ); CHKERRQ(ierr); 27011e60469SMark F. Adams for(i=0,j=0; i<ncrs0 ; i++) { 271eb07cef2SMark F. Adams PetscInt lid = idx[i*bs]/bs; assert(idx[i*bs]%bs==0); 272eb07cef2SMark F. Adams for( k=0; k<a_data_sz ; k++, j++) tidx[j] = lid*a_data_sz + k; 27311e60469SMark F. Adams } 274eb07cef2SMark F. Adams ierr = ISCreateGeneral( wcomm, a_data_sz*ncrs0, tidx, PETSC_COPY_VALUES, &isscat ); 27511e60469SMark F. Adams CHKERRQ(ierr); 27611e60469SMark F. Adams ierr = ISRestoreIndices( isnum, &idx ); CHKERRQ(ierr); 27711e60469SMark F. Adams /* 27811e60469SMark F. Adams Create a vector to contain the original vertex information for each element 27911e60469SMark F. Adams */ 280eb07cef2SMark F. Adams ierr = VecCreateSeq( PETSC_COMM_SELF, a_data_sz*ncrs0, &src_crd ); CHKERRQ(ierr); 281eb07cef2SMark F. Adams for (i=0; i<a_data_sz*ncrs0; i++) { 282eb07cef2SMark F. Adams ierr = VecSetValues(src_crd, 1, &i, &data[i], INSERT_VALUES ); CHKERRQ(ierr); 283eb07cef2SMark F. Adams } 284eb07cef2SMark F. Adams ierr = VecAssemblyBegin(src_crd); CHKERRQ(ierr); 285eb07cef2SMark F. Adams ierr = VecAssemblyEnd(src_crd); CHKERRQ(ierr); 28611e60469SMark F. Adams /* 28711e60469SMark F. Adams Scatter the element vertex information (still in the original vertex ordering) 28811e60469SMark F. Adams to the correct processor 28911e60469SMark F. Adams */ 29011e60469SMark F. Adams ierr = VecScatterCreate( src_crd, PETSC_NULL, dest_crd, isscat, &vecscat); 29111e60469SMark F. Adams CHKERRQ(ierr); 29211e60469SMark F. Adams ierr = ISDestroy( &isscat ); CHKERRQ(ierr); 29311e60469SMark F. Adams ierr = VecScatterBegin(vecscat,src_crd,dest_crd,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 29411e60469SMark F. Adams ierr = VecScatterEnd(vecscat,src_crd,dest_crd,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 29511e60469SMark F. Adams ierr = VecScatterDestroy( &vecscat ); CHKERRQ(ierr); 29611e60469SMark F. Adams ierr = VecDestroy( &src_crd ); CHKERRQ(ierr); 29711e60469SMark F. Adams /* 29811e60469SMark F. Adams Put the element vertex data into a new allocation of the gdata->ele 29911e60469SMark F. Adams */ 300eb07cef2SMark F. Adams ierr = PetscFree( *a_coarse_data ); CHKERRQ(ierr); 301eb07cef2SMark F. Adams ierr = PetscMalloc( a_data_sz*ncrs_new*sizeof(PetscReal), a_coarse_data ); CHKERRQ(ierr); 302eb07cef2SMark F. Adams VecGetLocalSize( dest_crd, &i ); assert(i==a_data_sz*ncrs_new); 303eb07cef2SMark F. Adams 30411e60469SMark F. Adams ierr = VecGetArray( dest_crd, &array ); CHKERRQ(ierr); 305eb07cef2SMark F. Adams data = *a_coarse_data; 306eb07cef2SMark F. Adams for (i=0; i<a_data_sz*ncrs_new; i++) data[i] = PetscRealPart(array[i]); 30711e60469SMark F. Adams ierr = VecRestoreArray( dest_crd, &array ); CHKERRQ(ierr); 30811e60469SMark F. Adams ierr = VecDestroy( &dest_crd ); CHKERRQ(ierr); 30911e60469SMark F. Adams } 31011e60469SMark F. Adams /* 31111e60469SMark F. Adams Invert for MatGetSubMatrix 31211e60469SMark F. Adams */ 313eb07cef2SMark F. Adams ierr = ISInvertPermutation( isnum, ncrs_new*bs, &new_indices ); CHKERRQ(ierr); 31411e60469SMark F. Adams ierr = ISSort( new_indices ); CHKERRQ(ierr); /* is this needed? */ 31511e60469SMark F. Adams ierr = ISDestroy( &isnum ); CHKERRQ(ierr); 31611e60469SMark F. Adams /* A_crs output */ 3173530afc2SMark F. Adams ierr = MatGetSubMatrix( Amat, new_indices, new_indices, MAT_INITIAL_MATRIX, a_Amat_crs ); 31811e60469SMark F. Adams CHKERRQ(ierr); 319eb07cef2SMark F. Adams 32011e60469SMark F. Adams ierr = MatDestroy( &Amat ); CHKERRQ(ierr); 3213530afc2SMark F. Adams Amat = *a_Amat_crs; 322eb07cef2SMark F. Adams ierr = MatSetBlockSize( Amat, bs ); CHKERRQ(ierr); 323eb07cef2SMark F. Adams 32411e60469SMark F. Adams /* prolongator */ 32511e60469SMark F. Adams ierr = MatGetOwnershipRange( Pold, &Istart, &Iend ); CHKERRQ(ierr); 326eb07cef2SMark F. Adams ierr = MatGetBlockSize( Pold, &bs2 ); CHKERRQ(ierr); assert(bs==bs2); 32711e60469SMark F. Adams { 32811e60469SMark F. Adams IS findices; 32911e60469SMark F. Adams ierr = ISCreateStride(wcomm,Iend-Istart,Istart,1,&findices); CHKERRQ(ierr); 33011e60469SMark F. Adams ierr = MatGetSubMatrix( Pold, findices, new_indices, MAT_INITIAL_MATRIX, &Pnew ); 33111e60469SMark F. Adams CHKERRQ(ierr); 33211e60469SMark F. Adams ierr = ISDestroy( &findices ); CHKERRQ(ierr); 333eb07cef2SMark F. Adams ierr = MatSetBlockSize( Pnew, bs ); CHKERRQ(ierr); 33411e60469SMark F. Adams } 3353530afc2SMark F. Adams ierr = MatDestroy( a_P_inout ); CHKERRQ(ierr); 3363530afc2SMark F. Adams *a_P_inout = Pnew; /* output */ 337eb07cef2SMark F. Adams ierr = MatGetBlockSize( Pnew, &bs2 ); CHKERRQ(ierr); assert(bs==bs2); 33811e60469SMark F. Adams ierr = ISDestroy( &new_indices ); CHKERRQ(ierr); 3395b89ad90SMark F. Adams 3405b89ad90SMark F. Adams PetscFunctionReturn(0); 3415b89ad90SMark F. Adams } 3425b89ad90SMark F. Adams 343eb07cef2SMark F. Adams #define GAMG_MAXLEVELS 30 3445ef31b24SMark F. Adams #if defined(PETSC_USE_LOG) 3455ef31b24SMark F. Adams PetscLogStage gamg_stages[20]; 3465ef31b24SMark F. Adams #endif 3475b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */ 3485b89ad90SMark F. Adams /* 3495b89ad90SMark F. Adams PCSetUp_GAMG - Prepares for the use of the GAMG preconditioner 3505b89ad90SMark F. Adams by setting data structures and options. 3515b89ad90SMark F. Adams 3525b89ad90SMark F. Adams Input Parameter: 3535b89ad90SMark F. Adams . pc - the preconditioner context 3545b89ad90SMark F. Adams 3555b89ad90SMark F. Adams Application Interface Routine: PCSetUp() 3565b89ad90SMark F. Adams 3575b89ad90SMark F. Adams Notes: 3585b89ad90SMark F. Adams The interface routine PCSetUp() is not usually called directly by 3595b89ad90SMark F. Adams the user, but instead is called by PCApply() if necessary. 3605b89ad90SMark F. Adams */ 3615b89ad90SMark F. Adams #undef __FUNCT__ 3625b89ad90SMark F. Adams #define __FUNCT__ "PCSetUp_GAMG" 363eb07cef2SMark F. Adams PetscErrorCode PCSetUp_GAMG( PC a_pc ) 3645b89ad90SMark F. Adams { 3655b89ad90SMark F. Adams PetscErrorCode ierr; 366eb07cef2SMark F. Adams PC_MG *mg = (PC_MG*)a_pc->data; 3675b89ad90SMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 368eb07cef2SMark F. Adams Mat Amat = a_pc->mat, Pmat = a_pc->pmat; 3695b89ad90SMark F. Adams PetscBool isSeq, isMPI; 370eb07cef2SMark F. Adams PetscInt fine_level, level, level1, M, N, bs, nloc, lidx, data_sz, Istart, Iend; 371eb07cef2SMark F. Adams MPI_Comm wcomm = ((PetscObject)a_pc)->comm; 3723530afc2SMark F. Adams PetscMPIInt mype,npe,nactivepe; 373eb07cef2SMark F. Adams PetscBool isOK, useSA = PETSC_FALSE, flag; 374*587fa25dSMark F. Adams Mat Aarr[GAMG_MAXLEVELS], Parr[GAMG_MAXLEVELS]; 375*587fa25dSMark F. Adams PetscReal *coarse_data = 0, *data, emaxs[GAMG_MAXLEVELS]; 376eb07cef2SMark F. Adams char str[16]; 3775ef31b24SMark F. Adams 3785b89ad90SMark F. Adams PetscFunctionBegin; 379eb07cef2SMark F. Adams if( a_pc->setupcalled ) { 380eb07cef2SMark F. Adams /* no state data in GAMG to destroy */ 381eb07cef2SMark F. Adams ierr = PCReset_MG( a_pc ); CHKERRQ(ierr); 382eb07cef2SMark F. Adams } 383baa4e9faSMark F. Adams ierr = MPI_Comm_rank(wcomm,&mype);CHKERRQ(ierr); 384baa4e9faSMark F. Adams ierr = MPI_Comm_size(wcomm,&npe);CHKERRQ(ierr); 3855b89ad90SMark F. Adams /* setup special features of PCGAMG */ 3865b89ad90SMark F. Adams ierr = PetscTypeCompare((PetscObject)Amat, MATSEQAIJ, &isSeq);CHKERRQ(ierr); 3875b89ad90SMark F. Adams ierr = PetscTypeCompare((PetscObject)Amat, MATMPIAIJ, &isMPI);CHKERRQ(ierr); 3885b89ad90SMark F. Adams if (isMPI) { 3895b89ad90SMark F. Adams } else if (isSeq) { 3905b89ad90SMark F. Adams } else SETERRQ1(wcomm,PETSC_ERR_ARG_WRONG, "Matrix type '%s' cannot be used with GAMG. GAMG can only handle AIJ matrices.",((PetscObject)Amat)->type_name); 3915b89ad90SMark F. Adams 3925b89ad90SMark F. Adams /* GAMG requires input of fine-grid matrix. It determines nlevels. */ 3935b89ad90SMark F. Adams ierr = MatGetBlockSize( Amat, &bs ); CHKERRQ(ierr); 3943530afc2SMark F. Adams ierr = MatGetSize( Amat, &M, &N );CHKERRQ(ierr); 395eb07cef2SMark F. Adams ierr = MatGetOwnershipRange( Amat, &Istart, &Iend ); CHKERRQ(ierr); 396eb07cef2SMark F. Adams nloc = (Iend-Istart)/bs; assert((Iend-Istart)%bs == 0); 397eb07cef2SMark F. Adams 398eb07cef2SMark F. Adams ierr = PetscOptionsGetString(PETSC_NULL,"-pc_gamg_type",str,16,&flag); CHKERRQ( ierr ); 399eb07cef2SMark F. Adams useSA = (PetscBool)(flag && strcmp(str,"sa") == 0); 400eb07cef2SMark F. Adams if( pc_gamg->m_data == 0 ) { 401eb07cef2SMark F. Adams useSA = PETSC_TRUE; /* use SA if no data */ 402eb07cef2SMark F. Adams ierr = PCSetCoordinates_GAMG( a_pc, 1, 0 ); CHKERRQ( ierr ); 403eb07cef2SMark F. Adams } 404eb07cef2SMark F. Adams data = pc_gamg->m_data; 405eb07cef2SMark F. Adams /* Get A_i and R_i */ 406eb07cef2SMark F. Adams data_sz = pc_gamg->m_data_sz/nloc; 407eb07cef2SMark F. Adams PetscPrintf(PETSC_COMM_WORLD,"\t[%d]%s level %d N=%d, data size=%d m_data_sz=%d nloc=%d\n",0,__FUNCT__,0,N,data_sz,pc_gamg->m_data_sz,nloc); 4088f4b7eb5SMark F. Adams for ( level=0, Aarr[0] = Pmat, nactivepe = npe; /* hard wired stopping logic */ 409eb07cef2SMark F. Adams level < GAMG_MAXLEVELS-1 && (level==0 || M/bs>TOP_GRID_LIM) && (npe==1 || nactivepe>1); 4100205a208SMark F. Adams level++ ) { 4115b89ad90SMark F. Adams level1 = level + 1; 4125ef31b24SMark F. Adams ierr = PetscLogEventBegin(gamg_setup_stages[SET1],0,0,0,0);CHKERRQ(ierr); 413eb07cef2SMark F. Adams ierr = createProlongation( Aarr[level], data, pc_gamg->m_dim, &data_sz, 414*587fa25dSMark F. Adams &Parr[level1], &coarse_data, &isOK, &emaxs[level] ); 4155b89ad90SMark F. Adams CHKERRQ(ierr); 4165ef31b24SMark F. Adams ierr = PetscLogEventEnd(gamg_setup_stages[SET1],0,0,0,0);CHKERRQ(ierr); 4175ef31b24SMark F. Adams 418eb07cef2SMark F. Adams ierr = PetscFree( data ); CHKERRQ( ierr ); 419baa4e9faSMark F. Adams if(level==0) Aarr[0] = Amat; /* use Pmat for finest level setup, but use mat for solver */ 420baa4e9faSMark F. Adams if( isOK ) { 4215ef31b24SMark F. Adams ierr = PetscLogEventBegin(gamg_setup_stages[SET2],0,0,0,0);CHKERRQ(ierr); 422eb07cef2SMark F. Adams ierr = partitionLevel( Aarr[level], pc_gamg->m_data_sz/nloc, 423eb07cef2SMark F. Adams &Parr[level1], &coarse_data, &nactivepe, &Aarr[level1] ); 4243530afc2SMark F. Adams CHKERRQ(ierr); 4255ef31b24SMark F. Adams ierr = PetscLogEventEnd(gamg_setup_stages[SET2],0,0,0,0);CHKERRQ(ierr); 4263530afc2SMark F. Adams ierr = MatGetSize( Aarr[level1], &M, &N );CHKERRQ(ierr); 427eb07cef2SMark F. Adams PetscPrintf(PETSC_COMM_WORLD,"\t\t[%d]%s %d) N=%d, %d data size, %d active pes\n",0,__FUNCT__,level1,N,data_sz,nactivepe); 428baa4e9faSMark F. Adams } 429baa4e9faSMark F. Adams else{ 430baa4e9faSMark F. Adams break; 431baa4e9faSMark F. Adams } 432eb07cef2SMark F. Adams data = coarse_data; 4335b89ad90SMark F. Adams } 434eb07cef2SMark F. Adams ierr = PetscFree( coarse_data ); CHKERRQ( ierr ); 435baa4e9faSMark F. Adams PetscPrintf(PETSC_COMM_WORLD,"\t[%d]%s %d levels\n",0,__FUNCT__,level + 1); 4365b89ad90SMark F. Adams pc_gamg->m_data = 0; /* destroyed coordinate data */ 4375b89ad90SMark F. Adams pc_gamg->m_Nlevels = level + 1; 4385b89ad90SMark F. Adams fine_level = level; 439eb07cef2SMark F. Adams ierr = PCMGSetLevels(a_pc,pc_gamg->m_Nlevels,PETSC_NULL);CHKERRQ(ierr); 4405b89ad90SMark F. Adams 441fc4362bfSMark F. Adams /* set default smoothers */ 442*587fa25dSMark F. Adams for ( lidx=1, level = pc_gamg->m_Nlevels-2; 443*587fa25dSMark F. Adams lidx <= fine_level; 444*587fa25dSMark F. Adams lidx++, level--) { 4455745e0f5SMark F. Adams PetscReal emax, emin; 4465b89ad90SMark F. Adams KSP smoother; PC subpc; 447*587fa25dSMark F. Adams ierr = PCMGGetSmoother( a_pc, lidx, &smoother ); CHKERRQ(ierr); 4485b89ad90SMark F. Adams ierr = KSPSetType( smoother, KSPCHEBYCHEV );CHKERRQ(ierr); 449*587fa25dSMark F. Adams if( emaxs[level] > 0.0 ) { 450*587fa25dSMark F. Adams emax = 1.05*emaxs[level]; 451*587fa25dSMark F. Adams } 452*587fa25dSMark F. Adams else{ /* eigen estimate 'emax' */ 453*587fa25dSMark F. Adams KSP eksp; Mat Lmat = Aarr[level]; 454fc4362bfSMark F. Adams Vec bb, xx; PC pc; 455fc4362bfSMark F. Adams PetscInt N1, N0, tt; 4565745e0f5SMark F. Adams ierr = MatGetVecs( Lmat, &bb, 0 ); CHKERRQ(ierr); 4575745e0f5SMark F. Adams ierr = MatGetVecs( Lmat, &xx, 0 ); CHKERRQ(ierr); 458fc4362bfSMark F. Adams { 459fc4362bfSMark F. Adams PetscRandom rctx; 460fc4362bfSMark F. Adams ierr = PetscRandomCreate(wcomm,&rctx);CHKERRQ(ierr); 461fc4362bfSMark F. Adams ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr); 462fc4362bfSMark F. Adams ierr = VecSetRandom(bb,rctx);CHKERRQ(ierr); 463fc4362bfSMark F. Adams ierr = PetscRandomDestroy( &rctx ); CHKERRQ(ierr); 4645b89ad90SMark F. Adams } 465fc4362bfSMark F. Adams ierr = KSPCreate(wcomm,&eksp);CHKERRQ(ierr); 466fc4362bfSMark F. Adams ierr = KSPSetInitialGuessNonzero( eksp, PETSC_FALSE ); CHKERRQ(ierr); 4675745e0f5SMark F. Adams ierr = KSPSetOperators( eksp, Lmat, Lmat, DIFFERENT_NONZERO_PATTERN ); CHKERRQ( ierr ); 468fc4362bfSMark F. Adams ierr = KSPGetPC( eksp, &pc );CHKERRQ( ierr ); 469fc4362bfSMark F. Adams ierr = PCSetType( pc, PCJACOBI ); CHKERRQ(ierr); /* should be same as above */ 470fc4362bfSMark F. Adams ierr = KSPSetTolerances( eksp, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, 5 ); 471fc4362bfSMark F. Adams CHKERRQ(ierr); 472fc4362bfSMark F. Adams ierr = KSPSetConvergenceTest( eksp, KSPSkipConverged, 0, 0 ); CHKERRQ(ierr); 473fc4362bfSMark F. Adams ierr = KSPSetNormType( eksp, KSP_NORM_NONE ); CHKERRQ(ierr); 474fc4362bfSMark F. Adams 475fc4362bfSMark F. Adams ierr = KSPSetComputeSingularValues( eksp,PETSC_TRUE ); CHKERRQ(ierr); 476fc4362bfSMark F. Adams ierr = KSPSolve( eksp, bb, xx ); CHKERRQ(ierr); 477fc4362bfSMark F. Adams ierr = KSPComputeExtremeSingularValues( eksp, &emax, &emin ); CHKERRQ(ierr); 4785745e0f5SMark F. Adams ierr = MatGetSize( Lmat, &N1, &tt ); CHKERRQ(ierr); 479*587fa25dSMark F. Adams ierr = MatGetSize( Aarr[level+1], &N0, &tt );CHKERRQ(ierr); 480eb07cef2SMark F. Adams PetscPrintf(PETSC_COMM_WORLD,"\t\t\t%s max eigen = %e (N=%d)\n",__FUNCT__,emax,N1/bs); 4815745e0f5SMark F. Adams emax *= 1.05; 482fc4362bfSMark F. Adams 483fc4362bfSMark F. Adams ierr = VecDestroy( &xx ); CHKERRQ(ierr); 484fc4362bfSMark F. Adams ierr = VecDestroy( &bb ); CHKERRQ(ierr); 485fc4362bfSMark F. Adams ierr = KSPDestroy( &eksp ); CHKERRQ(ierr); 486fc4362bfSMark F. Adams 487fc4362bfSMark F. Adams emin = emax/((PetscReal)N1/(PetscReal)N0); /* this should be about the coarsening rate */ 488fc4362bfSMark F. Adams } 489*587fa25dSMark F. Adams ierr = KSPSetOperators( smoother, Aarr[level], Aarr[level], DIFFERENT_NONZERO_PATTERN ); 490fc4362bfSMark F. Adams ierr = KSPChebychevSetEigenvalues( smoother, emax, emin );CHKERRQ(ierr); 4915745e0f5SMark F. Adams ierr = KSPGetPC( smoother, &subpc ); CHKERRQ(ierr); 4925745e0f5SMark F. Adams ierr = PCSetType( subpc, PCJACOBI ); CHKERRQ(ierr); 4935745e0f5SMark F. Adams ierr = KSPSetNormType( smoother, KSP_NORM_NONE ); CHKERRQ(ierr); 4945745e0f5SMark F. Adams } 4955745e0f5SMark F. Adams { 4965745e0f5SMark F. Adams KSP smoother; /* coarse grid */ 4975745e0f5SMark F. Adams Mat Lmat = Aarr[pc_gamg->m_Nlevels-1]; 498eb07cef2SMark F. Adams ierr = PCMGGetSmoother( a_pc, 0, &smoother ); CHKERRQ(ierr); 4995745e0f5SMark F. Adams ierr = KSPSetOperators( smoother, Lmat, Lmat, DIFFERENT_NONZERO_PATTERN ); 5005745e0f5SMark F. Adams CHKERRQ(ierr); 5015745e0f5SMark F. Adams ierr = KSPSetNormType( smoother, KSP_NORM_NONE ); CHKERRQ(ierr); 502fc4362bfSMark F. Adams } 503fc4362bfSMark F. Adams /* should be called in PCSetFromOptions_GAMG(), but cannot be called prior to PCMGSetLevels() */ 504eb07cef2SMark F. Adams ierr = PCSetFromOptions_MG(a_pc); CHKERRQ(ierr); 5055b89ad90SMark F. Adams { 5065b89ad90SMark F. Adams PetscBool galerkin; 507eb07cef2SMark F. Adams ierr = PCMGGetGalerkin( a_pc, &galerkin); CHKERRQ(ierr); 5085b89ad90SMark F. Adams if(galerkin){ 5095b89ad90SMark F. Adams SETERRQ(wcomm,PETSC_ERR_ARG_WRONG, "GAMG does galerkin manually so it must not be used in PC_MG."); 5105b89ad90SMark F. Adams } 5115b89ad90SMark F. Adams } 5125745e0f5SMark F. Adams 5135745e0f5SMark F. Adams /* set interpolation between the levels, create timer stages, clean up */ 5148f4b7eb5SMark F. Adams if( PETSC_FALSE ) { 5155ef31b24SMark F. Adams char str[32]; 5165ef31b24SMark F. Adams sprintf(str,"MG Level %d (%d)",0,pc_gamg->m_Nlevels-1); 5175ef31b24SMark F. Adams PetscLogStageRegister(str, &gamg_stages[fine_level]); 5185ef31b24SMark F. Adams } 519*587fa25dSMark F. Adams for (lidx=0,level=pc_gamg->m_Nlevels-1; 520*587fa25dSMark F. Adams lidx<fine_level; 521*587fa25dSMark F. Adams lidx++, level--){ 522*587fa25dSMark F. Adams ierr = PCMGSetInterpolation( a_pc, lidx+1, Parr[level] );CHKERRQ(ierr); 5236c237d78SBarry Smith if( !PETSC_TRUE ) { 52411e60469SMark F. Adams PetscViewer viewer; char fname[32]; 525*587fa25dSMark F. Adams sprintf(fname,"Amat_%d.m",level); 52611e60469SMark F. Adams ierr = PetscViewerASCIIOpen( wcomm, fname, &viewer ); CHKERRQ(ierr); 5275b89ad90SMark F. Adams ierr = PetscViewerSetFormat( viewer, PETSC_VIEWER_ASCII_MATLAB); CHKERRQ(ierr); 528*587fa25dSMark F. Adams ierr = MatView( Aarr[level], viewer ); CHKERRQ(ierr); 5295b89ad90SMark F. Adams ierr = PetscViewerDestroy( &viewer ); 5305b89ad90SMark F. Adams } 531*587fa25dSMark F. Adams ierr = MatDestroy( &Parr[level] ); CHKERRQ(ierr); 532*587fa25dSMark F. Adams ierr = MatDestroy( &Aarr[level] ); CHKERRQ(ierr); 5338f4b7eb5SMark F. Adams if( PETSC_FALSE ) { 5345ef31b24SMark F. Adams char str[32]; 535*587fa25dSMark F. Adams sprintf(str,"MG Level %d (%d)",lidx+1,level-1); 536*587fa25dSMark F. Adams PetscLogStageRegister(str, &gamg_stages[level-1]); 537a92563c5SMark F. Adams } 5385b89ad90SMark F. Adams } 5395745e0f5SMark F. Adams 5405b89ad90SMark F. Adams /* setupcalled is set to 0 so that MG is setup from scratch */ 541eb07cef2SMark F. Adams a_pc->setupcalled = 0; 542eb07cef2SMark F. Adams ierr = PCSetUp_MG(a_pc);CHKERRQ(ierr); 5435b89ad90SMark F. Adams PetscFunctionReturn(0); 5445b89ad90SMark F. Adams } 5455b89ad90SMark F. Adams 546eb07cef2SMark F. Adams /* ------------------------------------------------------------------------- */ 5475b89ad90SMark F. Adams /* 5485b89ad90SMark F. Adams PCDestroy_GAMG - Destroys the private context for the GAMG preconditioner 5495b89ad90SMark F. Adams that was created with PCCreate_GAMG(). 5505b89ad90SMark F. Adams 5515b89ad90SMark F. Adams Input Parameter: 5525b89ad90SMark F. Adams . pc - the preconditioner context 5535b89ad90SMark F. Adams 5545b89ad90SMark F. Adams Application Interface Routine: PCDestroy() 5555b89ad90SMark F. Adams */ 5565b89ad90SMark F. Adams #undef __FUNCT__ 5575b89ad90SMark F. Adams #define __FUNCT__ "PCDestroy_GAMG" 5585b89ad90SMark F. Adams PetscErrorCode PCDestroy_GAMG(PC pc) 5595b89ad90SMark F. Adams { 5605b89ad90SMark F. Adams PetscErrorCode ierr; 5615b89ad90SMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 5625b89ad90SMark F. Adams PC_GAMG *pc_gamg= (PC_GAMG*)mg->innerctx; 5635b89ad90SMark F. Adams 5645b89ad90SMark F. Adams PetscFunctionBegin; 5655b89ad90SMark F. Adams ierr = PCReset_GAMG(pc);CHKERRQ(ierr); 5665b89ad90SMark F. Adams ierr = PetscFree(pc_gamg);CHKERRQ(ierr); 5675b89ad90SMark F. Adams ierr = PCDestroy_MG(pc);CHKERRQ(ierr); 5685b89ad90SMark F. Adams PetscFunctionReturn(0); 5695b89ad90SMark F. Adams } 5705b89ad90SMark F. Adams 5715b89ad90SMark F. Adams #undef __FUNCT__ 5725b89ad90SMark F. Adams #define __FUNCT__ "PCSetFromOptions_GAMG" 5735b89ad90SMark F. Adams PetscErrorCode PCSetFromOptions_GAMG(PC pc) 5745b89ad90SMark F. Adams { 5755b89ad90SMark F. Adams /* PetscErrorCode ierr; */ 5765b89ad90SMark F. Adams /* PC_MG *mg = (PC_MG*)pc->data; */ 5775b89ad90SMark F. Adams /* PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; */ 5785b89ad90SMark F. Adams /* MPI_Comm comm = ((PetscObject)pc)->comm; */ 5795b89ad90SMark F. Adams 5805b89ad90SMark F. Adams PetscFunctionBegin; 5815b89ad90SMark F. Adams PetscFunctionReturn(0); 5825b89ad90SMark F. Adams } 5835b89ad90SMark F. Adams 5845b89ad90SMark F. Adams /* -------------------------------------------------------------------------- */ 5855b89ad90SMark F. Adams /* 5865b89ad90SMark F. Adams PCCreate_GAMG - Creates a GAMG preconditioner context, PC_GAMG 5875b89ad90SMark F. Adams 5885b89ad90SMark F. Adams Input Parameter: 5895b89ad90SMark F. Adams . pc - the preconditioner context 5905b89ad90SMark F. Adams 5915b89ad90SMark F. Adams Application Interface Routine: PCCreate() 5925b89ad90SMark F. Adams 5935b89ad90SMark F. Adams */ 5945b89ad90SMark F. Adams /* MC 5955b89ad90SMark F. Adams PCGAMG - Use algebraic multigrid preconditioning. This preconditioner requires you provide 5965b89ad90SMark F. Adams fine grid discretization matrix and coordinates on the fine grid. 5975b89ad90SMark F. Adams 5985b89ad90SMark F. Adams Options Database Key: 5995b89ad90SMark F. Adams Multigrid options(inherited) 6005b89ad90SMark F. Adams + -pc_mg_cycles <1>: 1 for V cycle, 2 for W-cycle (MGSetCycles) 6015b89ad90SMark F. Adams . -pc_mg_smoothup <1>: Number of post-smoothing steps (MGSetNumberSmoothUp) 6025b89ad90SMark F. Adams . -pc_mg_smoothdown <1>: Number of pre-smoothing steps (MGSetNumberSmoothDown) 6035b89ad90SMark F. Adams -pc_mg_type <multiplicative>: (one of) additive multiplicative full cascade kascade 6045b89ad90SMark F. Adams GAMG options: 6055b89ad90SMark F. Adams 6065b89ad90SMark F. Adams Level: intermediate 6075b89ad90SMark F. Adams Concepts: multigrid 6085b89ad90SMark F. Adams 6095b89ad90SMark F. Adams .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, PCMGType, 6105b89ad90SMark F. Adams PCMGSetLevels(), PCMGGetLevels(), PCMGSetType(), MPSetCycles(), PCMGSetNumberSmoothDown(), 6115b89ad90SMark F. Adams PCMGSetNumberSmoothUp(), PCMGGetCoarseSolve(), PCMGSetResidual(), PCMGSetInterpolation(), 6125b89ad90SMark F. Adams PCMGSetRestriction(), PCMGGetSmoother(), PCMGGetSmootherUp(), PCMGGetSmootherDown(), 6135b89ad90SMark F. Adams PCMGSetCyclesOnLevel(), PCMGSetRhs(), PCMGSetX(), PCMGSetR() 6145b89ad90SMark F. Adams M */ 6155b89ad90SMark F. Adams 6165b89ad90SMark F. Adams EXTERN_C_BEGIN 6175b89ad90SMark F. Adams #undef __FUNCT__ 6185b89ad90SMark F. Adams #define __FUNCT__ "PCCreate_GAMG" 6195b89ad90SMark F. Adams PetscErrorCode PCCreate_GAMG(PC pc) 6205b89ad90SMark F. Adams { 6215b89ad90SMark F. Adams PetscErrorCode ierr; 6225b89ad90SMark F. Adams PC_GAMG *pc_gamg; 6235b89ad90SMark F. Adams PC_MG *mg; 6245ef31b24SMark F. Adams PetscClassId cookie; 6255b89ad90SMark F. Adams 6265b89ad90SMark F. Adams PetscFunctionBegin; 6275b89ad90SMark F. Adams /* PCGAMG is an inherited class of PCMG. Initialize pc as PCMG */ 6285b89ad90SMark F. Adams ierr = PCSetType(pc,PCMG);CHKERRQ(ierr); /* calls PCCreate_MG() and MGCreate_Private() */ 6295b89ad90SMark F. Adams ierr = PetscObjectChangeTypeName((PetscObject)pc,PCGAMG);CHKERRQ(ierr); 6305b89ad90SMark F. Adams 6315b89ad90SMark F. Adams /* create a supporting struct and attach it to pc */ 6325b89ad90SMark F. Adams ierr = PetscNewLog(pc,PC_GAMG,&pc_gamg);CHKERRQ(ierr); 6335b89ad90SMark F. Adams mg = (PC_MG*)pc->data; 6345b89ad90SMark F. Adams mg->innerctx = pc_gamg; 6355b89ad90SMark F. Adams 6365b89ad90SMark F. Adams pc_gamg->m_Nlevels = -1; 6375b89ad90SMark F. Adams 6385b89ad90SMark F. Adams /* overwrite the pointers of PCMG by the functions of PCGAMG */ 6395b89ad90SMark F. Adams pc->ops->setfromoptions = PCSetFromOptions_GAMG; 6405b89ad90SMark F. Adams pc->ops->setup = PCSetUp_GAMG; 6415b89ad90SMark F. Adams pc->ops->reset = PCReset_GAMG; 6425b89ad90SMark F. Adams pc->ops->destroy = PCDestroy_GAMG; 6435b89ad90SMark F. Adams 6445b89ad90SMark F. Adams ierr = PetscObjectComposeFunctionDynamic( (PetscObject)pc, 6455b89ad90SMark F. Adams "PCSetCoordinates_C", 6465b89ad90SMark F. Adams "PCSetCoordinates_GAMG", 6475b89ad90SMark F. Adams PCSetCoordinates_GAMG);CHKERRQ(ierr); 6485ef31b24SMark F. Adams 6495ef31b24SMark F. Adams PetscClassIdRegister("GAMG Setup",&cookie); 6505ef31b24SMark F. Adams PetscLogEventRegister("GAMG-createProl", cookie, &gamg_setup_stages[SET1]); 6515ef31b24SMark F. Adams PetscLogEventRegister("GAMG-partLevel", cookie, &gamg_setup_stages[SET2]); 6525ef31b24SMark F. Adams PetscLogEventRegister("GAMG-MIS Graph", cookie, &gamg_setup_stages[SET3]); 6535ef31b24SMark F. Adams PetscLogEventRegister("GAMG-MIS-Agg", cookie, &gamg_setup_stages[SET4]); 6545ef31b24SMark F. Adams PetscLogEventRegister("GAMG-growSupp", cookie, &gamg_setup_stages[SET5]); 6555ef31b24SMark F. Adams PetscLogEventRegister("GAMG-tri-Prol", cookie, &gamg_setup_stages[SET6]); 6565ef31b24SMark F. Adams PetscLogEventRegister("GAMG-find-prol", cookie, &gamg_setup_stages[FIND_V]); 6575ef31b24SMark F. Adams 6585b89ad90SMark F. Adams PetscFunctionReturn(0); 6595b89ad90SMark F. Adams } 6605b89ad90SMark F. Adams EXTERN_C_END 661