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