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 29db781477SPatrick Sanan .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); 36cac4c232SBarry Smith 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 65db781477SPatrick Sanan .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); 72cac4c232SBarry Smith 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 104db781477SPatrick Sanan .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); 111cac4c232SBarry Smith 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; 133d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject,"GAMG-AGG options"); 1342e68589bSMark F. Adams { 1359566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_gamg_agg_nsmooths","smoothing steps for smoothed aggregation, usually 1","PCGAMGSetNSmooths",pc_gamg_agg->nsmooths,&pc_gamg_agg->nsmooths,NULL)); 1369566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-pc_gamg_sym_graph","Set for asymmetric matrices","PCGAMGSetSymGraph",pc_gamg_agg->sym_graph,&pc_gamg_agg->sym_graph,NULL)); 1379566063dSJacob Faibussowitsch PetscCall(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 } 139d0609cedSBarry Smith PetscOptionsHeadEnd(); 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; 1509566063dSJacob Faibussowitsch PetscCall(PetscFree(pc_gamg->subctx)); 1519566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL)); 1522e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGAMGSetNSmooths_C",NULL)); 1532e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGAMGSetSymGraph_C",NULL)); 1542e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGAMGSetSquareGraph_C",NULL)); 1552e68589bSMark F. Adams PetscFunctionReturn(0); 1562e68589bSMark F. Adams } 1572e68589bSMark F. Adams 1582e68589bSMark F. Adams /* -------------------------------------------------------------------------- */ 1592e68589bSMark F. Adams /* 1602e68589bSMark F. Adams PCSetCoordinates_AGG 161302f38e8SMark F. Adams - collective 1622e68589bSMark F. Adams 1632e68589bSMark F. Adams Input Parameter: 1642e68589bSMark F. Adams . pc - the preconditioner context 165a2f3521dSMark F. Adams . ndm - dimesion of data (used for dof/vertex for Stokes) 166302f38e8SMark F. Adams . a_nloc - number of vertices local 167302f38e8SMark F. Adams . coords - [a_nloc][ndm] - interleaved coordinate data: {x_0, y_0, z_0, x_1, y_1, ...} 1682e68589bSMark F. Adams */ 1691e6b0712SBarry Smith 1701e6b0712SBarry Smith static PetscErrorCode PCSetCoordinates_AGG(PC pc, PetscInt ndm, PetscInt a_nloc, PetscReal *coords) 1712e68589bSMark F. Adams { 1722e68589bSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 1732e68589bSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 17469344418SMark F. Adams PetscInt arrsz,kk,ii,jj,nloc,ndatarows,ndf; 175a2f3521dSMark F. Adams Mat mat = pc->pmat; 1762e68589bSMark F. Adams 1772e68589bSMark F. Adams PetscFunctionBegin; 178a2f3521dSMark F. Adams PetscValidHeaderSpecific(pc,PC_CLASSID,1); 179a2f3521dSMark F. Adams PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 180302f38e8SMark F. Adams nloc = a_nloc; 1812e68589bSMark F. Adams 1822e68589bSMark F. Adams /* SA: null space vectors */ 1839566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(mat, &ndf)); /* this does not work for Stokes */ 18469344418SMark F. Adams if (coords && ndf==1) pc_gamg->data_cell_cols = 1; /* scalar w/ coords and SA (not needed) */ 185a2f3521dSMark F. Adams else if (coords) { 18663a3b9bcSJacob Faibussowitsch PetscCheck(ndm <= ndf,PETSC_COMM_SELF,PETSC_ERR_PLIB,"degrees of motion %" PetscInt_FMT " > block size %" PetscInt_FMT,ndm,ndf); 18769344418SMark F. Adams pc_gamg->data_cell_cols = (ndm==2 ? 3 : 6); /* displacement elasticity */ 18869344418SMark F. Adams if (ndm != ndf) { 18963a3b9bcSJacob Faibussowitsch PetscCheck(pc_gamg->data_cell_cols == ndf,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Don't know how to create null space for ndm=%" PetscInt_FMT ", ndf=%" PetscInt_FMT ". Use MatSetNearNullSpace().",ndm,ndf); 190a2f3521dSMark F. Adams } 191806fa848SBarry Smith } else pc_gamg->data_cell_cols = ndf; /* no data, force SA with constant null space vectors */ 19271959b99SBarry Smith pc_gamg->data_cell_rows = ndatarows = ndf; 19363a3b9bcSJacob Faibussowitsch PetscCheck(pc_gamg->data_cell_cols > 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"pc_gamg->data_cell_cols %" PetscInt_FMT " <= 0",pc_gamg->data_cell_cols); 194c8b0795cSMark F. Adams arrsz = nloc*pc_gamg->data_cell_rows*pc_gamg->data_cell_cols; 1952e68589bSMark F. Adams 1967f66b68fSMark Adams if (!pc_gamg->data || (pc_gamg->data_sz != arrsz)) { 1979566063dSJacob Faibussowitsch PetscCall(PetscFree(pc_gamg->data)); 1989566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(arrsz+1, &pc_gamg->data)); 1992e68589bSMark F. Adams } 2002e68589bSMark F. Adams /* copy data in - column oriented */ 2012e68589bSMark F. Adams for (kk=0; kk<nloc; kk++) { 20269344418SMark F. Adams const PetscInt M = nloc*pc_gamg->data_cell_rows; /* stride into data */ 20369344418SMark F. Adams PetscReal *data = &pc_gamg->data[kk*ndatarows]; /* start of cell */ 204c8b0795cSMark F. Adams if (pc_gamg->data_cell_cols==1) *data = 1.0; 2052e68589bSMark F. Adams else { 20669344418SMark F. Adams /* translational modes */ 2072fa5cd67SKarl Rupp for (ii=0;ii<ndatarows;ii++) { 2082fa5cd67SKarl Rupp for (jj=0;jj<ndatarows;jj++) { 20969344418SMark F. Adams if (ii==jj)data[ii*M + jj] = 1.0; 2102e68589bSMark F. Adams else data[ii*M + jj] = 0.0; 2112fa5cd67SKarl Rupp } 2122fa5cd67SKarl Rupp } 21369344418SMark F. Adams 21469344418SMark F. Adams /* rotational modes */ 2152e68589bSMark F. Adams if (coords) { 21669344418SMark F. Adams if (ndm == 2) { 2172e68589bSMark F. Adams data += 2*M; 2182e68589bSMark F. Adams data[0] = -coords[2*kk+1]; 2192e68589bSMark F. Adams data[1] = coords[2*kk]; 220806fa848SBarry Smith } else { 2212e68589bSMark F. Adams data += 3*M; 2222e68589bSMark F. Adams data[0] = 0.0; data[M+0] = coords[3*kk+2]; data[2*M+0] = -coords[3*kk+1]; 2232e68589bSMark F. Adams data[1] = -coords[3*kk+2]; data[M+1] = 0.0; data[2*M+1] = coords[3*kk]; 2242e68589bSMark F. Adams data[2] = coords[3*kk+1]; data[M+2] = -coords[3*kk]; data[2*M+2] = 0.0; 2252e68589bSMark F. Adams } 2262e68589bSMark F. Adams } 2272e68589bSMark F. Adams } 2282e68589bSMark F. Adams } 2292e68589bSMark F. Adams pc_gamg->data_sz = arrsz; 2302e68589bSMark F. Adams PetscFunctionReturn(0); 2312e68589bSMark F. Adams } 2322e68589bSMark F. Adams 233b43b03e9SMark F. Adams typedef PetscInt NState; 234b43b03e9SMark F. Adams static const NState NOT_DONE=-2; 235b43b03e9SMark F. Adams static const NState DELETED =-1; 236b43b03e9SMark F. Adams static const NState REMOVED =-3; 237b43b03e9SMark F. Adams #define IS_SELECTED(s) (s!=DELETED && s!=NOT_DONE && s!=REMOVED) 238b43b03e9SMark F. Adams 239c8b0795cSMark F. Adams /* -------------------------------------------------------------------------- */ 240c8b0795cSMark F. Adams /* 241b43b03e9SMark F. Adams smoothAggs - greedy grab of with G1 (unsquared graph) -- AIJ specific 242b43b03e9SMark F. Adams - AGG-MG specific: clears singletons out of 'selected_2' 243c8b0795cSMark F. Adams 244c8b0795cSMark F. Adams Input Parameter: 245fdb86571SRichard Tran Mills . Gmat_2 - global matrix of graph (data not defined) base (squared) graph 2462adfe9d3SBarry Smith . Gmat_1 - base graph to grab with base graph 247c8b0795cSMark F. Adams Input/Output Parameter: 2480cbbd2e1SMark F. Adams . aggs_2 - linked list of aggs with gids) 249c8b0795cSMark F. Adams */ 250e3df7ea3SBarry Smith static PetscErrorCode smoothAggs(PC pc,Mat Gmat_2, Mat Gmat_1,PetscCoarsenData *aggs_2) 251c8b0795cSMark F. Adams { 252c8b0795cSMark F. Adams PetscBool isMPI; 2530a545947SLisandro Dalcin Mat_SeqAIJ *matA_1, *matB_1=NULL; 2543b4367a7SBarry Smith MPI_Comm comm; 2550cbbd2e1SMark F. Adams PetscInt lid,*ii,*idx,ix,Iend,my0,kk,n,j; 2560a545947SLisandro Dalcin Mat_MPIAIJ *mpimat_2 = NULL, *mpimat_1=NULL; 257c8b0795cSMark F. Adams const PetscInt nloc = Gmat_2->rmap->n; 2580cbbd2e1SMark F. Adams PetscScalar *cpcol_1_state,*cpcol_2_state,*cpcol_2_par_orig,*lid_parent_gid; 2590cbbd2e1SMark F. Adams PetscInt *lid_cprowID_1; 260c8b0795cSMark F. Adams NState *lid_state; 2610cbbd2e1SMark F. Adams Vec ghost_par_orig2; 262c8b0795cSMark F. Adams 263c8b0795cSMark F. Adams PetscFunctionBegin; 2649566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)Gmat_2,&comm)); 2659566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(Gmat_1,&my0,&Iend)); 266c8b0795cSMark F. Adams 267c8b0795cSMark F. Adams /* get submatrices */ 2689566063dSJacob Faibussowitsch PetscCall(PetscStrbeginswith(((PetscObject)Gmat_1)->type_name,MATMPIAIJ,&isMPI)); 269c8b0795cSMark F. Adams if (isMPI) { 270c8b0795cSMark F. Adams /* grab matrix objects */ 271c8b0795cSMark F. Adams mpimat_2 = (Mat_MPIAIJ*)Gmat_2->data; 272c8b0795cSMark F. Adams mpimat_1 = (Mat_MPIAIJ*)Gmat_1->data; 273c8b0795cSMark F. Adams matA_1 = (Mat_SeqAIJ*)mpimat_1->A->data; 274c8b0795cSMark F. Adams matB_1 = (Mat_SeqAIJ*)mpimat_1->B->data; 275c8b0795cSMark F. Adams 276c8b0795cSMark F. Adams /* force compressed row storage for B matrix in AuxMat */ 2779566063dSJacob Faibussowitsch PetscCall(MatCheckCompressedRow(mpimat_1->B,matB_1->nonzerorowcnt,&matB_1->compressedrow,matB_1->i,Gmat_1->rmap->n,-1.0)); 278c8b0795cSMark F. Adams 2799566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nloc, &lid_cprowID_1)); 2800cbbd2e1SMark F. Adams for (lid = 0; lid < nloc; lid++) lid_cprowID_1[lid] = -1; 281c8b0795cSMark F. Adams for (ix=0; ix<matB_1->compressedrow.nrows; ix++) { 282c8b0795cSMark F. Adams PetscInt lid = matB_1->compressedrow.rindex[ix]; 283c8b0795cSMark F. Adams lid_cprowID_1[lid] = ix; 284c8b0795cSMark F. Adams } 285806fa848SBarry Smith } else { 28615687449SMark Adams PetscBool isAIJ; 2879566063dSJacob Faibussowitsch PetscCall(PetscStrbeginswith(((PetscObject)Gmat_1)->type_name,MATSEQAIJ,&isAIJ)); 28828b400f6SJacob Faibussowitsch PetscCheck(isAIJ,PETSC_COMM_SELF,PETSC_ERR_USER,"Require AIJ matrix."); 289c8b0795cSMark F. Adams matA_1 = (Mat_SeqAIJ*)Gmat_1->data; 2900298fd71SBarry Smith lid_cprowID_1 = NULL; 291c8b0795cSMark F. Adams } 29278a438d6SMark Adams if (nloc>0) { 29308401ef6SPierre Jolivet PetscCheck(!matB_1 || matB_1->compressedrow.use,PETSC_COMM_SELF,PETSC_ERR_PLIB,"matB_1 && !matB_1->compressedrow.use: PETSc bug???"); 29478a438d6SMark Adams } 295c8b0795cSMark F. Adams /* get state of locals and selected gid for deleted */ 2969566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nloc, &lid_state,nloc, &lid_parent_gid)); 297c8b0795cSMark F. Adams for (lid = 0; lid < nloc; lid++) { 2980cbbd2e1SMark F. Adams lid_parent_gid[lid] = -1.0; 299c8b0795cSMark F. Adams lid_state[lid] = DELETED; 300c8b0795cSMark F. Adams } 3010cbbd2e1SMark F. Adams 3020cbbd2e1SMark F. Adams /* set lid_state */ 3030cbbd2e1SMark F. Adams for (lid = 0; lid < nloc; lid++) { 304539c167fSBarry Smith PetscCDIntNd *pos; 3059566063dSJacob Faibussowitsch PetscCall(PetscCDGetHeadPos(aggs_2,lid,&pos)); 306e78576d6SMark F. Adams if (pos) { 307e78576d6SMark F. Adams PetscInt gid1; 3082fa5cd67SKarl Rupp 3099566063dSJacob Faibussowitsch PetscCall(PetscCDIntNdGetID(pos, &gid1)); 31063a3b9bcSJacob Faibussowitsch PetscCheck(gid1 == lid+my0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"gid1 %" PetscInt_FMT " != lid %" PetscInt_FMT " + my0 %" PetscInt_FMT,gid1,lid,my0); 3110cbbd2e1SMark F. Adams lid_state[lid] = gid1; 312b43b03e9SMark F. Adams } 313b43b03e9SMark F. Adams } 3140cbbd2e1SMark F. Adams 3150cbbd2e1SMark F. Adams /* map local to selected local, DELETED means a ghost owns it */ 316c8b0795cSMark F. Adams for (lid=kk=0; lid<nloc; lid++) { 317c8b0795cSMark F. Adams NState state = lid_state[lid]; 318c8b0795cSMark F. Adams if (IS_SELECTED(state)) { 319539c167fSBarry Smith PetscCDIntNd *pos; 3209566063dSJacob Faibussowitsch PetscCall(PetscCDGetHeadPos(aggs_2,lid,&pos)); 321e78576d6SMark F. Adams while (pos) { 322e78576d6SMark F. Adams PetscInt gid1; 3239566063dSJacob Faibussowitsch PetscCall(PetscCDIntNdGetID(pos, &gid1)); 3249566063dSJacob Faibussowitsch PetscCall(PetscCDGetNextPos(aggs_2,lid,&pos)); 3252fa5cd67SKarl Rupp if (gid1 >= my0 && gid1 < Iend) lid_parent_gid[gid1-my0] = (PetscScalar)(lid + my0); 326c8b0795cSMark F. Adams } 3270cbbd2e1SMark F. Adams } 3280cbbd2e1SMark F. Adams } 3290cbbd2e1SMark F. Adams /* get 'cpcol_1/2_state' & cpcol_2_par_orig - uses mpimat_1/2->lvec for temp space */ 330c8b0795cSMark F. Adams if (isMPI) { 331c8b0795cSMark F. Adams Vec tempVec; 332c8b0795cSMark F. Adams /* get 'cpcol_1_state' */ 3339566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(Gmat_1, &tempVec, NULL)); 334c8b0795cSMark F. Adams for (kk=0,j=my0; kk<nloc; kk++,j++) { 335c8b0795cSMark F. Adams PetscScalar v = (PetscScalar)lid_state[kk]; 3369566063dSJacob Faibussowitsch PetscCall(VecSetValues(tempVec, 1, &j, &v, INSERT_VALUES)); 337c8b0795cSMark F. Adams } 3389566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(tempVec)); 3399566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(tempVec)); 3409566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mpimat_1->Mvctx,tempVec, mpimat_1->lvec,INSERT_VALUES,SCATTER_FORWARD)); 3419566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mpimat_1->Mvctx,tempVec, mpimat_1->lvec,INSERT_VALUES,SCATTER_FORWARD)); 3429566063dSJacob Faibussowitsch PetscCall(VecGetArray(mpimat_1->lvec, &cpcol_1_state)); 343c8b0795cSMark F. Adams /* get 'cpcol_2_state' */ 3449566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mpimat_2->Mvctx,tempVec, mpimat_2->lvec,INSERT_VALUES,SCATTER_FORWARD)); 3459566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mpimat_2->Mvctx,tempVec, mpimat_2->lvec,INSERT_VALUES,SCATTER_FORWARD)); 3469566063dSJacob Faibussowitsch PetscCall(VecGetArray(mpimat_2->lvec, &cpcol_2_state)); 3470cbbd2e1SMark F. Adams /* get 'cpcol_2_par_orig' */ 3480cbbd2e1SMark F. Adams for (kk=0,j=my0; kk<nloc; kk++,j++) { 3490cbbd2e1SMark F. Adams PetscScalar v = (PetscScalar)lid_parent_gid[kk]; 3509566063dSJacob Faibussowitsch PetscCall(VecSetValues(tempVec, 1, &j, &v, INSERT_VALUES)); 3510cbbd2e1SMark F. Adams } 3529566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(tempVec)); 3539566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(tempVec)); 3549566063dSJacob Faibussowitsch PetscCall(VecDuplicate(mpimat_2->lvec, &ghost_par_orig2)); 3559566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mpimat_2->Mvctx,tempVec, ghost_par_orig2,INSERT_VALUES,SCATTER_FORWARD)); 3569566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mpimat_2->Mvctx,tempVec, ghost_par_orig2,INSERT_VALUES,SCATTER_FORWARD)); 3579566063dSJacob Faibussowitsch PetscCall(VecGetArray(ghost_par_orig2, &cpcol_2_par_orig)); 3580cbbd2e1SMark F. Adams 3599566063dSJacob Faibussowitsch PetscCall(VecDestroy(&tempVec)); 360c8b0795cSMark F. Adams } /* ismpi */ 361c8b0795cSMark F. Adams for (lid=0; lid<nloc; lid++) { 362c8b0795cSMark F. Adams NState state = lid_state[lid]; 3630cbbd2e1SMark F. Adams if (IS_SELECTED(state)) { 3640cbbd2e1SMark F. Adams /* steal locals */ 365c8b0795cSMark F. Adams ii = matA_1->i; n = ii[lid+1] - ii[lid]; 366c8b0795cSMark F. Adams idx = matA_1->j + ii[lid]; 367c8b0795cSMark F. Adams for (j=0; j<n; j++) { 3680cbbd2e1SMark F. Adams PetscInt lidj = idx[j], sgid; 369c8b0795cSMark F. Adams NState statej = lid_state[lidj]; 3700cbbd2e1SMark F. Adams if (statej==DELETED && (sgid=(PetscInt)PetscRealPart(lid_parent_gid[lidj])) != lid+my0) { /* steal local */ 3710cbbd2e1SMark F. Adams lid_parent_gid[lidj] = (PetscScalar)(lid+my0); /* send this if sgid is not local */ 3720cbbd2e1SMark F. Adams if (sgid >= my0 && sgid < Iend) { /* I'm stealing this local from a local sgid */ 3730cbbd2e1SMark F. Adams PetscInt hav=0,slid=sgid-my0,gidj=lidj+my0; 374539c167fSBarry Smith PetscCDIntNd *pos,*last=NULL; 375c8b0795cSMark F. Adams /* looking for local from local so id_llist_2 works */ 3769566063dSJacob Faibussowitsch PetscCall(PetscCDGetHeadPos(aggs_2,slid,&pos)); 377e78576d6SMark F. Adams while (pos) { 378e78576d6SMark F. Adams PetscInt gid; 3799566063dSJacob Faibussowitsch PetscCall(PetscCDIntNdGetID(pos, &gid)); 3800cbbd2e1SMark F. Adams if (gid == gidj) { 38128b400f6SJacob Faibussowitsch PetscCheck(last,PETSC_COMM_SELF,PETSC_ERR_PLIB,"last cannot be null"); 3829566063dSJacob Faibussowitsch PetscCall(PetscCDRemoveNextNode(aggs_2, slid, last)); 3839566063dSJacob Faibussowitsch PetscCall(PetscCDAppendNode(aggs_2, lid, pos)); 3840cbbd2e1SMark F. Adams hav = 1; 385c8b0795cSMark F. Adams break; 386806fa848SBarry Smith } else last = pos; 3879566063dSJacob Faibussowitsch PetscCall(PetscCDGetNextPos(aggs_2,slid,&pos)); 388c8b0795cSMark F. Adams } 389c8b0795cSMark F. Adams if (hav != 1) { 39028b400f6SJacob Faibussowitsch PetscCheck(hav,PETSC_COMM_SELF,PETSC_ERR_PLIB,"failed to find adj in 'selected' lists - structurally unsymmetric matrix"); 39163a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"found node %" PetscInt_FMT " times???",hav); 392c8b0795cSMark F. Adams } 393806fa848SBarry Smith } else { /* I'm stealing this local, owned by a ghost */ 39408401ef6SPierre Jolivet PetscCheck(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 : ""); 3959566063dSJacob Faibussowitsch PetscCall(PetscCDAppendID(aggs_2, lid, lidj+my0)); 396c8b0795cSMark F. Adams } 397c8b0795cSMark F. Adams } 3980cbbd2e1SMark F. Adams } /* local neighbors */ 399806fa848SBarry Smith } else if (state == DELETED && lid_cprowID_1) { 4000cbbd2e1SMark F. Adams PetscInt sgidold = (PetscInt)PetscRealPart(lid_parent_gid[lid]); 401c8b0795cSMark F. Adams /* see if I have a selected ghost neighbor that will steal me */ 402c8b0795cSMark F. Adams if ((ix=lid_cprowID_1[lid]) != -1) { 403c8b0795cSMark F. Adams ii = matB_1->compressedrow.i; n = ii[ix+1] - ii[ix]; 404c8b0795cSMark F. Adams idx = matB_1->j + ii[ix]; 405c8b0795cSMark F. Adams for (j=0; j<n; j++) { 406c8b0795cSMark F. Adams PetscInt cpid = idx[j]; 407c8b0795cSMark F. Adams NState statej = (NState)PetscRealPart(cpcol_1_state[cpid]); 408c8b0795cSMark F. Adams if (IS_SELECTED(statej) && sgidold != (PetscInt)statej) { /* ghost will steal this, remove from my list */ 4090cbbd2e1SMark F. Adams lid_parent_gid[lid] = (PetscScalar)statej; /* send who selected */ 4100cbbd2e1SMark F. Adams if (sgidold>=my0 && sgidold<Iend) { /* this was mine */ 4110cbbd2e1SMark F. Adams PetscInt hav=0,oldslidj=sgidold-my0; 412539c167fSBarry Smith PetscCDIntNd *pos,*last=NULL; 4130cbbd2e1SMark F. Adams /* remove from 'oldslidj' list */ 4149566063dSJacob Faibussowitsch PetscCall(PetscCDGetHeadPos(aggs_2,oldslidj,&pos)); 415e78576d6SMark F. Adams while (pos) { 416e78576d6SMark F. Adams PetscInt gid; 4179566063dSJacob Faibussowitsch PetscCall(PetscCDIntNdGetID(pos, &gid)); 4180cbbd2e1SMark F. Adams if (lid+my0 == gid) { 4190cbbd2e1SMark F. Adams /* id_llist_2[lastid] = id_llist_2[flid]; /\* remove lid from oldslidj list *\/ */ 42028b400f6SJacob Faibussowitsch PetscCheck(last,PETSC_COMM_SELF,PETSC_ERR_PLIB,"last cannot be null"); 4219566063dSJacob Faibussowitsch PetscCall(PetscCDRemoveNextNode(aggs_2, oldslidj, last)); 4220cbbd2e1SMark F. Adams /* ghost (PetscScalar)statej will add this later */ 4230cbbd2e1SMark F. Adams hav = 1; 424c8b0795cSMark F. Adams break; 425806fa848SBarry Smith } else last = pos; 4269566063dSJacob Faibussowitsch PetscCall(PetscCDGetNextPos(aggs_2,oldslidj,&pos)); 427c8b0795cSMark F. Adams } 428c8b0795cSMark F. Adams if (hav != 1) { 42928b400f6SJacob Faibussowitsch PetscCheck(hav,PETSC_COMM_SELF,PETSC_ERR_PLIB,"failed to find adj in 'selected' lists - structurally unsymmetric matrix"); 43063a3b9bcSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"found node %" PetscInt_FMT " times???",hav); 431c8b0795cSMark F. Adams } 432806fa848SBarry Smith } else { 433d5d25401SBarry Smith /* TODO: ghosts remove this later */ 4340cbbd2e1SMark F. Adams } 435c8b0795cSMark F. Adams } 436c8b0795cSMark F. Adams } 437c8b0795cSMark F. Adams } 438c8b0795cSMark F. Adams } /* selected/deleted */ 439c8b0795cSMark F. Adams } /* node loop */ 440c8b0795cSMark F. Adams 441c8b0795cSMark F. Adams if (isMPI) { 4420cbbd2e1SMark F. Adams PetscScalar *cpcol_2_parent,*cpcol_2_gid; 4430cbbd2e1SMark F. Adams Vec tempVec,ghostgids2,ghostparents2; 4440cbbd2e1SMark F. Adams PetscInt cpid,nghost_2; 4451943db53SBarry Smith PCGAMGHashTable gid_cpid; 446c8b0795cSMark F. Adams 4479566063dSJacob Faibussowitsch PetscCall(VecGetSize(mpimat_2->lvec, &nghost_2)); 4489566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(Gmat_2, &tempVec, NULL)); 4490cbbd2e1SMark F. Adams 4500cbbd2e1SMark F. Adams /* get 'cpcol_2_parent' */ 451c8b0795cSMark F. Adams for (kk=0,j=my0; kk<nloc; kk++,j++) { 4529566063dSJacob Faibussowitsch PetscCall(VecSetValues(tempVec, 1, &j, &lid_parent_gid[kk], INSERT_VALUES)); 453c8b0795cSMark F. Adams } 4549566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(tempVec)); 4559566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(tempVec)); 4569566063dSJacob Faibussowitsch PetscCall(VecDuplicate(mpimat_2->lvec, &ghostparents2)); 4579566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mpimat_2->Mvctx,tempVec, ghostparents2,INSERT_VALUES,SCATTER_FORWARD)); 4589566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mpimat_2->Mvctx,tempVec, ghostparents2,INSERT_VALUES,SCATTER_FORWARD)); 4599566063dSJacob Faibussowitsch PetscCall(VecGetArray(ghostparents2, &cpcol_2_parent)); 4600cbbd2e1SMark F. Adams 4610cbbd2e1SMark F. Adams /* get 'cpcol_2_gid' */ 4620cbbd2e1SMark F. Adams for (kk=0,j=my0; kk<nloc; kk++,j++) { 4630cbbd2e1SMark F. Adams PetscScalar v = (PetscScalar)j; 4649566063dSJacob Faibussowitsch PetscCall(VecSetValues(tempVec, 1, &j, &v, INSERT_VALUES)); 4650cbbd2e1SMark F. Adams } 4669566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(tempVec)); 4679566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(tempVec)); 4689566063dSJacob Faibussowitsch PetscCall(VecDuplicate(mpimat_2->lvec, &ghostgids2)); 4699566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mpimat_2->Mvctx,tempVec, ghostgids2,INSERT_VALUES,SCATTER_FORWARD)); 4709566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mpimat_2->Mvctx,tempVec, ghostgids2,INSERT_VALUES,SCATTER_FORWARD)); 4719566063dSJacob Faibussowitsch PetscCall(VecGetArray(ghostgids2, &cpcol_2_gid)); 4729566063dSJacob Faibussowitsch PetscCall(VecDestroy(&tempVec)); 473c8b0795cSMark F. Adams 4740cbbd2e1SMark F. Adams /* look for deleted ghosts and add to table */ 4759566063dSJacob Faibussowitsch PetscCall(PCGAMGHashTableCreate(2*nghost_2+1, &gid_cpid)); 4760cbbd2e1SMark F. Adams for (cpid = 0; cpid < nghost_2; cpid++) { 4770cbbd2e1SMark F. Adams NState state = (NState)PetscRealPart(cpcol_2_state[cpid]); 4780cbbd2e1SMark F. Adams if (state==DELETED) { 4790cbbd2e1SMark F. Adams PetscInt sgid_new = (PetscInt)PetscRealPart(cpcol_2_parent[cpid]); 4800cbbd2e1SMark F. Adams PetscInt sgid_old = (PetscInt)PetscRealPart(cpcol_2_par_orig[cpid]); 4810cbbd2e1SMark F. Adams if (sgid_old == -1 && sgid_new != -1) { 4820cbbd2e1SMark F. Adams PetscInt gid = (PetscInt)PetscRealPart(cpcol_2_gid[cpid]); 4839566063dSJacob Faibussowitsch PetscCall(PCGAMGHashTableAdd(&gid_cpid, gid, cpid)); 4840cbbd2e1SMark F. Adams } 4850cbbd2e1SMark F. Adams } 4860cbbd2e1SMark F. Adams } 487c8b0795cSMark F. Adams 4880cbbd2e1SMark F. Adams /* look for deleted ghosts and see if they moved - remove it */ 489c8b0795cSMark F. Adams for (lid=0; lid<nloc; lid++) { 490c8b0795cSMark F. Adams NState state = lid_state[lid]; 491c8b0795cSMark F. Adams if (IS_SELECTED(state)) { 492539c167fSBarry Smith PetscCDIntNd *pos,*last=NULL; 493c8b0795cSMark F. Adams /* look for deleted ghosts and see if they moved */ 4949566063dSJacob Faibussowitsch PetscCall(PetscCDGetHeadPos(aggs_2,lid,&pos)); 495e78576d6SMark F. Adams while (pos) { 496e78576d6SMark F. Adams PetscInt gid; 4979566063dSJacob Faibussowitsch PetscCall(PetscCDIntNdGetID(pos, &gid)); 498e78576d6SMark F. Adams 4990cbbd2e1SMark F. Adams if (gid < my0 || gid >= Iend) { 5009566063dSJacob Faibussowitsch PetscCall(PCGAMGHashTableFind(&gid_cpid, gid, &cpid)); 5010cbbd2e1SMark F. Adams if (cpid != -1) { 5020cbbd2e1SMark F. Adams /* a moved ghost - */ 5030cbbd2e1SMark F. Adams /* id_llist_2[lastid] = id_llist_2[flid]; /\* remove 'flid' from list *\/ */ 5049566063dSJacob Faibussowitsch PetscCall(PetscCDRemoveNextNode(aggs_2, lid, last)); 505806fa848SBarry Smith } else last = pos; 506806fa848SBarry Smith } else last = pos; 507e78576d6SMark F. Adams 5089566063dSJacob Faibussowitsch PetscCall(PetscCDGetNextPos(aggs_2,lid,&pos)); 509c8b0795cSMark F. Adams } /* loop over list of deleted */ 510c8b0795cSMark F. Adams } /* selected */ 511c8b0795cSMark F. Adams } 5129566063dSJacob Faibussowitsch PetscCall(PCGAMGHashTableDestroy(&gid_cpid)); 513c8b0795cSMark F. Adams 5140cbbd2e1SMark F. Adams /* look at ghosts, see if they changed - and it */ 5150cbbd2e1SMark F. Adams for (cpid = 0; cpid < nghost_2; cpid++) { 5160cbbd2e1SMark F. Adams PetscInt sgid_new = (PetscInt)PetscRealPart(cpcol_2_parent[cpid]); 5170cbbd2e1SMark F. Adams if (sgid_new >= my0 && sgid_new < Iend) { /* this is mine */ 5180cbbd2e1SMark F. Adams PetscInt gid = (PetscInt)PetscRealPart(cpcol_2_gid[cpid]); 5190cbbd2e1SMark F. Adams PetscInt slid_new=sgid_new-my0,hav=0; 520539c167fSBarry Smith PetscCDIntNd *pos; 521539c167fSBarry Smith 5220cbbd2e1SMark F. Adams /* search for this gid to see if I have it */ 5239566063dSJacob Faibussowitsch PetscCall(PetscCDGetHeadPos(aggs_2,slid_new,&pos)); 524e78576d6SMark F. Adams while (pos) { 525e78576d6SMark F. Adams PetscInt gidj; 5269566063dSJacob Faibussowitsch PetscCall(PetscCDIntNdGetID(pos, &gidj)); 5279566063dSJacob Faibussowitsch PetscCall(PetscCDGetNextPos(aggs_2,slid_new,&pos)); 528e78576d6SMark F. Adams 5290cbbd2e1SMark F. Adams if (gidj == gid) { hav = 1; break; } 530c8b0795cSMark F. Adams } 531c8b0795cSMark F. Adams if (hav != 1) { 532ffc955d6SMark F. Adams /* insert 'flidj' into head of llist */ 5339566063dSJacob Faibussowitsch PetscCall(PetscCDAppendID(aggs_2, slid_new, gid)); 534c8b0795cSMark F. Adams } 535c8b0795cSMark F. Adams } 536c8b0795cSMark F. Adams } 537c8b0795cSMark F. Adams 5389566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(mpimat_1->lvec, &cpcol_1_state)); 5399566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(mpimat_2->lvec, &cpcol_2_state)); 5409566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(ghostparents2, &cpcol_2_parent)); 5419566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(ghostgids2, &cpcol_2_gid)); 5429566063dSJacob Faibussowitsch PetscCall(PetscFree(lid_cprowID_1)); 5439566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ghostgids2)); 5449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ghostparents2)); 5459566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ghost_par_orig2)); 546c8b0795cSMark F. Adams } 547c8b0795cSMark F. Adams 5489566063dSJacob Faibussowitsch PetscCall(PetscFree2(lid_state,lid_parent_gid)); 549c8b0795cSMark F. Adams PetscFunctionReturn(0); 550c8b0795cSMark F. Adams } 5512e68589bSMark F. Adams 5522e68589bSMark F. Adams /* -------------------------------------------------------------------------- */ 5532e68589bSMark F. Adams /* 554a2f3521dSMark F. Adams PCSetData_AGG - called if data is not set with PCSetCoordinates. 555a2f3521dSMark F. Adams Looks in Mat for near null space. 556a2f3521dSMark F. Adams Does not work for Stokes 5572e68589bSMark F. Adams 5582e68589bSMark F. Adams Input Parameter: 5592e68589bSMark F. Adams . pc - 560a2f3521dSMark F. Adams . a_A - matrix to get (near) null space out of. 5612e68589bSMark F. Adams */ 562e0877f53SBarry Smith static PetscErrorCode PCSetData_AGG(PC pc, Mat a_A) 5632e68589bSMark F. Adams { 564b8cd405aSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 565b8cd405aSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 566b8cd405aSMark F. Adams MatNullSpace mnull; 56766f2ef4bSMark Adams 568b817416eSBarry Smith PetscFunctionBegin; 5699566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(a_A, &mnull)); 570b8cd405aSMark F. Adams if (!mnull) { 57166f2ef4bSMark Adams DM dm; 5729566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 57366f2ef4bSMark Adams if (!dm) { 5749566063dSJacob Faibussowitsch PetscCall(MatGetDM(a_A, &dm)); 57566f2ef4bSMark Adams } 57666f2ef4bSMark Adams if (dm) { 57766f2ef4bSMark Adams PetscObject deformation; 578b0d30dd6SMatthew G. Knepley PetscInt Nf; 579b0d30dd6SMatthew G. Knepley 5809566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 581b0d30dd6SMatthew G. Knepley if (Nf) { 5829566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, 0, NULL, &deformation)); 5839566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)deformation,"nearnullspace",(PetscObject*)&mnull)); 58466f2ef4bSMark Adams if (!mnull) { 5859566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)deformation,"nullspace",(PetscObject*)&mnull)); 58666f2ef4bSMark Adams } 58766f2ef4bSMark Adams } 58866f2ef4bSMark Adams } 589b0d30dd6SMatthew G. Knepley } 59066f2ef4bSMark Adams 59166f2ef4bSMark Adams if (!mnull) { 592a2f3521dSMark F. Adams PetscInt bs,NN,MM; 5939566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(a_A, &bs)); 5949566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(a_A, &MM, &NN)); 59563a3b9bcSJacob Faibussowitsch PetscCheck(MM % bs == 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"MM %" PetscInt_FMT " must be divisible by bs %" PetscInt_FMT,MM,bs); 5969566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates_AGG(pc, bs, MM/bs, NULL)); 597806fa848SBarry Smith } else { 598b8cd405aSMark F. Adams PetscReal *nullvec; 599b8cd405aSMark F. Adams PetscBool has_const; 600b8cd405aSMark F. Adams PetscInt i,j,mlocal,nvec,bs; 601d5d25401SBarry Smith const Vec *vecs; 602d5d25401SBarry Smith const PetscScalar *v; 603b817416eSBarry Smith 6049566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(a_A,&mlocal,NULL)); 6059566063dSJacob Faibussowitsch PetscCall(MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs)); 606a0dea87dSMark Adams pc_gamg->data_sz = (nvec+!!has_const)*mlocal; 6079566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((nvec+!!has_const)*mlocal,&nullvec)); 608b8cd405aSMark F. Adams if (has_const) for (i=0; i<mlocal; i++) nullvec[i] = 1.0; 609b8cd405aSMark F. Adams for (i=0; i<nvec; i++) { 6109566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vecs[i],&v)); 611b8cd405aSMark F. Adams for (j=0; j<mlocal; j++) nullvec[(i+!!has_const)*mlocal + j] = PetscRealPart(v[j]); 6129566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vecs[i],&v)); 613b8cd405aSMark F. Adams } 614b8cd405aSMark F. Adams pc_gamg->data = nullvec; 615b8cd405aSMark F. Adams pc_gamg->data_cell_cols = (nvec+!!has_const); 6169566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(a_A, &bs)); 617b8cd405aSMark F. Adams pc_gamg->data_cell_rows = bs; 618b8cd405aSMark F. Adams } 6192e68589bSMark F. Adams PetscFunctionReturn(0); 6202e68589bSMark F. Adams } 6212e68589bSMark F. Adams 6222e68589bSMark F. Adams /* -------------------------------------------------------------------------- */ 6232e68589bSMark F. Adams /* 6242e68589bSMark F. Adams formProl0 6252e68589bSMark F. Adams 6262e68589bSMark F. Adams Input Parameter: 6272adfe9d3SBarry Smith . agg_llists - list of arrays with aggregates -- list from selected vertices of aggregate unselected vertices 6282adfe9d3SBarry Smith . bs - row block size 6290cbbd2e1SMark F. Adams . nSAvec - column bs of new P 6300cbbd2e1SMark F. Adams . my0crs - global index of start of locals 6312adfe9d3SBarry Smith . data_stride - bs*(nloc nodes + ghost nodes) [data_stride][nSAvec] 6322e68589bSMark F. Adams . data_in[data_stride*nSAvec] - local data on fine grid 6332e68589bSMark F. Adams . flid_fgid[data_stride/bs] - make local to global IDs, includes ghosts in 'locals_llist' 6342e68589bSMark F. Adams Output Parameter: 6352e68589bSMark F. Adams . a_data_out - in with fine grid data (w/ghosts), out with coarse grid data 6362e68589bSMark F. Adams . a_Prol - prolongation operator 6372e68589bSMark F. Adams */ 6382adfe9d3SBarry 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) 6392e68589bSMark F. Adams { 640bd026e97SJed Brown PetscInt Istart,my0,Iend,nloc,clid,flid = 0,aggID,kk,jj,ii,mm,nSelected,minsz,nghosts,out_data_stride; 6413b4367a7SBarry Smith MPI_Comm comm; 6422e68589bSMark F. Adams PetscReal *out_data; 643539c167fSBarry Smith PetscCDIntNd *pos; 6441943db53SBarry Smith PCGAMGHashTable fgid_flid; 6450cbbd2e1SMark F. Adams 6462e68589bSMark F. Adams PetscFunctionBegin; 6479566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)a_Prol,&comm)); 6489566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(a_Prol, &Istart, &Iend)); 64971959b99SBarry Smith nloc = (Iend-Istart)/bs; my0 = Istart/bs; 65063a3b9bcSJacob Faibussowitsch PetscCheck((Iend-Istart) % bs == 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Iend %" PetscInt_FMT " - Istart %" PetscInt_FMT " must be divisible by bs %" PetscInt_FMT,Iend,Istart,bs); 6510cbbd2e1SMark F. Adams Iend /= bs; 6520cbbd2e1SMark F. Adams nghosts = data_stride/bs - nloc; 6532e68589bSMark F. Adams 6549566063dSJacob Faibussowitsch PetscCall(PCGAMGHashTableCreate(2*nghosts+1, &fgid_flid)); 6550cbbd2e1SMark F. Adams for (kk=0; kk<nghosts; kk++) { 6569566063dSJacob Faibussowitsch PetscCall(PCGAMGHashTableAdd(&fgid_flid, flid_fgid[nloc+kk], nloc+kk)); 6572e68589bSMark F. Adams } 6582e68589bSMark F. Adams 6590cbbd2e1SMark F. Adams /* count selected -- same as number of cols of P */ 6600cbbd2e1SMark F. Adams for (nSelected=mm=0; mm<nloc; mm++) { 661e78576d6SMark F. Adams PetscBool ise; 6629566063dSJacob Faibussowitsch PetscCall(PetscCDEmptyAt(agg_llists, mm, &ise)); 663e78576d6SMark F. Adams if (!ise) nSelected++; 6640cbbd2e1SMark F. Adams } 6659566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(a_Prol, &ii, &jj)); 66663a3b9bcSJacob Faibussowitsch PetscCheck((ii/nSAvec) == my0crs,PETSC_COMM_SELF,PETSC_ERR_PLIB,"ii %" PetscInt_FMT " /nSAvec %" PetscInt_FMT " != my0crs %" PetscInt_FMT,ii,nSAvec,my0crs); 66763a3b9bcSJacob Faibussowitsch PetscCheck(nSelected == (jj-ii)/nSAvec,PETSC_COMM_SELF,PETSC_ERR_PLIB,"nSelected %" PetscInt_FMT " != (jj %" PetscInt_FMT " - ii %" PetscInt_FMT ")/nSAvec %" PetscInt_FMT,nSelected,jj,ii,nSAvec); 6680cbbd2e1SMark F. Adams 6692e68589bSMark F. Adams /* aloc space for coarse point data (output) */ 6700cbbd2e1SMark F. Adams out_data_stride = nSelected*nSAvec; 6712fa5cd67SKarl Rupp 6729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(out_data_stride*nSAvec, &out_data)); 67333812677SSatish Balay for (ii=0;ii<out_data_stride*nSAvec;ii++) out_data[ii]=PETSC_MAX_REAL; 6740cbbd2e1SMark F. Adams *a_data_out = out_data; /* output - stride nSelected*nSAvec */ 6752e68589bSMark F. Adams 6762e68589bSMark F. Adams /* find points and set prolongation */ 677c8b0795cSMark F. Adams minsz = 100; 6780cbbd2e1SMark F. Adams for (mm = clid = 0; mm < nloc; mm++) { 6799566063dSJacob Faibussowitsch PetscCall(PetscCDSizeAt(agg_llists, mm, &jj)); 680e78576d6SMark F. Adams if (jj > 0) { 6810cbbd2e1SMark F. Adams const PetscInt lid = mm, cgid = my0crs + clid; 6820cbbd2e1SMark F. Adams PetscInt cids[100]; /* max bs */ 6830cbbd2e1SMark F. Adams PetscBLASInt asz =jj,M=asz*bs,N=nSAvec,INFO; 6842e68589bSMark F. Adams PetscBLASInt Mdata=M+((N-M>0) ? N-M : 0),LDA=Mdata,LWORK=N*bs; 6852e68589bSMark F. Adams PetscScalar *qqc,*qqr,*TAU,*WORK; 6862e68589bSMark F. Adams PetscInt *fids; 68765d7b583SSatish Balay PetscReal *data; 688b817416eSBarry Smith 6890cbbd2e1SMark F. Adams /* count agg */ 6900cbbd2e1SMark F. Adams if (asz<minsz) minsz = asz; 6910cbbd2e1SMark F. Adams 6920cbbd2e1SMark F. Adams /* get block */ 6939566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(Mdata*N, &qqc,M*N, &qqr,N, &TAU,LWORK, &WORK,M, &fids)); 6942e68589bSMark F. Adams 6952e68589bSMark F. Adams aggID = 0; 6969566063dSJacob Faibussowitsch PetscCall(PetscCDGetHeadPos(agg_llists,lid,&pos)); 697e78576d6SMark F. Adams while (pos) { 698e78576d6SMark F. Adams PetscInt gid1; 6999566063dSJacob Faibussowitsch PetscCall(PetscCDIntNdGetID(pos, &gid1)); 7009566063dSJacob Faibussowitsch PetscCall(PetscCDGetNextPos(agg_llists,lid,&pos)); 701e78576d6SMark F. Adams 7020cbbd2e1SMark F. Adams if (gid1 >= my0 && gid1 < Iend) flid = gid1 - my0; 7030cbbd2e1SMark F. Adams else { 7049566063dSJacob Faibussowitsch PetscCall(PCGAMGHashTableFind(&fgid_flid, gid1, &flid)); 70508401ef6SPierre Jolivet PetscCheck(flid >= 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot find gid1 in table"); 7060cbbd2e1SMark F. Adams } 7072e68589bSMark F. Adams /* copy in B_i matrix - column oriented */ 70865d7b583SSatish Balay data = &data_in[flid*bs]; 7093d3eaba7SBarry Smith for (ii = 0; ii < bs; ii++) { 7102e68589bSMark F. Adams for (jj = 0; jj < N; jj++) { 7110cbbd2e1SMark F. Adams PetscReal d = data[jj*data_stride + ii]; 7120cbbd2e1SMark F. Adams qqc[jj*Mdata + aggID*bs + ii] = d; 7132e68589bSMark F. Adams } 7142e68589bSMark F. Adams } 7152e68589bSMark F. Adams /* set fine IDs */ 7162e68589bSMark F. Adams for (kk=0; kk<bs; kk++) fids[aggID*bs + kk] = flid_fgid[flid]*bs + kk; 7172e68589bSMark F. Adams aggID++; 7180cbbd2e1SMark F. Adams } 7192e68589bSMark F. Adams 7202e68589bSMark F. Adams /* pad with zeros */ 7212e68589bSMark F. Adams for (ii = asz*bs; ii < Mdata; ii++) { 7222e68589bSMark F. Adams for (jj = 0; jj < N; jj++, kk++) { 7232e68589bSMark F. Adams qqc[jj*Mdata + ii] = .0; 7242e68589bSMark F. Adams } 7252e68589bSMark F. Adams } 7262e68589bSMark F. Adams 7272e68589bSMark F. Adams /* QR */ 7289566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 7298b83055fSJed Brown PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Mdata, &N, qqc, &LDA, TAU, WORK, &LWORK, &INFO)); 7309566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 73108401ef6SPierre Jolivet PetscCheck(INFO == 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"xGEQRF error"); 7322e68589bSMark F. Adams /* get R - column oriented - output B_{i+1} */ 7332e68589bSMark F. Adams { 7342e68589bSMark F. Adams PetscReal *data = &out_data[clid*nSAvec]; 7352e68589bSMark F. Adams for (jj = 0; jj < nSAvec; jj++) { 7362e68589bSMark F. Adams for (ii = 0; ii < nSAvec; ii++) { 73708401ef6SPierre Jolivet PetscCheck(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); 7380cbbd2e1SMark F. Adams if (ii <= jj) data[jj*out_data_stride + ii] = PetscRealPart(qqc[jj*Mdata + ii]); 7390cbbd2e1SMark F. Adams else data[jj*out_data_stride + ii] = 0.; 7402e68589bSMark F. Adams } 7412e68589bSMark F. Adams } 7422e68589bSMark F. Adams } 7432e68589bSMark F. Adams 7442e68589bSMark F. Adams /* get Q - row oriented */ 745c964aadfSJose E. Roman PetscStackCallBLAS("LAPACKorgqr",LAPACKorgqr_(&Mdata, &N, &N, qqc, &LDA, TAU, WORK, &LWORK, &INFO)); 74663a3b9bcSJacob Faibussowitsch PetscCheck(INFO == 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"xORGQR error arg %" PetscBLASInt_FMT,-INFO); 7472e68589bSMark F. Adams 7482e68589bSMark F. Adams for (ii = 0; ii < M; ii++) { 7492e68589bSMark F. Adams for (jj = 0; jj < N; jj++) { 7502e68589bSMark F. Adams qqr[N*ii + jj] = qqc[jj*Mdata + ii]; 7512e68589bSMark F. Adams } 7522e68589bSMark F. Adams } 7532e68589bSMark F. Adams 7542e68589bSMark F. Adams /* add diagonal block of P0 */ 755c8b0795cSMark F. Adams for (kk=0; kk<N; kk++) { 756c8b0795cSMark F. Adams cids[kk] = N*cgid + kk; /* global col IDs in P0 */ 757c8b0795cSMark F. Adams } 7589566063dSJacob Faibussowitsch PetscCall(MatSetValues(a_Prol,M,fids,N,cids,qqr,INSERT_VALUES)); 7599566063dSJacob Faibussowitsch PetscCall(PetscFree5(qqc,qqr,TAU,WORK,fids)); 760b43b03e9SMark F. Adams clid++; 7610cbbd2e1SMark F. Adams } /* coarse agg */ 7620cbbd2e1SMark F. Adams } /* for all fine nodes */ 7639566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(a_Prol,MAT_FINAL_ASSEMBLY)); 7649566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(a_Prol,MAT_FINAL_ASSEMBLY)); 7659566063dSJacob Faibussowitsch PetscCall(PCGAMGHashTableDestroy(&fgid_flid)); 7662e68589bSMark F. Adams PetscFunctionReturn(0); 7672e68589bSMark F. Adams } 7682e68589bSMark F. Adams 7695adeb434SBarry Smith static PetscErrorCode PCView_GAMG_AGG(PC pc,PetscViewer viewer) 7705adeb434SBarry Smith { 7715adeb434SBarry Smith PC_MG *mg = (PC_MG*)pc->data; 7725adeb434SBarry Smith PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 7735adeb434SBarry Smith PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 7745adeb434SBarry Smith 7755adeb434SBarry Smith PetscFunctionBegin; 7769566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," AGG specific options\n")); 7779566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Symmetric graph %s\n",pc_gamg_agg->sym_graph ? "true" : "false")); 77863a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Number of levels to square graph %" PetscInt_FMT "\n",pc_gamg_agg->square_graph)); 77963a3b9bcSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer," Number smoothing steps %" PetscInt_FMT "\n",pc_gamg_agg->nsmooths)); 7805adeb434SBarry Smith PetscFunctionReturn(0); 7815adeb434SBarry Smith } 7825adeb434SBarry Smith 7832e68589bSMark F. Adams /* -------------------------------------------------------------------------- */ 7842e68589bSMark F. Adams /* 785fd1112cbSBarry Smith PCGAMGGraph_AGG 7862e68589bSMark F. Adams 7872e68589bSMark F. Adams Input Parameter: 7882e68589bSMark F. Adams . pc - this 7892e68589bSMark F. Adams . Amat - matrix on this fine level 7902e68589bSMark F. Adams Output Parameter: 791c8b0795cSMark F. Adams . a_Gmat - 7922e68589bSMark F. Adams */ 793e0877f53SBarry Smith static PetscErrorCode PCGAMGGraph_AGG(PC pc,Mat Amat,Mat *a_Gmat) 794c8b0795cSMark F. Adams { 795c8b0795cSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 796c8b0795cSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 797c1eae691SMark Adams const PetscReal vfilter = pc_gamg->threshold[pc_gamg->current_level]; 798c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 799*72833a62Smarkadams4 Mat Gmat,F=NULL; 8003b4367a7SBarry Smith MPI_Comm comm; 80167744fedSMark F. Adams PetscBool /* set,flg , */ symm; 802c8b0795cSMark F. Adams 803c8b0795cSMark F. Adams PetscFunctionBegin; 8049566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)Amat,&comm)); 805c8b0795cSMark F. Adams 8069566063dSJacob Faibussowitsch /* PetscCall(MatIsSymmetricKnown(Amat, &set, &flg)); || !(set && flg) -- this causes lot of symm calls */ 807c666adbfSMark F. Adams symm = (PetscBool)(pc_gamg_agg->sym_graph); /* && !pc_gamg_agg->square_graph; */ 8080cbbd2e1SMark F. Adams 809849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_GRAPH],0,0,0,0)); 810*72833a62Smarkadams4 PetscCall(MatCreateGraph(Amat, symm, PETSC_TRUE, &Gmat)); 811849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_GRAPH],0,0,0,0)); 812849bee69SMark Adams 813849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_FILTER],0,0,0,0)); 814*72833a62Smarkadams4 PetscCall(MatFilter(Gmat, vfilter,&F)); 815*72833a62Smarkadams4 if (F) { 816*72833a62Smarkadams4 PetscCall(MatDestroy(&Gmat)); 817*72833a62Smarkadams4 Gmat = F; 818*72833a62Smarkadams4 } 819849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_FILTER],0,0,0,0)); 820849bee69SMark Adams 821e0940f08SMark F. Adams *a_Gmat = Gmat; 822849bee69SMark Adams 823c8b0795cSMark F. Adams PetscFunctionReturn(0); 824c8b0795cSMark F. Adams } 825c8b0795cSMark F. Adams 826c8b0795cSMark F. Adams /* -------------------------------------------------------------------------- */ 827c8b0795cSMark F. Adams /* 828b43b03e9SMark F. Adams PCGAMGCoarsen_AGG 829c8b0795cSMark F. Adams 830c8b0795cSMark F. Adams Input Parameter: 831e0940f08SMark F. Adams . a_pc - this 832e0940f08SMark F. Adams Input/Output Parameter: 8330cbbd2e1SMark F. Adams . a_Gmat1 - graph on this fine level - coarsening can change this (squares it) 834c8b0795cSMark F. Adams Output Parameter: 8350cbbd2e1SMark F. Adams . agg_lists - list of aggregates 836c8b0795cSMark F. Adams */ 837e0877f53SBarry Smith static PetscErrorCode PCGAMGCoarsen_AGG(PC a_pc,Mat *a_Gmat1,PetscCoarsenData **agg_lists) 838c8b0795cSMark F. Adams { 839e0940f08SMark F. Adams PC_MG *mg = (PC_MG*)a_pc->data; 840c8b0795cSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 841c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 8420cbbd2e1SMark F. Adams Mat mat,Gmat2, Gmat1 = *a_Gmat1; /* squared graph */ 8430cbbd2e1SMark F. Adams IS perm; 8445cfd4bd9SMark Adams PetscInt Istart,Iend,Ii,nloc,bs,n,m; 845c8b0795cSMark F. Adams PetscInt *permute; 846c8b0795cSMark F. Adams PetscBool *bIndexSet; 847b43b03e9SMark F. Adams MatCoarsen crs; 8483b4367a7SBarry Smith MPI_Comm comm; 849aea53286SMark Adams PetscReal hashfact; 850e2c00dcbSBarry Smith PetscInt iSwapIndex; 8513b50add6SMark Adams PetscRandom random; 852c8b0795cSMark F. Adams 853c8b0795cSMark F. Adams PetscFunctionBegin; 854849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_COARSEN],0,0,0,0)); 8559566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)Gmat1,&comm)); 8569566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Gmat1, &n, &m)); 8579566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(Gmat1, &bs)); 85863a3b9bcSJacob Faibussowitsch PetscCheck(bs == 1,PETSC_COMM_SELF,PETSC_ERR_PLIB,"bs %" PetscInt_FMT " must be 1",bs); 859c8b0795cSMark F. Adams nloc = n/bs; 860c8b0795cSMark F. Adams 8619ab59c8bSMark Adams if (pc_gamg->current_level < pc_gamg_agg->square_graph) { 862849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_SQUARE],0,0,0,0)); 8639566063dSJacob Faibussowitsch PetscCall(PCGAMGSquareGraph_GAMG(a_pc,Gmat1,&Gmat2)); 864849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_SQUARE],0,0,0,0)); 865806fa848SBarry Smith } else Gmat2 = Gmat1; 866c8b0795cSMark F. Adams 8675cfd4bd9SMark Adams /* get MIS aggs - randomize */ 8689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nloc, &permute)); 8699566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nloc, &bIndexSet)); 8706e09b0e3SStefano Zampini for (Ii = 0; Ii < nloc; Ii++) permute[Ii] = Ii; 8719566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PETSC_COMM_SELF,&random)); 8729566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(Gmat1, &Istart, &Iend)); 873c8b0795cSMark F. Adams for (Ii = 0; Ii < nloc; Ii++) { 8749566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValueReal(random,&hashfact)); 875aea53286SMark Adams iSwapIndex = (PetscInt) (hashfact*nloc)%nloc; 876c8b0795cSMark F. Adams if (!bIndexSet[iSwapIndex] && iSwapIndex != Ii) { 877c8b0795cSMark F. Adams PetscInt iTemp = permute[iSwapIndex]; 878c8b0795cSMark F. Adams permute[iSwapIndex] = permute[Ii]; 879c8b0795cSMark F. Adams permute[Ii] = iTemp; 880c8b0795cSMark F. Adams bIndexSet[iSwapIndex] = PETSC_TRUE; 881c8b0795cSMark F. Adams } 882c8b0795cSMark F. Adams } 8839566063dSJacob Faibussowitsch PetscCall(PetscFree(bIndexSet)); 8849566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&random)); 8859566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nloc, permute, PETSC_USE_POINTER, &perm)); 886849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_MIS],0,0,0,0)); 8879566063dSJacob Faibussowitsch PetscCall(MatCoarsenCreate(comm, &crs)); 8889566063dSJacob Faibussowitsch PetscCall(MatCoarsenSetFromOptions(crs)); 8899566063dSJacob Faibussowitsch PetscCall(MatCoarsenSetGreedyOrdering(crs, perm)); 8909566063dSJacob Faibussowitsch PetscCall(MatCoarsenSetAdjacency(crs, Gmat2)); 8919566063dSJacob Faibussowitsch PetscCall(MatCoarsenSetStrictAggs(crs, PETSC_TRUE)); 8929566063dSJacob Faibussowitsch PetscCall(MatCoarsenApply(crs)); 8939566063dSJacob Faibussowitsch PetscCall(MatCoarsenGetData(crs, agg_lists)); /* output */ 8949566063dSJacob Faibussowitsch PetscCall(MatCoarsenDestroy(&crs)); 895b43b03e9SMark F. Adams 8969566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 8979566063dSJacob Faibussowitsch PetscCall(PetscFree(permute)); 898849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_MIS],0,0,0,0)); 8999f3f12c8SMark F. Adams 900c8b0795cSMark F. Adams /* smooth aggs */ 901e0940f08SMark F. Adams if (Gmat2 != Gmat1) { 9020cbbd2e1SMark F. Adams const PetscCoarsenData *llist = *agg_lists; 9039566063dSJacob Faibussowitsch PetscCall(smoothAggs(a_pc,Gmat2, Gmat1, *agg_lists)); 9049566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Gmat1)); 905e0940f08SMark F. Adams *a_Gmat1 = Gmat2; /* output */ 9069566063dSJacob Faibussowitsch PetscCall(PetscCDGetMat(llist, &mat)); 90728b400f6SJacob Faibussowitsch PetscCheck(!mat,comm,PETSC_ERR_ARG_WRONG, "Auxilary matrix with squared graph????"); 908806fa848SBarry Smith } else { 9090cbbd2e1SMark F. Adams const PetscCoarsenData *llist = *agg_lists; 9109ab59c8bSMark Adams /* see if we have a matrix that takes precedence (returned from MatCoarsenApply) */ 9119566063dSJacob Faibussowitsch PetscCall(PetscCDGetMat(llist, &mat)); 9120cbbd2e1SMark F. Adams if (mat) { 9139566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Gmat1)); 9140cbbd2e1SMark F. Adams *a_Gmat1 = mat; /* output */ 9150cbbd2e1SMark F. Adams } 9160cbbd2e1SMark F. Adams } 917849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_COARSEN],0,0,0,0)); 918c8b0795cSMark F. Adams PetscFunctionReturn(0); 919c8b0795cSMark F. Adams } 920c8b0795cSMark F. Adams 921c8b0795cSMark F. Adams /* -------------------------------------------------------------------------- */ 922c8b0795cSMark F. Adams /* 9230cbbd2e1SMark F. Adams PCGAMGProlongator_AGG 924c8b0795cSMark F. Adams 925c8b0795cSMark F. Adams Input Parameter: 926c8b0795cSMark F. Adams . pc - this 927c8b0795cSMark F. Adams . Amat - matrix on this fine level 928c8b0795cSMark F. Adams . Graph - used to get ghost data for nodes in 9290cbbd2e1SMark F. Adams . agg_lists - list of aggregates 930c8b0795cSMark F. Adams Output Parameter: 931c8b0795cSMark F. Adams . a_P_out - prolongation operator to the next level 932c8b0795cSMark F. Adams */ 933e0877f53SBarry Smith static PetscErrorCode PCGAMGProlongator_AGG(PC pc,Mat Amat,Mat Gmat,PetscCoarsenData *agg_lists,Mat *a_P_out) 9342e68589bSMark F. Adams { 9352e68589bSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 9362e68589bSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 9374a2f8832SBarry Smith const PetscInt col_bs = pc_gamg->data_cell_cols; 938c8b0795cSMark F. Adams PetscInt Istart,Iend,nloc,ii,jj,kk,my0,nLocalSelected,bs; 939c8b0795cSMark F. Adams Mat Prol; 940d5d25401SBarry Smith PetscMPIInt size; 9413b4367a7SBarry Smith MPI_Comm comm; 942c8b0795cSMark F. Adams PetscReal *data_w_ghost; 943c8b0795cSMark F. Adams PetscInt myCrs0, nbnodes=0, *flid_fgid; 944d9558ea9SBarry Smith MatType mtype; 9452e68589bSMark F. Adams 9462e68589bSMark F. Adams PetscFunctionBegin; 9479566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)Amat,&comm)); 94808401ef6SPierre Jolivet PetscCheck(col_bs >= 1,comm,PETSC_ERR_PLIB,"Column bs cannot be less than 1"); 949849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_PROL],0,0,0,0)); 9509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 9519566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(Amat, &Istart, &Iend)); 9529566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(Amat, &bs)); 95371959b99SBarry Smith nloc = (Iend-Istart)/bs; my0 = Istart/bs; 95463a3b9bcSJacob Faibussowitsch PetscCheck((Iend-Istart) % bs == 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"(Iend %" PetscInt_FMT " - Istart %" PetscInt_FMT ") not divisible by bs %" PetscInt_FMT,Iend,Istart,bs); 9552e68589bSMark F. Adams 9562e68589bSMark F. Adams /* get 'nLocalSelected' */ 9570cbbd2e1SMark F. Adams for (ii=0, nLocalSelected = 0; ii < nloc; ii++) { 958e78576d6SMark F. Adams PetscBool ise; 9590cbbd2e1SMark F. Adams /* filter out singletons 0 or 1? */ 9609566063dSJacob Faibussowitsch PetscCall(PetscCDEmptyAt(agg_lists, ii, &ise)); 961e78576d6SMark F. Adams if (!ise) nLocalSelected++; 9622e68589bSMark F. Adams } 9632e68589bSMark F. Adams 9642e68589bSMark F. Adams /* create prolongator, create P matrix */ 9659566063dSJacob Faibussowitsch PetscCall(MatGetType(Amat,&mtype)); 9669566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &Prol)); 9679566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Prol,nloc*bs,nLocalSelected*col_bs,PETSC_DETERMINE,PETSC_DETERMINE)); 9689566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(Prol, bs, col_bs)); 9699566063dSJacob Faibussowitsch PetscCall(MatSetType(Prol, mtype)); 9709566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(Prol,col_bs, NULL)); 9719566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(Prol,col_bs, NULL, col_bs, NULL)); 9722e68589bSMark F. Adams 9732e68589bSMark F. Adams /* can get all points "removed" */ 9749566063dSJacob Faibussowitsch PetscCall(MatGetSize(Prol, &kk, &ii)); 9757f66b68fSMark Adams if (!ii) { 97663a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(pc,"%s: No selected points on coarse grid\n",((PetscObject)pc)->prefix)); 9779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Prol)); 9780298fd71SBarry Smith *a_P_out = NULL; /* out */ 979849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_PROL],0,0,0,0)); 9802e68589bSMark F. Adams PetscFunctionReturn(0); 9812e68589bSMark F. Adams } 98263a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(pc,"%s: New grid %" PetscInt_FMT " nodes\n",((PetscObject)pc)->prefix,ii/col_bs)); 9839566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(Prol, &myCrs0, &kk)); 9840cbbd2e1SMark F. Adams 98563a3b9bcSJacob Faibussowitsch PetscCheck((kk-myCrs0) % col_bs == 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"(kk %" PetscInt_FMT " -myCrs0 %" PetscInt_FMT ") not divisible by col_bs %" PetscInt_FMT,kk,myCrs0,col_bs); 986c8b0795cSMark F. Adams myCrs0 = myCrs0/col_bs; 98763a3b9bcSJacob Faibussowitsch PetscCheck((kk/col_bs-myCrs0) == nLocalSelected,PETSC_COMM_SELF,PETSC_ERR_PLIB,"(kk %" PetscInt_FMT "/col_bs %" PetscInt_FMT " - myCrs0 %" PetscInt_FMT ") != nLocalSelected %" PetscInt_FMT ")",kk,col_bs,myCrs0,nLocalSelected); 9882e68589bSMark F. Adams 9892e68589bSMark F. Adams /* create global vector of data in 'data_w_ghost' */ 990849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_PROLA],0,0,0,0)); 991c5df96a5SBarry Smith if (size > 1) { /* */ 9922e68589bSMark F. Adams PetscReal *tmp_gdata,*tmp_ldata,*tp2; 9939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nloc, &tmp_ldata)); 9944a2f8832SBarry Smith for (jj = 0; jj < col_bs; jj++) { 995c8b0795cSMark F. Adams for (kk = 0; kk < bs; kk++) { 996a2f3521dSMark F. Adams PetscInt ii,stride; 997c8b0795cSMark F. Adams const PetscReal *tp = pc_gamg->data + jj*bs*nloc + kk; 9982fa5cd67SKarl Rupp for (ii = 0; ii < nloc; ii++, tp += bs) tmp_ldata[ii] = *tp; 9992fa5cd67SKarl Rupp 10009566063dSJacob Faibussowitsch PetscCall(PCGAMGGetDataWithGhosts(Gmat, 1, tmp_ldata, &stride, &tmp_gdata)); 1001a2f3521dSMark F. Adams 10027f66b68fSMark Adams if (!jj && !kk) { /* now I know how many todal nodes - allocate */ 10039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(stride*bs*col_bs, &data_w_ghost)); 1004a2f3521dSMark F. Adams nbnodes = bs*stride; 10052e68589bSMark F. Adams } 1006a2f3521dSMark F. Adams tp2 = data_w_ghost + jj*bs*stride + kk; 10072fa5cd67SKarl Rupp for (ii = 0; ii < stride; ii++, tp2 += bs) *tp2 = tmp_gdata[ii]; 10089566063dSJacob Faibussowitsch PetscCall(PetscFree(tmp_gdata)); 10092e68589bSMark F. Adams } 10102e68589bSMark F. Adams } 10119566063dSJacob Faibussowitsch PetscCall(PetscFree(tmp_ldata)); 1012806fa848SBarry Smith } else { 1013c8b0795cSMark F. Adams nbnodes = bs*nloc; 1014c8b0795cSMark F. Adams data_w_ghost = (PetscReal*)pc_gamg->data; 10152e68589bSMark F. Adams } 10162e68589bSMark F. Adams 10172e68589bSMark F. Adams /* get P0 */ 1018c5df96a5SBarry Smith if (size > 1) { 10192e68589bSMark F. Adams PetscReal *fid_glid_loc,*fiddata; 1020a2f3521dSMark F. Adams PetscInt stride; 10212e68589bSMark F. Adams 10229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nloc, &fid_glid_loc)); 10232e68589bSMark F. Adams for (kk=0; kk<nloc; kk++) fid_glid_loc[kk] = (PetscReal)(my0+kk); 10249566063dSJacob Faibussowitsch PetscCall(PCGAMGGetDataWithGhosts(Gmat, 1, fid_glid_loc, &stride, &fiddata)); 10259566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(stride, &flid_fgid)); 1026a2f3521dSMark F. Adams for (kk=0; kk<stride; kk++) flid_fgid[kk] = (PetscInt)fiddata[kk]; 10279566063dSJacob Faibussowitsch PetscCall(PetscFree(fiddata)); 1028a2f3521dSMark F. Adams 102963a3b9bcSJacob Faibussowitsch PetscCheck(stride == nbnodes/bs,PETSC_COMM_SELF,PETSC_ERR_PLIB,"stride %" PetscInt_FMT " != nbnodes %" PetscInt_FMT "/bs %" PetscInt_FMT,stride,nbnodes,bs); 10309566063dSJacob Faibussowitsch PetscCall(PetscFree(fid_glid_loc)); 1031806fa848SBarry Smith } else { 10329566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nloc, &flid_fgid)); 10332e68589bSMark F. Adams for (kk=0; kk<nloc; kk++) flid_fgid[kk] = my0 + kk; 10342e68589bSMark F. Adams } 1035849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_PROLA],0,0,0,0)); 1036849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_PROLB],0,0,0,0)); 1037c8b0795cSMark F. Adams { 10380298fd71SBarry Smith PetscReal *data_out = NULL; 10399566063dSJacob Faibussowitsch PetscCall(formProl0(agg_lists, bs, col_bs, myCrs0, nbnodes,data_w_ghost, flid_fgid, &data_out, Prol)); 10409566063dSJacob Faibussowitsch PetscCall(PetscFree(pc_gamg->data)); 10412fa5cd67SKarl Rupp 1042c8b0795cSMark F. Adams pc_gamg->data = data_out; 10434a2f8832SBarry Smith pc_gamg->data_cell_rows = col_bs; 10444a2f8832SBarry Smith pc_gamg->data_sz = col_bs*col_bs*nLocalSelected; 1045c8b0795cSMark F. Adams } 1046849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_PROLB],0,0,0,0)); 1047849bee69SMark Adams if (size > 1) {PetscCall(PetscFree(data_w_ghost));} 10489566063dSJacob Faibussowitsch PetscCall(PetscFree(flid_fgid)); 10492e68589bSMark F. Adams 1050c8b0795cSMark F. Adams *a_P_out = Prol; /* out */ 1051ed4e82eaSPeter Brune 1052849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_PROL],0,0,0,0)); 1053c8b0795cSMark F. Adams PetscFunctionReturn(0); 1054c8b0795cSMark F. Adams } 1055c8b0795cSMark F. Adams 1056c8b0795cSMark F. Adams /* -------------------------------------------------------------------------- */ 1057c8b0795cSMark F. Adams /* 1058fd1112cbSBarry Smith PCGAMGOptProlongator_AGG 1059c8b0795cSMark F. Adams 1060c8b0795cSMark F. Adams Input Parameter: 1061c8b0795cSMark F. Adams . pc - this 1062c8b0795cSMark F. Adams . Amat - matrix on this fine level 1063c8b0795cSMark F. Adams In/Output Parameter: 10642a808120SBarry Smith . a_P - prolongation operator to the next level 1065c8b0795cSMark F. Adams */ 1066e0877f53SBarry Smith static PetscErrorCode PCGAMGOptProlongator_AGG(PC pc,Mat Amat,Mat *a_P) 1067c8b0795cSMark F. Adams { 1068c8b0795cSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 1069c8b0795cSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 1070c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 1071c8b0795cSMark F. Adams PetscInt jj; 1072c8b0795cSMark F. Adams Mat Prol = *a_P; 10733b4367a7SBarry Smith MPI_Comm comm; 10742a808120SBarry Smith KSP eksp; 10752a808120SBarry Smith Vec bb, xx; 10762a808120SBarry Smith PC epc; 10772a808120SBarry Smith PetscReal alpha, emax, emin; 1078c8b0795cSMark F. Adams 1079c8b0795cSMark F. Adams PetscFunctionBegin; 10809566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)Amat,&comm)); 1081849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_OPT],0,0,0,0)); 1082c8b0795cSMark F. Adams 1083d5d25401SBarry Smith /* compute maximum singular value of operator to be used in smoother */ 10842a808120SBarry Smith if (0 < pc_gamg_agg->nsmooths) { 108518c3aa7eSMark /* get eigen estimates */ 108618c3aa7eSMark if (pc_gamg->emax > 0) { 108718c3aa7eSMark emin = pc_gamg->emin; 108818c3aa7eSMark emax = pc_gamg->emax; 108918c3aa7eSMark } else { 10900ed2132dSStefano Zampini const char *prefix; 10910ed2132dSStefano Zampini 10929566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(Amat, &bb, NULL)); 10939566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(Amat, &xx, NULL)); 10949566063dSJacob Faibussowitsch PetscCall(KSPSetNoisy_Private(bb)); 1095e696ed0bSMark F. Adams 10969566063dSJacob Faibussowitsch PetscCall(KSPCreate(comm,&eksp)); 10979566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc,&prefix)); 10989566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(eksp,prefix)); 10999566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(eksp,"pc_gamg_esteig_")); 110073f7197eSJed Brown { 1101acbb5b45SJed Brown PetscBool sflg; 11029566063dSJacob Faibussowitsch PetscCall(MatGetOption(Amat, MAT_SPD, &sflg)); 11031baa6e33SBarry Smith if (sflg) PetscCall(KSPSetType(eksp, KSPCG)); 1104d24ecf33SMark } 11059566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(eksp,pc->erroriffailure)); 11069566063dSJacob Faibussowitsch PetscCall(KSPSetNormType(eksp, KSP_NORM_NONE)); 1107c2436cacSMark F. Adams 11089566063dSJacob Faibussowitsch PetscCall(KSPSetInitialGuessNonzero(eksp, PETSC_FALSE)); 11099566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(eksp, Amat, Amat)); 11102e68589bSMark F. Adams 11119566063dSJacob Faibussowitsch PetscCall(KSPGetPC(eksp, &epc)); 11129566063dSJacob Faibussowitsch PetscCall(PCSetType(epc, PCJACOBI)); /* smoother in smoothed agg. */ 1113c2436cacSMark F. Adams 11149566063dSJacob Faibussowitsch PetscCall(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 1115074aec55SMark Adams 11169566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(eksp)); 11179566063dSJacob Faibussowitsch PetscCall(KSPSetComputeSingularValues(eksp,PETSC_TRUE)); 11189566063dSJacob Faibussowitsch PetscCall(KSPSolve(eksp, bb, xx)); 11199566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(eksp,pc,xx)); 11202e68589bSMark F. Adams 11219566063dSJacob Faibussowitsch PetscCall(KSPComputeExtremeSingularValues(eksp, &emax, &emin)); 11229566063dSJacob Faibussowitsch PetscCall(PetscInfo(pc,"%s: Smooth P0: max eigen=%e min=%e PC=%s\n",((PetscObject)pc)->prefix,(double)emax,(double)emin,PCJACOBI)); 11239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xx)); 11249566063dSJacob Faibussowitsch PetscCall(VecDestroy(&bb)); 11259566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&eksp)); 11262e68589bSMark F. Adams } 112718c3aa7eSMark if (pc_gamg->use_sa_esteig) { 112818c3aa7eSMark mg->min_eigen_DinvA[pc_gamg->current_level] = emin; 112918c3aa7eSMark mg->max_eigen_DinvA[pc_gamg->current_level] = emax; 113063a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(pc,"%s: Smooth P0: level %" PetscInt_FMT ", cache spectra %g %g\n",((PetscObject)pc)->prefix,pc_gamg->current_level,(double)emin,(double)emax)); 113118c3aa7eSMark } else { 113218c3aa7eSMark mg->min_eigen_DinvA[pc_gamg->current_level] = 0; 113318c3aa7eSMark mg->max_eigen_DinvA[pc_gamg->current_level] = 0; 113418c3aa7eSMark } 113518c3aa7eSMark } else { 113618c3aa7eSMark mg->min_eigen_DinvA[pc_gamg->current_level] = 0; 113718c3aa7eSMark mg->max_eigen_DinvA[pc_gamg->current_level] = 0; 113818c3aa7eSMark } 11392e68589bSMark F. Adams 11402a808120SBarry Smith /* smooth P0 */ 11412a808120SBarry Smith for (jj = 0; jj < pc_gamg_agg->nsmooths; jj++) { 11422a808120SBarry Smith Mat tMat; 11432a808120SBarry Smith Vec diag; 11442a808120SBarry Smith 1145849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_OPTSM],0,0,0,0)); 11462a808120SBarry Smith 11472e68589bSMark F. Adams /* smooth P1 := (I - omega/lam D^{-1}A)P0 */ 11489566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(petsc_gamg_setup_matmat_events[pc_gamg->current_level][2],0,0,0,0)); 11499566063dSJacob Faibussowitsch PetscCall(MatMatMult(Amat, Prol, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &tMat)); 11509566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(petsc_gamg_setup_matmat_events[pc_gamg->current_level][2],0,0,0,0)); 11519566063dSJacob Faibussowitsch PetscCall(MatProductClear(tMat)); 11529566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(Amat, &diag, NULL)); 11539566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(Amat, diag)); /* effectively PCJACOBI */ 11549566063dSJacob Faibussowitsch PetscCall(VecReciprocal(diag)); 11559566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(tMat, diag, NULL)); 11569566063dSJacob Faibussowitsch PetscCall(VecDestroy(&diag)); 1157b4da3a1bSStefano Zampini 1158d5d25401SBarry Smith /* TODO: Set a PCFailedReason and exit the building of the AMG preconditioner */ 115908401ef6SPierre Jolivet PetscCheck(emax != 0.0,PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Computed maximum singular value as zero"); 1160d5d25401SBarry Smith /* TODO: Document the 1.4 and don't hardwire it in this routine */ 1161b4ec6429SMark F. Adams alpha = -1.4/emax; 1162b4da3a1bSStefano Zampini 11639566063dSJacob Faibussowitsch PetscCall(MatAYPX(tMat, alpha, Prol, SUBSET_NONZERO_PATTERN)); 11649566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Prol)); 11652e68589bSMark F. Adams Prol = tMat; 1166849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_OPTSM],0,0,0,0)); 11672e68589bSMark F. Adams } 1168849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_OPT],0,0,0,0)); 1169c8b0795cSMark F. Adams *a_P = Prol; 1170c8b0795cSMark F. Adams PetscFunctionReturn(0); 11712e68589bSMark F. Adams } 11722e68589bSMark F. Adams 1173c8b0795cSMark F. Adams /* -------------------------------------------------------------------------- */ 1174c8b0795cSMark F. Adams /* 1175c8b0795cSMark F. Adams PCCreateGAMG_AGG 11762e68589bSMark F. Adams 1177c8b0795cSMark F. Adams Input Parameter: 1178c8b0795cSMark F. Adams . pc - 1179c8b0795cSMark F. Adams */ 1180c8b0795cSMark F. Adams PetscErrorCode PCCreateGAMG_AGG(PC pc) 1181c8b0795cSMark F. Adams { 1182c8b0795cSMark F. Adams PC_MG *mg = (PC_MG*)pc->data; 1183c8b0795cSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 1184c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg; 11852e68589bSMark F. Adams 1186c8b0795cSMark F. Adams PetscFunctionBegin; 1187c8b0795cSMark F. Adams /* create sub context for SA */ 11889566063dSJacob Faibussowitsch PetscCall(PetscNewLog(pc,&pc_gamg_agg)); 1189c8b0795cSMark F. Adams pc_gamg->subctx = pc_gamg_agg; 1190c8b0795cSMark F. Adams 11911ab5ffc9SJed Brown pc_gamg->ops->setfromoptions = PCSetFromOptions_GAMG_AGG; 11929b8ffb57SJed Brown pc_gamg->ops->destroy = PCDestroy_GAMG_AGG; 1193c8b0795cSMark F. Adams /* reset does not do anything; setup not virtual */ 1194c8b0795cSMark F. Adams 1195c8b0795cSMark F. Adams /* set internal function pointers */ 1196fd1112cbSBarry Smith pc_gamg->ops->graph = PCGAMGGraph_AGG; 11971ab5ffc9SJed Brown pc_gamg->ops->coarsen = PCGAMGCoarsen_AGG; 11981ab5ffc9SJed Brown pc_gamg->ops->prolongator = PCGAMGProlongator_AGG; 1199fd1112cbSBarry Smith pc_gamg->ops->optprolongator = PCGAMGOptProlongator_AGG; 12001ab5ffc9SJed Brown pc_gamg->ops->createdefaultdata = PCSetData_AGG; 12015adeb434SBarry Smith pc_gamg->ops->view = PCView_GAMG_AGG; 1202c8b0795cSMark F. Adams 1203cab9ed1eSBarry Smith pc_gamg_agg->square_graph = 1; 1204cab9ed1eSBarry Smith pc_gamg_agg->sym_graph = PETSC_FALSE; 1205cab9ed1eSBarry Smith pc_gamg_agg->nsmooths = 1; 1206cab9ed1eSBarry Smith 12079566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGAMGSetNSmooths_C",PCGAMGSetNSmooths_AGG)); 12089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGAMGSetSymGraph_C",PCGAMGSetSymGraph_AGG)); 12099566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCGAMGSetSquareGraph_C",PCGAMGSetSquareGraph_AGG)); 12109566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_AGG)); 12112e68589bSMark F. Adams PetscFunctionReturn(0); 12122e68589bSMark F. Adams } 1213