1 /* 2 GAMG geometric-algebric multiogrid PC - Mark Adams 2011 3 */ 4 5 #include <../src/ksp/pc/impls/gamg/gamg.h> /*I "petscpc.h" I*/ 6 #include <petsc/private/kspimpl.h> 7 8 #include <petscblaslapack.h> 9 10 typedef struct { 11 PetscInt nsmooths; 12 PetscBool sym_graph; 13 PetscInt square_graph; 14 } PC_GAMG_AGG; 15 16 #undef __FUNCT__ 17 #define __FUNCT__ "PCGAMGSetNSmooths" 18 /*@ 19 PCGAMGSetNSmooths - Set number of smoothing steps (1 is typical) 20 21 Not Collective on PC 22 23 Input Parameters: 24 . pc - the preconditioner context 25 26 Options Database Key: 27 . -pc_gamg_agg_nsmooths 28 29 Level: intermediate 30 31 Concepts: Aggregation AMG preconditioner 32 33 .seealso: () 34 @*/ 35 PetscErrorCode PCGAMGSetNSmooths(PC pc, PetscInt n) 36 { 37 PetscErrorCode ierr; 38 39 PetscFunctionBegin; 40 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 41 ierr = PetscTryMethod(pc,"PCGAMGSetNSmooths_C",(PC,PetscInt),(pc,n));CHKERRQ(ierr); 42 PetscFunctionReturn(0); 43 } 44 45 #undef __FUNCT__ 46 #define __FUNCT__ "PCGAMGSetNSmooths_GAMG" 47 PetscErrorCode PCGAMGSetNSmooths_GAMG(PC pc, PetscInt n) 48 { 49 PC_MG *mg = (PC_MG*)pc->data; 50 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 51 PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 52 53 PetscFunctionBegin; 54 pc_gamg_agg->nsmooths = n; 55 PetscFunctionReturn(0); 56 } 57 58 #undef __FUNCT__ 59 #define __FUNCT__ "PCGAMGSetSymGraph" 60 /*@ 61 PCGAMGSetSymGraph - 62 63 Not Collective on PC 64 65 Input Parameters: 66 . pc - the preconditioner context 67 68 Options Database Key: 69 . -pc_gamg_sym_graph 70 71 Level: intermediate 72 73 Concepts: Aggregation AMG preconditioner 74 75 .seealso: () 76 @*/ 77 PetscErrorCode PCGAMGSetSymGraph(PC pc, PetscBool n) 78 { 79 PetscErrorCode ierr; 80 81 PetscFunctionBegin; 82 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 83 ierr = PetscTryMethod(pc,"PCGAMGSetSymGraph_C",(PC,PetscBool),(pc,n));CHKERRQ(ierr); 84 PetscFunctionReturn(0); 85 } 86 87 #undef __FUNCT__ 88 #define __FUNCT__ "PCGAMGSetSymGraph_GAMG" 89 PetscErrorCode PCGAMGSetSymGraph_GAMG(PC pc, PetscBool n) 90 { 91 PC_MG *mg = (PC_MG*)pc->data; 92 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 93 PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 94 95 PetscFunctionBegin; 96 pc_gamg_agg->sym_graph = n; 97 PetscFunctionReturn(0); 98 } 99 100 #undef __FUNCT__ 101 #define __FUNCT__ "PCGAMGSetSquareGraph" 102 /*@ 103 PCGAMGSetSquareGraph - 104 105 Not Collective on PC 106 107 Input Parameters: 108 . pc - the preconditioner context 109 110 Options Database Key: 111 . -pc_gamg_square_graph 112 113 Level: intermediate 114 115 Concepts: Aggregation AMG preconditioner 116 117 .seealso: () 118 @*/ 119 PetscErrorCode PCGAMGSetSquareGraph(PC pc, PetscInt n) 120 { 121 PetscErrorCode ierr; 122 123 PetscFunctionBegin; 124 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 125 ierr = PetscTryMethod(pc,"PCGAMGSetSquareGraph_C",(PC,PetscInt),(pc,n));CHKERRQ(ierr); 126 PetscFunctionReturn(0); 127 } 128 129 #undef __FUNCT__ 130 #define __FUNCT__ "PCGAMGSetSquareGraph_GAMG" 131 PetscErrorCode PCGAMGSetSquareGraph_GAMG(PC pc, PetscInt n) 132 { 133 PC_MG *mg = (PC_MG*)pc->data; 134 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 135 PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 136 137 PetscFunctionBegin; 138 pc_gamg_agg->square_graph = n; 139 PetscFunctionReturn(0); 140 } 141 142 /* -------------------------------------------------------------------------- */ 143 /* 144 PCSetFromOptions_GAMG_AGG 145 146 Input Parameter: 147 . pc - 148 */ 149 #undef __FUNCT__ 150 #define __FUNCT__ "PCSetFromOptions_GAMG_AGG" 151 PetscErrorCode PCSetFromOptions_GAMG_AGG(PetscOptions *PetscOptionsObject,PC pc) 152 { 153 PetscErrorCode ierr; 154 PC_MG *mg = (PC_MG*)pc->data; 155 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 156 PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 157 158 PetscFunctionBegin; 159 ierr = PetscOptionsHead(PetscOptionsObject,"GAMG-AGG options");CHKERRQ(ierr); 160 { 161 /* -pc_gamg_agg_nsmooths */ 162 pc_gamg_agg->nsmooths = 1; 163 164 ierr = PetscOptionsInt("-pc_gamg_agg_nsmooths","smoothing steps for smoothed aggregation, usually 1","PCGAMGSetNSmooths",pc_gamg_agg->nsmooths,&pc_gamg_agg->nsmooths,NULL);CHKERRQ(ierr); 165 166 /* -pc_gamg_sym_graph */ 167 pc_gamg_agg->sym_graph = PETSC_FALSE; 168 169 ierr = PetscOptionsBool("-pc_gamg_sym_graph","Set for asymmetric matrices","PCGAMGSetSymGraph",pc_gamg_agg->sym_graph,&pc_gamg_agg->sym_graph,NULL);CHKERRQ(ierr); 170 171 /* -pc_gamg_square_graph */ 172 pc_gamg_agg->square_graph = 1; 173 174 ierr = 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);CHKERRQ(ierr); 175 } 176 ierr = PetscOptionsTail();CHKERRQ(ierr); 177 PetscFunctionReturn(0); 178 } 179 180 /* -------------------------------------------------------------------------- */ 181 /* 182 PCDestroy_AGG 183 184 Input Parameter: 185 . pc - 186 */ 187 #undef __FUNCT__ 188 #define __FUNCT__ "PCDestroy_GAMG_AGG" 189 PetscErrorCode PCDestroy_GAMG_AGG(PC pc) 190 { 191 PetscErrorCode ierr; 192 PC_MG *mg = (PC_MG*)pc->data; 193 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 194 195 PetscFunctionBegin; 196 ierr = PetscFree(pc_gamg->subctx);CHKERRQ(ierr); 197 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",NULL);CHKERRQ(ierr); 198 PetscFunctionReturn(0); 199 } 200 201 /* -------------------------------------------------------------------------- */ 202 /* 203 PCSetCoordinates_AGG 204 - collective 205 206 Input Parameter: 207 . pc - the preconditioner context 208 . ndm - dimesion of data (used for dof/vertex for Stokes) 209 . a_nloc - number of vertices local 210 . coords - [a_nloc][ndm] - interleaved coordinate data: {x_0, y_0, z_0, x_1, y_1, ...} 211 */ 212 213 #undef __FUNCT__ 214 #define __FUNCT__ "PCSetCoordinates_AGG" 215 static PetscErrorCode PCSetCoordinates_AGG(PC pc, PetscInt ndm, PetscInt a_nloc, PetscReal *coords) 216 { 217 PC_MG *mg = (PC_MG*)pc->data; 218 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 219 PetscErrorCode ierr; 220 PetscInt arrsz,kk,ii,jj,nloc,ndatarows,ndf; 221 Mat mat = pc->pmat; 222 223 PetscFunctionBegin; 224 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 225 PetscValidHeaderSpecific(mat,MAT_CLASSID,1); 226 nloc = a_nloc; 227 228 /* SA: null space vectors */ 229 ierr = MatGetBlockSize(mat, &ndf);CHKERRQ(ierr); /* this does not work for Stokes */ 230 if (coords && ndf==1) pc_gamg->data_cell_cols = 1; /* scalar w/ coords and SA (not needed) */ 231 else if (coords) { 232 if (ndm > ndf) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"degrees of motion %d > block size %d",ndm,ndf); 233 pc_gamg->data_cell_cols = (ndm==2 ? 3 : 6); /* displacement elasticity */ 234 if (ndm != ndf) { 235 if (pc_gamg->data_cell_cols != ndf) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Don't know how to create null space for ndm=%d, ndf=%d. Use MatSetNearNullSpace.",ndm,ndf); 236 } 237 } else pc_gamg->data_cell_cols = ndf; /* no data, force SA with constant null space vectors */ 238 pc_gamg->data_cell_rows = ndatarows = ndf; 239 if (pc_gamg->data_cell_cols <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"pc_gamg->data_cell_cols %D <= 0",pc_gamg->data_cell_cols); 240 arrsz = nloc*pc_gamg->data_cell_rows*pc_gamg->data_cell_cols; 241 242 /* create data - syntactic sugar that should be refactored at some point */ 243 if (pc_gamg->data==0 || (pc_gamg->data_sz != arrsz)) { 244 ierr = PetscFree(pc_gamg->data);CHKERRQ(ierr); 245 ierr = PetscMalloc1(arrsz+1, &pc_gamg->data);CHKERRQ(ierr); 246 } 247 /* copy data in - column oriented */ 248 for (kk=0; kk<nloc; kk++) { 249 const PetscInt M = nloc*pc_gamg->data_cell_rows; /* stride into data */ 250 PetscReal *data = &pc_gamg->data[kk*ndatarows]; /* start of cell */ 251 if (pc_gamg->data_cell_cols==1) *data = 1.0; 252 else { 253 /* translational modes */ 254 for (ii=0;ii<ndatarows;ii++) { 255 for (jj=0;jj<ndatarows;jj++) { 256 if (ii==jj)data[ii*M + jj] = 1.0; 257 else data[ii*M + jj] = 0.0; 258 } 259 } 260 261 /* rotational modes */ 262 if (coords) { 263 if (ndm == 2) { 264 data += 2*M; 265 data[0] = -coords[2*kk+1]; 266 data[1] = coords[2*kk]; 267 } else { 268 data += 3*M; 269 data[0] = 0.0; data[M+0] = coords[3*kk+2]; data[2*M+0] = -coords[3*kk+1]; 270 data[1] = -coords[3*kk+2]; data[M+1] = 0.0; data[2*M+1] = coords[3*kk]; 271 data[2] = coords[3*kk+1]; data[M+2] = -coords[3*kk]; data[2*M+2] = 0.0; 272 } 273 } 274 } 275 } 276 277 pc_gamg->data_sz = arrsz; 278 PetscFunctionReturn(0); 279 } 280 281 typedef PetscInt NState; 282 static const NState NOT_DONE=-2; 283 static const NState DELETED =-1; 284 static const NState REMOVED =-3; 285 #define IS_SELECTED(s) (s!=DELETED && s!=NOT_DONE && s!=REMOVED) 286 287 /* -------------------------------------------------------------------------- */ 288 /* 289 smoothAggs - greedy grab of with G1 (unsquared graph) -- AIJ specific 290 - AGG-MG specific: clears singletons out of 'selected_2' 291 292 Input Parameter: 293 . Gmat_2 - glabal matrix of graph (data not defined) base (squared) graph 294 . Gmat_1 - base graph to grab with base graph 295 Input/Output Parameter: 296 . aggs_2 - linked list of aggs with gids) 297 */ 298 #undef __FUNCT__ 299 #define __FUNCT__ "smoothAggs" 300 static PetscErrorCode smoothAggs(Mat Gmat_2, Mat Gmat_1,PetscCoarsenData *aggs_2) 301 { 302 PetscErrorCode ierr; 303 PetscBool isMPI; 304 Mat_SeqAIJ *matA_1, *matB_1=0, *matA_2, *matB_2=0; 305 MPI_Comm comm; 306 PetscInt lid,*ii,*idx,ix,Iend,my0,kk,n,j; 307 Mat_MPIAIJ *mpimat_2 = 0, *mpimat_1=0; 308 const PetscInt nloc = Gmat_2->rmap->n; 309 PetscScalar *cpcol_1_state,*cpcol_2_state,*cpcol_2_par_orig,*lid_parent_gid; 310 PetscInt *lid_cprowID_1; 311 NState *lid_state; 312 Vec ghost_par_orig2; 313 314 PetscFunctionBegin; 315 ierr = PetscObjectGetComm((PetscObject)Gmat_2,&comm);CHKERRQ(ierr); 316 ierr = MatGetOwnershipRange(Gmat_1,&my0,&Iend);CHKERRQ(ierr); 317 318 if (PETSC_FALSE) { 319 PetscViewer viewer; char fname[32]; static int llev=0; 320 sprintf(fname,"Gmat2_%d.m",llev++); 321 PetscViewerASCIIOpen(comm,fname,&viewer); 322 ierr = PetscViewerSetFormat(viewer, PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr); 323 ierr = MatView(Gmat_2, viewer);CHKERRQ(ierr); 324 ierr = PetscViewerDestroy(&viewer); 325 } 326 327 /* get submatrices */ 328 ierr = PetscObjectTypeCompare((PetscObject)Gmat_1, MATMPIAIJ, &isMPI);CHKERRQ(ierr); 329 if (isMPI) { 330 /* grab matrix objects */ 331 mpimat_2 = (Mat_MPIAIJ*)Gmat_2->data; 332 mpimat_1 = (Mat_MPIAIJ*)Gmat_1->data; 333 matA_1 = (Mat_SeqAIJ*)mpimat_1->A->data; 334 matB_1 = (Mat_SeqAIJ*)mpimat_1->B->data; 335 matA_2 = (Mat_SeqAIJ*)mpimat_2->A->data; 336 matB_2 = (Mat_SeqAIJ*)mpimat_2->B->data; 337 338 /* force compressed row storage for B matrix in AuxMat */ 339 ierr = MatCheckCompressedRow(mpimat_1->B,matB_1->nonzerorowcnt,&matB_1->compressedrow,matB_1->i,Gmat_1->rmap->n,-1.0);CHKERRQ(ierr); 340 341 ierr = PetscMalloc1(nloc, &lid_cprowID_1);CHKERRQ(ierr); 342 for (lid = 0; lid < nloc; lid++) lid_cprowID_1[lid] = -1; 343 for (ix=0; ix<matB_1->compressedrow.nrows; ix++) { 344 PetscInt lid = matB_1->compressedrow.rindex[ix]; 345 lid_cprowID_1[lid] = ix; 346 } 347 } else { 348 matA_1 = (Mat_SeqAIJ*)Gmat_1->data; 349 matA_2 = (Mat_SeqAIJ*)Gmat_2->data; 350 lid_cprowID_1 = NULL; 351 } 352 if (nloc>0) { 353 if (!(matA_1 && !matA_1->compressedrow.use)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"!(matA_1 && !matA_1->compressedrow.use)"); 354 if (!(matB_1==0 || matB_1->compressedrow.use)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"!(matB_1==0 || matB_1->compressedrow.use)"); 355 if (!(matA_2 && !matA_2->compressedrow.use)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"!(matA_2 && !matA_2->compressedrow.use)"); 356 if (!(matB_2==0 || matB_2->compressedrow.use)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"!(matB_2==0 || matB_2->compressedrow.use)"); 357 } 358 /* get state of locals and selected gid for deleted */ 359 ierr = PetscMalloc2(nloc, &lid_state,nloc, &lid_parent_gid);CHKERRQ(ierr); 360 for (lid = 0; lid < nloc; lid++) { 361 lid_parent_gid[lid] = -1.0; 362 lid_state[lid] = DELETED; 363 } 364 365 /* set lid_state */ 366 for (lid = 0; lid < nloc; lid++) { 367 PetscCDPos pos; 368 ierr = PetscCDGetHeadPos(aggs_2,lid,&pos);CHKERRQ(ierr); 369 if (pos) { 370 PetscInt gid1; 371 372 ierr = PetscLLNGetID(pos, &gid1);CHKERRQ(ierr); 373 if (gid1 != lid+my0) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"gid1 %D != lid %D + my0 %D",gid1,lid,my0); 374 lid_state[lid] = gid1; 375 } 376 } 377 378 /* map local to selected local, DELETED means a ghost owns it */ 379 for (lid=kk=0; lid<nloc; lid++) { 380 NState state = lid_state[lid]; 381 if (IS_SELECTED(state)) { 382 PetscCDPos pos; 383 ierr = PetscCDGetHeadPos(aggs_2,lid,&pos);CHKERRQ(ierr); 384 while (pos) { 385 PetscInt gid1; 386 ierr = PetscLLNGetID(pos, &gid1);CHKERRQ(ierr); 387 ierr = PetscCDGetNextPos(aggs_2,lid,&pos);CHKERRQ(ierr); 388 389 if (gid1 >= my0 && gid1 < Iend) lid_parent_gid[gid1-my0] = (PetscScalar)(lid + my0); 390 } 391 } 392 } 393 /* get 'cpcol_1/2_state' & cpcol_2_par_orig - uses mpimat_1/2->lvec for temp space */ 394 if (isMPI) { 395 Vec tempVec; 396 /* get 'cpcol_1_state' */ 397 ierr = MatCreateVecs(Gmat_1, &tempVec, 0);CHKERRQ(ierr); 398 for (kk=0,j=my0; kk<nloc; kk++,j++) { 399 PetscScalar v = (PetscScalar)lid_state[kk]; 400 ierr = VecSetValues(tempVec, 1, &j, &v, INSERT_VALUES);CHKERRQ(ierr); 401 } 402 ierr = VecAssemblyBegin(tempVec);CHKERRQ(ierr); 403 ierr = VecAssemblyEnd(tempVec);CHKERRQ(ierr); 404 ierr = VecScatterBegin(mpimat_1->Mvctx,tempVec, mpimat_1->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 405 ierr = VecScatterEnd(mpimat_1->Mvctx,tempVec, mpimat_1->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 406 ierr = VecGetArray(mpimat_1->lvec, &cpcol_1_state);CHKERRQ(ierr); 407 /* get 'cpcol_2_state' */ 408 ierr = VecScatterBegin(mpimat_2->Mvctx,tempVec, mpimat_2->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 409 ierr = VecScatterEnd(mpimat_2->Mvctx,tempVec, mpimat_2->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 410 ierr = VecGetArray(mpimat_2->lvec, &cpcol_2_state);CHKERRQ(ierr); 411 /* get 'cpcol_2_par_orig' */ 412 for (kk=0,j=my0; kk<nloc; kk++,j++) { 413 PetscScalar v = (PetscScalar)lid_parent_gid[kk]; 414 ierr = VecSetValues(tempVec, 1, &j, &v, INSERT_VALUES);CHKERRQ(ierr); 415 } 416 ierr = VecAssemblyBegin(tempVec);CHKERRQ(ierr); 417 ierr = VecAssemblyEnd(tempVec);CHKERRQ(ierr); 418 ierr = VecDuplicate(mpimat_2->lvec, &ghost_par_orig2);CHKERRQ(ierr); 419 ierr = VecScatterBegin(mpimat_2->Mvctx,tempVec, ghost_par_orig2,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 420 ierr = VecScatterEnd(mpimat_2->Mvctx,tempVec, ghost_par_orig2,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 421 ierr = VecGetArray(ghost_par_orig2, &cpcol_2_par_orig);CHKERRQ(ierr); 422 423 ierr = VecDestroy(&tempVec);CHKERRQ(ierr); 424 } /* ismpi */ 425 426 /* doit */ 427 for (lid=0; lid<nloc; lid++) { 428 NState state = lid_state[lid]; 429 if (IS_SELECTED(state)) { 430 /* steal locals */ 431 ii = matA_1->i; n = ii[lid+1] - ii[lid]; 432 idx = matA_1->j + ii[lid]; 433 for (j=0; j<n; j++) { 434 PetscInt lidj = idx[j], sgid; 435 NState statej = lid_state[lidj]; 436 if (statej==DELETED && (sgid=(PetscInt)PetscRealPart(lid_parent_gid[lidj])) != lid+my0) { /* steal local */ 437 lid_parent_gid[lidj] = (PetscScalar)(lid+my0); /* send this if sgid is not local */ 438 if (sgid >= my0 && sgid < Iend) { /* I'm stealing this local from a local sgid */ 439 PetscInt hav=0,slid=sgid-my0,gidj=lidj+my0; 440 PetscCDPos pos,last=NULL; 441 /* looking for local from local so id_llist_2 works */ 442 ierr = PetscCDGetHeadPos(aggs_2,slid,&pos);CHKERRQ(ierr); 443 while (pos) { 444 PetscInt gid; 445 ierr = PetscLLNGetID(pos, &gid);CHKERRQ(ierr); 446 if (gid == gidj) { 447 if (!last) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"last cannot be null"); 448 ierr = PetscCDRemoveNextNode(aggs_2, slid, last);CHKERRQ(ierr); 449 ierr = PetscCDAppendNode(aggs_2, lid, pos);CHKERRQ(ierr); 450 hav = 1; 451 break; 452 } else last = pos; 453 454 ierr = PetscCDGetNextPos(aggs_2,slid,&pos);CHKERRQ(ierr); 455 } 456 if (hav!=1) { 457 if (!hav) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"failed to find adj in 'selected' lists - structurally unsymmetric matrix"); 458 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"found node %d times???",hav); 459 } 460 } else { /* I'm stealing this local, owned by a ghost */ 461 if (sgid != -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Have un-symmetric graph (apparently). Use '-pc_gamg_sym_graph true' to symetrize the graph or '-pc_gamg_threshold 0.0' if the matrix is structurally symmetric."); 462 ierr = PetscCDAppendID(aggs_2, lid, lidj+my0);CHKERRQ(ierr); 463 } 464 } 465 } /* local neighbors */ 466 } else if (state == DELETED && lid_cprowID_1) { 467 PetscInt sgidold = (PetscInt)PetscRealPart(lid_parent_gid[lid]); 468 /* see if I have a selected ghost neighbor that will steal me */ 469 if ((ix=lid_cprowID_1[lid]) != -1) { 470 ii = matB_1->compressedrow.i; n = ii[ix+1] - ii[ix]; 471 idx = matB_1->j + ii[ix]; 472 for (j=0; j<n; j++) { 473 PetscInt cpid = idx[j]; 474 NState statej = (NState)PetscRealPart(cpcol_1_state[cpid]); 475 if (IS_SELECTED(statej) && sgidold != (PetscInt)statej) { /* ghost will steal this, remove from my list */ 476 lid_parent_gid[lid] = (PetscScalar)statej; /* send who selected */ 477 if (sgidold>=my0 && sgidold<Iend) { /* this was mine */ 478 PetscInt hav=0,oldslidj=sgidold-my0; 479 PetscCDPos pos,last=NULL; 480 /* remove from 'oldslidj' list */ 481 ierr = PetscCDGetHeadPos(aggs_2,oldslidj,&pos);CHKERRQ(ierr); 482 while (pos) { 483 PetscInt gid; 484 ierr = PetscLLNGetID(pos, &gid);CHKERRQ(ierr); 485 if (lid+my0 == gid) { 486 /* id_llist_2[lastid] = id_llist_2[flid]; /\* remove lid from oldslidj list *\/ */ 487 if (!last) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"last cannot be null"); 488 ierr = PetscCDRemoveNextNode(aggs_2, oldslidj, last);CHKERRQ(ierr); 489 /* ghost (PetscScalar)statej will add this later */ 490 hav = 1; 491 break; 492 } else last = pos; 493 494 ierr = PetscCDGetNextPos(aggs_2,oldslidj,&pos);CHKERRQ(ierr); 495 } 496 if (hav!=1) { 497 if (hav==0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"failed to find adj in 'selected' lists - structurally unsymmetric matrix"); 498 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"found node %d times???",hav); 499 } 500 } else { 501 /* ghosts remove this later */ 502 } 503 } 504 } 505 } 506 } /* selected/deleted */ 507 } /* node loop */ 508 509 if (isMPI) { 510 PetscScalar *cpcol_2_parent,*cpcol_2_gid; 511 Vec tempVec,ghostgids2,ghostparents2; 512 PetscInt cpid,nghost_2; 513 GAMGHashTable gid_cpid; 514 515 ierr = VecGetSize(mpimat_2->lvec, &nghost_2);CHKERRQ(ierr); 516 ierr = MatCreateVecs(Gmat_2, &tempVec, 0);CHKERRQ(ierr); 517 518 /* get 'cpcol_2_parent' */ 519 for (kk=0,j=my0; kk<nloc; kk++,j++) { 520 ierr = VecSetValues(tempVec, 1, &j, &lid_parent_gid[kk], INSERT_VALUES);CHKERRQ(ierr); 521 } 522 ierr = VecAssemblyBegin(tempVec);CHKERRQ(ierr); 523 ierr = VecAssemblyEnd(tempVec);CHKERRQ(ierr); 524 ierr = VecDuplicate(mpimat_2->lvec, &ghostparents2);CHKERRQ(ierr); 525 ierr = VecScatterBegin(mpimat_2->Mvctx,tempVec, ghostparents2,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 526 ierr = VecScatterEnd(mpimat_2->Mvctx,tempVec, ghostparents2,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 527 ierr = VecGetArray(ghostparents2, &cpcol_2_parent);CHKERRQ(ierr); 528 529 /* get 'cpcol_2_gid' */ 530 for (kk=0,j=my0; kk<nloc; kk++,j++) { 531 PetscScalar v = (PetscScalar)j; 532 ierr = VecSetValues(tempVec, 1, &j, &v, INSERT_VALUES);CHKERRQ(ierr); 533 } 534 ierr = VecAssemblyBegin(tempVec);CHKERRQ(ierr); 535 ierr = VecAssemblyEnd(tempVec);CHKERRQ(ierr); 536 ierr = VecDuplicate(mpimat_2->lvec, &ghostgids2);CHKERRQ(ierr); 537 ierr = VecScatterBegin(mpimat_2->Mvctx,tempVec, ghostgids2,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 538 ierr = VecScatterEnd(mpimat_2->Mvctx,tempVec, ghostgids2,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 539 ierr = VecGetArray(ghostgids2, &cpcol_2_gid);CHKERRQ(ierr); 540 541 ierr = VecDestroy(&tempVec);CHKERRQ(ierr); 542 543 /* look for deleted ghosts and add to table */ 544 ierr = GAMGTableCreate(2*nghost_2+1, &gid_cpid);CHKERRQ(ierr); 545 for (cpid = 0; cpid < nghost_2; cpid++) { 546 NState state = (NState)PetscRealPart(cpcol_2_state[cpid]); 547 if (state==DELETED) { 548 PetscInt sgid_new = (PetscInt)PetscRealPart(cpcol_2_parent[cpid]); 549 PetscInt sgid_old = (PetscInt)PetscRealPart(cpcol_2_par_orig[cpid]); 550 if (sgid_old == -1 && sgid_new != -1) { 551 PetscInt gid = (PetscInt)PetscRealPart(cpcol_2_gid[cpid]); 552 ierr = GAMGTableAdd(&gid_cpid, gid, cpid);CHKERRQ(ierr); 553 } 554 } 555 } 556 557 /* look for deleted ghosts and see if they moved - remove it */ 558 for (lid=0; lid<nloc; lid++) { 559 NState state = lid_state[lid]; 560 if (IS_SELECTED(state)) { 561 PetscCDPos pos,last=NULL; 562 /* look for deleted ghosts and see if they moved */ 563 ierr = PetscCDGetHeadPos(aggs_2,lid,&pos);CHKERRQ(ierr); 564 while (pos) { 565 PetscInt gid; 566 ierr = PetscLLNGetID(pos, &gid);CHKERRQ(ierr); 567 568 if (gid < my0 || gid >= Iend) { 569 ierr = GAMGTableFind(&gid_cpid, gid, &cpid);CHKERRQ(ierr); 570 if (cpid != -1) { 571 /* a moved ghost - */ 572 /* id_llist_2[lastid] = id_llist_2[flid]; /\* remove 'flid' from list *\/ */ 573 ierr = PetscCDRemoveNextNode(aggs_2, lid, last);CHKERRQ(ierr); 574 } else last = pos; 575 } else last = pos; 576 577 ierr = PetscCDGetNextPos(aggs_2,lid,&pos);CHKERRQ(ierr); 578 } /* loop over list of deleted */ 579 } /* selected */ 580 } 581 ierr = GAMGTableDestroy(&gid_cpid);CHKERRQ(ierr); 582 583 /* look at ghosts, see if they changed - and it */ 584 for (cpid = 0; cpid < nghost_2; cpid++) { 585 PetscInt sgid_new = (PetscInt)PetscRealPart(cpcol_2_parent[cpid]); 586 if (sgid_new >= my0 && sgid_new < Iend) { /* this is mine */ 587 PetscInt gid = (PetscInt)PetscRealPart(cpcol_2_gid[cpid]); 588 PetscInt slid_new=sgid_new-my0,hav=0; 589 PetscCDPos pos; 590 /* search for this gid to see if I have it */ 591 ierr = PetscCDGetHeadPos(aggs_2,slid_new,&pos);CHKERRQ(ierr); 592 while (pos) { 593 PetscInt gidj; 594 ierr = PetscLLNGetID(pos, &gidj);CHKERRQ(ierr); 595 ierr = PetscCDGetNextPos(aggs_2,slid_new,&pos);CHKERRQ(ierr); 596 597 if (gidj == gid) { hav = 1; break; } 598 } 599 if (hav != 1) { 600 /* insert 'flidj' into head of llist */ 601 ierr = PetscCDAppendID(aggs_2, slid_new, gid);CHKERRQ(ierr); 602 } 603 } 604 } 605 606 ierr = VecRestoreArray(mpimat_1->lvec, &cpcol_1_state);CHKERRQ(ierr); 607 ierr = VecRestoreArray(mpimat_2->lvec, &cpcol_2_state);CHKERRQ(ierr); 608 ierr = VecRestoreArray(ghostparents2, &cpcol_2_parent);CHKERRQ(ierr); 609 ierr = VecRestoreArray(ghostgids2, &cpcol_2_gid);CHKERRQ(ierr); 610 ierr = PetscFree(lid_cprowID_1);CHKERRQ(ierr); 611 ierr = VecDestroy(&ghostgids2);CHKERRQ(ierr); 612 ierr = VecDestroy(&ghostparents2);CHKERRQ(ierr); 613 ierr = VecDestroy(&ghost_par_orig2);CHKERRQ(ierr); 614 } 615 616 ierr = PetscFree2(lid_state,lid_parent_gid);CHKERRQ(ierr); 617 PetscFunctionReturn(0); 618 } 619 620 /* -------------------------------------------------------------------------- */ 621 /* 622 PCSetData_AGG - called if data is not set with PCSetCoordinates. 623 Looks in Mat for near null space. 624 Does not work for Stokes 625 626 Input Parameter: 627 . pc - 628 . a_A - matrix to get (near) null space out of. 629 */ 630 #undef __FUNCT__ 631 #define __FUNCT__ "PCSetData_AGG" 632 PetscErrorCode PCSetData_AGG(PC pc, Mat a_A) 633 { 634 PetscErrorCode ierr; 635 PC_MG *mg = (PC_MG*)pc->data; 636 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 637 MatNullSpace mnull; 638 639 PetscFunctionBegin; 640 ierr = MatGetNearNullSpace(a_A, &mnull);CHKERRQ(ierr); 641 if (!mnull) { 642 PetscInt bs,NN,MM; 643 ierr = MatGetBlockSize(a_A, &bs);CHKERRQ(ierr); 644 ierr = MatGetLocalSize(a_A, &MM, &NN);CHKERRQ(ierr); 645 if (MM % bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"MM %D must be divisible by bs %D",MM,bs); 646 ierr = PCSetCoordinates_AGG(pc, bs, MM/bs, NULL);CHKERRQ(ierr); 647 } else { 648 PetscReal *nullvec; 649 PetscBool has_const; 650 PetscInt i,j,mlocal,nvec,bs; 651 const Vec *vecs; const PetscScalar *v; 652 ierr = MatGetLocalSize(a_A,&mlocal,NULL);CHKERRQ(ierr); 653 ierr = MatNullSpaceGetVecs(mnull, &has_const, &nvec, &vecs);CHKERRQ(ierr); 654 pc_gamg->data_sz = (nvec+!!has_const)*mlocal; 655 ierr = PetscMalloc1((nvec+!!has_const)*mlocal,&nullvec);CHKERRQ(ierr); 656 if (has_const) for (i=0; i<mlocal; i++) nullvec[i] = 1.0; 657 for (i=0; i<nvec; i++) { 658 ierr = VecGetArrayRead(vecs[i],&v);CHKERRQ(ierr); 659 for (j=0; j<mlocal; j++) nullvec[(i+!!has_const)*mlocal + j] = PetscRealPart(v[j]); 660 ierr = VecRestoreArrayRead(vecs[i],&v);CHKERRQ(ierr); 661 } 662 pc_gamg->data = nullvec; 663 pc_gamg->data_cell_cols = (nvec+!!has_const); 664 665 ierr = MatGetBlockSize(a_A, &bs);CHKERRQ(ierr); 666 667 pc_gamg->data_cell_rows = bs; 668 } 669 PetscFunctionReturn(0); 670 } 671 672 /* -------------------------------------------------------------------------- */ 673 /* 674 formProl0 675 676 Input Parameter: 677 . agg_llists - list of arrays with aggregates -- list from selected vertices of aggregate unselected vertices 678 . bs - row block size 679 . nSAvec - column bs of new P 680 . my0crs - global index of start of locals 681 . data_stride - bs*(nloc nodes + ghost nodes) [data_stride][nSAvec] 682 . data_in[data_stride*nSAvec] - local data on fine grid 683 . flid_fgid[data_stride/bs] - make local to global IDs, includes ghosts in 'locals_llist' 684 Output Parameter: 685 . a_data_out - in with fine grid data (w/ghosts), out with coarse grid data 686 . a_Prol - prolongation operator 687 */ 688 #undef __FUNCT__ 689 #define __FUNCT__ "formProl0" 690 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) 691 { 692 PetscErrorCode ierr; 693 PetscInt Istart,my0,Iend,nloc,clid,flid = 0,aggID,kk,jj,ii,mm,ndone,nSelected,minsz,nghosts,out_data_stride; 694 MPI_Comm comm; 695 PetscMPIInt rank; 696 PetscReal *out_data; 697 PetscCDPos pos; 698 GAMGHashTable fgid_flid; 699 700 /* #define OUT_AGGS */ 701 #if defined(OUT_AGGS) 702 static PetscInt llev = 0; char fname[32]; FILE *file = NULL; PetscInt pM; 703 #endif 704 705 PetscFunctionBegin; 706 ierr = PetscObjectGetComm((PetscObject)a_Prol,&comm);CHKERRQ(ierr); 707 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 708 ierr = MatGetOwnershipRange(a_Prol, &Istart, &Iend);CHKERRQ(ierr); 709 nloc = (Iend-Istart)/bs; my0 = Istart/bs; 710 if ((Iend-Istart) % bs) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Iend %D - Istart %d must be divisible by bs %D",Iend,Istart,bs); 711 Iend /= bs; 712 nghosts = data_stride/bs - nloc; 713 714 ierr = GAMGTableCreate(2*nghosts+1, &fgid_flid);CHKERRQ(ierr); 715 for (kk=0; kk<nghosts; kk++) { 716 ierr = GAMGTableAdd(&fgid_flid, flid_fgid[nloc+kk], nloc+kk);CHKERRQ(ierr); 717 } 718 719 #if defined(OUT_AGGS) 720 sprintf(fname,"aggs_%d_%d.m",llev++,rank); 721 if (llev==1) file = fopen(fname,"w"); 722 MatGetSize(a_Prol, &pM, &jj); 723 #endif 724 725 /* count selected -- same as number of cols of P */ 726 for (nSelected=mm=0; mm<nloc; mm++) { 727 PetscBool ise; 728 ierr = PetscCDEmptyAt(agg_llists, mm, &ise);CHKERRQ(ierr); 729 if (!ise) nSelected++; 730 } 731 ierr = MatGetOwnershipRangeColumn(a_Prol, &ii, &jj);CHKERRQ(ierr); 732 if ((ii/nSAvec) != my0crs) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"ii %D /nSAvec %D != my0crs %D",ii,nSAvec,my0crs); 733 if (nSelected != (jj-ii)/nSAvec) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"nSelected %D != (jj %D - ii %D)/nSAvec %D",nSelected,jj,ii,nSAvec); 734 735 /* aloc space for coarse point data (output) */ 736 out_data_stride = nSelected*nSAvec; 737 738 ierr = PetscMalloc1(out_data_stride*nSAvec, &out_data);CHKERRQ(ierr); 739 for (ii=0;ii<out_data_stride*nSAvec;ii++) out_data[ii]=PETSC_MAX_REAL; 740 *a_data_out = out_data; /* output - stride nSelected*nSAvec */ 741 742 /* find points and set prolongation */ 743 minsz = 100; 744 ndone = 0; 745 for (mm = clid = 0; mm < nloc; mm++) { 746 ierr = PetscCDSizeAt(agg_llists, mm, &jj);CHKERRQ(ierr); 747 if (jj > 0) { 748 const PetscInt lid = mm, cgid = my0crs + clid; 749 PetscInt cids[100]; /* max bs */ 750 PetscBLASInt asz =jj,M=asz*bs,N=nSAvec,INFO; 751 PetscBLASInt Mdata=M+((N-M>0) ? N-M : 0),LDA=Mdata,LWORK=N*bs; 752 PetscScalar *qqc,*qqr,*TAU,*WORK; 753 PetscInt *fids; 754 PetscReal *data; 755 /* count agg */ 756 if (asz<minsz) minsz = asz; 757 758 /* get block */ 759 ierr = PetscMalloc5(Mdata*N, &qqc,M*N, &qqr,N, &TAU,LWORK, &WORK,M, &fids);CHKERRQ(ierr); 760 761 aggID = 0; 762 ierr = PetscCDGetHeadPos(agg_llists,lid,&pos);CHKERRQ(ierr); 763 while (pos) { 764 PetscInt gid1; 765 ierr = PetscLLNGetID(pos, &gid1);CHKERRQ(ierr); 766 ierr = PetscCDGetNextPos(agg_llists,lid,&pos);CHKERRQ(ierr); 767 768 if (gid1 >= my0 && gid1 < Iend) flid = gid1 - my0; 769 else { 770 ierr = GAMGTableFind(&fgid_flid, gid1, &flid);CHKERRQ(ierr); 771 if (flid < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cannot find gid1 in table"); 772 } 773 /* copy in B_i matrix - column oriented */ 774 data = &data_in[flid*bs]; 775 for (kk = ii = 0; ii < bs; ii++) { 776 for (jj = 0; jj < N; jj++) { 777 PetscReal d = data[jj*data_stride + ii]; 778 qqc[jj*Mdata + aggID*bs + ii] = d; 779 } 780 } 781 #if defined(OUT_AGGS) 782 if (llev==1) { 783 char str[] = "plot(%e,%e,'r*'), hold on,\n", col[] = "rgbkmc", sim[] = "*os+h>d<vx^"; 784 PetscInt MM,pi,pj; 785 str[12] = col[(clid+17*rank)%6]; str[13] = sim[(clid+17*rank)%11]; 786 MM = (PetscInt)(PetscSqrtReal((PetscReal)pM)); 787 pj = gid1/MM; pi = gid1%MM; 788 fprintf(file,str,(double)pi,(double)pj); 789 /* fprintf(file,str,data[2*data_stride+1],-data[2*data_stride]); */ 790 } 791 #endif 792 /* set fine IDs */ 793 for (kk=0; kk<bs; kk++) fids[aggID*bs + kk] = flid_fgid[flid]*bs + kk; 794 795 aggID++; 796 } 797 798 /* pad with zeros */ 799 for (ii = asz*bs; ii < Mdata; ii++) { 800 for (jj = 0; jj < N; jj++, kk++) { 801 qqc[jj*Mdata + ii] = .0; 802 } 803 } 804 805 ndone += aggID; 806 /* QR */ 807 ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr); 808 PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Mdata, &N, qqc, &LDA, TAU, WORK, &LWORK, &INFO)); 809 ierr = PetscFPTrapPop();CHKERRQ(ierr); 810 if (INFO != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"xGEQRF error"); 811 /* get R - column oriented - output B_{i+1} */ 812 { 813 PetscReal *data = &out_data[clid*nSAvec]; 814 for (jj = 0; jj < nSAvec; jj++) { 815 for (ii = 0; ii < nSAvec; ii++) { 816 if (data[jj*out_data_stride + ii] != PETSC_MAX_REAL) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"data[jj*out_data_stride + ii] != %e",PETSC_MAX_REAL); 817 if (ii <= jj) data[jj*out_data_stride + ii] = PetscRealPart(qqc[jj*Mdata + ii]); 818 else data[jj*out_data_stride + ii] = 0.; 819 } 820 } 821 } 822 823 /* get Q - row oriented */ 824 PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Mdata, &N, &N, qqc, &LDA, TAU, WORK, &LWORK, &INFO)); 825 if (INFO != 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"xORGQR error arg %d",-INFO); 826 827 for (ii = 0; ii < M; ii++) { 828 for (jj = 0; jj < N; jj++) { 829 qqr[N*ii + jj] = qqc[jj*Mdata + ii]; 830 } 831 } 832 833 /* add diagonal block of P0 */ 834 for (kk=0; kk<N; kk++) { 835 cids[kk] = N*cgid + kk; /* global col IDs in P0 */ 836 } 837 ierr = MatSetValues(a_Prol,M,fids,N,cids,qqr,INSERT_VALUES);CHKERRQ(ierr); 838 839 ierr = PetscFree5(qqc,qqr,TAU,WORK,fids);CHKERRQ(ierr); 840 clid++; 841 } /* coarse agg */ 842 } /* for all fine nodes */ 843 ierr = MatAssemblyBegin(a_Prol,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 844 ierr = MatAssemblyEnd(a_Prol,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 845 846 /* ierr = MPI_Allreduce(&ndone, &ii, 1, MPIU_INT, MPIU_SUM, comm); */ 847 /* MatGetSize(a_Prol, &kk, &jj); */ 848 /* ierr = MPI_Allreduce(&minsz, &jj, 1, MPIU_INT, MPIU_MIN, comm); */ 849 /* PetscPrintf(comm," **** [%d]%s %d total done, %d nodes (%d local done), min agg. size = %d\n",rank,__FUNCT__,ii,kk/bs,ndone,jj); */ 850 851 #if defined(OUT_AGGS) 852 if (llev==1) fclose(file); 853 #endif 854 ierr = GAMGTableDestroy(&fgid_flid);CHKERRQ(ierr); 855 PetscFunctionReturn(0); 856 } 857 858 #undef __FUNCT__ 859 #define __FUNCT__ "PCView_GAMG_AGG" 860 static PetscErrorCode PCView_GAMG_AGG(PC pc,PetscViewer viewer) 861 { 862 PetscErrorCode ierr; 863 PC_MG *mg = (PC_MG*)pc->data; 864 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 865 PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 866 867 PetscFunctionBegin; 868 ierr = PetscViewerASCIIPrintf(viewer," AGG specific options\n");CHKERRQ(ierr); 869 ierr = PetscViewerASCIIPrintf(viewer," Symmetric graph %s\n",pc_gamg_agg->sym_graph ? "true" : "false");CHKERRQ(ierr); 870 PetscFunctionReturn(0); 871 } 872 873 /* -------------------------------------------------------------------------- */ 874 /* 875 PCGAMGGraph_AGG 876 877 Input Parameter: 878 . pc - this 879 . Amat - matrix on this fine level 880 Output Parameter: 881 . a_Gmat - 882 */ 883 #undef __FUNCT__ 884 #define __FUNCT__ "PCGAMGGraph_AGG" 885 PetscErrorCode PCGAMGGraph_AGG(PC pc,Mat Amat,Mat *a_Gmat) 886 { 887 PetscErrorCode ierr; 888 PC_MG *mg = (PC_MG*)pc->data; 889 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 890 const PetscReal vfilter = pc_gamg->threshold; 891 PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 892 Mat Gmat; 893 MPI_Comm comm; 894 PetscBool /* set,flg , */ symm; 895 896 PetscFunctionBegin; 897 ierr = PetscObjectGetComm((PetscObject)Amat,&comm);CHKERRQ(ierr); 898 ierr = PetscLogEventBegin(PC_GAMGGraph_AGG,0,0,0,0);CHKERRQ(ierr); 899 900 /* ierr = MatIsSymmetricKnown(Amat, &set, &flg);CHKERRQ(ierr); || !(set && flg) -- this causes lot of symm calls */ 901 symm = (PetscBool)(pc_gamg_agg->sym_graph); /* && !pc_gamg_agg->square_graph; */ 902 903 ierr = PCGAMGCreateGraph(Amat, &Gmat);CHKERRQ(ierr); 904 ierr = PCGAMGFilterGraph(&Gmat, vfilter, symm);CHKERRQ(ierr); 905 906 *a_Gmat = Gmat; 907 908 ierr = PetscLogEventEnd(PC_GAMGGraph_AGG,0,0,0,0);CHKERRQ(ierr); 909 PetscFunctionReturn(0); 910 } 911 912 /* -------------------------------------------------------------------------- */ 913 /* 914 PCGAMGCoarsen_AGG 915 916 Input Parameter: 917 . a_pc - this 918 Input/Output Parameter: 919 . a_Gmat1 - graph on this fine level - coarsening can change this (squares it) 920 Output Parameter: 921 . agg_lists - list of aggregates 922 */ 923 #undef __FUNCT__ 924 #define __FUNCT__ "PCGAMGCoarsen_AGG" 925 PetscErrorCode PCGAMGCoarsen_AGG(PC a_pc,Mat *a_Gmat1,PetscCoarsenData **agg_lists) 926 { 927 PetscErrorCode ierr; 928 PC_MG *mg = (PC_MG*)a_pc->data; 929 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 930 PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 931 Mat mat,Gmat2, Gmat1 = *a_Gmat1; /* squared graph */ 932 IS perm; 933 PetscInt Ii,nloc,bs,n,m; 934 PetscInt *permute; 935 PetscBool *bIndexSet; 936 MatCoarsen crs; 937 MPI_Comm comm; 938 PetscMPIInt rank; 939 940 PetscFunctionBegin; 941 ierr = PetscLogEventBegin(PC_GAMGCoarsen_AGG,0,0,0,0);CHKERRQ(ierr); 942 ierr = PetscObjectGetComm((PetscObject)Gmat1,&comm);CHKERRQ(ierr); 943 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 944 ierr = MatGetLocalSize(Gmat1, &n, &m);CHKERRQ(ierr); 945 ierr = MatGetBlockSize(Gmat1, &bs);CHKERRQ(ierr); 946 if (bs != 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"bs %D must be 1",bs); 947 nloc = n/bs; 948 949 if (pc_gamg->current_level < pc_gamg_agg->square_graph) { 950 ierr = PetscInfo2(a_pc,"Square Graph on level %d of %d to square\n",pc_gamg->current_level+1,pc_gamg_agg->square_graph); 951 CHKERRQ(ierr); 952 /* ierr = MatMatTransposeMult(Gmat1, Gmat1, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &Gmat2); */ 953 ierr = MatTransposeMatMult(Gmat1, Gmat1, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &Gmat2);CHKERRQ(ierr); 954 } else Gmat2 = Gmat1; 955 956 /* get MIS aggs */ 957 /* randomize */ 958 ierr = PetscMalloc1(nloc, &permute);CHKERRQ(ierr); 959 ierr = PetscMalloc1(nloc, &bIndexSet);CHKERRQ(ierr); 960 for (Ii = 0; Ii < nloc; Ii++) { 961 bIndexSet[Ii] = PETSC_FALSE; 962 permute[Ii] = Ii; 963 } 964 srand(1); /* make deterministic */ 965 for (Ii = 0; Ii < nloc; Ii++) { 966 PetscInt iSwapIndex = rand()%nloc; 967 if (!bIndexSet[iSwapIndex] && iSwapIndex != Ii) { 968 PetscInt iTemp = permute[iSwapIndex]; 969 permute[iSwapIndex] = permute[Ii]; 970 permute[Ii] = iTemp; 971 bIndexSet[iSwapIndex] = PETSC_TRUE; 972 } 973 } 974 ierr = PetscFree(bIndexSet);CHKERRQ(ierr); 975 976 ierr = ISCreateGeneral(PETSC_COMM_SELF, nloc, permute, PETSC_USE_POINTER, &perm);CHKERRQ(ierr); 977 #if defined PETSC_GAMG_USE_LOG 978 ierr = PetscLogEventBegin(petsc_gamg_setup_events[SET4],0,0,0,0);CHKERRQ(ierr); 979 #endif 980 ierr = MatCoarsenCreate(comm, &crs);CHKERRQ(ierr); 981 /* ierr = MatCoarsenSetType(crs, MATCOARSENMIS);CHKERRQ(ierr); */ 982 ierr = MatCoarsenSetFromOptions(crs);CHKERRQ(ierr); 983 ierr = MatCoarsenSetGreedyOrdering(crs, perm);CHKERRQ(ierr); 984 ierr = MatCoarsenSetAdjacency(crs, Gmat2);CHKERRQ(ierr); 985 ierr = MatCoarsenSetStrictAggs(crs, PETSC_TRUE);CHKERRQ(ierr); 986 ierr = MatCoarsenApply(crs);CHKERRQ(ierr); 987 ierr = MatCoarsenGetData(crs, agg_lists);CHKERRQ(ierr); /* output */ 988 ierr = MatCoarsenDestroy(&crs);CHKERRQ(ierr); 989 990 ierr = ISDestroy(&perm);CHKERRQ(ierr); 991 ierr = PetscFree(permute);CHKERRQ(ierr); 992 #if defined PETSC_GAMG_USE_LOG 993 ierr = PetscLogEventEnd(petsc_gamg_setup_events[SET4],0,0,0,0);CHKERRQ(ierr); 994 #endif 995 996 /* smooth aggs */ 997 if (Gmat2 != Gmat1) { 998 const PetscCoarsenData *llist = *agg_lists; 999 ierr = smoothAggs(Gmat2, Gmat1, *agg_lists);CHKERRQ(ierr); 1000 ierr = MatDestroy(&Gmat1);CHKERRQ(ierr); 1001 *a_Gmat1 = Gmat2; /* output */ 1002 ierr = PetscCDGetMat(llist, &mat);CHKERRQ(ierr); 1003 if (mat) SETERRQ(comm,PETSC_ERR_ARG_WRONG, "Auxilary matrix with squared graph????"); 1004 } else { 1005 const PetscCoarsenData *llist = *agg_lists; 1006 /* see if we have a matrix that takes precedence (returned from MatCoarsenApply) */ 1007 ierr = PetscCDGetMat(llist, &mat);CHKERRQ(ierr); 1008 if (mat) { 1009 ierr = MatDestroy(&Gmat1);CHKERRQ(ierr); 1010 *a_Gmat1 = mat; /* output */ 1011 } 1012 } 1013 ierr = PetscLogEventEnd(PC_GAMGCoarsen_AGG,0,0,0,0);CHKERRQ(ierr); 1014 PetscFunctionReturn(0); 1015 } 1016 1017 /* -------------------------------------------------------------------------- */ 1018 /* 1019 PCGAMGProlongator_AGG 1020 1021 Input Parameter: 1022 . pc - this 1023 . Amat - matrix on this fine level 1024 . Graph - used to get ghost data for nodes in 1025 . agg_lists - list of aggregates 1026 Output Parameter: 1027 . a_P_out - prolongation operator to the next level 1028 */ 1029 #undef __FUNCT__ 1030 #define __FUNCT__ "PCGAMGProlongator_AGG" 1031 PetscErrorCode PCGAMGProlongator_AGG(PC pc,Mat Amat,Mat Gmat,PetscCoarsenData *agg_lists,Mat *a_P_out) 1032 { 1033 PC_MG *mg = (PC_MG*)pc->data; 1034 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 1035 const PetscInt data_cols = pc_gamg->data_cell_cols; 1036 PetscErrorCode ierr; 1037 PetscInt Istart,Iend,nloc,ii,jj,kk,my0,nLocalSelected,bs; 1038 Mat Prol; 1039 PetscMPIInt rank, size; 1040 MPI_Comm comm; 1041 const PetscInt col_bs = data_cols; 1042 PetscReal *data_w_ghost; 1043 PetscInt myCrs0, nbnodes=0, *flid_fgid; 1044 MatType mtype; 1045 1046 PetscFunctionBegin; 1047 ierr = PetscObjectGetComm((PetscObject)Amat,&comm);CHKERRQ(ierr); 1048 ierr = PetscLogEventBegin(PC_GAMGProlongator_AGG,0,0,0,0);CHKERRQ(ierr); 1049 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 1050 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 1051 ierr = MatGetOwnershipRange(Amat, &Istart, &Iend);CHKERRQ(ierr); 1052 ierr = MatGetBlockSize(Amat, &bs);CHKERRQ(ierr); 1053 nloc = (Iend-Istart)/bs; my0 = Istart/bs; 1054 if ((Iend-Istart) % bs) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"(Iend %D - Istart %D) not divisible by bs %D",Iend,Istart,bs); 1055 1056 /* get 'nLocalSelected' */ 1057 for (ii=0, nLocalSelected = 0; ii < nloc; ii++) { 1058 PetscBool ise; 1059 /* filter out singletons 0 or 1? */ 1060 ierr = PetscCDEmptyAt(agg_lists, ii, &ise);CHKERRQ(ierr); 1061 if (!ise) nLocalSelected++; 1062 } 1063 1064 /* create prolongator, create P matrix */ 1065 ierr = MatGetType(Amat,&mtype);CHKERRQ(ierr); 1066 ierr = MatCreate(comm, &Prol);CHKERRQ(ierr); 1067 ierr = MatSetSizes(Prol,nloc*bs,nLocalSelected*col_bs,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 1068 ierr = MatSetBlockSizes(Prol, bs, col_bs);CHKERRQ(ierr); 1069 ierr = MatSetType(Prol, mtype);CHKERRQ(ierr); 1070 ierr = MatSeqAIJSetPreallocation(Prol, data_cols, NULL);CHKERRQ(ierr); 1071 ierr = MatMPIAIJSetPreallocation(Prol,data_cols, NULL,data_cols, NULL);CHKERRQ(ierr); 1072 /* nloc*bs, nLocalSelected*col_bs, */ 1073 /* PETSC_DETERMINE, PETSC_DETERMINE, */ 1074 /* data_cols, NULL, data_cols, NULL, */ 1075 /* &Prol); */ 1076 1077 /* can get all points "removed" */ 1078 ierr = MatGetSize(Prol, &kk, &ii);CHKERRQ(ierr); 1079 if (ii==0) { 1080 ierr = PetscInfo(pc,"No selected points on coarse grid\n");CHKERRQ(ierr); 1081 ierr = MatDestroy(&Prol);CHKERRQ(ierr); 1082 *a_P_out = NULL; /* out */ 1083 PetscFunctionReturn(0); 1084 } 1085 ierr = PetscInfo1(pc,"New grid %D nodes\n",ii/col_bs);CHKERRQ(ierr); 1086 ierr = MatGetOwnershipRangeColumn(Prol, &myCrs0, &kk);CHKERRQ(ierr); 1087 1088 if ((kk-myCrs0) % col_bs) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"(kk %D -myCrs0 %D) not divisible by col_bs %D",kk,myCrs0,col_bs); 1089 myCrs0 = myCrs0/col_bs; 1090 if ((kk/col_bs-myCrs0) != nLocalSelected) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"(kk %D/col_bs %D - myCrs0 %D) != nLocalSelected %D)",kk,col_bs,myCrs0,nLocalSelected); 1091 1092 /* create global vector of data in 'data_w_ghost' */ 1093 #if defined PETSC_GAMG_USE_LOG 1094 ierr = PetscLogEventBegin(petsc_gamg_setup_events[SET7],0,0,0,0);CHKERRQ(ierr); 1095 #endif 1096 if (size > 1) { /* */ 1097 PetscReal *tmp_gdata,*tmp_ldata,*tp2; 1098 ierr = PetscMalloc1(nloc, &tmp_ldata);CHKERRQ(ierr); 1099 for (jj = 0; jj < data_cols; jj++) { 1100 for (kk = 0; kk < bs; kk++) { 1101 PetscInt ii,stride; 1102 const PetscReal *tp = pc_gamg->data + jj*bs*nloc + kk; 1103 for (ii = 0; ii < nloc; ii++, tp += bs) tmp_ldata[ii] = *tp; 1104 1105 ierr = PCGAMGGetDataWithGhosts(Gmat, 1, tmp_ldata, &stride, &tmp_gdata);CHKERRQ(ierr); 1106 1107 if (jj==0 && kk==0) { /* now I know how many todal nodes - allocate */ 1108 ierr = PetscMalloc1(stride*bs*data_cols, &data_w_ghost);CHKERRQ(ierr); 1109 nbnodes = bs*stride; 1110 } 1111 tp2 = data_w_ghost + jj*bs*stride + kk; 1112 for (ii = 0; ii < stride; ii++, tp2 += bs) *tp2 = tmp_gdata[ii]; 1113 ierr = PetscFree(tmp_gdata);CHKERRQ(ierr); 1114 } 1115 } 1116 ierr = PetscFree(tmp_ldata);CHKERRQ(ierr); 1117 } else { 1118 nbnodes = bs*nloc; 1119 data_w_ghost = (PetscReal*)pc_gamg->data; 1120 } 1121 1122 /* get P0 */ 1123 if (size > 1) { 1124 PetscReal *fid_glid_loc,*fiddata; 1125 PetscInt stride; 1126 1127 ierr = PetscMalloc1(nloc, &fid_glid_loc);CHKERRQ(ierr); 1128 for (kk=0; kk<nloc; kk++) fid_glid_loc[kk] = (PetscReal)(my0+kk); 1129 ierr = PCGAMGGetDataWithGhosts(Gmat, 1, fid_glid_loc, &stride, &fiddata);CHKERRQ(ierr); 1130 ierr = PetscMalloc1(stride, &flid_fgid);CHKERRQ(ierr); 1131 for (kk=0; kk<stride; kk++) flid_fgid[kk] = (PetscInt)fiddata[kk]; 1132 ierr = PetscFree(fiddata);CHKERRQ(ierr); 1133 1134 if (stride != nbnodes/bs) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"stride %D != nbnodes %D/bs %D",stride,nbnodes,bs); 1135 ierr = PetscFree(fid_glid_loc);CHKERRQ(ierr); 1136 } else { 1137 ierr = PetscMalloc1(nloc, &flid_fgid);CHKERRQ(ierr); 1138 for (kk=0; kk<nloc; kk++) flid_fgid[kk] = my0 + kk; 1139 } 1140 #if defined PETSC_GAMG_USE_LOG 1141 ierr = PetscLogEventEnd(petsc_gamg_setup_events[SET7],0,0,0,0);CHKERRQ(ierr); 1142 ierr = PetscLogEventBegin(petsc_gamg_setup_events[SET8],0,0,0,0);CHKERRQ(ierr); 1143 #endif 1144 { 1145 PetscReal *data_out = NULL; 1146 ierr = formProl0(agg_lists, bs, data_cols, myCrs0, nbnodes,data_w_ghost, flid_fgid, &data_out, Prol);CHKERRQ(ierr); 1147 ierr = PetscFree(pc_gamg->data);CHKERRQ(ierr); 1148 1149 pc_gamg->data = data_out; 1150 pc_gamg->data_cell_rows = data_cols; 1151 pc_gamg->data_sz = data_cols*data_cols*nLocalSelected; 1152 } 1153 #if defined PETSC_GAMG_USE_LOG 1154 ierr = PetscLogEventEnd(petsc_gamg_setup_events[SET8],0,0,0,0);CHKERRQ(ierr); 1155 #endif 1156 if (size > 1) ierr = PetscFree(data_w_ghost);CHKERRQ(ierr); 1157 ierr = PetscFree(flid_fgid);CHKERRQ(ierr); 1158 1159 *a_P_out = Prol; /* out */ 1160 1161 ierr = PetscLogEventEnd(PC_GAMGProlongator_AGG,0,0,0,0);CHKERRQ(ierr); 1162 PetscFunctionReturn(0); 1163 } 1164 1165 /* -------------------------------------------------------------------------- */ 1166 /* 1167 PCGAMGOptProlongator_AGG 1168 1169 Input Parameter: 1170 . pc - this 1171 . Amat - matrix on this fine level 1172 In/Output Parameter: 1173 . a_P_out - prolongation operator to the next level 1174 */ 1175 #undef __FUNCT__ 1176 #define __FUNCT__ "PCGAMGOptProlongator_AGG" 1177 PetscErrorCode PCGAMGOptProlongator_AGG(PC pc,Mat Amat,Mat *a_P) 1178 { 1179 PetscErrorCode ierr; 1180 PC_MG *mg = (PC_MG*)pc->data; 1181 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 1182 PC_GAMG_AGG *pc_gamg_agg = (PC_GAMG_AGG*)pc_gamg->subctx; 1183 PetscInt jj; 1184 Mat Prol = *a_P; 1185 MPI_Comm comm; 1186 1187 PetscFunctionBegin; 1188 ierr = PetscObjectGetComm((PetscObject)Amat,&comm);CHKERRQ(ierr); 1189 ierr = PetscLogEventBegin(PC_GAMGOptProlongator_AGG,0,0,0,0);CHKERRQ(ierr); 1190 1191 /* smooth P0 */ 1192 for (jj = 0; jj < pc_gamg_agg->nsmooths; jj++) { 1193 Mat tMat; 1194 Vec diag; 1195 PetscReal alpha, emax, emin; 1196 #if defined PETSC_GAMG_USE_LOG 1197 ierr = PetscLogEventBegin(petsc_gamg_setup_events[SET9],0,0,0,0);CHKERRQ(ierr); 1198 #endif 1199 if (jj == 0) { 1200 KSP eksp; 1201 Vec bb, xx; 1202 PC epc; 1203 ierr = MatCreateVecs(Amat, &bb, 0);CHKERRQ(ierr); 1204 ierr = MatCreateVecs(Amat, &xx, 0);CHKERRQ(ierr); 1205 { 1206 PetscRandom rctx; 1207 ierr = PetscRandomCreate(comm,&rctx);CHKERRQ(ierr); 1208 ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr); 1209 ierr = VecSetRandom(bb,rctx);CHKERRQ(ierr); 1210 ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr); 1211 } 1212 1213 /* zeroing out BC rows -- needed for crazy matrices */ 1214 { 1215 PetscInt Istart,Iend,ncols,jj,Ii; 1216 PetscScalar zero = 0.0; 1217 ierr = MatGetOwnershipRange(Amat, &Istart, &Iend);CHKERRQ(ierr); 1218 for (Ii = Istart, jj = 0; Ii < Iend; Ii++, jj++) { 1219 ierr = MatGetRow(Amat,Ii,&ncols,0,0);CHKERRQ(ierr); 1220 if (ncols <= 1) { 1221 ierr = VecSetValues(bb, 1, &Ii, &zero, INSERT_VALUES);CHKERRQ(ierr); 1222 } 1223 ierr = MatRestoreRow(Amat,Ii,&ncols,0,0);CHKERRQ(ierr); 1224 } 1225 ierr = VecAssemblyBegin(bb);CHKERRQ(ierr); 1226 ierr = VecAssemblyEnd(bb);CHKERRQ(ierr); 1227 } 1228 1229 ierr = KSPCreate(comm,&eksp);CHKERRQ(ierr); 1230 ierr = KSPSetErrorIfNotConverged(eksp,pc->erroriffailure);CHKERRQ(ierr); 1231 ierr = KSPSetTolerances(eksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,10);CHKERRQ(ierr); 1232 ierr = KSPSetNormType(eksp, KSP_NORM_NONE);CHKERRQ(ierr); 1233 ierr = KSPSetOptionsPrefix(eksp,((PetscObject)pc)->prefix);CHKERRQ(ierr); 1234 ierr = KSPAppendOptionsPrefix(eksp, "gamg_est_");CHKERRQ(ierr); 1235 ierr = KSPSetFromOptions(eksp);CHKERRQ(ierr); 1236 1237 ierr = KSPSetInitialGuessNonzero(eksp, PETSC_FALSE);CHKERRQ(ierr); 1238 ierr = KSPSetOperators(eksp, Amat, Amat);CHKERRQ(ierr); 1239 ierr = KSPSetComputeSingularValues(eksp,PETSC_TRUE);CHKERRQ(ierr); 1240 1241 ierr = KSPGetPC(eksp, &epc);CHKERRQ(ierr); 1242 ierr = PCSetType(epc, PCJACOBI);CHKERRQ(ierr); /* smoother in smoothed agg. */ 1243 1244 /* solve - keep stuff out of logging */ 1245 ierr = PetscLogEventDeactivate(KSP_Solve);CHKERRQ(ierr); 1246 ierr = PetscLogEventDeactivate(PC_Apply);CHKERRQ(ierr); 1247 ierr = KSPSolve(eksp, bb, xx);CHKERRQ(ierr); 1248 ierr = PetscLogEventActivate(KSP_Solve);CHKERRQ(ierr); 1249 ierr = PetscLogEventActivate(PC_Apply);CHKERRQ(ierr); 1250 1251 ierr = KSPComputeExtremeSingularValues(eksp, &emax, &emin);CHKERRQ(ierr); 1252 ierr = PetscInfo3(pc,"Smooth P0: max eigen=%e min=%e PC=%s\n",emax,emin,PCJACOBI);CHKERRQ(ierr); 1253 ierr = VecDestroy(&xx);CHKERRQ(ierr); 1254 ierr = VecDestroy(&bb);CHKERRQ(ierr); 1255 ierr = KSPDestroy(&eksp);CHKERRQ(ierr); 1256 1257 if (pc_gamg->emax_id == -1) { 1258 ierr = PetscObjectComposedDataRegister(&pc_gamg->emax_id);CHKERRQ(ierr); 1259 if (pc_gamg->emax_id == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"pc_gamg->emax_id == -1"); 1260 } 1261 ierr = PetscObjectComposedDataSetScalar((PetscObject)Amat, pc_gamg->emax_id, emax);CHKERRQ(ierr); 1262 } 1263 1264 /* smooth P1 := (I - omega/lam D^{-1}A)P0 */ 1265 ierr = MatMatMult(Amat, Prol, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &tMat);CHKERRQ(ierr); 1266 ierr = MatCreateVecs(Amat, &diag, 0);CHKERRQ(ierr); 1267 ierr = MatGetDiagonal(Amat, diag);CHKERRQ(ierr); /* effectively PCJACOBI */ 1268 ierr = VecReciprocal(diag);CHKERRQ(ierr); 1269 ierr = MatDiagonalScale(tMat, diag, 0);CHKERRQ(ierr); 1270 ierr = VecDestroy(&diag);CHKERRQ(ierr); 1271 alpha = -1.4/emax; 1272 ierr = MatAYPX(tMat, alpha, Prol, SUBSET_NONZERO_PATTERN);CHKERRQ(ierr); 1273 ierr = MatDestroy(&Prol);CHKERRQ(ierr); 1274 Prol = tMat; 1275 #if defined PETSC_GAMG_USE_LOG 1276 ierr = PetscLogEventEnd(petsc_gamg_setup_events[SET9],0,0,0,0);CHKERRQ(ierr); 1277 #endif 1278 } 1279 ierr = PetscLogEventEnd(PC_GAMGOptProlongator_AGG,0,0,0,0);CHKERRQ(ierr); 1280 *a_P = Prol; 1281 PetscFunctionReturn(0); 1282 } 1283 1284 /* -------------------------------------------------------------------------- */ 1285 /* 1286 PCCreateGAMG_AGG 1287 1288 Input Parameter: 1289 . pc - 1290 */ 1291 #undef __FUNCT__ 1292 #define __FUNCT__ "PCCreateGAMG_AGG" 1293 PetscErrorCode PCCreateGAMG_AGG(PC pc) 1294 { 1295 PetscErrorCode ierr; 1296 PC_MG *mg = (PC_MG*)pc->data; 1297 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 1298 PC_GAMG_AGG *pc_gamg_agg; 1299 1300 PetscFunctionBegin; 1301 /* create sub context for SA */ 1302 ierr = PetscNewLog(pc,&pc_gamg_agg);CHKERRQ(ierr); 1303 pc_gamg->subctx = pc_gamg_agg; 1304 1305 pc_gamg->ops->setfromoptions = PCSetFromOptions_GAMG_AGG; 1306 pc_gamg->ops->destroy = PCDestroy_GAMG_AGG; 1307 /* reset does not do anything; setup not virtual */ 1308 1309 /* set internal function pointers */ 1310 pc_gamg->ops->graph = PCGAMGGraph_AGG; 1311 pc_gamg->ops->coarsen = PCGAMGCoarsen_AGG; 1312 pc_gamg->ops->prolongator = PCGAMGProlongator_AGG; 1313 pc_gamg->ops->optprolongator = PCGAMGOptProlongator_AGG; 1314 pc_gamg->ops->createdefaultdata = PCSetData_AGG; 1315 pc_gamg->ops->view = PCView_GAMG_AGG; 1316 1317 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCSetCoordinates_C",PCSetCoordinates_AGG);CHKERRQ(ierr); 1318 PetscFunctionReturn(0); 1319 } 1320