12e68589bSMark F. Adams /* 2b817416eSBarry Smith GAMG geometric-algebric multigrid PC - Mark Adams 2011 32e68589bSMark F. Adams */ 42e68589bSMark F. Adams 52e68589bSMark F. Adams #include <../src/ksp/pc/impls/gamg/gamg.h> /*I "petscpc.h" I*/ 62e68589bSMark F. Adams #include <petscblaslapack.h> 7539c167fSBarry Smith #include <petscdm.h> 873f7197eSJed Brown #include <petsc/private/kspimpl.h> 92e68589bSMark F. Adams 102e68589bSMark F. Adams typedef struct { 11c8b0795cSMark F. Adams PetscInt nsmooths; 12c8b0795cSMark F. Adams PetscBool sym_graph; 139ab59c8bSMark Adams PetscInt square_graph; 142e68589bSMark F. Adams } PC_GAMG_AGG; 152e68589bSMark F. Adams 162e68589bSMark F. Adams /*@ 172e68589bSMark F. Adams PCGAMGSetNSmooths - Set number of smoothing steps (1 is typical) 182e68589bSMark F. Adams 19d5d25401SBarry Smith Logically Collective on PC 202e68589bSMark F. Adams 212e68589bSMark F. Adams Input Parameters: 222e68589bSMark F. Adams . pc - the preconditioner context 232e68589bSMark F. Adams 242e68589bSMark F. Adams Options Database Key: 25cab9ed1eSBarry Smith . -pc_gamg_agg_nsmooths <nsmooth, default=1> - number of smoothing steps to use with smooth aggregation 262e68589bSMark F. Adams 272e68589bSMark F. Adams Level: intermediate 282e68589bSMark F. Adams 292e68589bSMark F. Adams .seealso: () 302e68589bSMark F. Adams @*/ 312e68589bSMark F. Adams PetscErrorCode PCGAMGSetNSmooths(PC pc, PetscInt n) 322e68589bSMark F. Adams { 332e68589bSMark F. Adams PetscFunctionBegin; 342e68589bSMark F. Adams PetscValidHeaderSpecific(pc,PC_CLASSID,1); 35d5d25401SBarry Smith PetscValidLogicalCollectiveInt(pc,n,2); 365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTryMethod(pc,"PCGAMGSetNSmooths_C",(PC,PetscInt),(pc,n))); 372e68589bSMark F. Adams PetscFunctionReturn(0); 382e68589bSMark F. Adams } 392e68589bSMark F. Adams 40e0877f53SBarry Smith static PetscErrorCode PCGAMGSetNSmooths_AGG(PC pc, PetscInt n) 412e68589bSMark F. Adams { 422e68589bSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 432e68589bSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 44c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 452e68589bSMark F. Adams 462e68589bSMark F. Adams PetscFunctionBegin; 47c8b0795cSMark F. Adams pc_gamg_agg->nsmooths = n; 48c8b0795cSMark F. Adams PetscFunctionReturn(0); 49c8b0795cSMark F. Adams } 50c8b0795cSMark F. Adams 51c8b0795cSMark F. Adams /*@ 52cab9ed1eSBarry Smith PCGAMGSetSymGraph - Symmetrize the graph before computing the aggregation. Some algorithms require the graph be symmetric 53c8b0795cSMark F. Adams 54d5d25401SBarry Smith Logically Collective on PC 55c8b0795cSMark F. Adams 56c8b0795cSMark F. Adams Input Parameters: 57cab9ed1eSBarry Smith + pc - the preconditioner context 58a2b725a8SWilliam Gropp - n - PETSC_TRUE or PETSC_FALSE 59c8b0795cSMark F. Adams 60c8b0795cSMark F. Adams Options Database Key: 61cab9ed1eSBarry Smith . -pc_gamg_sym_graph <true,default=false> - symmetrize the graph before computing the aggregation 62c8b0795cSMark F. Adams 63c8b0795cSMark F. Adams Level: intermediate 64c8b0795cSMark F. Adams 65cab9ed1eSBarry Smith .seealso: PCGAMGSetSquareGraph() 66c8b0795cSMark F. Adams @*/ 67c8b0795cSMark F. Adams PetscErrorCode PCGAMGSetSymGraph(PC pc, PetscBool n) 68c8b0795cSMark F. Adams { 69c8b0795cSMark F. Adams PetscFunctionBegin; 70c8b0795cSMark F. Adams PetscValidHeaderSpecific(pc,PC_CLASSID,1); 71d5d25401SBarry Smith PetscValidLogicalCollectiveBool(pc,n,2); 725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTryMethod(pc,"PCGAMGSetSymGraph_C",(PC,PetscBool),(pc,n))); 73c8b0795cSMark F. Adams PetscFunctionReturn(0); 74c8b0795cSMark F. Adams } 75c8b0795cSMark F. Adams 76e0877f53SBarry Smith static PetscErrorCode PCGAMGSetSymGraph_AGG(PC pc, PetscBool n) 77c8b0795cSMark F. Adams { 78c8b0795cSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 79c8b0795cSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 80c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 81c8b0795cSMark F. Adams 82c8b0795cSMark F. Adams PetscFunctionBegin; 83c8b0795cSMark F. Adams pc_gamg_agg->sym_graph = n; 842e68589bSMark F. Adams PetscFunctionReturn(0); 852e68589bSMark F. Adams } 862e68589bSMark F. Adams 87ef4ad70eSMark F. Adams /*@ 88cab9ed1eSBarry Smith PCGAMGSetSquareGraph - Square the graph, ie. compute A'*A before aggregating it 89ef4ad70eSMark F. Adams 90d5d25401SBarry Smith Logically Collective on PC 91ef4ad70eSMark F. Adams 92ef4ad70eSMark F. Adams Input Parameters: 93cab9ed1eSBarry Smith + pc - the preconditioner context 94d5d25401SBarry Smith - n - 0, 1 or more 95ef4ad70eSMark F. Adams 96ef4ad70eSMark F. Adams Options Database Key: 97cab9ed1eSBarry Smith . -pc_gamg_square_graph <n,default = 1> - number of levels to square the graph on before aggregating it 98ef4ad70eSMark F. Adams 99af3c827dSMark Adams Notes: 100af3c827dSMark Adams Squaring the graph increases the rate of coarsening (aggressive coarsening) and thereby reduces the complexity of the coarse grids, and generally results in slower solver converge rates. Reducing coarse grid complexity reduced the complexity of Galerkin coarse grid construction considerably. 101af3c827dSMark Adams 102ef4ad70eSMark F. Adams Level: intermediate 103ef4ad70eSMark F. Adams 104af3c827dSMark Adams .seealso: PCGAMGSetSymGraph(), PCGAMGSetThreshold() 105ef4ad70eSMark F. Adams @*/ 1069ab59c8bSMark Adams PetscErrorCode PCGAMGSetSquareGraph(PC pc, PetscInt n) 107ef4ad70eSMark F. Adams { 108ef4ad70eSMark F. Adams PetscFunctionBegin; 109ef4ad70eSMark F. Adams PetscValidHeaderSpecific(pc,PC_CLASSID,1); 110d5d25401SBarry Smith PetscValidLogicalCollectiveInt(pc,n,2); 1115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscTryMethod(pc,"PCGAMGSetSquareGraph_C",(PC,PetscInt),(pc,n))); 112ef4ad70eSMark F. Adams PetscFunctionReturn(0); 113ef4ad70eSMark F. Adams } 114ef4ad70eSMark F. Adams 115e0877f53SBarry Smith static PetscErrorCode PCGAMGSetSquareGraph_AGG(PC pc, PetscInt n) 116ef4ad70eSMark F. Adams { 117ef4ad70eSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 118ef4ad70eSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 119ef4ad70eSMark F. Adams PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 120ef4ad70eSMark F. Adams 121ef4ad70eSMark F. Adams PetscFunctionBegin; 122ef4ad70eSMark F. Adams pc_gamg_agg->square_graph = n; 123ef4ad70eSMark F. Adams PetscFunctionReturn(0); 124ef4ad70eSMark F. Adams } 125ef4ad70eSMark F. Adams 126e0877f53SBarry Smith static PetscErrorCode PCSetFromOptions_GAMG_AGG(PetscOptionItems *PetscOptionsObject,PC pc) 1272e68589bSMark F. Adams { 1282e68589bSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 1292e68589bSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 130c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 1312e68589bSMark F. Adams 1322e68589bSMark F. Adams PetscFunctionBegin; 1335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsHead(PetscOptionsObject,"GAMG-AGG options")); 1342e68589bSMark F. Adams { 1355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-pc_gamg_agg_nsmooths","smoothing steps for smoothed aggregation, usually 1","PCGAMGSetNSmooths",pc_gamg_agg->nsmooths,&pc_gamg_agg->nsmooths,NULL)); 1365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-pc_gamg_sym_graph","Set for asymmetric matrices","PCGAMGSetSymGraph",pc_gamg_agg->sym_graph,&pc_gamg_agg->sym_graph,NULL)); 1375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsInt("-pc_gamg_square_graph","Number of levels to square graph for faster coarsening and lower coarse grid complexity","PCGAMGSetSquareGraph",pc_gamg_agg->square_graph,&pc_gamg_agg->square_graph,NULL)); 1382e68589bSMark F. Adams } 1395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsTail()); 1402e68589bSMark F. Adams PetscFunctionReturn(0); 1412e68589bSMark F. Adams } 1422e68589bSMark F. Adams 1432e68589bSMark F. Adams /* -------------------------------------------------------------------------- */ 144e0877f53SBarry Smith static PetscErrorCode PCDestroy_GAMG_AGG(PC pc) 1452e68589bSMark F. Adams { 1462e68589bSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 1472e68589bSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 1482e68589bSMark F. Adams 1492e68589bSMark F. Adams PetscFunctionBegin; 1505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pc_gamg->subctx)); 1515f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL)); 1522e68589bSMark F. Adams PetscFunctionReturn(0); 1532e68589bSMark F. Adams } 1542e68589bSMark F. Adams 1552e68589bSMark F. Adams /* -------------------------------------------------------------------------- */ 1562e68589bSMark F. Adams /* 1572e68589bSMark F. Adams PCSetCoordinates_AGG 158302f38e8SMark F. Adams - collective 1592e68589bSMark F. Adams 1602e68589bSMark F. Adams Input Parameter: 1612e68589bSMark F. Adams . pc - the preconditioner context 162a2f3521dSMark F. Adams . ndm - dimesion of data (used for dof/vertex for Stokes) 163302f38e8SMark F. Adams . a_nloc - number of vertices local 164302f38e8SMark F. Adams . coords - [a_nloc][ndm] - interleaved coordinate data: {x_0, y_0, z_0, x_1, y_1, ...} 1652e68589bSMark F. Adams */ 1661e6b0712SBarry Smith 1671e6b0712SBarry Smith static PetscErrorCode PCSetCoordinates_AGG(PC pc, PetscInt ndm, PetscInt a_nloc, PetscReal *coords) 1682e68589bSMark F. Adams { 1692e68589bSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 1702e68589bSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 17169344418SMark F. Adams PetscInt arrsz,kk,ii,jj,nloc,ndatarows,ndf; 172a2f3521dSMark F. Adams Mat mat = pc->pmat; 1732e68589bSMark F. Adams 1742e68589bSMark F. Adams PetscFunctionBegin; 175a2f3521dSMark F. Adams PetscValidHeaderSpecific(pc,PC_CLASSID,1); 176a2f3521dSMark F. Adams PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 177302f38e8SMark F. Adams nloc = a_nloc; 1782e68589bSMark F. Adams 1792e68589bSMark F. Adams /* SA: null space vectors */ 1805f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetBlockSize(mat, &ndf)); /* this does not work for Stokes */ 18169344418SMark F. Adams if (coords && ndf==1) pc_gamg->data_cell_cols = 1; /* scalar w/ coords and SA (not needed) */ 182a2f3521dSMark F. Adams else if (coords) { 1832c71b3e2SJacob Faibussowitsch PetscCheckFalse(ndm > ndf,PETSC_COMM_SELF,PETSC_ERR_PLIB,"degrees of motion %D > block size %D",ndm,ndf); 18469344418SMark F. Adams pc_gamg->data_cell_cols = (ndm==2 ? 3 : 6); /* displacement elasticity */ 18569344418SMark F. Adams if (ndm != ndf) { 1862c71b3e2SJacob Faibussowitsch PetscCheckFalse(pc_gamg->data_cell_cols != ndf,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Don't know how to create null space for ndm=%D, ndf=%D. Use MatSetNearNullSpace().",ndm,ndf); 187a2f3521dSMark F. Adams } 188806fa848SBarry Smith } else pc_gamg->data_cell_cols = ndf; /* no data, force SA with constant null space vectors */ 18971959b99SBarry Smith pc_gamg->data_cell_rows = ndatarows = ndf; 1902c71b3e2SJacob Faibussowitsch PetscCheckFalse(pc_gamg->data_cell_cols <= 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"pc_gamg->data_cell_cols %D <= 0",pc_gamg->data_cell_cols); 191c8b0795cSMark F. Adams arrsz = nloc*pc_gamg->data_cell_rows*pc_gamg->data_cell_cols; 1922e68589bSMark F. Adams 1937f66b68fSMark Adams if (!pc_gamg->data || (pc_gamg->data_sz != arrsz)) { 1945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pc_gamg->data)); 1955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(arrsz+1, &pc_gamg->data)); 1962e68589bSMark F. Adams } 1972e68589bSMark F. Adams /* copy data in - column oriented */ 1982e68589bSMark F. Adams for (kk=0; kk<nloc; kk++) { 19969344418SMark F. Adams const PetscInt M = nloc*pc_gamg->data_cell_rows; /* stride into data */ 20069344418SMark F. Adams PetscReal *data = &pc_gamg->data[kk*ndatarows]; /* start of cell */ 201c8b0795cSMark F. Adams if (pc_gamg->data_cell_cols==1) *data = 1.0; 2022e68589bSMark F. Adams else { 20369344418SMark F. Adams /* translational modes */ 2042fa5cd67SKarl Rupp for (ii=0;ii<ndatarows;ii++) { 2052fa5cd67SKarl Rupp for (jj=0;jj<ndatarows;jj++) { 20669344418SMark F. Adams if (ii==jj)data[ii*M + jj] = 1.0; 2072e68589bSMark F. Adams else data[ii*M + jj] = 0.0; 2082fa5cd67SKarl Rupp } 2092fa5cd67SKarl Rupp } 21069344418SMark F. Adams 21169344418SMark F. Adams /* rotational modes */ 2122e68589bSMark F. Adams if (coords) { 21369344418SMark F. Adams if (ndm == 2) { 2142e68589bSMark F. Adams data += 2*M; 2152e68589bSMark F. Adams data[0] = -coords[2*kk+1]; 2162e68589bSMark F. Adams data[1] = coords[2*kk]; 217806fa848SBarry Smith } else { 2182e68589bSMark F. Adams data += 3*M; 2192e68589bSMark F. Adams data[0] = 0.0; data[M+0] = coords[3*kk+2]; data[2*M+0] = -coords[3*kk+1]; 2202e68589bSMark F. Adams data[1] = -coords[3*kk+2]; data[M+1] = 0.0; data[2*M+1] = coords[3*kk]; 2212e68589bSMark F. Adams data[2] = coords[3*kk+1]; data[M+2] = -coords[3*kk]; data[2*M+2] = 0.0; 2222e68589bSMark F. Adams } 2232e68589bSMark F. Adams } 2242e68589bSMark F. Adams } 2252e68589bSMark F. Adams } 2262e68589bSMark F. Adams pc_gamg->data_sz = arrsz; 2272e68589bSMark F. Adams PetscFunctionReturn(0); 2282e68589bSMark F. Adams } 2292e68589bSMark F. Adams 230b43b03e9SMark F. Adams typedef PetscInt NState; 231b43b03e9SMark F. Adams static const NState NOT_DONE=-2; 232b43b03e9SMark F. Adams static const NState DELETED =-1; 233b43b03e9SMark F. Adams static const NState REMOVED =-3; 234b43b03e9SMark F. Adams #define IS_SELECTED(s) (s!=DELETED && s!=NOT_DONE && s!=REMOVED) 235b43b03e9SMark F. Adams 236c8b0795cSMark F. Adams /* -------------------------------------------------------------------------- */ 237c8b0795cSMark F. Adams /* 238b43b03e9SMark F. Adams smoothAggs - greedy grab of with G1 (unsquared graph) -- AIJ specific 239b43b03e9SMark F. Adams - AGG-MG specific: clears singletons out of 'selected_2' 240c8b0795cSMark F. Adams 241c8b0795cSMark F. Adams Input Parameter: 242fdb86571SRichard Tran Mills . Gmat_2 - global matrix of graph (data not defined) base (squared) graph 2432adfe9d3SBarry Smith . Gmat_1 - base graph to grab with base graph 244c8b0795cSMark F. Adams Input/Output Parameter: 2450cbbd2e1SMark F. Adams . aggs_2 - linked list of aggs with gids) 246c8b0795cSMark F. Adams */ 247e3df7ea3SBarry Smith static PetscErrorCode smoothAggs(PC pc,Mat Gmat_2, Mat Gmat_1,PetscCoarsenData *aggs_2) 248c8b0795cSMark F. Adams { 249c8b0795cSMark F. Adams PetscBool isMPI; 2500a545947SLisandro Dalcin Mat_SeqAIJ *matA_1, *matB_1=NULL; 2513b4367a7SBarry Smith MPI_Comm comm; 2520cbbd2e1SMark F. Adams PetscInt lid,*ii,*idx,ix,Iend,my0,kk,n,j; 2530a545947SLisandro Dalcin Mat_MPIAIJ *mpimat_2 = NULL, *mpimat_1=NULL; 254c8b0795cSMark F. Adams const PetscInt nloc = Gmat_2->rmap->n; 2550cbbd2e1SMark F. Adams PetscScalar *cpcol_1_state,*cpcol_2_state,*cpcol_2_par_orig,*lid_parent_gid; 2560cbbd2e1SMark F. Adams PetscInt *lid_cprowID_1; 257c8b0795cSMark F. Adams NState *lid_state; 2580cbbd2e1SMark F. Adams Vec ghost_par_orig2; 259c8b0795cSMark F. Adams 260c8b0795cSMark F. Adams PetscFunctionBegin; 2615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)Gmat_2,&comm)); 2625f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRange(Gmat_1,&my0,&Iend)); 263c8b0795cSMark F. Adams 264c8b0795cSMark F. Adams /* get submatrices */ 2655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrbeginswith(((PetscObject)Gmat_1)->type_name,MATMPIAIJ,&isMPI)); 266c8b0795cSMark F. Adams if (isMPI) { 267c8b0795cSMark F. Adams /* grab matrix objects */ 268c8b0795cSMark F. Adams mpimat_2 = (Mat_MPIAIJ*)Gmat_2->data; 269c8b0795cSMark F. Adams mpimat_1 = (Mat_MPIAIJ*)Gmat_1->data; 270c8b0795cSMark F. Adams matA_1 = (Mat_SeqAIJ*)mpimat_1->A->data; 271c8b0795cSMark F. Adams matB_1 = (Mat_SeqAIJ*)mpimat_1->B->data; 272c8b0795cSMark F. Adams 273c8b0795cSMark F. Adams /* force compressed row storage for B matrix in AuxMat */ 2745f80ce2aSJacob Faibussowitsch CHKERRQ(MatCheckCompressedRow(mpimat_1->B,matB_1->nonzerorowcnt,&matB_1->compressedrow,matB_1->i,Gmat_1->rmap->n,-1.0)); 275c8b0795cSMark F. Adams 2765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nloc, &lid_cprowID_1)); 2770cbbd2e1SMark F. Adams for (lid = 0; lid < nloc; lid++) lid_cprowID_1[lid] = -1; 278c8b0795cSMark F. Adams for (ix=0; ix<matB_1->compressedrow.nrows; ix++) { 279c8b0795cSMark F. Adams PetscInt lid = matB_1->compressedrow.rindex[ix]; 280c8b0795cSMark F. Adams lid_cprowID_1[lid] = ix; 281c8b0795cSMark F. Adams } 282806fa848SBarry Smith } else { 28315687449SMark Adams PetscBool isAIJ; 2845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrbeginswith(((PetscObject)Gmat_1)->type_name,MATSEQAIJ,&isAIJ)); 285*28b400f6SJacob Faibussowitsch PetscCheck(isAIJ,PETSC_COMM_SELF,PETSC_ERR_USER,"Require AIJ matrix."); 286c8b0795cSMark F. Adams matA_1 = (Mat_SeqAIJ*)Gmat_1->data; 2870298fd71SBarry Smith lid_cprowID_1 = NULL; 288c8b0795cSMark F. Adams } 28978a438d6SMark Adams if (nloc>0) { 2902c71b3e2SJacob Faibussowitsch PetscCheckFalse(matB_1 && !matB_1->compressedrow.use,PETSC_COMM_SELF,PETSC_ERR_PLIB,"matB_1 && !matB_1->compressedrow.use: PETSc bug???"); 29178a438d6SMark Adams } 292c8b0795cSMark F. Adams /* get state of locals and selected gid for deleted */ 2935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(nloc, &lid_state,nloc, &lid_parent_gid)); 294c8b0795cSMark F. Adams for (lid = 0; lid < nloc; lid++) { 2950cbbd2e1SMark F. Adams lid_parent_gid[lid] = -1.0; 296c8b0795cSMark F. Adams lid_state[lid] = DELETED; 297c8b0795cSMark F. Adams } 2980cbbd2e1SMark F. Adams 2990cbbd2e1SMark F. Adams /* set lid_state */ 3000cbbd2e1SMark F. Adams for (lid = 0; lid < nloc; lid++) { 301539c167fSBarry Smith PetscCDIntNd *pos; 3025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDGetHeadPos(aggs_2,lid,&pos)); 303e78576d6SMark F. Adams if (pos) { 304e78576d6SMark F. Adams PetscInt gid1; 3052fa5cd67SKarl Rupp 3065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDIntNdGetID(pos, &gid1)); 3072c71b3e2SJacob Faibussowitsch PetscCheckFalse(gid1 != lid+my0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"gid1 %D != lid %D + my0 %D",gid1,lid,my0); 3080cbbd2e1SMark F. Adams lid_state[lid] = gid1; 309b43b03e9SMark F. Adams } 310b43b03e9SMark F. Adams } 3110cbbd2e1SMark F. Adams 3120cbbd2e1SMark F. Adams /* map local to selected local, DELETED means a ghost owns it */ 313c8b0795cSMark F. Adams for (lid=kk=0; lid<nloc; lid++) { 314c8b0795cSMark F. Adams NState state = lid_state[lid]; 315c8b0795cSMark F. Adams if (IS_SELECTED(state)) { 316539c167fSBarry Smith PetscCDIntNd *pos; 3175f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDGetHeadPos(aggs_2,lid,&pos)); 318e78576d6SMark F. Adams while (pos) { 319e78576d6SMark F. Adams PetscInt gid1; 3205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDIntNdGetID(pos, &gid1)); 3215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDGetNextPos(aggs_2,lid,&pos)); 3222fa5cd67SKarl Rupp if (gid1 >= my0 && gid1 < Iend) lid_parent_gid[gid1-my0] = (PetscScalar)(lid + my0); 323c8b0795cSMark F. Adams } 3240cbbd2e1SMark F. Adams } 3250cbbd2e1SMark F. Adams } 3260cbbd2e1SMark F. Adams /* get 'cpcol_1/2_state' & cpcol_2_par_orig - uses mpimat_1/2->lvec for temp space */ 327c8b0795cSMark F. Adams if (isMPI) { 328c8b0795cSMark F. Adams Vec tempVec; 329c8b0795cSMark F. Adams /* get 'cpcol_1_state' */ 3305f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(Gmat_1, &tempVec, NULL)); 331c8b0795cSMark F. Adams for (kk=0,j=my0; kk<nloc; kk++,j++) { 332c8b0795cSMark F. Adams PetscScalar v = (PetscScalar)lid_state[kk]; 3335f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(tempVec, 1, &j, &v, INSERT_VALUES)); 334c8b0795cSMark F. Adams } 3355f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(tempVec)); 3365f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(tempVec)); 3375f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(mpimat_1->Mvctx,tempVec, mpimat_1->lvec,INSERT_VALUES,SCATTER_FORWARD)); 3385f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(mpimat_1->Mvctx,tempVec, mpimat_1->lvec,INSERT_VALUES,SCATTER_FORWARD)); 3395f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(mpimat_1->lvec, &cpcol_1_state)); 340c8b0795cSMark F. Adams /* get 'cpcol_2_state' */ 3415f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(mpimat_2->Mvctx,tempVec, mpimat_2->lvec,INSERT_VALUES,SCATTER_FORWARD)); 3425f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(mpimat_2->Mvctx,tempVec, mpimat_2->lvec,INSERT_VALUES,SCATTER_FORWARD)); 3435f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(mpimat_2->lvec, &cpcol_2_state)); 3440cbbd2e1SMark F. Adams /* get 'cpcol_2_par_orig' */ 3450cbbd2e1SMark F. Adams for (kk=0,j=my0; kk<nloc; kk++,j++) { 3460cbbd2e1SMark F. Adams PetscScalar v = (PetscScalar)lid_parent_gid[kk]; 3475f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(tempVec, 1, &j, &v, INSERT_VALUES)); 3480cbbd2e1SMark F. Adams } 3495f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(tempVec)); 3505f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(tempVec)); 3515f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(mpimat_2->lvec, &ghost_par_orig2)); 3525f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(mpimat_2->Mvctx,tempVec, ghost_par_orig2,INSERT_VALUES,SCATTER_FORWARD)); 3535f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(mpimat_2->Mvctx,tempVec, ghost_par_orig2,INSERT_VALUES,SCATTER_FORWARD)); 3545f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(ghost_par_orig2, &cpcol_2_par_orig)); 3550cbbd2e1SMark F. Adams 3565f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&tempVec)); 357c8b0795cSMark F. Adams } /* ismpi */ 358c8b0795cSMark F. Adams for (lid=0; lid<nloc; lid++) { 359c8b0795cSMark F. Adams NState state = lid_state[lid]; 3600cbbd2e1SMark F. Adams if (IS_SELECTED(state)) { 3610cbbd2e1SMark F. Adams /* steal locals */ 362c8b0795cSMark F. Adams ii = matA_1->i; n = ii[lid+1] - ii[lid]; 363c8b0795cSMark F. Adams idx = matA_1->j + ii[lid]; 364c8b0795cSMark F. Adams for (j=0; j<n; j++) { 3650cbbd2e1SMark F. Adams PetscInt lidj = idx[j], sgid; 366c8b0795cSMark F. Adams NState statej = lid_state[lidj]; 3670cbbd2e1SMark F. Adams if (statej==DELETED && (sgid=(PetscInt)PetscRealPart(lid_parent_gid[lidj])) != lid+my0) { /* steal local */ 3680cbbd2e1SMark F. Adams lid_parent_gid[lidj] = (PetscScalar)(lid+my0); /* send this if sgid is not local */ 3690cbbd2e1SMark F. Adams if (sgid >= my0 && sgid < Iend) { /* I'm stealing this local from a local sgid */ 3700cbbd2e1SMark F. Adams PetscInt hav=0,slid=sgid-my0,gidj=lidj+my0; 371539c167fSBarry Smith PetscCDIntNd *pos,*last=NULL; 372c8b0795cSMark F. Adams /* looking for local from local so id_llist_2 works */ 3735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDGetHeadPos(aggs_2,slid,&pos)); 374e78576d6SMark F. Adams while (pos) { 375e78576d6SMark F. Adams PetscInt gid; 3765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDIntNdGetID(pos, &gid)); 3770cbbd2e1SMark F. Adams if (gid == gidj) { 378*28b400f6SJacob Faibussowitsch PetscCheck(last,PETSC_COMM_SELF,PETSC_ERR_PLIB,"last cannot be null"); 3795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDRemoveNextNode(aggs_2, slid, last)); 3805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDAppendNode(aggs_2, lid, pos)); 3810cbbd2e1SMark F. Adams hav = 1; 382c8b0795cSMark F. Adams break; 383806fa848SBarry Smith } else last = pos; 3845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDGetNextPos(aggs_2,slid,&pos)); 385c8b0795cSMark F. Adams } 386c8b0795cSMark F. Adams if (hav != 1) { 387*28b400f6SJacob Faibussowitsch PetscCheck(hav,PETSC_COMM_SELF,PETSC_ERR_PLIB,"failed to find adj in 'selected' lists - structurally unsymmetric matrix"); 38898921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"found node %D times???",hav); 389c8b0795cSMark F. Adams } 390806fa848SBarry Smith } else { /* I'm stealing this local, owned by a ghost */ 3912c71b3e2SJacob Faibussowitsch PetscCheckFalse(sgid != -1,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Mat has an un-symmetric graph. Use '-%spc_gamg_sym_graph true' to symmetrize the graph or '-%spc_gamg_threshold -1' if the matrix is structurally symmetric.",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : "",((PetscObject)pc)->prefix ? ((PetscObject)pc)->prefix : ""); 3925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDAppendID(aggs_2, lid, lidj+my0)); 393c8b0795cSMark F. Adams } 394c8b0795cSMark F. Adams } 3950cbbd2e1SMark F. Adams } /* local neighbors */ 396806fa848SBarry Smith } else if (state == DELETED && lid_cprowID_1) { 3970cbbd2e1SMark F. Adams PetscInt sgidold = (PetscInt)PetscRealPart(lid_parent_gid[lid]); 398c8b0795cSMark F. Adams /* see if I have a selected ghost neighbor that will steal me */ 399c8b0795cSMark F. Adams if ((ix=lid_cprowID_1[lid]) != -1) { 400c8b0795cSMark F. Adams ii = matB_1->compressedrow.i; n = ii[ix+1] - ii[ix]; 401c8b0795cSMark F. Adams idx = matB_1->j + ii[ix]; 402c8b0795cSMark F. Adams for (j=0; j<n; j++) { 403c8b0795cSMark F. Adams PetscInt cpid = idx[j]; 404c8b0795cSMark F. Adams NState statej = (NState)PetscRealPart(cpcol_1_state[cpid]); 405c8b0795cSMark F. Adams if (IS_SELECTED(statej) && sgidold != (PetscInt)statej) { /* ghost will steal this, remove from my list */ 4060cbbd2e1SMark F. Adams lid_parent_gid[lid] = (PetscScalar)statej; /* send who selected */ 4070cbbd2e1SMark F. Adams if (sgidold>=my0 && sgidold<Iend) { /* this was mine */ 4080cbbd2e1SMark F. Adams PetscInt hav=0,oldslidj=sgidold-my0; 409539c167fSBarry Smith PetscCDIntNd *pos,*last=NULL; 4100cbbd2e1SMark F. Adams /* remove from 'oldslidj' list */ 4115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDGetHeadPos(aggs_2,oldslidj,&pos)); 412e78576d6SMark F. Adams while (pos) { 413e78576d6SMark F. Adams PetscInt gid; 4145f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDIntNdGetID(pos, &gid)); 4150cbbd2e1SMark F. Adams if (lid+my0 == gid) { 4160cbbd2e1SMark F. Adams /* id_llist_2[lastid] = id_llist_2[flid]; /\* remove lid from oldslidj list *\/ */ 417*28b400f6SJacob Faibussowitsch PetscCheck(last,PETSC_COMM_SELF,PETSC_ERR_PLIB,"last cannot be null"); 4185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDRemoveNextNode(aggs_2, oldslidj, last)); 4190cbbd2e1SMark F. Adams /* ghost (PetscScalar)statej will add this later */ 4200cbbd2e1SMark F. Adams hav = 1; 421c8b0795cSMark F. Adams break; 422806fa848SBarry Smith } else last = pos; 4235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDGetNextPos(aggs_2,oldslidj,&pos)); 424c8b0795cSMark F. Adams } 425c8b0795cSMark F. Adams if (hav != 1) { 426*28b400f6SJacob Faibussowitsch PetscCheck(hav,PETSC_COMM_SELF,PETSC_ERR_PLIB,"failed to find adj in 'selected' lists - structurally unsymmetric matrix"); 42798921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"found node %D times???",hav); 428c8b0795cSMark F. Adams } 429806fa848SBarry Smith } else { 430d5d25401SBarry Smith /* TODO: ghosts remove this later */ 4310cbbd2e1SMark F. Adams } 432c8b0795cSMark F. Adams } 433c8b0795cSMark F. Adams } 434c8b0795cSMark F. Adams } 435c8b0795cSMark F. Adams } /* selected/deleted */ 436c8b0795cSMark F. Adams } /* node loop */ 437c8b0795cSMark F. Adams 438c8b0795cSMark F. Adams if (isMPI) { 4390cbbd2e1SMark F. Adams PetscScalar *cpcol_2_parent,*cpcol_2_gid; 4400cbbd2e1SMark F. Adams Vec tempVec,ghostgids2,ghostparents2; 4410cbbd2e1SMark F. Adams PetscInt cpid,nghost_2; 4421943db53SBarry Smith PCGAMGHashTable gid_cpid; 443c8b0795cSMark F. Adams 4445f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetSize(mpimat_2->lvec, &nghost_2)); 4455f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(Gmat_2, &tempVec, NULL)); 4460cbbd2e1SMark F. Adams 4470cbbd2e1SMark F. Adams /* get 'cpcol_2_parent' */ 448c8b0795cSMark F. Adams for (kk=0,j=my0; kk<nloc; kk++,j++) { 4495f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(tempVec, 1, &j, &lid_parent_gid[kk], INSERT_VALUES)); 450c8b0795cSMark F. Adams } 4515f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(tempVec)); 4525f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(tempVec)); 4535f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(mpimat_2->lvec, &ghostparents2)); 4545f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(mpimat_2->Mvctx,tempVec, ghostparents2,INSERT_VALUES,SCATTER_FORWARD)); 4555f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(mpimat_2->Mvctx,tempVec, ghostparents2,INSERT_VALUES,SCATTER_FORWARD)); 4565f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(ghostparents2, &cpcol_2_parent)); 4570cbbd2e1SMark F. Adams 4580cbbd2e1SMark F. Adams /* get 'cpcol_2_gid' */ 4590cbbd2e1SMark F. Adams for (kk=0,j=my0; kk<nloc; kk++,j++) { 4600cbbd2e1SMark F. Adams PetscScalar v = (PetscScalar)j; 4615f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(tempVec, 1, &j, &v, INSERT_VALUES)); 4620cbbd2e1SMark F. Adams } 4635f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(tempVec)); 4645f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(tempVec)); 4655f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(mpimat_2->lvec, &ghostgids2)); 4665f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterBegin(mpimat_2->Mvctx,tempVec, ghostgids2,INSERT_VALUES,SCATTER_FORWARD)); 4675f80ce2aSJacob Faibussowitsch CHKERRQ(VecScatterEnd(mpimat_2->Mvctx,tempVec, ghostgids2,INSERT_VALUES,SCATTER_FORWARD)); 4685f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(ghostgids2, &cpcol_2_gid)); 4695f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&tempVec)); 470c8b0795cSMark F. Adams 4710cbbd2e1SMark F. Adams /* look for deleted ghosts and add to table */ 4725f80ce2aSJacob Faibussowitsch CHKERRQ(PCGAMGHashTableCreate(2*nghost_2+1, &gid_cpid)); 4730cbbd2e1SMark F. Adams for (cpid = 0; cpid < nghost_2; cpid++) { 4740cbbd2e1SMark F. Adams NState state = (NState)PetscRealPart(cpcol_2_state[cpid]); 4750cbbd2e1SMark F. Adams if (state==DELETED) { 4760cbbd2e1SMark F. Adams PetscInt sgid_new = (PetscInt)PetscRealPart(cpcol_2_parent[cpid]); 4770cbbd2e1SMark F. Adams PetscInt sgid_old = (PetscInt)PetscRealPart(cpcol_2_par_orig[cpid]); 4780cbbd2e1SMark F. Adams if (sgid_old == -1 && sgid_new != -1) { 4790cbbd2e1SMark F. Adams PetscInt gid = (PetscInt)PetscRealPart(cpcol_2_gid[cpid]); 4805f80ce2aSJacob Faibussowitsch CHKERRQ(PCGAMGHashTableAdd(&gid_cpid, gid, cpid)); 4810cbbd2e1SMark F. Adams } 4820cbbd2e1SMark F. Adams } 4830cbbd2e1SMark F. Adams } 484c8b0795cSMark F. Adams 4850cbbd2e1SMark F. Adams /* look for deleted ghosts and see if they moved - remove it */ 486c8b0795cSMark F. Adams for (lid=0; lid<nloc; lid++) { 487c8b0795cSMark F. Adams NState state = lid_state[lid]; 488c8b0795cSMark F. Adams if (IS_SELECTED(state)) { 489539c167fSBarry Smith PetscCDIntNd *pos,*last=NULL; 490c8b0795cSMark F. Adams /* look for deleted ghosts and see if they moved */ 4915f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDGetHeadPos(aggs_2,lid,&pos)); 492e78576d6SMark F. Adams while (pos) { 493e78576d6SMark F. Adams PetscInt gid; 4945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDIntNdGetID(pos, &gid)); 495e78576d6SMark F. Adams 4960cbbd2e1SMark F. Adams if (gid < my0 || gid >= Iend) { 4975f80ce2aSJacob Faibussowitsch CHKERRQ(PCGAMGHashTableFind(&gid_cpid, gid, &cpid)); 4980cbbd2e1SMark F. Adams if (cpid != -1) { 4990cbbd2e1SMark F. Adams /* a moved ghost - */ 5000cbbd2e1SMark F. Adams /* id_llist_2[lastid] = id_llist_2[flid]; /\* remove 'flid' from list *\/ */ 5015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDRemoveNextNode(aggs_2, lid, last)); 502806fa848SBarry Smith } else last = pos; 503806fa848SBarry Smith } else last = pos; 504e78576d6SMark F. Adams 5055f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDGetNextPos(aggs_2,lid,&pos)); 506c8b0795cSMark F. Adams } /* loop over list of deleted */ 507c8b0795cSMark F. Adams } /* selected */ 508c8b0795cSMark F. Adams } 5095f80ce2aSJacob Faibussowitsch CHKERRQ(PCGAMGHashTableDestroy(&gid_cpid)); 510c8b0795cSMark F. Adams 5110cbbd2e1SMark F. Adams /* look at ghosts, see if they changed - and it */ 5120cbbd2e1SMark F. Adams for (cpid = 0; cpid < nghost_2; cpid++) { 5130cbbd2e1SMark F. Adams PetscInt sgid_new = (PetscInt)PetscRealPart(cpcol_2_parent[cpid]); 5140cbbd2e1SMark F. Adams if (sgid_new >= my0 && sgid_new < Iend) { /* this is mine */ 5150cbbd2e1SMark F. Adams PetscInt gid = (PetscInt)PetscRealPart(cpcol_2_gid[cpid]); 5160cbbd2e1SMark F. Adams PetscInt slid_new=sgid_new-my0,hav=0; 517539c167fSBarry Smith PetscCDIntNd *pos; 518539c167fSBarry Smith 5190cbbd2e1SMark F. Adams /* search for this gid to see if I have it */ 5205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDGetHeadPos(aggs_2,slid_new,&pos)); 521e78576d6SMark F. Adams while (pos) { 522e78576d6SMark F. Adams PetscInt gidj; 5235f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDIntNdGetID(pos, &gidj)); 5245f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDGetNextPos(aggs_2,slid_new,&pos)); 525e78576d6SMark F. Adams 5260cbbd2e1SMark F. Adams if (gidj == gid) { hav = 1; break; } 527c8b0795cSMark F. Adams } 528c8b0795cSMark F. Adams if (hav != 1) { 529ffc955d6SMark F. Adams /* insert 'flidj' into head of llist */ 5305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDAppendID(aggs_2, slid_new, gid)); 531c8b0795cSMark F. Adams } 532c8b0795cSMark F. Adams } 533c8b0795cSMark F. Adams } 534c8b0795cSMark F. Adams 5355f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(mpimat_1->lvec, &cpcol_1_state)); 5365f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(mpimat_2->lvec, &cpcol_2_state)); 5375f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(ghostparents2, &cpcol_2_parent)); 5385f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(ghostgids2, &cpcol_2_gid)); 5395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(lid_cprowID_1)); 5405f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&ghostgids2)); 5415f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&ghostparents2)); 5425f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&ghost_par_orig2)); 543c8b0795cSMark F. Adams } 544c8b0795cSMark F. Adams 5455f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(lid_state,lid_parent_gid)); 546c8b0795cSMark F. Adams PetscFunctionReturn(0); 547c8b0795cSMark F. Adams } 5482e68589bSMark F. Adams 5492e68589bSMark F. Adams /* -------------------------------------------------------------------------- */ 5502e68589bSMark F. Adams /* 551a2f3521dSMark F. Adams PCSetData_AGG - called if data is not set with PCSetCoordinates. 552a2f3521dSMark F. Adams Looks in Mat for near null space. 553a2f3521dSMark F. Adams Does not work for Stokes 5542e68589bSMark F. Adams 5552e68589bSMark F. Adams Input Parameter: 5562e68589bSMark F. Adams . pc - 557a2f3521dSMark F. Adams . a_A - matrix to get (near) null space out of. 5582e68589bSMark F. Adams */ 559e0877f53SBarry Smith static PetscErrorCode PCSetData_AGG(PC pc, Mat a_A) 5602e68589bSMark F. Adams { 561b8cd405aSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 562b8cd405aSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 563b8cd405aSMark F. Adams MatNullSpace mnull; 56466f2ef4bSMark Adams 565b817416eSBarry Smith PetscFunctionBegin; 5665f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetNearNullSpace(a_A, &mnull)); 567b8cd405aSMark F. Adams if (!mnull) { 56866f2ef4bSMark Adams DM dm; 5695f80ce2aSJacob Faibussowitsch CHKERRQ(PCGetDM(pc, &dm)); 57066f2ef4bSMark Adams if (!dm) { 5715f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetDM(a_A, &dm)); 57266f2ef4bSMark Adams } 57366f2ef4bSMark Adams if (dm) { 57466f2ef4bSMark Adams PetscObject deformation; 575b0d30dd6SMatthew G. Knepley PetscInt Nf; 576b0d30dd6SMatthew G. Knepley 5775f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetNumFields(dm, &Nf)); 578b0d30dd6SMatthew G. Knepley if (Nf) { 5795f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetField(dm, 0, NULL, &deformation)); 5805f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQuery((PetscObject)deformation,"nearnullspace",(PetscObject*)&mnull)); 58166f2ef4bSMark Adams if (!mnull) { 5825f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQuery((PetscObject)deformation,"nullspace",(PetscObject*)&mnull)); 58366f2ef4bSMark Adams } 58466f2ef4bSMark Adams } 58566f2ef4bSMark Adams } 586b0d30dd6SMatthew G. Knepley } 58766f2ef4bSMark Adams 58866f2ef4bSMark Adams if (!mnull) { 589a2f3521dSMark F. Adams PetscInt bs,NN,MM; 5905f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetBlockSize(a_A, &bs)); 5915f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(a_A, &MM, &NN)); 5922c71b3e2SJacob Faibussowitsch PetscCheckFalse(MM % bs,PETSC_COMM_SELF,PETSC_ERR_PLIB,"MM %D must be divisible by bs %D",MM,bs); 5935f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetCoordinates_AGG(pc, bs, MM/bs, NULL)); 594806fa848SBarry Smith } else { 595b8cd405aSMark F. Adams PetscReal *nullvec; 596b8cd405aSMark F. Adams PetscBool has_const; 597b8cd405aSMark F. Adams PetscInt i,j,mlocal,nvec,bs; 598d5d25401SBarry Smith const Vec *vecs; 599d5d25401SBarry Smith const PetscScalar *v; 600b817416eSBarry Smith 6015f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(a_A,&mlocal,NULL)); 6025f80ce2aSJacob Faibussowitsch CHKERRQ(MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs)); 603a0dea87dSMark Adams pc_gamg->data_sz = (nvec+!!has_const)*mlocal; 6045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1((nvec+!!has_const)*mlocal,&nullvec)); 605b8cd405aSMark F. Adams if (has_const) for (i=0; i<mlocal; i++) nullvec[i] = 1.0; 606b8cd405aSMark F. Adams for (i=0; i<nvec; i++) { 6075f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(vecs[i],&v)); 608b8cd405aSMark F. Adams for (j=0; j<mlocal; j++) nullvec[(i+!!has_const)*mlocal + j] = PetscRealPart(v[j]); 6095f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(vecs[i],&v)); 610b8cd405aSMark F. Adams } 611b8cd405aSMark F. Adams pc_gamg->data = nullvec; 612b8cd405aSMark F. Adams pc_gamg->data_cell_cols = (nvec+!!has_const); 6135f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetBlockSize(a_A, &bs)); 614b8cd405aSMark F. Adams pc_gamg->data_cell_rows = bs; 615b8cd405aSMark F. Adams } 6162e68589bSMark F. Adams PetscFunctionReturn(0); 6172e68589bSMark F. Adams } 6182e68589bSMark F. Adams 6192e68589bSMark F. Adams /* -------------------------------------------------------------------------- */ 6202e68589bSMark F. Adams /* 6212e68589bSMark F. Adams formProl0 6222e68589bSMark F. Adams 6232e68589bSMark F. Adams Input Parameter: 6242adfe9d3SBarry Smith . agg_llists - list of arrays with aggregates -- list from selected vertices of aggregate unselected vertices 6252adfe9d3SBarry Smith . bs - row block size 6260cbbd2e1SMark F. Adams . nSAvec - column bs of new P 6270cbbd2e1SMark F. Adams . my0crs - global index of start of locals 6282adfe9d3SBarry Smith . data_stride - bs*(nloc nodes + ghost nodes) [data_stride][nSAvec] 6292e68589bSMark F. Adams . data_in[data_stride*nSAvec] - local data on fine grid 6302e68589bSMark F. Adams . flid_fgid[data_stride/bs] - make local to global IDs, includes ghosts in 'locals_llist' 6312e68589bSMark F. Adams Output Parameter: 6322e68589bSMark F. Adams . a_data_out - in with fine grid data (w/ghosts), out with coarse grid data 6332e68589bSMark F. Adams . a_Prol - prolongation operator 6342e68589bSMark F. Adams */ 6352adfe9d3SBarry Smith static PetscErrorCode formProl0(PetscCoarsenData *agg_llists,PetscInt bs,PetscInt nSAvec,PetscInt my0crs,PetscInt data_stride,PetscReal data_in[],const PetscInt flid_fgid[],PetscReal **a_data_out,Mat a_Prol) 6362e68589bSMark F. Adams { 637bd026e97SJed Brown PetscInt Istart,my0,Iend,nloc,clid,flid = 0,aggID,kk,jj,ii,mm,nSelected,minsz,nghosts,out_data_stride; 6383b4367a7SBarry Smith MPI_Comm comm; 6392e68589bSMark F. Adams PetscReal *out_data; 640539c167fSBarry Smith PetscCDIntNd *pos; 6411943db53SBarry Smith PCGAMGHashTable fgid_flid; 6420cbbd2e1SMark F. Adams 6432e68589bSMark F. Adams PetscFunctionBegin; 6445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)a_Prol,&comm)); 6455f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRange(a_Prol, &Istart, &Iend)); 64671959b99SBarry Smith nloc = (Iend-Istart)/bs; my0 = Istart/bs; 6472c71b3e2SJacob Faibussowitsch PetscCheckFalse((Iend-Istart) % bs,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Iend %D - Istart %D must be divisible by bs %D",Iend,Istart,bs); 6480cbbd2e1SMark F. Adams Iend /= bs; 6490cbbd2e1SMark F. Adams nghosts = data_stride/bs - nloc; 6502e68589bSMark F. Adams 6515f80ce2aSJacob Faibussowitsch CHKERRQ(PCGAMGHashTableCreate(2*nghosts+1, &fgid_flid)); 6520cbbd2e1SMark F. Adams for (kk=0; kk<nghosts; kk++) { 6535f80ce2aSJacob Faibussowitsch CHKERRQ(PCGAMGHashTableAdd(&fgid_flid, flid_fgid[nloc+kk], nloc+kk)); 6542e68589bSMark F. Adams } 6552e68589bSMark F. Adams 6560cbbd2e1SMark F. Adams /* count selected -- same as number of cols of P */ 6570cbbd2e1SMark F. Adams for (nSelected=mm=0; mm<nloc; mm++) { 658e78576d6SMark F. Adams PetscBool ise; 6595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDEmptyAt(agg_llists, mm, &ise)); 660e78576d6SMark F. Adams if (!ise) nSelected++; 6610cbbd2e1SMark F. Adams } 6625f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRangeColumn(a_Prol, &ii, &jj)); 6632c71b3e2SJacob Faibussowitsch PetscCheckFalse((ii/nSAvec) != my0crs,PETSC_COMM_SELF,PETSC_ERR_PLIB,"ii %D /nSAvec %D != my0crs %D",ii,nSAvec,my0crs); 6642c71b3e2SJacob Faibussowitsch PetscCheckFalse(nSelected != (jj-ii)/nSAvec,PETSC_COMM_SELF,PETSC_ERR_PLIB,"nSelected %D != (jj %D - ii %D)/nSAvec %D",nSelected,jj,ii,nSAvec); 6650cbbd2e1SMark F. Adams 6662e68589bSMark F. Adams /* aloc space for coarse point data (output) */ 6670cbbd2e1SMark F. Adams out_data_stride = nSelected*nSAvec; 6682fa5cd67SKarl Rupp 6695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(out_data_stride*nSAvec, &out_data)); 67033812677SSatish Balay for (ii=0;ii<out_data_stride*nSAvec;ii++) out_data[ii]=PETSC_MAX_REAL; 6710cbbd2e1SMark F. Adams *a_data_out = out_data; /* output - stride nSelected*nSAvec */ 6722e68589bSMark F. Adams 6732e68589bSMark F. Adams /* find points and set prolongation */ 674c8b0795cSMark F. Adams minsz = 100; 6750cbbd2e1SMark F. Adams for (mm = clid = 0; mm < nloc; mm++) { 6765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDSizeAt(agg_llists, mm, &jj)); 677e78576d6SMark F. Adams if (jj > 0) { 6780cbbd2e1SMark F. Adams const PetscInt lid = mm, cgid = my0crs + clid; 6790cbbd2e1SMark F. Adams PetscInt cids[100]; /* max bs */ 6800cbbd2e1SMark F. Adams PetscBLASInt asz =jj,M=asz*bs,N=nSAvec,INFO; 6812e68589bSMark F. Adams PetscBLASInt Mdata=M+((N-M>0) ? N-M : 0),LDA=Mdata,LWORK=N*bs; 6822e68589bSMark F. Adams PetscScalar *qqc,*qqr,*TAU,*WORK; 6832e68589bSMark F. Adams PetscInt *fids; 68465d7b583SSatish Balay PetscReal *data; 685b817416eSBarry Smith 6860cbbd2e1SMark F. Adams /* count agg */ 6870cbbd2e1SMark F. Adams if (asz<minsz) minsz = asz; 6880cbbd2e1SMark F. Adams 6890cbbd2e1SMark F. Adams /* get block */ 6905f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc5(Mdata*N, &qqc,M*N, &qqr,N, &TAU,LWORK, &WORK,M, &fids)); 6912e68589bSMark F. Adams 6922e68589bSMark F. Adams aggID = 0; 6935f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDGetHeadPos(agg_llists,lid,&pos)); 694e78576d6SMark F. Adams while (pos) { 695e78576d6SMark F. Adams PetscInt gid1; 6965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDIntNdGetID(pos, &gid1)); 6975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDGetNextPos(agg_llists,lid,&pos)); 698e78576d6SMark F. Adams 6990cbbd2e1SMark F. Adams if (gid1 >= my0 && gid1 < Iend) flid = gid1 - my0; 7000cbbd2e1SMark F. Adams else { 7015f80ce2aSJacob Faibussowitsch CHKERRQ(PCGAMGHashTableFind(&fgid_flid, gid1, &flid)); 7022c71b3e2SJacob Faibussowitsch PetscCheckFalse(flid < 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot find gid1 in table"); 7030cbbd2e1SMark F. Adams } 7042e68589bSMark F. Adams /* copy in B_i matrix - column oriented */ 70565d7b583SSatish Balay data = &data_in[flid*bs]; 7063d3eaba7SBarry Smith for (ii = 0; ii < bs; ii++) { 7072e68589bSMark F. Adams for (jj = 0; jj < N; jj++) { 7080cbbd2e1SMark F. Adams PetscReal d = data[jj*data_stride + ii]; 7090cbbd2e1SMark F. Adams qqc[jj*Mdata + aggID*bs + ii] = d; 7102e68589bSMark F. Adams } 7112e68589bSMark F. Adams } 7122e68589bSMark F. Adams /* set fine IDs */ 7132e68589bSMark F. Adams for (kk=0; kk<bs; kk++) fids[aggID*bs + kk] = flid_fgid[flid]*bs + kk; 7142e68589bSMark F. Adams aggID++; 7150cbbd2e1SMark F. Adams } 7162e68589bSMark F. Adams 7172e68589bSMark F. Adams /* pad with zeros */ 7182e68589bSMark F. Adams for (ii = asz*bs; ii < Mdata; ii++) { 7192e68589bSMark F. Adams for (jj = 0; jj < N; jj++, kk++) { 7202e68589bSMark F. Adams qqc[jj*Mdata + ii] = .0; 7212e68589bSMark F. Adams } 7222e68589bSMark F. Adams } 7232e68589bSMark F. Adams 7242e68589bSMark F. Adams /* QR */ 7255f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7268b83055fSJed Brown PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Mdata, &N, qqc, &LDA, TAU, WORK, &LWORK, &INFO)); 7275f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFPTrapPop()); 7282c71b3e2SJacob Faibussowitsch PetscCheckFalse(INFO != 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"xGEQRF error"); 7292e68589bSMark F. Adams /* get R - column oriented - output B_{i+1} */ 7302e68589bSMark F. Adams { 7312e68589bSMark F. Adams PetscReal *data = &out_data[clid*nSAvec]; 7322e68589bSMark F. Adams for (jj = 0; jj < nSAvec; jj++) { 7332e68589bSMark F. Adams for (ii = 0; ii < nSAvec; ii++) { 7342c71b3e2SJacob Faibussowitsch PetscCheckFalse(data[jj*out_data_stride + ii] != PETSC_MAX_REAL,PETSC_COMM_SELF,PETSC_ERR_PLIB,"data[jj*out_data_stride + ii] != %e",(double)PETSC_MAX_REAL); 7350cbbd2e1SMark F. Adams if (ii <= jj) data[jj*out_data_stride + ii] = PetscRealPart(qqc[jj*Mdata + ii]); 7360cbbd2e1SMark F. Adams else data[jj*out_data_stride + ii] = 0.; 7372e68589bSMark F. Adams } 7382e68589bSMark F. Adams } 7392e68589bSMark F. Adams } 7402e68589bSMark F. Adams 7412e68589bSMark F. Adams /* get Q - row oriented */ 742c964aadfSJose E. Roman PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Mdata, &N, &N, qqc, &LDA, TAU, WORK, &LWORK, &INFO)); 7432c71b3e2SJacob Faibussowitsch PetscCheckFalse(INFO != 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"xORGQR error arg %d",-INFO); 7442e68589bSMark F. Adams 7452e68589bSMark F. Adams for (ii = 0; ii < M; ii++) { 7462e68589bSMark F. Adams for (jj = 0; jj < N; jj++) { 7472e68589bSMark F. Adams qqr[N*ii + jj] = qqc[jj*Mdata + ii]; 7482e68589bSMark F. Adams } 7492e68589bSMark F. Adams } 7502e68589bSMark F. Adams 7512e68589bSMark F. Adams /* add diagonal block of P0 */ 752c8b0795cSMark F. Adams for (kk=0; kk<N; kk++) { 753c8b0795cSMark F. Adams cids[kk] = N*cgid + kk; /* global col IDs in P0 */ 754c8b0795cSMark F. Adams } 7555f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(a_Prol,M,fids,N,cids,qqr,INSERT_VALUES)); 7565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree5(qqc,qqr,TAU,WORK,fids)); 757b43b03e9SMark F. Adams clid++; 7580cbbd2e1SMark F. Adams } /* coarse agg */ 7590cbbd2e1SMark F. Adams } /* for all fine nodes */ 7605f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(a_Prol,MAT_FINAL_ASSEMBLY)); 7615f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(a_Prol,MAT_FINAL_ASSEMBLY)); 7625f80ce2aSJacob Faibussowitsch CHKERRQ(PCGAMGHashTableDestroy(&fgid_flid)); 7632e68589bSMark F. Adams PetscFunctionReturn(0); 7642e68589bSMark F. Adams } 7652e68589bSMark F. Adams 7665adeb434SBarry Smith static PetscErrorCode PCView_GAMG_AGG(PC pc,PetscViewer viewer) 7675adeb434SBarry Smith { 7685adeb434SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 7695adeb434SBarry Smith PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 7705adeb434SBarry Smith PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 7715adeb434SBarry Smith 7725adeb434SBarry Smith PetscFunctionBegin; 7735f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer," AGG specific options\n")); 7745f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer," Symmetric graph %s\n",pc_gamg_agg->sym_graph ? "true" : "false")); 7755f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer," Number of levels to square graph %D\n",pc_gamg_agg->square_graph)); 7765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerASCIIPrintf(viewer," Number smoothing steps %D\n",pc_gamg_agg->nsmooths)); 7775adeb434SBarry Smith PetscFunctionReturn(0); 7785adeb434SBarry Smith } 7795adeb434SBarry Smith 7802e68589bSMark F. Adams /* -------------------------------------------------------------------------- */ 7812e68589bSMark F. Adams /* 782fd1112cbSBarry Smith PCGAMGGraph_AGG 7832e68589bSMark F. Adams 7842e68589bSMark F. Adams Input Parameter: 7852e68589bSMark F. Adams . pc - this 7862e68589bSMark F. Adams . Amat - matrix on this fine level 7872e68589bSMark F. Adams Output Parameter: 788c8b0795cSMark F. Adams . a_Gmat - 7892e68589bSMark F. Adams */ 790e0877f53SBarry Smith static PetscErrorCode PCGAMGGraph_AGG(PC pc,Mat Amat,Mat *a_Gmat) 791c8b0795cSMark F. Adams { 792c8b0795cSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 793c8b0795cSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 794c1eae691SMark Adams const PetscReal vfilter = pc_gamg->threshold[pc_gamg->current_level]; 795c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 796e0940f08SMark F. Adams Mat Gmat; 7973b4367a7SBarry Smith MPI_Comm comm; 79867744fedSMark F. Adams PetscBool /* set,flg , */ symm; 799c8b0795cSMark F. Adams 800c8b0795cSMark F. Adams PetscFunctionBegin; 8015f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)Amat,&comm)); 8025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PC_GAMGGraph_AGG,0,0,0,0)); 803c8b0795cSMark F. Adams 8045f80ce2aSJacob Faibussowitsch /* CHKERRQ(MatIsSymmetricKnown(Amat, &set, &flg)); || !(set && flg) -- this causes lot of symm calls */ 805c666adbfSMark F. Adams symm = (PetscBool)(pc_gamg_agg->sym_graph); /* && !pc_gamg_agg->square_graph; */ 8060cbbd2e1SMark F. Adams 8075f80ce2aSJacob Faibussowitsch CHKERRQ(PCGAMGCreateGraph(Amat, &Gmat)); 8085f80ce2aSJacob Faibussowitsch CHKERRQ(PCGAMGFilterGraph(&Gmat, vfilter, symm)); 809e0940f08SMark F. Adams *a_Gmat = Gmat; 8105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PC_GAMGGraph_AGG,0,0,0,0)); 811c8b0795cSMark F. Adams PetscFunctionReturn(0); 812c8b0795cSMark F. Adams } 813c8b0795cSMark F. Adams 814c8b0795cSMark F. Adams /* -------------------------------------------------------------------------- */ 815c8b0795cSMark F. Adams /* 816b43b03e9SMark F. Adams PCGAMGCoarsen_AGG 817c8b0795cSMark F. Adams 818c8b0795cSMark F. Adams Input Parameter: 819e0940f08SMark F. Adams . a_pc - this 820e0940f08SMark F. Adams Input/Output Parameter: 8210cbbd2e1SMark F. Adams . a_Gmat1 - graph on this fine level - coarsening can change this (squares it) 822c8b0795cSMark F. Adams Output Parameter: 8230cbbd2e1SMark F. Adams . agg_lists - list of aggregates 824c8b0795cSMark F. Adams */ 825e0877f53SBarry Smith static PetscErrorCode PCGAMGCoarsen_AGG(PC a_pc,Mat *a_Gmat1,PetscCoarsenData **agg_lists) 826c8b0795cSMark F. Adams { 827e0940f08SMark F. Adams PC_MG *mg = (PC_MG*)a_pc->data; 828c8b0795cSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 829c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 8300cbbd2e1SMark F. Adams Mat mat,Gmat2, Gmat1 = *a_Gmat1; /* squared graph */ 8310cbbd2e1SMark F. Adams IS perm; 8325cfd4bd9SMark Adams PetscInt Istart,Iend,Ii,nloc,bs,n,m; 833c8b0795cSMark F. Adams PetscInt *permute; 834c8b0795cSMark F. Adams PetscBool *bIndexSet; 835b43b03e9SMark F. Adams MatCoarsen crs; 8363b4367a7SBarry Smith MPI_Comm comm; 837aea53286SMark Adams PetscReal hashfact; 838e2c00dcbSBarry Smith PetscInt iSwapIndex; 8393b50add6SMark Adams PetscRandom random; 840c8b0795cSMark F. Adams 841c8b0795cSMark F. Adams PetscFunctionBegin; 8425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PC_GAMGCoarsen_AGG,0,0,0,0)); 8435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)Gmat1,&comm)); 8445f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(Gmat1, &n, &m)); 8455f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetBlockSize(Gmat1, &bs)); 8462c71b3e2SJacob Faibussowitsch PetscCheckFalse(bs != 1,PETSC_COMM_SELF,PETSC_ERR_PLIB,"bs %D must be 1",bs); 847c8b0795cSMark F. Adams nloc = n/bs; 848c8b0795cSMark F. Adams 8499ab59c8bSMark Adams if (pc_gamg->current_level < pc_gamg_agg->square_graph) { 8505f80ce2aSJacob Faibussowitsch CHKERRQ(PCGAMGSquareGraph_GAMG(a_pc,Gmat1,&Gmat2)); 851806fa848SBarry Smith } else Gmat2 = Gmat1; 852c8b0795cSMark F. Adams 8535cfd4bd9SMark Adams /* get MIS aggs - randomize */ 8545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nloc, &permute)); 8555f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(nloc, &bIndexSet)); 8566e09b0e3SStefano Zampini for (Ii = 0; Ii < nloc; Ii++) permute[Ii] = Ii; 8575f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomCreate(PETSC_COMM_SELF,&random)); 8585f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRange(Gmat1, &Istart, &Iend)); 859c8b0795cSMark F. Adams for (Ii = 0; Ii < nloc; Ii++) { 8605f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomGetValueReal(random,&hashfact)); 861aea53286SMark Adams iSwapIndex = (PetscInt) (hashfact*nloc)%nloc; 862c8b0795cSMark F. Adams if (!bIndexSet[iSwapIndex] && iSwapIndex != Ii) { 863c8b0795cSMark F. Adams PetscInt iTemp = permute[iSwapIndex]; 864c8b0795cSMark F. Adams permute[iSwapIndex] = permute[Ii]; 865c8b0795cSMark F. Adams permute[Ii] = iTemp; 866c8b0795cSMark F. Adams bIndexSet[iSwapIndex] = PETSC_TRUE; 867c8b0795cSMark F. Adams } 868c8b0795cSMark F. Adams } 8695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(bIndexSet)); 8705f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRandomDestroy(&random)); 8715f80ce2aSJacob Faibussowitsch CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF, nloc, permute, PETSC_USE_POINTER, &perm)); 8725f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(petsc_gamg_setup_events[SET4],0,0,0,0)); 8735f80ce2aSJacob Faibussowitsch CHKERRQ(MatCoarsenCreate(comm, &crs)); 8745f80ce2aSJacob Faibussowitsch CHKERRQ(MatCoarsenSetFromOptions(crs)); 8755f80ce2aSJacob Faibussowitsch CHKERRQ(MatCoarsenSetGreedyOrdering(crs, perm)); 8765f80ce2aSJacob Faibussowitsch CHKERRQ(MatCoarsenSetAdjacency(crs, Gmat2)); 8775f80ce2aSJacob Faibussowitsch CHKERRQ(MatCoarsenSetStrictAggs(crs, PETSC_TRUE)); 8785f80ce2aSJacob Faibussowitsch CHKERRQ(MatCoarsenApply(crs)); 8795f80ce2aSJacob Faibussowitsch CHKERRQ(MatCoarsenGetData(crs, agg_lists)); /* output */ 8805f80ce2aSJacob Faibussowitsch CHKERRQ(MatCoarsenDestroy(&crs)); 881b43b03e9SMark F. Adams 8825f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&perm)); 8835f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(permute)); 8845f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(petsc_gamg_setup_events[SET4],0,0,0,0)); 8859f3f12c8SMark F. Adams 886c8b0795cSMark F. Adams /* smooth aggs */ 887e0940f08SMark F. Adams if (Gmat2 != Gmat1) { 8880cbbd2e1SMark F. Adams const PetscCoarsenData *llist = *agg_lists; 8895f80ce2aSJacob Faibussowitsch CHKERRQ(smoothAggs(a_pc,Gmat2, Gmat1, *agg_lists)); 8905f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Gmat1)); 891e0940f08SMark F. Adams *a_Gmat1 = Gmat2; /* output */ 8925f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDGetMat(llist, &mat)); 893*28b400f6SJacob Faibussowitsch PetscCheck(!mat,comm,PETSC_ERR_ARG_WRONG, "Auxilary matrix with squared graph????"); 894806fa848SBarry Smith } else { 8950cbbd2e1SMark F. Adams const PetscCoarsenData *llist = *agg_lists; 8969ab59c8bSMark Adams /* see if we have a matrix that takes precedence (returned from MatCoarsenApply) */ 8975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDGetMat(llist, &mat)); 8980cbbd2e1SMark F. Adams if (mat) { 8995f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Gmat1)); 9000cbbd2e1SMark F. Adams *a_Gmat1 = mat; /* output */ 9010cbbd2e1SMark F. Adams } 9020cbbd2e1SMark F. Adams } 9035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PC_GAMGCoarsen_AGG,0,0,0,0)); 904c8b0795cSMark F. Adams PetscFunctionReturn(0); 905c8b0795cSMark F. Adams } 906c8b0795cSMark F. Adams 907c8b0795cSMark F. Adams /* -------------------------------------------------------------------------- */ 908c8b0795cSMark F. Adams /* 9090cbbd2e1SMark F. Adams PCGAMGProlongator_AGG 910c8b0795cSMark F. Adams 911c8b0795cSMark F. Adams Input Parameter: 912c8b0795cSMark F. Adams . pc - this 913c8b0795cSMark F. Adams . Amat - matrix on this fine level 914c8b0795cSMark F. Adams . Graph - used to get ghost data for nodes in 9150cbbd2e1SMark F. Adams . agg_lists - list of aggregates 916c8b0795cSMark F. Adams Output Parameter: 917c8b0795cSMark F. Adams . a_P_out - prolongation operator to the next level 918c8b0795cSMark F. Adams */ 919e0877f53SBarry Smith static PetscErrorCode PCGAMGProlongator_AGG(PC pc,Mat Amat,Mat Gmat,PetscCoarsenData *agg_lists,Mat *a_P_out) 9202e68589bSMark F. Adams { 9212e68589bSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 9222e68589bSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 9234a2f8832SBarry Smith const PetscInt col_bs = pc_gamg->data_cell_cols; 924c8b0795cSMark F. Adams PetscInt Istart,Iend,nloc,ii,jj,kk,my0,nLocalSelected,bs; 925c8b0795cSMark F. Adams Mat Prol; 926d5d25401SBarry Smith PetscMPIInt size; 9273b4367a7SBarry Smith MPI_Comm comm; 928c8b0795cSMark F. Adams PetscReal *data_w_ghost; 929c8b0795cSMark F. Adams PetscInt myCrs0, nbnodes=0, *flid_fgid; 930d9558ea9SBarry Smith MatType mtype; 9312e68589bSMark F. Adams 9322e68589bSMark F. Adams PetscFunctionBegin; 9335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)Amat,&comm)); 9342c71b3e2SJacob Faibussowitsch PetscCheckFalse(col_bs < 1,comm,PETSC_ERR_PLIB,"Column bs cannot be less than 1"); 9355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PC_GAMGProlongator_AGG,0,0,0,0)); 9365f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_size(comm, &size)); 9375f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRange(Amat, &Istart, &Iend)); 9385f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetBlockSize(Amat, &bs)); 93971959b99SBarry Smith nloc = (Iend-Istart)/bs; my0 = Istart/bs; 9402c71b3e2SJacob Faibussowitsch PetscCheckFalse((Iend-Istart) % bs,PETSC_COMM_SELF,PETSC_ERR_PLIB,"(Iend %D - Istart %D) not divisible by bs %D",Iend,Istart,bs); 9412e68589bSMark F. Adams 9422e68589bSMark F. Adams /* get 'nLocalSelected' */ 9430cbbd2e1SMark F. Adams for (ii=0, nLocalSelected = 0; ii < nloc; ii++) { 944e78576d6SMark F. Adams PetscBool ise; 9450cbbd2e1SMark F. Adams /* filter out singletons 0 or 1? */ 9465f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCDEmptyAt(agg_lists, ii, &ise)); 947e78576d6SMark F. Adams if (!ise) nLocalSelected++; 9482e68589bSMark F. Adams } 9492e68589bSMark F. Adams 9502e68589bSMark F. Adams /* create prolongator, create P matrix */ 9515f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetType(Amat,&mtype)); 9525f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(comm, &Prol)); 9535f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetSizes(Prol,nloc*bs,nLocalSelected*col_bs,PETSC_DETERMINE,PETSC_DETERMINE)); 9545f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetBlockSizes(Prol, bs, col_bs)); 9555f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(Prol, mtype)); 9565f80ce2aSJacob Faibussowitsch CHKERRQ(MatSeqAIJSetPreallocation(Prol,col_bs, NULL)); 9575f80ce2aSJacob Faibussowitsch CHKERRQ(MatMPIAIJSetPreallocation(Prol,col_bs, NULL, col_bs, NULL)); 9582e68589bSMark F. Adams 9592e68589bSMark F. Adams /* can get all points "removed" */ 9605f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(Prol, &kk, &ii)); 9617f66b68fSMark Adams if (!ii) { 9625f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(pc,"%s: No selected points on coarse grid\n")); 9635f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Prol)); 9640298fd71SBarry Smith *a_P_out = NULL; /* out */ 9655f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PC_GAMGProlongator_AGG,0,0,0,0)); 9662e68589bSMark F. Adams PetscFunctionReturn(0); 9672e68589bSMark F. Adams } 9685f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(pc,"%s: New grid %D nodes\n",((PetscObject)pc)->prefix,ii/col_bs)); 9695f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRangeColumn(Prol, &myCrs0, &kk)); 9700cbbd2e1SMark F. Adams 9712c71b3e2SJacob Faibussowitsch PetscCheckFalse((kk-myCrs0) % col_bs,PETSC_COMM_SELF,PETSC_ERR_PLIB,"(kk %D -myCrs0 %D) not divisible by col_bs %D",kk,myCrs0,col_bs); 972c8b0795cSMark F. Adams myCrs0 = myCrs0/col_bs; 9732c71b3e2SJacob Faibussowitsch PetscCheckFalse((kk/col_bs-myCrs0) != nLocalSelected,PETSC_COMM_SELF,PETSC_ERR_PLIB,"(kk %D/col_bs %D - myCrs0 %D) != nLocalSelected %D)",kk,col_bs,myCrs0,nLocalSelected); 9742e68589bSMark F. Adams 9752e68589bSMark F. Adams /* create global vector of data in 'data_w_ghost' */ 9765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(petsc_gamg_setup_events[SET7],0,0,0,0)); 977c5df96a5SBarry Smith if (size > 1) { /* */ 9782e68589bSMark F. Adams PetscReal *tmp_gdata,*tmp_ldata,*tp2; 9795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nloc, &tmp_ldata)); 9804a2f8832SBarry Smith for (jj = 0; jj < col_bs; jj++) { 981c8b0795cSMark F. Adams for (kk = 0; kk < bs; kk++) { 982a2f3521dSMark F. Adams PetscInt ii,stride; 983c8b0795cSMark F. Adams const PetscReal *tp = pc_gamg->data + jj*bs*nloc + kk; 9842fa5cd67SKarl Rupp for (ii = 0; ii < nloc; ii++, tp += bs) tmp_ldata[ii] = *tp; 9852fa5cd67SKarl Rupp 9865f80ce2aSJacob Faibussowitsch CHKERRQ(PCGAMGGetDataWithGhosts(Gmat, 1, tmp_ldata, &stride, &tmp_gdata)); 987a2f3521dSMark F. Adams 9887f66b68fSMark Adams if (!jj && !kk) { /* now I know how many todal nodes - allocate */ 9895f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(stride*bs*col_bs, &data_w_ghost)); 990a2f3521dSMark F. Adams nbnodes = bs*stride; 9912e68589bSMark F. Adams } 992a2f3521dSMark F. Adams tp2 = data_w_ghost + jj*bs*stride + kk; 9932fa5cd67SKarl Rupp for (ii = 0; ii < stride; ii++, tp2 += bs) *tp2 = tmp_gdata[ii]; 9945f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(tmp_gdata)); 9952e68589bSMark F. Adams } 9962e68589bSMark F. Adams } 9975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(tmp_ldata)); 998806fa848SBarry Smith } else { 999c8b0795cSMark F. Adams nbnodes = bs*nloc; 1000c8b0795cSMark F. Adams data_w_ghost = (PetscReal*)pc_gamg->data; 10012e68589bSMark F. Adams } 10022e68589bSMark F. Adams 10032e68589bSMark F. Adams /* get P0 */ 1004c5df96a5SBarry Smith if (size > 1) { 10052e68589bSMark F. Adams PetscReal *fid_glid_loc,*fiddata; 1006a2f3521dSMark F. Adams PetscInt stride; 10072e68589bSMark F. Adams 10085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nloc, &fid_glid_loc)); 10092e68589bSMark F. Adams for (kk=0; kk<nloc; kk++) fid_glid_loc[kk] = (PetscReal)(my0+kk); 10105f80ce2aSJacob Faibussowitsch CHKERRQ(PCGAMGGetDataWithGhosts(Gmat, 1, fid_glid_loc, &stride, &fiddata)); 10115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(stride, &flid_fgid)); 1012a2f3521dSMark F. Adams for (kk=0; kk<stride; kk++) flid_fgid[kk] = (PetscInt)fiddata[kk]; 10135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(fiddata)); 1014a2f3521dSMark F. Adams 10152c71b3e2SJacob Faibussowitsch PetscCheckFalse(stride != nbnodes/bs,PETSC_COMM_SELF,PETSC_ERR_PLIB,"stride %D != nbnodes %D/bs %D",stride,nbnodes,bs); 10165f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(fid_glid_loc)); 1017806fa848SBarry Smith } else { 10185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(nloc, &flid_fgid)); 10192e68589bSMark F. Adams for (kk=0; kk<nloc; kk++) flid_fgid[kk] = my0 + kk; 10202e68589bSMark F. Adams } 10215f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(petsc_gamg_setup_events[SET7],0,0,0,0)); 10225f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(petsc_gamg_setup_events[SET8],0,0,0,0)); 1023c8b0795cSMark F. Adams { 10240298fd71SBarry Smith PetscReal *data_out = NULL; 10255f80ce2aSJacob Faibussowitsch CHKERRQ(formProl0(agg_lists, bs, col_bs, myCrs0, nbnodes,data_w_ghost, flid_fgid, &data_out, Prol)); 10265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(pc_gamg->data)); 10272fa5cd67SKarl Rupp 1028c8b0795cSMark F. Adams pc_gamg->data = data_out; 10294a2f8832SBarry Smith pc_gamg->data_cell_rows = col_bs; 10304a2f8832SBarry Smith pc_gamg->data_sz = col_bs*col_bs*nLocalSelected; 1031c8b0795cSMark F. Adams } 10325f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(petsc_gamg_setup_events[SET8],0,0,0,0)); 10335f80ce2aSJacob Faibussowitsch if (size > 1) CHKERRQ(PetscFree(data_w_ghost)); 10345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(flid_fgid)); 10352e68589bSMark F. Adams 1036c8b0795cSMark F. Adams *a_P_out = Prol; /* out */ 1037ed4e82eaSPeter Brune 10385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PC_GAMGProlongator_AGG,0,0,0,0)); 1039c8b0795cSMark F. Adams PetscFunctionReturn(0); 1040c8b0795cSMark F. Adams } 1041c8b0795cSMark F. Adams 1042c8b0795cSMark F. Adams /* -------------------------------------------------------------------------- */ 1043c8b0795cSMark F. Adams /* 1044fd1112cbSBarry Smith PCGAMGOptProlongator_AGG 1045c8b0795cSMark F. Adams 1046c8b0795cSMark F. Adams Input Parameter: 1047c8b0795cSMark F. Adams . pc - this 1048c8b0795cSMark F. Adams . Amat - matrix on this fine level 1049c8b0795cSMark F. Adams In/Output Parameter: 10502a808120SBarry Smith . a_P - prolongation operator to the next level 1051c8b0795cSMark F. Adams */ 1052e0877f53SBarry Smith static PetscErrorCode PCGAMGOptProlongator_AGG(PC pc,Mat Amat,Mat *a_P) 1053c8b0795cSMark F. Adams { 1054c8b0795cSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 1055c8b0795cSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 1056c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 1057c8b0795cSMark F. Adams PetscInt jj; 1058c8b0795cSMark F. Adams Mat Prol = *a_P; 10593b4367a7SBarry Smith MPI_Comm comm; 10602a808120SBarry Smith KSP eksp; 10612a808120SBarry Smith Vec bb, xx; 10622a808120SBarry Smith PC epc; 10632a808120SBarry Smith PetscReal alpha, emax, emin; 1064c8b0795cSMark F. Adams 1065c8b0795cSMark F. Adams PetscFunctionBegin; 10665f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectGetComm((PetscObject)Amat,&comm)); 10675f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(PC_GAMGOptProlongator_AGG,0,0,0,0)); 1068c8b0795cSMark F. Adams 1069d5d25401SBarry Smith /* compute maximum singular value of operator to be used in smoother */ 10702a808120SBarry Smith if (0 < pc_gamg_agg->nsmooths) { 107118c3aa7eSMark /* get eigen estimates */ 107218c3aa7eSMark if (pc_gamg->emax > 0) { 107318c3aa7eSMark emin = pc_gamg->emin; 107418c3aa7eSMark emax = pc_gamg->emax; 107518c3aa7eSMark } else { 10760ed2132dSStefano Zampini const char *prefix; 10770ed2132dSStefano Zampini 10785f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(Amat, &bb, NULL)); 10795f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(Amat, &xx, NULL)); 10805f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetNoisy_Private(bb)); 1081e696ed0bSMark F. Adams 10825f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCreate(comm,&eksp)); 10835f80ce2aSJacob Faibussowitsch CHKERRQ(PCGetOptionsPrefix(pc,&prefix)); 10845f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOptionsPrefix(eksp,prefix)); 10855f80ce2aSJacob Faibussowitsch CHKERRQ(KSPAppendOptionsPrefix(eksp,"pc_gamg_esteig_")); 108673f7197eSJed Brown { 1087acbb5b45SJed Brown PetscBool sflg; 10885f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOption(Amat, MAT_SPD, &sflg)); 108990db8557SMark Adams if (sflg) { 10905f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetType(eksp, KSPCG)); 1091d24ecf33SMark } 1092d24ecf33SMark } 10935f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetErrorIfNotConverged(eksp,pc->erroriffailure)); 10945f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetNormType(eksp, KSP_NORM_NONE)); 1095c2436cacSMark F. Adams 10965f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetInitialGuessNonzero(eksp, PETSC_FALSE)); 10975f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(eksp, Amat, Amat)); 10982e68589bSMark F. Adams 10995f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(eksp, &epc)); 11005f80ce2aSJacob Faibussowitsch CHKERRQ(PCSetType(epc, PCJACOBI)); /* smoother in smoothed agg. */ 1101c2436cacSMark F. Adams 11025f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetTolerances(eksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT, 10)); // 10 is safer, but 5 is often fine, can override with -pc_gamg_esteig_ksp_max_it -mg_levels_ksp_chebyshev_esteig 0,0.25,0,1.2 1103074aec55SMark Adams 11045f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetFromOptions(eksp)); 11055f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetComputeSingularValues(eksp,PETSC_TRUE)); 11065f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolve(eksp, bb, xx)); 11075f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCheckSolve(eksp,pc,xx)); 11082e68589bSMark F. Adams 11095f80ce2aSJacob Faibussowitsch CHKERRQ(KSPComputeExtremeSingularValues(eksp, &emax, &emin)); 11105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(pc,"%s: Smooth P0: max eigen=%e min=%e PC=%s\n",((PetscObject)pc)->prefix,(double)emax,(double)emin,PCJACOBI)); 11115f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&xx)); 11125f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&bb)); 11135f80ce2aSJacob Faibussowitsch CHKERRQ(KSPDestroy(&eksp)); 11142e68589bSMark F. Adams } 111518c3aa7eSMark if (pc_gamg->use_sa_esteig) { 111618c3aa7eSMark mg->min_eigen_DinvA[pc_gamg->current_level] = emin; 111718c3aa7eSMark mg->max_eigen_DinvA[pc_gamg->current_level] = emax; 11185f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(pc,"%s: Smooth P0: level %D, cache spectra %g %g\n",((PetscObject)pc)->prefix,pc_gamg->current_level,(double)emin,(double)emax)); 111918c3aa7eSMark } else { 112018c3aa7eSMark mg->min_eigen_DinvA[pc_gamg->current_level] = 0; 112118c3aa7eSMark mg->max_eigen_DinvA[pc_gamg->current_level] = 0; 112218c3aa7eSMark } 112318c3aa7eSMark } else { 112418c3aa7eSMark mg->min_eigen_DinvA[pc_gamg->current_level] = 0; 112518c3aa7eSMark mg->max_eigen_DinvA[pc_gamg->current_level] = 0; 112618c3aa7eSMark } 11272e68589bSMark F. Adams 11282a808120SBarry Smith /* smooth P0 */ 11292a808120SBarry Smith for (jj = 0; jj < pc_gamg_agg->nsmooths; jj++) { 11302a808120SBarry Smith Mat tMat; 11312a808120SBarry Smith Vec diag; 11322a808120SBarry Smith 11335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(petsc_gamg_setup_events[SET9],0,0,0,0)); 11342a808120SBarry Smith 11352e68589bSMark F. Adams /* smooth P1 := (I - omega/lam D^{-1}A)P0 */ 11365f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(petsc_gamg_setup_matmat_events[pc_gamg->current_level][2],0,0,0,0)); 11375f80ce2aSJacob Faibussowitsch CHKERRQ(MatMatMult(Amat, Prol, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &tMat)); 11385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(petsc_gamg_setup_matmat_events[pc_gamg->current_level][2],0,0,0,0)); 11395f80ce2aSJacob Faibussowitsch CHKERRQ(MatProductClear(tMat)); 11405f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateVecs(Amat, &diag, NULL)); 11415f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetDiagonal(Amat, diag)); /* effectively PCJACOBI */ 11425f80ce2aSJacob Faibussowitsch CHKERRQ(VecReciprocal(diag)); 11435f80ce2aSJacob Faibussowitsch CHKERRQ(MatDiagonalScale(tMat, diag, NULL)); 11445f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&diag)); 1145b4da3a1bSStefano Zampini 1146d5d25401SBarry Smith /* TODO: Set a PCFailedReason and exit the building of the AMG preconditioner */ 11472c71b3e2SJacob Faibussowitsch PetscCheckFalse(emax == 0.0,PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Computed maximum singular value as zero"); 1148d5d25401SBarry Smith /* TODO: Document the 1.4 and don't hardwire it in this routine */ 1149b4ec6429SMark F. Adams alpha = -1.4/emax; 1150b4da3a1bSStefano Zampini 11515f80ce2aSJacob Faibussowitsch CHKERRQ(MatAYPX(tMat, alpha, Prol, SUBSET_NONZERO_PATTERN)); 11525f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&Prol)); 11532e68589bSMark F. Adams Prol = tMat; 11545f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(petsc_gamg_setup_events[SET9],0,0,0,0)); 11552e68589bSMark F. Adams } 11565f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(PC_GAMGOptProlongator_AGG,0,0,0,0)); 1157c8b0795cSMark F. Adams *a_P = Prol; 1158c8b0795cSMark F. Adams PetscFunctionReturn(0); 11592e68589bSMark F. Adams } 11602e68589bSMark F. Adams 1161c8b0795cSMark F. Adams /* -------------------------------------------------------------------------- */ 1162c8b0795cSMark F. Adams /* 1163c8b0795cSMark F. Adams PCCreateGAMG_AGG 11642e68589bSMark F. Adams 1165c8b0795cSMark F. Adams Input Parameter: 1166c8b0795cSMark F. Adams . pc - 1167c8b0795cSMark F. Adams */ 1168c8b0795cSMark F. Adams PetscErrorCode PCCreateGAMG_AGG(PC pc) 1169c8b0795cSMark F. Adams { 1170c8b0795cSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 1171c8b0795cSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 1172c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg; 11732e68589bSMark F. Adams 1174c8b0795cSMark F. Adams PetscFunctionBegin; 1175c8b0795cSMark F. Adams /* create sub context for SA */ 11765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNewLog(pc,&pc_gamg_agg)); 1177c8b0795cSMark F. Adams pc_gamg->subctx = pc_gamg_agg; 1178c8b0795cSMark F. Adams 11791ab5ffc9SJed Brown pc_gamg->ops->setfromoptions = PCSetFromOptions_GAMG_AGG; 11809b8ffb57SJed Brown pc_gamg->ops->destroy = PCDestroy_GAMG_AGG; 1181c8b0795cSMark F. Adams /* reset does not do anything; setup not virtual */ 1182c8b0795cSMark F. Adams 1183c8b0795cSMark F. Adams /* set internal function pointers */ 1184fd1112cbSBarry Smith pc_gamg->ops->graph = PCGAMGGraph_AGG; 11851ab5ffc9SJed Brown pc_gamg->ops->coarsen = PCGAMGCoarsen_AGG; 11861ab5ffc9SJed Brown pc_gamg->ops->prolongator = PCGAMGProlongator_AGG; 1187fd1112cbSBarry Smith pc_gamg->ops->optprolongator = PCGAMGOptProlongator_AGG; 11881ab5ffc9SJed Brown pc_gamg->ops->createdefaultdata = PCSetData_AGG; 11895adeb434SBarry Smith pc_gamg->ops->view = PCView_GAMG_AGG; 1190c8b0795cSMark F. Adams 1191cab9ed1eSBarry Smith pc_gamg_agg->square_graph = 1; 1192cab9ed1eSBarry Smith pc_gamg_agg->sym_graph = PETSC_FALSE; 1193cab9ed1eSBarry Smith pc_gamg_agg->nsmooths = 1; 1194cab9ed1eSBarry Smith 11955f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCGAMGSetNSmooths_C",PCGAMGSetNSmooths_AGG)); 11965f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCGAMGSetSymGraph_C",PCGAMGSetSymGraph_AGG)); 11975f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCGAMGSetSquareGraph_C",PCGAMGSetSquareGraph_AGG)); 11985f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_AGG)); 11992e68589bSMark F. Adams PetscFunctionReturn(0); 12002e68589bSMark F. Adams } 1201