1 #include <../src/ksp/pc/impls/gamg/gamg.h> /*I "petscpc.h" I*/ 2 #include <petscsf.h> 3 4 PetscFunctionList PCGAMGClassicalProlongatorList = NULL; 5 PetscBool PCGAMGClassicalPackageInitialized = PETSC_FALSE; 6 7 typedef struct { 8 PetscReal interp_threshold; /* interpolation threshold */ 9 char prolongtype[256]; 10 PetscInt nsmooths; /* number of jacobi smoothings on the prolongator */ 11 } PC_GAMG_Classical; 12 13 /*@C 14 PCGAMGClassicalSetType - Sets the type of classical interpolation to use 15 16 Collective on PC 17 18 Input Parameters: 19 . pc - the preconditioner context 20 21 Options Database Key: 22 . -pc_gamg_classical_type 23 24 Level: intermediate 25 26 .seealso: () 27 @*/ 28 PetscErrorCode PCGAMGClassicalSetType(PC pc, PCGAMGClassicalType type) 29 { 30 PetscErrorCode ierr; 31 32 PetscFunctionBegin; 33 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 34 ierr = PetscTryMethod(pc,"PCGAMGClassicalSetType_C",(PC,PCGAMGClassicalType),(pc,type));CHKERRQ(ierr); 35 PetscFunctionReturn(0); 36 } 37 38 /*@C 39 PCGAMGClassicalGetType - Gets the type of classical interpolation to use 40 41 Collective on PC 42 43 Input Parameter: 44 . pc - the preconditioner context 45 46 Output Parameter: 47 . type - the type used 48 49 Level: intermediate 50 51 .seealso: () 52 @*/ 53 PetscErrorCode PCGAMGClassicalGetType(PC pc, PCGAMGClassicalType *type) 54 { 55 PetscErrorCode ierr; 56 57 PetscFunctionBegin; 58 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 59 ierr = PetscUseMethod(pc,"PCGAMGClassicalGetType_C",(PC,PCGAMGClassicalType*),(pc,type));CHKERRQ(ierr); 60 PetscFunctionReturn(0); 61 } 62 63 static PetscErrorCode PCGAMGClassicalSetType_GAMG(PC pc, PCGAMGClassicalType type) 64 { 65 PetscErrorCode ierr; 66 PC_MG *mg = (PC_MG*)pc->data; 67 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 68 PC_GAMG_Classical *cls = (PC_GAMG_Classical*)pc_gamg->subctx; 69 70 PetscFunctionBegin; 71 ierr = PetscStrcpy(cls->prolongtype,type);CHKERRQ(ierr); 72 PetscFunctionReturn(0); 73 } 74 75 static PetscErrorCode PCGAMGClassicalGetType_GAMG(PC pc, PCGAMGClassicalType *type) 76 { 77 PC_MG *mg = (PC_MG*)pc->data; 78 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 79 PC_GAMG_Classical *cls = (PC_GAMG_Classical*)pc_gamg->subctx; 80 81 PetscFunctionBegin; 82 *type = cls->prolongtype; 83 PetscFunctionReturn(0); 84 } 85 86 PetscErrorCode PCGAMGGraph_Classical(PC pc,Mat A,Mat *G) 87 { 88 PetscInt s,f,n,idx,lidx,gidx; 89 PetscInt r,c,ncols; 90 const PetscInt *rcol; 91 const PetscScalar *rval; 92 PetscInt *gcol; 93 PetscScalar *gval; 94 PetscReal rmax; 95 PetscInt cmax = 0; 96 PC_MG *mg = (PC_MG *)pc->data; 97 PC_GAMG *gamg = (PC_GAMG *)mg->innerctx; 98 PetscErrorCode ierr; 99 PetscInt *gsparse,*lsparse; 100 PetscScalar *Amax; 101 MatType mtype; 102 103 PetscFunctionBegin; 104 ierr = MatGetOwnershipRange(A,&s,&f);CHKERRQ(ierr); 105 n=f-s; 106 ierr = PetscMalloc3(n,&lsparse,n,&gsparse,n,&Amax);CHKERRQ(ierr); 107 108 for (r = 0;r < n;r++) { 109 lsparse[r] = 0; 110 gsparse[r] = 0; 111 } 112 113 for (r = s;r < f;r++) { 114 /* determine the maximum off-diagonal in each row */ 115 rmax = 0.; 116 ierr = MatGetRow(A,r,&ncols,&rcol,&rval);CHKERRQ(ierr); 117 for (c = 0; c < ncols; c++) { 118 if (PetscRealPart(-rval[c]) > rmax && rcol[c] != r) { 119 rmax = PetscRealPart(-rval[c]); 120 } 121 } 122 Amax[r-s] = rmax; 123 if (ncols > cmax) cmax = ncols; 124 lidx = 0; 125 gidx = 0; 126 /* create the local and global sparsity patterns */ 127 for (c = 0; c < ncols; c++) { 128 if (PetscRealPart(-rval[c]) > gamg->threshold[0]*PetscRealPart(Amax[r-s]) || rcol[c] == r) { 129 if (rcol[c] < f && rcol[c] >= s) { 130 lidx++; 131 } else { 132 gidx++; 133 } 134 } 135 } 136 ierr = MatRestoreRow(A,r,&ncols,&rcol,&rval);CHKERRQ(ierr); 137 lsparse[r-s] = lidx; 138 gsparse[r-s] = gidx; 139 } 140 ierr = PetscMalloc2(cmax,&gval,cmax,&gcol);CHKERRQ(ierr); 141 142 ierr = MatCreate(PetscObjectComm((PetscObject)A),G);CHKERRQ(ierr); 143 ierr = MatGetType(A,&mtype);CHKERRQ(ierr); 144 ierr = MatSetType(*G,mtype);CHKERRQ(ierr); 145 ierr = MatSetSizes(*G,n,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 146 ierr = MatMPIAIJSetPreallocation(*G,0,lsparse,0,gsparse);CHKERRQ(ierr); 147 ierr = MatSeqAIJSetPreallocation(*G,0,lsparse);CHKERRQ(ierr); 148 for (r = s;r < f;r++) { 149 ierr = MatGetRow(A,r,&ncols,&rcol,&rval);CHKERRQ(ierr); 150 idx = 0; 151 for (c = 0; c < ncols; c++) { 152 /* classical strength of connection */ 153 if (PetscRealPart(-rval[c]) > gamg->threshold[0]*PetscRealPart(Amax[r-s]) || rcol[c] == r) { 154 gcol[idx] = rcol[c]; 155 gval[idx] = rval[c]; 156 idx++; 157 } 158 } 159 ierr = MatSetValues(*G,1,&r,idx,gcol,gval,INSERT_VALUES);CHKERRQ(ierr); 160 ierr = MatRestoreRow(A,r,&ncols,&rcol,&rval);CHKERRQ(ierr); 161 } 162 ierr = MatAssemblyBegin(*G, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 163 ierr = MatAssemblyEnd(*G, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 164 165 ierr = PetscFree2(gval,gcol);CHKERRQ(ierr); 166 ierr = PetscFree3(lsparse,gsparse,Amax);CHKERRQ(ierr); 167 PetscFunctionReturn(0); 168 } 169 170 171 PetscErrorCode PCGAMGCoarsen_Classical(PC pc,Mat *G,PetscCoarsenData **agg_lists) 172 { 173 PetscErrorCode ierr; 174 MatCoarsen crs; 175 MPI_Comm fcomm = ((PetscObject)pc)->comm; 176 177 PetscFunctionBegin; 178 if (!G) SETERRQ(fcomm,PETSC_ERR_ARG_WRONGSTATE,"Must set Graph in PC in PCGAMG before coarsening"); 179 180 ierr = MatCoarsenCreate(fcomm,&crs);CHKERRQ(ierr); 181 ierr = MatCoarsenSetFromOptions(crs);CHKERRQ(ierr); 182 ierr = MatCoarsenSetAdjacency(crs,*G);CHKERRQ(ierr); 183 ierr = MatCoarsenSetStrictAggs(crs,PETSC_TRUE);CHKERRQ(ierr); 184 ierr = MatCoarsenApply(crs);CHKERRQ(ierr); 185 ierr = MatCoarsenGetData(crs,agg_lists);CHKERRQ(ierr); 186 ierr = MatCoarsenDestroy(&crs);CHKERRQ(ierr); 187 PetscFunctionReturn(0); 188 } 189 190 PetscErrorCode PCGAMGProlongator_Classical_Direct(PC pc, Mat A, Mat G, PetscCoarsenData *agg_lists,Mat *P) 191 { 192 PetscErrorCode ierr; 193 PC_MG *mg = (PC_MG*)pc->data; 194 PC_GAMG *gamg = (PC_GAMG*)mg->innerctx; 195 PetscBool iscoarse,isMPIAIJ,isSEQAIJ; 196 PetscInt fn,cn,fs,fe,cs,ce,i,j,ncols,col,row_f,row_c,cmax=0,idx,noff; 197 PetscInt *lcid,*gcid,*lsparse,*gsparse,*colmap,*pcols; 198 const PetscInt *rcol; 199 PetscReal *Amax_pos,*Amax_neg; 200 PetscScalar g_pos,g_neg,a_pos,a_neg,diag,invdiag,alpha,beta,pij; 201 PetscScalar *pvals; 202 const PetscScalar *rval; 203 Mat lA,gA=NULL; 204 MatType mtype; 205 Vec C,lvec; 206 PetscLayout clayout; 207 PetscSF sf; 208 Mat_MPIAIJ *mpiaij; 209 210 PetscFunctionBegin; 211 ierr = MatGetOwnershipRange(A,&fs,&fe);CHKERRQ(ierr); 212 fn = fe-fs; 213 ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&isMPIAIJ);CHKERRQ(ierr); 214 ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&isSEQAIJ);CHKERRQ(ierr); 215 if (!isMPIAIJ && !isSEQAIJ) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Classical AMG requires MPIAIJ matrix"); 216 if (isMPIAIJ) { 217 mpiaij = (Mat_MPIAIJ*)A->data; 218 lA = mpiaij->A; 219 gA = mpiaij->B; 220 lvec = mpiaij->lvec; 221 ierr = VecGetSize(lvec,&noff);CHKERRQ(ierr); 222 colmap = mpiaij->garray; 223 ierr = MatGetLayouts(A,NULL,&clayout);CHKERRQ(ierr); 224 ierr = PetscSFCreate(PetscObjectComm((PetscObject)A),&sf);CHKERRQ(ierr); 225 ierr = PetscSFSetGraphLayout(sf,clayout,noff,NULL,PETSC_COPY_VALUES,colmap);CHKERRQ(ierr); 226 ierr = PetscMalloc1(noff,&gcid);CHKERRQ(ierr); 227 } else { 228 lA = A; 229 } 230 ierr = PetscMalloc5(fn,&lsparse,fn,&gsparse,fn,&lcid,fn,&Amax_pos,fn,&Amax_neg);CHKERRQ(ierr); 231 232 /* count the number of coarse unknowns */ 233 cn = 0; 234 for (i=0;i<fn;i++) { 235 /* filter out singletons */ 236 ierr = PetscCDEmptyAt(agg_lists,i,&iscoarse);CHKERRQ(ierr); 237 lcid[i] = -1; 238 if (!iscoarse) { 239 cn++; 240 } 241 } 242 243 /* create the coarse vector */ 244 ierr = VecCreateMPI(PetscObjectComm((PetscObject)A),cn,PETSC_DECIDE,&C);CHKERRQ(ierr); 245 ierr = VecGetOwnershipRange(C,&cs,&ce);CHKERRQ(ierr); 246 247 cn = 0; 248 for (i=0;i<fn;i++) { 249 ierr = PetscCDEmptyAt(agg_lists,i,&iscoarse);CHKERRQ(ierr); 250 if (!iscoarse) { 251 lcid[i] = cs+cn; 252 cn++; 253 } else { 254 lcid[i] = -1; 255 } 256 } 257 258 if (gA) { 259 ierr = PetscSFBcastBegin(sf,MPIU_INT,lcid,gcid);CHKERRQ(ierr); 260 ierr = PetscSFBcastEnd(sf,MPIU_INT,lcid,gcid);CHKERRQ(ierr); 261 } 262 263 /* determine the largest off-diagonal entries in each row */ 264 for (i=fs;i<fe;i++) { 265 Amax_pos[i-fs] = 0.; 266 Amax_neg[i-fs] = 0.; 267 ierr = MatGetRow(A,i,&ncols,&rcol,&rval);CHKERRQ(ierr); 268 for (j=0;j<ncols;j++){ 269 if ((PetscRealPart(-rval[j]) > Amax_neg[i-fs]) && i != rcol[j]) Amax_neg[i-fs] = PetscAbsScalar(rval[j]); 270 if ((PetscRealPart(rval[j]) > Amax_pos[i-fs]) && i != rcol[j]) Amax_pos[i-fs] = PetscAbsScalar(rval[j]); 271 } 272 if (ncols > cmax) cmax = ncols; 273 ierr = MatRestoreRow(A,i,&ncols,&rcol,&rval);CHKERRQ(ierr); 274 } 275 ierr = PetscMalloc2(cmax,&pcols,cmax,&pvals);CHKERRQ(ierr); 276 ierr = VecDestroy(&C);CHKERRQ(ierr); 277 278 /* count the on and off processor sparsity patterns for the prolongator */ 279 for (i=0;i<fn;i++) { 280 /* on */ 281 lsparse[i] = 0; 282 gsparse[i] = 0; 283 if (lcid[i] >= 0) { 284 lsparse[i] = 1; 285 gsparse[i] = 0; 286 } else { 287 ierr = MatGetRow(lA,i,&ncols,&rcol,&rval);CHKERRQ(ierr); 288 for (j = 0;j < ncols;j++) { 289 col = rcol[j]; 290 if (lcid[col] >= 0 && (PetscRealPart(rval[j]) > gamg->threshold[0]*Amax_pos[i] || PetscRealPart(-rval[j]) > gamg->threshold[0]*Amax_neg[i])) { 291 lsparse[i] += 1; 292 } 293 } 294 ierr = MatRestoreRow(lA,i,&ncols,&rcol,&rval);CHKERRQ(ierr); 295 /* off */ 296 if (gA) { 297 ierr = MatGetRow(gA,i,&ncols,&rcol,&rval);CHKERRQ(ierr); 298 for (j = 0; j < ncols; j++) { 299 col = rcol[j]; 300 if (gcid[col] >= 0 && (PetscRealPart(rval[j]) > gamg->threshold[0]*Amax_pos[i] || PetscRealPart(-rval[j]) > gamg->threshold[0]*Amax_neg[i])) { 301 gsparse[i] += 1; 302 } 303 } 304 ierr = MatRestoreRow(gA,i,&ncols,&rcol,&rval);CHKERRQ(ierr); 305 } 306 } 307 } 308 309 /* preallocate and create the prolongator */ 310 ierr = MatCreate(PetscObjectComm((PetscObject)A),P);CHKERRQ(ierr); 311 ierr = MatGetType(G,&mtype);CHKERRQ(ierr); 312 ierr = MatSetType(*P,mtype);CHKERRQ(ierr); 313 ierr = MatSetSizes(*P,fn,cn,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 314 ierr = MatMPIAIJSetPreallocation(*P,0,lsparse,0,gsparse);CHKERRQ(ierr); 315 ierr = MatSeqAIJSetPreallocation(*P,0,lsparse);CHKERRQ(ierr); 316 317 /* loop over local fine nodes -- get the diagonal, the sum of positive and negative strong and weak weights, and set up the row */ 318 for (i = 0;i < fn;i++) { 319 /* determine on or off */ 320 row_f = i + fs; 321 row_c = lcid[i]; 322 if (row_c >= 0) { 323 pij = 1.; 324 ierr = MatSetValues(*P,1,&row_f,1,&row_c,&pij,INSERT_VALUES);CHKERRQ(ierr); 325 } else { 326 g_pos = 0.; 327 g_neg = 0.; 328 a_pos = 0.; 329 a_neg = 0.; 330 diag = 0.; 331 332 /* local connections */ 333 ierr = MatGetRow(lA,i,&ncols,&rcol,&rval);CHKERRQ(ierr); 334 for (j = 0; j < ncols; j++) { 335 col = rcol[j]; 336 if (lcid[col] >= 0 && (PetscRealPart(rval[j]) > gamg->threshold[0]*Amax_pos[i] || PetscRealPart(-rval[j]) > gamg->threshold[0]*Amax_neg[i])) { 337 if (PetscRealPart(rval[j]) > 0.) { 338 g_pos += rval[j]; 339 } else { 340 g_neg += rval[j]; 341 } 342 } 343 if (col != i) { 344 if (PetscRealPart(rval[j]) > 0.) { 345 a_pos += rval[j]; 346 } else { 347 a_neg += rval[j]; 348 } 349 } else { 350 diag = rval[j]; 351 } 352 } 353 ierr = MatRestoreRow(lA,i,&ncols,&rcol,&rval);CHKERRQ(ierr); 354 355 /* ghosted connections */ 356 if (gA) { 357 ierr = MatGetRow(gA,i,&ncols,&rcol,&rval);CHKERRQ(ierr); 358 for (j = 0; j < ncols; j++) { 359 col = rcol[j]; 360 if (gcid[col] >= 0 && (PetscRealPart(rval[j]) > gamg->threshold[0]*Amax_pos[i] || PetscRealPart(-rval[j]) > gamg->threshold[0]*Amax_neg[i])) { 361 if (PetscRealPart(rval[j]) > 0.) { 362 g_pos += rval[j]; 363 } else { 364 g_neg += rval[j]; 365 } 366 } 367 if (PetscRealPart(rval[j]) > 0.) { 368 a_pos += rval[j]; 369 } else { 370 a_neg += rval[j]; 371 } 372 } 373 ierr = MatRestoreRow(gA,i,&ncols,&rcol,&rval);CHKERRQ(ierr); 374 } 375 376 if (g_neg == 0.) { 377 alpha = 0.; 378 } else { 379 alpha = -a_neg/g_neg; 380 } 381 382 if (g_pos == 0.) { 383 diag += a_pos; 384 beta = 0.; 385 } else { 386 beta = -a_pos/g_pos; 387 } 388 if (diag == 0.) { 389 invdiag = 0.; 390 } else invdiag = 1. / diag; 391 /* on */ 392 ierr = MatGetRow(lA,i,&ncols,&rcol,&rval);CHKERRQ(ierr); 393 idx = 0; 394 for (j = 0;j < ncols;j++) { 395 col = rcol[j]; 396 if (lcid[col] >= 0 && (PetscRealPart(rval[j]) > gamg->threshold[0]*Amax_pos[i] || PetscRealPart(-rval[j]) > gamg->threshold[0]*Amax_neg[i])) { 397 row_f = i + fs; 398 row_c = lcid[col]; 399 /* set the values for on-processor ones */ 400 if (PetscRealPart(rval[j]) < 0.) { 401 pij = rval[j]*alpha*invdiag; 402 } else { 403 pij = rval[j]*beta*invdiag; 404 } 405 if (PetscAbsScalar(pij) != 0.) { 406 pvals[idx] = pij; 407 pcols[idx] = row_c; 408 idx++; 409 } 410 } 411 } 412 ierr = MatRestoreRow(lA,i,&ncols,&rcol,&rval);CHKERRQ(ierr); 413 /* off */ 414 if (gA) { 415 ierr = MatGetRow(gA,i,&ncols,&rcol,&rval);CHKERRQ(ierr); 416 for (j = 0; j < ncols; j++) { 417 col = rcol[j]; 418 if (gcid[col] >= 0 && (PetscRealPart(rval[j]) > gamg->threshold[0]*Amax_pos[i] || PetscRealPart(-rval[j]) > gamg->threshold[0]*Amax_neg[i])) { 419 row_f = i + fs; 420 row_c = gcid[col]; 421 /* set the values for on-processor ones */ 422 if (PetscRealPart(rval[j]) < 0.) { 423 pij = rval[j]*alpha*invdiag; 424 } else { 425 pij = rval[j]*beta*invdiag; 426 } 427 if (PetscAbsScalar(pij) != 0.) { 428 pvals[idx] = pij; 429 pcols[idx] = row_c; 430 idx++; 431 } 432 } 433 } 434 ierr = MatRestoreRow(gA,i,&ncols,&rcol,&rval);CHKERRQ(ierr); 435 } 436 ierr = MatSetValues(*P,1,&row_f,idx,pcols,pvals,INSERT_VALUES);CHKERRQ(ierr); 437 } 438 } 439 440 ierr = MatAssemblyBegin(*P, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 441 ierr = MatAssemblyEnd(*P, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 442 443 ierr = PetscFree5(lsparse,gsparse,lcid,Amax_pos,Amax_neg);CHKERRQ(ierr); 444 445 ierr = PetscFree2(pcols,pvals);CHKERRQ(ierr); 446 if (gA) { 447 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 448 ierr = PetscFree(gcid);CHKERRQ(ierr); 449 } 450 PetscFunctionReturn(0); 451 } 452 453 PetscErrorCode PCGAMGTruncateProlongator_Private(PC pc,Mat *P) 454 { 455 PetscInt j,i,ps,pf,pn,pcs,pcf,pcn,idx,cmax; 456 PetscErrorCode ierr; 457 const PetscScalar *pval; 458 const PetscInt *pcol; 459 PetscScalar *pnval; 460 PetscInt *pncol; 461 PetscInt ncols; 462 Mat Pnew; 463 PetscInt *lsparse,*gsparse; 464 PetscReal pmax_pos,pmax_neg,ptot_pos,ptot_neg,pthresh_pos,pthresh_neg; 465 PC_MG *mg = (PC_MG*)pc->data; 466 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 467 PC_GAMG_Classical *cls = (PC_GAMG_Classical*)pc_gamg->subctx; 468 MatType mtype; 469 470 PetscFunctionBegin; 471 /* trim and rescale with reallocation */ 472 ierr = MatGetOwnershipRange(*P,&ps,&pf);CHKERRQ(ierr); 473 ierr = MatGetOwnershipRangeColumn(*P,&pcs,&pcf);CHKERRQ(ierr); 474 pn = pf-ps; 475 pcn = pcf-pcs; 476 ierr = PetscMalloc2(pn,&lsparse,pn,&gsparse);CHKERRQ(ierr); 477 /* allocate */ 478 cmax = 0; 479 for (i=ps;i<pf;i++) { 480 lsparse[i-ps] = 0; 481 gsparse[i-ps] = 0; 482 ierr = MatGetRow(*P,i,&ncols,&pcol,&pval);CHKERRQ(ierr); 483 if (ncols > cmax) { 484 cmax = ncols; 485 } 486 pmax_pos = 0.; 487 pmax_neg = 0.; 488 for (j=0;j<ncols;j++) { 489 if (PetscRealPart(pval[j]) > pmax_pos) { 490 pmax_pos = PetscRealPart(pval[j]); 491 } else if (PetscRealPart(pval[j]) < pmax_neg) { 492 pmax_neg = PetscRealPart(pval[j]); 493 } 494 } 495 for (j=0;j<ncols;j++) { 496 if (PetscRealPart(pval[j]) >= pmax_pos*cls->interp_threshold || PetscRealPart(pval[j]) <= pmax_neg*cls->interp_threshold) { 497 if (pcol[j] >= pcs && pcol[j] < pcf) { 498 lsparse[i-ps]++; 499 } else { 500 gsparse[i-ps]++; 501 } 502 } 503 } 504 ierr = MatRestoreRow(*P,i,&ncols,&pcol,&pval);CHKERRQ(ierr); 505 } 506 507 ierr = PetscMalloc2(cmax,&pnval,cmax,&pncol);CHKERRQ(ierr); 508 509 ierr = MatGetType(*P,&mtype);CHKERRQ(ierr); 510 ierr = MatCreate(PetscObjectComm((PetscObject)*P),&Pnew);CHKERRQ(ierr); 511 ierr = MatSetType(Pnew, mtype);CHKERRQ(ierr); 512 ierr = MatSetSizes(Pnew,pn,pcn,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 513 ierr = MatSeqAIJSetPreallocation(Pnew,0,lsparse);CHKERRQ(ierr); 514 ierr = MatMPIAIJSetPreallocation(Pnew,0,lsparse,0,gsparse);CHKERRQ(ierr); 515 516 for (i=ps;i<pf;i++) { 517 ierr = MatGetRow(*P,i,&ncols,&pcol,&pval);CHKERRQ(ierr); 518 pmax_pos = 0.; 519 pmax_neg = 0.; 520 for (j=0;j<ncols;j++) { 521 if (PetscRealPart(pval[j]) > pmax_pos) { 522 pmax_pos = PetscRealPart(pval[j]); 523 } else if (PetscRealPart(pval[j]) < pmax_neg) { 524 pmax_neg = PetscRealPart(pval[j]); 525 } 526 } 527 pthresh_pos = 0.; 528 pthresh_neg = 0.; 529 ptot_pos = 0.; 530 ptot_neg = 0.; 531 for (j=0;j<ncols;j++) { 532 if (PetscRealPart(pval[j]) >= cls->interp_threshold*pmax_pos) { 533 pthresh_pos += PetscRealPart(pval[j]); 534 } else if (PetscRealPart(pval[j]) <= cls->interp_threshold*pmax_neg) { 535 pthresh_neg += PetscRealPart(pval[j]); 536 } 537 if (PetscRealPart(pval[j]) > 0.) { 538 ptot_pos += PetscRealPart(pval[j]); 539 } else { 540 ptot_neg += PetscRealPart(pval[j]); 541 } 542 } 543 if (PetscAbsReal(pthresh_pos) > 0.) ptot_pos /= pthresh_pos; 544 if (PetscAbsReal(pthresh_neg) > 0.) ptot_neg /= pthresh_neg; 545 idx=0; 546 for (j=0;j<ncols;j++) { 547 if (PetscRealPart(pval[j]) >= pmax_pos*cls->interp_threshold) { 548 pnval[idx] = ptot_pos*pval[j]; 549 pncol[idx] = pcol[j]; 550 idx++; 551 } else if (PetscRealPart(pval[j]) <= pmax_neg*cls->interp_threshold) { 552 pnval[idx] = ptot_neg*pval[j]; 553 pncol[idx] = pcol[j]; 554 idx++; 555 } 556 } 557 ierr = MatRestoreRow(*P,i,&ncols,&pcol,&pval);CHKERRQ(ierr); 558 ierr = MatSetValues(Pnew,1,&i,idx,pncol,pnval,INSERT_VALUES);CHKERRQ(ierr); 559 } 560 561 ierr = MatAssemblyBegin(Pnew, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 562 ierr = MatAssemblyEnd(Pnew, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 563 ierr = MatDestroy(P);CHKERRQ(ierr); 564 565 *P = Pnew; 566 ierr = PetscFree2(lsparse,gsparse);CHKERRQ(ierr); 567 ierr = PetscFree2(pnval,pncol);CHKERRQ(ierr); 568 PetscFunctionReturn(0); 569 } 570 571 PetscErrorCode PCGAMGProlongator_Classical_Standard(PC pc, Mat A, Mat G, PetscCoarsenData *agg_lists,Mat *P) 572 { 573 PetscErrorCode ierr; 574 Mat lA,*lAs; 575 MatType mtype; 576 Vec cv; 577 PetscInt *gcid,*lcid,*lsparse,*gsparse,*picol; 578 PetscInt fs,fe,cs,ce,nl,i,j,k,li,lni,ci,ncols,maxcols,fn,cn,cid; 579 PetscMPIInt size; 580 const PetscInt *lidx,*icol,*gidx; 581 PetscBool iscoarse; 582 PetscScalar vi,pentry,pjentry; 583 PetscScalar *pcontrib,*pvcol; 584 const PetscScalar *vcol; 585 PetscReal diag,jdiag,jwttotal; 586 PetscInt pncols; 587 PetscSF sf; 588 PetscLayout clayout; 589 IS lis; 590 591 PetscFunctionBegin; 592 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRMPI(ierr); 593 ierr = MatGetOwnershipRange(A,&fs,&fe);CHKERRQ(ierr); 594 fn = fe-fs; 595 ierr = ISCreateStride(PETSC_COMM_SELF,fe-fs,fs,1,&lis);CHKERRQ(ierr); 596 if (size > 1) { 597 ierr = MatGetLayouts(A,NULL,&clayout);CHKERRQ(ierr); 598 /* increase the overlap by two to get neighbors of neighbors */ 599 ierr = MatIncreaseOverlap(A,1,&lis,2);CHKERRQ(ierr); 600 ierr = ISSort(lis);CHKERRQ(ierr); 601 /* get the local part of A */ 602 ierr = MatCreateSubMatrices(A,1,&lis,&lis,MAT_INITIAL_MATRIX,&lAs);CHKERRQ(ierr); 603 lA = lAs[0]; 604 /* build an SF out of it */ 605 ierr = ISGetLocalSize(lis,&nl);CHKERRQ(ierr); 606 ierr = PetscSFCreate(PetscObjectComm((PetscObject)A),&sf);CHKERRQ(ierr); 607 ierr = ISGetIndices(lis,&lidx);CHKERRQ(ierr); 608 ierr = PetscSFSetGraphLayout(sf,clayout,nl,NULL,PETSC_COPY_VALUES,lidx);CHKERRQ(ierr); 609 ierr = ISRestoreIndices(lis,&lidx);CHKERRQ(ierr); 610 } else { 611 lA = A; 612 nl = fn; 613 } 614 /* create a communication structure for the overlapped portion and transmit coarse indices */ 615 ierr = PetscMalloc3(fn,&lsparse,fn,&gsparse,nl,&pcontrib);CHKERRQ(ierr); 616 /* create coarse vector */ 617 cn = 0; 618 for (i=0;i<fn;i++) { 619 ierr = PetscCDEmptyAt(agg_lists,i,&iscoarse);CHKERRQ(ierr); 620 if (!iscoarse) { 621 cn++; 622 } 623 } 624 ierr = PetscMalloc1(fn,&gcid);CHKERRQ(ierr); 625 ierr = VecCreateMPI(PetscObjectComm((PetscObject)A),cn,PETSC_DECIDE,&cv);CHKERRQ(ierr); 626 ierr = VecGetOwnershipRange(cv,&cs,&ce);CHKERRQ(ierr); 627 cn = 0; 628 for (i=0;i<fn;i++) { 629 ierr = PetscCDEmptyAt(agg_lists,i,&iscoarse);CHKERRQ(ierr); 630 if (!iscoarse) { 631 gcid[i] = cs+cn; 632 cn++; 633 } else { 634 gcid[i] = -1; 635 } 636 } 637 if (size > 1) { 638 ierr = PetscMalloc1(nl,&lcid);CHKERRQ(ierr); 639 ierr = PetscSFBcastBegin(sf,MPIU_INT,gcid,lcid);CHKERRQ(ierr); 640 ierr = PetscSFBcastEnd(sf,MPIU_INT,gcid,lcid);CHKERRQ(ierr); 641 } else { 642 lcid = gcid; 643 } 644 /* count to preallocate the prolongator */ 645 ierr = ISGetIndices(lis,&gidx);CHKERRQ(ierr); 646 maxcols = 0; 647 /* count the number of unique contributing coarse cells for each fine */ 648 for (i=0;i<nl;i++) { 649 pcontrib[i] = 0.; 650 ierr = MatGetRow(lA,i,&ncols,&icol,NULL);CHKERRQ(ierr); 651 if (gidx[i] >= fs && gidx[i] < fe) { 652 li = gidx[i] - fs; 653 lsparse[li] = 0; 654 gsparse[li] = 0; 655 cid = lcid[i]; 656 if (cid >= 0) { 657 lsparse[li] = 1; 658 } else { 659 for (j=0;j<ncols;j++) { 660 if (lcid[icol[j]] >= 0) { 661 pcontrib[icol[j]] = 1.; 662 } else { 663 ci = icol[j]; 664 ierr = MatRestoreRow(lA,i,&ncols,&icol,NULL);CHKERRQ(ierr); 665 ierr = MatGetRow(lA,ci,&ncols,&icol,NULL);CHKERRQ(ierr); 666 for (k=0;k<ncols;k++) { 667 if (lcid[icol[k]] >= 0) { 668 pcontrib[icol[k]] = 1.; 669 } 670 } 671 ierr = MatRestoreRow(lA,ci,&ncols,&icol,NULL);CHKERRQ(ierr); 672 ierr = MatGetRow(lA,i,&ncols,&icol,NULL);CHKERRQ(ierr); 673 } 674 } 675 for (j=0;j<ncols;j++) { 676 if (lcid[icol[j]] >= 0 && pcontrib[icol[j]] != 0.) { 677 lni = lcid[icol[j]]; 678 if (lni >= cs && lni < ce) { 679 lsparse[li]++; 680 } else { 681 gsparse[li]++; 682 } 683 pcontrib[icol[j]] = 0.; 684 } else { 685 ci = icol[j]; 686 ierr = MatRestoreRow(lA,i,&ncols,&icol,NULL);CHKERRQ(ierr); 687 ierr = MatGetRow(lA,ci,&ncols,&icol,NULL);CHKERRQ(ierr); 688 for (k=0;k<ncols;k++) { 689 if (lcid[icol[k]] >= 0 && pcontrib[icol[k]] != 0.) { 690 lni = lcid[icol[k]]; 691 if (lni >= cs && lni < ce) { 692 lsparse[li]++; 693 } else { 694 gsparse[li]++; 695 } 696 pcontrib[icol[k]] = 0.; 697 } 698 } 699 ierr = MatRestoreRow(lA,ci,&ncols,&icol,NULL);CHKERRQ(ierr); 700 ierr = MatGetRow(lA,i,&ncols,&icol,NULL);CHKERRQ(ierr); 701 } 702 } 703 } 704 if (lsparse[li] + gsparse[li] > maxcols) maxcols = lsparse[li]+gsparse[li]; 705 } 706 ierr = MatRestoreRow(lA,i,&ncols,&icol,&vcol);CHKERRQ(ierr); 707 } 708 ierr = PetscMalloc2(maxcols,&picol,maxcols,&pvcol);CHKERRQ(ierr); 709 ierr = MatCreate(PetscObjectComm((PetscObject)A),P);CHKERRQ(ierr); 710 ierr = MatGetType(A,&mtype);CHKERRQ(ierr); 711 ierr = MatSetType(*P,mtype);CHKERRQ(ierr); 712 ierr = MatSetSizes(*P,fn,cn,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 713 ierr = MatMPIAIJSetPreallocation(*P,0,lsparse,0,gsparse);CHKERRQ(ierr); 714 ierr = MatSeqAIJSetPreallocation(*P,0,lsparse);CHKERRQ(ierr); 715 for (i=0;i<nl;i++) { 716 diag = 0.; 717 if (gidx[i] >= fs && gidx[i] < fe) { 718 pncols=0; 719 cid = lcid[i]; 720 if (cid >= 0) { 721 pncols = 1; 722 picol[0] = cid; 723 pvcol[0] = 1.; 724 } else { 725 ierr = MatGetRow(lA,i,&ncols,&icol,&vcol);CHKERRQ(ierr); 726 for (j=0;j<ncols;j++) { 727 pentry = vcol[j]; 728 if (lcid[icol[j]] >= 0) { 729 /* coarse neighbor */ 730 pcontrib[icol[j]] += pentry; 731 } else if (icol[j] != i) { 732 /* the neighbor is a strongly connected fine node */ 733 ci = icol[j]; 734 vi = vcol[j]; 735 ierr = MatRestoreRow(lA,i,&ncols,&icol,&vcol);CHKERRQ(ierr); 736 ierr = MatGetRow(lA,ci,&ncols,&icol,&vcol);CHKERRQ(ierr); 737 jwttotal=0.; 738 jdiag = 0.; 739 for (k=0;k<ncols;k++) { 740 if (ci == icol[k]) { 741 jdiag = PetscRealPart(vcol[k]); 742 } 743 } 744 for (k=0;k<ncols;k++) { 745 if (lcid[icol[k]] >= 0 && jdiag*PetscRealPart(vcol[k]) < 0.) { 746 pjentry = vcol[k]; 747 jwttotal += PetscRealPart(pjentry); 748 } 749 } 750 if (jwttotal != 0.) { 751 jwttotal = PetscRealPart(vi)/jwttotal; 752 for (k=0;k<ncols;k++) { 753 if (lcid[icol[k]] >= 0 && jdiag*PetscRealPart(vcol[k]) < 0.) { 754 pjentry = vcol[k]*jwttotal; 755 pcontrib[icol[k]] += pjentry; 756 } 757 } 758 } else { 759 diag += PetscRealPart(vi); 760 } 761 ierr = MatRestoreRow(lA,ci,&ncols,&icol,&vcol);CHKERRQ(ierr); 762 ierr = MatGetRow(lA,i,&ncols,&icol,&vcol);CHKERRQ(ierr); 763 } else { 764 diag += PetscRealPart(vcol[j]); 765 } 766 } 767 if (diag != 0.) { 768 diag = 1./diag; 769 for (j=0;j<ncols;j++) { 770 if (lcid[icol[j]] >= 0 && pcontrib[icol[j]] != 0.) { 771 /* the neighbor is a coarse node */ 772 if (PetscAbsScalar(pcontrib[icol[j]]) > 0.0) { 773 lni = lcid[icol[j]]; 774 pvcol[pncols] = -pcontrib[icol[j]]*diag; 775 picol[pncols] = lni; 776 pncols++; 777 } 778 pcontrib[icol[j]] = 0.; 779 } else { 780 /* the neighbor is a strongly connected fine node */ 781 ci = icol[j]; 782 ierr = MatRestoreRow(lA,i,&ncols,&icol,&vcol);CHKERRQ(ierr); 783 ierr = MatGetRow(lA,ci,&ncols,&icol,&vcol);CHKERRQ(ierr); 784 for (k=0;k<ncols;k++) { 785 if (lcid[icol[k]] >= 0 && pcontrib[icol[k]] != 0.) { 786 if (PetscAbsScalar(pcontrib[icol[k]]) > 0.0) { 787 lni = lcid[icol[k]]; 788 pvcol[pncols] = -pcontrib[icol[k]]*diag; 789 picol[pncols] = lni; 790 pncols++; 791 } 792 pcontrib[icol[k]] = 0.; 793 } 794 } 795 ierr = MatRestoreRow(lA,ci,&ncols,&icol,&vcol);CHKERRQ(ierr); 796 ierr = MatGetRow(lA,i,&ncols,&icol,&vcol);CHKERRQ(ierr); 797 } 798 pcontrib[icol[j]] = 0.; 799 } 800 ierr = MatRestoreRow(lA,i,&ncols,&icol,&vcol);CHKERRQ(ierr); 801 } 802 } 803 ci = gidx[i]; 804 if (pncols > 0) { 805 ierr = MatSetValues(*P,1,&ci,pncols,picol,pvcol,INSERT_VALUES);CHKERRQ(ierr); 806 } 807 } 808 } 809 ierr = ISRestoreIndices(lis,&gidx);CHKERRQ(ierr); 810 ierr = PetscFree2(picol,pvcol);CHKERRQ(ierr); 811 ierr = PetscFree3(lsparse,gsparse,pcontrib);CHKERRQ(ierr); 812 ierr = ISDestroy(&lis);CHKERRQ(ierr); 813 ierr = PetscFree(gcid);CHKERRQ(ierr); 814 if (size > 1) { 815 ierr = PetscFree(lcid);CHKERRQ(ierr); 816 ierr = MatDestroyMatrices(1,&lAs);CHKERRQ(ierr); 817 ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 818 } 819 ierr = VecDestroy(&cv);CHKERRQ(ierr); 820 ierr = MatAssemblyBegin(*P, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 821 ierr = MatAssemblyEnd(*P, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 822 PetscFunctionReturn(0); 823 } 824 825 PetscErrorCode PCGAMGOptProlongator_Classical_Jacobi(PC pc,Mat A,Mat *P) 826 { 827 828 PetscErrorCode ierr; 829 PetscInt f,s,n,cf,cs,i,idx; 830 PetscInt *coarserows; 831 PetscInt ncols; 832 const PetscInt *pcols; 833 const PetscScalar *pvals; 834 Mat Pnew; 835 Vec diag; 836 PC_MG *mg = (PC_MG*)pc->data; 837 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 838 PC_GAMG_Classical *cls = (PC_GAMG_Classical*)pc_gamg->subctx; 839 840 PetscFunctionBegin; 841 if (cls->nsmooths == 0) { 842 ierr = PCGAMGTruncateProlongator_Private(pc,P);CHKERRQ(ierr); 843 PetscFunctionReturn(0); 844 } 845 ierr = MatGetOwnershipRange(*P,&s,&f);CHKERRQ(ierr); 846 n = f-s; 847 ierr = MatGetOwnershipRangeColumn(*P,&cs,&cf);CHKERRQ(ierr); 848 ierr = PetscMalloc1(n,&coarserows);CHKERRQ(ierr); 849 /* identify the rows corresponding to coarse unknowns */ 850 idx = 0; 851 for (i=s;i<f;i++) { 852 ierr = MatGetRow(*P,i,&ncols,&pcols,&pvals);CHKERRQ(ierr); 853 /* assume, for now, that it's a coarse unknown if it has a single unit entry */ 854 if (ncols == 1) { 855 if (pvals[0] == 1.) { 856 coarserows[idx] = i; 857 idx++; 858 } 859 } 860 ierr = MatRestoreRow(*P,i,&ncols,&pcols,&pvals);CHKERRQ(ierr); 861 } 862 ierr = MatCreateVecs(A,&diag,NULL);CHKERRQ(ierr); 863 ierr = MatGetDiagonal(A,diag);CHKERRQ(ierr); 864 ierr = VecReciprocal(diag);CHKERRQ(ierr); 865 for (i=0;i<cls->nsmooths;i++) { 866 ierr = MatMatMult(A,*P,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&Pnew);CHKERRQ(ierr); 867 ierr = MatZeroRows(Pnew,idx,coarserows,0.,NULL,NULL);CHKERRQ(ierr); 868 ierr = MatDiagonalScale(Pnew,diag,NULL);CHKERRQ(ierr); 869 ierr = MatAYPX(Pnew,-1.0,*P,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 870 ierr = MatDestroy(P);CHKERRQ(ierr); 871 *P = Pnew; 872 Pnew = NULL; 873 } 874 ierr = VecDestroy(&diag);CHKERRQ(ierr); 875 ierr = PetscFree(coarserows);CHKERRQ(ierr); 876 ierr = PCGAMGTruncateProlongator_Private(pc,P);CHKERRQ(ierr); 877 PetscFunctionReturn(0); 878 } 879 880 PetscErrorCode PCGAMGProlongator_Classical(PC pc, Mat A, Mat G, PetscCoarsenData *agg_lists,Mat *P) 881 { 882 PetscErrorCode ierr; 883 PetscErrorCode (*f)(PC,Mat,Mat,PetscCoarsenData*,Mat*); 884 PC_MG *mg = (PC_MG*)pc->data; 885 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 886 PC_GAMG_Classical *cls = (PC_GAMG_Classical*)pc_gamg->subctx; 887 888 PetscFunctionBegin; 889 ierr = PetscFunctionListFind(PCGAMGClassicalProlongatorList,cls->prolongtype,&f);CHKERRQ(ierr); 890 if (!f)SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Cannot find PCGAMG Classical prolongator type"); 891 ierr = (*f)(pc,A,G,agg_lists,P);CHKERRQ(ierr); 892 PetscFunctionReturn(0); 893 } 894 895 PetscErrorCode PCGAMGDestroy_Classical(PC pc) 896 { 897 PetscErrorCode ierr; 898 PC_MG *mg = (PC_MG*)pc->data; 899 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 900 901 PetscFunctionBegin; 902 ierr = PetscFree(pc_gamg->subctx);CHKERRQ(ierr); 903 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCGAMGClassicalSetType_C",NULL);CHKERRQ(ierr); 904 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCGAMGClassicalGetType_C",NULL);CHKERRQ(ierr); 905 PetscFunctionReturn(0); 906 } 907 908 PetscErrorCode PCGAMGSetFromOptions_Classical(PetscOptionItems *PetscOptionsObject,PC pc) 909 { 910 PC_MG *mg = (PC_MG*)pc->data; 911 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 912 PC_GAMG_Classical *cls = (PC_GAMG_Classical*)pc_gamg->subctx; 913 char tname[256]; 914 PetscErrorCode ierr; 915 PetscBool flg; 916 917 PetscFunctionBegin; 918 ierr = PetscOptionsHead(PetscOptionsObject,"GAMG-Classical options");CHKERRQ(ierr); 919 ierr = PetscOptionsFList("-pc_gamg_classical_type","Type of Classical AMG prolongation","PCGAMGClassicalSetType",PCGAMGClassicalProlongatorList,cls->prolongtype, tname, sizeof(tname), &flg);CHKERRQ(ierr); 920 if (flg) { 921 ierr = PCGAMGClassicalSetType(pc,tname);CHKERRQ(ierr); 922 } 923 ierr = PetscOptionsReal("-pc_gamg_classical_interp_threshold","Threshold for classical interpolator entries","",cls->interp_threshold,&cls->interp_threshold,NULL);CHKERRQ(ierr); 924 ierr = PetscOptionsInt("-pc_gamg_classical_nsmooths","Threshold for classical interpolator entries","",cls->nsmooths,&cls->nsmooths,NULL);CHKERRQ(ierr); 925 ierr = PetscOptionsTail();CHKERRQ(ierr); 926 PetscFunctionReturn(0); 927 } 928 929 PetscErrorCode PCGAMGSetData_Classical(PC pc, Mat A) 930 { 931 PC_MG *mg = (PC_MG*)pc->data; 932 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 933 934 PetscFunctionBegin; 935 /* no data for classical AMG */ 936 pc_gamg->data = NULL; 937 pc_gamg->data_cell_cols = 0; 938 pc_gamg->data_cell_rows = 0; 939 pc_gamg->data_sz = 0; 940 PetscFunctionReturn(0); 941 } 942 943 944 PetscErrorCode PCGAMGClassicalFinalizePackage(void) 945 { 946 PetscErrorCode ierr; 947 948 PetscFunctionBegin; 949 PCGAMGClassicalPackageInitialized = PETSC_FALSE; 950 ierr = PetscFunctionListDestroy(&PCGAMGClassicalProlongatorList);CHKERRQ(ierr); 951 PetscFunctionReturn(0); 952 } 953 954 PetscErrorCode PCGAMGClassicalInitializePackage(void) 955 { 956 PetscErrorCode ierr; 957 958 PetscFunctionBegin; 959 if (PCGAMGClassicalPackageInitialized) PetscFunctionReturn(0); 960 ierr = PetscFunctionListAdd(&PCGAMGClassicalProlongatorList,PCGAMGCLASSICALDIRECT,PCGAMGProlongator_Classical_Direct);CHKERRQ(ierr); 961 ierr = PetscFunctionListAdd(&PCGAMGClassicalProlongatorList,PCGAMGCLASSICALSTANDARD,PCGAMGProlongator_Classical_Standard);CHKERRQ(ierr); 962 ierr = PetscRegisterFinalize(PCGAMGClassicalFinalizePackage);CHKERRQ(ierr); 963 PetscFunctionReturn(0); 964 } 965 966 /* -------------------------------------------------------------------------- */ 967 /* 968 PCCreateGAMG_Classical 969 970 */ 971 PetscErrorCode PCCreateGAMG_Classical(PC pc) 972 { 973 PetscErrorCode ierr; 974 PC_MG *mg = (PC_MG*)pc->data; 975 PC_GAMG *pc_gamg = (PC_GAMG*)mg->innerctx; 976 PC_GAMG_Classical *pc_gamg_classical; 977 978 PetscFunctionBegin; 979 ierr = PCGAMGClassicalInitializePackage();CHKERRQ(ierr); 980 if (pc_gamg->subctx) { 981 /* call base class */ 982 ierr = PCDestroy_GAMG(pc);CHKERRQ(ierr); 983 } 984 985 /* create sub context for SA */ 986 ierr = PetscNewLog(pc,&pc_gamg_classical);CHKERRQ(ierr); 987 pc_gamg->subctx = pc_gamg_classical; 988 pc->ops->setfromoptions = PCGAMGSetFromOptions_Classical; 989 /* reset does not do anything; setup not virtual */ 990 991 /* set internal function pointers */ 992 pc_gamg->ops->destroy = PCGAMGDestroy_Classical; 993 pc_gamg->ops->graph = PCGAMGGraph_Classical; 994 pc_gamg->ops->coarsen = PCGAMGCoarsen_Classical; 995 pc_gamg->ops->prolongator = PCGAMGProlongator_Classical; 996 pc_gamg->ops->optprolongator = PCGAMGOptProlongator_Classical_Jacobi; 997 pc_gamg->ops->setfromoptions = PCGAMGSetFromOptions_Classical; 998 999 pc_gamg->ops->createdefaultdata = PCGAMGSetData_Classical; 1000 pc_gamg_classical->interp_threshold = 0.2; 1001 pc_gamg_classical->nsmooths = 0; 1002 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCGAMGClassicalSetType_C",PCGAMGClassicalSetType_GAMG);CHKERRQ(ierr); 1003 ierr = PetscObjectComposeFunction((PetscObject)pc,"PCGAMGClassicalGetType_C",PCGAMGClassicalGetType_GAMG);CHKERRQ(ierr); 1004 ierr = PCGAMGClassicalSetType(pc,PCGAMGCLASSICALSTANDARD);CHKERRQ(ierr); 1005 PetscFunctionReturn(0); 1006 } 1007