1 2 /* 3 Provides an interface to the LLNL package hypre 4 */ 5 6 /* Must use hypre 2.0.0 or more recent. */ 7 8 #include <private/pcimpl.h> /*I "petscpc.h" I*/ 9 #include <../src/dm/impls/da/hypre/mhyp.h> 10 11 /* 12 Private context (data structure) for the preconditioner. 13 */ 14 typedef struct { 15 HYPRE_Solver hsolver; 16 HYPRE_IJMatrix ij; 17 HYPRE_IJVector b,x; 18 19 PetscErrorCode (*destroy)(HYPRE_Solver); 20 PetscErrorCode (*solve)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector); 21 PetscErrorCode (*setup)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector); 22 23 MPI_Comm comm_hypre; 24 char *hypre_type; 25 26 /* options for Pilut and BoomerAMG*/ 27 int maxiter; 28 double tol; 29 30 /* options for Pilut */ 31 int factorrowsize; 32 33 /* options for ParaSails */ 34 int nlevels; 35 double threshhold; 36 double filter; 37 int sym; 38 double loadbal; 39 int logging; 40 int ruse; 41 int symt; 42 43 /* options for Euclid */ 44 PetscBool bjilu; 45 int levels; 46 47 /* options for Euclid and BoomerAMG */ 48 PetscBool printstatistics; 49 50 /* options for BoomerAMG */ 51 int cycletype; 52 int maxlevels; 53 double strongthreshold; 54 double maxrowsum; 55 int gridsweeps[3]; 56 int coarsentype; 57 int measuretype; 58 int relaxtype[3]; 59 double relaxweight; 60 double outerrelaxweight; 61 int relaxorder; 62 double truncfactor; 63 PetscBool applyrichardson; 64 int pmax; 65 int interptype; 66 int agg_nl; 67 int agg_num_paths; 68 int nodal_coarsen; 69 PetscBool nodal_relax; 70 int nodal_relax_levels; 71 } PC_HYPRE; 72 73 74 #undef __FUNCT__ 75 #define __FUNCT__ "PCSetUp_HYPRE" 76 static PetscErrorCode PCSetUp_HYPRE(PC pc) 77 { 78 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 79 PetscErrorCode ierr; 80 HYPRE_ParCSRMatrix hmat; 81 HYPRE_ParVector bv,xv; 82 PetscInt bs; 83 84 PetscFunctionBegin; 85 if (!jac->hypre_type) { 86 ierr = PCHYPRESetType(pc,"boomeramg");CHKERRQ(ierr); 87 } 88 89 if (pc->setupcalled) { 90 /* always destroy the old matrix and create a new memory; 91 hope this does not churn the memory too much. The problem 92 is I do not know if it is possible to put the matrix back to 93 its initial state so that we can directly copy the values 94 the second time through. */ 95 PetscStackCallHypre(0,HYPRE_IJMatrixDestroy,(jac->ij)); 96 jac->ij = 0; 97 } 98 99 if (!jac->ij) { /* create the matrix the first time through */ 100 ierr = MatHYPRE_IJMatrixCreate(pc->pmat,&jac->ij);CHKERRQ(ierr); 101 } 102 if (!jac->b) { /* create the vectors the first time through */ 103 Vec x,b; 104 ierr = MatGetVecs(pc->pmat,&x,&b);CHKERRQ(ierr); 105 ierr = VecHYPRE_IJVectorCreate(x,&jac->x);CHKERRQ(ierr); 106 ierr = VecHYPRE_IJVectorCreate(b,&jac->b);CHKERRQ(ierr); 107 ierr = VecDestroy(&x);CHKERRQ(ierr); 108 ierr = VecDestroy(&b);CHKERRQ(ierr); 109 } 110 111 /* special case for BoomerAMG */ 112 if (jac->setup == HYPRE_BoomerAMGSetup) { 113 ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr); 114 if (bs > 1) { 115 PetscStackCallHypre(0,HYPRE_BoomerAMGSetNumFunctions,(jac->hsolver,bs)); 116 } 117 }; 118 ierr = MatHYPRE_IJMatrixCopy(pc->pmat,jac->ij);CHKERRQ(ierr); 119 PetscStackCallHypre(0,HYPRE_IJMatrixGetObject,(jac->ij,(void**)&hmat)); 120 PetscStackCallHypre(0,HYPRE_IJVectorGetObject,(jac->b,(void**)&bv)); 121 PetscStackCallHypre(0,HYPRE_IJVectorGetObject,(jac->x,(void**)&xv)); 122 PetscStackCallHypre("HYPRE_SetupXXX",(*jac->setup),(jac->hsolver,hmat,bv,xv)); 123 PetscFunctionReturn(0); 124 } 125 126 /* 127 Replaces the address where the HYPRE vector points to its data with the address of 128 PETSc's data. Saves the old address so it can be reset when we are finished with it. 129 Allows use to get the data into a HYPRE vector without the cost of memcopies 130 */ 131 #define HYPREReplacePointer(b,newvalue,savedvalue) {\ 132 hypre_ParVector *par_vector = (hypre_ParVector *)hypre_IJVectorObject(((hypre_IJVector*)b));\ 133 hypre_Vector *local_vector = hypre_ParVectorLocalVector(par_vector);\ 134 savedvalue = local_vector->data;\ 135 local_vector->data = newvalue;} 136 137 #undef __FUNCT__ 138 #define __FUNCT__ "PCApply_HYPRE" 139 static PetscErrorCode PCApply_HYPRE(PC pc,Vec b,Vec x) 140 { 141 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 142 PetscErrorCode ierr; 143 HYPRE_ParCSRMatrix hmat; 144 PetscScalar *bv,*xv; 145 HYPRE_ParVector jbv,jxv; 146 PetscScalar *sbv,*sxv; 147 int hierr; 148 149 PetscFunctionBegin; 150 if (!jac->applyrichardson) {ierr = VecSet(x,0.0);CHKERRQ(ierr);} 151 ierr = VecGetArray(b,&bv);CHKERRQ(ierr); 152 ierr = VecGetArray(x,&xv);CHKERRQ(ierr); 153 HYPREReplacePointer(jac->b,bv,sbv); 154 HYPREReplacePointer(jac->x,xv,sxv); 155 156 PetscStackCallHypre(0,HYPRE_IJMatrixGetObject,(jac->ij,(void**)&hmat)); 157 PetscStackCallHypre(0,HYPRE_IJVectorGetObject,(jac->b,(void**)&jbv)); 158 PetscStackCallHypre(0,HYPRE_IJVectorGetObject,(jac->x,(void**)&jxv)); 159 hierr = (*jac->solve)(jac->hsolver,hmat,jbv,jxv); 160 if (hierr && hierr != HYPRE_ERROR_CONV) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",hierr); 161 if (hierr) hypre__global_error = 0; 162 163 HYPREReplacePointer(jac->b,sbv,bv); 164 HYPREReplacePointer(jac->x,sxv,xv); 165 ierr = VecRestoreArray(x,&xv);CHKERRQ(ierr); 166 ierr = VecRestoreArray(b,&bv);CHKERRQ(ierr); 167 PetscFunctionReturn(0); 168 } 169 170 #undef __FUNCT__ 171 #define __FUNCT__ "PCDestroy_HYPRE" 172 static PetscErrorCode PCDestroy_HYPRE(PC pc) 173 { 174 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 175 PetscErrorCode ierr; 176 177 PetscFunctionBegin; 178 if (jac->ij) PetscStackCallHypre(0,HYPRE_IJMatrixDestroy,(jac->ij)); 179 if (jac->b) PetscStackCallHypre(0,HYPRE_IJVectorDestroy,(jac->b)); 180 if (jac->x) PetscStackCallHypre(0,HYPRE_IJVectorDestroy,(jac->x)); 181 if (jac->destroy) PetscStackCallHypre("HYPRE_DistroyXXX",(*jac->destroy),(jac->hsolver)); 182 ierr = PetscFree(jac->hypre_type);CHKERRQ(ierr); 183 if (jac->comm_hypre != MPI_COMM_NULL) { ierr = MPI_Comm_free(&(jac->comm_hypre));CHKERRQ(ierr);} 184 ierr = PetscFree(pc->data);CHKERRQ(ierr); 185 186 ierr = PetscObjectChangeTypeName((PetscObject)pc,0);CHKERRQ(ierr); 187 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPRESetType_C","",PETSC_NULL);CHKERRQ(ierr); 188 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPREGetType_C","",PETSC_NULL);CHKERRQ(ierr); 189 PetscFunctionReturn(0); 190 } 191 192 /* --------------------------------------------------------------------------------------------*/ 193 #undef __FUNCT__ 194 #define __FUNCT__ "PCSetFromOptions_HYPRE_Pilut" 195 static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc) 196 { 197 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 198 PetscErrorCode ierr; 199 PetscBool flag; 200 201 PetscFunctionBegin; 202 ierr = PetscOptionsHead("HYPRE Pilut Options");CHKERRQ(ierr); 203 ierr = PetscOptionsInt("-pc_hypre_pilut_maxiter","Number of iterations","None",jac->maxiter,&jac->maxiter,&flag);CHKERRQ(ierr); 204 if (flag) PetscStackCallHypre(0,HYPRE_ParCSRPilutSetMaxIter,(jac->hsolver,jac->maxiter)); 205 ierr = PetscOptionsReal("-pc_hypre_pilut_tol","Drop tolerance","None",jac->tol,&jac->tol,&flag);CHKERRQ(ierr); 206 if (flag) PetscStackCallHypre(0,HYPRE_ParCSRPilutSetDropTolerance,(jac->hsolver,jac->tol)); 207 ierr = PetscOptionsInt("-pc_hypre_pilut_factorrowsize","FactorRowSize","None",jac->factorrowsize,&jac->factorrowsize,&flag);CHKERRQ(ierr); 208 if (flag) PetscStackCallHypre(0,HYPRE_ParCSRPilutSetFactorRowSize,(jac->hsolver,jac->factorrowsize)); 209 ierr = PetscOptionsTail();CHKERRQ(ierr); 210 PetscFunctionReturn(0); 211 } 212 213 #undef __FUNCT__ 214 #define __FUNCT__ "PCView_HYPRE_Pilut" 215 static PetscErrorCode PCView_HYPRE_Pilut(PC pc,PetscViewer viewer) 216 { 217 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 218 PetscErrorCode ierr; 219 PetscBool iascii; 220 221 PetscFunctionBegin; 222 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 223 if (iascii) { 224 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut preconditioning\n");CHKERRQ(ierr); 225 if (jac->maxiter != PETSC_DEFAULT) { 226 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: maximum number of iterations %d\n",jac->maxiter);CHKERRQ(ierr); 227 } else { 228 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: default maximum number of iterations \n");CHKERRQ(ierr); 229 } 230 if (jac->tol != PETSC_DEFAULT) { 231 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: drop tolerance %G\n",jac->tol);CHKERRQ(ierr); 232 } else { 233 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: default drop tolerance \n");CHKERRQ(ierr); 234 } 235 if (jac->factorrowsize != PETSC_DEFAULT) { 236 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: factor row size %d\n",jac->factorrowsize);CHKERRQ(ierr); 237 } else { 238 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: default factor row size \n");CHKERRQ(ierr); 239 } 240 } 241 PetscFunctionReturn(0); 242 } 243 244 /* --------------------------------------------------------------------------------------------*/ 245 #undef __FUNCT__ 246 #define __FUNCT__ "PCSetFromOptions_HYPRE_Euclid" 247 static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc) 248 { 249 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 250 PetscErrorCode ierr; 251 PetscBool flag; 252 char *args[8],levels[16]; 253 PetscInt cnt = 0; 254 255 PetscFunctionBegin; 256 ierr = PetscOptionsHead("HYPRE Euclid Options");CHKERRQ(ierr); 257 ierr = PetscOptionsInt("-pc_hypre_euclid_levels","Number of levels of fill ILU(k)","None",jac->levels,&jac->levels,&flag);CHKERRQ(ierr); 258 if (flag) { 259 if (jac->levels < 0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %d must be nonegative",jac->levels); 260 sprintf(levels,"%d",jac->levels); 261 args[cnt++] = (char*)"-level"; args[cnt++] = levels; 262 } 263 ierr = PetscOptionsBool("-pc_hypre_euclid_bj","Use block Jacobi ILU(k)","None",jac->bjilu,&jac->bjilu,PETSC_NULL);CHKERRQ(ierr); 264 if (jac->bjilu) { 265 args[cnt++] =(char*) "-bj"; args[cnt++] = (char*)"1"; 266 } 267 268 ierr = PetscOptionsBool("-pc_hypre_euclid_print_statistics","Print statistics","None",jac->printstatistics,&jac->printstatistics,PETSC_NULL);CHKERRQ(ierr); 269 if (jac->printstatistics) { 270 args[cnt++] = (char*)"-eu_stats"; args[cnt++] = (char*)"1"; 271 args[cnt++] = (char*)"-eu_mem"; args[cnt++] = (char*)"1"; 272 } 273 ierr = PetscOptionsTail();CHKERRQ(ierr); 274 if (cnt) PetscStackCallHypre(0,HYPRE_EuclidSetParams,(jac->hsolver,cnt,args)); 275 PetscFunctionReturn(0); 276 } 277 278 #undef __FUNCT__ 279 #define __FUNCT__ "PCView_HYPRE_Euclid" 280 static PetscErrorCode PCView_HYPRE_Euclid(PC pc,PetscViewer viewer) 281 { 282 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 283 PetscErrorCode ierr; 284 PetscBool iascii; 285 286 PetscFunctionBegin; 287 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 288 if (iascii) { 289 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Euclid preconditioning\n");CHKERRQ(ierr); 290 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Euclid: number of levels %d\n",jac->levels);CHKERRQ(ierr); 291 if (jac->bjilu) { 292 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Euclid: Using block Jacobi ILU instead of parallel ILU\n");CHKERRQ(ierr); 293 } 294 } 295 PetscFunctionReturn(0); 296 } 297 298 /* --------------------------------------------------------------------------------------------*/ 299 300 #undef __FUNCT__ 301 #define __FUNCT__ "PCApplyTranspose_HYPRE_BoomerAMG" 302 static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc,Vec b,Vec x) 303 { 304 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 305 PetscErrorCode ierr; 306 HYPRE_ParCSRMatrix hmat; 307 PetscScalar *bv,*xv; 308 HYPRE_ParVector jbv,jxv; 309 PetscScalar *sbv,*sxv; 310 int hierr; 311 312 PetscFunctionBegin; 313 ierr = VecSet(x,0.0);CHKERRQ(ierr); 314 ierr = VecGetArray(b,&bv);CHKERRQ(ierr); 315 ierr = VecGetArray(x,&xv);CHKERRQ(ierr); 316 HYPREReplacePointer(jac->b,bv,sbv); 317 HYPREReplacePointer(jac->x,xv,sxv); 318 319 PetscStackCallHypre(0,HYPRE_IJMatrixGetObject,(jac->ij,(void**)&hmat)); 320 PetscStackCallHypre(0,HYPRE_IJVectorGetObject,(jac->b,(void**)&jbv)); 321 PetscStackCallHypre(0,HYPRE_IJVectorGetObject,(jac->x,(void**)&jxv)); 322 323 hierr = HYPRE_BoomerAMGSolveT(jac->hsolver,hmat,jbv,jxv); 324 /* error code of 1 in BoomerAMG merely means convergence not achieved */ 325 if (hierr && (hierr != 1)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",hierr); 326 if (hierr) hypre__global_error = 0; 327 328 HYPREReplacePointer(jac->b,sbv,bv); 329 HYPREReplacePointer(jac->x,sxv,xv); 330 ierr = VecRestoreArray(x,&xv);CHKERRQ(ierr); 331 ierr = VecRestoreArray(b,&bv);CHKERRQ(ierr); 332 PetscFunctionReturn(0); 333 } 334 335 static const char *HYPREBoomerAMGCycleType[] = {"","V","W"}; 336 static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP","Ruge-Stueben","","modifiedRuge-Stueben","","","Falgout", "", "PMIS", "", "HMIS"}; 337 static const char *HYPREBoomerAMGMeasureType[] = {"local","global"}; 338 static const char *HYPREBoomerAMGRelaxType[] = {"Jacobi","sequential-Gauss-Seidel","","SOR/Jacobi","backward-SOR/Jacobi","","symmetric-SOR/Jacobi", 339 "","","Gaussian-elimination"}; 340 static const char *HYPREBoomerAMGInterpType[] = {"classical", "", "", "direct", "multipass", "multipass-wts", "ext+i", 341 "ext+i-cc", "standard", "standard-wts", "", "", "FF", "FF1"}; 342 #undef __FUNCT__ 343 #define __FUNCT__ "PCSetFromOptions_HYPRE_BoomerAMG" 344 static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc) 345 { 346 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 347 PetscErrorCode ierr; 348 int n,indx,level; 349 PetscBool flg, tmp_truth; 350 double tmpdbl, twodbl[2]; 351 352 PetscFunctionBegin; 353 ierr = PetscOptionsHead("HYPRE BoomerAMG Options");CHKERRQ(ierr); 354 ierr = PetscOptionsEList("-pc_hypre_boomeramg_cycle_type","Cycle type","None",HYPREBoomerAMGCycleType+1,2,HYPREBoomerAMGCycleType[jac->cycletype],&indx,&flg);CHKERRQ(ierr); 355 if (flg) { 356 jac->cycletype = indx+1; 357 PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleType,(jac->hsolver,jac->cycletype)); 358 } 359 ierr = PetscOptionsInt("-pc_hypre_boomeramg_max_levels","Number of levels (of grids) allowed","None",jac->maxlevels,&jac->maxlevels,&flg);CHKERRQ(ierr); 360 if (flg) { 361 if (jac->maxlevels < 2) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %d must be at least two",jac->maxlevels); 362 PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxLevels,(jac->hsolver,jac->maxlevels)); 363 } 364 ierr = PetscOptionsInt("-pc_hypre_boomeramg_max_iter","Maximum iterations used PER hypre call","None",jac->maxiter,&jac->maxiter,&flg);CHKERRQ(ierr); 365 if (flg) { 366 if (jac->maxiter < 1) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of iterations %d must be at least one",jac->maxiter); 367 PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,jac->maxiter)); 368 } 369 ierr = PetscOptionsScalar("-pc_hypre_boomeramg_tol","Convergence tolerance PER hypre call (0.0 = use a fixed number of iterations)","None",jac->tol,&jac->tol,&flg);CHKERRQ(ierr); 370 if (flg) { 371 if (jac->tol < 0.0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Tolerance %G must be greater than or equal to zero",jac->tol); 372 PetscStackCallHypre(0,HYPRE_BoomerAMGSetTol,(jac->hsolver,jac->tol)); 373 } 374 375 ierr = PetscOptionsScalar("-pc_hypre_boomeramg_truncfactor","Truncation factor for interpolation (0=no truncation)","None",jac->truncfactor,&jac->truncfactor,&flg);CHKERRQ(ierr); 376 if (flg) { 377 if (jac->truncfactor < 0.0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Truncation factor %G must be great than or equal zero",jac->truncfactor); 378 PetscStackCallHypre(0,HYPRE_BoomerAMGSetTruncFactor,(jac->hsolver,jac->truncfactor)); 379 } 380 381 ierr = PetscOptionsInt("-pc_hypre_boomeramg_P_max","Max elements per row for interpolation operator ( 0=unlimited )","None",jac->pmax,&jac->pmax,&flg);CHKERRQ(ierr); 382 if (flg) { 383 if (jac->pmax < 0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"P_max %G must be greater than or equal to zero",jac->pmax); 384 PetscStackCallHypre(0,HYPRE_BoomerAMGSetPMaxElmts,(jac->hsolver,jac->pmax)); 385 } 386 387 ierr = PetscOptionsInt("-pc_hypre_boomeramg_agg_nl","Number of levels of aggressive coarsening","None",jac->agg_nl,&jac->agg_nl,&flg);CHKERRQ(ierr); 388 if (flg) { 389 if (jac->agg_nl < 0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %G must be greater than or equal to zero",jac->agg_nl); 390 391 PetscStackCallHypre(0,HYPRE_BoomerAMGSetAggNumLevels,(jac->hsolver,jac->agg_nl)); 392 } 393 394 395 ierr = PetscOptionsInt("-pc_hypre_boomeramg_agg_num_paths","Number of paths for aggressive coarsening","None",jac->agg_num_paths,&jac->agg_num_paths,&flg);CHKERRQ(ierr); 396 if (flg) { 397 if (jac->agg_num_paths < 1) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Number of paths %G must be greater than or equal to 1",jac->agg_num_paths); 398 399 PetscStackCallHypre(0,HYPRE_BoomerAMGSetNumPaths,(jac->hsolver,jac->agg_num_paths)); 400 } 401 402 403 ierr = PetscOptionsScalar("-pc_hypre_boomeramg_strong_threshold","Threshold for being strongly connected","None",jac->strongthreshold,&jac->strongthreshold,&flg);CHKERRQ(ierr); 404 if (flg) { 405 if (jac->strongthreshold < 0.0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Strong threshold %G must be great than or equal zero",jac->strongthreshold); 406 PetscStackCallHypre(0,HYPRE_BoomerAMGSetStrongThreshold,(jac->hsolver,jac->strongthreshold)); 407 } 408 ierr = PetscOptionsScalar("-pc_hypre_boomeramg_max_row_sum","Maximum row sum","None",jac->maxrowsum,&jac->maxrowsum,&flg);CHKERRQ(ierr); 409 if (flg) { 410 if (jac->maxrowsum < 0.0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Maximum row sum %G must be greater than zero",jac->maxrowsum); 411 if (jac->maxrowsum > 1.0) SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Maximum row sum %G must be less than or equal one",jac->maxrowsum); 412 PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxRowSum,(jac->hsolver,jac->maxrowsum)); 413 } 414 415 /* Grid sweeps */ 416 ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_all","Number of sweeps for the up and down grid levels","None",jac->gridsweeps[0],&indx,&flg);CHKERRQ(ierr); 417 if (flg) { 418 PetscStackCallHypre(0,HYPRE_BoomerAMGSetNumSweeps,(jac->hsolver,indx)); 419 /* modify the jac structure so we can view the updated options with PC_View */ 420 jac->gridsweeps[0] = indx; 421 jac->gridsweeps[1] = indx; 422 /*defaults coarse to 1 */ 423 jac->gridsweeps[2] = 1; 424 } 425 426 ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down","Number of sweeps for the down cycles","None",jac->gridsweeps[0], &indx ,&flg);CHKERRQ(ierr); 427 if (flg) { 428 PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleNumSweeps,(jac->hsolver,indx, 1)); 429 jac->gridsweeps[0] = indx; 430 } 431 ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up","Number of sweeps for the up cycles","None",jac->gridsweeps[1],&indx,&flg);CHKERRQ(ierr); 432 if (flg) { 433 PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleNumSweeps,(jac->hsolver,indx, 2)); 434 jac->gridsweeps[1] = indx; 435 } 436 ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse","Number of sweeps for the coarse level","None",jac->gridsweeps[2],&indx,&flg);CHKERRQ(ierr); 437 if (flg) { 438 PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleNumSweeps,(jac->hsolver,indx, 3)); 439 jac->gridsweeps[2] = indx; 440 } 441 442 /* Relax type */ 443 ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_all","Relax type for the up and down cycles","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[6],&indx,&flg);CHKERRQ(ierr); 444 if (flg) { 445 jac->relaxtype[0] = jac->relaxtype[1] = indx; 446 PetscStackCallHypre(0,HYPRE_BoomerAMGSetRelaxType,(jac->hsolver, indx)); 447 /* by default, coarse type set to 9 */ 448 jac->relaxtype[2] = 9; 449 450 } 451 ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_down","Relax type for the down cycles","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[6],&indx,&flg);CHKERRQ(ierr); 452 if (flg) { 453 jac->relaxtype[0] = indx; 454 PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleRelaxType,(jac->hsolver, indx, 1)); 455 } 456 ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_up","Relax type for the up cycles","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[6],&indx,&flg);CHKERRQ(ierr); 457 if (flg) { 458 jac->relaxtype[1] = indx; 459 PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleRelaxType,(jac->hsolver, indx, 2)); 460 } 461 ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_coarse","Relax type on coarse grid","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[9],&indx,&flg);CHKERRQ(ierr); 462 if (flg) { 463 jac->relaxtype[2] = indx; 464 PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleRelaxType,(jac->hsolver, indx, 3)); 465 } 466 467 /* Relaxation Weight */ 468 ierr = PetscOptionsReal("-pc_hypre_boomeramg_relax_weight_all","Relaxation weight for all levels (0 = hypre estimates, -k = determined with k CG steps)","None",jac->relaxweight, &tmpdbl ,&flg);CHKERRQ(ierr); 469 if (flg) { 470 PetscStackCallHypre(0,HYPRE_BoomerAMGSetRelaxWt,(jac->hsolver,tmpdbl)); 471 jac->relaxweight = tmpdbl; 472 } 473 474 n=2; 475 twodbl[0] = twodbl[1] = 1.0; 476 ierr = PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level","Set the relaxation weight for a particular level (weight,level)","None",twodbl, &n, &flg);CHKERRQ(ierr); 477 if (flg) { 478 if (n == 2) { 479 indx = (int)PetscAbsReal(twodbl[1]); 480 PetscStackCallHypre(0,HYPRE_BoomerAMGSetLevelRelaxWt,(jac->hsolver,twodbl[0],indx)); 481 } else { 482 SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Relax weight level: you must provide 2 values separated by a comma (and no space), you provided %d",n); 483 } 484 } 485 486 /* Outer relaxation Weight */ 487 ierr = PetscOptionsReal("-pc_hypre_boomeramg_outer_relax_weight_all","Outer relaxation weight for all levels ( -k = determined with k CG steps)","None",jac->outerrelaxweight, &tmpdbl ,&flg);CHKERRQ(ierr); 488 if (flg) { 489 PetscStackCallHypre(0,HYPRE_BoomerAMGSetOuterWt,( jac->hsolver, tmpdbl)); 490 jac->outerrelaxweight = tmpdbl; 491 } 492 493 n=2; 494 twodbl[0] = twodbl[1] = 1.0; 495 ierr = PetscOptionsRealArray("-pc_hypre_boomeramg_outer_relax_weight_level","Set the outer relaxation weight for a particular level (weight,level)","None",twodbl, &n, &flg);CHKERRQ(ierr); 496 if (flg) { 497 if (n == 2) { 498 indx = (int)PetscAbsReal(twodbl[1]); 499 PetscStackCallHypre(0,HYPRE_BoomerAMGSetLevelOuterWt,( jac->hsolver, twodbl[0], indx)); 500 } else { 501 SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Relax weight outer level: You must provide 2 values separated by a comma (and no space), you provided %d",n); 502 } 503 } 504 505 /* the Relax Order */ 506 ierr = PetscOptionsBool( "-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr); 507 508 if (flg) { 509 jac->relaxorder = 0; 510 PetscStackCallHypre(0,HYPRE_BoomerAMGSetRelaxOrder,(jac->hsolver, jac->relaxorder)); 511 } 512 ierr = PetscOptionsEList("-pc_hypre_boomeramg_measure_type","Measure type","None",HYPREBoomerAMGMeasureType,2,HYPREBoomerAMGMeasureType[0],&indx,&flg);CHKERRQ(ierr); 513 if (flg) { 514 jac->measuretype = indx; 515 PetscStackCallHypre(0,HYPRE_BoomerAMGSetMeasureType,(jac->hsolver,jac->measuretype)); 516 } 517 /* update list length 3/07 */ 518 ierr = PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type","Coarsen type","None",HYPREBoomerAMGCoarsenType,11,HYPREBoomerAMGCoarsenType[6],&indx,&flg);CHKERRQ(ierr); 519 if (flg) { 520 jac->coarsentype = indx; 521 PetscStackCallHypre(0,HYPRE_BoomerAMGSetCoarsenType,(jac->hsolver,jac->coarsentype)); 522 } 523 524 /* new 3/07 */ 525 ierr = PetscOptionsEList("-pc_hypre_boomeramg_interp_type","Interpolation type","None",HYPREBoomerAMGInterpType,14,HYPREBoomerAMGInterpType[0],&indx,&flg);CHKERRQ(ierr); 526 if (flg) { 527 jac->interptype = indx; 528 PetscStackCallHypre(0,HYPRE_BoomerAMGSetInterpType,(jac->hsolver,jac->interptype)); 529 } 530 531 ierr = PetscOptionsName("-pc_hypre_boomeramg_print_statistics","Print statistics","None",&flg);CHKERRQ(ierr); 532 if (flg) { 533 level = 3; 534 ierr = PetscOptionsInt("-pc_hypre_boomeramg_print_statistics","Print statistics","None",level,&level,PETSC_NULL);CHKERRQ(ierr); 535 jac->printstatistics = PETSC_TRUE; 536 PetscStackCallHypre(0,HYPRE_BoomerAMGSetPrintLevel,(jac->hsolver,level)); 537 } 538 539 ierr = PetscOptionsName("-pc_hypre_boomeramg_print_debug","Print debug information","None",&flg);CHKERRQ(ierr); 540 if (flg) { 541 level = 3; 542 ierr = PetscOptionsInt("-pc_hypre_boomeramg_print_debug","Print debug information","None",level,&level,PETSC_NULL);CHKERRQ(ierr); 543 jac->printstatistics = PETSC_TRUE; 544 PetscStackCallHypre(0,HYPRE_BoomerAMGSetDebugFlag,(jac->hsolver,level)); 545 } 546 547 ierr = PetscOptionsBool( "-pc_hypre_boomeramg_nodal_coarsen", "HYPRE_BoomerAMGSetNodal()", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr); 548 if (flg && tmp_truth) { 549 jac->nodal_coarsen = 1; 550 PetscStackCallHypre(0,HYPRE_BoomerAMGSetNodal,(jac->hsolver,1)); 551 } 552 553 ierr = PetscOptionsBool( "-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None", PETSC_FALSE, &tmp_truth, &flg);CHKERRQ(ierr); 554 if (flg && tmp_truth) { 555 PetscInt tmp_int; 556 ierr = PetscOptionsInt( "-pc_hypre_boomeramg_nodal_relaxation", "Nodal relaxation via Schwarz", "None",jac->nodal_relax_levels,&tmp_int,&flg);CHKERRQ(ierr); 557 if (flg) jac->nodal_relax_levels = tmp_int; 558 PetscStackCallHypre(0,HYPRE_BoomerAMGSetSmoothType,(jac->hsolver,6)); 559 PetscStackCallHypre(0,HYPRE_BoomerAMGSetDomainType,(jac->hsolver,1)); 560 PetscStackCallHypre(0,HYPRE_BoomerAMGSetOverlap,(jac->hsolver,0)); 561 PetscStackCallHypre(0,HYPRE_BoomerAMGSetSmoothNumLevels,(jac->hsolver,jac->nodal_relax_levels)); 562 } 563 564 ierr = PetscOptionsTail();CHKERRQ(ierr); 565 PetscFunctionReturn(0); 566 } 567 568 #undef __FUNCT__ 569 #define __FUNCT__ "PCApplyRichardson_HYPRE_BoomerAMG" 570 static PetscErrorCode PCApplyRichardson_HYPRE_BoomerAMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason) 571 { 572 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 573 PetscErrorCode ierr; 574 int oits; 575 576 PetscFunctionBegin; 577 PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,its*jac->maxiter)); 578 PetscStackCallHypre(0,HYPRE_BoomerAMGSetTol,(jac->hsolver,rtol)); 579 jac->applyrichardson = PETSC_TRUE; 580 ierr = PCApply_HYPRE(pc,b,y);CHKERRQ(ierr); 581 jac->applyrichardson = PETSC_FALSE; 582 PetscStackCallHypre(0,HYPRE_BoomerAMGGetNumIterations,(jac->hsolver,&oits)); 583 *outits = oits; 584 if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS; 585 else *reason = PCRICHARDSON_CONVERGED_RTOL; 586 PetscStackCallHypre(0,HYPRE_BoomerAMGSetTol,(jac->hsolver,jac->tol)); 587 PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,jac->maxiter)); 588 PetscFunctionReturn(0); 589 } 590 591 592 #undef __FUNCT__ 593 #define __FUNCT__ "PCView_HYPRE_BoomerAMG" 594 static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc,PetscViewer viewer) 595 { 596 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 597 PetscErrorCode ierr; 598 PetscBool iascii; 599 600 PetscFunctionBegin; 601 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 602 if (iascii) { 603 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG preconditioning\n");CHKERRQ(ierr); 604 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Cycle type %s\n",HYPREBoomerAMGCycleType[jac->cycletype]);CHKERRQ(ierr); 605 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Maximum number of levels %d\n",jac->maxlevels);CHKERRQ(ierr); 606 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Maximum number of iterations PER hypre call %d\n",jac->maxiter);CHKERRQ(ierr); 607 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Convergence tolerance PER hypre call %G\n",jac->tol);CHKERRQ(ierr); 608 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Threshold for strong coupling %G\n",jac->strongthreshold);CHKERRQ(ierr); 609 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Interpolation truncation factor %G\n",jac->truncfactor);CHKERRQ(ierr); 610 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Interpolation: max elements per row %d\n",jac->pmax);CHKERRQ(ierr); 611 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Number of levels of aggressive coarsening %d\n",jac->agg_nl);CHKERRQ(ierr); 612 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Number of paths for aggressive coarsening %d\n",jac->agg_num_paths);CHKERRQ(ierr); 613 614 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Maximum row sums %G\n",jac->maxrowsum);CHKERRQ(ierr); 615 616 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps down %d\n",jac->gridsweeps[0]);CHKERRQ(ierr); 617 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps up %d\n",jac->gridsweeps[1]);CHKERRQ(ierr); 618 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps on coarse %d\n",jac->gridsweeps[2]);CHKERRQ(ierr); 619 620 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax down %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[0]]);CHKERRQ(ierr); 621 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax up %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[1]]);CHKERRQ(ierr); 622 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax on coarse %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[2]]);CHKERRQ(ierr); 623 624 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax weight (all) %G\n",jac->relaxweight);CHKERRQ(ierr); 625 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Outer relax weight (all) %G\n",jac->outerrelaxweight);CHKERRQ(ierr); 626 627 if (jac->relaxorder) { 628 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Using CF-relaxation\n");CHKERRQ(ierr); 629 } else { 630 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Not using CF-relaxation\n");CHKERRQ(ierr); 631 } 632 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Measure type %s\n",HYPREBoomerAMGMeasureType[jac->measuretype]);CHKERRQ(ierr); 633 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Coarsen type %s\n",HYPREBoomerAMGCoarsenType[jac->coarsentype]);CHKERRQ(ierr); 634 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Interpolation type %s\n",HYPREBoomerAMGInterpType[jac->interptype]);CHKERRQ(ierr); 635 if (jac->nodal_coarsen) { 636 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Using nodal coarsening (with HYPRE_BOOMERAMGSetNodal())\n");CHKERRQ(ierr); 637 } 638 if (jac->nodal_relax) { 639 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Using nodal relaxation via Schwarz smoothing on levels %d\n",jac->nodal_relax_levels);CHKERRQ(ierr); 640 } 641 } 642 PetscFunctionReturn(0); 643 } 644 645 /* --------------------------------------------------------------------------------------------*/ 646 #undef __FUNCT__ 647 #define __FUNCT__ "PCSetFromOptions_HYPRE_ParaSails" 648 static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc) 649 { 650 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 651 PetscErrorCode ierr; 652 int indx; 653 PetscBool flag; 654 const char *symtlist[] = {"nonsymmetric","SPD","nonsymmetric,SPD"}; 655 656 PetscFunctionBegin; 657 ierr = PetscOptionsHead("HYPRE ParaSails Options");CHKERRQ(ierr); 658 ierr = PetscOptionsInt("-pc_hypre_parasails_nlevels","Number of number of levels","None",jac->nlevels,&jac->nlevels,0);CHKERRQ(ierr); 659 ierr = PetscOptionsReal("-pc_hypre_parasails_thresh","Threshold","None",jac->threshhold,&jac->threshhold,&flag);CHKERRQ(ierr); 660 if (flag) { 661 PetscStackCallHypre(0,HYPRE_ParaSailsSetParams,(jac->hsolver,jac->threshhold,jac->nlevels)); 662 } 663 664 ierr = PetscOptionsReal("-pc_hypre_parasails_filter","filter","None",jac->filter,&jac->filter,&flag);CHKERRQ(ierr); 665 if (flag) { 666 PetscStackCallHypre(0,HYPRE_ParaSailsSetFilter,(jac->hsolver,jac->filter)); 667 } 668 669 ierr = PetscOptionsReal("-pc_hypre_parasails_loadbal","Load balance","None",jac->loadbal,&jac->loadbal,&flag);CHKERRQ(ierr); 670 if (flag) { 671 PetscStackCallHypre(0,HYPRE_ParaSailsSetLoadbal,(jac->hsolver,jac->loadbal)); 672 } 673 674 ierr = PetscOptionsBool("-pc_hypre_parasails_logging","Print info to screen","None",(PetscBool)jac->logging,(PetscBool*)&jac->logging,&flag);CHKERRQ(ierr); 675 if (flag) { 676 PetscStackCallHypre(0,HYPRE_ParaSailsSetLogging,(jac->hsolver,jac->logging)); 677 } 678 679 ierr = PetscOptionsBool("-pc_hypre_parasails_reuse","Reuse nonzero pattern in preconditioner","None",(PetscBool)jac->ruse,(PetscBool*)&jac->ruse,&flag);CHKERRQ(ierr); 680 if (flag) { 681 PetscStackCallHypre(0,HYPRE_ParaSailsSetReuse,(jac->hsolver,jac->ruse)); 682 } 683 684 ierr = PetscOptionsEList("-pc_hypre_parasails_sym","Symmetry of matrix and preconditioner","None",symtlist,3,symtlist[0],&indx,&flag);CHKERRQ(ierr); 685 if (flag) { 686 jac->symt = indx; 687 PetscStackCallHypre(0,HYPRE_ParaSailsSetSym,(jac->hsolver,jac->symt)); 688 } 689 690 ierr = PetscOptionsTail();CHKERRQ(ierr); 691 PetscFunctionReturn(0); 692 } 693 694 #undef __FUNCT__ 695 #define __FUNCT__ "PCView_HYPRE_ParaSails" 696 static PetscErrorCode PCView_HYPRE_ParaSails(PC pc,PetscViewer viewer) 697 { 698 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 699 PetscErrorCode ierr; 700 PetscBool iascii; 701 const char *symt = 0;; 702 703 PetscFunctionBegin; 704 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 705 if (iascii) { 706 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails preconditioning\n");CHKERRQ(ierr); 707 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: nlevels %d\n",jac->nlevels);CHKERRQ(ierr); 708 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: threshold %G\n",jac->threshhold);CHKERRQ(ierr); 709 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: filter %G\n",jac->filter);CHKERRQ(ierr); 710 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: load balance %G\n",jac->loadbal);CHKERRQ(ierr); 711 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: reuse nonzero structure %s\n",PetscBools[jac->ruse]);CHKERRQ(ierr); 712 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: print info to screen %s\n",PetscBools[jac->logging]);CHKERRQ(ierr); 713 if (!jac->symt) { 714 symt = "nonsymmetric matrix and preconditioner"; 715 } else if (jac->symt == 1) { 716 symt = "SPD matrix and preconditioner"; 717 } else if (jac->symt == 2) { 718 symt = "nonsymmetric matrix but SPD preconditioner"; 719 } else { 720 SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONG,"Unknown HYPRE ParaSails symmetric option %d",jac->symt); 721 } 722 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: %s\n",symt);CHKERRQ(ierr); 723 } 724 PetscFunctionReturn(0); 725 } 726 /* ---------------------------------------------------------------------------------*/ 727 728 EXTERN_C_BEGIN 729 #undef __FUNCT__ 730 #define __FUNCT__ "PCHYPREGetType_HYPRE" 731 PetscErrorCode PCHYPREGetType_HYPRE(PC pc,const char *name[]) 732 { 733 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 734 735 PetscFunctionBegin; 736 *name = jac->hypre_type; 737 PetscFunctionReturn(0); 738 } 739 EXTERN_C_END 740 741 EXTERN_C_BEGIN 742 #undef __FUNCT__ 743 #define __FUNCT__ "PCHYPRESetType_HYPRE" 744 PetscErrorCode PCHYPRESetType_HYPRE(PC pc,const char name[]) 745 { 746 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 747 PetscErrorCode ierr; 748 PetscBool flag; 749 750 PetscFunctionBegin; 751 if (jac->hypre_type) { 752 ierr = PetscStrcmp(jac->hypre_type,name,&flag);CHKERRQ(ierr); 753 if (!flag) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ORDER,"Cannot reset the HYPRE preconditioner type once it has been set"); 754 PetscFunctionReturn(0); 755 } else { 756 ierr = PetscStrallocpy(name, &jac->hypre_type);CHKERRQ(ierr); 757 } 758 759 jac->maxiter = PETSC_DEFAULT; 760 jac->tol = PETSC_DEFAULT; 761 jac->printstatistics = PetscLogPrintInfo; 762 763 ierr = PetscStrcmp("pilut",jac->hypre_type,&flag);CHKERRQ(ierr); 764 if (flag) { 765 PetscStackCallHypre(0,HYPRE_ParCSRPilutCreate,(jac->comm_hypre,&jac->hsolver)); 766 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut; 767 pc->ops->view = PCView_HYPRE_Pilut; 768 jac->destroy = HYPRE_ParCSRPilutDestroy; 769 jac->setup = HYPRE_ParCSRPilutSetup; 770 jac->solve = HYPRE_ParCSRPilutSolve; 771 jac->factorrowsize = PETSC_DEFAULT; 772 PetscFunctionReturn(0); 773 } 774 ierr = PetscStrcmp("parasails",jac->hypre_type,&flag);CHKERRQ(ierr); 775 if (flag) { 776 PetscStackCallHypre(0,HYPRE_ParaSailsCreate,(jac->comm_hypre,&jac->hsolver)); 777 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails; 778 pc->ops->view = PCView_HYPRE_ParaSails; 779 jac->destroy = HYPRE_ParaSailsDestroy; 780 jac->setup = HYPRE_ParaSailsSetup; 781 jac->solve = HYPRE_ParaSailsSolve; 782 /* initialize */ 783 jac->nlevels = 1; 784 jac->threshhold = .1; 785 jac->filter = .1; 786 jac->loadbal = 0; 787 if (PetscLogPrintInfo) { 788 jac->logging = (int) PETSC_TRUE; 789 } else { 790 jac->logging = (int) PETSC_FALSE; 791 } 792 jac->ruse = (int) PETSC_FALSE; 793 jac->symt = 0; 794 PetscStackCallHypre(0,HYPRE_ParaSailsSetParams,(jac->hsolver,jac->threshhold,jac->nlevels)); 795 PetscStackCallHypre(0,HYPRE_ParaSailsSetFilter,(jac->hsolver,jac->filter)); 796 PetscStackCallHypre(0,HYPRE_ParaSailsSetLoadbal,(jac->hsolver,jac->loadbal)); 797 PetscStackCallHypre(0,HYPRE_ParaSailsSetLogging,(jac->hsolver,jac->logging)); 798 PetscStackCallHypre(0,HYPRE_ParaSailsSetReuse,(jac->hsolver,jac->ruse)); 799 PetscStackCallHypre(0,HYPRE_ParaSailsSetSym,(jac->hsolver,jac->symt)); 800 PetscFunctionReturn(0); 801 } 802 ierr = PetscStrcmp("euclid",jac->hypre_type,&flag);CHKERRQ(ierr); 803 if (flag) { 804 ierr = HYPRE_EuclidCreate(jac->comm_hypre,&jac->hsolver); 805 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid; 806 pc->ops->view = PCView_HYPRE_Euclid; 807 jac->destroy = HYPRE_EuclidDestroy; 808 jac->setup = HYPRE_EuclidSetup; 809 jac->solve = HYPRE_EuclidSolve; 810 /* initialization */ 811 jac->bjilu = PETSC_FALSE; 812 jac->levels = 1; 813 PetscFunctionReturn(0); 814 } 815 ierr = PetscStrcmp("boomeramg",jac->hypre_type,&flag);CHKERRQ(ierr); 816 if (flag) { 817 ierr = HYPRE_BoomerAMGCreate(&jac->hsolver); 818 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_BoomerAMG; 819 pc->ops->view = PCView_HYPRE_BoomerAMG; 820 pc->ops->applytranspose = PCApplyTranspose_HYPRE_BoomerAMG; 821 pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG; 822 jac->destroy = HYPRE_BoomerAMGDestroy; 823 jac->setup = HYPRE_BoomerAMGSetup; 824 jac->solve = HYPRE_BoomerAMGSolve; 825 jac->applyrichardson = PETSC_FALSE; 826 /* these defaults match the hypre defaults */ 827 jac->cycletype = 1; 828 jac->maxlevels = 25; 829 jac->maxiter = 1; 830 jac->tol = 0.0; /* tolerance of zero indicates use as preconditioner (suppresses convergence errors) */ 831 jac->truncfactor = 0.0; 832 jac->strongthreshold = .25; 833 jac->maxrowsum = .9; 834 jac->coarsentype = 6; 835 jac->measuretype = 0; 836 jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = 1; 837 jac->relaxtype[0] = jac->relaxtype[1] = 6; /* Defaults to SYMMETRIC since in PETSc we are using a a PC - most likely with CG */ 838 jac->relaxtype[2] = 9; /*G.E. */ 839 jac->relaxweight = 1.0; 840 jac->outerrelaxweight = 1.0; 841 jac->relaxorder = 1; 842 jac->interptype = 0; 843 jac->agg_nl = 0; 844 jac->pmax = 0; 845 jac->truncfactor = 0.0; 846 jac->agg_num_paths = 1; 847 848 jac->nodal_coarsen = 0; 849 jac->nodal_relax = PETSC_FALSE; 850 jac->nodal_relax_levels = 1; 851 PetscStackCallHypre(0,HYPRE_BoomerAMGSetCycleType,(jac->hsolver,jac->cycletype)); 852 PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxLevels,(jac->hsolver,jac->maxlevels)); 853 PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxIter,(jac->hsolver,jac->maxiter)); 854 PetscStackCallHypre(0,HYPRE_BoomerAMGSetTol,(jac->hsolver,jac->tol)); 855 PetscStackCallHypre(0,HYPRE_BoomerAMGSetTruncFactor,(jac->hsolver,jac->truncfactor)); 856 PetscStackCallHypre(0,HYPRE_BoomerAMGSetStrongThreshold,(jac->hsolver,jac->strongthreshold)); 857 PetscStackCallHypre(0,HYPRE_BoomerAMGSetMaxRowSum,(jac->hsolver,jac->maxrowsum)); 858 PetscStackCallHypre(0,HYPRE_BoomerAMGSetCoarsenType,(jac->hsolver,jac->coarsentype)); 859 PetscStackCallHypre(0,HYPRE_BoomerAMGSetMeasureType,(jac->hsolver,jac->measuretype)); 860 PetscStackCallHypre(0,HYPRE_BoomerAMGSetRelaxOrder,(jac->hsolver, jac->relaxorder)); 861 PetscStackCallHypre(0,HYPRE_BoomerAMGSetInterpType,(jac->hsolver,jac->interptype)); 862 PetscStackCallHypre(0,HYPRE_BoomerAMGSetAggNumLevels,(jac->hsolver,jac->agg_nl)); 863 PetscStackCallHypre(0,HYPRE_BoomerAMGSetPMaxElmts,(jac->hsolver,jac->pmax)); 864 PetscStackCallHypre(0,HYPRE_BoomerAMGSetNumPaths,(jac->hsolver,jac->agg_num_paths)); 865 PetscStackCallHypre(0,HYPRE_BoomerAMGSetRelaxType,(jac->hsolver, jac->relaxtype[0])); /*defaults coarse to 9*/ 866 PetscStackCallHypre(0,HYPRE_BoomerAMGSetNumSweeps,(jac->hsolver, jac->gridsweeps[0])); /*defaults coarse to 1 */ 867 PetscFunctionReturn(0); 868 } 869 ierr = PetscFree(jac->hypre_type);CHKERRQ(ierr); 870 jac->hypre_type = PETSC_NULL; 871 SETERRQ1(((PetscObject)pc)->comm,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown HYPRE preconditioner %s; Choices are pilut, parasails, euclid, boomeramg",name); 872 PetscFunctionReturn(0); 873 } 874 EXTERN_C_END 875 876 /* 877 It only gets here if the HYPRE type has not been set before the call to 878 ...SetFromOptions() which actually is most of the time 879 */ 880 #undef __FUNCT__ 881 #define __FUNCT__ "PCSetFromOptions_HYPRE" 882 static PetscErrorCode PCSetFromOptions_HYPRE(PC pc) 883 { 884 PetscErrorCode ierr; 885 int indx; 886 const char *type[] = {"pilut","parasails","boomeramg","euclid"}; 887 PetscBool flg; 888 889 PetscFunctionBegin; 890 ierr = PetscOptionsHead("HYPRE preconditioner options");CHKERRQ(ierr); 891 ierr = PetscOptionsEList("-pc_hypre_type","HYPRE preconditioner type","PCHYPRESetType",type,4,"boomeramg",&indx,&flg);CHKERRQ(ierr); 892 if (flg) { 893 ierr = PCHYPRESetType_HYPRE(pc,type[indx]);CHKERRQ(ierr); 894 } else { 895 ierr = PCHYPRESetType_HYPRE(pc,"boomeramg");CHKERRQ(ierr); 896 } 897 if (pc->ops->setfromoptions) { 898 ierr = pc->ops->setfromoptions(pc);CHKERRQ(ierr); 899 } 900 ierr = PetscOptionsTail();CHKERRQ(ierr); 901 PetscFunctionReturn(0); 902 } 903 904 #undef __FUNCT__ 905 #define __FUNCT__ "PCHYPRESetType" 906 /*@C 907 PCHYPRESetType - Sets which hypre preconditioner you wish to use 908 909 Input Parameters: 910 + pc - the preconditioner context 911 - name - either pilut, parasails, boomeramg, euclid 912 913 Options Database Keys: 914 -pc_hypre_type - One of pilut, parasails, boomeramg, euclid 915 916 Level: intermediate 917 918 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 919 PCHYPRE 920 921 @*/ 922 PetscErrorCode PCHYPRESetType(PC pc,const char name[]) 923 { 924 PetscErrorCode ierr; 925 926 PetscFunctionBegin; 927 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 928 PetscValidCharPointer(name,2); 929 ierr = PetscTryMethod(pc,"PCHYPRESetType_C",(PC,const char[]),(pc,name));CHKERRQ(ierr); 930 PetscFunctionReturn(0); 931 } 932 933 #undef __FUNCT__ 934 #define __FUNCT__ "PCHYPREGetType" 935 /*@C 936 PCHYPREGetType - Gets which hypre preconditioner you are using 937 938 Input Parameter: 939 . pc - the preconditioner context 940 941 Output Parameter: 942 . name - either pilut, parasails, boomeramg, euclid 943 944 Level: intermediate 945 946 .seealso: PCCreate(), PCHYPRESetType(), PCType (for list of available types), PC, 947 PCHYPRE 948 949 @*/ 950 PetscErrorCode PCHYPREGetType(PC pc,const char *name[]) 951 { 952 PetscErrorCode ierr; 953 954 PetscFunctionBegin; 955 PetscValidHeaderSpecific(pc,PC_CLASSID,1); 956 PetscValidPointer(name,2); 957 ierr = PetscTryMethod(pc,"PCHYPREGetType_C",(PC,const char*[]),(pc,name));CHKERRQ(ierr); 958 PetscFunctionReturn(0); 959 } 960 961 /*MC 962 PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre 963 964 Options Database Keys: 965 + -pc_hypre_type - One of pilut, parasails, boomeramg, euclid 966 - Too many others to list, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX 967 preconditioner 968 969 Level: intermediate 970 971 Notes: Apart from pc_hypre_type (for which there is PCHYPRESetType()), 972 the many hypre options can ONLY be set via the options database (e.g. the command line 973 or with PetscOptionsSetValue(), there are no functions to set them) 974 975 The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_rtol refer to the number of iterations 976 (V-cycles) and tolerance that boomeramg does EACH time it is called. So for example, if 977 -pc_hypre_boomeramg_max_iter is set to 2 then 2-V-cycles are being used to define the preconditioner 978 (-pc_hypre_boomeramg_rtol should be set to 0.0 - the default - to strictly use a fixed number of 979 iterations per hypre call). -ksp_max_it and -ksp_rtol STILL determine the total number of iterations 980 and tolerance for the Krylov solver. For example, if -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10 981 then AT MOST twenty V-cycles of boomeramg will be called. 982 983 Note that the option -pc_hypre_boomeramg_relax_type_all defaults to symmetric relaxation 984 (symmetric-SOR/Jacobi), which is required for Krylov solvers like CG that expect symmetry. 985 Otherwise, you may want to use -pc_hypre_boomeramg_relax_type_all SOR/Jacobi. 986 If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly 987 and use -ksp_max_it to control the number of V-cycles. 988 (see the PETSc FAQ.html at the PETSc website under the Documentation tab). 989 990 2007-02-03 Using HYPRE-1.11.1b, the routine HYPRE_BoomerAMGSolveT and the option 991 -pc_hypre_parasails_reuse were failing with SIGSEGV. Dalcin L. 992 993 See PCPFMG for access to the hypre Struct PFMG solver 994 995 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 996 PCHYPRESetType(), PCPFMG 997 998 M*/ 999 1000 EXTERN_C_BEGIN 1001 #undef __FUNCT__ 1002 #define __FUNCT__ "PCCreate_HYPRE" 1003 PetscErrorCode PCCreate_HYPRE(PC pc) 1004 { 1005 PC_HYPRE *jac; 1006 PetscErrorCode ierr; 1007 1008 PetscFunctionBegin; 1009 ierr = PetscNewLog(pc,PC_HYPRE,&jac);CHKERRQ(ierr); 1010 pc->data = jac; 1011 pc->ops->destroy = PCDestroy_HYPRE; 1012 pc->ops->setfromoptions = PCSetFromOptions_HYPRE; 1013 pc->ops->setup = PCSetUp_HYPRE; 1014 pc->ops->apply = PCApply_HYPRE; 1015 jac->comm_hypre = MPI_COMM_NULL; 1016 jac->hypre_type = PETSC_NULL; 1017 /* duplicate communicator for hypre */ 1018 ierr = MPI_Comm_dup(((PetscObject)pc)->comm,&(jac->comm_hypre));CHKERRQ(ierr); 1019 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPRESetType_C","PCHYPRESetType_HYPRE",PCHYPRESetType_HYPRE);CHKERRQ(ierr); 1020 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPREGetType_C","PCHYPREGetType_HYPRE",PCHYPREGetType_HYPRE);CHKERRQ(ierr); 1021 PetscFunctionReturn(0); 1022 } 1023 EXTERN_C_END 1024 1025 /* ---------------------------------------------------------------------------------------------------------------------------------*/ 1026 1027 /* this include is needed ONLY to allow access to the private data inside the Mat object specific to hypre */ 1028 #include <private/matimpl.h> 1029 1030 typedef struct { 1031 MPI_Comm hcomm; /* does not share comm with HYPRE_StructMatrix because need to create solver before getting matrix */ 1032 HYPRE_StructSolver hsolver; 1033 1034 /* keep copy of PFMG options used so may view them */ 1035 int its; 1036 double tol; 1037 int relax_type; 1038 int rap_type; 1039 int num_pre_relax,num_post_relax; 1040 int max_levels; 1041 } PC_PFMG; 1042 1043 #undef __FUNCT__ 1044 #define __FUNCT__ "PCDestroy_PFMG" 1045 PetscErrorCode PCDestroy_PFMG(PC pc) 1046 { 1047 PetscErrorCode ierr; 1048 PC_PFMG *ex = (PC_PFMG*) pc->data; 1049 1050 PetscFunctionBegin; 1051 if (ex->hsolver) {PetscStackCallHypre(0,HYPRE_StructPFMGDestroy,(ex->hsolver));} 1052 ierr = MPI_Comm_free(&ex->hcomm);CHKERRQ(ierr); 1053 ierr = PetscFree(pc->data);CHKERRQ(ierr); 1054 PetscFunctionReturn(0); 1055 } 1056 1057 static const char *PFMGRelaxType[] = {"Jacobi","Weighted-Jacobi","symmetric-Red/Black-Gauss-Seidel","Red/Black-Gauss-Seidel"}; 1058 static const char *PFMGRAPType[] = {"Galerkin","non-Galerkin"}; 1059 1060 #undef __FUNCT__ 1061 #define __FUNCT__ "PCView_PFMG" 1062 PetscErrorCode PCView_PFMG(PC pc,PetscViewer viewer) 1063 { 1064 PetscErrorCode ierr; 1065 PetscBool iascii; 1066 PC_PFMG *ex = (PC_PFMG*) pc->data; 1067 1068 PetscFunctionBegin; 1069 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1070 if (iascii) { 1071 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG preconditioning\n");CHKERRQ(ierr); 1072 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: max iterations %d\n",ex->its);CHKERRQ(ierr); 1073 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: tolerance %g\n",ex->tol);CHKERRQ(ierr); 1074 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: relax type %s\n",PFMGRelaxType[ex->relax_type]);CHKERRQ(ierr); 1075 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: RAP type %s\n",PFMGRAPType[ex->rap_type]);CHKERRQ(ierr); 1076 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: number pre-relax %d post-relax %d\n",ex->num_pre_relax,ex->num_post_relax);CHKERRQ(ierr); 1077 ierr = PetscViewerASCIIPrintf(viewer," HYPRE PFMG: max levels %d\n",ex->max_levels);CHKERRQ(ierr); 1078 } 1079 PetscFunctionReturn(0); 1080 } 1081 1082 1083 #undef __FUNCT__ 1084 #define __FUNCT__ "PCSetFromOptions_PFMG" 1085 PetscErrorCode PCSetFromOptions_PFMG(PC pc) 1086 { 1087 PetscErrorCode ierr; 1088 PC_PFMG *ex = (PC_PFMG*) pc->data; 1089 PetscBool flg = PETSC_FALSE; 1090 1091 PetscFunctionBegin; 1092 ierr = PetscOptionsHead("PFMG options");CHKERRQ(ierr); 1093 ierr = PetscOptionsBool("-pc_pfmg_print_statistics","Print statistics","HYPRE_StructPFMGSetPrintLevel",flg,&flg,PETSC_NULL);CHKERRQ(ierr); 1094 if (flg) { 1095 int level=3; 1096 PetscStackCallHypre(0,HYPRE_StructPFMGSetPrintLevel,(ex->hsolver,level)); 1097 } 1098 ierr = PetscOptionsInt("-pc_pfmg_its","Number of iterations of PFMG to use as preconditioner","HYPRE_StructPFMGSetMaxIter",ex->its,&ex->its,PETSC_NULL);CHKERRQ(ierr); 1099 PetscStackCallHypre(0,HYPRE_StructPFMGSetMaxIter,(ex->hsolver,ex->its)); 1100 ierr = PetscOptionsInt("-pc_pfmg_num_pre_relax","Number of smoothing steps before coarse grid","HYPRE_StructPFMGSetNumPreRelax",ex->num_pre_relax,&ex->num_pre_relax,PETSC_NULL);CHKERRQ(ierr); 1101 PetscStackCallHypre(0,HYPRE_StructPFMGSetNumPreRelax,(ex->hsolver,ex->num_pre_relax)); 1102 ierr = PetscOptionsInt("-pc_pfmg_num_post_relax","Number of smoothing steps after coarse grid","HYPRE_StructPFMGSetNumPostRelax",ex->num_post_relax,&ex->num_post_relax,PETSC_NULL);CHKERRQ(ierr); 1103 PetscStackCallHypre(0,HYPRE_StructPFMGSetNumPostRelax,(ex->hsolver,ex->num_post_relax)); 1104 1105 ierr = PetscOptionsInt("-pc_pfmg_max_levels","Max Levels for MG hierarchy","HYPRE_StructPFMGSetMaxLevels",ex->max_levels,&ex->max_levels,PETSC_NULL);CHKERRQ(ierr); 1106 PetscStackCallHypre(0,HYPRE_StructPFMGSetMaxLevels,(ex->hsolver,ex->max_levels)); 1107 1108 ierr = PetscOptionsReal("-pc_pfmg_tol","Tolerance of PFMG","HYPRE_StructPFMGSetTol",ex->tol,&ex->tol,PETSC_NULL);CHKERRQ(ierr); 1109 PetscStackCallHypre(0,HYPRE_StructPFMGSetTol,(ex->hsolver,ex->tol)); 1110 ierr = PetscOptionsEList("-pc_pfmg_relax_type","Relax type for the up and down cycles","HYPRE_StructPFMGSetRelaxType",PFMGRelaxType,4,PFMGRelaxType[ex->relax_type],&ex->relax_type,PETSC_NULL);CHKERRQ(ierr); 1111 PetscStackCallHypre(0,HYPRE_StructPFMGSetRelaxType,(ex->hsolver, ex->relax_type)); 1112 ierr = PetscOptionsEList("-pc_pfmg_rap_type","RAP type","HYPRE_StructPFMGSetRAPType",PFMGRAPType,2,PFMGRAPType[ex->rap_type],&ex->rap_type,PETSC_NULL);CHKERRQ(ierr); 1113 PetscStackCallHypre(0,HYPRE_StructPFMGSetRAPType,(ex->hsolver, ex->rap_type)); 1114 ierr = PetscOptionsTail();CHKERRQ(ierr); 1115 PetscFunctionReturn(0); 1116 } 1117 1118 #undef __FUNCT__ 1119 #define __FUNCT__ "PCApply_PFMG" 1120 PetscErrorCode PCApply_PFMG(PC pc,Vec x,Vec y) 1121 { 1122 PetscErrorCode ierr; 1123 PC_PFMG *ex = (PC_PFMG*) pc->data; 1124 PetscScalar *xx,*yy; 1125 int ilower[3],iupper[3]; 1126 Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data); 1127 1128 PetscFunctionBegin; 1129 ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr); 1130 iupper[0] += ilower[0] - 1; 1131 iupper[1] += ilower[1] - 1; 1132 iupper[2] += ilower[2] - 1; 1133 1134 /* copy x values over to hypre */ 1135 PetscStackCallHypre(0,HYPRE_StructVectorSetConstantValues,(mx->hb,0.0)); 1136 ierr = VecGetArray(x,&xx);CHKERRQ(ierr); 1137 PetscStackCallHypre(0,HYPRE_StructVectorSetBoxValues,(mx->hb,ilower,iupper,xx)); 1138 ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr); 1139 PetscStackCallHypre(0,HYPRE_StructVectorAssemble,(mx->hb)); 1140 PetscStackCallHypre(0,HYPRE_StructPFMGSolve,(ex->hsolver,mx->hmat,mx->hb,mx->hx)); 1141 1142 /* copy solution values back to PETSc */ 1143 ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 1144 PetscStackCallHypre(0,HYPRE_StructVectorGetBoxValues,(mx->hx,ilower,iupper,yy)); 1145 ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 1146 PetscFunctionReturn(0); 1147 } 1148 1149 #undef __FUNCT__ 1150 #define __FUNCT__ "PCApplyRichardson_PFMG" 1151 static PetscErrorCode PCApplyRichardson_PFMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason) 1152 { 1153 PC_PFMG *jac = (PC_PFMG*)pc->data; 1154 PetscErrorCode ierr; 1155 int oits; 1156 1157 PetscFunctionBegin; 1158 PetscStackCallHypre(0,HYPRE_StructPFMGSetMaxIter,(jac->hsolver,its*jac->its)); 1159 PetscStackCallHypre(0,HYPRE_StructPFMGSetTol,(jac->hsolver,rtol)); 1160 1161 ierr = PCApply_PFMG(pc,b,y);CHKERRQ(ierr); 1162 PetscStackCallHypre(0,HYPRE_StructPFMGGetNumIterations,(jac->hsolver,&oits)); 1163 *outits = oits; 1164 if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS; 1165 else *reason = PCRICHARDSON_CONVERGED_RTOL; 1166 PetscStackCallHypre(0,HYPRE_StructPFMGSetTol,(jac->hsolver,jac->tol)); 1167 PetscStackCallHypre(0,HYPRE_StructPFMGSetMaxIter,(jac->hsolver,jac->its)); 1168 PetscFunctionReturn(0); 1169 } 1170 1171 1172 #undef __FUNCT__ 1173 #define __FUNCT__ "PCSetUp_PFMG" 1174 PetscErrorCode PCSetUp_PFMG(PC pc) 1175 { 1176 PetscErrorCode ierr; 1177 PC_PFMG *ex = (PC_PFMG*) pc->data; 1178 Mat_HYPREStruct *mx = (Mat_HYPREStruct *)(pc->pmat->data); 1179 PetscBool flg; 1180 1181 PetscFunctionBegin; 1182 ierr = PetscTypeCompare((PetscObject)pc->pmat,MATHYPRESTRUCT,&flg);CHKERRQ(ierr); 1183 if (!flg) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_INCOMP,"Must use MATHYPRESTRUCT with this preconditioner"); 1184 1185 /* create the hypre solver object and set its information */ 1186 if (ex->hsolver) { 1187 PetscStackCallHypre(0,HYPRE_StructPFMGDestroy,(ex->hsolver)); 1188 } 1189 PetscStackCallHypre(0,HYPRE_StructPFMGCreate,(ex->hcomm,&ex->hsolver)); 1190 ierr = PCSetFromOptions_PFMG(pc);CHKERRQ(ierr); 1191 PetscStackCallHypre(0,HYPRE_StructPFMGSetup,(ex->hsolver,mx->hmat,mx->hb,mx->hx)); 1192 PetscStackCallHypre(0,HYPRE_StructPFMGSetZeroGuess,(ex->hsolver)); 1193 PetscFunctionReturn(0); 1194 } 1195 1196 1197 /*MC 1198 PCPFMG - the hypre PFMG multigrid solver 1199 1200 Level: advanced 1201 1202 Options Database: 1203 + -pc_pfmg_its <its> number of iterations of PFMG to use as preconditioner 1204 . -pc_pfmg_num_pre_relax <steps> number of smoothing steps before coarse grid 1205 . -pc_pfmg_num_post_relax <steps> number of smoothing steps after coarse grid 1206 . -pc_pfmg_tol <tol> tolerance of PFMG 1207 . -pc_pfmg_relax_type -relaxation type for the up and down cycles, one of Jacobi,Weighted-Jacobi,symmetric-Red/Black-Gauss-Seidel,Red/Black-Gauss-Seidel 1208 - -pc_pfmg_rap_type - type of coarse matrix generation, one of Galerkin,non-Galerkin 1209 1210 Notes: This is for CELL-centered descretizations 1211 1212 This must be used with the MATHYPRESTRUCT matrix type. 1213 This is less general than in hypre, it supports only one block per process defined by a PETSc DMDA. 1214 1215 .seealso: PCMG, MATHYPRESTRUCT 1216 M*/ 1217 1218 EXTERN_C_BEGIN 1219 #undef __FUNCT__ 1220 #define __FUNCT__ "PCCreate_PFMG" 1221 PetscErrorCode PCCreate_PFMG(PC pc) 1222 { 1223 PetscErrorCode ierr; 1224 PC_PFMG *ex; 1225 1226 PetscFunctionBegin; 1227 ierr = PetscNew(PC_PFMG,&ex);CHKERRQ(ierr);\ 1228 pc->data = ex; 1229 1230 ex->its = 1; 1231 ex->tol = 1.e-8; 1232 ex->relax_type = 1; 1233 ex->rap_type = 0; 1234 ex->num_pre_relax = 1; 1235 ex->num_post_relax = 1; 1236 ex->max_levels = 0; 1237 1238 pc->ops->setfromoptions = PCSetFromOptions_PFMG; 1239 pc->ops->view = PCView_PFMG; 1240 pc->ops->destroy = PCDestroy_PFMG; 1241 pc->ops->apply = PCApply_PFMG; 1242 pc->ops->applyrichardson = PCApplyRichardson_PFMG; 1243 pc->ops->setup = PCSetUp_PFMG; 1244 ierr = MPI_Comm_dup(((PetscObject)pc)->comm,&(ex->hcomm));CHKERRQ(ierr); 1245 PetscStackCallHypre(0,HYPRE_StructPFMGCreate,(ex->hcomm,&ex->hsolver)); 1246 PetscFunctionReturn(0); 1247 } 1248 EXTERN_C_END 1249 1250 /* ---------------------------------------------------------------------------------------------------------------------------------------------------*/ 1251 1252 /* we know we are working with a HYPRE_SStructMatrix */ 1253 typedef struct { 1254 MPI_Comm hcomm; /* does not share comm with HYPRE_SStructMatrix because need to create solver before getting matrix */ 1255 HYPRE_SStructSolver ss_solver; 1256 1257 /* keep copy of SYSPFMG options used so may view them */ 1258 int its; 1259 double tol; 1260 int relax_type; 1261 int num_pre_relax,num_post_relax; 1262 } PC_SysPFMG; 1263 1264 #undef __FUNCT__ 1265 #define __FUNCT__ "PCDestroy_SysPFMG" 1266 PetscErrorCode PCDestroy_SysPFMG(PC pc) 1267 { 1268 PetscErrorCode ierr; 1269 PC_SysPFMG *ex = (PC_SysPFMG*) pc->data; 1270 1271 PetscFunctionBegin; 1272 if (ex->ss_solver) {PetscStackCallHypre(0,HYPRE_SStructSysPFMGDestroy,(ex->ss_solver));} 1273 ierr = MPI_Comm_free(&ex->hcomm);CHKERRQ(ierr); 1274 ierr = PetscFree(pc->data);CHKERRQ(ierr); 1275 PetscFunctionReturn(0); 1276 } 1277 1278 static const char *SysPFMGRelaxType[] = {"Weighted-Jacobi","Red/Black-Gauss-Seidel"}; 1279 1280 #undef __FUNCT__ 1281 #define __FUNCT__ "PCView_SysPFMG" 1282 PetscErrorCode PCView_SysPFMG(PC pc,PetscViewer viewer) 1283 { 1284 PetscErrorCode ierr; 1285 PetscBool iascii; 1286 PC_SysPFMG *ex = (PC_SysPFMG*) pc->data; 1287 1288 PetscFunctionBegin; 1289 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1290 if (iascii) { 1291 ierr = PetscViewerASCIIPrintf(viewer," HYPRE SysPFMG preconditioning\n");CHKERRQ(ierr); 1292 ierr = PetscViewerASCIIPrintf(viewer," HYPRE SysPFMG: max iterations %d\n",ex->its);CHKERRQ(ierr); 1293 ierr = PetscViewerASCIIPrintf(viewer," HYPRE SysPFMG: tolerance %g\n",ex->tol);CHKERRQ(ierr); 1294 ierr = PetscViewerASCIIPrintf(viewer," HYPRE SysPFMG: relax type %s\n",PFMGRelaxType[ex->relax_type]);CHKERRQ(ierr); 1295 ierr = PetscViewerASCIIPrintf(viewer," HYPRE SysPFMG: number pre-relax %d post-relax %d\n",ex->num_pre_relax,ex->num_post_relax);CHKERRQ(ierr); 1296 } 1297 PetscFunctionReturn(0); 1298 } 1299 1300 1301 #undef __FUNCT__ 1302 #define __FUNCT__ "PCSetFromOptions_SysPFMG" 1303 PetscErrorCode PCSetFromOptions_SysPFMG(PC pc) 1304 { 1305 PetscErrorCode ierr; 1306 PC_SysPFMG *ex = (PC_SysPFMG*) pc->data; 1307 PetscBool flg = PETSC_FALSE; 1308 1309 PetscFunctionBegin; 1310 ierr = PetscOptionsHead("SysPFMG options");CHKERRQ(ierr); 1311 ierr = PetscOptionsBool("-pc_syspfmg_print_statistics","Print statistics","HYPRE_SStructSysPFMGSetPrintLevel",flg,&flg,PETSC_NULL);CHKERRQ(ierr); 1312 if (flg) { 1313 int level=3; 1314 PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetPrintLevel,(ex->ss_solver,level)); 1315 } 1316 ierr = PetscOptionsInt("-pc_syspfmg_its","Number of iterations of SysPFMG to use as preconditioner","HYPRE_SStructSysPFMGSetMaxIter",ex->its,&ex->its,PETSC_NULL);CHKERRQ(ierr); 1317 PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetMaxIter,(ex->ss_solver,ex->its)); 1318 ierr = PetscOptionsInt("-pc_syspfmg_num_pre_relax","Number of smoothing steps before coarse grid","HYPRE_SStructSysPFMGSetNumPreRelax",ex->num_pre_relax,&ex->num_pre_relax,PETSC_NULL);CHKERRQ(ierr); 1319 PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetNumPreRelax,(ex->ss_solver,ex->num_pre_relax)); 1320 ierr = PetscOptionsInt("-pc_syspfmg_num_post_relax","Number of smoothing steps after coarse grid","HYPRE_SStructSysPFMGSetNumPostRelax",ex->num_post_relax,&ex->num_post_relax,PETSC_NULL);CHKERRQ(ierr); 1321 PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetNumPostRelax,(ex->ss_solver,ex->num_post_relax)); 1322 1323 ierr = PetscOptionsReal("-pc_syspfmg_tol","Tolerance of SysPFMG","HYPRE_SStructSysPFMGSetTol",ex->tol,&ex->tol,PETSC_NULL);CHKERRQ(ierr); 1324 PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetTol,(ex->ss_solver,ex->tol)); 1325 ierr = PetscOptionsEList("-pc_syspfmg_relax_type","Relax type for the up and down cycles","HYPRE_SStructSysPFMGSetRelaxType",SysPFMGRelaxType,4,SysPFMGRelaxType[ex->relax_type],&ex->relax_type,PETSC_NULL);CHKERRQ(ierr); 1326 PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetRelaxType,(ex->ss_solver, ex->relax_type)); 1327 ierr = PetscOptionsTail();CHKERRQ(ierr); 1328 PetscFunctionReturn(0); 1329 } 1330 1331 #undef __FUNCT__ 1332 #define __FUNCT__ "PCApply_SysPFMG" 1333 PetscErrorCode PCApply_SysPFMG(PC pc,Vec x,Vec y) 1334 { 1335 PetscErrorCode ierr; 1336 PC_SysPFMG *ex = (PC_SysPFMG*) pc->data; 1337 PetscScalar *xx,*yy; 1338 int ilower[3],iupper[3]; 1339 Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(pc->pmat->data); 1340 int ordering= mx->dofs_order; 1341 int nvars= mx->nvars; 1342 int part= 0; 1343 int size; 1344 int i; 1345 1346 PetscFunctionBegin; 1347 ierr = DMDAGetCorners(mx->da,&ilower[0],&ilower[1],&ilower[2],&iupper[0],&iupper[1],&iupper[2]);CHKERRQ(ierr); 1348 iupper[0] += ilower[0] - 1; 1349 iupper[1] += ilower[1] - 1; 1350 iupper[2] += ilower[2] - 1; 1351 1352 size= 1; 1353 for (i= 0; i< 3; i++) { 1354 size*= (iupper[i]-ilower[i]+1); 1355 } 1356 /* copy x values over to hypre for variable ordering */ 1357 if (ordering) { 1358 PetscStackCallHypre(0,HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0)); 1359 ierr = VecGetArray(x,&xx);CHKERRQ(ierr); 1360 for (i= 0; i< nvars; i++) { 1361 PetscStackCallHypre(0,HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,ilower,iupper,i,xx+(size*i))); 1362 } 1363 ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr); 1364 PetscStackCallHypre(0,HYPRE_SStructVectorAssemble,(mx->ss_b)); 1365 PetscStackCallHypre(0,HYPRE_SStructMatrixMatvec,(1.0,mx->ss_mat,mx->ss_b,0.0,mx->ss_x)); 1366 PetscStackCallHypre(0,HYPRE_SStructSysPFMGSolve,(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x)); 1367 1368 /* copy solution values back to PETSc */ 1369 ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 1370 for (i= 0; i< nvars; i++) { 1371 PetscStackCallHypre(0,HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,ilower,iupper,i,yy+(size*i))); 1372 } 1373 ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 1374 } else { /* nodal ordering must be mapped to variable ordering for sys_pfmg */ 1375 PetscScalar *z; 1376 int j, k; 1377 1378 ierr = PetscMalloc(nvars*size*sizeof(PetscScalar),&z);CHKERRQ(ierr); 1379 PetscStackCallHypre(0,HYPRE_SStructVectorSetConstantValues,(mx->ss_b,0.0)); 1380 ierr = VecGetArray(x,&xx);CHKERRQ(ierr); 1381 1382 /* transform nodal to hypre's variable ordering for sys_pfmg */ 1383 for (i= 0; i< size; i++) { 1384 k= i*nvars; 1385 for (j= 0; j< nvars; j++) { 1386 z[j*size+i]= xx[k+j]; 1387 } 1388 } 1389 for (i= 0; i< nvars; i++) { 1390 PetscStackCallHypre(0,HYPRE_SStructVectorSetBoxValues,(mx->ss_b,part,ilower,iupper,i,z+(size*i))); 1391 } 1392 ierr = VecRestoreArray(x,&xx);CHKERRQ(ierr); 1393 PetscStackCallHypre(0,HYPRE_SStructVectorAssemble,(mx->ss_b)); 1394 PetscStackCallHypre(0,HYPRE_SStructSysPFMGSolve,(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x)); 1395 1396 /* copy solution values back to PETSc */ 1397 ierr = VecGetArray(y,&yy);CHKERRQ(ierr); 1398 for (i= 0; i< nvars; i++) { 1399 PetscStackCallHypre(0,HYPRE_SStructVectorGetBoxValues,(mx->ss_x,part,ilower,iupper,i,z+(size*i))); 1400 } 1401 /* transform hypre's variable ordering for sys_pfmg to nodal ordering */ 1402 for (i= 0; i< size; i++) { 1403 k= i*nvars; 1404 for (j= 0; j< nvars; j++) { 1405 yy[k+j]= z[j*size+i]; 1406 } 1407 } 1408 ierr = VecRestoreArray(y,&yy);CHKERRQ(ierr); 1409 ierr = PetscFree(z);CHKERRQ(ierr); 1410 } 1411 PetscFunctionReturn(0); 1412 } 1413 1414 #undef __FUNCT__ 1415 #define __FUNCT__ "PCApplyRichardson_SysPFMG" 1416 static PetscErrorCode PCApplyRichardson_SysPFMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its,PetscBool guesszero,PetscInt *outits,PCRichardsonConvergedReason *reason) 1417 { 1418 PC_SysPFMG *jac = (PC_SysPFMG*)pc->data; 1419 PetscErrorCode ierr; 1420 int oits; 1421 1422 PetscFunctionBegin; 1423 PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetMaxIter,(jac->ss_solver,its*jac->its)); 1424 PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetTol,(jac->ss_solver,rtol)); 1425 ierr = PCApply_SysPFMG(pc,b,y);CHKERRQ(ierr); 1426 PetscStackCallHypre(0,HYPRE_SStructSysPFMGGetNumIterations,(jac->ss_solver,&oits)); 1427 *outits = oits; 1428 if (oits == its) *reason = PCRICHARDSON_CONVERGED_ITS; 1429 else *reason = PCRICHARDSON_CONVERGED_RTOL; 1430 PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetTol,(jac->ss_solver,jac->tol)); 1431 PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetMaxIter,(jac->ss_solver,jac->its)); 1432 PetscFunctionReturn(0); 1433 } 1434 1435 1436 #undef __FUNCT__ 1437 #define __FUNCT__ "PCSetUp_SysPFMG" 1438 PetscErrorCode PCSetUp_SysPFMG(PC pc) 1439 { 1440 PetscErrorCode ierr; 1441 PC_SysPFMG *ex = (PC_SysPFMG*) pc->data; 1442 Mat_HYPRESStruct *mx = (Mat_HYPRESStruct *)(pc->pmat->data); 1443 PetscBool flg; 1444 1445 PetscFunctionBegin; 1446 ierr = PetscTypeCompare((PetscObject)pc->pmat,MATHYPRESSTRUCT,&flg);CHKERRQ(ierr); 1447 if (!flg) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_INCOMP,"Must use MATHYPRESSTRUCT with this preconditioner"); 1448 1449 /* create the hypre sstruct solver object and set its information */ 1450 if (ex->ss_solver) { 1451 PetscStackCallHypre(0,HYPRE_SStructSysPFMGDestroy,(ex->ss_solver)); 1452 } 1453 PetscStackCallHypre(0,HYPRE_SStructSysPFMGCreate,(ex->hcomm,&ex->ss_solver)); 1454 ierr = PCSetFromOptions_SysPFMG(pc);CHKERRQ(ierr); 1455 PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetZeroGuess,(ex->ss_solver)); 1456 PetscStackCallHypre(0,HYPRE_SStructSysPFMGSetup,(ex->ss_solver,mx->ss_mat,mx->ss_b,mx->ss_x)); 1457 PetscFunctionReturn(0); 1458 } 1459 1460 1461 /*MC 1462 PCSysPFMG - the hypre SysPFMG multigrid solver 1463 1464 Level: advanced 1465 1466 Options Database: 1467 + -pc_syspfmg_its <its> number of iterations of SysPFMG to use as preconditioner 1468 . -pc_syspfmg_num_pre_relax <steps> number of smoothing steps before coarse grid 1469 . -pc_syspfmg_num_post_relax <steps> number of smoothing steps after coarse grid 1470 . -pc_syspfmg_tol <tol> tolerance of SysPFMG 1471 . -pc_syspfmg_relax_type -relaxation type for the up and down cycles, one of Weighted-Jacobi,Red/Black-Gauss-Seidel 1472 1473 Notes: This is for CELL-centered descretizations 1474 1475 This must be used with the MATHYPRESSTRUCT matrix type. 1476 This is less general than in hypre, it supports only one part, and one block per process defined by a PETSc DMDA. 1477 Also, only cell-centered variables. 1478 1479 .seealso: PCMG, MATHYPRESSTRUCT 1480 M*/ 1481 1482 EXTERN_C_BEGIN 1483 #undef __FUNCT__ 1484 #define __FUNCT__ "PCCreate_SysPFMG" 1485 PetscErrorCode PCCreate_SysPFMG(PC pc) 1486 { 1487 PetscErrorCode ierr; 1488 PC_SysPFMG *ex; 1489 1490 PetscFunctionBegin; 1491 ierr = PetscNew(PC_SysPFMG,&ex);CHKERRQ(ierr);\ 1492 pc->data = ex; 1493 1494 ex->its = 1; 1495 ex->tol = 1.e-8; 1496 ex->relax_type = 1; 1497 ex->num_pre_relax = 1; 1498 ex->num_post_relax = 1; 1499 1500 pc->ops->setfromoptions = PCSetFromOptions_SysPFMG; 1501 pc->ops->view = PCView_SysPFMG; 1502 pc->ops->destroy = PCDestroy_SysPFMG; 1503 pc->ops->apply = PCApply_SysPFMG; 1504 pc->ops->applyrichardson = PCApplyRichardson_SysPFMG; 1505 pc->ops->setup = PCSetUp_SysPFMG; 1506 ierr = MPI_Comm_dup(((PetscObject)pc)->comm,&(ex->hcomm));CHKERRQ(ierr); 1507 PetscStackCallHypre(0,HYPRE_SStructSysPFMGCreate,(ex->hcomm,&ex->ss_solver)); 1508 PetscFunctionReturn(0); 1509 } 1510 EXTERN_C_END 1511