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