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