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