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; 12bae903cbSmarkadams4 PetscInt aggressive_coarsening_levels; // number of aggressive coarsening levels (square or MISk) 132d776b49SBarry Smith MatCoarsen crs; 142e68589bSMark F. Adams } PC_GAMG_AGG; 152e68589bSMark F. Adams 162e68589bSMark F. Adams /*@ 17f1580f4eSBarry Smith PCGAMGSetNSmooths - Set number of smoothing steps (1 is typical) used for multigrid on all the levels 182e68589bSMark F. Adams 19c3339decSBarry Smith Logically Collective 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 29f1580f4eSBarry Smith .seealso: `PCMG`, `PCGAMG` 302e68589bSMark F. Adams @*/ 31d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGAMGSetNSmooths(PC pc, PetscInt n) 32d71ae5a4SJacob Faibussowitsch { 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)); 37*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 382e68589bSMark F. Adams } 392e68589bSMark F. Adams 40d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGAMGSetNSmooths_AGG(PC pc, PetscInt n) 41d71ae5a4SJacob Faibussowitsch { 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; 48*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 49c8b0795cSMark F. Adams } 50c8b0795cSMark F. Adams 51c8b0795cSMark F. Adams /*@ 52f1580f4eSBarry Smith PCGAMGSetAggressiveLevels - Use aggressive coarsening on first n levels 53ef4ad70eSMark F. Adams 54c3339decSBarry Smith Logically Collective 55ef4ad70eSMark F. Adams 56ef4ad70eSMark F. Adams Input Parameters: 57cab9ed1eSBarry Smith + pc - the preconditioner context 58d5d25401SBarry Smith - n - 0, 1 or more 59ef4ad70eSMark F. Adams 60ef4ad70eSMark F. Adams Options Database Key: 61bae903cbSmarkadams4 . -pc_gamg_aggressive_coarsening <n,default = 1> - Number of levels to square the graph on before aggregating it 62af3c827dSMark Adams 63ef4ad70eSMark F. Adams Level: intermediate 64ef4ad70eSMark F. Adams 652d776b49SBarry Smith .seealso: `PCGAMG`, `PCGAMGSetThreshold()` 66ef4ad70eSMark F. Adams @*/ 67d71ae5a4SJacob Faibussowitsch PetscErrorCode PCGAMGSetAggressiveLevels(PC pc, PetscInt n) 68d71ae5a4SJacob Faibussowitsch { 69ef4ad70eSMark F. Adams PetscFunctionBegin; 70ef4ad70eSMark F. Adams PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 71d5d25401SBarry Smith PetscValidLogicalCollectiveInt(pc, n, 2); 72bae903cbSmarkadams4 PetscTryMethod(pc, "PCGAMGSetAggressiveLevels_C", (PC, PetscInt), (pc, n)); 73*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 74ef4ad70eSMark F. Adams } 75ef4ad70eSMark F. Adams 76d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGAMGSetAggressiveLevels_AGG(PC pc, PetscInt n) 77d71ae5a4SJacob Faibussowitsch { 78ef4ad70eSMark F. Adams PC_MG *mg = (PC_MG *)pc->data; 79ef4ad70eSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG *)mg->innerctx; 80ef4ad70eSMark F. Adams PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG *)pc_gamg->subctx; 81ef4ad70eSMark F. Adams 82ef4ad70eSMark F. Adams PetscFunctionBegin; 83bae903cbSmarkadams4 pc_gamg_agg->aggressive_coarsening_levels = n; 84*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 85ef4ad70eSMark F. Adams } 86ef4ad70eSMark F. Adams 87d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_GAMG_AGG(PC pc, PetscOptionItems *PetscOptionsObject) 88d71ae5a4SJacob Faibussowitsch { 892e68589bSMark F. Adams PC_MG *mg = (PC_MG *)pc->data; 902e68589bSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG *)mg->innerctx; 91c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG *)pc_gamg->subctx; 922e68589bSMark F. Adams 932e68589bSMark F. Adams PetscFunctionBegin; 94d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "GAMG-AGG options"); 952e68589bSMark F. Adams { 96bae903cbSmarkadams4 PetscBool flg; 979566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-pc_gamg_agg_nsmooths", "smoothing steps for smoothed aggregation, usually 1", "PCGAMGSetNSmooths", pc_gamg_agg->nsmooths, &pc_gamg_agg->nsmooths, NULL)); 989371c9d4SSatish Balay PetscCall( 999371c9d4SSatish Balay PetscOptionsInt("-pc_gamg_square_graph", "Number of aggressive coarsening (MIS-2) levels from finest (alias for -pc_gamg_aggressive_coarsening, deprecated)", "PCGAMGSetAggressiveLevels", pc_gamg_agg->aggressive_coarsening_levels, &pc_gamg_agg->aggressive_coarsening_levels, &flg)); 100bae903cbSmarkadams4 if (!flg) { 101bae903cbSmarkadams4 PetscCall(PetscOptionsInt("-pc_gamg_aggressive_coarsening", "Number of aggressive coarsening (MIS-2) levels from finest", "PCGAMGSetAggressiveLevels", pc_gamg_agg->aggressive_coarsening_levels, &pc_gamg_agg->aggressive_coarsening_levels, NULL)); 102bae903cbSmarkadams4 } else { 103bae903cbSmarkadams4 PetscCall(PetscOptionsInt("-pc_gamg_aggressive_coarsening", "Number of aggressive coarsening (MIS-2) levels from finest", "PCGAMGSetAggressiveLevels", pc_gamg_agg->aggressive_coarsening_levels, &pc_gamg_agg->aggressive_coarsening_levels, &flg)); 104bae903cbSmarkadams4 if (flg) PetscCall(PetscInfo(pc, "Warning: both -pc_gamg_square_graph and -pc_gamg_aggressive_coarsening are used. -pc_gamg_square_graph is deprecated, Number of aggressive levels is %d\n", (int)pc_gamg_agg->aggressive_coarsening_levels)); 105bae903cbSmarkadams4 } 1062e68589bSMark F. Adams } 107d0609cedSBarry Smith PetscOptionsHeadEnd(); 108*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1092e68589bSMark F. Adams } 1102e68589bSMark F. Adams 111d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_GAMG_AGG(PC pc) 112d71ae5a4SJacob Faibussowitsch { 1132e68589bSMark F. Adams PC_MG *mg = (PC_MG *)pc->data; 1142e68589bSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG *)mg->innerctx; 1152e68589bSMark F. Adams 1162e68589bSMark F. Adams PetscFunctionBegin; 1179566063dSJacob Faibussowitsch PetscCall(PetscFree(pc_gamg->subctx)); 1182e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGAMGSetNSmooths_C", NULL)); 119bae903cbSmarkadams4 PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGAMGSetAggressiveLevels_C", NULL)); 120bae903cbSmarkadams4 PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", NULL)); 121*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1222e68589bSMark F. Adams } 1232e68589bSMark F. Adams 1242e68589bSMark F. Adams /* 1252e68589bSMark F. Adams PCSetCoordinates_AGG 126302f38e8SMark F. Adams - collective 1272e68589bSMark F. Adams 1282e68589bSMark F. Adams Input Parameter: 1292e68589bSMark F. Adams . pc - the preconditioner context 130a2f3521dSMark F. Adams . ndm - dimesion of data (used for dof/vertex for Stokes) 131302f38e8SMark F. Adams . a_nloc - number of vertices local 132302f38e8SMark F. Adams . coords - [a_nloc][ndm] - interleaved coordinate data: {x_0, y_0, z_0, x_1, y_1, ...} 1332e68589bSMark F. Adams */ 1341e6b0712SBarry Smith 135d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetCoordinates_AGG(PC pc, PetscInt ndm, PetscInt a_nloc, PetscReal *coords) 136d71ae5a4SJacob Faibussowitsch { 1372e68589bSMark F. Adams PC_MG *mg = (PC_MG *)pc->data; 1382e68589bSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG *)mg->innerctx; 13969344418SMark F. Adams PetscInt arrsz, kk, ii, jj, nloc, ndatarows, ndf; 140a2f3521dSMark F. Adams Mat mat = pc->pmat; 1412e68589bSMark F. Adams 1422e68589bSMark F. Adams PetscFunctionBegin; 143a2f3521dSMark F. Adams PetscValidHeaderSpecific(pc, PC_CLASSID, 1); 144a2f3521dSMark F. Adams PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 145302f38e8SMark F. Adams nloc = a_nloc; 1462e68589bSMark F. Adams 1472e68589bSMark F. Adams /* SA: null space vectors */ 1489566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(mat, &ndf)); /* this does not work for Stokes */ 14969344418SMark F. Adams if (coords && ndf == 1) pc_gamg->data_cell_cols = 1; /* scalar w/ coords and SA (not needed) */ 150a2f3521dSMark F. Adams else if (coords) { 15163a3b9bcSJacob Faibussowitsch PetscCheck(ndm <= ndf, PETSC_COMM_SELF, PETSC_ERR_PLIB, "degrees of motion %" PetscInt_FMT " > block size %" PetscInt_FMT, ndm, ndf); 15269344418SMark F. Adams pc_gamg->data_cell_cols = (ndm == 2 ? 3 : 6); /* displacement elasticity */ 153ad540459SPierre Jolivet if (ndm != ndf) 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); 154806fa848SBarry Smith } else pc_gamg->data_cell_cols = ndf; /* no data, force SA with constant null space vectors */ 15571959b99SBarry Smith pc_gamg->data_cell_rows = ndatarows = ndf; 15663a3b9bcSJacob 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); 157c8b0795cSMark F. Adams arrsz = nloc * pc_gamg->data_cell_rows * pc_gamg->data_cell_cols; 1582e68589bSMark F. Adams 1597f66b68fSMark Adams if (!pc_gamg->data || (pc_gamg->data_sz != arrsz)) { 1609566063dSJacob Faibussowitsch PetscCall(PetscFree(pc_gamg->data)); 1619566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(arrsz + 1, &pc_gamg->data)); 1622e68589bSMark F. Adams } 1632e68589bSMark F. Adams /* copy data in - column oriented */ 1642e68589bSMark F. Adams for (kk = 0; kk < nloc; kk++) { 16569344418SMark F. Adams const PetscInt M = nloc * pc_gamg->data_cell_rows; /* stride into data */ 16669344418SMark F. Adams PetscReal *data = &pc_gamg->data[kk * ndatarows]; /* start of cell */ 167c8b0795cSMark F. Adams if (pc_gamg->data_cell_cols == 1) *data = 1.0; 1682e68589bSMark F. Adams else { 16969344418SMark F. Adams /* translational modes */ 1702fa5cd67SKarl Rupp for (ii = 0; ii < ndatarows; ii++) { 1712fa5cd67SKarl Rupp for (jj = 0; jj < ndatarows; jj++) { 17269344418SMark F. Adams if (ii == jj) data[ii * M + jj] = 1.0; 1732e68589bSMark F. Adams else data[ii * M + jj] = 0.0; 1742fa5cd67SKarl Rupp } 1752fa5cd67SKarl Rupp } 17669344418SMark F. Adams 17769344418SMark F. Adams /* rotational modes */ 1782e68589bSMark F. Adams if (coords) { 17969344418SMark F. Adams if (ndm == 2) { 1802e68589bSMark F. Adams data += 2 * M; 1812e68589bSMark F. Adams data[0] = -coords[2 * kk + 1]; 1822e68589bSMark F. Adams data[1] = coords[2 * kk]; 183806fa848SBarry Smith } else { 1842e68589bSMark F. Adams data += 3 * M; 1859371c9d4SSatish Balay data[0] = 0.0; 1869371c9d4SSatish Balay data[M + 0] = coords[3 * kk + 2]; 1879371c9d4SSatish Balay data[2 * M + 0] = -coords[3 * kk + 1]; 1889371c9d4SSatish Balay data[1] = -coords[3 * kk + 2]; 1899371c9d4SSatish Balay data[M + 1] = 0.0; 1909371c9d4SSatish Balay data[2 * M + 1] = coords[3 * kk]; 1919371c9d4SSatish Balay data[2] = coords[3 * kk + 1]; 1929371c9d4SSatish Balay data[M + 2] = -coords[3 * kk]; 1939371c9d4SSatish Balay data[2 * M + 2] = 0.0; 1942e68589bSMark F. Adams } 1952e68589bSMark F. Adams } 1962e68589bSMark F. Adams } 1972e68589bSMark F. Adams } 1982e68589bSMark F. Adams pc_gamg->data_sz = arrsz; 199*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2002e68589bSMark F. Adams } 2012e68589bSMark F. Adams 2022e68589bSMark F. Adams /* 203a2f3521dSMark F. Adams PCSetData_AGG - called if data is not set with PCSetCoordinates. 204a2f3521dSMark F. Adams Looks in Mat for near null space. 205a2f3521dSMark F. Adams Does not work for Stokes 2062e68589bSMark F. Adams 2072e68589bSMark F. Adams Input Parameter: 2082e68589bSMark F. Adams . pc - 209a2f3521dSMark F. Adams . a_A - matrix to get (near) null space out of. 2102e68589bSMark F. Adams */ 211d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetData_AGG(PC pc, Mat a_A) 212d71ae5a4SJacob Faibussowitsch { 213b8cd405aSMark F. Adams PC_MG *mg = (PC_MG *)pc->data; 214b8cd405aSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG *)mg->innerctx; 215b8cd405aSMark F. Adams MatNullSpace mnull; 21666f2ef4bSMark Adams 217b817416eSBarry Smith PetscFunctionBegin; 2189566063dSJacob Faibussowitsch PetscCall(MatGetNearNullSpace(a_A, &mnull)); 219b8cd405aSMark F. Adams if (!mnull) { 22066f2ef4bSMark Adams DM dm; 2219566063dSJacob Faibussowitsch PetscCall(PCGetDM(pc, &dm)); 22248a46eb9SPierre Jolivet if (!dm) PetscCall(MatGetDM(a_A, &dm)); 22366f2ef4bSMark Adams if (dm) { 22466f2ef4bSMark Adams PetscObject deformation; 225b0d30dd6SMatthew G. Knepley PetscInt Nf; 226b0d30dd6SMatthew G. Knepley 2279566063dSJacob Faibussowitsch PetscCall(DMGetNumFields(dm, &Nf)); 228b0d30dd6SMatthew G. Knepley if (Nf) { 2299566063dSJacob Faibussowitsch PetscCall(DMGetField(dm, 0, NULL, &deformation)); 2309566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)deformation, "nearnullspace", (PetscObject *)&mnull)); 23148a46eb9SPierre Jolivet if (!mnull) PetscCall(PetscObjectQuery((PetscObject)deformation, "nullspace", (PetscObject *)&mnull)); 23266f2ef4bSMark Adams } 23366f2ef4bSMark Adams } 234b0d30dd6SMatthew G. Knepley } 23566f2ef4bSMark Adams 23666f2ef4bSMark Adams if (!mnull) { 237a2f3521dSMark F. Adams PetscInt bs, NN, MM; 2389566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(a_A, &bs)); 2399566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(a_A, &MM, &NN)); 24063a3b9bcSJacob Faibussowitsch PetscCheck(MM % bs == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MM %" PetscInt_FMT " must be divisible by bs %" PetscInt_FMT, MM, bs); 2419566063dSJacob Faibussowitsch PetscCall(PCSetCoordinates_AGG(pc, bs, MM / bs, NULL)); 242806fa848SBarry Smith } else { 243b8cd405aSMark F. Adams PetscReal *nullvec; 244b8cd405aSMark F. Adams PetscBool has_const; 245b8cd405aSMark F. Adams PetscInt i, j, mlocal, nvec, bs; 246d5d25401SBarry Smith const Vec *vecs; 247d5d25401SBarry Smith const PetscScalar *v; 248b817416eSBarry Smith 2499566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(a_A, &mlocal, NULL)); 2509566063dSJacob Faibussowitsch PetscCall(MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs)); 251d19c4ebbSmarkadams4 for (i = 0; i < nvec; i++) { 252d19c4ebbSmarkadams4 PetscCall(VecGetLocalSize(vecs[i], &j)); 253d19c4ebbSmarkadams4 PetscCheck(j == mlocal, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Attached null space vector size %" PetscInt_FMT " != matrix size %" PetscInt_FMT, j, mlocal); 254d19c4ebbSmarkadams4 } 255a0dea87dSMark Adams pc_gamg->data_sz = (nvec + !!has_const) * mlocal; 2569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1((nvec + !!has_const) * mlocal, &nullvec)); 2579371c9d4SSatish Balay if (has_const) 2589371c9d4SSatish Balay for (i = 0; i < mlocal; i++) nullvec[i] = 1.0; 259b8cd405aSMark F. Adams for (i = 0; i < nvec; i++) { 2609566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(vecs[i], &v)); 261b8cd405aSMark F. Adams for (j = 0; j < mlocal; j++) nullvec[(i + !!has_const) * mlocal + j] = PetscRealPart(v[j]); 2629566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(vecs[i], &v)); 263b8cd405aSMark F. Adams } 264b8cd405aSMark F. Adams pc_gamg->data = nullvec; 265b8cd405aSMark F. Adams pc_gamg->data_cell_cols = (nvec + !!has_const); 2669566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(a_A, &bs)); 267b8cd405aSMark F. Adams pc_gamg->data_cell_rows = bs; 268b8cd405aSMark F. Adams } 269*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2702e68589bSMark F. Adams } 2712e68589bSMark F. Adams 2722e68589bSMark F. Adams /* 273bae903cbSmarkadams4 formProl0 - collect null space data for each aggregate, do QR, put R in coarse grid data and Q in P_0 2742e68589bSMark F. Adams 2752e68589bSMark F. Adams Input Parameter: 2762adfe9d3SBarry Smith . agg_llists - list of arrays with aggregates -- list from selected vertices of aggregate unselected vertices 2772adfe9d3SBarry Smith . bs - row block size 2780cbbd2e1SMark F. Adams . nSAvec - column bs of new P 2790cbbd2e1SMark F. Adams . my0crs - global index of start of locals 2802adfe9d3SBarry Smith . data_stride - bs*(nloc nodes + ghost nodes) [data_stride][nSAvec] 2812e68589bSMark F. Adams . data_in[data_stride*nSAvec] - local data on fine grid 2822e68589bSMark F. Adams . flid_fgid[data_stride/bs] - make local to global IDs, includes ghosts in 'locals_llist' 283bae903cbSmarkadams4 2842e68589bSMark F. Adams Output Parameter: 2852e68589bSMark F. Adams . a_data_out - in with fine grid data (w/ghosts), out with coarse grid data 2862e68589bSMark F. Adams . a_Prol - prolongation operator 2872e68589bSMark F. Adams */ 288d71ae5a4SJacob Faibussowitsch 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) 289d71ae5a4SJacob Faibussowitsch { 290bd026e97SJed Brown PetscInt Istart, my0, Iend, nloc, clid, flid = 0, aggID, kk, jj, ii, mm, nSelected, minsz, nghosts, out_data_stride; 2913b4367a7SBarry Smith MPI_Comm comm; 2922e68589bSMark F. Adams PetscReal *out_data; 293539c167fSBarry Smith PetscCDIntNd *pos; 2941943db53SBarry Smith PCGAMGHashTable fgid_flid; 2950cbbd2e1SMark F. Adams 2962e68589bSMark F. Adams PetscFunctionBegin; 2979566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)a_Prol, &comm)); 2989566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(a_Prol, &Istart, &Iend)); 2999371c9d4SSatish Balay nloc = (Iend - Istart) / bs; 3009371c9d4SSatish Balay my0 = Istart / bs; 30163a3b9bcSJacob 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); 3020cbbd2e1SMark F. Adams Iend /= bs; 3030cbbd2e1SMark F. Adams nghosts = data_stride / bs - nloc; 3042e68589bSMark F. Adams 3059566063dSJacob Faibussowitsch PetscCall(PCGAMGHashTableCreate(2 * nghosts + 1, &fgid_flid)); 30648a46eb9SPierre Jolivet for (kk = 0; kk < nghosts; kk++) PetscCall(PCGAMGHashTableAdd(&fgid_flid, flid_fgid[nloc + kk], nloc + kk)); 3072e68589bSMark F. Adams 3080cbbd2e1SMark F. Adams /* count selected -- same as number of cols of P */ 3090cbbd2e1SMark F. Adams for (nSelected = mm = 0; mm < nloc; mm++) { 310e78576d6SMark F. Adams PetscBool ise; 3119566063dSJacob Faibussowitsch PetscCall(PetscCDEmptyAt(agg_llists, mm, &ise)); 312e78576d6SMark F. Adams if (!ise) nSelected++; 3130cbbd2e1SMark F. Adams } 3149566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(a_Prol, &ii, &jj)); 31563a3b9bcSJacob Faibussowitsch PetscCheck((ii / nSAvec) == my0crs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "ii %" PetscInt_FMT " /nSAvec %" PetscInt_FMT " != my0crs %" PetscInt_FMT, ii, nSAvec, my0crs); 31663a3b9bcSJacob 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); 3170cbbd2e1SMark F. Adams 3182e68589bSMark F. Adams /* aloc space for coarse point data (output) */ 3190cbbd2e1SMark F. Adams out_data_stride = nSelected * nSAvec; 3202fa5cd67SKarl Rupp 3219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(out_data_stride * nSAvec, &out_data)); 32233812677SSatish Balay for (ii = 0; ii < out_data_stride * nSAvec; ii++) out_data[ii] = PETSC_MAX_REAL; 3230cbbd2e1SMark F. Adams *a_data_out = out_data; /* output - stride nSelected*nSAvec */ 3242e68589bSMark F. Adams 3252e68589bSMark F. Adams /* find points and set prolongation */ 326c8b0795cSMark F. Adams minsz = 100; 3270cbbd2e1SMark F. Adams for (mm = clid = 0; mm < nloc; mm++) { 3289566063dSJacob Faibussowitsch PetscCall(PetscCDSizeAt(agg_llists, mm, &jj)); 329e78576d6SMark F. Adams if (jj > 0) { 3300cbbd2e1SMark F. Adams const PetscInt lid = mm, cgid = my0crs + clid; 3310cbbd2e1SMark F. Adams PetscInt cids[100]; /* max bs */ 3320cbbd2e1SMark F. Adams PetscBLASInt asz = jj, M = asz * bs, N = nSAvec, INFO; 3332e68589bSMark F. Adams PetscBLASInt Mdata = M + ((N - M > 0) ? N - M : 0), LDA = Mdata, LWORK = N * bs; 3342e68589bSMark F. Adams PetscScalar *qqc, *qqr, *TAU, *WORK; 3352e68589bSMark F. Adams PetscInt *fids; 33665d7b583SSatish Balay PetscReal *data; 337b817416eSBarry Smith 3380cbbd2e1SMark F. Adams /* count agg */ 3390cbbd2e1SMark F. Adams if (asz < minsz) minsz = asz; 3400cbbd2e1SMark F. Adams 3410cbbd2e1SMark F. Adams /* get block */ 3429566063dSJacob Faibussowitsch PetscCall(PetscMalloc5(Mdata * N, &qqc, M * N, &qqr, N, &TAU, LWORK, &WORK, M, &fids)); 3432e68589bSMark F. Adams 3442e68589bSMark F. Adams aggID = 0; 3459566063dSJacob Faibussowitsch PetscCall(PetscCDGetHeadPos(agg_llists, lid, &pos)); 346e78576d6SMark F. Adams while (pos) { 347e78576d6SMark F. Adams PetscInt gid1; 3489566063dSJacob Faibussowitsch PetscCall(PetscCDIntNdGetID(pos, &gid1)); 3499566063dSJacob Faibussowitsch PetscCall(PetscCDGetNextPos(agg_llists, lid, &pos)); 350e78576d6SMark F. Adams 3510cbbd2e1SMark F. Adams if (gid1 >= my0 && gid1 < Iend) flid = gid1 - my0; 3520cbbd2e1SMark F. Adams else { 3539566063dSJacob Faibussowitsch PetscCall(PCGAMGHashTableFind(&fgid_flid, gid1, &flid)); 35408401ef6SPierre Jolivet PetscCheck(flid >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cannot find gid1 in table"); 3550cbbd2e1SMark F. Adams } 3562e68589bSMark F. Adams /* copy in B_i matrix - column oriented */ 35765d7b583SSatish Balay data = &data_in[flid * bs]; 3583d3eaba7SBarry Smith for (ii = 0; ii < bs; ii++) { 3592e68589bSMark F. Adams for (jj = 0; jj < N; jj++) { 3600cbbd2e1SMark F. Adams PetscReal d = data[jj * data_stride + ii]; 3610cbbd2e1SMark F. Adams qqc[jj * Mdata + aggID * bs + ii] = d; 3622e68589bSMark F. Adams } 3632e68589bSMark F. Adams } 3642e68589bSMark F. Adams /* set fine IDs */ 3652e68589bSMark F. Adams for (kk = 0; kk < bs; kk++) fids[aggID * bs + kk] = flid_fgid[flid] * bs + kk; 3662e68589bSMark F. Adams aggID++; 3670cbbd2e1SMark F. Adams } 3682e68589bSMark F. Adams 3692e68589bSMark F. Adams /* pad with zeros */ 3702e68589bSMark F. Adams for (ii = asz * bs; ii < Mdata; ii++) { 371ad540459SPierre Jolivet for (jj = 0; jj < N; jj++, kk++) qqc[jj * Mdata + ii] = .0; 3722e68589bSMark F. Adams } 3732e68589bSMark F. Adams 3742e68589bSMark F. Adams /* QR */ 3759566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPush(PETSC_FP_TRAP_OFF)); 376792fecdfSBarry Smith PetscCallBLAS("LAPACKgeqrf", LAPACKgeqrf_(&Mdata, &N, qqc, &LDA, TAU, WORK, &LWORK, &INFO)); 3779566063dSJacob Faibussowitsch PetscCall(PetscFPTrapPop()); 37808401ef6SPierre Jolivet PetscCheck(INFO == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "xGEQRF error"); 3792e68589bSMark F. Adams /* get R - column oriented - output B_{i+1} */ 3802e68589bSMark F. Adams { 3812e68589bSMark F. Adams PetscReal *data = &out_data[clid * nSAvec]; 3822e68589bSMark F. Adams for (jj = 0; jj < nSAvec; jj++) { 3832e68589bSMark F. Adams for (ii = 0; ii < nSAvec; ii++) { 38408401ef6SPierre 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); 3850cbbd2e1SMark F. Adams if (ii <= jj) data[jj * out_data_stride + ii] = PetscRealPart(qqc[jj * Mdata + ii]); 3860cbbd2e1SMark F. Adams else data[jj * out_data_stride + ii] = 0.; 3872e68589bSMark F. Adams } 3882e68589bSMark F. Adams } 3892e68589bSMark F. Adams } 3902e68589bSMark F. Adams 3912e68589bSMark F. Adams /* get Q - row oriented */ 392792fecdfSBarry Smith PetscCallBLAS("LAPACKorgqr", LAPACKorgqr_(&Mdata, &N, &N, qqc, &LDA, TAU, WORK, &LWORK, &INFO)); 39363a3b9bcSJacob Faibussowitsch PetscCheck(INFO == 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "xORGQR error arg %" PetscBLASInt_FMT, -INFO); 3942e68589bSMark F. Adams 3952e68589bSMark F. Adams for (ii = 0; ii < M; ii++) { 396ad540459SPierre Jolivet for (jj = 0; jj < N; jj++) qqr[N * ii + jj] = qqc[jj * Mdata + ii]; 3972e68589bSMark F. Adams } 3982e68589bSMark F. Adams 3992e68589bSMark F. Adams /* add diagonal block of P0 */ 4009371c9d4SSatish Balay for (kk = 0; kk < N; kk++) { cids[kk] = N * cgid + kk; /* global col IDs in P0 */ } 4019566063dSJacob Faibussowitsch PetscCall(MatSetValues(a_Prol, M, fids, N, cids, qqr, INSERT_VALUES)); 4029566063dSJacob Faibussowitsch PetscCall(PetscFree5(qqc, qqr, TAU, WORK, fids)); 403b43b03e9SMark F. Adams clid++; 4040cbbd2e1SMark F. Adams } /* coarse agg */ 4050cbbd2e1SMark F. Adams } /* for all fine nodes */ 4069566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(a_Prol, MAT_FINAL_ASSEMBLY)); 4079566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(a_Prol, MAT_FINAL_ASSEMBLY)); 4089566063dSJacob Faibussowitsch PetscCall(PCGAMGHashTableDestroy(&fgid_flid)); 409*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4102e68589bSMark F. Adams } 4112e68589bSMark F. Adams 412d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCView_GAMG_AGG(PC pc, PetscViewer viewer) 413d71ae5a4SJacob Faibussowitsch { 4145adeb434SBarry Smith PC_MG *mg = (PC_MG *)pc->data; 4155adeb434SBarry Smith PC_GAMG *pc_gamg = (PC_GAMG *)mg->innerctx; 4165adeb434SBarry Smith PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG *)pc_gamg->subctx; 4175adeb434SBarry Smith 4185adeb434SBarry Smith PetscFunctionBegin; 4199566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, " AGG specific options\n")); 420bae903cbSmarkadams4 PetscCall(PetscViewerASCIIPrintf(viewer, " Number of levels to square graph %d\n", (int)pc_gamg_agg->aggressive_coarsening_levels)); 421bae903cbSmarkadams4 PetscCall(PetscViewerASCIIPrintf(viewer, " Number smoothing steps %d\n", (int)pc_gamg_agg->nsmooths)); 422*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4235adeb434SBarry Smith } 4245adeb434SBarry Smith 4252d776b49SBarry Smith static PetscErrorCode PCGAMGCreateGraph_AGG(PC pc, Mat Amat, Mat *a_Gmat) 426d71ae5a4SJacob Faibussowitsch { 427c8b0795cSMark F. Adams PC_MG *mg = (PC_MG *)pc->data; 428c8b0795cSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG *)mg->innerctx; 429c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG *)pc_gamg->subctx; 4302d776b49SBarry Smith const PetscReal vfilter = pc_gamg->threshold[pc_gamg->current_level]; 4312d776b49SBarry Smith PetscBool ishem; 4322d776b49SBarry Smith const char *prefix; 433c8b0795cSMark F. Adams 434c8b0795cSMark F. Adams PetscFunctionBegin; 435849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_GRAPH], 0, 0, 0, 0)); 4362d776b49SBarry Smith /* Note: depending on the algorithm that will be used for computing the coarse grid points this should pass PETSC_TRUE or PETSC_FALSE as the first argument */ 4372d776b49SBarry Smith 4382d776b49SBarry Smith /* MATCOARSENHEM requires numerical weights for edges so ensure they are computed */ 4392d776b49SBarry Smith PetscCall(MatCoarsenCreate(PetscObjectComm((PetscObject)pc), &pc_gamg_agg->crs)); 4402d776b49SBarry Smith PetscCall(PetscObjectGetOptionsPrefix((PetscObject)pc, &prefix)); 4412d776b49SBarry Smith PetscCall(PetscObjectSetOptionsPrefix((PetscObject)pc_gamg_agg->crs, prefix)); 4422d776b49SBarry Smith PetscCall(MatCoarsenSetFromOptions(pc_gamg_agg->crs)); 4432d776b49SBarry Smith PetscCall(PetscObjectTypeCompare((PetscObject)pc_gamg_agg->crs, MATCOARSENHEM, &ishem)); 4442d776b49SBarry Smith 4452d776b49SBarry Smith PetscCall(MatCreateGraph(Amat, PETSC_TRUE, (vfilter >= 0 || ishem) ? PETSC_TRUE : PETSC_FALSE, vfilter, a_Gmat)); 446849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_GRAPH], 0, 0, 0, 0)); 447*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 448c8b0795cSMark F. Adams } 449c8b0795cSMark F. Adams 450c8b0795cSMark F. Adams /* 451bae903cbSmarkadams4 PCGAMGCoarsen_AGG - supports squaring the graph (deprecated) and new graph for 452bae903cbSmarkadams4 communication of QR data used with HEM and MISk coarsening 453c8b0795cSMark F. Adams 454c8b0795cSMark F. Adams Input Parameter: 455e0940f08SMark F. Adams . a_pc - this 456bae903cbSmarkadams4 457e0940f08SMark F. Adams Input/Output Parameter: 458bae903cbSmarkadams4 . a_Gmat1 - graph to coarsen (in), graph off processor edges for QR gather scatter (out) 459bae903cbSmarkadams4 460c8b0795cSMark F. Adams Output Parameter: 4610cbbd2e1SMark F. Adams . agg_lists - list of aggregates 462bae903cbSmarkadams4 463c8b0795cSMark F. Adams */ 464d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGAMGCoarsen_AGG(PC a_pc, Mat *a_Gmat1, PetscCoarsenData **agg_lists) 465d71ae5a4SJacob Faibussowitsch { 466e0940f08SMark F. Adams PC_MG *mg = (PC_MG *)a_pc->data; 467c8b0795cSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG *)mg->innerctx; 468c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG *)pc_gamg->subctx; 469bae903cbSmarkadams4 Mat mat, Gmat1 = *a_Gmat1; /* aggressive graph */ 4700cbbd2e1SMark F. Adams IS perm; 471bae903cbSmarkadams4 PetscInt Istart, Iend, Ii, nloc, bs, nn; 472bae903cbSmarkadams4 PetscInt *permute, *degree; 473c8b0795cSMark F. Adams PetscBool *bIndexSet; 474aea53286SMark Adams PetscReal hashfact; 475e2c00dcbSBarry Smith PetscInt iSwapIndex; 4763b50add6SMark Adams PetscRandom random; 477c8b0795cSMark F. Adams 478c8b0795cSMark F. Adams PetscFunctionBegin; 479849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_COARSEN], 0, 0, 0, 0)); 480bae903cbSmarkadams4 PetscCall(MatGetLocalSize(Gmat1, &nn, NULL)); 4819566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(Gmat1, &bs)); 48263a3b9bcSJacob Faibussowitsch PetscCheck(bs == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "bs %" PetscInt_FMT " must be 1", bs); 483bae903cbSmarkadams4 nloc = nn / bs; 484c8b0795cSMark F. Adams 4855cfd4bd9SMark Adams /* get MIS aggs - randomize */ 486bae903cbSmarkadams4 PetscCall(PetscMalloc2(nloc, &permute, nloc, °ree)); 4879566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(nloc, &bIndexSet)); 4886e09b0e3SStefano Zampini for (Ii = 0; Ii < nloc; Ii++) permute[Ii] = Ii; 4899566063dSJacob Faibussowitsch PetscCall(PetscRandomCreate(PETSC_COMM_SELF, &random)); 4909566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(Gmat1, &Istart, &Iend)); 491c8b0795cSMark F. Adams for (Ii = 0; Ii < nloc; Ii++) { 492bae903cbSmarkadams4 PetscInt nc; 493bae903cbSmarkadams4 PetscCall(MatGetRow(Gmat1, Istart + Ii, &nc, NULL, NULL)); 494bae903cbSmarkadams4 degree[Ii] = nc; 495bae903cbSmarkadams4 PetscCall(MatRestoreRow(Gmat1, Istart + Ii, &nc, NULL, NULL)); 496bae903cbSmarkadams4 } 497bae903cbSmarkadams4 for (Ii = 0; Ii < nloc; Ii++) { 4989566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValueReal(random, &hashfact)); 499aea53286SMark Adams iSwapIndex = (PetscInt)(hashfact * nloc) % nloc; 500c8b0795cSMark F. Adams if (!bIndexSet[iSwapIndex] && iSwapIndex != Ii) { 501c8b0795cSMark F. Adams PetscInt iTemp = permute[iSwapIndex]; 502c8b0795cSMark F. Adams permute[iSwapIndex] = permute[Ii]; 503c8b0795cSMark F. Adams permute[Ii] = iTemp; 504bae903cbSmarkadams4 iTemp = degree[iSwapIndex]; 505bae903cbSmarkadams4 degree[iSwapIndex] = degree[Ii]; 506bae903cbSmarkadams4 degree[Ii] = iTemp; 507c8b0795cSMark F. Adams bIndexSet[iSwapIndex] = PETSC_TRUE; 508c8b0795cSMark F. Adams } 509c8b0795cSMark F. Adams } 510bae903cbSmarkadams4 // create minimum degree ordering 511bae903cbSmarkadams4 PetscCall(PetscSortIntWithArray(nloc, degree, permute)); 512bae903cbSmarkadams4 5139566063dSJacob Faibussowitsch PetscCall(PetscFree(bIndexSet)); 5149566063dSJacob Faibussowitsch PetscCall(PetscRandomDestroy(&random)); 5159566063dSJacob Faibussowitsch PetscCall(ISCreateGeneral(PETSC_COMM_SELF, nloc, permute, PETSC_USE_POINTER, &perm)); 516849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_MIS], 0, 0, 0, 0)); 5172d776b49SBarry Smith PetscCall(MatCoarsenSetGreedyOrdering(pc_gamg_agg->crs, perm)); 5182d776b49SBarry Smith PetscCall(MatCoarsenSetAdjacency(pc_gamg_agg->crs, Gmat1)); 5192d776b49SBarry Smith PetscCall(MatCoarsenSetStrictAggs(pc_gamg_agg->crs, PETSC_TRUE)); 5202d776b49SBarry Smith if (pc_gamg->current_level < pc_gamg_agg->aggressive_coarsening_levels) PetscCall(MatCoarsenMISKSetDistance(pc_gamg_agg->crs, 2)); // hardwire to MIS-2 5212d776b49SBarry Smith else PetscCall(MatCoarsenMISKSetDistance(pc_gamg_agg->crs, 1)); // MIS 5222d776b49SBarry Smith PetscCall(MatCoarsenApply(pc_gamg_agg->crs)); 5232d776b49SBarry Smith PetscCall(MatCoarsenViewFromOptions(pc_gamg_agg->crs, NULL, "-mat_coarsen_view")); 5242d776b49SBarry Smith PetscCall(MatCoarsenGetData(pc_gamg_agg->crs, agg_lists)); /* output */ 5252d776b49SBarry Smith PetscCall(MatCoarsenDestroy(&pc_gamg_agg->crs)); 526b43b03e9SMark F. Adams 5279566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 528bae903cbSmarkadams4 PetscCall(PetscFree2(permute, degree)); 529849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_MIS], 0, 0, 0, 0)); 5309f3f12c8SMark F. Adams 531bae903cbSmarkadams4 { 532bae903cbSmarkadams4 PetscCoarsenData *llist = *agg_lists; 5339ab59c8bSMark Adams /* see if we have a matrix that takes precedence (returned from MatCoarsenApply) */ 5349566063dSJacob Faibussowitsch PetscCall(PetscCDGetMat(llist, &mat)); 5350cbbd2e1SMark F. Adams if (mat) { 5369566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Gmat1)); 5370cbbd2e1SMark F. Adams *a_Gmat1 = mat; /* output */ 5380cbbd2e1SMark F. Adams } 5390cbbd2e1SMark F. Adams } 540849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_COARSEN], 0, 0, 0, 0)); 541*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 542c8b0795cSMark F. Adams } 543c8b0795cSMark F. Adams 544c8b0795cSMark F. Adams /* 5450cbbd2e1SMark F. Adams PCGAMGProlongator_AGG 546c8b0795cSMark F. Adams 547c8b0795cSMark F. Adams Input Parameter: 548c8b0795cSMark F. Adams . pc - this 549c8b0795cSMark F. Adams . Amat - matrix on this fine level 550c8b0795cSMark F. Adams . Graph - used to get ghost data for nodes in 5510cbbd2e1SMark F. Adams . agg_lists - list of aggregates 552c8b0795cSMark F. Adams Output Parameter: 553c8b0795cSMark F. Adams . a_P_out - prolongation operator to the next level 554c8b0795cSMark F. Adams */ 555d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGAMGProlongator_AGG(PC pc, Mat Amat, Mat Gmat, PetscCoarsenData *agg_lists, Mat *a_P_out) 556d71ae5a4SJacob Faibussowitsch { 5572e68589bSMark F. Adams PC_MG *mg = (PC_MG *)pc->data; 5582e68589bSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG *)mg->innerctx; 5594a2f8832SBarry Smith const PetscInt col_bs = pc_gamg->data_cell_cols; 560c8b0795cSMark F. Adams PetscInt Istart, Iend, nloc, ii, jj, kk, my0, nLocalSelected, bs; 561c8b0795cSMark F. Adams Mat Prol; 562d5d25401SBarry Smith PetscMPIInt size; 5633b4367a7SBarry Smith MPI_Comm comm; 564c8b0795cSMark F. Adams PetscReal *data_w_ghost; 565c8b0795cSMark F. Adams PetscInt myCrs0, nbnodes = 0, *flid_fgid; 566d9558ea9SBarry Smith MatType mtype; 5672e68589bSMark F. Adams 5682e68589bSMark F. Adams PetscFunctionBegin; 5699566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)Amat, &comm)); 57008401ef6SPierre Jolivet PetscCheck(col_bs >= 1, comm, PETSC_ERR_PLIB, "Column bs cannot be less than 1"); 571849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_PROL], 0, 0, 0, 0)); 5729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 5739566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(Amat, &Istart, &Iend)); 5749566063dSJacob Faibussowitsch PetscCall(MatGetBlockSize(Amat, &bs)); 5759371c9d4SSatish Balay nloc = (Iend - Istart) / bs; 5769371c9d4SSatish Balay my0 = Istart / bs; 57763a3b9bcSJacob 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); 5782e68589bSMark F. Adams 5792e68589bSMark F. Adams /* get 'nLocalSelected' */ 5800cbbd2e1SMark F. Adams for (ii = 0, nLocalSelected = 0; ii < nloc; ii++) { 581e78576d6SMark F. Adams PetscBool ise; 5820cbbd2e1SMark F. Adams /* filter out singletons 0 or 1? */ 5839566063dSJacob Faibussowitsch PetscCall(PetscCDEmptyAt(agg_lists, ii, &ise)); 584e78576d6SMark F. Adams if (!ise) nLocalSelected++; 5852e68589bSMark F. Adams } 5862e68589bSMark F. Adams 5872e68589bSMark F. Adams /* create prolongator, create P matrix */ 5889566063dSJacob Faibussowitsch PetscCall(MatGetType(Amat, &mtype)); 5899566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &Prol)); 5909566063dSJacob Faibussowitsch PetscCall(MatSetSizes(Prol, nloc * bs, nLocalSelected * col_bs, PETSC_DETERMINE, PETSC_DETERMINE)); 5919566063dSJacob Faibussowitsch PetscCall(MatSetBlockSizes(Prol, bs, col_bs)); 5929566063dSJacob Faibussowitsch PetscCall(MatSetType(Prol, mtype)); 5939566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(Prol, col_bs, NULL)); 5949566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(Prol, col_bs, NULL, col_bs, NULL)); 5952e68589bSMark F. Adams 5962e68589bSMark F. Adams /* can get all points "removed" */ 5979566063dSJacob Faibussowitsch PetscCall(MatGetSize(Prol, &kk, &ii)); 5987f66b68fSMark Adams if (!ii) { 59963a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(pc, "%s: No selected points on coarse grid\n", ((PetscObject)pc)->prefix)); 6009566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Prol)); 6010298fd71SBarry Smith *a_P_out = NULL; /* out */ 602849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_PROL], 0, 0, 0, 0)); 603*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6042e68589bSMark F. Adams } 60563a3b9bcSJacob Faibussowitsch PetscCall(PetscInfo(pc, "%s: New grid %" PetscInt_FMT " nodes\n", ((PetscObject)pc)->prefix, ii / col_bs)); 6069566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRangeColumn(Prol, &myCrs0, &kk)); 6070cbbd2e1SMark F. Adams 60863a3b9bcSJacob 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); 609c8b0795cSMark F. Adams myCrs0 = myCrs0 / col_bs; 61063a3b9bcSJacob 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); 6112e68589bSMark F. Adams 6122e68589bSMark F. Adams /* create global vector of data in 'data_w_ghost' */ 613849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_PROLA], 0, 0, 0, 0)); 614bae903cbSmarkadams4 if (size > 1) { /* get ghost null space data */ 6152e68589bSMark F. Adams PetscReal *tmp_gdata, *tmp_ldata, *tp2; 6169566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nloc, &tmp_ldata)); 6174a2f8832SBarry Smith for (jj = 0; jj < col_bs; jj++) { 618c8b0795cSMark F. Adams for (kk = 0; kk < bs; kk++) { 619a2f3521dSMark F. Adams PetscInt ii, stride; 620c8b0795cSMark F. Adams const PetscReal *tp = pc_gamg->data + jj * bs * nloc + kk; 6212fa5cd67SKarl Rupp for (ii = 0; ii < nloc; ii++, tp += bs) tmp_ldata[ii] = *tp; 6222fa5cd67SKarl Rupp 6239566063dSJacob Faibussowitsch PetscCall(PCGAMGGetDataWithGhosts(Gmat, 1, tmp_ldata, &stride, &tmp_gdata)); 624a2f3521dSMark F. Adams 625bae903cbSmarkadams4 if (!jj && !kk) { /* now I know how many total nodes - allocate TODO: move below and do in one 'col_bs' call */ 6269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(stride * bs * col_bs, &data_w_ghost)); 627a2f3521dSMark F. Adams nbnodes = bs * stride; 6282e68589bSMark F. Adams } 629a2f3521dSMark F. Adams tp2 = data_w_ghost + jj * bs * stride + kk; 6302fa5cd67SKarl Rupp for (ii = 0; ii < stride; ii++, tp2 += bs) *tp2 = tmp_gdata[ii]; 6319566063dSJacob Faibussowitsch PetscCall(PetscFree(tmp_gdata)); 6322e68589bSMark F. Adams } 6332e68589bSMark F. Adams } 6349566063dSJacob Faibussowitsch PetscCall(PetscFree(tmp_ldata)); 635806fa848SBarry Smith } else { 636c8b0795cSMark F. Adams nbnodes = bs * nloc; 637c8b0795cSMark F. Adams data_w_ghost = (PetscReal *)pc_gamg->data; 6382e68589bSMark F. Adams } 6392e68589bSMark F. Adams 640bae903cbSmarkadams4 /* get 'flid_fgid' TODO - move up to get 'stride' and do get null space data above in one step (jj loop) */ 641c5df96a5SBarry Smith if (size > 1) { 6422e68589bSMark F. Adams PetscReal *fid_glid_loc, *fiddata; 643a2f3521dSMark F. Adams PetscInt stride; 6442e68589bSMark F. Adams 6459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nloc, &fid_glid_loc)); 6462e68589bSMark F. Adams for (kk = 0; kk < nloc; kk++) fid_glid_loc[kk] = (PetscReal)(my0 + kk); 6479566063dSJacob Faibussowitsch PetscCall(PCGAMGGetDataWithGhosts(Gmat, 1, fid_glid_loc, &stride, &fiddata)); 648bae903cbSmarkadams4 PetscCall(PetscMalloc1(stride, &flid_fgid)); /* copy real data to in */ 649a2f3521dSMark F. Adams for (kk = 0; kk < stride; kk++) flid_fgid[kk] = (PetscInt)fiddata[kk]; 6509566063dSJacob Faibussowitsch PetscCall(PetscFree(fiddata)); 651a2f3521dSMark F. Adams 65263a3b9bcSJacob Faibussowitsch PetscCheck(stride == nbnodes / bs, PETSC_COMM_SELF, PETSC_ERR_PLIB, "stride %" PetscInt_FMT " != nbnodes %" PetscInt_FMT "/bs %" PetscInt_FMT, stride, nbnodes, bs); 6539566063dSJacob Faibussowitsch PetscCall(PetscFree(fid_glid_loc)); 654806fa848SBarry Smith } else { 6559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nloc, &flid_fgid)); 6562e68589bSMark F. Adams for (kk = 0; kk < nloc; kk++) flid_fgid[kk] = my0 + kk; 6572e68589bSMark F. Adams } 658849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_PROLA], 0, 0, 0, 0)); 659bae903cbSmarkadams4 /* get P0 */ 660849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_PROLB], 0, 0, 0, 0)); 661c8b0795cSMark F. Adams { 6620298fd71SBarry Smith PetscReal *data_out = NULL; 6639566063dSJacob Faibussowitsch PetscCall(formProl0(agg_lists, bs, col_bs, myCrs0, nbnodes, data_w_ghost, flid_fgid, &data_out, Prol)); 6649566063dSJacob Faibussowitsch PetscCall(PetscFree(pc_gamg->data)); 6652fa5cd67SKarl Rupp 666c8b0795cSMark F. Adams pc_gamg->data = data_out; 6674a2f8832SBarry Smith pc_gamg->data_cell_rows = col_bs; 6684a2f8832SBarry Smith pc_gamg->data_sz = col_bs * col_bs * nLocalSelected; 669c8b0795cSMark F. Adams } 670849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_PROLB], 0, 0, 0, 0)); 67148a46eb9SPierre Jolivet if (size > 1) PetscCall(PetscFree(data_w_ghost)); 6729566063dSJacob Faibussowitsch PetscCall(PetscFree(flid_fgid)); 6732e68589bSMark F. Adams 674c8b0795cSMark F. Adams *a_P_out = Prol; /* out */ 675ed4e82eaSPeter Brune 676849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_PROL], 0, 0, 0, 0)); 677*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 678c8b0795cSMark F. Adams } 679c8b0795cSMark F. Adams 680c8b0795cSMark F. Adams /* 681fd1112cbSBarry Smith PCGAMGOptProlongator_AGG 682c8b0795cSMark F. Adams 683c8b0795cSMark F. Adams Input Parameter: 684c8b0795cSMark F. Adams . pc - this 685c8b0795cSMark F. Adams . Amat - matrix on this fine level 686c8b0795cSMark F. Adams In/Output Parameter: 6872a808120SBarry Smith . a_P - prolongation operator to the next level 688c8b0795cSMark F. Adams */ 689d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCGAMGOptProlongator_AGG(PC pc, Mat Amat, Mat *a_P) 690d71ae5a4SJacob Faibussowitsch { 691c8b0795cSMark F. Adams PC_MG *mg = (PC_MG *)pc->data; 692c8b0795cSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG *)mg->innerctx; 693c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG *)pc_gamg->subctx; 694c8b0795cSMark F. Adams PetscInt jj; 695c8b0795cSMark F. Adams Mat Prol = *a_P; 6963b4367a7SBarry Smith MPI_Comm comm; 6972a808120SBarry Smith KSP eksp; 6982a808120SBarry Smith Vec bb, xx; 6992a808120SBarry Smith PC epc; 7002a808120SBarry Smith PetscReal alpha, emax, emin; 701c8b0795cSMark F. Adams 702c8b0795cSMark F. Adams PetscFunctionBegin; 7039566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)Amat, &comm)); 704849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_OPT], 0, 0, 0, 0)); 705c8b0795cSMark F. Adams 706d5d25401SBarry Smith /* compute maximum singular value of operator to be used in smoother */ 7072a808120SBarry Smith if (0 < pc_gamg_agg->nsmooths) { 70818c3aa7eSMark /* get eigen estimates */ 70918c3aa7eSMark if (pc_gamg->emax > 0) { 71018c3aa7eSMark emin = pc_gamg->emin; 71118c3aa7eSMark emax = pc_gamg->emax; 71218c3aa7eSMark } else { 7130ed2132dSStefano Zampini const char *prefix; 7140ed2132dSStefano Zampini 7159566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(Amat, &bb, NULL)); 7169566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(Amat, &xx, NULL)); 7179566063dSJacob Faibussowitsch PetscCall(KSPSetNoisy_Private(bb)); 718e696ed0bSMark F. Adams 7199566063dSJacob Faibussowitsch PetscCall(KSPCreate(comm, &eksp)); 7209566063dSJacob Faibussowitsch PetscCall(PCGetOptionsPrefix(pc, &prefix)); 7219566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(eksp, prefix)); 7229566063dSJacob Faibussowitsch PetscCall(KSPAppendOptionsPrefix(eksp, "pc_gamg_esteig_")); 72373f7197eSJed Brown { 724b94d7dedSBarry Smith PetscBool isset, sflg; 725b94d7dedSBarry Smith PetscCall(MatIsSPDKnown(Amat, &isset, &sflg)); 726b94d7dedSBarry Smith if (isset && sflg) PetscCall(KSPSetType(eksp, KSPCG)); 727d24ecf33SMark } 7289566063dSJacob Faibussowitsch PetscCall(KSPSetErrorIfNotConverged(eksp, pc->erroriffailure)); 7299566063dSJacob Faibussowitsch PetscCall(KSPSetNormType(eksp, KSP_NORM_NONE)); 730c2436cacSMark F. Adams 7319566063dSJacob Faibussowitsch PetscCall(KSPSetInitialGuessNonzero(eksp, PETSC_FALSE)); 7329566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(eksp, Amat, Amat)); 7332e68589bSMark F. Adams 7349566063dSJacob Faibussowitsch PetscCall(KSPGetPC(eksp, &epc)); 7359566063dSJacob Faibussowitsch PetscCall(PCSetType(epc, PCJACOBI)); /* smoother in smoothed agg. */ 736c2436cacSMark F. Adams 7379566063dSJacob 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 738074aec55SMark Adams 7399566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(eksp)); 7409566063dSJacob Faibussowitsch PetscCall(KSPSetComputeSingularValues(eksp, PETSC_TRUE)); 7419566063dSJacob Faibussowitsch PetscCall(KSPSolve(eksp, bb, xx)); 7429566063dSJacob Faibussowitsch PetscCall(KSPCheckSolve(eksp, pc, xx)); 7432e68589bSMark F. Adams 7449566063dSJacob Faibussowitsch PetscCall(KSPComputeExtremeSingularValues(eksp, &emax, &emin)); 7459566063dSJacob Faibussowitsch PetscCall(PetscInfo(pc, "%s: Smooth P0: max eigen=%e min=%e PC=%s\n", ((PetscObject)pc)->prefix, (double)emax, (double)emin, PCJACOBI)); 7469566063dSJacob Faibussowitsch PetscCall(VecDestroy(&xx)); 7479566063dSJacob Faibussowitsch PetscCall(VecDestroy(&bb)); 7489566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&eksp)); 7492e68589bSMark F. Adams } 75018c3aa7eSMark if (pc_gamg->use_sa_esteig) { 75118c3aa7eSMark mg->min_eigen_DinvA[pc_gamg->current_level] = emin; 75218c3aa7eSMark mg->max_eigen_DinvA[pc_gamg->current_level] = emax; 75363a3b9bcSJacob 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)); 75418c3aa7eSMark } else { 75518c3aa7eSMark mg->min_eigen_DinvA[pc_gamg->current_level] = 0; 75618c3aa7eSMark mg->max_eigen_DinvA[pc_gamg->current_level] = 0; 75718c3aa7eSMark } 75818c3aa7eSMark } else { 75918c3aa7eSMark mg->min_eigen_DinvA[pc_gamg->current_level] = 0; 76018c3aa7eSMark mg->max_eigen_DinvA[pc_gamg->current_level] = 0; 76118c3aa7eSMark } 7622e68589bSMark F. Adams 7632a808120SBarry Smith /* smooth P0 */ 7642a808120SBarry Smith for (jj = 0; jj < pc_gamg_agg->nsmooths; jj++) { 7652a808120SBarry Smith Mat tMat; 7662a808120SBarry Smith Vec diag; 7672a808120SBarry Smith 768849bee69SMark Adams PetscCall(PetscLogEventBegin(petsc_gamg_setup_events[GAMG_OPTSM], 0, 0, 0, 0)); 7692a808120SBarry Smith 7702e68589bSMark F. Adams /* smooth P1 := (I - omega/lam D^{-1}A)P0 */ 7719566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(petsc_gamg_setup_matmat_events[pc_gamg->current_level][2], 0, 0, 0, 0)); 7729566063dSJacob Faibussowitsch PetscCall(MatMatMult(Amat, Prol, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &tMat)); 7739566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(petsc_gamg_setup_matmat_events[pc_gamg->current_level][2], 0, 0, 0, 0)); 7749566063dSJacob Faibussowitsch PetscCall(MatProductClear(tMat)); 7759566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(Amat, &diag, NULL)); 7769566063dSJacob Faibussowitsch PetscCall(MatGetDiagonal(Amat, diag)); /* effectively PCJACOBI */ 7779566063dSJacob Faibussowitsch PetscCall(VecReciprocal(diag)); 7789566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(tMat, diag, NULL)); 7799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&diag)); 780b4da3a1bSStefano Zampini 781d5d25401SBarry Smith /* TODO: Set a PCFailedReason and exit the building of the AMG preconditioner */ 78208401ef6SPierre Jolivet PetscCheck(emax != 0.0, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "Computed maximum singular value as zero"); 783d5d25401SBarry Smith /* TODO: Document the 1.4 and don't hardwire it in this routine */ 784b4ec6429SMark F. Adams alpha = -1.4 / emax; 785b4da3a1bSStefano Zampini 7869566063dSJacob Faibussowitsch PetscCall(MatAYPX(tMat, alpha, Prol, SUBSET_NONZERO_PATTERN)); 7879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&Prol)); 7882e68589bSMark F. Adams Prol = tMat; 789849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_OPTSM], 0, 0, 0, 0)); 7902e68589bSMark F. Adams } 791849bee69SMark Adams PetscCall(PetscLogEventEnd(petsc_gamg_setup_events[GAMG_OPT], 0, 0, 0, 0)); 792c8b0795cSMark F. Adams *a_P = Prol; 793*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7942e68589bSMark F. Adams } 7952e68589bSMark F. Adams 796c8b0795cSMark F. Adams /* 797c8b0795cSMark F. Adams PCCreateGAMG_AGG 7982e68589bSMark F. Adams 799c8b0795cSMark F. Adams Input Parameter: 800c8b0795cSMark F. Adams . pc - 801c8b0795cSMark F. Adams */ 802d71ae5a4SJacob Faibussowitsch PetscErrorCode PCCreateGAMG_AGG(PC pc) 803d71ae5a4SJacob Faibussowitsch { 804c8b0795cSMark F. Adams PC_MG *mg = (PC_MG *)pc->data; 805c8b0795cSMark F. Adams PC_GAMG *pc_gamg = (PC_GAMG *)mg->innerctx; 806c8b0795cSMark F. Adams PC_GAMG_AGG *pc_gamg_agg; 8072e68589bSMark F. Adams 808c8b0795cSMark F. Adams PetscFunctionBegin; 809c8b0795cSMark F. Adams /* create sub context for SA */ 8104dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&pc_gamg_agg)); 811c8b0795cSMark F. Adams pc_gamg->subctx = pc_gamg_agg; 812c8b0795cSMark F. Adams 8131ab5ffc9SJed Brown pc_gamg->ops->setfromoptions = PCSetFromOptions_GAMG_AGG; 8149b8ffb57SJed Brown pc_gamg->ops->destroy = PCDestroy_GAMG_AGG; 815c8b0795cSMark F. Adams /* reset does not do anything; setup not virtual */ 816c8b0795cSMark F. Adams 817c8b0795cSMark F. Adams /* set internal function pointers */ 8182d776b49SBarry Smith pc_gamg->ops->creategraph = PCGAMGCreateGraph_AGG; 8191ab5ffc9SJed Brown pc_gamg->ops->coarsen = PCGAMGCoarsen_AGG; 8201ab5ffc9SJed Brown pc_gamg->ops->prolongator = PCGAMGProlongator_AGG; 821fd1112cbSBarry Smith pc_gamg->ops->optprolongator = PCGAMGOptProlongator_AGG; 8221ab5ffc9SJed Brown pc_gamg->ops->createdefaultdata = PCSetData_AGG; 8235adeb434SBarry Smith pc_gamg->ops->view = PCView_GAMG_AGG; 824c8b0795cSMark F. Adams 825599482c2Smarkadams4 pc_gamg_agg->aggressive_coarsening_levels = 1; 826cab9ed1eSBarry Smith pc_gamg_agg->nsmooths = 1; 827cab9ed1eSBarry Smith 8289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGAMGSetNSmooths_C", PCGAMGSetNSmooths_AGG)); 829bae903cbSmarkadams4 PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCGAMGSetAggressiveLevels_C", PCGAMGSetAggressiveLevels_AGG)); 8309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCSetCoordinates_C", PCSetCoordinates_AGG)); 831*3ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8322e68589bSMark F. Adams } 833