1 #define PETSCKSP_DLL 2 3 /* 4 Provides an interface to the LLNL package hypre 5 */ 6 #include "private/pcimpl.h" /*I "petscpc.h" I*/ 7 EXTERN_C_BEGIN 8 #include "HYPRE.h" 9 #include "IJ_mv.h" 10 #include "parcsr_ls.h" 11 EXTERN_C_END 12 13 EXTERN PetscErrorCode MatHYPRE_IJMatrixCreate(Mat,HYPRE_IJMatrix*); 14 EXTERN PetscErrorCode MatHYPRE_IJMatrixCopy(Mat,HYPRE_IJMatrix); 15 EXTERN PetscErrorCode VecHYPRE_IJVectorCreate(Vec,HYPRE_IJVector*); 16 17 /* 18 Private context (data structure) for the preconditioner. 19 */ 20 typedef struct { 21 HYPRE_Solver hsolver; 22 HYPRE_IJMatrix ij; 23 HYPRE_IJVector b,x; 24 25 PetscErrorCode (*destroy)(HYPRE_Solver); 26 PetscErrorCode (*solve)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector); 27 PetscErrorCode (*setup)(HYPRE_Solver,HYPRE_ParCSRMatrix,HYPRE_ParVector,HYPRE_ParVector); 28 29 MPI_Comm comm_hypre; 30 char *hypre_type; 31 32 /* options for Pilut and BoomerAMG*/ 33 int maxiter; 34 double tol; 35 36 /* options for Pilut */ 37 int factorrowsize; 38 39 /* options for ParaSails */ 40 int nlevels; 41 double threshhold; 42 double filter; 43 int sym; 44 double loadbal; 45 int logging; 46 int ruse; 47 int symt; 48 49 /* options for Euclid */ 50 PetscTruth bjilu; 51 int levels; 52 53 /* options for Euclid and BoomerAMG */ 54 PetscTruth printstatistics; 55 56 /* options for BoomerAMG */ 57 int cycletype; 58 int maxlevels; 59 double strongthreshold; 60 double maxrowsum; 61 int gridsweeps[4]; 62 int coarsentype; 63 int measuretype; 64 int relaxtype[4]; 65 double relaxweight; 66 double outerrelaxweight; 67 int relaxorder; 68 double truncfactor; 69 PetscTruth applyrichardson; 70 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 int hierr; 84 85 PetscFunctionBegin; 86 if (!jac->hypre_type) { 87 ierr = PCHYPRESetType(pc,"pilut");CHKERRQ(ierr); 88 } 89 #if 1 90 if (!pc->setupcalled) { 91 /* create the matrix and vectors the first time through */ 92 Vec x,b; 93 ierr = MatHYPRE_IJMatrixCreate(pc->pmat,&jac->ij);CHKERRQ(ierr); 94 ierr = MatGetVecs(pc->pmat,&x,&b);CHKERRQ(ierr); 95 ierr = VecHYPRE_IJVectorCreate(x,&jac->x);CHKERRQ(ierr); 96 ierr = VecHYPRE_IJVectorCreate(b,&jac->b);CHKERRQ(ierr); 97 ierr = VecDestroy(x);CHKERRQ(ierr); 98 ierr = VecDestroy(b);CHKERRQ(ierr); 99 } else if (pc->flag != SAME_NONZERO_PATTERN) { 100 /* rebuild the matrix from scratch */ 101 ierr = HYPRE_IJMatrixDestroy(jac->ij);CHKERRQ(ierr); 102 ierr = MatHYPRE_IJMatrixCreate(pc->pmat,&jac->ij);CHKERRQ(ierr); 103 } 104 #else 105 if (!jac->ij) { /* create the matrix the first time through */ 106 ierr = MatHYPRE_IJMatrixCreate(pc->pmat,&jac->ij);CHKERRQ(ierr); 107 } 108 if (!jac->b) { /* create the vectors the first time through */ 109 Vec x,b; 110 ierr = MatGetVecs(pc->pmat,&x,&b);CHKERRQ(ierr); 111 ierr = VecHYPRE_IJVectorCreate(x,&jac->x);CHKERRQ(ierr); 112 ierr = VecHYPRE_IJVectorCreate(b,&jac->b);CHKERRQ(ierr); 113 ierr = VecDestroy(x);CHKERRQ(ierr); 114 ierr = VecDestroy(b);CHKERRQ(ierr); 115 } 116 #endif 117 /* special case for BoomerAMG */ 118 if (jac->setup == HYPRE_BoomerAMGSetup) { 119 ierr = MatGetBlockSize(pc->pmat,&bs);CHKERRQ(ierr); 120 if (bs > 1) { 121 ierr = HYPRE_BoomerAMGSetNumFunctions(jac->hsolver,bs);CHKERRQ(ierr); 122 } 123 }; 124 ierr = MatHYPRE_IJMatrixCopy(pc->pmat,jac->ij);CHKERRQ(ierr); 125 ierr = HYPRE_IJMatrixGetObject(jac->ij,(void**)&hmat);CHKERRQ(ierr); 126 ierr = HYPRE_IJVectorGetObject(jac->b,(void**)&bv);CHKERRQ(ierr); 127 ierr = HYPRE_IJVectorGetObject(jac->x,(void**)&xv);CHKERRQ(ierr); 128 hierr = (*jac->setup)(jac->hsolver,hmat,bv,xv); 129 if (hierr) SETERRQ1(PETSC_ERR_LIB,"Error in HYPRE setup, error code %d",hierr); 130 PetscFunctionReturn(0); 131 } 132 133 /* 134 Replaces the address where the HYPRE vector points to its data with the address of 135 PETSc's data. Saves the old address so it can be reset when we are finished with it. 136 Allows use to get the data into a HYPRE vector without the cost of memcopies 137 */ 138 #define HYPREReplacePointer(b,newvalue,savedvalue) {\ 139 hypre_ParVector *par_vector = (hypre_ParVector *)hypre_IJVectorObject(((hypre_IJVector*)b));\ 140 hypre_Vector *local_vector = hypre_ParVectorLocalVector(par_vector);\ 141 savedvalue = local_vector->data;\ 142 local_vector->data = newvalue;} 143 144 #undef __FUNCT__ 145 #define __FUNCT__ "PCApply_HYPRE" 146 static PetscErrorCode PCApply_HYPRE(PC pc,Vec b,Vec x) 147 { 148 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 149 PetscErrorCode ierr; 150 HYPRE_ParCSRMatrix hmat; 151 PetscScalar *bv,*xv; 152 HYPRE_ParVector jbv,jxv; 153 PetscScalar *sbv,*sxv; 154 int hierr; 155 156 PetscFunctionBegin; 157 if (!jac->applyrichardson) {ierr = VecSet(x,0.0);CHKERRQ(ierr);} 158 ierr = VecGetArray(b,&bv);CHKERRQ(ierr); 159 ierr = VecGetArray(x,&xv);CHKERRQ(ierr); 160 HYPREReplacePointer(jac->b,bv,sbv); 161 HYPREReplacePointer(jac->x,xv,sxv); 162 163 ierr = HYPRE_IJMatrixGetObject(jac->ij,(void**)&hmat);CHKERRQ(ierr); 164 ierr = HYPRE_IJVectorGetObject(jac->b,(void**)&jbv);CHKERRQ(ierr); 165 ierr = HYPRE_IJVectorGetObject(jac->x,(void**)&jxv);CHKERRQ(ierr); 166 hierr = (*jac->solve)(jac->hsolver,hmat,jbv,jxv); 167 /* error code of 1 in BoomerAMG merely means convergence not achieved */ 168 if (hierr && (hierr != 1 || jac->solve != HYPRE_BoomerAMGSolve)) SETERRQ1(PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",hierr); 169 if (hierr) hypre__global_error = 0; 170 171 HYPREReplacePointer(jac->b,sbv,bv); 172 HYPREReplacePointer(jac->x,sxv,xv); 173 ierr = VecRestoreArray(x,&xv);CHKERRQ(ierr); 174 ierr = VecRestoreArray(b,&bv);CHKERRQ(ierr); 175 PetscFunctionReturn(0); 176 } 177 178 #undef __FUNCT__ 179 #define __FUNCT__ "PCDestroy_HYPRE" 180 static PetscErrorCode PCDestroy_HYPRE(PC pc) 181 { 182 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 183 PetscErrorCode ierr; 184 185 PetscFunctionBegin; 186 if (jac->ij) { ierr = HYPRE_IJMatrixDestroy(jac->ij);CHKERRQ(ierr); } 187 if (jac->b) { ierr = HYPRE_IJVectorDestroy(jac->b);CHKERRQ(ierr); } 188 if (jac->x) { ierr = HYPRE_IJVectorDestroy(jac->x);CHKERRQ(ierr); } 189 if (jac->destroy) { ierr = (*jac->destroy)(jac->hsolver);CHKERRQ(ierr); } 190 ierr = PetscStrfree(jac->hypre_type);CHKERRQ(ierr); 191 if (jac->comm_hypre != MPI_COMM_NULL) { ierr = MPI_Comm_free(&(jac->comm_hypre));CHKERRQ(ierr);} 192 ierr = PetscFree(jac);CHKERRQ(ierr); 193 194 ierr = PetscObjectChangeTypeName((PetscObject)pc,0);CHKERRQ(ierr); 195 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPRESetType_C","",PETSC_NULL);CHKERRQ(ierr); 196 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPREGetType_C","",PETSC_NULL);CHKERRQ(ierr); 197 PetscFunctionReturn(0); 198 } 199 200 /* --------------------------------------------------------------------------------------------*/ 201 #undef __FUNCT__ 202 #define __FUNCT__ "PCSetFromOptions_HYPRE_Pilut" 203 static PetscErrorCode PCSetFromOptions_HYPRE_Pilut(PC pc) 204 { 205 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 206 PetscErrorCode ierr; 207 PetscTruth flag; 208 209 PetscFunctionBegin; 210 ierr = PetscOptionsHead("HYPRE Pilut Options");CHKERRQ(ierr); 211 ierr = PetscOptionsInt("-pc_hypre_pilut_maxiter","Number of iterations","None",jac->maxiter,&jac->maxiter,&flag);CHKERRQ(ierr); 212 if (flag) { 213 ierr = HYPRE_ParCSRPilutSetMaxIter(jac->hsolver,jac->maxiter);CHKERRQ(ierr); 214 } 215 ierr = PetscOptionsReal("-pc_hypre_pilut_tol","Drop tolerance","None",jac->tol,&jac->tol,&flag);CHKERRQ(ierr); 216 if (flag) { 217 ierr = HYPRE_ParCSRPilutSetDropTolerance(jac->hsolver,jac->tol);CHKERRQ(ierr); 218 } 219 ierr = PetscOptionsInt("-pc_hypre_pilut_factorrowsize","FactorRowSize","None",jac->factorrowsize,&jac->factorrowsize,&flag);CHKERRQ(ierr); 220 if (flag) { 221 ierr = HYPRE_ParCSRPilutSetFactorRowSize(jac->hsolver,jac->factorrowsize);CHKERRQ(ierr); 222 } 223 ierr = PetscOptionsTail();CHKERRQ(ierr); 224 PetscFunctionReturn(0); 225 } 226 227 #undef __FUNCT__ 228 #define __FUNCT__ "PCView_HYPRE_Pilut" 229 static PetscErrorCode PCView_HYPRE_Pilut(PC pc,PetscViewer viewer) 230 { 231 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 232 PetscErrorCode ierr; 233 PetscTruth iascii; 234 235 PetscFunctionBegin; 236 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 237 if (iascii) { 238 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut preconditioning\n");CHKERRQ(ierr); 239 if (jac->maxiter != PETSC_DEFAULT) { 240 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: maximum number of iterations %d\n",jac->maxiter);CHKERRQ(ierr); 241 } else { 242 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: default maximum number of iterations \n");CHKERRQ(ierr); 243 } 244 if (jac->tol != PETSC_DEFAULT) { 245 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: drop tolerance %G\n",jac->tol);CHKERRQ(ierr); 246 } else { 247 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: default drop tolerance \n");CHKERRQ(ierr); 248 } 249 if (jac->factorrowsize != PETSC_DEFAULT) { 250 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: factor row size %d\n",jac->factorrowsize);CHKERRQ(ierr); 251 } else { 252 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Pilut: default factor row size \n");CHKERRQ(ierr); 253 } 254 } 255 PetscFunctionReturn(0); 256 } 257 258 /* --------------------------------------------------------------------------------------------*/ 259 #undef __FUNCT__ 260 #define __FUNCT__ "PCSetFromOptions_HYPRE_Euclid" 261 static PetscErrorCode PCSetFromOptions_HYPRE_Euclid(PC pc) 262 { 263 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 264 PetscErrorCode ierr; 265 PetscTruth flag; 266 char *args[2]; 267 268 PetscFunctionBegin; 269 ierr = PetscOptionsHead("HYPRE Euclid Options");CHKERRQ(ierr); 270 ierr = PetscOptionsInt("-pc_hypre_euclid_levels","Number of levels of fill ILU(k)","None",jac->levels,&jac->levels,&flag);CHKERRQ(ierr); 271 if (flag) { 272 char levels[16]; 273 if (jac->levels < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %d must be nonegative",jac->levels); 274 sprintf(levels,"%d",jac->levels); 275 args[0] = (char*)"-level"; args[1] = levels; 276 ierr = HYPRE_EuclidSetParams(jac->hsolver,2,args);CHKERRQ(ierr); 277 } 278 ierr = PetscOptionsTruth("-pc_hypre_euclid_bj","Use block Jacobi ILU(k)","None",jac->bjilu,&jac->bjilu,PETSC_NULL);CHKERRQ(ierr); 279 if (jac->bjilu) { 280 args[0] =(char*) "-bj"; args[1] = (char*)"1"; 281 ierr = HYPRE_EuclidSetParams(jac->hsolver,2,args);CHKERRQ(ierr); 282 } 283 284 ierr = PetscOptionsTruth("-pc_hypre_euclid_print_statistics","Print statistics","None",jac->printstatistics,&jac->printstatistics,PETSC_NULL);CHKERRQ(ierr); 285 if (jac->printstatistics) { 286 args[0] = (char*)"-eu_stats"; args[1] = (char*)"1"; 287 ierr = HYPRE_EuclidSetParams(jac->hsolver,2,args);CHKERRQ(ierr); 288 args[0] = (char*)"-eu_mem"; args[1] = (char*)"1"; 289 ierr = HYPRE_EuclidSetParams(jac->hsolver,2,args);CHKERRQ(ierr); 290 } 291 ierr = PetscOptionsTail();CHKERRQ(ierr); 292 PetscFunctionReturn(0); 293 } 294 295 #undef __FUNCT__ 296 #define __FUNCT__ "PCView_HYPRE_Euclid" 297 static PetscErrorCode PCView_HYPRE_Euclid(PC pc,PetscViewer viewer) 298 { 299 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 300 PetscErrorCode ierr; 301 PetscTruth iascii; 302 303 PetscFunctionBegin; 304 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 305 if (iascii) { 306 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Euclid preconditioning\n");CHKERRQ(ierr); 307 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Euclid: number of levels %d\n",jac->levels);CHKERRQ(ierr); 308 if (jac->bjilu) { 309 ierr = PetscViewerASCIIPrintf(viewer," HYPRE Euclid: Using block Jacobi ILU instead of parallel ILU\n");CHKERRQ(ierr); 310 } 311 } 312 PetscFunctionReturn(0); 313 } 314 315 /* --------------------------------------------------------------------------------------------*/ 316 317 #undef __FUNCT__ 318 #define __FUNCT__ "PCApplyTranspose_HYPRE_BoomerAMG" 319 static PetscErrorCode PCApplyTranspose_HYPRE_BoomerAMG(PC pc,Vec b,Vec x) 320 { 321 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 322 PetscErrorCode ierr; 323 HYPRE_ParCSRMatrix hmat; 324 PetscScalar *bv,*xv; 325 HYPRE_ParVector jbv,jxv; 326 PetscScalar *sbv,*sxv; 327 int hierr; 328 329 PetscFunctionBegin; 330 ierr = VecSet(x,0.0);CHKERRQ(ierr); 331 ierr = VecGetArray(b,&bv);CHKERRQ(ierr); 332 ierr = VecGetArray(x,&xv);CHKERRQ(ierr); 333 HYPREReplacePointer(jac->b,bv,sbv); 334 HYPREReplacePointer(jac->x,xv,sxv); 335 336 ierr = HYPRE_IJMatrixGetObject(jac->ij,(void**)&hmat);CHKERRQ(ierr); 337 ierr = HYPRE_IJVectorGetObject(jac->b,(void**)&jbv);CHKERRQ(ierr); 338 ierr = HYPRE_IJVectorGetObject(jac->x,(void**)&jxv);CHKERRQ(ierr); 339 340 hierr = HYPRE_BoomerAMGSolveT(jac->hsolver,hmat,jbv,jxv); 341 /* error code of 1 in BoomerAMG merely means convergence not achieved */ 342 if (hierr && (hierr != 1)) SETERRQ1(PETSC_ERR_LIB,"Error in HYPRE solver, error code %d",hierr); 343 if (hierr) hypre__global_error = 0; 344 345 HYPREReplacePointer(jac->b,sbv,bv); 346 HYPREReplacePointer(jac->x,sxv,xv); 347 ierr = VecRestoreArray(x,&xv);CHKERRQ(ierr); 348 ierr = VecRestoreArray(b,&bv);CHKERRQ(ierr); 349 PetscFunctionReturn(0); 350 } 351 352 static const char *HYPREBoomerAMGCycleType[] = {"","V","W"}; 353 static const char *HYPREBoomerAMGCoarsenType[] = {"CLJP","Ruge-Stueben","","modifiedRuge-Stueben","","","Falgout"}; 354 static const char *HYPREBoomerAMGMeasureType[] = {"local","global"}; 355 static const char *HYPREBoomerAMGRelaxType[] = {"Jacobi","sequential-Gauss-Seidel","","SOR/Jacobi","backward-SOR/Jacobi","","symmetric-SOR/Jacobi","","","Gaussian-elimination"}; 356 357 #undef __FUNCT__ 358 #define __FUNCT__ "PCSetFromOptions_HYPRE_BoomerAMG" 359 static PetscErrorCode PCSetFromOptions_HYPRE_BoomerAMG(PC pc) 360 { 361 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 362 PetscErrorCode ierr; 363 int n,indx; 364 PetscTruth flg, tmp_truth; 365 double tmpdbl, twodbl[2]; 366 367 PetscFunctionBegin; 368 ierr = PetscOptionsHead("HYPRE BoomerAMG Options");CHKERRQ(ierr); 369 ierr = PetscOptionsEList("-pc_hypre_boomeramg_cycle_type","Cycle type","None",HYPREBoomerAMGCycleType,2,HYPREBoomerAMGCycleType[jac->cycletype],&indx,&flg);CHKERRQ(ierr); 370 if (flg) { 371 jac->cycletype = indx; 372 ierr = HYPRE_BoomerAMGSetCycleType(jac->hsolver,jac->cycletype);CHKERRQ(ierr); 373 } 374 ierr = PetscOptionsInt("-pc_hypre_boomeramg_max_levels","Number of levels (of grids) allowed","None",jac->maxlevels,&jac->maxlevels,&flg);CHKERRQ(ierr); 375 if (flg) { 376 if (jac->maxlevels < 2) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Number of levels %d must be at least two",jac->maxlevels); 377 ierr = HYPRE_BoomerAMGSetMaxLevels(jac->hsolver,jac->maxlevels);CHKERRQ(ierr); 378 } 379 ierr = PetscOptionsInt("-pc_hypre_boomeramg_max_iter","Maximum iterations used PER hypre call","None",jac->maxiter,&jac->maxiter,&flg);CHKERRQ(ierr); 380 if (flg) { 381 if (jac->maxiter < 1) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Number of iterations %d must be at least one",jac->maxiter); 382 ierr = HYPRE_BoomerAMGSetMaxIter(jac->hsolver,jac->maxiter);CHKERRQ(ierr); 383 } 384 ierr = PetscOptionsScalar("-pc_hypre_boomeramg_tol","Convergence tolerance PER hypre call","None",jac->tol,&jac->tol,&flg);CHKERRQ(ierr); 385 if (flg) { 386 if (jac->tol < 0.0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Tolerance %G must be great than or equal zero",jac->tol); 387 ierr = HYPRE_BoomerAMGSetTol(jac->hsolver,jac->tol);CHKERRQ(ierr); 388 } 389 390 ierr = PetscOptionsScalar("-pc_hypre_boomeramg_truncfactor","Truncation factor","None",jac->truncfactor,&jac->truncfactor,&flg);CHKERRQ(ierr); 391 if (flg) { 392 if (jac->truncfactor < 0.0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Truncation factor %G must be great than or equal zero",jac->truncfactor); 393 ierr = HYPRE_BoomerAMGSetTruncFactor(jac->hsolver,jac->truncfactor);CHKERRQ(ierr); 394 } 395 396 ierr = PetscOptionsScalar("-pc_hypre_boomeramg_strong_threshold","Threshold for being strongly connected","None",jac->strongthreshold,&jac->strongthreshold,&flg);CHKERRQ(ierr); 397 if (flg) { 398 if (jac->strongthreshold < 0.0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Strong threshold %G must be great than or equal zero",jac->strongthreshold); 399 ierr = HYPRE_BoomerAMGSetStrongThreshold(jac->hsolver,jac->strongthreshold);CHKERRQ(ierr); 400 } 401 ierr = PetscOptionsScalar("-pc_hypre_boomeramg_max_row_sum","Maximum row sum","None",jac->maxrowsum,&jac->maxrowsum,&flg);CHKERRQ(ierr); 402 if (flg) { 403 if (jac->maxrowsum < 0.0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Maximum row sum %G must be greater than zero",jac->maxrowsum); 404 if (jac->maxrowsum > 1.0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Maximum row sum %G must be less than or equal one",jac->maxrowsum); 405 ierr = HYPRE_BoomerAMGSetMaxRowSum(jac->hsolver,jac->maxrowsum);CHKERRQ(ierr); 406 } 407 408 /* Grid sweeps */ 409 ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_all","Number of sweeps for all grid levels (fine, up, and down)","None",jac->gridsweeps[0],&indx,&flg);CHKERRQ(ierr); 410 if (flg) { 411 ierr = HYPRE_BoomerAMGSetNumSweeps(jac->hsolver,indx);CHKERRQ(ierr); 412 /* modify the jac structure so we can view the updated options with PC_View */ 413 jac->gridsweeps[0] = indx; 414 jac->gridsweeps[1] = jac->gridsweeps[2] = jac->gridsweeps[0]; 415 jac->gridsweeps[3] = 1; /*The coarse level is not affected by this function - hypre code sets to 1*/ 416 } 417 ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_fine","Number of sweeps for the fine level","None",jac->gridsweeps[0],&indx,&flg);CHKERRQ(ierr); 418 if (flg) { 419 ierr = HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver,indx, 0);CHKERRQ(ierr); 420 jac->gridsweeps[0] = indx; 421 } 422 ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_down","Number of sweeps for the down cycles","None",jac->gridsweeps[2],&indx,&flg);CHKERRQ(ierr); 423 if (flg) { 424 ierr = HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver,indx, 1);CHKERRQ(ierr); 425 jac->gridsweeps[1] = indx; 426 } 427 ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_up","Number of sweeps for the up cycles","None",jac->gridsweeps[1],&indx,&flg);CHKERRQ(ierr); 428 if (flg) { 429 ierr = HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver,indx, 2);CHKERRQ(ierr); 430 jac->gridsweeps[2] = indx; 431 } 432 ierr = PetscOptionsInt("-pc_hypre_boomeramg_grid_sweeps_coarse","Number of sweeps for the coarse level","None",jac->gridsweeps[3],&indx,&flg);CHKERRQ(ierr); 433 if (flg) { 434 ierr = HYPRE_BoomerAMGSetCycleNumSweeps(jac->hsolver,indx, 3);CHKERRQ(ierr); 435 jac->gridsweeps[3] = indx; 436 } 437 438 /* Relax type */ 439 ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_all","Relax type for fine, up, and down cycles (coarse level set to gaussian elimination)","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[3],&indx,&flg);CHKERRQ(ierr); 440 if (flg) { 441 jac->relaxtype[0] = jac->relaxtype[1] = jac->relaxtype[2] = indx; 442 jac->relaxtype[3] = 9; /* hypre code sets coarse grid to 9 (G.E.)*/ 443 ierr = HYPRE_BoomerAMGSetRelaxType(jac->hsolver, indx);CHKERRQ(ierr); 444 } 445 ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_fine","Relax type on fine grid","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[3],&indx,&flg);CHKERRQ(ierr); 446 if (flg) { 447 jac->relaxtype[0] = indx; 448 ierr = HYPRE_BoomerAMGSetCycleRelaxType(jac->hsolver, indx, 0);CHKERRQ(ierr); 449 } 450 ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_down","Relax type for the down cycles","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[3],&indx,&flg);CHKERRQ(ierr); 451 if (flg) { 452 jac->relaxtype[1] = indx; 453 ierr = HYPRE_BoomerAMGSetCycleRelaxType(jac->hsolver, indx, 1);CHKERRQ(ierr); 454 } 455 ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_up","Relax type for the up cycles","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[3],&indx,&flg);CHKERRQ(ierr); 456 if (flg) { 457 jac->relaxtype[2] = indx; 458 ierr = HYPRE_BoomerAMGSetCycleRelaxType(jac->hsolver, indx, 2);CHKERRQ(ierr); 459 } 460 ierr = PetscOptionsEList("-pc_hypre_boomeramg_relax_type_coarse","Relax type on coarse grid","None",HYPREBoomerAMGRelaxType,10,HYPREBoomerAMGRelaxType[9],&indx,&flg);CHKERRQ(ierr); 461 if (flg) { 462 jac->relaxtype[3] = indx; 463 ierr = HYPRE_BoomerAMGSetCycleRelaxType(jac->hsolver, indx, 3);CHKERRQ(ierr); 464 } 465 466 /* Relaxation Weight */ 467 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); 468 if (flg) { 469 ierr = HYPRE_BoomerAMGSetRelaxWt(jac->hsolver,tmpdbl);CHKERRQ(ierr); 470 jac->relaxweight = tmpdbl; 471 } 472 473 n=2; 474 twodbl[0] = twodbl[1] = 1.0; 475 ierr = PetscOptionsRealArray("-pc_hypre_boomeramg_relax_weight_level","Set the relaxation weight for a particular level (weight,level)","None",twodbl, &n, &flg);CHKERRQ(ierr); 476 if (flg) { 477 if (n == 2) { 478 indx = (int)PetscAbsReal(twodbl[1]); 479 ierr = HYPRE_BoomerAMGSetLevelRelaxWt(jac->hsolver,twodbl[0],indx);CHKERRQ(ierr); 480 } else { 481 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Relax weight level: you must provide 2 values separated by a comma (and no space), you provided %d",n); 482 } 483 } 484 485 /* Outer relaxation Weight */ 486 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); 487 if (flg) { 488 ierr = HYPRE_BoomerAMGSetOuterWt( jac->hsolver, tmpdbl);CHKERRQ(ierr); 489 jac->outerrelaxweight = tmpdbl; 490 } 491 492 n=2; 493 twodbl[0] = twodbl[1] = 1.0; 494 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); 495 if (flg) { 496 if (n == 2) { 497 indx = (int)PetscAbsReal(twodbl[1]); 498 ierr = HYPRE_BoomerAMGSetLevelOuterWt( jac->hsolver, twodbl[0], indx);CHKERRQ(ierr); 499 } else { 500 SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Relax weight outer level: You must provide 2 values separated by a comma (and no space), you provided %d",n); 501 } 502 } 503 504 /* the Relax Order */ 505 /* ierr = PetscOptionsName("-pc_hypre_boomeramg_no_CF", "Do not use CF-relaxation", "None", &flg);CHKERRQ(ierr); */ 506 ierr = PetscOptionsTruth( "-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 ierr = HYPRE_BoomerAMGSetRelaxOrder(jac->hsolver, jac->relaxorder);CHKERRQ(ierr); 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 ierr = HYPRE_BoomerAMGSetMeasureType(jac->hsolver,jac->measuretype);CHKERRQ(ierr); 516 } 517 ierr = PetscOptionsEList("-pc_hypre_boomeramg_coarsen_type","Coarsen type","None",HYPREBoomerAMGCoarsenType,7,HYPREBoomerAMGCoarsenType[6],&indx,&flg);CHKERRQ(ierr); 518 if (flg) { 519 jac->coarsentype = indx; 520 ierr = HYPRE_BoomerAMGSetCoarsenType(jac->hsolver,jac->coarsentype);CHKERRQ(ierr); 521 } 522 ierr = PetscOptionsName("-pc_hypre_boomeramg_print_statistics","Print statistics","None",&flg);CHKERRQ(ierr); 523 if (flg) { 524 int level=3; 525 jac->printstatistics = PETSC_TRUE; 526 ierr = PetscOptionsInt("-pc_hypre_boomeramg_print_statistics","Print statistics","None",level,&level,PETSC_NULL);CHKERRQ(ierr); 527 ierr = HYPRE_BoomerAMGSetPrintLevel(jac->hsolver,level);CHKERRQ(ierr); 528 ierr = HYPRE_BoomerAMGSetDebugFlag(jac->hsolver,level);CHKERRQ(ierr); 529 } 530 ierr = PetscOptionsTail();CHKERRQ(ierr); 531 PetscFunctionReturn(0); 532 } 533 534 #undef __FUNCT__ 535 #define __FUNCT__ "PCApplyRichardson_HYPRE_BoomerAMG" 536 static PetscErrorCode PCApplyRichardson_HYPRE_BoomerAMG(PC pc,Vec b,Vec y,Vec w,PetscReal rtol,PetscReal abstol, PetscReal dtol,PetscInt its) 537 { 538 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 539 PetscErrorCode ierr; 540 541 PetscFunctionBegin; 542 ierr = HYPRE_BoomerAMGSetMaxIter(jac->hsolver,its*jac->maxiter);CHKERRQ(ierr); 543 ierr = HYPRE_BoomerAMGSetTol(jac->hsolver,PetscMin(rtol,jac->tol));CHKERRQ(ierr); 544 jac->applyrichardson = PETSC_TRUE; 545 ierr = PCApply_HYPRE(pc,b,y);CHKERRQ(ierr); 546 jac->applyrichardson = PETSC_FALSE; 547 ierr = HYPRE_BoomerAMGSetTol(jac->hsolver,jac->tol);CHKERRQ(ierr); 548 ierr = HYPRE_BoomerAMGSetMaxIter(jac->hsolver,jac->maxiter);CHKERRQ(ierr); 549 PetscFunctionReturn(0); 550 } 551 552 553 #undef __FUNCT__ 554 #define __FUNCT__ "PCView_HYPRE_BoomerAMG" 555 static PetscErrorCode PCView_HYPRE_BoomerAMG(PC pc,PetscViewer viewer) 556 { 557 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 558 PetscErrorCode ierr; 559 PetscTruth iascii; 560 561 PetscFunctionBegin; 562 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 563 if (iascii) { 564 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG preconditioning\n");CHKERRQ(ierr); 565 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Cycle type %s\n",HYPREBoomerAMGCycleType[jac->cycletype]);CHKERRQ(ierr); 566 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Maximum number of levels %d\n",jac->maxlevels);CHKERRQ(ierr); 567 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Maximum number of iterations PER hypre call %d\n",jac->maxiter);CHKERRQ(ierr); 568 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Convergence tolerance PER hypre call %G\n",jac->tol);CHKERRQ(ierr); 569 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Threshold for strong coupling %G\n",jac->strongthreshold);CHKERRQ(ierr); 570 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Maximum row sums %G\n",jac->maxrowsum);CHKERRQ(ierr); 571 572 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps on fine grid %d\n",jac->gridsweeps[0]);CHKERRQ(ierr); 573 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps down %d\n",jac->gridsweeps[1]);CHKERRQ(ierr); 574 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps up %d\n",jac->gridsweeps[2]);CHKERRQ(ierr); 575 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Sweeps on coarse %d\n",jac->gridsweeps[3]);CHKERRQ(ierr); 576 577 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax on fine grid %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[0]]);CHKERRQ(ierr); 578 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax down %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[1]]);CHKERRQ(ierr); 579 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax up %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[2]]);CHKERRQ(ierr); 580 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax on coarse %s\n",HYPREBoomerAMGRelaxType[jac->relaxtype[3]]);CHKERRQ(ierr); 581 582 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Relax weight (all) %G\n",jac->relaxweight);CHKERRQ(ierr); 583 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Outer relax weight (all) %G\n",jac->outerrelaxweight);CHKERRQ(ierr); 584 585 if (jac->relaxorder) { 586 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Using CF-relaxation\n");CHKERRQ(ierr); 587 } else { 588 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Not using CF-relaxation\n");CHKERRQ(ierr); 589 } 590 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Measure type %s\n",HYPREBoomerAMGMeasureType[jac->measuretype]);CHKERRQ(ierr); 591 ierr = PetscViewerASCIIPrintf(viewer," HYPRE BoomerAMG: Coarsen type %s\n",HYPREBoomerAMGCoarsenType[jac->coarsentype]);CHKERRQ(ierr); 592 } 593 PetscFunctionReturn(0); 594 } 595 596 /* --------------------------------------------------------------------------------------------*/ 597 #undef __FUNCT__ 598 #define __FUNCT__ "PCSetFromOptions_HYPRE_ParaSails" 599 static PetscErrorCode PCSetFromOptions_HYPRE_ParaSails(PC pc) 600 { 601 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 602 PetscErrorCode ierr; 603 int indx; 604 PetscTruth flag; 605 const char *symtlist[] = {"nonsymmetric","SPD","nonsymmetric,SPD"}; 606 607 PetscFunctionBegin; 608 ierr = PetscOptionsHead("HYPRE ParaSails Options");CHKERRQ(ierr); 609 ierr = PetscOptionsInt("-pc_hypre_parasails_nlevels","Number of number of levels","None",jac->nlevels,&jac->nlevels,0);CHKERRQ(ierr); 610 ierr = PetscOptionsReal("-pc_hypre_parasails_thresh","Threshold","None",jac->threshhold,&jac->threshhold,&flag);CHKERRQ(ierr); 611 if (flag) { 612 ierr = HYPRE_ParaSailsSetParams(jac->hsolver,jac->threshhold,jac->nlevels);CHKERRQ(ierr); 613 } 614 615 ierr = PetscOptionsReal("-pc_hypre_parasails_filter","filter","None",jac->filter,&jac->filter,&flag);CHKERRQ(ierr); 616 if (flag) { 617 ierr = HYPRE_ParaSailsSetFilter(jac->hsolver,jac->filter);CHKERRQ(ierr); 618 } 619 620 ierr = PetscOptionsReal("-pc_hypre_parasails_loadbal","Load balance","None",jac->loadbal,&jac->loadbal,&flag);CHKERRQ(ierr); 621 if (flag) { 622 ierr = HYPRE_ParaSailsSetLoadbal(jac->hsolver,jac->loadbal);CHKERRQ(ierr); 623 } 624 625 ierr = PetscOptionsTruth("-pc_hypre_parasails_logging","Print info to screen","None",(PetscTruth)jac->logging,(PetscTruth*)&jac->logging,&flag);CHKERRQ(ierr); 626 if (flag) { 627 ierr = HYPRE_ParaSailsSetLogging(jac->hsolver,jac->logging);CHKERRQ(ierr); 628 } 629 630 ierr = PetscOptionsTruth("-pc_hypre_parasails_reuse","Reuse nonzero pattern in preconditioner","None",(PetscTruth)jac->ruse,(PetscTruth*)&jac->ruse,&flag);CHKERRQ(ierr); 631 if (flag) { 632 ierr = HYPRE_ParaSailsSetReuse(jac->hsolver,jac->ruse);CHKERRQ(ierr); 633 } 634 635 ierr = PetscOptionsEList("-pc_hypre_parasails_sym","Symmetry of matrix and preconditioner","None",symtlist,3,symtlist[0],&indx,&flag);CHKERRQ(ierr); 636 if (flag) { 637 jac->symt = indx; 638 ierr = HYPRE_ParaSailsSetSym(jac->hsolver,jac->symt);CHKERRQ(ierr); 639 } 640 641 ierr = PetscOptionsTail();CHKERRQ(ierr); 642 PetscFunctionReturn(0); 643 } 644 645 #undef __FUNCT__ 646 #define __FUNCT__ "PCView_HYPRE_ParaSails" 647 static PetscErrorCode PCView_HYPRE_ParaSails(PC pc,PetscViewer viewer) 648 { 649 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 650 PetscErrorCode ierr; 651 PetscTruth iascii; 652 const char *symt = 0;; 653 654 PetscFunctionBegin; 655 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 656 if (iascii) { 657 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails preconditioning\n");CHKERRQ(ierr); 658 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: nlevels %d\n",jac->nlevels);CHKERRQ(ierr); 659 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: threshold %G\n",jac->threshhold);CHKERRQ(ierr); 660 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: filter %G\n",jac->filter);CHKERRQ(ierr); 661 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: load balance %G\n",jac->loadbal);CHKERRQ(ierr); 662 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: reuse nonzero structure %s\n",PetscTruths[jac->ruse]);CHKERRQ(ierr); 663 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: print info to screen %s\n",PetscTruths[jac->logging]);CHKERRQ(ierr); 664 if (!jac->symt) { 665 symt = "nonsymmetric matrix and preconditioner"; 666 } else if (jac->symt == 1) { 667 symt = "SPD matrix and preconditioner"; 668 } else if (jac->symt == 2) { 669 symt = "nonsymmetric matrix but SPD preconditioner"; 670 } else { 671 SETERRQ1(PETSC_ERR_ARG_WRONG,"Unknown HYPRE ParaSails symmetric option %d",jac->symt); 672 } 673 ierr = PetscViewerASCIIPrintf(viewer," HYPRE ParaSails: %s\n",symt);CHKERRQ(ierr); 674 } 675 PetscFunctionReturn(0); 676 } 677 /* ---------------------------------------------------------------------------------*/ 678 679 EXTERN_C_BEGIN 680 #undef __FUNCT__ 681 #define __FUNCT__ "PCHYPREGetType_HYPRE" 682 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPREGetType_HYPRE(PC pc,const char *name[]) 683 { 684 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 685 686 PetscFunctionBegin; 687 *name = jac->hypre_type; 688 PetscFunctionReturn(0); 689 } 690 EXTERN_C_END 691 692 EXTERN_C_BEGIN 693 #undef __FUNCT__ 694 #define __FUNCT__ "PCHYPRESetType_HYPRE" 695 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPRESetType_HYPRE(PC pc,const char name[]) 696 { 697 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 698 PetscErrorCode ierr; 699 PetscTruth flag; 700 701 PetscFunctionBegin; 702 if (jac->hypre_type) { 703 ierr = PetscStrcmp(jac->hypre_type,name,&flag);CHKERRQ(ierr); 704 if (!flag) SETERRQ(PETSC_ERR_ORDER,"Cannot reset the HYPRE preconditioner type once it has been set"); 705 PetscFunctionReturn(0); 706 } else { 707 ierr = PetscStrallocpy(name, &jac->hypre_type);CHKERRQ(ierr); 708 } 709 710 jac->maxiter = PETSC_DEFAULT; 711 jac->tol = PETSC_DEFAULT; 712 jac->printstatistics = PetscLogPrintInfo; 713 714 ierr = PetscStrcmp("pilut",jac->hypre_type,&flag);CHKERRQ(ierr); 715 if (flag) { 716 ierr = HYPRE_ParCSRPilutCreate(jac->comm_hypre,&jac->hsolver); 717 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Pilut; 718 pc->ops->view = PCView_HYPRE_Pilut; 719 jac->destroy = HYPRE_ParCSRPilutDestroy; 720 jac->setup = HYPRE_ParCSRPilutSetup; 721 jac->solve = HYPRE_ParCSRPilutSolve; 722 jac->factorrowsize = PETSC_DEFAULT; 723 PetscFunctionReturn(0); 724 } 725 ierr = PetscStrcmp("parasails",jac->hypre_type,&flag);CHKERRQ(ierr); 726 if (flag) { 727 ierr = HYPRE_ParaSailsCreate(jac->comm_hypre,&jac->hsolver); 728 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_ParaSails; 729 pc->ops->view = PCView_HYPRE_ParaSails; 730 jac->destroy = HYPRE_ParaSailsDestroy; 731 jac->setup = HYPRE_ParaSailsSetup; 732 jac->solve = HYPRE_ParaSailsSolve; 733 /* initialize */ 734 jac->nlevels = 1; 735 jac->threshhold = .1; 736 jac->filter = .1; 737 jac->loadbal = 0; 738 if (PetscLogPrintInfo) { 739 jac->logging = (int) PETSC_TRUE; 740 } else { 741 jac->logging = (int) PETSC_FALSE; 742 } 743 jac->ruse = (int) PETSC_FALSE; 744 jac->symt = 0; 745 ierr = HYPRE_ParaSailsSetParams(jac->hsolver,jac->threshhold,jac->nlevels);CHKERRQ(ierr); 746 ierr = HYPRE_ParaSailsSetFilter(jac->hsolver,jac->filter);CHKERRQ(ierr); 747 ierr = HYPRE_ParaSailsSetLoadbal(jac->hsolver,jac->loadbal);CHKERRQ(ierr); 748 ierr = HYPRE_ParaSailsSetLogging(jac->hsolver,jac->logging);CHKERRQ(ierr); 749 ierr = HYPRE_ParaSailsSetReuse(jac->hsolver,jac->ruse);CHKERRQ(ierr); 750 ierr = HYPRE_ParaSailsSetSym(jac->hsolver,jac->symt);CHKERRQ(ierr); 751 PetscFunctionReturn(0); 752 } 753 ierr = PetscStrcmp("euclid",jac->hypre_type,&flag);CHKERRQ(ierr); 754 if (flag) { 755 ierr = HYPRE_EuclidCreate(jac->comm_hypre,&jac->hsolver); 756 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_Euclid; 757 pc->ops->view = PCView_HYPRE_Euclid; 758 jac->destroy = HYPRE_EuclidDestroy; 759 jac->setup = HYPRE_EuclidSetup; 760 jac->solve = HYPRE_EuclidSolve; 761 /* initialization */ 762 jac->bjilu = PETSC_FALSE; 763 jac->levels = 1; 764 PetscFunctionReturn(0); 765 } 766 ierr = PetscStrcmp("boomeramg",jac->hypre_type,&flag);CHKERRQ(ierr); 767 if (flag) { 768 ierr = HYPRE_BoomerAMGCreate(&jac->hsolver); 769 pc->ops->setfromoptions = PCSetFromOptions_HYPRE_BoomerAMG; 770 pc->ops->view = PCView_HYPRE_BoomerAMG; 771 pc->ops->applytranspose = PCApplyTranspose_HYPRE_BoomerAMG; 772 pc->ops->applyrichardson = PCApplyRichardson_HYPRE_BoomerAMG; 773 jac->destroy = HYPRE_BoomerAMGDestroy; 774 jac->setup = HYPRE_BoomerAMGSetup; 775 jac->solve = HYPRE_BoomerAMGSolve; 776 jac->applyrichardson = PETSC_FALSE; 777 /* these defaults match the hypre defaults */ 778 jac->cycletype = 1; 779 jac->maxlevels = 25; 780 jac->maxiter = 1; 781 jac->tol = 1.e-7; 782 jac->truncfactor = 0.0; 783 jac->strongthreshold = .25; 784 jac->maxrowsum = .9; 785 jac->coarsentype = 6; 786 jac->measuretype = 0; 787 jac->gridsweeps[0] = jac->gridsweeps[1] = jac->gridsweeps[2] = jac->gridsweeps[3] = 1; 788 jac->relaxtype[0] = jac->relaxtype[1] = jac->relaxtype[2] = 3; 789 jac->relaxtype[3] = 9; 790 jac->relaxweight = 1.0; 791 jac->outerrelaxweight = 1.0; 792 jac->relaxorder = 1; 793 ierr = HYPRE_BoomerAMGSetCycleType(jac->hsolver,jac->cycletype);CHKERRQ(ierr); 794 ierr = HYPRE_BoomerAMGSetMaxLevels(jac->hsolver,jac->maxlevels);CHKERRQ(ierr); 795 ierr = HYPRE_BoomerAMGSetMaxIter(jac->hsolver,jac->maxiter);CHKERRQ(ierr); 796 ierr = HYPRE_BoomerAMGSetTol(jac->hsolver,jac->tol);CHKERRQ(ierr); 797 ierr = HYPRE_BoomerAMGSetTruncFactor(jac->hsolver,jac->truncfactor);CHKERRQ(ierr); 798 ierr = HYPRE_BoomerAMGSetStrongThreshold(jac->hsolver,jac->strongthreshold);CHKERRQ(ierr); 799 ierr = HYPRE_BoomerAMGSetMaxRowSum(jac->hsolver,jac->maxrowsum);CHKERRQ(ierr); 800 ierr = HYPRE_BoomerAMGSetCoarsenType(jac->hsolver,jac->coarsentype);CHKERRQ(ierr); 801 ierr = HYPRE_BoomerAMGSetMeasureType(jac->hsolver,jac->measuretype);CHKERRQ(ierr); 802 ierr = HYPRE_BoomerAMGSetRelaxOrder(jac->hsolver, jac->relaxorder);CHKERRQ(ierr); 803 PetscFunctionReturn(0); 804 } 805 ierr = PetscStrfree(jac->hypre_type);CHKERRQ(ierr); 806 jac->hypre_type = PETSC_NULL; 807 SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown HYPRE preconditioner %s; Choices are pilut, parasails, euclid, boomeramg",name); 808 PetscFunctionReturn(0); 809 } 810 EXTERN_C_END 811 812 /* 813 It only gets here if the HYPRE type has not been set before the call to 814 ...SetFromOptions() which actually is most of the time 815 */ 816 #undef __FUNCT__ 817 #define __FUNCT__ "PCSetFromOptions_HYPRE" 818 static PetscErrorCode PCSetFromOptions_HYPRE(PC pc) 819 { 820 PC_HYPRE *jac = (PC_HYPRE*)pc->data; 821 PetscErrorCode ierr; 822 int indx; 823 const char *type[] = {"pilut","parasails","boomeramg","euclid"}; 824 PetscTruth flg; 825 826 PetscFunctionBegin; 827 ierr = PetscOptionsHead("HYPRE preconditioner options");CHKERRQ(ierr); 828 ierr = PetscOptionsEList("-pc_hypre_type","HYPRE preconditioner type","PCHYPRESetType",type,4,"pilut",&indx,&flg);CHKERRQ(ierr); 829 if (PetscOptionsPublishCount) { /* force the default if it was not yet set and user did not set with option */ 830 if (!flg && !jac->hypre_type) { 831 flg = PETSC_TRUE; 832 indx = 0; 833 } 834 } 835 if (flg) { 836 ierr = PCHYPRESetType_HYPRE(pc,type[indx]);CHKERRQ(ierr); 837 } 838 if (pc->ops->setfromoptions) { 839 ierr = pc->ops->setfromoptions(pc);CHKERRQ(ierr); 840 } 841 ierr = PetscOptionsTail();CHKERRQ(ierr); 842 PetscFunctionReturn(0); 843 } 844 845 #undef __FUNCT__ 846 #define __FUNCT__ "PCHYPRESetType" 847 /*@C 848 PCHYPRESetType - Sets which hypre preconditioner you wish to use 849 850 Input Parameters: 851 + pc - the preconditioner context 852 - name - either pilut, parasails, boomeramg, euclid 853 854 Options Database Keys: 855 -pc_hypre_type - One of pilut, parasails, boomeramg, euclid 856 857 Level: intermediate 858 859 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 860 PCHYPRE 861 862 @*/ 863 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPRESetType(PC pc,const char name[]) 864 { 865 PetscErrorCode ierr,(*f)(PC,const char[]); 866 867 PetscFunctionBegin; 868 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 869 PetscValidCharPointer(name,2); 870 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCHYPRESetType_C",(void (**)(void))&f);CHKERRQ(ierr); 871 if (f) { 872 ierr = (*f)(pc,name);CHKERRQ(ierr); 873 } 874 PetscFunctionReturn(0); 875 } 876 877 #undef __FUNCT__ 878 #define __FUNCT__ "PCHYPREGetType" 879 /*@C 880 PCHYPREGetType - Gets which hypre preconditioner you are using 881 882 Input Parameter: 883 . pc - the preconditioner context 884 885 Output Parameter: 886 . name - either pilut, parasails, boomeramg, euclid 887 888 Level: intermediate 889 890 .seealso: PCCreate(), PCHYPRESetType(), PCType (for list of available types), PC, 891 PCHYPRE 892 893 @*/ 894 PetscErrorCode PETSCKSP_DLLEXPORT PCHYPREGetType(PC pc,const char *name[]) 895 { 896 PetscErrorCode ierr,(*f)(PC,const char*[]); 897 898 PetscFunctionBegin; 899 PetscValidHeaderSpecific(pc,PC_COOKIE,1); 900 PetscValidPointer(name,2); 901 ierr = PetscObjectQueryFunction((PetscObject)pc,"PCHYPREGetType_C",(void (**)(void))&f);CHKERRQ(ierr); 902 if (f) { 903 ierr = (*f)(pc,name);CHKERRQ(ierr); 904 } 905 PetscFunctionReturn(0); 906 } 907 908 /*MC 909 PCHYPRE - Allows you to use the matrix element based preconditioners in the LLNL package hypre 910 911 Options Database Keys: 912 + -pc_hypre_type - One of pilut, parasails, boomeramg, euclid 913 - Too many others to list, run with -pc_type hypre -pc_hypre_type XXX -help to see options for the XXX 914 preconditioner 915 916 Level: intermediate 917 918 Notes: Apart from pc_hypre_type (for which there is PCHYPRESetType()), 919 the many hypre options can ONLY be set via the options database (e.g. the command line 920 or with PetscOptionsSetValue(), there are no functions to set them) 921 922 The options -pc_hypre_boomeramg_max_iter and -pc_hypre_boomeramg_rtol refer to the number of iterations 923 (V-cycles) that boomeramg does EACH time it is called. So for example, if it is set to 2 then 924 2-V-cycles are being used to define the preconditioner. -ksp_max_iter and -ksp_rtol STILL determine 925 the total number of iterations and tolerance for the Krylov solver. For example, if 926 -pc_hypre_boomeramg_max_iter is 2 and -ksp_max_it is 10 then AT MOST twenty V-cycles of boomeramg 927 will be called. 928 929 If you wish to use BoomerAMG WITHOUT a Krylov method use -ksp_type richardson NOT -ksp_type preonly 930 and use -ksp_max_it to control the number of V-cycles. 931 (see the PETSc FAQ.html at the PETSc website under the Documentation tab). 932 933 2007-02-03 Using HYPRE-1.11.1b, the routine HYPRE_BoomerAMGSolveT and the option 934 -pc_hypre_parasails_reuse were failing with SIGSEGV. Dalcin L. 935 936 .seealso: PCCreate(), PCSetType(), PCType (for list of available types), PC, 937 PCHYPRESetType() 938 939 M*/ 940 941 EXTERN_C_BEGIN 942 #undef __FUNCT__ 943 #define __FUNCT__ "PCCreate_HYPRE" 944 PetscErrorCode PETSCKSP_DLLEXPORT PCCreate_HYPRE(PC pc) 945 { 946 PC_HYPRE *jac; 947 PetscErrorCode ierr; 948 949 PetscFunctionBegin; 950 ierr = PetscNew(PC_HYPRE,&jac);CHKERRQ(ierr); 951 ierr = PetscLogObjectMemory(pc,sizeof(PC_HYPRE));CHKERRQ(ierr); 952 pc->data = jac; 953 pc->ops->destroy = PCDestroy_HYPRE; 954 pc->ops->setfromoptions = PCSetFromOptions_HYPRE; 955 pc->ops->setup = PCSetUp_HYPRE; 956 pc->ops->apply = PCApply_HYPRE; 957 jac->comm_hypre = MPI_COMM_NULL; 958 jac->hypre_type = PETSC_NULL; 959 /* duplicate communicator for hypre */ 960 ierr = MPI_Comm_dup(pc->comm,&(jac->comm_hypre));CHKERRQ(ierr); 961 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPRESetType_C","PCHYPRESetType_HYPRE",PCHYPRESetType_HYPRE);CHKERRQ(ierr); 962 ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCHYPREGetType_C","PCHYPREGetType_HYPRE",PCHYPREGetType_HYPRE);CHKERRQ(ierr); 963 PetscFunctionReturn(0); 964 } 965 EXTERN_C_END 966