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